source: trunk/src/core/RpBuffer.cc @ 1038

Last change on this file since 1038 was 1038, checked in by dkearney, 15 years ago

adding the simple buffer object back to the repository because it was accidentally removed in rev 1018

File size: 10.5 KB
Line 
1/*
2 * ======================================================================
3 *  Rappture::Buffer
4 *
5 *  AUTHOR:  Derrick Kearney, Purdue University
6 *
7 *  Copyright (c) 2004-2008  Purdue Research Foundation
8 * ----------------------------------------------------------------------
9 *  See the file "license.terms" for information on usage and
10 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11 * ======================================================================
12 */
13
14#include "RpBuffer.h"
15
16#include "zlib.h"
17#include "b64/encode.h"
18#include "b64/decode.h"
19#include <fstream>
20#include <assert.h>
21
22#ifdef __cplusplus
23    extern "C" {
24#endif // ifdef __cplusplus
25
26using namespace Rappture;
27
28/**
29 * Construct an empty Buffer.
30 */
31Buffer::Buffer()
32  : SimpleBuffer(),
33    _level(6),
34    _compressionType(RPCOMPRESS_GZIP),
35    _windowBits(15)
36{}
37
38
39/**
40 * Construct an empty Buffer of specified size.
41 */
42Buffer::Buffer(int nbytes)
43  : SimpleBuffer(nbytes),
44    _level(6),
45    _compressionType(RPCOMPRESS_GZIP),
46    _windowBits(15)
47{}
48
49
50/**
51 * Construct a Buffer loaded with initial data.
52 *
53 * @param bytes pointer to bytes being stored.
54 * @param nbytes number of bytes being stored.
55 */
56Buffer::Buffer(const char* bytes, int nbytes)
57  : SimpleBuffer(bytes,nbytes),
58    _level(6),
59    _compressionType(RPCOMPRESS_GZIP),
60    _windowBits(15)
61{}
62
63/**
64 * Copy constructor
65 * @param Buffer object to copy
66 */
67Buffer::Buffer(const Buffer& b)
68  : SimpleBuffer(b),
69    _level(b._level),
70    _compressionType(b._compressionType),
71    _windowBits(b._windowBits)
72{}
73
74/**
75 * Assignment operator
76 * @param Buffer object to copy
77 */
78Buffer&
79Buffer::operator=(const Buffer& b)
80{
81    SimpleBuffer::operator=(b);
82
83    _level = b._level;
84    _compressionType = b._compressionType;
85    _windowBits = b._windowBits;
86
87    return *this;
88}
89
90
91Buffer
92Buffer::operator+(const Buffer& b) const
93{
94    Buffer newBuffer(*this);
95    newBuffer.operator+=(b);
96    return newBuffer;
97}
98
99
100Buffer&
101Buffer::operator+=(const Buffer& b)
102{
103    SimpleBuffer::operator+=(b);
104    return *this;
105}
106
107
108Buffer::~Buffer()
109{}
110
111
112Outcome
113Buffer::load (const char* filePath)
114{
115    Outcome status;
116    std::ifstream::pos_type size = 0;
117    std::ifstream inFile;
118    char* memblock = NULL;
119
120
121    inFile.open(filePath, std::ios::in | std::ios::ate | std::ios::binary);
122    if (!inFile.is_open()) {
123        status.error("error while opening file");
124        status.addContext("Rappture::Buffer::load()");
125        return status;
126    }
127
128    size = inFile.tellg();
129    memblock = new char [size];
130    if (memblock == NULL) {
131        status.error("error while allocating memory");
132        status.addContext("Rappture::Buffer::load()");
133        inFile.close();
134        return status;
135    }
136
137    inFile.seekg(0,std::ios::beg);
138    inFile.read(memblock,size);
139
140    // save data in buffer object.
141    append(memblock,size);
142
143    // close files, free memory
144    inFile.close();
145    delete [] memblock;
146    memblock = NULL;
147
148    // exit nicely
149    return status;
150}
151
152
153Outcome
154Buffer::dump (const char* filePath)
155{
156    Outcome status;
157    std::ofstream outFile;
158
159    outFile.open(filePath, std::ios::out|std::ios::trunc|std::ios::binary);
160    if (!outFile.is_open()) {
161        status.error("error while opening file");
162        status.addContext("Rappture::Buffer::dump()");
163        return status;
164    }
165
166    outFile.write(bytes(),size());
167    outFile.close();
168
169    // exit nicely
170    return status;
171}
172
173
174Outcome
175Buffer::encode (unsigned int compress, unsigned int base64)
176{
177    Outcome err;
178    SimpleBuffer bin;
179    SimpleBuffer bout;
180
181    if ((base64 == 0) && (compress == 0)) {
182        return err;
183    }
184
185    err.addContext("Rappture::Buffer::encode()");
186    rewind();
187
188    if (compress != 0) {
189        do_compress(err,*this,bout);
190        if (err) {
191            return err;
192        }
193    }
194
195    if (base64 != 0) {
196        if (compress != 0) {
197            bin.move(bout);
198            do_base64_enc(err,bin,bout);
199        }
200        else {
201            do_base64_enc(err,*this,bout);
202        }
203    }
204
205    if (!err) {
206        // write the encoded data to the internal buffer
207        move(bout);
208    }
209
210    return err;
211}
212
213
214Outcome
215Buffer::decode (unsigned int decompress, unsigned int base64)
216{
217    Outcome err;
218    SimpleBuffer bin;
219    SimpleBuffer bout;
220
221    if ((base64 == 0) && (decompress == 0)) {
222        return err;
223    }
224
225    err.addContext("Rappture::Buffer::decode()");
226    rewind();
227
228    if (base64 != 0) {
229        do_base64_dec(err,*this,bout);
230        if (err) {
231            return err;
232        }
233    }
234
235    if (decompress != 0) {
236        if (base64) {
237            bin.move(bout);
238            do_decompress(err,bin,bout);
239        }
240        else {
241            do_decompress(err,*this,bout);
242        }
243    }
244
245    if (!err) {
246        // write the decoded data to the internal buffer
247        move(bout);
248    }
249
250    return err;
251}
252
253
254void
255Buffer::do_compress(    Outcome& status,
256                        SimpleBuffer& bin,
257                        SimpleBuffer& bout  )
258{
259    int ret=0, flush=0;
260    unsigned have=0;
261    z_stream strm;
262
263    char in[CHUNK];
264    char out[CHUNK];
265
266    int bytesWritten = 0;
267
268    /* allocate deflate state */
269    strm.zalloc = Z_NULL;
270    strm.zfree = Z_NULL;
271    strm.opaque = Z_NULL;
272
273    ret = deflateInit2( &strm, _level, Z_DEFLATED,
274                        _windowBits+_compressionType,
275                        8, Z_DEFAULT_STRATEGY);
276
277    if (ret != Z_OK) {
278        status.error("error while initializing zlib stream object");
279        status.addContext("Rappture::Buffer::do_compress()");
280        return;
281    }
282
283    /* compress until end of file */
284    do {
285        strm.avail_in = bin.read(in, CHUNK);
286        if (bin.bad() == true) {
287            (void)deflateEnd(&strm);
288            // return Z_ERRNO;
289            status.error("error while compressing");
290            status.addContext("Rappture::Buffer::do_compress()");
291            return;
292        }
293        flush = bin.eof() ? Z_FINISH : Z_NO_FLUSH;
294        strm.next_in = (Bytef*) in;
295        /* run deflate() on input until output buffer not full, finish
296           compression if all of source has been read in */
297        do {
298            strm.avail_out = CHUNK;
299            strm.next_out = (Bytef*) out;
300            ret = deflate(&strm, flush);    /* no bad return value */
301            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
302            have = CHUNK - strm.avail_out;
303            /* write to file and check for error */
304            bytesWritten = bout.append(out, have);
305            if ( ( (unsigned) bytesWritten != have ) ) {
306                (void)deflateEnd(&strm);
307                bout.clear();
308                // return Z_ERRNO;
309                status.error("error writing compressed data to temp buffer");
310                status.addContext("Rappture::Buffer::do_compress()");
311                return;
312            }
313
314        } while (strm.avail_out == 0);
315        assert(strm.avail_in == 0);     /* all input will be used */
316
317        /* done when last data in file processed */
318    } while (flush != Z_FINISH);
319
320    assert(ret == Z_STREAM_END);        /* stream will be complete */
321
322    /* clean up and return */
323    (void)deflateEnd(&strm);
324    // return Z_OK;
325    return;
326}
327
328void
329Buffer::do_decompress(  Outcome& status,
330                        SimpleBuffer& bin,
331                        SimpleBuffer& bout  )
332{
333    int ret;
334    unsigned have;
335    z_stream strm;
336
337    char in[CHUNK];
338    char out[CHUNK];
339
340    int bytesWritten = 0;
341
342    /* allocate inflate state */
343    strm.zalloc = Z_NULL;
344    strm.zfree = Z_NULL;
345    strm.opaque = Z_NULL;
346    strm.avail_in = 0;
347    strm.next_in = Z_NULL;
348    ret = inflateInit2(&strm,_windowBits+_compressionType);
349    if (ret != Z_OK) {
350        status.error("error while initializing zlib stream object");
351        status.addContext("Rappture::Buffer::do_decompress()");
352        // return status;
353        return;
354    }
355
356    /* decompress until deflate stream ends or end of file */
357    do {
358        strm.avail_in = bin.read(in, CHUNK);
359        if (bin.bad() == true) {
360            (void)inflateEnd(&strm);
361            // return Z_ERRNO;
362            status.error("error while compressing");
363            status.addContext("Rappture::Buffer::do_decompress()");
364            // return status;
365            return;
366        }
367        if (strm.avail_in == 0)
368            break;
369        strm.next_in = (unsigned char*) in;
370        /* run inflate() on input until output buffer not full */
371        do {
372            strm.avail_out = CHUNK;
373            strm.next_out = (unsigned char*) out;
374            ret = inflate(&strm, Z_NO_FLUSH);
375            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
376            switch (ret) {
377            case Z_NEED_DICT:
378                ret = Z_DATA_ERROR;     /* and fall through */
379            case Z_DATA_ERROR:
380            case Z_MEM_ERROR:
381                (void)inflateEnd(&strm);
382                bout.clear();
383                status.error("memory error while inflating data");
384                status.addContext("Rappture::Buffer::do_decompress()");
385                return;
386            }
387            have = CHUNK - strm.avail_out;
388            bytesWritten = bout.append(out, have);
389            if ( ( (unsigned) bytesWritten != have) ) {
390                (void)inflateEnd(&strm);
391                bout.clear();
392                // return Z_ERRNO;
393                status.error("error writing compressed data to temp buffer");
394                status.addContext("Rappture::Buffer::do_decompress()");
395                return;
396            }
397        } while (strm.avail_out == 0);
398
399        /* done when inflate() says it's done */
400    } while (ret != Z_STREAM_END);
401
402    /* clean up and return */
403    (void)inflateEnd(&strm);
404    // return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
405    return;
406}
407
408
409void
410Buffer::do_base64_enc(  Outcome& status,
411                        const SimpleBuffer& bin,
412                        SimpleBuffer& bout )
413{
414    int tBufSize = 0;
415    unsigned int tBufAvl = 2*bin.size();
416    char* tBuf = new char[tBufAvl];
417
418    base64::encoder E;
419
420    tBufSize = E.encode(bin.bytes(),bin.size(),tBuf);
421    tBufSize += E.encode_end(tBuf+tBufSize);
422
423    bout = SimpleBuffer(tBuf,tBufSize);
424    delete [] tBuf;
425
426    return;
427}
428
429
430void
431Buffer::do_base64_dec(  Outcome& status,
432                        const SimpleBuffer& bin,
433                        SimpleBuffer& bout )
434{
435    int tBufSize = 0;
436    unsigned int tBufAvl = bin.size();
437    char* tBuf = new char[tBufAvl];
438
439    base64::decoder D;
440
441    tBufSize = D.decode(bin.bytes(),bin.size(),tBuf);
442
443    bout = SimpleBuffer(tBuf,tBufSize);
444    delete [] tBuf;
445
446    return;
447}
448
449#ifdef __cplusplus
450    }
451#endif // ifdef __cplusplus
452
Note: See TracBrowser for help on using the repository browser.