1/*
2 * Copyright (c) 2011-2014, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30#include "BinaryStream.h"
31#include <string.h>
32#include <assert.h>
33
34using namespace std;
35
36CBinaryStream::CBinaryStream(const string& strFileName, bool bOut, size_t uiDataSize, uint8_t uiStructureChecksum) :
37    _strFileName(strFileName),
38    _bOut(bOut),
39    _uiDataSize(uiDataSize),
40    _uiStructureChecksum(uiStructureChecksum),
41    _puiData(new uint8_t[uiDataSize]),
42    _uiPos(0),
43    _bOpen(false)
44{
45}
46
47CBinaryStream::~CBinaryStream()
48{
49    if (_bOpen) {
50
51        close();
52    }
53
54    delete [] _puiData;
55}
56
57bool CBinaryStream::open(string& strError)
58{
59    assert(!_bOpen);
60
61    _fileStream.open(_strFileName.c_str(), (_bOut ? ios::out : ios::in|ios::ate)|ios::binary);
62
63    if (!_fileStream.is_open() || !_fileStream.good()) {
64
65        strError = string("Failed to ") + (_bOut ? "write" : "read") + "-open";
66
67        return false;
68    }
69    if (!_bOut) {
70
71        // Get file size
72        size_t uiFileSize = _fileStream.tellg();
73
74        // Validate file size
75        if (_uiDataSize + sizeof(_uiStructureChecksum) != uiFileSize) {
76
77            // Size different from expected
78            strError = "Unexpected file size";
79
80            return false;
81        }
82
83        // Back to beginning of file
84        _fileStream.seekg(0, ios::beg);
85
86        // Get data
87        _fileStream.read((char*)_puiData, _uiDataSize);
88
89        // File checksum
90        uint8_t uiFileChecksum;
91        _fileStream.read((char*)&uiFileChecksum, sizeof(uiFileChecksum));
92
93        // Data checksum
94        uint8_t uiDataChecksum = computeChecksum();
95
96        // Validate checksum
97        if (uiDataChecksum != uiFileChecksum) {
98
99            strError = "Integrity checks failed";
100
101            return false;
102        }
103    }
104
105    // Keep track
106    _bOpen = true;
107
108    return true;
109}
110
111void CBinaryStream::close()
112{
113    assert(_bOpen);
114
115    if (_bOut) {
116
117        // Get data
118        _fileStream.write((const char*)_puiData, _uiDataSize);
119
120        // Compute checksum
121        uint8_t uiDataChecksum = computeChecksum();
122
123        // Write checksum
124        _fileStream.write((const char*)&uiDataChecksum, sizeof(uiDataChecksum));
125    }
126
127    // Keep track
128    _bOpen = false;
129
130    // Close file
131    _fileStream.close();
132}
133
134void CBinaryStream::reset()
135{
136    _uiPos = 0;
137}
138
139void CBinaryStream::write(const uint8_t* puiData, size_t uiSize)
140{
141    assert(_uiPos + uiSize <= _uiDataSize);
142
143    memcpy(&_puiData[_uiPos], puiData, uiSize);
144
145    _uiPos += uiSize;
146}
147
148void CBinaryStream::read(uint8_t* puiData, size_t uiSize)
149{
150    assert(_uiPos + uiSize <= _uiDataSize);
151
152    memcpy(puiData, &_puiData[_uiPos], uiSize);
153
154    _uiPos += uiSize;
155}
156
157uint8_t CBinaryStream::computeChecksum() const
158{
159    uint32_t uiIndex;
160    uint8_t uiDataChecksum = _uiStructureChecksum;
161
162    for (uiIndex = 0; uiIndex < _uiDataSize; uiIndex++) {
163
164        uiDataChecksum += _puiData[uiIndex];
165    }
166    return uiDataChecksum;
167}
168
169bool CBinaryStream::isOut() const
170{
171    return _bOut;
172}
173