forked from niklasso/minisatp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFile.h
More file actions
153 lines (117 loc) · 5.68 KB
/
Copy pathFile.h
File metadata and controls
153 lines (117 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/******************************************************************************************[File.h]
Copyright (c) 2005-2010, Niklas Een, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef File_h
#define File_h
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define lseek64 lseek // }- (disable explicit 64-bit support for FreeBSD...)
#define open64 ::open // }
//=================================================================================================
// A buffered file abstraction with only 'putChar()' and 'getChar()'.
#define File_BufSize 1024 // A small buffer seem to work just as fine as a big one (at least under Linux)
enum FileMode { READ, WRITE };
// WARNING! This code is not thoroughly tested. May contain bugs!
class File {
int fd; // Underlying file descriptor.
FileMode mode; // Reading or writing.
uchar* buf; // Read or write buffer.
int size; // Size of buffer (at end of file, less than 'File_BufSize').
int pos; // Current position in buffer
bool own_fd; // Do we own the file descriptor? If so, will close file in destructor.
public:
#define DEFAULTS fd(-1), mode(READ), buf(NULL), size(-1), pos(0), own_fd(true)
File(void) : DEFAULTS {}
File(int fd, FileMode mode, bool own_fd = true) : DEFAULTS {
open(fd, mode, own_fd); }
File(cchar* name, cchar* mode) : DEFAULTS {
open(name, mode); }
#undef DEFAULTS
~File(void) {
close(); }
void open(int fd, FileMode mode, bool own_fd = true); // Low-level open. If 'own_fd' is FALSE, descriptor will not be closed by destructor.
void open(cchar* name, cchar* mode); // FILE* compatible interface.
void close(void);
bool null(void) { // TRUE if no file is opened.
return fd == -1; }
int releaseDescriptor(void) { // Don't run UNIX function 'close()' on descriptor in 'File's 'close()'.
if (mode == READ)
lseek64(fd, pos - size, SEEK_CUR);
own_fd = false;
return fd; }
FileMode getMode(void) {
return mode; }
void setMode(FileMode m) {
if (m == mode) return;
if (m == READ){
flush();
size = read(fd, buf, File_BufSize);
}else{
lseek64(fd, pos - size, SEEK_CUR);
size = -1; }
mode = m;
pos = 0; }
int getCharQ(void) { // Quick version with minimal overhead -- don't call this in the wrong mode!
#ifdef PARANOID
assert(mode == READ);
#endif
if (pos < size) return (uchar)buf[pos++];
if (size < File_BufSize) return EOF;
size = read(fd, buf, File_BufSize);
pos = 0;
if (size == 0) return EOF;
return (uchar)buf[pos++]; }
int putCharQ(int chr) { // Quick version with minimal overhead -- don't call this in the wrong mode!
#ifdef PARANOID
assert(mode == WRITE);
#endif
if (pos == File_BufSize){
ssize_t wrote = write(fd, buf, File_BufSize);
if (wrote != File_BufSize) printf("ERROR! Write failed.\n"), exit(1);
pos = 0; }
return buf[pos++] = (uchar)chr; }
int getChar(void) {
if (mode == WRITE) setMode(READ);
return getCharQ(); }
int putChar(int chr) {
if (mode == READ) setMode(WRITE);
return putCharQ(chr); }
bool eof(void) {
assert(mode == READ);
if (pos < size) return false;
if (size < File_BufSize) return true;
size = read(fd, buf, File_BufSize);
pos = 0;
if (size == 0) return true;
return false; }
void flush(void) {
assert(mode == WRITE);
ssize_t wrote = write(fd, buf, pos);
if (wrote != pos) printf("ERROR! Write failed.\n"), exit(1);
pos = 0; }
void seek(int64 pos, int whence = SEEK_SET);
int64 tell(void);
};
//=================================================================================================
// Some nice helper functions:
void putUInt (File& out, uint64 val);
uint64 getUInt (File& in);
macro uint64 encode64(int64 val) { return (val >= 0) ? (uint64)val << 1 : (((uint64)(~val) << 1) | 1); }
macro int64 decode64(uint64 val) { return ((val & 1) == 0) ? (int64)(val >> 1) : ~(int64)(val >> 1); }
macro void putInt (File& out, int64 val) { putUInt(out, encode64(val)); }
macro uint64 getInt (File& in) { return decode64(getUInt(in)); }
//=================================================================================================
#endif