feisty meow concerns codebase 2.140
byte_filer.cpp
Go to the documentation of this file.
1/*****************************************************************************\
2* *
3* Name : byte_filer *
4* Author : Chris Koeritz *
5* *
6*******************************************************************************
7* Copyright (c) 2000-$now By Author. This program is free software; you can *
8* redistribute it and/or modify it under the terms of the GNU General Public *
9* License as published by the Free Software Foundation; either version 2 of *
10* the License or (at your option) any later version. This is online at: *
11* http://www.fsf.org/copyleft/gpl.html *
12* Please send any updates to: fred@gruntose.com *
13\*****************************************************************************/
14
15#include "byte_filer.h"
16
18#include <basis/astring.h>
19#include <basis/byte_array.h>
20#include <basis/functions.h>
22
23#include <stdio.h>
24#include <string.h>
25#ifdef __UNIX__
26 #include <unistd.h>
27#endif
28#ifdef __WIN32__
29 #include <io.h>
30#endif
31
32#define DEBUG_BYTE_FILER
33 // uncomment for noisy version of class.
34
35using namespace basis;
36
37namespace filesystem {
38
39const size_t BTFL_FILE_TELL_LIMIT = size_t(2) * size_t(GIGABYTE);
40 // the largest a long integer can represent in the tell system call.
41
42class file_hider
43{
44public:
45 FILE *fp; // the real file pointer.
46
47 file_hider() : fp(NULL_POINTER) {}
48};
49
51
53: _handle(new file_hider),
54 _filename(new filename),
55 _auto_close(true)
56{}
57
58byte_filer::byte_filer(const astring &fname, const astring &perms)
59: _handle(new file_hider),
60 _filename(new filename),
61 _auto_close(true)
62{ open(fname, perms); }
63
64byte_filer::byte_filer(const char *fname, const char *perms)
65: _handle(new file_hider),
66 _filename(new filename),
67 _auto_close(true)
68{ open(fname, perms); }
69
70byte_filer::byte_filer(bool auto_close, void *handle)
71: _handle(new file_hider),
72 _filename(new filename),
73 _auto_close(auto_close)
74{
75 if (handle) {
76 _handle->fp = (FILE *)handle;
77 }
78}
79
80byte_filer::~byte_filer() { close(); WHACK(_handle); WHACK(_filename); }
81
82const astring &byte_filer::name() const { return _filename->raw(); }
83
85
86bool byte_filer::open(const astring &fname, const astring &perms)
87{
88 close();
89 _auto_close = true; // reset since we know we're opening this.
90 _filename->reset(fname);
91 _handle->fp = _filename->raw().t()? fopen(_filename->raw().s(), perms.s()) : NULL_POINTER;
92 if (_handle->fp == NULL_POINTER) return false;
93 return good();
94}
95
97{
98 _filename->reset("");
99 if (_auto_close && _handle->fp) fclose(_handle->fp);
100 _handle->fp = NULL_POINTER;
101}
102
103bool byte_filer::good() { return !!_handle->fp; }
104
106{
107 if (!_handle->fp) return 0;
108 long to_return = ::ftell(_handle->fp);
109 if (to_return == -1) {
110 // if we couldn't get the size, either the file isn't there or the size
111 // is too big for our OS to report.
113 if (good()) return BTFL_FILE_TELL_LIMIT;
114 else return 0;
115 }
116 return size_t(to_return);
117}
118
119void *byte_filer::file_handle() { return _handle->fp; }
120
121bool byte_filer::eof() { return !_handle->fp ? true : !!feof(_handle->fp); }
122
123int byte_filer::read(abyte *buff, int size)
124{ return !_handle->fp ? 0 : int(::fread((char *)buff, 1, size, _handle->fp)); }
125
126int byte_filer::write(const abyte *buff, int size)
127{ return !_handle->fp ? 0 : int(::fwrite((char *)buff, 1, size, _handle->fp)); }
128
129int byte_filer::read(byte_array &buff, int desired_size)
130{
131 buff.reset(desired_size);
132 int to_return = read(buff.access(), desired_size);
133 buff.zap(to_return, buff.length() - 1);
134 return to_return;
135}
136
138{ return write(buff.observe(), buff.length()); }
139
141{
142 size_t current_posn = tell();
143 seek(0, FROM_END); // jump to end of file.
144 size_t file_size = tell(); // get position.
145 seek(int(current_posn), FROM_START); // jump back to previous place.
146 return file_size;
147}
148
149int byte_filer::read(astring &s, int desired_size)
150{
151 s.pad(desired_size + 2);
152 int found = read((abyte *)s.observe(), desired_size);
153 if (non_negative(found)) s[found] = '\0';
154 s.shrink();
155 return found;
156}
157
158int byte_filer::write(const astring &s, bool add_null)
159{
160 int len = s.length();
161 if (add_null) len++;
162 return write((abyte *)s.observe(), len);
163}
164
166{
167 if (!_handle->fp) return;
168 ::fflush(_handle->fp);
169}
170
172{
173 flush();
174 int fnum = fileno(_handle->fp);
175#ifdef __WIN32__
176 return SetEndOfFile((HANDLE)_get_osfhandle(fnum));
177#else
178 size_t posn = tell();
179 // if we're at the highest point we can be, we no longer trust our
180 // ability to truncate properly.
181 if (posn >= file_size_limit())
182 return false;
183 return !ftruncate(fnum, posn);
184#endif
185}
186
187bool byte_filer::seek(int where, origins origin)
188{
189 if (!_handle->fp) return false;
190 int real_origin;
191 switch (origin) {
192 case FROM_START: real_origin = SEEK_SET; break;
193 case FROM_END: real_origin = SEEK_END; break;
194 case FROM_CURRENT: real_origin = SEEK_CUR; break;
195 default: return false; // not a valid choice.
196 }
197 int ret = ::fseek(_handle->fp, where, real_origin);
198 return !ret;
199}
200
201int byte_filer::getline(abyte *buff, int desired_size)
202{
203 if (!_handle->fp) return 0;
204 char *ret = ::fgets((char *)buff, desired_size, _handle->fp);
205 return !ret? 0 : int(strlen((char *)buff)) + 1;
206}
207
208int byte_filer::getline(byte_array &buff, int desired_size)
209{
210 buff.reset(desired_size + 1);
211 return getline(buff.access(), desired_size);
212}
213
214int byte_filer::getline(astring &buff, int desired_size)
215{
216 buff.pad(desired_size + 1);
217 int to_return = getline((abyte *)buff.access(), desired_size);
218 if (non_negative(to_return)) buff[to_return] = '\0';
219 buff.shrink();
220 return to_return;
221}
222
223} //namespace.
224
225
#define fileno
Definition Xos2defs.h:27
#define read
Definition Xos2defs.h:38
#define open
Definition Xos2defs.h:36
#define write
Definition Xos2defs.h:46
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition array.h:349
contents * access()
A non-constant access of the underlying C-array. BE REALLY CAREFUL.
Definition array.h:175
const contents * observe() const
Returns a pointer to the underlying C array of data.
Definition array.h:172
int length() const
Returns the current reported length of the allocated C array.
Definition array.h:115
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
Definition array.h:769
Provides a dynamically resizable ASCII character string.
Definition astring.h:35
bool t() const
t() is a shortcut for the string being "true", as in non-empty.
Definition astring.h:97
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition astring.h:113
void shrink()
changes all occurrences of "to_replace" into "new_string".
Definition astring.cpp:168
void pad(int length, char padding=' ')
makes the string "length" characters long.
Definition astring.cpp:496
int length() const
Returns the current length of the string.
Definition astring.cpp:132
virtual char * access()
provides access to the actual string held.
Definition astring.cpp:136
virtual const char * observe() const
observes the underlying pointer to the zero-terminated string.
Definition astring.cpp:140
A very common template for a dynamic array of bytes.
Definition byte_array.h:36
int getline(basis::abyte *buffer, int desired_size)
reads a line of text (terminated by a return) into the "buffer".
static size_t file_size_limit()
returns the maximum size that seek and length can support.
int write(const basis::abyte *buffer, int buffer_size)
writes "buffer_size" bytes into the file from "buffer".
void * file_handle()
provides a hook to get at the operating system's file handle.
byte_filer()
constructs an object that doesn't access a file yet.
void close()
shuts down the open file, if any.
@ FROM_START
offset is from the beginning of the file.
Definition byte_filer.h:94
@ FROM_CURRENT
offset is from current cursor position.
Definition byte_filer.h:96
@ FROM_END
offset is from the end of the file.
Definition byte_filer.h:95
bool seek(int where, origins origin=FROM_START)
places the cursor in the file at "where", based on the "origin".
const basis::astring & name() const
returns the file name that the object is operating on.
int read(basis::abyte *buffer, int buffer_size)
reads "buffer_size" bytes from the file into "buffer".
bool eof()
returns true if the cursor is at (or after) the end of the file.
size_t tell()
returns the current position within the file, in terms of bytes.
void flush()
forces any pending writes to actually be saved to the file.
size_t length()
returns the file's total length, in bytes.
bool truncate()
truncates the file after the current position.
bool good()
returns true if the file seems to be in the appropriate desired state.
bool open(const basis::astring &fname, const basis::astring &permissions)
opens a file with "fname" and "permissions" as in the constructor.
Provides operations commonly needed on file names.
Definition filename.h:64
const basis::astring & raw() const
returns the astring that we're holding onto for the path.
Definition filename.cpp:97
void reset(const basis::astring &name)
changes the file name held by the object.
Definition filename.cpp:103
#define NULL_POINTER
The value representing a pointer to nothing.
Definition definitions.h:32
The guards collection helps in testing preconditions and reporting errors.
Definition array.h:30
const int GIGABYTE
Number of bytes in a gigabyte.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition functions.h:121
unsigned char abyte
A fairly important unit which is seldom defined...
Definition definitions.h:51
bool non_negative(const type &a)
non_negative returns true if "a" is greater than or equal to zero.
Definition functions.h:45
A platform independent way to obtain the timestamp of a file.
const size_t BTFL_FILE_TELL_LIMIT
Support for unicode builds.
Aids in achievement of platform independence.
void * HANDLE