summaryrefslogtreecommitdiffstats
path: root/labb6/src/bitstream.h
blob: 3e6c4b1b54594816d170eab7f07c533efa385078 (plain) (blame)
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
/*
 * TDDD86 Huffman Encoding
 * This file defines the ibitstream and obitstream classes which are basically
 * same as the ordinary istream and ostream classes, but add the
 * functionality to read and write one bit at a time.
 *
 * The idea is that you can substitute an ibitstream in place of an
 * istream and use the same operations (get, fail, >>, etc.)
 * along with added member functions of readBit, rewind, and size.
 *
 * Similarly, the obitstream can be used in place of ofstream, and has
 * same operations (put, fail, <<, etc.) along with additional
 * member functions writebit and size.
 *
 * There are two subclasses of ibitstream: ifbitstream and istringbitstream,
 * which are similar to the ifstream and istringstream classes.	 The
 * obitstream class similarly has ofbitstream and ostringbitstream as
 * subclasses.
 *
 * Please do not modify this provided file. Your turned-in files should work
 * with an unmodified version of all provided code files.
 */

#ifndef _bitstream_h
#define _bitstream_h

#include <istream>
#include <ostream>
#include <fstream>
#include <sstream>
using namespace std;

/* Constant: PSEUDO_EOF
 * A constant representing the PSEUDO_EOF marker that you will
 * write at the end of your Huffman-encoded file.
 */
const int PSEUDO_EOF = 256;

/* Constant: NOT_A_CHAR
 * A constant representing an extended character that does not
 * actually hold a value.	 When you are constructing your Huffman
 * encoding tree, you should set the characters in each internal
 * node (non-leaf) to this value to explicitly mark that they are not
 * being used.
 */
const int NOT_A_CHAR = 257;

/*
 * Class: ibitstream
 * ---------------
 * Defines a class for reading files with all the functionality of istream
 * along with an added member function for reading a single bit and convenience
 * functions for rewinding the stream back to the beginning and getting the stream
 * size.
 *
 * You will probably not create instances of this class directly.	 Instead, you
 * will create ifbitstreams or istringbitstreams to read from files or string buffers.
 */
class ibitstream: public istream {
public:
    /*
     * Constructor: ibitstream
     * Usage: ibitstream stream;
     * -----------------------
     * Initializes a new ibitstream that is not attached to any source.	 You are
     * unlikely to use this function directly.
     */
    ibitstream();

    /*
     * Member function: readBit
     * Usage: bit = in.readBit();
     * --------------------------
     * Reads a single bit from the ibitstream and returns 0 or 1 depending on
     * the bit value.	 If the stream is exhausted, EOF (-1) is returned.
     * Raises an error if this ibitstream has not been properly opened.
     */
    int readBit();

    /*
     * Member function: rewind
     * Usage: in.rewind();
     * -------------------
     * Rewinds the ibitstream back to the beginning so that subsequent reads
     * start again from the beginning.	Raises an error if this ibitstream
     * has not been properly opened.
     */
    void rewind();

    /*
     * Member function: size
     * Usage: sz = in.size();
     * ----------------------
     * Returns the size in bytes of the data attached to this stream.
     * Raises an error if this ibitstream has not been properly opened.
     */
    long size();

    /*
     * Member function: is_open()
     * Usage: if (ibs.is_open()) { ... }
     * ----------------------
     * Returns whether or not this ibitstream is opened.	This only has
     * meaning if the ibitstream is a file stream; otherwise it always
     * returns true.
     */
    virtual bool is_open();

private:
    std::streampos lastTell;
    int curByte;
    int pos;
};


/*
 * Class: obitstream
 * ---------------
 * Defines a class for writing files with all the functionality of ostream
 * along with an added member function for writing a single bit and a convenience
 * function for getting the stream size.
 *
 * You are unlikely to instantiate this class directly; instead, instantiate one
 * of the subclasses.
 */

class obitstream: public ostream {
public:
    /*
     * Constructor: obitstream
     * Usage: obitstream outfile;
     * ------------------------
     * Initializes a new obitstream that is not attached to any file.	 Use the
     * open member function from ofstream to attach the stream to a file.
     */
        obitstream();

    /*
     * Member function: writeBit
     * Usage: out.writeBit(1);
     * -----------------------
     * Writes a single bit to the obitstream.
     * Raises an error if this ibitstream has not been properly opened.
     */
    void writeBit(int bit);

    /*
     * Member function: size
     * Usage: sz = in.size();
     * ----------------------
     * Returns the size in bytes of the file attached to this stream.
     * Raises an error if this obitstream has not been properly opened.
     */
    long size();

    /*
     * Member function: is_open()
     * Usage: if (ibs.is_open()) { ... }
     * ----------------------
     * Returns whether or not this obitstream is opened.	This only has
     * meaning if the obitstream is a file stream; otherwise it always
     * returns true.
     */
    virtual bool is_open();

private:
    std::streampos lastTell;
    int curByte;
    int pos;
};

/*
 * Class: ifbitstream
 * ---------------
 * A class for reading files in all of the usual ways, plus bit-by-bit.
 * You can treat this class like a normal ifstream, except that there is
 * extra support for bit-level operations.
 */

