00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00033
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
00041
00042 class file_hider
00043 {
00044 public:
00045 FILE *fp;
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;
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
00122
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);
00155 size_t file_size = tell();
00156 seek(int(current_posn), FROM_START);
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
00191
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;
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 }
00235
00236