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 
34 using namespace std;
35 
CBinaryStream(const string & strFileName,bool bOut,size_t uiDataSize,uint8_t uiStructureChecksum)36 CBinaryStream::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 
~CBinaryStream()47 CBinaryStream::~CBinaryStream()
48 {
49     if (_bOpen) {
50 
51         close();
52     }
53 
54     delete [] _puiData;
55 }
56 
open(string & strError)57 bool 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 
close()111 void 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 
reset()134 void CBinaryStream::reset()
135 {
136     _uiPos = 0;
137 }
138 
write(const uint8_t * puiData,size_t uiSize)139 void 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 
read(uint8_t * puiData,size_t uiSize)148 void 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 
computeChecksum() const157 uint8_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 
isOut() const169 bool CBinaryStream::isOut() const
170 {
171     return _bOut;
172 }
173