GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/b_stream.cpp
Date: 2026-09-07 02:28:19
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