class ifbitstream: public ibitstream {
public:
    /*
     * Constructor: ifbitstream();
     * Usage: ifbitstream ifb;
     * -------------------------
     * Constructs a new ifbitstream not attached to any file.	 You can
     * open a file for reading using the .open() member functions.
     */
    ifbitstream();

    /*
     * Constructor: ifbitstream(const char* filename);
     * Constructor: ifbitstream(string filename);
     * Usage: ifbitstream ifb("filename");
     * -------------------------
     * Constructs a new ifbitstream that reads the specified file, if
     * it exists.	 If not, the stream enters an error state.
     */
    ifbitstream(const char* filename);
    ifbitstream(string filename);

    /*
     * Member function: open(const char* filename);
     * Member function: open(string filename);
     * Usage: ifb.open("my-file.txt");
     * -------------------------
     * Opens the specified file for reading.	If an error occurs, the
     * stream enters a failure state, which can be detected by calling
     * ifb.fail().
     */
    void open(const char* filename);
    void open(string filename);

    /*
     * Member function: is_open();
     * Usage: if (ifb.is_open()) { ... }
     * --------------------------
     * Returns whether or not this ifbitstream is connected to a file for
     * reading.
     */
    bool is_open();

    /*
     * Member function: close();
     * Usage: ifb.close();
     * --------------------------
     * Closes the currently-opened file, if the stream is open.	 If the
     * stream is not open, puts the stream into a fail state.
     */
    void close();

private:
    /* The actual file buffer which does reading and writing. */
    filebuf fb;
};

/*
 * Class: ofbitstream
 * ---------------
 * A class for writing files in all of the usual ways, plus bit-by-bit.
 * You can treat this class like a normal ofstream, except that there is
 * extra support for bit-level operations.
 *
 * As a safety feature, you cannot use ofbitstream to open files that end
 * in .h, .hh, .cpp, or .cc for writing, as this could very easily cause
 * you to destroy your source files.
 */

class ofbitstream: public obitstream {
public:
    /*
     * Constructor: ofbitstream();
     * Usage: ofbitstream ofb;
     * -------------------------
     * Constructs a new ofbitstream not attached to any file.	 You can
     * open a file for writing using the .open() member functions.
     */
    ofbitstream();

    /*
     * Constructor: ofbitstream(const char* filename);
     * Constructor: ofbitstream(string filename);
     * Usage: ofbitstream ofb("filename");
     * -------------------------
     * Constructs a new ofbitstream that writes the specified file, if
     * it exists.	 If not, the stream enters an error state.	Read
     * the documentation on "open" for more details.
     */
    ofbitstream(const char* filename);
    ofbitstream(string filename);

    /*
     * Member function: open(const char* filename);
     * Member function: open(string filename);
     * Usage: ofb.open("my-file.txt");
     * -------------------------
     * Opens the specified file for writing.	If an error occurs, the
     * stream enters a failure state, which can be detected by calling
     * ifb.fail().	If an invalid filename is specified (for example,
     * a source file), reports an error.
     */
    void open(const char* filename);
    void open(string filename);

    /*
     * Member function: is_open();
     * Usage: if (ofb.is_open()) { ... }
     * --------------------------
     * Returns whether or not this ofbitstream is connected to a file for
     * reading.
     */
    bool is_open();

    /*
     * Member function: close();
     * Usage: ifb.close();
     * --------------------------
     * Closes the currently-opened file, if the stream is open.	 If the
     * stream is not open, puts the stream into a fail state.
     */
    void close();

private:
    /* The actual file buffer which does reading and writing. */
    filebuf fb;
};

/*
 * Class: istringbitstream
 * ---------------
 * A variant on C++'s istringstream class, which acts as a stream that
 * reads its data from a string.	This is mostly used by the testing
 * code to test your Huffman encoding without having to read or write
 * files on disk, but you can use it in your own testing if you would
 * like.
 */
class istringbitstream: public ibitstream {
public:
    /* Constructor: istringbitstream(string s = "");
     * Usage: istringbitstream stream;
     * --------------------------
     * Constructs an istringbitstream reading the specified string.
     */
    istringbitstream(string s = "");

    /* Member Function: str(string s);
     * Usage: isb.str("This is some text!");
     * ---------------------------
     * Sets the underlying string of the istringbitstream.
     */
    void str(string s);
private:
    /* The actual string buffer that does character storage. */
    stringbuf sb;
};

/*
 * Class: ostringbitstream
 * ---------------
 * A variant on C++'s ostringstream class, which acts as a stream that
 * writes its data to a string.	 This is mostly used by the testing
 * code to test your Huffman encoding without having to read or write
 * files on disk, but you can use it in your own testing if you would
 * like.
 */

class ostringbitstream: public obitstream {
public:
    /* Constructor: ostringbitstream();
     * Usage: ostringbitstream stream;
     * --------------------------
     * Constructs an ostringbitstream.
     */
    ostringbitstream();

    /* Member function: string str();
     * Usage: cout << osb.str() << endl;
     * ----------------------------
     * Retrieves the underlying string of the istringbitstream.
     */
    string str();

private:
    /* The actual string buffer that does character storage. */
    stringbuf sb;
};

#endif