byte_filer.cpp

Go to the documentation of this file.
00001 #ifndef BYTE_FILER_IMPLEMENTATION_FILE
00002 #define BYTE_FILER_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : byte_filer                                                        *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "byte_filer.h"
00019 
00020 #include <basis/byte_array.h>
00021 #include <basis/convert_utf.h>
00022 #include <basis/function.h>
00023 #include <basis/istring.h>
00024 #include <basis/portable.h>
00025 
00026 #include <stdio.h>
00027 #include <string.h>
00028 #ifdef __UNIX__
00029   #include <unistd.h>
00030 #endif
00031 #ifdef __WIN32__
00032   #include <io.h>
00033 #endif
00034 
00035 //#define DEBUG_BYTE_FILER
00036   // uncomment for noisy version of class.
00037 
00038 const size_t BTFL_FILE_TELL_LIMIT = size_t(2) * size_t(GIGABYTE);
00039   // the largest a long integer can represent in the tell system call.
00040 
00041 class file_hider
00042 {
00043 public:
00044   FILE *fp;  // the real file pointer.
00045 
00046   file_hider() : fp(NIL) {}
00047 };
00048 
00050 
00051 byte_filer::byte_filer()
00052 : _handle(new file_hider),
00053   _filename(new istring),
00054   _auto_close(true)
00055 {}
00056 
00057 byte_filer::byte_filer(const istring &filename, const istring &perms)
00058 : _handle(new file_hider),
00059   _filename(new istring),
00060   _auto_close(true)
00061 { open(filename, perms); }
00062 
00063 byte_filer::byte_filer(const char *filename, const char *perms)
00064 : _handle(new file_hider),
00065   _filename(new istring),
00066   _auto_close(true)
00067 { open(filename, perms); }
00068 
00069 byte_filer::byte_filer(bool auto_close, void *handle)
00070 : _handle(new file_hider),
00071   _filename(new istring),
00072   _auto_close(auto_close)
00073 {
00074   if (handle) {
00075     _handle->fp = (FILE *)handle;
00076   }
00077 }
00078 
00079 byte_filer::~byte_filer() { close(); WHACK(_handle); WHACK(_filename); }
00080 
00081 istring byte_filer::filename() const { return *_filename; }
00082 
00083 size_t byte_filer::file_size_limit() { return BTFL_FILE_TELL_LIMIT; }
00084 
00085 bool byte_filer::open(const istring &filename, const istring &perms)
00086 {
00087   close();
00088   _auto_close = true;  // reset since we know we're opening this.
00089   *_filename = filename;
00090 #ifndef __WIN32__
00091   _handle->fp = filename.t()? fopen(filename.s(), perms.s()) : NIL;
00092 #else
00093   _handle->fp = filename.t()? _wfopen((wchar_t *)(UTF16 *)transcode_to_utf16(filename),
00094       (wchar_t *)(UTF16 *)transcode_to_utf16(perms)) : NIL;
00095 
00096 #ifdef DEBUG_BYTE_FILER
00097   if (!_handle->fp)
00098     wprintf((wchar_t *)(UTF16 *)transcode_to_utf16("could not open: %ls\n"),
00099         (wchar_t *)(UTF16 *)transcode_to_utf16(filename));
00100 #endif
00101 
00102 #endif
00103   return good();
00104 }
00105 
00106 void byte_filer::close()
00107 {
00108   *_filename = "";
00109   if (_auto_close && _handle->fp) fclose(_handle->fp);
00110   _handle->fp = NIL;
00111 }
00112 
00113 bool byte_filer::good() { return !!_handle->fp; }
00114 
00115 size_t byte_filer::tell()
00116 {
00117   if (!_handle->fp) return 0;
00118   long to_return = ::ftell(_handle->fp);
00119   if (to_return == -1) {
00120     // if we couldn't get the size, either the file isn't there or the size
00121     // is too big for our OS to report.
00123     if (good()) return BTFL_FILE_TELL_LIMIT;
00124     else return 0;
00125   }
00126   return size_t(to_return);
00127 }
00128 
00129 void *byte_filer::file_handle() { return _handle->fp; }
00130 
00131 bool byte_filer::eof() { return !_handle->fp ? true : !!feof(_handle->fp); }
00132 
00133 int byte_filer::read(byte *buff, int size)
00134 { return !_handle->fp ? 0 : int(::fread((char *)buff, 1, size, _handle->fp)); }
00135 
00136 int byte_filer::write(const byte *buff, int size)
00137 { return !_handle->fp ? 0 : int(::fwrite((char *)buff, 1, size, _handle->fp)); }
00138 
00139 int byte_filer::read(byte_array &buff, int desired_size)
00140 {
00141   buff.reset(desired_size);
00142   int to_return = read(buff.access(), desired_size); 
00143   buff.zap(to_return, buff.length() - 1);
00144   return to_return;
00145 }
00146 
00147 int byte_filer::write(const byte_array &buff)
00148 { return write(buff.observe(), buff.length()); }
00149 
00150 size_t byte_filer::length()
00151 {
00152   size_t current_posn = tell();
00153   seek(0, FROM_END);  // jump to end of file.
00154   size_t file_size = tell();  // get position.
00155   seek(int(current_posn), FROM_START);  // jump back to previous place.
00156   return file_size;
00157 }
00158 
00159 int byte_filer::read(istring &s, int desired_size)
00160 {
00161   s.pad(desired_size + 2);
00162   int found = read((byte *)s.observe(), desired_size);
00163   if (non_negative(found)) s[found] = '\0';
00164   s.shrink();
00165   return found;
00166 }
00167 
00168 int byte_filer::write(const istring &s, bool add_null)
00169 {
00170   int len = s.length();
00171   if (add_null) len++;
00172   return write((byte *)s.observe(), len);
00173 }
00174 
00175 void byte_filer::flush()
00176 {
00177   if (!_handle->fp) return;
00178   ::fflush(_handle->fp);
00179 }
00180 
00181 bool byte_filer::truncate()
00182 {
00183   flush();
00184   int fnum = fileno(_handle->fp);
00185 #ifdef __WIN32__
00186   return SetEndOfFile((HANDLE)_get_osfhandle(fnum));
00187 #else
00188   size_t posn = tell();
00189   // if we're at the highest point we can be, we no longer trust our
00190   // ability to truncate properly.
00191   if (posn >= file_size_limit())
00192     return false;
00193   return !ftruncate(fnum, posn);
00194 #endif
00195 }
00196 
00197 bool byte_filer::seek(int where, origins origin)
00198 {
00199   if (!_handle->fp) return false;
00200   int real_origin;
00201   switch (origin) {
00202     case FROM_START: real_origin = SEEK_SET; break;
00203     case FROM_END: real_origin = SEEK_END; break;
00204     case FROM_CURRENT: real_origin = SEEK_CUR; break;
00205     default: return false;  // not a valid choice.
00206   }
00207   int ret = ::fseek(_handle->fp, where, real_origin);
00208   return !ret;
00209 }
00210 
00211 int byte_filer::getline(byte *buff, int desired_size)
00212 {
00213   if (!_handle->fp) return 0;
00214   char *ret = ::fgets((char *)buff, desired_size, _handle->fp);
00215   return !ret? 0 : int(strlen((char *)buff)) + 1;
00216 }
00217 
00218 int byte_filer::getline(byte_array &buff, int desired_size)
00219 {
00220   buff.reset(desired_size + 1);
00221   return getline(buff.access(), desired_size);
00222 }
00223 
00224 int byte_filer::getline(istring &buff, int desired_size)
00225 {
00226   buff.pad(desired_size + 1);
00227   int to_return = getline((byte *)buff.access(), desired_size);
00228   if (non_negative(to_return)) buff[to_return] = '\0';
00229   buff.shrink();
00230   return to_return;
00231 }
00232 
00233 
00234 #endif //BYTE_FILER_IMPLEMENTATION_FILE
00235 

Generated on Wed Nov 19 04:28:52 2008 for HOOPLE Libraries by  doxygen 1.5.1