-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilebuf.h
136 lines (111 loc) · 3.5 KB
/
filebuf.h
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
#ifndef __FILEBUF_H
#define __FILEBUF_H
#include <stdexcept>
#include <string>
namespace tmacam {
/**@brief A string-io like class, i.e., bound-checked array read and seek.
*
* The idea of this class is to provide a safe way to use a buffer/array/string
* as if it was a file: you can read(), seek() and etc on it. On the same
* time, it also wants to pretend to be a pointer/iterator: you can
* dereference it, add to it. All those operations are bound checked.
*/
struct filebuf {
const char* current; /**< current position */
const char* start; /**< start of this buffer (for seek...) */
const char* end; /**< end of the buffer (1 past the end) */
filebuf() : current(0), start(0),end(0){}
filebuf(const char* buffer, unsigned int length) : current(buffer),
start(buffer),
end(buffer+length){}
filebuf(const filebuf& orig): current(orig.current),
start(orig.current),
end(orig.end){}
#ifdef __MEMBUF_F_
filebuf(const membuf& buffer) : current((const char*)buffer.start),
start((const char*) buffer.start),
end((const char*)buffer.start + buffer.length()){}
#endif // __MEMBUF_F_
/**@brief Garantees you can read "length" bytes from the filebuf
* and advances the current position by the same ammount.
*
* This function tries to garantee that at least length bytes from the
* filebuf can be read without transpessing its end. If it is possible,
* it will return the current buffer read position and advance its
* current position internally in length bytes.
*
* After a read the current position can reach the end of this filebuf
* and leave this filebuf in a eof state but if it goes beyond the
* end then it is an error and a std::out_of_range exception will be
* raised
*/
inline const char* read(unsigned int length)
{
const char* old_pos = this->current;
/* This read can make the current position reach the
* end of this filebuf...
*/
if ( (this->current + length) > this->end ){
/* ... but if it goes *beyond* the end of the buffer
* it is an ERROR.
*/
throw std::out_of_range("End of filebuf reached or access out of bounds.");
} else {
this->current += length;
return old_pos;
}
}
/**@brief Seeks to a different position in the buffer.
*
* It the seek crosses the filebuf boundaries a std::out_of_range is
* thrown.
*/
const char* seek(int offset)
{
const char* new_pos = this->current + offset;
if (new_pos >= this->start && new_pos < this->end){
this->current = new_pos;
return new_pos;
} else {
throw std::out_of_range("Seek crosses filebuf boundaries.");
}
}
inline filebuf readf(unsigned int length)
{
return filebuf(this->read(length),length);
}
inline bool eof() const {return (this->current >= this->end);}
inline size_t len() const {return (this->end - this->current);}
filebuf& operator+=(unsigned int offset)
{
this->read(offset);
return *this;
}
inline filebuf& operator++()
{
this->read(1);
return *this;
}
/**Get the current character
*
*@throw std::out_of_range if there is no data to read or if we
reach the end of the buffer.
*/
inline const char operator*()
{
if (eof()) {
throw std::out_of_range("End of filebuf reached"
" or access out of bounds.");
} else {
return *current;
}
}
/**Convert this buffer into a std::string*/
inline std::string str() const
{
return std::string(current, len());
}
};
} //namespace tmacam
#endif /* __FILEBUF_H */
// vim:syn=cpp.doxygen:autoindent:smartindent:fo+=tcroq: