file_slurp.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 00005 */ 00006 00007 /*************************************************************************************************/ 00008 00009 #ifndef ADOBE_FILE_SLURP_HPP 00010 #define ADOBE_FILE_SLURP_HPP 00011 00012 /*************************************************************************************************/ 00013 00014 #include <adobe/config.hpp> 00015 00016 #include <boost/filesystem/operations.hpp> 00017 #include <boost/filesystem/fstream.hpp> 00018 00019 #include <boost/noncopyable.hpp> 00020 00021 #include <stdexcept> 00022 00023 /****************************************************************************************************/ 00024 00025 // REVISIT (fbrereto) : Eventually I'd like to get this file slurper to the point where 00026 // it reads 64k blocks out of the file as it needs to, instead of 00027 // slurping the file all at once. 00028 00029 /****************************************************************************************************/ 00030 00031 namespace adobe { 00032 00033 /****************************************************************************************************/ 00034 00035 template <typename T> 00036 struct file_slurp : boost::noncopyable 00037 { 00038 typedef T* store_type; 00039 typedef std::size_t size_type; 00040 typedef T value_type; 00041 typedef T* iterator; 00042 typedef const T* const_iterator; 00043 00044 explicit file_slurp(const boost::filesystem::path& path) : 00045 contents_m(0), size_m(0), path_m(path) 00046 { reslurp(); } 00047 00048 ~file_slurp() 00049 { if (contents_m) delete [] contents_m; } 00050 00051 iterator begin() { return &contents_m[0]; } 00052 iterator end() { return begin() + size(); } 00053 00054 const_iterator begin() const { return &contents_m[0]; } 00055 const_iterator end() const { return begin() + size(); } 00056 00057 bool empty() const { return size() == 0; } 00058 size_type size() const { return size_m; } 00059 00060 T* c_str() { return contents_m; } 00061 00062 T* release() 00063 { 00064 T* result(contents_m); 00065 00066 contents_m = 0; 00067 00068 return result; 00069 } 00070 00071 void reslurp(); 00072 00073 private: 00074 T* contents_m; 00075 size_type size_m; 00076 boost::filesystem::path path_m; 00077 }; 00078 00079 /****************************************************************************************************/ 00080 00081 template <typename T> 00082 void file_slurp<T>::reslurp() 00083 { 00084 if (contents_m) 00085 return; 00086 00087 size_m = 0; 00088 00089 boost::intmax_t size(boost::filesystem::file_size(path_m)); 00090 00091 contents_m = new T[static_cast<std::size_t>(size) + 1]; 00092 00093 if (size == 0) 00094 return; 00095 00096 boost::filesystem::ifstream in(path_m, std::ios_base::in | std::ios_base::binary); 00097 00098 if (!in.is_open()) 00099 #if 1 00100 throw std::runtime_error("file slurp: failed to open file"); 00101 #else 00102 return; 00103 #endif 00104 00105 in.unsetf(std::ios_base::skipws); 00106 00107 // read in max 64K at a time 00108 std::size_t buffer_size(64*1024); 00109 00110 if (static_cast<std::size_t>(size) < buffer_size) 00111 buffer_size = static_cast<std::size_t>(size); 00112 00113 while (true) 00114 { 00115 in.read(&contents_m[size_m], static_cast<std::streamsize>(buffer_size)); 00116 00117 std::size_t count(static_cast<std::size_t>(in.gcount())); 00118 00119 size_m += count; 00120 00121 if (count != buffer_size) 00122 break; 00123 } 00124 00125 contents_m[size_m] = 0; 00126 } 00127 00128 /****************************************************************************************************/ 00129 00130 } // namespace adobe 00131 00132 /****************************************************************************************************/ 00133 00134 #endif 00135 00136 /****************************************************************************************************/ |