| 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 | #include <geogram/basic/geofile.h> | ||
| 41 | #include <geogram/basic/string.h> | ||
| 42 | #include <geogram/basic/logger.h> | ||
| 43 | #include <ctype.h> | ||
| 44 | |||
| 45 | #ifdef GEO_OS_WINDOWS | ||
| 46 | # define INT64_T_FMT "%Id" | ||
| 47 | #else | ||
| 48 | # include <inttypes.h> | ||
| 49 | # define INT64_T_FMT "%" PRIu64 | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #ifdef GARGANTUA | ||
| 53 | # define INDEX_T_FMT INT64_T_FMT | ||
| 54 | #else | ||
| 55 | # define INDEX_T_FMT "%u" | ||
| 56 | #endif | ||
| 57 | |||
| 58 | namespace { | ||
| 59 | |||
| 60 | void skip_comments(FILE* f) { | ||
| 61 |
7/8✓ Branch 1 taken 767 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 747 times.
✓ Branch 4 taken 20 times.
✓ Branch 6 taken 336 times.
✓ Branch 7 taken 8 times.
✓ Branch 9 taken 153 times.
✓ Branch 10 taken 3 times.
|
1267 | while(char(fgetc(f)) != '\n'); |
| 62 | } | ||
| 63 | |||
| 64 | |||
| 65 | 108 | std::string encode(const std::string& s) { | |
| 66 | std::string result; | ||
| 67 |
2/2✓ Branch 0 taken 2071 times.
✓ Branch 1 taken 108 times.
|
4358 | for(size_t i=0; i<s.size(); ++i) { |
| 68 |
1/3✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2071 times.
|
2071 | switch(s[i]) { |
| 69 | ✗ | case '\\': | |
| 70 | ✗ | result.push_back('\\'); | |
| 71 | ✗ | result.push_back('\\'); | |
| 72 | break; | ||
| 73 | ✗ | case '\"': | |
| 74 | ✗ | result.push_back('\\'); | |
| 75 | ✗ | result.push_back('\"'); | |
| 76 | break; | ||
| 77 | default: | ||
| 78 |
1/2✓ Branch 1 taken 2071 times.
✗ Branch 2 not taken.
|
2071 | result.push_back(s[i]); |
| 79 | } | ||
| 80 | } | ||
| 81 | 108 | return result; | |
| 82 | } | ||
| 83 | |||
| 84 | 20 | std::string decode(const std::string& s) { | |
| 85 | std::string result; | ||
| 86 | size_t i=0; | ||
| 87 |
2/2✓ Branch 0 taken 383 times.
✓ Branch 1 taken 20 times.
|
423 | while(i < s.size()) { |
| 88 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
|
383 | if(s[i] == '\\') { |
| 89 | ✗ | ++i; | |
| 90 | ✗ | if(i >= s.size()) { | |
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 |
1/2✓ Branch 1 taken 383 times.
✗ Branch 2 not taken.
|
383 | result.push_back(s[i]); |
| 95 | 383 | ++i; | |
| 96 | } | ||
| 97 | 20 | return result; | |
| 98 | } | ||
| 99 | |||
| 100 | |||
| 101 | /** \brief Maximum length of a gzlib gzread() or gzwrite() */ | ||
| 102 | static constexpr GEO::Numeric::uint32 MAX_GZ_IO_SIZE = 1024*1024*1024; | ||
| 103 | |||
| 104 | #ifdef Z_LARGE64 | ||
| 105 | |||
| 106 | #if defined(GEO_OS_WINDOWS) | ||
| 107 | typedef GEO::Numeric::int64 ssize_t; | ||
| 108 | #endif | ||
| 109 | |||
| 110 | /** | ||
| 111 | * \brief Wrapper around gzread() to read more than 4Gb | ||
| 112 | */ | ||
| 113 | 5 | ssize_t gzread64(gzFile file, void* buf_in, size_t len) { | |
| 114 | GEO::Memory::pointer buf = GEO::Memory::pointer(buf_in); | ||
| 115 | ssize_t bytes_read = 0; | ||
| 116 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
|
9 | while(len > size_t(MAX_GZ_IO_SIZE)) { |
| 117 | 4 | int result = gzread(file, buf, MAX_GZ_IO_SIZE); | |
| 118 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(result < 0) { |
| 119 | ✗ | return ssize_t(result); | |
| 120 | } | ||
| 121 | 4 | bytes_read += ssize_t(result); | |
| 122 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if(result < int(MAX_GZ_IO_SIZE)) { |
| 123 | return ssize_t(bytes_read); | ||
| 124 | } | ||
| 125 | 4 | len -= MAX_GZ_IO_SIZE; | |
| 126 | 4 | buf += MAX_GZ_IO_SIZE; | |
| 127 | } | ||
| 128 | 5 | int result = gzread(file, buf, unsigned(len)); | |
| 129 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if(result < 0) { |
| 130 | ✗ | return ssize_t(result); | |
| 131 | } | ||
| 132 | 5 | bytes_read += ssize_t(result); | |
| 133 | 5 | return ssize_t(bytes_read); | |
| 134 | } | ||
| 135 | |||
| 136 | /** | ||
| 137 | * \brief Wrapper around gzwrite() to write more than 4Gb | ||
| 138 | */ | ||
| 139 | 133 | ssize_t gzwrite64(gzFile file, const void* buf_in, size_t len) { | |
| 140 | GEO::Memory::const_pointer buf = GEO::Memory::const_pointer(buf_in); | ||
| 141 | ssize_t bytes_read = 0; | ||
| 142 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 133 times.
|
137 | while(len > size_t(MAX_GZ_IO_SIZE)) { |
| 143 | 4 | int result = gzwrite(file, buf, MAX_GZ_IO_SIZE); | |
| 144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(result < 0) { |
| 145 | ✗ | return ssize_t(result); | |
| 146 | } | ||
| 147 | 4 | bytes_read += ssize_t(result); | |
| 148 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if(result < int(MAX_GZ_IO_SIZE)) { |
| 149 | return ssize_t(bytes_read); | ||
| 150 | } | ||
| 151 | 4 | len -= MAX_GZ_IO_SIZE; | |
| 152 | 4 | buf += MAX_GZ_IO_SIZE; | |
| 153 | } | ||
| 154 | 133 | int result = gzwrite(file, buf, unsigned(len)); | |
| 155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
|
133 | if(result < 0) { |
| 156 | ✗ | return ssize_t(result); | |
| 157 | } | ||
| 158 | 133 | bytes_read += ssize_t(result); | |
| 159 | 133 | return ssize_t(bytes_read); | |
| 160 | } | ||
| 161 | |||
| 162 | #else | ||
| 163 | |||
| 164 | // Normally it will not get there (64 bit file offsets are supported under | ||
| 165 | // Linux, Mac and Windows), but I keep the fallback here (for Android and | ||
| 166 | // Emscripten for instance). | ||
| 167 | |||
| 168 | #ifdef GEO_OS_WINDOWS | ||
| 169 | typedef GEO::Numeric::int64 ssize_t; | ||
| 170 | #endif | ||
| 171 | |||
| 172 | ssize_t gzread64(gzFile file, void* buf_in, size_t len) { | ||
| 173 | geo_assert(len < size_t(MAX_GZ_IO_SIZE)); | ||
| 174 | return ssize_t(gzread(file, buf_in, unsigned(len))); | ||
| 175 | } | ||
| 176 | |||
| 177 | ssize_t gzwrite64(gzFile file, const void* buf_in, size_t len) { | ||
| 178 | geo_assert(len < size_t(MAX_GZ_IO_SIZE)); | ||
| 179 | return ssize_t(gzwrite(file, buf_in, unsigned(len))); | ||
| 180 | } | ||
| 181 | |||
| 182 | ssize_t gztell64(gzFile file) { | ||
| 183 | return ssize_t(gztell(file)); | ||
| 184 | } | ||
| 185 | |||
| 186 | ssize_t gzseek64(gzFile file, ssize_t off, int whence) { | ||
| 187 | geo_assert( | ||
| 188 | off >= -ssize_t(MAX_GZ_IO_SIZE) && off <= ssize_t(MAX_GZ_IO_SIZE) | ||
| 189 | ); | ||
| 190 | return ssize_t(gzseek(file, z_off_t(off), whence)); | ||
| 191 | } | ||
| 192 | |||
| 193 | |||
| 194 | |||
| 195 | #endif | ||
| 196 | |||
| 197 | } | ||
| 198 | |||
| 199 | namespace GEO { | ||
| 200 | |||
| 201 | /**************************************************************/ | ||
| 202 | |||
| 203 | ✗ | GeoFileException::~GeoFileException() GEO_NOEXCEPT { | |
| 204 | ✗ | } | |
| 205 | |||
| 206 | /**************************************************************/ | ||
| 207 | |||
| 208 | std::map<std::string, GeoFile::AsciiAttributeReadSerializer> | ||
| 209 | GeoFile::ascii_attribute_read_; | ||
| 210 | |||
| 211 | std::map<std::string, GeoFile::AsciiAttributeWriteSerializer> | ||
| 212 | GeoFile::ascii_attribute_write_; | ||
| 213 | |||
| 214 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2741 times.
|
2741 | void GeoFile::register_ascii_attribute_serializer( |
| 215 | const std::string& type_name, | ||
| 216 | AsciiAttributeReadSerializer read, | ||
| 217 | AsciiAttributeWriteSerializer write | ||
| 218 | ) { | ||
| 219 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 2741 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
2741 | geo_assert( |
| 220 | ascii_attribute_read_.find(type_name) == | ||
| 221 | ascii_attribute_read_.end() | ||
| 222 | ); | ||
| 223 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2741 times.
|
2741 | ascii_attribute_read_[type_name] = read; |
| 224 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 2741 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
2741 | geo_assert( |
| 225 | ascii_attribute_write_.find(type_name) == | ||
| 226 | ascii_attribute_write_.end() | ||
| 227 | ); | ||
| 228 | 2741 | ascii_attribute_write_[type_name] = write; | |
| 229 | 2741 | } | |
| 230 | |||
| 231 | /**************************************************************/ | ||
| 232 | |||
| 233 | 38 | GeoFile::GeoFile(const std::string& filename) : | |
| 234 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | filename_(filename), |
| 235 | 38 | file_(nullptr), | |
| 236 | 38 | ascii_(false), | |
| 237 | 38 | ascii_file_(nullptr), | |
| 238 |
1/4✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
38 | current_chunk_class_("0000"), |
| 239 | 38 | current_chunk_size_(0), | |
| 240 |
1/2✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
|
38 | current_chunk_file_pos_(0) { |
| 241 |
3/6✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 38 times.
✗ Branch 7 not taken.
|
38 | ascii_ = String::string_ends_with(filename, "_ascii"); |
| 242 | 38 | gargantua_mode_ = false; | |
| 243 | 38 | convert_32_to_64_ = false; | |
| 244 | 38 | convert_64_to_32_ = false; | |
| 245 | 38 | } | |
| 246 | |||
| 247 | 38 | GeoFile::~GeoFile() { | |
| 248 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 4 times.
|
38 | if(file_ != nullptr) { |
| 249 | 34 | gzclose(file_); | |
| 250 | } | ||
| 251 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37 times.
|
38 | if(ascii_file_ != nullptr) { |
| 252 | 1 | fclose(ascii_file_); | |
| 253 | } | ||
| 254 | 38 | } | |
| 255 | |||
| 256 | 471 | void GeoFile::check_chunk_size() { | |
| 257 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 452 times.
|
471 | if(ascii_) { |
| 258 | 19 | return; | |
| 259 | } | ||
| 260 | 452 | size_t chunk_size = size_t(gztell64(file_)) - current_chunk_file_pos_; | |
| 261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 452 times.
|
452 | if(current_chunk_size_ != chunk_size) { |
| 262 | throw GeoFileException( | ||
| 263 | ✗ | std::string("Chunk size mismatch: ") + | |
| 264 | ✗ | " expected " + String::to_string(current_chunk_size_) + | |
| 265 | ✗ | "/ got " + String::to_string(chunk_size) | |
| 266 | ✗ | ); | |
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | 36 | void GeoFile::check_zlib_version() { | |
| 271 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
|
36 | if(strcmp(ZLIB_VERSION, zlibVersion())) { |
| 272 | ✗ | Logger::warn("GeoFile") << "ZLib version mismatch !" << std::endl; | |
| 273 | ✗ | Logger::warn("GeoFile") << " from header: " << ZLIB_VERSION | |
| 274 | << std::endl; | ||
| 275 | ✗ | Logger::warn("GeoFile") << " from runtime: " << zlibVersion() | |
| 276 | << std::endl; | ||
| 277 | } | ||
| 278 | 36 | } | |
| 279 | |||
| 280 | 34 | void GeoFile::read_chunk_header() { | |
| 281 | 34 | current_chunk_class_ = read_chunk_class(); | |
| 282 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 21 times.
|
34 | if(ascii_) { |
| 283 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 12 times.
|
13 | if(feof(ascii_file_)) { |
| 284 | 1 | fclose(ascii_file_); | |
| 285 | 1 | ascii_file_ = nullptr; | |
| 286 | 1 | current_chunk_size_ = 0; | |
| 287 | current_chunk_class_ = "EOFL"; | ||
| 288 | 1 | return; | |
| 289 | } | ||
| 290 | } else { | ||
| 291 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 19 times.
|
21 | if(gzeof(file_)) { |
| 292 | 2 | gzclose(file_); | |
| 293 | 2 | file_ = nullptr; | |
| 294 | 2 | current_chunk_size_ = 0; | |
| 295 | current_chunk_class_ = "EOFL"; | ||
| 296 | 2 | return; | |
| 297 | } | ||
| 298 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | current_chunk_size_ = ascii_ ? 0 : read_size_t(); |
| 299 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | current_chunk_file_pos_ = ascii_ ? 0 : size_t(gztell64(file_)); |
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | 447 | void GeoFile::write_chunk_header( | |
| 304 | const std::string& chunk_class, size_t size | ||
| 305 | ) { | ||
| 306 | 447 | write_chunk_class(chunk_class); | |
| 307 |
2/2✓ Branch 0 taken 435 times.
✓ Branch 1 taken 12 times.
|
447 | if(!ascii_) { |
| 308 | 435 | write_size_t(size); | |
| 309 | } | ||
| 310 |
2/2✓ Branch 0 taken 435 times.
✓ Branch 1 taken 12 times.
|
447 | current_chunk_file_pos_ = ascii_ ? 0 : size_t(gztell64(file_)); |
| 311 | 447 | current_chunk_class_ = chunk_class; | |
| 312 | 447 | current_chunk_size_ = size; | |
| 313 | 447 | } | |
| 314 | |||
| 315 | 7 | index_t GeoFile::read_index_t() { | |
| 316 | 7 | index_t result=0; | |
| 317 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
|
7 | if(ascii_) { |
| 318 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if(fscanf(ascii_file_, INDEX_T_FMT, &result) == 0) { |
| 319 | ✗ | throw GeoFileException("Could not read integer from file"); | |
| 320 | } | ||
| 321 | 3 | skip_comments(ascii_file_); | |
| 322 | 3 | return result; | |
| 323 | } | ||
| 324 | |||
| 325 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(convert_32_to_64_) { |
| 326 | ✗ | Numeric::uint32 result32 = 0; | |
| 327 | ✗ | int check = gzread(file_, &result32, sizeof(Numeric::uint32)); | |
| 328 | ✗ | if(check == 0 && gzeof(file_)) { | |
| 329 | ✗ | result = NO_INDEX; | |
| 330 | } else { | ||
| 331 | ✗ | if(size_t(check) != sizeof(Numeric::uint32)) { | |
| 332 | ✗ | throw GeoFileException("Could not read integer from file"); | |
| 333 | } | ||
| 334 | ✗ | result = index_t(result32); | |
| 335 | } | ||
| 336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | } else if(convert_64_to_32_) { |
| 337 | ✗ | Numeric::uint64 result64 = 0; | |
| 338 | ✗ | int check = gzread(file_, &result64, sizeof(Numeric::uint64)); | |
| 339 | ✗ | if(check == 0 && gzeof(file_)) { | |
| 340 | ✗ | result = NO_INDEX; | |
| 341 | } else { | ||
| 342 | ✗ | if(size_t(check) != sizeof(Numeric::uint64)) { | |
| 343 | ✗ | throw GeoFileException("Could not read integer from file"); | |
| 344 | } | ||
| 345 | ✗ | if(result64 > std::numeric_limits<Numeric::uint32>::max()) { | |
| 346 | throw GeoFileException( | ||
| 347 | ✗ | "Integer in GARGANTUA file exceeds 32 bits" | |
| 348 | ✗ | ); | |
| 349 | } | ||
| 350 | ✗ | result = index_t(result64); | |
| 351 | } | ||
| 352 | } else { | ||
| 353 | 4 | int check = gzread(file_, &result, sizeof(index_t)); | |
| 354 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
4 | if(check == 0 && gzeof(file_)) { |
| 355 | ✗ | result = NO_INDEX; | |
| 356 | } else { | ||
| 357 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(size_t(check) != sizeof(index_t)) { |
| 358 | ✗ | throw GeoFileException("Could not read integer from file"); | |
| 359 | } | ||
| 360 | } | ||
| 361 | } | ||
| 362 | 4 | return result; | |
| 363 | } | ||
| 364 | |||
| 365 | 135 | void GeoFile::write_index_t(index_t x, const char* comment) { | |
| 366 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 132 times.
|
135 | if(ascii_) { |
| 367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if(comment == nullptr) { |
| 368 | ✗ | if(fprintf(ascii_file_,INDEX_T_FMT "\n",x) ==0) { | |
| 369 | ✗ | throw GeoFileException("Could not write integer to file"); | |
| 370 | } | ||
| 371 | } else { | ||
| 372 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if( |
| 373 | 3 | fprintf( | |
| 374 | ascii_file_,INDEX_T_FMT "# this is %s\n",x,comment | ||
| 375 | ) ==0 | ||
| 376 | ) { | ||
| 377 | ✗ | throw GeoFileException("Could not write integer to file"); | |
| 378 | } | ||
| 379 | } | ||
| 380 | 3 | return; | |
| 381 | } | ||
| 382 | 132 | int check = gzwrite(file_, &x, sizeof(index_t)); | |
| 383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if(size_t(check) != sizeof(index_t)) { |
| 384 | ✗ | throw GeoFileException("Could not write integer to file"); | |
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | /**********************************************************************/ | ||
| 389 | |||
| 390 | 47 | index_t GeoFile::read_index_t_32() { | |
| 391 | 47 | index_t result=0; | |
| 392 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 39 times.
|
47 | if(ascii_) { |
| 393 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if(fscanf(ascii_file_, INDEX_T_FMT, &result) == 0) { |
| 394 | ✗ | throw GeoFileException("Could not read integer from file"); | |
| 395 | } | ||
| 396 | 8 | skip_comments(ascii_file_); | |
| 397 | #ifdef GARGANTUA | ||
| 398 | 8 | if( | |
| 399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | result > index_t(std::numeric_limits<Numeric::uint32>::max()) |
| 400 | ) { | ||
| 401 | throw GeoFileException( | ||
| 402 | ✗ | "read_index_t_32(): integer does not fit in 32 bits" | |
| 403 | ✗ | ); | |
| 404 | } | ||
| 405 | #endif | ||
| 406 | return result; | ||
| 407 | } | ||
| 408 | 39 | Numeric::uint32 result32=0; | |
| 409 | 39 | int check = gzread(file_, &result32, sizeof(Numeric::uint32)); | |
| 410 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
39 | if(check == 0 && gzeof(file_)) { |
| 411 | result = NO_INDEX; | ||
| 412 | } else { | ||
| 413 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
|
39 | if(size_t(check) != sizeof(Numeric::uint32)) { |
| 414 | ✗ | throw GeoFileException("Could not read integer from file"); | |
| 415 | } | ||
| 416 | } | ||
| 417 | 39 | result = index_t(result32); | |
| 418 | 39 | return result; | |
| 419 | } | ||
| 420 | |||
| 421 | 2176 | void GeoFile::write_index_t_32(index_t x, const char* comment) { | |
| 422 | #ifdef GARGANTUA | ||
| 423 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2176 times.
|
2176 | if(x > index_t(std::numeric_limits<Numeric::uint32>::max())) { |
| 424 | throw GeoFileException( | ||
| 425 | ✗ | "write_index_t_32(): integer does not fit in 32 bits" | |
| 426 | ✗ | ); | |
| 427 | } | ||
| 428 | #endif | ||
| 429 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2167 times.
|
2176 | if(ascii_) { |
| 430 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if(comment == nullptr) { |
| 431 | ✗ | if(fprintf(ascii_file_,INDEX_T_FMT "\n",x) ==0) { | |
| 432 | ✗ | throw GeoFileException("Could not write integer to file"); | |
| 433 | } | ||
| 434 | } else { | ||
| 435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if( |
| 436 | 9 | fprintf( | |
| 437 | ascii_file_,INDEX_T_FMT "# this is %s\n",x,comment | ||
| 438 | ) ==0 | ||
| 439 | ) { | ||
| 440 | ✗ | throw GeoFileException("Could not write integer to file"); | |
| 441 | } | ||
| 442 | } | ||
| 443 | 9 | return; | |
| 444 | } | ||
| 445 | 2167 | Numeric::uint32 x32 = Numeric::uint32(x); | |
| 446 | 2167 | int check = gzwrite(file_, &x32, sizeof(Numeric::uint32)); | |
| 447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2167 times.
|
2167 | if(size_t(check) != sizeof(Numeric::uint32)) { |
| 448 | ✗ | throw GeoFileException("Could not write integer to file"); | |
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | /**********************************************************************/ | ||
| 453 | |||
| 454 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 29 times.
|
49 | std::string GeoFile::read_string() { |
| 455 | std::string result; | ||
| 456 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 29 times.
|
49 | if(ascii_) { |
| 457 | int cur; | ||
| 458 |
3/4✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 20 times.
|
31 | while(char(cur = fgetc(ascii_file_)) != '\"') { |
| 459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if(cur == EOF) { |
| 460 | throw GeoFileException( | ||
| 461 | ✗ | "Could not read string data from file" | |
| 462 | ✗ | ); | |
| 463 | } | ||
| 464 | } | ||
| 465 |
3/4✓ Branch 1 taken 403 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 383 times.
✓ Branch 4 taken 20 times.
|
403 | while(char(cur = fgetc(ascii_file_)) != '\"') { |
| 466 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
|
383 | if(cur == EOF) { |
| 467 | throw GeoFileException( | ||
| 468 | ✗ | "Could not read string data from file" | |
| 469 | ✗ | ); | |
| 470 | } | ||
| 471 |
1/2✓ Branch 1 taken 383 times.
✗ Branch 2 not taken.
|
383 | result.push_back(char(cur)); |
| 472 | } | ||
| 473 | 20 | skip_comments(ascii_file_); | |
| 474 |
1/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
20 | result = decode(result); |
| 475 | 20 | return result; | |
| 476 | } | ||
| 477 | |||
| 478 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | index_t len=read_index_t_32(); |
| 479 | result.resize(len); | ||
| 480 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | if(len != 0) { |
| 481 |
1/2✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
|
29 | int check = gzread(file_, &result[0], (unsigned int)(len)); |
| 482 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
|
29 | if(index_t(check) != len) { |
| 483 | ✗ | throw GeoFileException("Could not read string data from file"); | |
| 484 | } | ||
| 485 | } | ||
| 486 | return result; | ||
| 487 | } | ||
| 488 | |||
| 489 | 1975 | void GeoFile::write_string(const std::string& str, const char* comment) { | |
| 490 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1867 times.
|
1975 | if(ascii_) { |
| 491 |
2/2✓ Branch 0 taken 93 times.
✓ Branch 1 taken 15 times.
|
108 | if(comment == nullptr) { |
| 492 |
2/4✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 93 times.
|
186 | if(fprintf(ascii_file_, "\"%s\"\n", encode(str).c_str()) == 0) { |
| 493 | throw GeoFileException( | ||
| 494 | ✗ | "Could not write string data to file" | |
| 495 | ✗ | ); | |
| 496 | } | ||
| 497 | } else { | ||
| 498 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | if(fprintf( |
| 499 | ascii_file_, "\"%s\" # this is %s\n", | ||
| 500 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
|
30 | encode(str).c_str(), comment) == 0 |
| 501 | ) { | ||
| 502 | throw GeoFileException( | ||
| 503 | ✗ | "Could not write string data to file" | |
| 504 | ✗ | ); | |
| 505 | } | ||
| 506 | } | ||
| 507 | 108 | return; | |
| 508 | } | ||
| 509 | index_t len = index_t(str.length()); | ||
| 510 | 1867 | write_index_t_32(len); | |
| 511 |
1/2✓ Branch 0 taken 1867 times.
✗ Branch 1 not taken.
|
1867 | if(len != 0) { |
| 512 | 1867 | int check = gzwrite(file_, &str[0], (unsigned int)(len)); | |
| 513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1867 times.
|
1867 | if(index_t(check) != len) { |
| 514 | ✗ | throw GeoFileException("Could not write string data to file"); | |
| 515 | } | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | 19 | size_t GeoFile::read_size_t() { | |
| 520 | 19 | Numeric::uint64 result=0; | |
| 521 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if(ascii_) { |
| 522 | ✗ | if(fscanf(ascii_file_, INT64_T_FMT "\n", &result) == 0) { | |
| 523 | ✗ | throw GeoFileException("Could not write size to file"); | |
| 524 | } | ||
| 525 | } else { | ||
| 526 | 19 | int check = gzread(file_, &result, sizeof(Numeric::uint64)); | |
| 527 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
19 | if(check == 0 && gzeof(file_)) { |
| 528 | ✗ | result = size_t(-1); | |
| 529 | } else { | ||
| 530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if(size_t(check) != sizeof(Numeric::uint64)) { |
| 531 | ✗ | throw GeoFileException("Could not read size from file"); | |
| 532 | } | ||
| 533 | } | ||
| 534 | } | ||
| 535 | 19 | return size_t(result); | |
| 536 | } | ||
| 537 | |||
| 538 | 435 | void GeoFile::write_size_t(size_t x_in) { | |
| 539 | 435 | Numeric::uint64 x = Numeric::uint64(x_in); | |
| 540 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
|
435 | if(ascii_) { |
| 541 | ✗ | if(fprintf(ascii_file_, INT64_T_FMT "\n", x) == 0) { | |
| 542 | ✗ | throw GeoFileException("Could not write size to file"); | |
| 543 | } | ||
| 544 | } else { | ||
| 545 | 435 | int check = gzwrite(file_, &x, sizeof(Numeric::uint64)); | |
| 546 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
|
435 | if(size_t(check) != sizeof(Numeric::uint64)) { |
| 547 | ✗ | throw GeoFileException("Could not write size to file"); | |
| 548 | } | ||
| 549 | } | ||
| 550 | 435 | } | |
| 551 | |||
| 552 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 21 times.
|
34 | std::string GeoFile::read_chunk_class() { |
| 553 | std::string result; | ||
| 554 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 21 times.
|
34 | if(ascii_) { |
| 555 | int cur; | ||
| 556 |
3/4✓ Branch 1 taken 2000 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1988 times.
✓ Branch 4 taken 12 times.
|
2000 | while(char(cur = fgetc(ascii_file_)) != '[') { |
| 557 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1987 times.
|
1988 | if(cur == EOF) { |
| 558 | result = "EOFL"; | ||
| 559 | return result; | ||
| 560 | } | ||
| 561 | } | ||
| 562 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 12 times.
|
60 | for(index_t i=0; i<4; ++i) { |
| 563 |
1/2✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
|
48 | cur = fgetc(ascii_file_); |
| 564 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | if(cur == EOF) { |
| 565 | throw GeoFileException( | ||
| 566 | ✗ | "Could not read chunk class from file" | |
| 567 | ✗ | ); | |
| 568 | } | ||
| 569 |
1/2✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
|
48 | result.push_back(char(cur)); |
| 570 | } | ||
| 571 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | cur = fgetc(ascii_file_); |
| 572 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if(char(cur) != ']') { |
| 573 | throw GeoFileException( | ||
| 574 | ✗ | "Could not read chunk class from file" | |
| 575 | ✗ | ); | |
| 576 | } | ||
| 577 | return result; | ||
| 578 | } | ||
| 579 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | result.resize(4,'\0'); |
| 580 |
1/2✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
|
21 | int check = gzread(file_, &result[0], 4); |
| 581 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
21 | if(check == 0 && gzeof(file_)) { |
| 582 | result = "EOFL"; | ||
| 583 | } else { | ||
| 584 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if(check != 4) { |
| 585 | ✗ | throw GeoFileException("Could not read chunk class from file"); | |
| 586 | } | ||
| 587 | } | ||
| 588 | return result; | ||
| 589 | } | ||
| 590 | |||
| 591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | void GeoFile::write_chunk_class(const std::string& chunk_class) { |
| 592 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
447 | geo_assert(chunk_class.length() == 4); |
| 593 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 435 times.
|
447 | if(ascii_) { |
| 594 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | if(fprintf(ascii_file_, "[%s]\n", chunk_class.c_str()) == 0) { |
| 595 | ✗ | throw GeoFileException("Could not write chunk class to file"); | |
| 596 | } | ||
| 597 | return; | ||
| 598 | } | ||
| 599 | 435 | int check = gzwrite(file_, &chunk_class[0], 4); | |
| 600 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
|
435 | if(check != 4) { |
| 601 | ✗ | throw GeoFileException("Could not write chunk class to file"); | |
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
|
35 | void GeoFile::write_string_array(const std::vector<std::string>& strings) { |
| 606 | 35 | write_index_t_32(index_t(strings.size()),"the number of strings"); | |
| 607 |
2/2✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 35 times.
|
2578 | for(index_t i=0; i<strings.size(); ++i) { |
| 608 | 1254 | write_string(strings[i]); | |
| 609 | } | ||
| 610 | 35 | } | |
| 611 | |||
| 612 | ✗ | void GeoFile::read_string_array(std::vector<std::string>& strings) { | |
| 613 | ✗ | index_t nb_strings = read_index_t_32(); | |
| 614 | ✗ | strings.resize(nb_strings); | |
| 615 | ✗ | for(index_t i=0; i<nb_strings; ++i) { | |
| 616 | ✗ | strings[i] = read_string(); | |
| 617 | } | ||
| 618 | ✗ | } | |
| 619 | |||
| 620 | 35 | size_t GeoFile::string_array_size( | |
| 621 | const std::vector<std::string>& strings | ||
| 622 | ) const { | ||
| 623 | size_t result = sizeof(Numeric::uint32); | ||
| 624 |
2/2✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 35 times.
|
1324 | for(index_t i=0; i<strings.size(); ++i) { |
| 625 | 1254 | result += string_size(strings[i]); | |
| 626 | } | ||
| 627 | 35 | return result; | |
| 628 | } | ||
| 629 | |||
| 630 | ✗ | void GeoFile::clear_attribute_maps() { | |
| 631 | attribute_sets_.clear(); | ||
| 632 | ✗ | } | |
| 633 | |||
| 634 | /**********************************************************************/ | ||
| 635 | |||
| 636 | 3 | InputGeoFile::InputGeoFile( | |
| 637 | const std::string& filename | ||
| 638 | 3 | ) : GeoFile(filename), | |
| 639 | 3 | current_attribute_set_(nullptr), | |
| 640 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | current_attribute_(nullptr) |
| 641 | { | ||
| 642 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if(ascii_) { |
| 643 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ascii_file_ = fopen(filename.c_str(), "rb"); |
| 644 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(ascii_file_ == nullptr) { |
| 645 | ✗ | throw GeoFileException("Could not open file: " + filename); | |
| 646 | } | ||
| 647 | } else { | ||
| 648 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | check_zlib_version(); |
| 649 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | file_ = gzopen(filename.c_str(), "rb"); |
| 650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if(file_ == nullptr) { |
| 651 | ✗ | throw GeoFileException("Could not open file: " + filename); | |
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | read_chunk_header(); |
| 656 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if(current_chunk_class_ != "HEAD") { |
| 657 | throw GeoFileException( | ||
| 658 | ✗ | filename + " Does not start with HEAD chunk" | |
| 659 | ✗ | ); | |
| 660 | } | ||
| 661 | |||
| 662 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::string magic = read_string(); |
| 663 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if(magic != "GEOGRAM" && magic != "GEOGRAM-GARGANTUA") { |
| 664 | throw GeoFileException( | ||
| 665 | ✗ | filename + " is not a GEOGRAM file" + | |
| 666 | ✗ | " (got magic=" + magic + ")" | |
| 667 | ✗ | ); | |
| 668 | } | ||
| 669 | |||
| 670 | 3 | gargantua_mode_ = (magic == "GEOGRAM-GARGANTUA"); | |
| 671 | |||
| 672 | #ifdef GARGANTUA | ||
| 673 | 3 | convert_32_to_64_ = !gargantua_mode_; | |
| 674 | 3 | convert_64_to_32_ = false; | |
| 675 | #else | ||
| 676 | convert_64_to_32_ = gargantua_mode_; | ||
| 677 | convert_32_to_64_ = false; | ||
| 678 | #endif | ||
| 679 | |||
| 680 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::string version = read_string(); |
| 681 | geo_argused(version); | ||
| 682 | // Logger::out("I/O") << "GeoFile version: " << version << std::endl; | ||
| 683 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | check_chunk_size(); |
| 684 | 3 | } | |
| 685 | |||
| 686 | 31 | const std::string& InputGeoFile::next_chunk() { | |
| 687 | |||
| 688 | // If the file pointer did not advance as expected | ||
| 689 | // between two consecutive calls of next_chunk, it | ||
| 690 | // means that the client code does not want to | ||
| 691 | // read the current chunk, then it needs to be | ||
| 692 | // skipped. | ||
| 693 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12 times.
|
31 | if(ascii_) { |
| 694 | // TODO: skip chunk mechanism for ASCII | ||
| 695 | } else { | ||
| 696 | 19 | if( | |
| 697 | 19 | size_t(gztell64(file_)) != | |
| 698 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
|
19 | current_chunk_file_pos_ + current_chunk_size_ |
| 699 | ) { | ||
| 700 | 2 | skip_chunk(); | |
| 701 | } | ||
| 702 | } | ||
| 703 | |||
| 704 | 31 | read_chunk_header(); | |
| 705 | |||
| 706 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 24 times.
|
31 | if(current_chunk_class_ == "ATTS") { |
| 707 | 7 | std::string attribute_set_name = read_string(); | |
| 708 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | index_t nb_items = read_index_t(); |
| 709 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | check_chunk_size(); |
| 710 | |||
| 711 | if(find_attribute_set(attribute_set_name) != nullptr) { | ||
| 712 | throw GeoFileException( | ||
| 713 | ✗ | "Duplicate attribute set " + attribute_set_name | |
| 714 | ✗ | ); | |
| 715 | } | ||
| 716 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | attribute_sets_[attribute_set_name] = |
| 717 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | AttributeSetInfo(attribute_set_name, nb_items); |
| 718 | 7 | current_attribute_set_ = find_attribute_set(attribute_set_name); | |
| 719 |
1/10✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
7 | geo_assert(current_attribute_set_ != nullptr); |
| 720 | 7 | current_attribute_ = nullptr; | |
| 721 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | current_comment_ = ""; |
| 722 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 15 times.
|
24 | } else if(current_chunk_class_ == "ATTR") { |
| 723 | 9 | std::string attribute_set_name = read_string(); | |
| 724 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | std::string attribute_name = read_string(); |
| 725 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | std::string element_type = read_string(); |
| 726 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | index_t element_size = read_index_t_32(); |
| 727 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | index_t dimension = read_index_t_32(); |
| 728 | 9 | current_attribute_set_ = find_attribute_set(attribute_set_name); | |
| 729 | 9 | if( | |
| 730 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | current_attribute_set_->find_attribute(attribute_name) |
| 731 | != nullptr | ||
| 732 | ) { | ||
| 733 | throw GeoFileException( | ||
| 734 | ✗ | "Duplicate attribute " + attribute_name + | |
| 735 | ✗ | " in attribute set " + attribute_set_name | |
| 736 | ✗ | ); | |
| 737 | } | ||
| 738 | 9 | current_attribute_set_->attributes.push_back( | |
| 739 | 9 | AttributeInfo( | |
| 740 | attribute_name, | ||
| 741 | element_type, | ||
| 742 | element_size, | ||
| 743 | dimension | ||
| 744 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | ) |
| 745 | ); | ||
| 746 | 9 | current_attribute_ = | |
| 747 | 9 | current_attribute_set_->find_attribute(attribute_name); | |
| 748 |
1/10✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
9 | geo_assert(current_attribute_ != nullptr); |
| 749 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | current_comment_ = ""; |
| 750 | |||
| 751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if(current_attribute_set_->skip) { |
| 752 | ✗ | skip_chunk(); | |
| 753 | ✗ | return next_chunk(); | |
| 754 | } | ||
| 755 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 6 times.
|
15 | } else if(current_chunk_class_ == "CMNT") { |
| 756 | 9 | current_attribute_ = nullptr; | |
| 757 | 9 | current_attribute_set_ = nullptr; | |
| 758 | 9 | current_comment_ = read_string(); | |
| 759 | 9 | check_chunk_size(); | |
| 760 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | } else if(current_chunk_class_ == "SPTR") { |
| 761 | ✗ | clear_attribute_maps(); | |
| 762 | } | ||
| 763 | return current_chunk_class_; | ||
| 764 | } | ||
| 765 | |||
| 766 | 9 | void InputGeoFile::read_attribute(void* addr) { | |
| 767 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
9 | geo_assert(current_chunk_class_ == "ATTR"); |
| 768 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
|
9 | if(ascii_) { |
| 769 | AsciiAttributeReadSerializer read_attribute_func = | ||
| 770 | 4 | ascii_attribute_read_[current_attribute_->element_type]; | |
| 771 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(read_attribute_func == nullptr) { |
| 772 | throw GeoFileException( | ||
| 773 | ✗ | "No ASCII serializer for type:" + | |
| 774 | ✗ | current_attribute_->element_type | |
| 775 | ✗ | ); | |
| 776 | } | ||
| 777 | 4 | bool result = (*read_attribute_func)( | |
| 778 | ascii_file_, | ||
| 779 | Memory::pointer(addr), | ||
| 780 | index_t( | ||
| 781 | 4 | current_attribute_set_->nb_items* | |
| 782 | 4 | current_attribute_->dimension | |
| 783 | ) | ||
| 784 | ); | ||
| 785 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(!result) { |
| 786 | throw GeoFileException( | ||
| 787 | ✗ | "Could not read attribute " + current_attribute_->name + | |
| 788 | ✗ | " in set " + current_attribute_set_->name | |
| 789 | ✗ | ); | |
| 790 | } | ||
| 791 | return; | ||
| 792 | } | ||
| 793 | |||
| 794 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if(current_attribute_->element_type == "index_t") { |
| 795 | 2 | read_and_convert_index_t_array( | |
| 796 | reinterpret_cast<index_t*>(addr), | ||
| 797 | 2 | size_t(current_attribute_->dimension) * | |
| 798 | 2 | size_t(current_attribute_set_->nb_items), | |
| 799 | 2 | size_t(current_attribute_->element_size) | |
| 800 | ); | ||
| 801 | } else { | ||
| 802 | 3 | size_t size = | |
| 803 | 3 | size_t(current_attribute_->element_size) * | |
| 804 | 3 | size_t(current_attribute_->dimension) * | |
| 805 | 3 | size_t(current_attribute_set_->nb_items); | |
| 806 | 3 | ssize_t check = gzread64(file_, addr, size); | |
| 807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if(size_t(check) != size) { |
| 808 | throw GeoFileException( | ||
| 809 | ✗ | "Could not read attribute " + current_attribute_->name + | |
| 810 | ✗ | " in set " + current_attribute_set_->name + | |
| 811 | ✗ | " (" + String::to_string(check) + "/" | |
| 812 | ✗ | + String::to_string(size) + " bytes read)" | |
| 813 | ✗ | ); | |
| 814 | } | ||
| 815 | } | ||
| 816 | 5 | check_chunk_size(); | |
| 817 | } | ||
| 818 | |||
| 819 | 2 | void InputGeoFile::read_and_convert_index_t_array( | |
| 820 | index_t* addr, size_t nb_elements, size_t element_size | ||
| 821 | ) { | ||
| 822 | |||
| 823 | #ifdef __clang__ | ||
| 824 | #pragma GCC diagnostic push | ||
| 825 | #pragma GCC diagnostic ignored "-Wtautological-type-limit-compare" | ||
| 826 | #endif | ||
| 827 | |||
| 828 | // Three modes: | ||
| 829 | // copy (just read index_t array) | ||
| 830 | // expand (read 32 bits, store 64 bits). Beware NO_INDEX | ||
| 831 | // truncate (read 64 bits, store 32 bits). Beware NO_INDEX, chk bounds | ||
| 832 | 2 | bool copy = (element_size == sizeof(index_t)); | |
| 833 | 2 | bool expand = (element_size == 4 && sizeof(index_t) == 8); | |
| 834 | bool truncate = (element_size == 8 && sizeof(index_t) == 4); | ||
| 835 | |||
| 836 | static constexpr Numeric::uint32 NO_INDEX32 = Numeric::uint32(-1); | ||
| 837 | static constexpr Numeric::uint64 NO_INDEX64 = Numeric::uint64(-1); | ||
| 838 | |||
| 839 | Numeric::uint32* addr32 = reinterpret_cast<Numeric::uint32*>(addr); | ||
| 840 | |||
| 841 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if(copy || expand) { |
| 842 | 2 | size_t size = nb_elements * element_size; | |
| 843 | 2 | ssize_t check = gzread64(file_, addr, size); | |
| 844 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if(size_t(check) != size) { |
| 845 | throw GeoFileException( | ||
| 846 | ✗ | "Could not read attribute " + current_attribute_->name + | |
| 847 | ✗ | " in set " + current_attribute_set_->name + | |
| 848 | ✗ | " (" + String::to_string(check) + "/" | |
| 849 | ✗ | + String::to_string(size) + " bytes read)" | |
| 850 | ✗ | ); | |
| 851 | } | ||
| 852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if(expand) { |
| 853 | // Convert values starting from end of array so that we do | ||
| 854 | // not overwrite values before using them ! | ||
| 855 | ✗ | for(ssize_t i = ssize_t(nb_elements-1); i>=0; --i) { | |
| 856 | ✗ | addr[i] = (addr32[i] == NO_INDEX32) | |
| 857 | ✗ | ? NO_INDEX : index_t(addr32[i]) ; | |
| 858 | } | ||
| 859 | } | ||
| 860 | } else if(truncate) { | ||
| 861 | |||
| 862 | // Use a temporary buffer of max 1M entries. 64-bit indices are | ||
| 863 | // read there, then each chunk of 1M entries is converted and | ||
| 864 | // written to the destination array (addr). | ||
| 865 | |||
| 866 | static constexpr size_t BUFFER_SIZE = 1024*1024; | ||
| 867 | size_t buffer_size = std::min(nb_elements, BUFFER_SIZE); | ||
| 868 | |||
| 869 | index_t* to_addr = addr; | ||
| 870 | Numeric::uint64* buff64 = new Numeric::uint64[buffer_size]; | ||
| 871 | size_t nb_elements_to_read = nb_elements; | ||
| 872 | |||
| 873 | while(nb_elements_to_read != 0) { | ||
| 874 | size_t nb_elements_in_buffer = std::min( | ||
| 875 | nb_elements_to_read, BUFFER_SIZE | ||
| 876 | ); | ||
| 877 | |||
| 878 | size_t size_to_read = | ||
| 879 | nb_elements_in_buffer * sizeof(Numeric::uint64); | ||
| 880 | |||
| 881 | ssize_t check = gzread64(file_, buff64, size_to_read); | ||
| 882 | |||
| 883 | if(size_t(check) != size_to_read) { | ||
| 884 | throw GeoFileException( | ||
| 885 | "Could not read attribute " + current_attribute_->name + | ||
| 886 | " in set " + current_attribute_set_->name + | ||
| 887 | " ( buffread" + String::to_string(check) + "/" | ||
| 888 | + String::to_string(size_to_read) + " bytes read)" | ||
| 889 | ); | ||
| 890 | } | ||
| 891 | |||
| 892 | for(size_t i=0; i<nb_elements_in_buffer; ++i) { | ||
| 893 | index_t val = 0; | ||
| 894 | if(buff64[i] == NO_INDEX64) { | ||
| 895 | val = NO_INDEX; | ||
| 896 | } else if(buff64[i] > std::numeric_limits<index_t>::max()) { | ||
| 897 | throw GeoFileException( | ||
| 898 | "Could not read attribute " + current_attribute_->name + | ||
| 899 | " in set " + current_attribute_set_->name + | ||
| 900 | " ( index_t exceeds max 32-bit index )" | ||
| 901 | ); | ||
| 902 | } else { | ||
| 903 | val = index_t(buff64[i]); | ||
| 904 | } | ||
| 905 | to_addr[i] = val; | ||
| 906 | } | ||
| 907 | |||
| 908 | to_addr += nb_elements_in_buffer; | ||
| 909 | nb_elements_to_read -= nb_elements_in_buffer; | ||
| 910 | } | ||
| 911 | delete[] buff64; | ||
| 912 | } else { | ||
| 913 | ✗ | geo_assert_not_reached; | |
| 914 | } | ||
| 915 | |||
| 916 | #ifdef __clang__ | ||
| 917 | #pragma clang diagnostic pop | ||
| 918 | #endif | ||
| 919 | 2 | } | |
| 920 | |||
| 921 | |||
| 922 | 2 | void InputGeoFile::skip_chunk() { | |
| 923 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if(ascii_) { |
| 924 | // TODO | ||
| 925 | return; | ||
| 926 | } | ||
| 927 | 2 | gzseek64( | |
| 928 | file_, | ||
| 929 | 2 | ssize_t(current_chunk_size_ + current_chunk_file_pos_), | |
| 930 | SEEK_SET | ||
| 931 | ); | ||
| 932 | } | ||
| 933 | |||
| 934 | ✗ | void InputGeoFile::skip_attribute_set() { | |
| 935 | ✗ | geo_assert(current_chunk_class_ == "ATTS"); | |
| 936 | ✗ | current_attribute_set_->skip = true; | |
| 937 | ✗ | } | |
| 938 | |||
| 939 | ✗ | void InputGeoFile::read_command_line( | |
| 940 | std::vector<std::string>& args | ||
| 941 | ) { | ||
| 942 | ✗ | geo_assert(current_chunk_class() == "CMDL"); | |
| 943 | ✗ | read_string_array(args); | |
| 944 | ✗ | check_chunk_size(); | |
| 945 | ✗ | } | |
| 946 | |||
| 947 | /**************************************************************/ | ||
| 948 | |||
| 949 | 35 | OutputGeoFile::OutputGeoFile( | |
| 950 | const std::string& filename, index_t compression_level | ||
| 951 | 35 | ) : GeoFile(filename) { | |
| 952 | |||
| 953 | #ifdef GARGANTUA | ||
| 954 | 35 | gargantua_mode_ = true; | |
| 955 | #endif | ||
| 956 | |||
| 957 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
|
35 | if(ascii_) { |
| 958 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | ascii_file_ = fopen(filename.c_str(), "wb"); |
| 959 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if(ascii_file_ == nullptr) { |
| 960 | ✗ | throw GeoFileException("Could not create file: " + filename); | |
| 961 | } | ||
| 962 | } else { | ||
| 963 |
1/2✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
|
34 | check_zlib_version(); |
| 964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if(compression_level == 0) { |
| 965 | ✗ | file_ = gzopen(filename.c_str(), "wb"); | |
| 966 | } else { | ||
| 967 |
2/4✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 34 times.
✗ Branch 4 not taken.
|
34 | file_ = gzopen( |
| 968 | filename.c_str(), | ||
| 969 |
1/2✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
|
68 | ("wb" + String::to_string(compression_level)).c_str() |
| 970 | ); | ||
| 971 | } | ||
| 972 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
|
34 | if(file_ == nullptr) { |
| 973 | ✗ | throw GeoFileException("Could not create file: " + filename); | |
| 974 | } | ||
| 975 | } | ||
| 976 | |||
| 977 | #ifdef GARGANTUA | ||
| 978 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | std::string magic = "GEOGRAM-GARGANTUA"; |
| 979 | #else | ||
| 980 | std::string magic = "GEOGRAM"; | ||
| 981 | #endif | ||
| 982 |
2/6✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
35 | std::string version = "1.0"; |
| 983 |
2/4✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
35 | write_chunk_header("HEAD", string_size(magic) + string_size(version)); |
| 984 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | write_string(magic); |
| 985 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | write_string(version); |
| 986 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | check_chunk_size(); |
| 987 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | write_comment( |
| 988 |
3/6✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 35 times.
✗ Branch 8 not taken.
|
35 | "geogram version=" + Environment::instance()->get_value("version") |
| 989 | ); | ||
| 990 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | write_comment( |
| 991 | 35 | "geogram release date=" + | |
| 992 |
3/6✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 35 times.
✗ Branch 8 not taken.
|
35 | Environment::instance()->get_value("release_date") |
| 993 | ); | ||
| 994 |
1/2✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
|
35 | write_comment( |
| 995 | 35 | "geogram SVN revision=" + | |
| 996 |
4/10✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 35 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 35 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
70 | Environment::instance()->get_value("SVN revision") |
| 997 | ); | ||
| 998 | 35 | } | |
| 999 | |||
| 1000 |
1/2✓ Branch 0 taken 135 times.
✗ Branch 1 not taken.
|
135 | void OutputGeoFile::write_attribute_set( |
| 1001 | const std::string& attribute_set_name, index_t nb_items | ||
| 1002 | ) { | ||
| 1003 | ✗ | geo_assert(find_attribute_set(attribute_set_name) == nullptr); | |
| 1004 | |||
| 1005 |
1/2✓ Branch 1 taken 135 times.
✗ Branch 2 not taken.
|
135 | attribute_sets_[attribute_set_name] = |
| 1006 | 135 | AttributeSetInfo(attribute_set_name, nb_items); | |
| 1007 | |||
| 1008 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 135 times.
✓ Branch 3 taken 135 times.
✗ Branch 4 not taken.
|
270 | write_chunk_header( |
| 1009 | 135 | "ATTS", | |
| 1010 | string_size(attribute_set_name) + | ||
| 1011 | sizeof(index_t) | ||
| 1012 | ); | ||
| 1013 | |||
| 1014 | 135 | write_string(attribute_set_name, "the name of this attribute set"); | |
| 1015 | 135 | write_index_t(nb_items, "the number of items in this attribute set"); | |
| 1016 | |||
| 1017 | 135 | check_chunk_size(); | |
| 1018 | 135 | } | |
| 1019 | |||
| 1020 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
|
137 | void OutputGeoFile::write_attribute( |
| 1021 | const std::string& attribute_set_name, | ||
| 1022 | const std::string& attribute_name, | ||
| 1023 | const std::string& element_type, | ||
| 1024 | size_t element_size, | ||
| 1025 | index_t dimension, | ||
| 1026 | const void* data | ||
| 1027 | ) { | ||
| 1028 | AttributeSetInfo* attribute_set_info = find_attribute_set( | ||
| 1029 | attribute_set_name | ||
| 1030 | ); | ||
| 1031 | ✗ | geo_assert(attribute_set_info != nullptr); | |
| 1032 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
137 | geo_assert( |
| 1033 | attribute_set_info->find_attribute(attribute_name) == nullptr | ||
| 1034 | ); | ||
| 1035 | |||
| 1036 | size_t data_size = | ||
| 1037 | 137 | element_size * dimension * | |
| 1038 | 137 | attribute_sets_[attribute_set_name].nb_items; | |
| 1039 | |||
| 1040 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
✓ Branch 3 taken 137 times.
✗ Branch 4 not taken.
|
274 | write_chunk_header( |
| 1041 | 274 | "ATTR", | |
| 1042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
|
137 | string_size(attribute_set_name) + |
| 1043 | 137 | string_size(attribute_name) + | |
| 1044 | string_size(element_type) + | ||
| 1045 | sizeof(Numeric::uint32) + | ||
| 1046 | 137 | sizeof(Numeric::uint32) + | |
| 1047 | data_size | ||
| 1048 | ); | ||
| 1049 | |||
| 1050 | 137 | write_string( | |
| 1051 | attribute_set_name, | ||
| 1052 | "the name of the attribute set this attribute belongs to" | ||
| 1053 | ); | ||
| 1054 | 137 | write_string(attribute_name, "the name of this attribute"); | |
| 1055 | 137 | write_string( | |
| 1056 | element_type, "the type of the elements in this attribute" | ||
| 1057 | ); | ||
| 1058 | 137 | write_index_t_32( | |
| 1059 | index_t(element_size), "the size of an element (in bytes)" | ||
| 1060 | ); | ||
| 1061 | 137 | write_index_t_32(dimension, "the number of elements per item"); | |
| 1062 | |||
| 1063 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 133 times.
|
137 | if(ascii_) { |
| 1064 | AsciiAttributeWriteSerializer write_attribute_func = | ||
| 1065 | 4 | ascii_attribute_write_[element_type]; | |
| 1066 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(write_attribute_func == nullptr) { |
| 1067 | throw GeoFileException( | ||
| 1068 | ✗ | "No ASCII serializer for type:"+element_type | |
| 1069 | ✗ | ); | |
| 1070 | } | ||
| 1071 | 4 | bool result = (*write_attribute_func)( | |
| 1072 | ascii_file_, Memory::const_pointer(data), | ||
| 1073 | 4 | index_t(data_size/element_size) | |
| 1074 | ); | ||
| 1075 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if(!result) { |
| 1076 | ✗ | throw GeoFileException("Could not write attribute data"); | |
| 1077 | } | ||
| 1078 | } else { | ||
| 1079 | 133 | ssize_t check = gzwrite64(file_, data, data_size); | |
| 1080 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
|
133 | if(size_t(check) != data_size) { |
| 1081 | ✗ | throw GeoFileException("Could not write attribute data"); | |
| 1082 | } | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | 137 | check_chunk_size(); | |
| 1086 | |||
| 1087 | 137 | attribute_set_info->attributes.push_back( | |
| 1088 | 274 | AttributeInfo(attribute_name, element_type, element_size, dimension) | |
| 1089 | ); | ||
| 1090 | 137 | } | |
| 1091 | |||
| 1092 | 105 | void OutputGeoFile::write_comment(const std::string& comment) { | |
| 1093 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
✓ Branch 3 taken 105 times.
✗ Branch 4 not taken.
|
210 | write_chunk_header( |
| 1094 | 105 | "CMNT", | |
| 1095 | string_size(comment) | ||
| 1096 | ); | ||
| 1097 | 105 | write_string(comment); | |
| 1098 | 105 | check_chunk_size(); | |
| 1099 | 105 | } | |
| 1100 | |||
| 1101 | 35 | void OutputGeoFile::write_command_line( | |
| 1102 | const std::vector<std::string>& args | ||
| 1103 | ) { | ||
| 1104 |
1/2✓ Branch 3 taken 35 times.
✗ Branch 4 not taken.
|
35 | write_chunk_header("CMDL", string_array_size(args)); |
| 1105 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
|
35 | if(ascii_) { |
| 1106 | std::vector<std::string> new_args; | ||
| 1107 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 1 times.
|
89 | for(const std::string& arg : args) { |
| 1108 | bool serializable = true; | ||
| 1109 |
2/2✓ Branch 0 taken 1688 times.
✓ Branch 1 taken 88 times.
|
3464 | for(index_t i=0; i<arg.size(); ++i) { |
| 1110 |
2/4✓ Branch 0 taken 1688 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1688 times.
✗ Branch 3 not taken.
|
1688 | if(!isprint(arg[i]) || arg[i] == '\"') { |
| 1111 | serializable = false; | ||
| 1112 | break; | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 |
1/2✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
|
88 | if(serializable) { |
| 1116 |
1/2✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
|
88 | new_args.push_back(arg); |
| 1117 | } else { | ||
| 1118 | ✗ | Logger::warn("GeoFile") << "Skipping arg: " | |
| 1119 | << arg << std::endl; | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | write_string_array(new_args); |
| 1123 | 1 | } else { | |
| 1124 | 34 | write_string_array(args); | |
| 1125 | } | ||
| 1126 | 35 | check_chunk_size(); | |
| 1127 | 35 | } | |
| 1128 | |||
| 1129 | ✗ | void OutputGeoFile::write_separator() { | |
| 1130 | ✗ | clear_attribute_maps(); | |
| 1131 | ✗ | write_chunk_header("SPTR", 4); | |
| 1132 | ✗ | write_chunk_class("____"); | |
| 1133 | ✗ | check_chunk_size(); | |
| 1134 | ✗ | } | |
| 1135 | |||
| 1136 | /**************************************************************/ | ||
| 1137 | } | ||
| 1138 |