GCC Code Coverage Report


Directory: ./
File: basic/b_stream.cpp
Date: 2026-09-27 03:10:11
Exec Total Coverage
Lines: 35 168 20.8%
Functions: 8 23 34.8%
Branches: 8 80 10.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 /*
41 *
42 * b_stream.cpp
43 *
44 */
45
46 #include <geogram/basic/b_stream.h>
47 #include <geogram/basic/assert.h>
48 #include <geogram/basic/logger.h>
49
50 #include <iostream>
51 #include <stdlib.h>
52
53 namespace GEO {
54
55 25 BinaryStream::BinaryStream(int stream_endian) {
56 25 has_record_markers_ = true;
57 25 detect_machine_endian();
58 25 set_stream_endian(stream_endian);
59 25 }
60
61 25 void BinaryStream::detect_machine_endian() {
62
63 Numeric::int32 data = 0x04030201;
64 Numeric::uint8* pointer = (Numeric::uint8*) &data;
65
66 if(
67 pointer[0] == 1 &&
68 pointer[1] == 2 &&
69 pointer[2] == 3 &&
70 pointer[3] == 4
71 ) {
72 25 machine_endian_ = GEO_LITTLE_ENDIAN;
73 } else if(
74 pointer[0] == 4 &&
75 pointer[1] == 3 &&
76 pointer[2] == 2 &&
77 pointer[3] == 1) {
78 machine_endian_ = GEO_BIG_ENDIAN;
79 } else {
80 Logger::err("BinaryStream")
81 << "invalid processor type" << std::endl;
82 // Should not occur, nowadays machines are either little or
83 // big endian.
84 ::abort();
85 }
86 25 }
87
88 25 void BinaryStream::set_stream_endian(int stream_endian) {
89 25 stream_endian_ = stream_endian;
90 25 swapped_ = stream_endian_ != machine_endian_;
91 25 }
92
93 /************************************************************************/
94
95 25 BinaryInputStream::BinaryInputStream(
96 const std::string& file_name, int stream_endian_in
97 25 ) :
98 25 BinaryStream(stream_endian_in) {
99 25 record_OK_ = true;
100 25 record_count_ = 0;
101 25 input_ = new std::ifstream(
102 file_name.c_str(),
103 std::fstream::in | std::fstream::binary
104
1/2
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 );
105 25 owns_input_ = true;
106 if(!input_) {
107 delete input_;
108 input_ = nullptr;
109 }
110 25 }
111
112 ✗ BinaryInputStream::BinaryInputStream(
113 std::istream& input, int stream_endian_in
114 ✗ ) :
115 ✗ BinaryStream(stream_endian_in) {
116 ✗ record_OK_ = true;
117 ✗ record_count_ = 0;
118 ✗ input_ = &input;
119 ✗ owns_input_ = false;
120 ✗ }
121
122 18552 bool BinaryInputStream::OK() const {
123
3/6
✓ Branch 0 taken 18552 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18552 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18552 times.
18552 return record_OK_ && input_ != nullptr && input_->good();
124 }
125
126 ✗ bool BinaryInputStream::more() const {
127 ✗ return !input_->eof();
128 }
129
130 ✗ void BinaryInputStream::begin_record() {
131 ✗ if(input_->eof()) {
132 ✗ record_OK_ = false;
133 } else {
134 ✗ if(has_record_markers()) {
135 ✗ (*this) >> count1_;
136 }
137 }
138 ✗ }
139
140 ✗ void BinaryInputStream::end_record() {
141 ✗ record_count_++;
142 ✗ if(input_->eof()) {
143 ✗ record_OK_ = false;
144 } else {
145 ✗ if(has_record_markers()) {
146 ✗ (*this) >> count2_;
147 ✗ if(count1_ != count2_) {
148 ✗ record_OK_ = false;
149 ✗ Logger::err("BinaryStream")
150 << "Invalid record length in record #"
151 ✗ << record_count_ << std::endl;
152 ✗ Logger::err("BinaryStream")
153 ✗ << " count1=" << count1_
154 ✗ << " count2=" << count2_ << std::endl;
155 }
156 }
157 }
158 ✗ }
159
160 25 BinaryInputStream::~BinaryInputStream() {
161
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 if(input_ != nullptr && owns_input_) {
162 25 delete input_;
163 }
164 input_ = nullptr;
165 25 }
166
167 18502 BinaryInputStream& BinaryInputStream::read(
168 char* data, size_t n, ItemSize<2>
169 ) {
170 const size_t size = 2;
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18502 times.
18502 if(!swapped_) {
172 18502 input_->read(data, (std::streamsize) (size * n));
173 } else {
174 char buffer[size];
175 ✗ for(; n != 0; --n) {
176 ✗ input_->read(buffer, size);
177 ✗ data[0] = buffer[1];
178 ✗ data[1] = buffer[0];
179 ✗ data += size;
180 }
181 }
182 18502 return *this;
183 }
184
185 222049 BinaryInputStream& BinaryInputStream::read(
186 char* data, size_t n, ItemSize<4>
187 ) {
188 const size_t size = 4;
189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 222049 times.
222049 if(!swapped_) {
190 222049 input_->read(data, (std::streamsize) (size * n));
191 } else {
192 char buffer[size];
193 ✗ for(; n != 0; --n) {
194 ✗ input_->read(buffer, size);
195 ✗ data[0] = buffer[3];
196 ✗ data[1] = buffer[2];
197 ✗ data[2] = buffer[1];
198 ✗ data[3] = buffer[0];
199 ✗ data += size;
200 }
201 }
202 222049 return *this;
203 }
204
205 ✗ BinaryInputStream& BinaryInputStream::read(
206 char* data, size_t n, ItemSize<8>
207 ) {
208 const size_t size = 8;
209 ✗ if(!swapped_) {
210 ✗ input_->read(data, (std::streamsize) (size * n));
211 } else {
212 char buffer[size];
213 ✗ for(; n != 0; --n) {
214 ✗ input_->read(buffer, size);
215 ✗ data[0] = buffer[7];
216 ✗ data[1] = buffer[6];
217 ✗ data[2] = buffer[5];
218 ✗ data[3] = buffer[4];
219 ✗ data[4] = buffer[3];
220 ✗ data[5] = buffer[2];
221 ✗ data[6] = buffer[1];
222 ✗ data[7] = buffer[0];
223 ✗ data += size;
224 }
225 }
226 ✗ return *this;
227 }
228
229 /************************************************************************/
230
231 ✗ BinaryOutputStream::BinaryOutputStream(
232 const std::string& file_name, int stream_endian_in
233 ✗ ) :
234 ✗ BinaryStream(stream_endian_in) {
235 ✗ output_ = new std::ofstream(
236 file_name.c_str(),
237 std::fstream::out | std::fstream::trunc | std::fstream::binary
238 ✗ );
239 if(!output_) {
240 delete output_;
241 output_ = nullptr;
242 }
243 ✗ owns_output_ = true;
244 ✗ }
245
246 ✗ BinaryOutputStream::BinaryOutputStream(
247 std::ostream& output, int stream_endian_in
248 ✗ ) :
249 ✗ BinaryStream(stream_endian_in) {
250 ✗ output_ = &output;
251 ✗ owns_output_ = false;
252 ✗ }
253
254 ✗ bool BinaryOutputStream::OK() const {
255 ✗ return output_ != nullptr && output_->good();
256 }
257
258 ✗ void BinaryOutputStream::begin_record() {
259 ✗ if(has_record_markers()) {
260 ✗ count_ = 0;
261 ✗ pos_ = output_->tellp();
262 ✗ write_marker(Numeric::uint32(count_));
263 }
264 ✗ }
265
266 ✗ void BinaryOutputStream::end_record() {
267 ✗ if(has_record_markers()) {
268 ✗ write_marker(Numeric::uint32(count_));
269 ✗ std::streamoff pos = output_->tellp();
270 ✗ output_->seekp(pos_);
271 ✗ write_marker(Numeric::uint32(count_));
272 ✗ output_->seekp(pos);
273 }
274 ✗ }
275
276 ✗ BinaryOutputStream::~BinaryOutputStream() {
277 ✗ if(output_ != nullptr && owns_output_) {
278 ✗ delete output_;
279 }
280 output_ = nullptr;
281 ✗ }
282
283 ✗ void BinaryOutputStream::write_marker(Numeric::uint32 x) {
284 ✗ geo_assert(output_ != nullptr);
285 ✗ BinaryOutputStream::operator<< (x);
286
287 // Warning: operator<<() increments count_!
288 ✗ count_ -= sizeof(x);
289 ✗ }
290
291 ✗ BinaryOutputStream& BinaryOutputStream::write(
292 const char* data, size_t n, ItemSize<2>
293 ) {
294 const size_t size = 2;
295 ✗ if(!swapped_) {
296 ✗ output_->write(data, (std::streamsize) (size * n));
297 } else {
298 char buffer[size];
299 ✗ for(; n != 0; --n) {
300 ✗ buffer[0] = data[1];
301 ✗ buffer[1] = data[0];
302 ✗ output_->write(buffer, size);
303 ✗ data += size;
304 }
305 }
306 ✗ count_ += size * n;
307 ✗ return *this;
308 }
309
310 ✗ BinaryOutputStream& BinaryOutputStream::write(
311 const char* data, size_t n, ItemSize<4>
312 ) {
313 const size_t size = 4;
314 ✗ if(!swapped_) {
315 ✗ output_->write(data, (std::streamsize) (size * n));
316 } else {
317 char buffer[size];
318 ✗ for(; n != 0; --n) {
319 ✗ buffer[0] = data[3];
320 ✗ buffer[1] = data[2];
321 ✗ buffer[2] = data[1];
322 ✗ buffer[3] = data[0];
323 ✗ output_->write(buffer, size);
324 ✗ data += size;
325 }
326 }
327 ✗ count_ += size * n;
328 ✗ return *this;
329 }
330
331 ✗ BinaryOutputStream& BinaryOutputStream::write(
332 const char* data, size_t n, ItemSize<8>
333 ) {
334 const size_t size = 8;
335 ✗ if(!swapped_) {
336 ✗ output_->write(data, (std::streamsize) (size * n));
337 } else {
338 char buffer[size];
339 ✗ for(; n != 0; --n) {
340 ✗ buffer[0] = data[7];
341 ✗ buffer[1] = data[6];
342 ✗ buffer[2] = data[5];
343 ✗ buffer[3] = data[4];
344 ✗ buffer[4] = data[3];
345 ✗ buffer[5] = data[2];
346 ✗ buffer[6] = data[1];
347 ✗ buffer[7] = data[0];
348 ✗ output_->write(buffer, size);
349 ✗ data += size;
350 }
351 }
352 ✗ count_ += size * n;
353 ✗ return *this;
354 }
355 }
356