00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/FileBuf.hpp"
00040 #include "blocxx/IOException.hpp"
00041
00042 #ifdef BLOCXX_HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #endif
00045
00046 #include <fcntl.h>
00047 #include <ios>
00048
00049 #ifdef BLOCXX_WIN32
00050 #include <io.h>
00051 #endif
00052
00053 namespace BLOCXX_NAMESPACE
00054 {
00055
00056 FileBuf::FileBuf()
00057 : BaseStreamBuffer(E_IN_OUT)
00058 , m_file(0)
00059 {
00060 }
00061
00062 FileBuf::~FileBuf()
00063 {
00064 close();
00065 }
00066
00067 bool
00068 FileBuf::isOpen() const
00069 {
00070 return m_file != 0;
00071 }
00072
00073 FileBuf*
00074 FileBuf::open(FILE* fp)
00075 {
00076 if (isOpen())
00077 {
00078 return 0;
00079 }
00080
00081 m_file = fp;
00082 return this;
00083 }
00084
00085 FileBuf*
00086 FileBuf::open(AutoDescriptor fd)
00087 {
00088 if (isOpen())
00089 {
00090 return 0;
00091 }
00092
00093 int d = -1;
00094
00095 #ifdef BLOCXX_WIN32
00096 #pragma message(Reminder "TODO: implement it for Win!")
00097
00098
00099 int flags = O_RDWR;
00100
00101 d = _open_osfhandle(reinterpret_cast<long>(fd.get()), flags);
00102 #else
00103 d = fd.get();
00104 int flags = ::fcntl(d, F_GETFL);
00105 if (flags == -1)
00106 {
00107 return 0;
00108 }
00109 #endif
00110
00111 m_file = ::fdopen(d, cppModeToCMode(posixModeToCppMode(flags)));
00112 if (m_file == 0)
00113 {
00114 return 0;
00115 }
00116 ::setbuf(m_file, 0);
00117 fd.release();
00118 return this;
00119 }
00120
00121 #if 0
00122 FileBuf*
00123 FileBuf::open(const File& f)
00124 {
00125 if (isOpen())
00126 {
00127 return 0;
00128 }
00129 int flags = ::fcntl(f.???, F_GETFL);
00130 if (flags == -1)
00131 {
00132 return 0;
00133 }
00134
00135 m_file = ::fdopen(???, cppModeToCMode(posixModeToCppMode(flags)));
00136 if (m_file == 0)
00137 {
00138 return 0;
00139 }
00140 ::setbuf(m_file, 0);
00141 return this;
00142 }
00143 #endif
00144
00145 FileBuf*
00146 FileBuf::open(const char* path, std::ios_base::openmode mode, mode_t permissions)
00147 {
00148 if (isOpen())
00149 {
00150 return 0;
00151 }
00152
00153 int d = ::open(path, cppModeToPOSIXMode(mode), permissions);
00154
00155 #ifdef BLOCXX_WIN32
00156 Descriptor h = reinterpret_cast<Descriptor>(_get_osfhandle(d));
00157 AutoDescriptor fd(h);
00158 #else
00159 AutoDescriptor fd(d);
00160 #endif
00161
00162 if (fd.get() == BLOCXX_INVALID_HANDLE)
00163 {
00164 return 0;
00165 }
00166
00167 m_file = ::fdopen(d, cppModeToCMode(mode));
00168
00169 if (m_file == 0)
00170 {
00171 return 0;
00172 }
00173
00174 ::setbuf(m_file, 0);
00175 fd.release();
00176
00177 return this;
00178 }
00179
00180 FileBuf*
00181 FileBuf::close()
00182 {
00183 if (isOpen())
00184 {
00185 ::fclose(m_file);
00186 }
00187 m_file = 0;
00188 return this;
00189 }
00190
00191 int
00192 FileBuf::buffer_to_device(const char* c, int n)
00193 {
00194 size_t written = ::fwrite(c, 1, n, m_file);
00195 if (written == static_cast<size_t>(n))
00196 {
00197 return 0;
00198 }
00199 else
00200 {
00201 return -1;
00202 }
00203 }
00204
00205 int
00206 FileBuf::buffer_from_device(char* c, int n)
00207 {
00208 if (!isOpen())
00209 {
00210 return -1;
00211 }
00212 size_t numRead = ::fread(c, 1, n, m_file);
00213 if (numRead != static_cast<size_t>(n))
00214 {
00215 if (ferror(m_file))
00216 {
00217 BLOCXX_THROW_ERRNO_MSG(IOException, "FileBuf::buffer_from_device: ::fread()");
00218 }
00219 else if (feof(m_file) && numRead == 0)
00220 {
00221 return -1;
00222 }
00223 else
00224 {
00225 return numRead;
00226 }
00227 }
00228 else
00229 {
00230 return n;
00231 }
00232 }
00233
00234 std::ios_base::openmode
00235 FileBuf::posixModeToCppMode(int posixMode)
00236 {
00237 std::ios_base::openmode mode = posixMode & O_APPEND ? std::ios::app : std::ios_base::openmode(0);
00238
00239 #ifdef BLOCXX_WIN32
00240 #define O_ACCMODE 3
00241 #endif
00242 switch (posixMode & O_ACCMODE)
00243 {
00244 case O_RDONLY: mode |= (std::ios::in | std::ios::binary); break;
00245 case O_WRONLY: mode |= (std::ios::out | std::ios::binary); break;
00246 case O_RDWR: mode |= (std::ios::in | std::ios::out | std::ios::binary); break;
00247 }
00248 return mode;
00249 }
00250
00251 int
00252 FileBuf::cppModeToPOSIXMode(std::ios_base::openmode cppMode)
00253 {
00254 int mode = 0;
00255 if (cppMode & std::ios::app)
00256 {
00257 mode |= O_APPEND;
00258 }
00259
00260 if (cppMode & std::ios::trunc)
00261 {
00262 mode |= O_TRUNC;
00263 }
00264
00265 if (cppMode & (std::ios::in | std::ios::out))
00266 {
00267 mode |= O_RDWR;
00268 }
00269 else if (cppMode & std::ios::in)
00270 {
00271 mode |= O_RDONLY;
00272 }
00273 else if (cppMode & std::ios::out)
00274 {
00275 mode |= O_WRONLY;
00276 }
00277 return mode;
00278 }
00279
00280 const char* FileBuf::cppModeToCMode(std::ios_base::openmode cppMode)
00281 {
00282
00283 cppMode = cppMode & ~std::ios::ate;
00284
00285 using std::ios;
00286
00287 if( cppMode == ios::app ||
00288 cppMode == (ios::in|ios::app) ||
00289 cppMode == (ios::out|ios::app) )
00290 {
00291 return "a";
00292 }
00293
00294 else if( cppMode == (ios::binary|ios::app) ||
00295 cppMode == (ios::in|ios::binary|ios::app) ||
00296 cppMode == (ios::out|ios::binary|ios::app) )
00297 {
00298 return "ab";
00299 }
00300
00301 else if (cppMode == ios::in)
00302 {
00303 return "r";
00304 }
00305
00306 else if (cppMode == (ios::in|ios::binary))
00307 {
00308 return "rb";
00309 }
00310
00311 else if (cppMode == (ios::out|ios::in))
00312 {
00313 return "r+";
00314 }
00315
00316 else if (cppMode == (ios::out|ios::in|ios::app))
00317 {
00318 return "a+";
00319 }
00320
00321 else if (cppMode == (ios::out|ios::in|ios::binary))
00322 {
00323 return "r+b";
00324 }
00325
00326 else if (cppMode == (ios::out|ios::in|ios::binary|ios::app))
00327 {
00328 return "a+b";
00329 }
00330
00331 else if( (cppMode == ios::out) ||
00332 cppMode == (ios::trunc) ||
00333 cppMode == (ios::trunc|ios::app) ||
00334 cppMode == (ios::trunc|ios::out) ||
00335 cppMode == (ios::trunc|ios::out|ios::app) )
00336 {
00337 return "w";
00338 }
00339
00340 else if( (cppMode == (ios::trunc|ios::binary)) ||
00341 (cppMode == (ios::trunc|ios::binary|ios::app)) ||
00342 (cppMode == (ios::out|ios::binary)) ||
00343 (cppMode == (ios::trunc|ios::out|ios::binary)) ||
00344 (cppMode == (ios::trunc|ios::out|ios::binary|ios::app) ))
00345 {
00346 return "wb";
00347 }
00348
00349 else if( (cppMode == (ios::trunc|ios::out|ios::in)) ||
00350 (cppMode == (ios::trunc|ios::out|ios::in|ios::app)) )
00351 {
00352 return "w+";
00353 }
00354
00355 else if( (cppMode == (ios::trunc|ios::out|ios::in|ios::binary)) ||
00356 (cppMode == (ios::trunc|ios::out|ios::in|ios::binary|ios::app)) )
00357 {
00358 return "w+b";
00359 }
00360 else
00361 {
00362 return "";
00363 }
00364
00365 }
00366
00367
00368 }
00369
00370