differential code coverage report with master
Current view: top level - source/worksheet - range_reference.cpp (source / functions) Coverage Total Hit UBC CBC
Current: coverage.info Lines: 96.8 % 124 120 4 120
Current Date: 2025-12-07 02:01:22 Functions: 93.5 % 31 29 2 29
Baseline: coverage_master.info Branches: 91.0 % 134 122 24 244
Baseline Date: 2025-12-07 02:01:21

             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                 :                : #include <xlnt/worksheet/range_reference.hpp>
      26                 :                : 
      27                 :                : #include <detail/constants.hpp>
      28                 :                : #include <xlnt/utils/exceptions.hpp>
      29                 :                : #include <detail/serialization/parsers.hpp>
      30                 :                : 
      31                 :                : namespace {
      32                 :                : 
      33                 :CBC         131 : bool is_whole_column(const std::string &s)
      34                 :                : {
      35         [ +  + ]:            131 :     if (s.empty())
      36                 :                :     {
      37                 :              1 :         return false;
      38                 :                :     }
      39                 :                : 
      40         [ +  + ]:            130 :     size_t start_pos = (s[0] == '$') ? 1 : 0;
      41         [ +  + ]:            130 :     if (start_pos >= s.length()) // String contains only a "$"
      42                 :                :     {
      43                 :              1 :         return false;
      44                 :                :     }
      45                 :                : 
      46         [ +  + ]:            246 :     for (size_t i = start_pos; i < s.length(); ++i)
      47                 :                :     {
      48         [ +  + ]:            228 :         if (!std::isalpha(static_cast<unsigned char>(s[i])))
      49                 :                :         {
      50                 :            111 :             return false;
      51                 :                :         }
      52                 :                :     }
      53                 :                : 
      54                 :             18 :     return true;
      55                 :                : }
      56                 :                : 
      57                 :            124 : bool is_whole_row(const std::string &s)
      58                 :                : {
      59         [ +  + ]:            124 :     if (s.empty())
      60                 :                :     {
      61                 :              1 :         return false;
      62                 :                :     }
      63                 :                : 
      64         [ +  + ]:            123 :     size_t start_pos = (s[0] == '$') ? 1 : 0;
      65         [ +  + ]:            123 :     if (start_pos >= s.length()) // String contains only a "$"
      66                 :                :     {
      67                 :              1 :         return false;
      68                 :                :     }
      69                 :                : 
      70         [ +  + ]:            234 :     for (size_t i = start_pos; i < s.length(); ++i)
      71                 :                :     {
      72         [ +  + ]:            212 :         if (!std::isdigit(static_cast<unsigned char>(s[i])))
      73                 :                :         {
      74                 :            100 :             return false;
      75                 :                :         }
      76                 :                :     }
      77                 :                : 
      78                 :             22 :     return true;
      79                 :                : }
      80                 :                : 
      81                 :             40 : bool extract_absolute (std::string& part)
      82                 :                : {
      83                 :             40 :     bool absolute = part[0] == '$';
      84         [ +  + ]:             40 :     if (absolute)
      85                 :                :     {
      86                 :             14 :         part.erase(0, 1);
      87                 :                :     }
      88                 :             40 :     return absolute;
      89                 :                : }
      90                 :                : }
      91                 :                : 
      92                 :                : namespace xlnt {
      93                 :                : 
      94                 :              5 : range_reference range_reference::make_absolute(const xlnt::range_reference &relative)
      95                 :                : {
      96                 :              5 :     range_reference copy = relative;
      97                 :                : 
      98                 :              5 :     copy.top_left_.make_absolute(true, true);
      99                 :              5 :     copy.bottom_right_.make_absolute(true, true);
     100                 :                : 
     101                 :              5 :     return copy;
     102                 :                : }
     103                 :                : 
     104                 :              9 : range_reference::range_reference()
     105                 :              9 :     : range_reference("A1")
     106                 :                : {
     107                 :              9 : }
     108                 :                : 
     109                 :             59 : range_reference::range_reference(const char *range_string)
     110         [ +  + ]:             65 :     : range_reference(std::string(range_string))
     111                 :                : {
     112                 :             53 : }
     113                 :                : 
     114                 :            233 : range_reference::range_reference(const std::string &range_string)
     115                 :                : {
     116                 :            233 :     auto colon_index = range_string.find(':');
     117                 :                : 
     118         [ +  + ]:            233 :     if (colon_index == std::string::npos)
     119                 :                :     {
     120                 :                :         // Single cell reference, e.g., "A1"
     121            [ + ]:            111 :         top_left_ = cell_reference(range_string);
     122                 :            110 :         bottom_right_ = top_left_;
     123                 :            110 :         return;
     124                 :                :     }
     125                 :                : 
     126            [ + ]:            122 :     std::string start_part = range_string.substr(0, colon_index);
     127            [ + ]:            122 :     std::string end_part = range_string.substr(colon_index + 1);
     128                 :                : 
     129   [ +  +  +  -  :            122 :     if (is_whole_column(start_part) && is_whole_column(end_part))
                   +  + ]
     130                 :                :     {
     131                 :                :         // Whole column reference, e.g., "A:C"
     132            [ + ]:              9 :         bool absoluteStart = extract_absolute(start_part);
     133            [ + ]:              9 :         bool absoluteEnd = extract_absolute(end_part);
     134                 :                : 
     135      [ +  +  + ]:              9 :         top_left_ = cell_reference(start_part, 1).make_absolute(absoluteStart, true);
     136   [ +  +  +  + ]:              9 :         bottom_right_ = cell_reference(end_part, constants::max_row()).make_absolute(absoluteEnd, true);
     137                 :                :     }
     138   [ +  +  +  -  :            113 :     else if (is_whole_row(start_part) && is_whole_row(end_part))
                   +  + ]
     139                 :                :     {
     140                 :                :         // Whole row reference, e.g., "1:5"
     141            [ + ]:             11 :         bool absoluteStart = extract_absolute(start_part);
     142            [ + ]:             11 :         bool absoluteEnd = extract_absolute(end_part);
     143                 :                : 
     144                 :                :         row_t start_row;
     145      [ +  +  + ]:             11 :         if (detail::parse(start_part, start_row) != std::errc())
     146                 :                :         {
     147            [ + ]:              1 :             throw xlnt::invalid_cell_reference(start_part);
     148                 :                :         }
     149                 :                :         row_t end_row;
     150      [ +  +  + ]:             10 :         if (detail::parse(end_part, end_row) != std::errc())
     151                 :                :         {
     152            [ + ]:              1 :             throw xlnt::invalid_cell_reference(end_part);
     153                 :                :         }
     154                 :                : 
     155      [ +  +  + ]:              9 :         top_left_ = cell_reference(constants::min_column(), start_row).make_absolute(true, absoluteStart);
     156      [ +  +  + ]:              9 :         bottom_right_ = cell_reference(constants::max_column(), end_row).make_absolute(true, absoluteEnd);
     157                 :                :     }
     158                 :                :     else
     159                 :                :     {
     160            [ + ]:            102 :         top_left_ = cell_reference(start_part);
     161            [ + ]:             99 :         bottom_right_ = cell_reference(end_part);
     162                 :                :     }
     163                 :            127 : }
     164                 :                : 
     165                 :             44 : range_reference::range_reference(const cell_reference &top_left,
     166                 :             44 :     const cell_reference &bottom_right)
     167                 :             44 :     : top_left_(top_left),
     168                 :             44 :       bottom_right_(bottom_right)
     169                 :                : {
     170                 :             44 : }
     171                 :                : 
     172                 :            169 : range_reference::range_reference(column_t column_index_start,
     173                 :                :     row_t row_index_start,
     174                 :                :     column_t column_index_end,
     175                 :            169 :     row_t row_index_end)
     176                 :            169 :     : top_left_(column_index_start, row_index_start),
     177                 :            169 :       bottom_right_(column_index_end, row_index_end)
     178                 :                : {
     179                 :            169 : }
     180                 :                : 
     181                 :              2 : range_reference range_reference::make_offset(int column_offset, int row_offset) const
     182                 :                : {
     183            [ + ]:              2 :     auto top_left = top_left_.make_offset(column_offset, row_offset);
     184            [ + ]:              2 :     auto bottom_right = bottom_right_.make_offset(column_offset, row_offset);
     185                 :                : 
     186                 :              4 :     return range_reference(top_left, bottom_right);
     187                 :                : }
     188                 :                : 
     189                 :             69 : std::size_t range_reference::height() const
     190                 :                : {
     191                 :             69 :     return 1 + bottom_right_.row() - top_left_.row();
     192                 :                : }
     193                 :                : 
     194                 :            101 : std::size_t range_reference::width() const
     195                 :                : {
     196      [ +  +  + ]:            101 :     return 1 + (bottom_right_.column() - top_left_.column()).index;
     197                 :                : }
     198                 :                : 
     199                 :             97 : bool range_reference::is_single_cell() const
     200                 :                : {
     201   [ +  +  +  + ]:             97 :     return width() == 1 && height() == 1;
     202                 :                : }
     203                 :                : 
     204                 :              8 : bool range_reference::whole_row() const
     205                 :                : {
     206   [ +  +  +  +  :             15 :     return top_left_.column() == xlnt::constants::min_column() && top_left_.column_absolute()
                   +  + ]
     207   [ +  +  +  +  :             15 :         && bottom_right_.column() == xlnt::constants::max_column() && bottom_right_.column_absolute();
          +  +  +  +  +  
                      - ]
     208                 :                : }
     209                 :                : 
     210                 :              8 : bool range_reference::whole_column() const
     211                 :                : {
     212         [ +  + ]:             15 :     return top_left_.row() == xlnt::constants::min_row() && top_left_.row_absolute()
     213   [ +  +  +  +  :             15 :         && bottom_right_.row() == xlnt::constants::max_row() && bottom_right_.row_absolute();
                   +  - ]
     214                 :                : }
     215                 :                : 
     216                 :             94 : std::string range_reference::to_string() const
     217                 :                : {
     218         [ +  + ]:             94 :     if (is_single_cell())
     219            [ + ]:             49 :         return top_left().to_string();
     220                 :                :     else
     221   [ +  +  +  + ]:             45 :         return top_left_.to_string() + ":" + bottom_right_.to_string();
     222                 :                : }
     223                 :                : 
     224                 :            424 : bool range_reference::operator==(const range_reference &comparand) const
     225                 :                : {
     226   [ +  +  +  + ]:            424 :     return comparand.top_left_ == top_left_ && comparand.bottom_right_ == bottom_right_;
     227                 :                : }
     228                 :                : 
     229                 :             31 : bool range_reference::operator!=(const range_reference &comparand) const
     230                 :                : {
     231                 :             31 :     return !(*this == comparand);
     232                 :                : }
     233                 :                : 
     234                 :           6212 : cell_reference range_reference::top_left() const
     235                 :                : {
     236                 :           6212 :     return top_left_;
     237                 :                : }
     238                 :                : 
     239                 :UBC           0 : cell_reference range_reference::top_right() const
     240                 :                : {
     241      [ #  #  # ]:              0 :     return cell_reference(bottom_right_.column(), top_left_.row());
     242                 :                : }
     243                 :                : 
     244                 :              0 : cell_reference range_reference::bottom_left() const
     245                 :                : {
     246      [ #  #  # ]:              0 :     return cell_reference(top_left_.column(), bottom_right_.row());
     247                 :                : }
     248                 :                : 
     249                 :CBC       22206 : cell_reference range_reference::bottom_right() const
     250                 :                : {
     251                 :          22206 :     return bottom_right_;
     252                 :                : }
     253                 :                : 
     254                 :              4 : bool range_reference::contains(const cell_reference &ref) const
     255                 :                : {
     256                 :              4 :     return top_left_.column_index() <= ref.column_index()
     257         [ +  + ]:              4 :         && bottom_right_.column_index() >= ref.column_index()
     258         [ +  - ]:              3 :         && top_left_.row() <= ref.row()
     259   [ +  -  +  + ]:              8 :         && bottom_right_.row() >= ref.row();
     260                 :                : }
     261                 :                : 
     262                 :             32 : bool range_reference::operator==(const std::string &reference_string) const
     263                 :                : {
     264         [ +  + ]:             32 :     return *this == range_reference(reference_string);
     265                 :                : }
     266                 :                : 
     267                 :             30 : bool range_reference::operator==(const char *reference_string) const
     268                 :                : {
     269         [ +  + ]:             60 :     return *this == std::string(reference_string);
     270                 :                : }
     271                 :                : 
     272                 :              5 : bool range_reference::operator!=(const std::string &reference_string) const
     273                 :                : {
     274         [ +  + ]:              5 :     return *this != range_reference(reference_string);
     275                 :                : }
     276                 :                : 
     277                 :              3 : bool range_reference::operator!=(const char *reference_string) const
     278                 :                : {
     279         [ +  + ]:              6 :     return *this != std::string(reference_string);
     280                 :                : }
     281                 :                : 
     282                 :              1 : bool operator==(const std::string &reference_string, const range_reference &ref)
     283                 :                : {
     284                 :              1 :     return ref == reference_string;
     285                 :                : }
     286                 :                : 
     287                 :             13 : bool operator==(const char *reference_string, const range_reference &ref)
     288                 :                : {
     289                 :             13 :     return ref == reference_string;
     290                 :                : }
     291                 :                : 
     292                 :              1 : bool operator!=(const std::string &reference_string, const range_reference &ref)
     293                 :                : {
     294                 :              1 :     return ref != reference_string;
     295                 :                : }
     296                 :                : 
     297                 :              1 : bool operator!=(const char *reference_string, const range_reference &ref)
     298                 :                : {
     299                 :              1 :     return ref != reference_string;
     300                 :                : }
     301                 :                : 
     302                 :                : } // namespace xlnt
        

Generated by: LCOV version 2.3.1-beta