differential code coverage report with master
Current view: top level - source/detail - binary.hpp (source / functions) Coverage Total Hit UBC CBC
Current: coverage.info Lines: 96.6 % 88 85 3 85
Current Date: 2025-12-15 23:01:28 Functions: 95.3 % 43 41 2 41
Baseline: coverage_master.info Branches: 65.0 % 20 13 14 26
Baseline Date: 2025-12-15 23:01:27

             Branch data    TLA  Line data    Source code
       1                 :                : // Copyright (c) 2014-2022 Thomas Fussell
       2                 :                : // Copyright (c) 2024-2025 xlnt-community
       3                 :                : //
       4                 :                : // Permission is hereby granted, free of charge, to any person obtaining a copy
       5                 :                : // of this software and associated documentation files (the "Software"), to deal
       6                 :                : // in the Software without restriction, including without limitation the rights
       7                 :                : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8                 :                : // copies of the Software, and to permit persons to whom the Software is
       9                 :                : // furnished to do so, subject to the following conditions:
      10                 :                : //
      11                 :                : // The above copyright notice and this permission notice shall be included in
      12                 :                : // all copies or substantial portions of the Software.
      13                 :                : //
      14                 :                : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15                 :                : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16                 :                : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17                 :                : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18                 :                : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19                 :                : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20                 :                : // THE SOFTWARE
      21                 :                : //
      22                 :                : // @license: http://www.opensource.org/licenses/mit-license.php
      23                 :                : // @author: see AUTHORS file
      24                 :                : 
      25                 :                : #pragma once
      26                 :                : 
      27                 :                : #include <cstdint>
      28                 :                : #include <cstring>
      29                 :                : #include <iostream>
      30                 :                : #include <vector>
      31                 :                : 
      32                 :                : #include <xlnt/utils/exceptions.hpp>
      33                 :                : 
      34                 :                : namespace xlnt {
      35                 :                : namespace detail {
      36                 :                : 
      37                 :                : using byte = std::uint8_t;
      38                 :                : 
      39                 :                : template<typename T>
      40                 :                : class binary_reader
      41                 :                : {
      42                 :                : public:
      43                 :                :     binary_reader() = delete;
      44                 :                : 
      45                 :CBC        6002 :     binary_reader(const std::vector<T> &vector)
      46                 :           6002 :         : vector_(&vector),
      47                 :           6002 :           data_(nullptr),
      48                 :           6002 :           size_(0)
      49                 :                :     {
      50                 :           6002 :     }
      51                 :                : 
      52                 :                :     binary_reader(const T *source_data, std::size_t size)
      53                 :                :         : vector_(nullptr),
      54                 :                :           data_(source_data),
      55                 :                :           size_(size)
      56                 :                :     {
      57                 :                :     }
      58                 :                : 
      59                 :                :     binary_reader(const binary_reader &other) = default;
      60                 :                : 
      61                 :                :     binary_reader &operator=(const binary_reader &other)
      62                 :                :     {
      63                 :                :         vector_ = other.vector_;
      64                 :                :         offset_ = other.offset_;
      65                 :                :         data_ = other.data_;
      66                 :                : 
      67                 :                :         return *this;
      68                 :                :     }
      69                 :                : 
      70                 :           6002 :     ~binary_reader()
      71                 :                :     {
      72                 :           6002 :     }
      73                 :                : 
      74                 :          13516 :     const T *data() const
      75                 :                :     {
      76         [ -  + ]:          13516 :         return vector_ == nullptr ? data_ : vector_->data();
      77                 :                :     }
      78                 :                : 
      79                 :            297 :     void offset(std::size_t offset)
      80                 :                :     {
      81                 :            297 :         offset_ = offset;
      82                 :            297 :     }
      83                 :                : 
      84                 :          27140 :     std::size_t offset() const
      85                 :                :     {
      86                 :          27140 :         return offset_;
      87                 :                :     }
      88                 :                : 
      89                 :            986 :     void reset()
      90                 :                :     {
      91                 :            986 :         offset_ = 0;
      92                 :            986 :     }
      93                 :                : 
      94                 :                :     template<typename U>
      95                 :                :     U read()
      96                 :                :     {
      97                 :                :         return read_reference<U>();
      98                 :                :     }
      99                 :                : 
     100                 :                :     template<typename U>
     101                 :                :     const U *read_pointer()
     102                 :                :     {
     103                 :                :         const auto result = reinterpret_cast<const U *>(data() + offset_);
     104                 :                :         offset_ += sizeof(U) / sizeof(T);
     105                 :                : 
     106                 :                :         return result;
     107                 :                :     }
     108                 :                : 
     109                 :                :     template<typename U>
     110                 :                :     const U &read_reference()
     111                 :                :     {
     112                 :                :         return *read_pointer<U>();
     113                 :                :     }
     114                 :                : 
     115                 :                :     template<typename U>
     116                 :                :     std::vector<U> as_vector() const
     117                 :                :     {
     118                 :                :         auto result = std::vector<T>(bytes() / sizeof(U), U());
     119                 :                :         std::memcpy(result.data(), data(), bytes());
     120                 :                : 
     121                 :                :         return result;
     122                 :                :     }
     123                 :                : 
     124                 :                :     template<typename U>
     125                 :                :     std::vector<U> read_vector(std::size_t count)
     126                 :                :     {
     127                 :                :         auto result = std::vector<U>(count, U());
     128                 :                :         std::memcpy(result.data(), data() + offset_, count * sizeof(U));
     129                 :                :         offset_ += count * sizeof(T) / sizeof(U);
     130                 :                : 
     131                 :                :         return result;
     132                 :                :     }
     133                 :                : 
     134                 :          13516 :     std::size_t count() const
     135                 :                :     {
     136         [ +  - ]:          13516 :         return vector_ != nullptr ? vector_->size() : size_;
     137                 :                :     }
     138                 :                : 
     139                 :          13516 :     std::size_t bytes() const
     140                 :                :     {
     141                 :          13516 :         return count() * sizeof(T);
     142                 :                :     }
     143                 :                : 
     144                 :                : private:
     145                 :                :     std::size_t offset_ = 0;
     146                 :                :     const std::vector<T> *vector_ = nullptr;
     147                 :                :     const T *data_ = nullptr;
     148                 :                :     const std::size_t size_ = 0;
     149                 :                : };
     150                 :                : 
     151                 :                : template<typename T>
     152                 :                : class binary_writer
     153                 :                : {
     154                 :                : public:
     155                 :            304 :     binary_writer(std::vector<T> &bytes)
     156                 :            304 :         : data_(&bytes)
     157                 :                :     {
     158                 :            304 :     }
     159                 :                : 
     160                 :                :     binary_writer(const binary_writer &other)
     161                 :                :     {
     162                 :                :         *this = other;
     163                 :                :     }
     164                 :                : 
     165                 :            304 :     ~binary_writer()
     166                 :                :     {
     167                 :            304 :     }
     168                 :                : 
     169                 :                :     binary_writer &operator=(const binary_writer &other)
     170                 :                :     {
     171                 :                :         data_ = other.data_;
     172                 :                :         offset_ = other.offset_;
     173                 :                : 
     174                 :                :         return *this;
     175                 :                :     }
     176                 :                : 
     177                 :                :     std::vector<T> &data()
     178                 :                :     {
     179                 :                :         return *data_;
     180                 :                :     }
     181                 :                : 
     182                 :                :     // Make the bytes of the data pointed to by this writer equivalent to those in the given vector
     183                 :                :     // sizeof(U) should be a multiple of sizeof(T)
     184                 :                :     template<typename U>
     185                 :                :     void assign(const std::vector<U> &ints)
     186                 :                :     {
     187                 :                :         resize(ints.size() * sizeof(U));
     188                 :                :         std::memcpy(data_->data(), ints.data(), bytes());
     189                 :                :     }
     190                 :                : 
     191                 :                :     // Make the bytes of the data pointed to by this writer equivalent to those in the given string
     192                 :                :     // sizeof(U) should be a multiple of sizeof(T)
     193                 :                :     template<typename U>
     194                 :             25 :     void assign(const std::basic_string<U> &string)
     195                 :                :     {
     196                 :             25 :         resize(string.size() * sizeof(U));
     197                 :             25 :         std::memcpy(data_->data(), string.data(), bytes());
     198                 :             25 :     }
     199                 :                : 
     200                 :                :     void offset(std::size_t new_offset)
     201                 :                :     {
     202                 :                :         offset_ = new_offset;
     203                 :                :     }
     204                 :                : 
     205                 :           2957 :     std::size_t offset() const
     206                 :                :     {
     207                 :           2957 :         return offset_;
     208                 :                :     }
     209                 :                : 
     210                 :           2264 :     void reset()
     211                 :                :     {
     212                 :           2264 :         offset_ = 0;
     213                 :           2264 :         data_->clear();
     214                 :           2264 :     }
     215                 :                : 
     216                 :                :     template<typename U>
     217                 :             48 :     void write(U value)
     218                 :                :     {
     219                 :             48 :         const auto num_bytes = sizeof(U);
     220                 :             48 :         const auto remaining_bytes = bytes() - offset() * sizeof(T);
     221                 :                : 
     222         [ +  - ]:             48 :         if (remaining_bytes < num_bytes)
     223                 :                :         {
     224                 :             48 :             extend((num_bytes - remaining_bytes) / sizeof(T));
     225                 :                :         }
     226                 :                : 
     227                 :             48 :         std::memcpy(data_->data() + offset(), &value, num_bytes);
     228                 :             48 :         offset_ += num_bytes / sizeof(T);
     229                 :             48 :     }
     230                 :                : 
     231                 :           5843 :     std::size_t count() const
     232                 :                :     {
     233                 :           5843 :         return data_->size();
     234                 :                :     }
     235                 :                : 
     236                 :           2934 :     std::size_t bytes() const
     237                 :                :     {
     238                 :           2934 :         return count() * sizeof(T);
     239                 :                :     }
     240                 :                : 
     241                 :             25 :     void resize(std::size_t new_size, byte fill = 0)
     242                 :                :     {
     243                 :             25 :         data_->resize(new_size, fill);
     244                 :             25 :     }
     245                 :                : 
     246                 :           2909 :     void extend(std::size_t amount, byte fill = 0)
     247                 :                :     {
     248            [ + ]:           2909 :         data_->resize(count() + amount, fill);
     249                 :           2909 :     }
     250                 :                : 
     251                 :                :     std::vector<byte>::iterator iterator()
     252                 :                :     {
     253                 :                :         return data_->begin() + static_cast<std::ptrdiff_t>(offset());
     254                 :                :     }
     255                 :                : 
     256                 :                :     template<typename U>
     257                 :           2687 :     void append(const std::vector<U> &data)
     258                 :                :     {
     259                 :           2687 :         binary_reader<U> reader(data);
     260            [ + ]:           2687 :         append(reader, data.size() * sizeof(U));
     261                 :           2687 :     }
     262                 :                : 
     263                 :                :     template<typename U>
     264                 :           2861 :     void append(binary_reader<U> &reader, std::size_t reader_element_count)
     265                 :                :     {
     266                 :           2861 :         const auto num_bytes = sizeof(U) * reader_element_count;
     267                 :           2861 :         const auto remaining_bytes = bytes() - offset() * sizeof(T);
     268                 :                : 
     269         [ +  - ]:           2861 :         if (remaining_bytes < num_bytes)
     270                 :                :         {
     271                 :           2861 :             extend((num_bytes - remaining_bytes) / sizeof(T));
     272                 :                :         }
     273                 :                : 
     274         [ -  + ]:           2861 :         if ((reader.offset() + reader_element_count) * sizeof(U) > reader.bytes())
     275                 :                :         {
     276         [ #  # ]:UBC           0 :             throw xlnt::exception("reading past end");
     277                 :                :         }
     278                 :                : 
     279                 :CBC        2861 :         std::memcpy(data_->data() + offset_, reader.data() + reader.offset(), reader_element_count * sizeof(U));
     280                 :           2861 :         offset_ += reader_element_count * sizeof(U) / sizeof(T);
     281                 :           2861 :     }
     282                 :                : 
     283                 :                : private:
     284                 :                :     std::vector<T> *data_ = nullptr;
     285                 :                :     std::size_t offset_ = 0;
     286                 :                : };
     287                 :                : 
     288                 :                : template<typename T>
     289                 :             25 : std::vector<byte> string_to_bytes(const std::basic_string<T> &string)
     290                 :                : {
     291                 :             25 :     std::vector<byte> bytes;
     292                 :             25 :     binary_writer<byte> writer(bytes);
     293            [ + ]:             25 :     writer.assign(string);
     294                 :                : 
     295                 :             25 :     return bytes;
     296                 :             25 : }
     297                 :                : 
     298                 :                : template<typename T>
     299                 :            244 : T read(std::istream &in)
     300                 :                : {
     301                 :                :     T result;
     302            [ + ]:            244 :     in.read(reinterpret_cast<char *>(&result), sizeof(T));
     303                 :                : 
     304                 :            244 :     return result;
     305                 :                : }
     306                 :                : 
     307                 :                : template<typename T>
     308                 :             45 : std::vector<T> read_vector(std::istream &in, std::size_t count)
     309                 :                : {
     310            [ + ]:             45 :     std::vector<T> result(count, T());
     311            [ + ]:             45 :     in.read(reinterpret_cast<char *>(&result[0]),
     312                 :                :         static_cast<std::streamsize>(sizeof(T) * count));
     313                 :                : 
     314                 :             45 :     return result;
     315                 :UBC           0 : }
     316                 :                : 
     317                 :                : template<typename T>
     318                 :CBC          15 : std::basic_string<T> read_string(std::istream &in, std::size_t count)
     319                 :                : {
     320            [ + ]:             15 :     std::basic_string<T> result(count, T());
     321            [ + ]:             15 :     in.read(reinterpret_cast<char *>(&result[0]),
     322                 :             15 :         static_cast<std::streamsize>(sizeof(T) * count));
     323                 :                : 
     324                 :             15 :     return result;
     325                 :UBC           0 : }
     326                 :                : 
     327                 :                : } // namespace detail
     328                 :                : } // namespace xlnt
        

Generated by: LCOV version 2.3.1-beta