byte_filer.cpp

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