LCOV - code coverage report
Current view: top level - src/base - format.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 75 75 100.0 %
Date: 2026-09-30 18:30:16 Functions: 8 8 100.0 %
Branches: 83 102 81.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2026 by Thun Lu. All rights reserved.
       3                 :            :  * Author: Thun Lu <thun.lu@zohomail.cn>
       4                 :            :  * Repo:   https://github.com/thun-res/vlink
       5                 :            :  *  _    __   __      _           __
       6                 :            :  * | |  / /  / /     (_) ____    / /__
       7                 :            :  * | | / /  / /     / / / __ \  / //_/
       8                 :            :  * | |/ /  / /___  / / / / / / / ,<
       9                 :            :  * |___/  /_____/ /_/ /_/ /_/ /_/|_|
      10                 :            :  *
      11                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
      12                 :            :  * you may not use this file except in compliance with the License.
      13                 :            :  * You may obtain a copy of the License at
      14                 :            :  *
      15                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      16                 :            :  *
      17                 :            :  * Unless required by applicable law or agreed to in writing, software
      18                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      19                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      20                 :            :  * See the License for the specific language governing permissions and
      21                 :            :  * limitations under the License.
      22                 :            :  */
      23                 :            : 
      24                 :            : #include "./base/format.h"
      25                 :            : 
      26                 :            : #include <cstdint>
      27                 :            : #include <cstring>
      28                 :            : 
      29                 :            : #include "./base/helpers.h"
      30                 :            : 
      31                 :            : namespace vlink {
      32                 :            : namespace format {
      33                 :            : namespace detail {
      34                 :            : 
      35                 :            : // NOLINTBEGIN
      36                 :          9 : size_t format_pointer_to(char* buf, const void* ptr) noexcept {
      37                 :            :   static constexpr const char kHexDigits[] = "0123456789abcdef";
      38                 :            :   static_assert(sizeof(uintptr_t) <= 8, "pointer size > 64bit not supported");
      39                 :            : 
      40                 :          9 :   buf[0] = '0';
      41                 :          9 :   buf[1] = 'x';
      42                 :            : 
      43                 :            :   char hex[16];
      44                 :          9 :   int i = 16;
      45                 :          9 :   auto value = reinterpret_cast<uintptr_t>(ptr);
      46                 :            : 
      47                 :            :   do {
      48                 :         23 :     hex[--i] = kHexDigits[value & 0xF];
      49                 :         23 :     value >>= 4;
      50         [ +  + ]:         23 :   } while (value != 0);
      51                 :            : 
      52                 :          9 :   size_t n = static_cast<size_t>(16 - i);
      53                 :          9 :   std::memcpy(buf + 2, hex + i, n);
      54                 :            : 
      55                 :          9 :   return 2 + n;
      56                 :            : }
      57                 :            : 
      58                 :          4 : size_t format_float_to(char* buf, size_t buflen, float value) noexcept {
      59                 :          4 :   return Helpers::format_floating_to(buf, buflen, value);
      60                 :            : }
      61                 :            : 
      62                 :          9 : size_t format_double_to(char* buf, size_t buflen, double value) noexcept {
      63                 :          9 :   return Helpers::format_floating_to(buf, buflen, value);
      64                 :            : }
      65                 :            : 
      66                 :          1 : size_t format_long_double_to(char* buf, size_t buflen, long double value) noexcept {
      67                 :          1 :   return Helpers::format_floating_to(buf, buflen, value);
      68                 :            : }
      69                 :            : 
      70                 :         51 : size_t format_double_spec_to(char* buf, size_t buflen, double value, char type, int precision, bool alt) noexcept {
      71                 :         51 :   return Helpers::format_floating_spec_to(buf, buflen, value, type, precision, alt);
      72                 :            : }
      73                 :            : 
      74                 :          5 : size_t format_long_double_spec_to(char* buf, size_t buflen, long double value, char type, int precision,
      75                 :            :                                   bool alt) noexcept {
      76                 :          5 :   return Helpers::format_floating_spec_to(buf, buflen, value, type, precision, alt);
      77                 :            : }
      78                 :            : 
      79                 :         21 : const char* parse_spec_ref(const char* p, const char* end, int& ref) noexcept {
      80                 :         21 :   ++p;
      81                 :         21 :   int index = kSpecRefAuto;
      82                 :            : 
      83   [ +  -  +  -  :         21 :   if (p != end && *p >= '0' && *p <= '9') {
                   +  + ]
      84                 :          3 :     index = 0;
      85                 :            : 
      86   [ +  -  +  -  :          6 :     while (p != end && *p >= '0' && *p <= '9') {
                   +  + ]
      87         [ +  - ]:          3 :       if (index < 100000000) {
      88                 :          3 :         index = index * 10 + (*p - '0');
      89                 :            :       }
      90                 :            : 
      91                 :          3 :       ++p;
      92                 :            :     }
      93                 :            :   }
      94                 :            : 
      95   [ +  -  +  + ]:         21 :   if (p != end && *p == '}') {
      96                 :         19 :     ref = index;
      97                 :         19 :     ++p;
      98                 :            :   }
      99                 :            : 
     100                 :         21 :   return p;
     101                 :            : }
     102                 :            : 
     103                 :        224 : const char* parse_format_spec(const char* p, const char* end, FormatSpec& spec) noexcept {
     104   [ +  -  +  +  :        224 :   if (p != end && p + 1 != end && (p[1] == '<' || p[1] == '>' || p[1] == '^') && *p != '{' && *p != '}') {
          +  +  +  +  +  
             +  +  -  +  
                      - ]
     105                 :          8 :     spec.fill = *p;
     106   [ +  +  +  + ]:          8 :     spec.align = p[1] == '<' ? Align::kLeft : (p[1] == '>' ? Align::kRight : Align::kCenter);
     107                 :          8 :     p += 2;
     108   [ +  -  +  +  :        216 :   } else if (p != end && (*p == '<' || *p == '>' || *p == '^')) {
             +  +  +  + ]
     109   [ +  +  +  + ]:         27 :     spec.align = *p == '<' ? Align::kLeft : (*p == '>' ? Align::kRight : Align::kCenter);
     110                 :         27 :     ++p;
     111                 :            :   }
     112                 :            : 
     113   [ +  -  +  +  :        224 :   if (p != end && (*p == '+' || *p == '-' || *p == ' ')) {
             +  +  +  + ]
     114   [ +  +  +  + ]:         13 :     spec.sign = *p == '+' ? Sign::kPlus : (*p == ' ' ? Sign::kSpace : Sign::kMinus);
     115                 :         13 :     ++p;
     116                 :            :   }
     117                 :            : 
     118   [ +  -  +  + ]:        224 :   if (p != end && *p == '#') {
     119                 :         27 :     spec.alt = true;
     120                 :         27 :     ++p;
     121                 :            :   }
     122                 :            : 
     123   [ +  -  +  + ]:        224 :   if (p != end && *p == '0') {
     124                 :         25 :     spec.zero = true;
     125                 :         25 :     ++p;
     126                 :            :   }
     127                 :            : 
     128   [ +  -  +  + ]:        224 :   if (p != end && *p == '{') {
     129                 :         17 :     p = parse_spec_ref(p, end, spec.width_ref);
     130                 :            :   } else {
     131   [ +  +  +  +  :        305 :     while (p != end && *p >= '0' && *p <= '9') {
                   +  + ]
     132         [ +  - ]:         98 :       if (spec.width < 100000000) {
     133                 :         98 :         spec.width = spec.width * 10 + (*p - '0');
     134                 :            :       }
     135                 :            : 
     136                 :         98 :       ++p;
     137                 :            :     }
     138                 :            :   }
     139                 :            : 
     140   [ +  +  +  + ]:        224 :   if (p != end && *p == '.') {
     141                 :         44 :     ++p;
     142                 :         44 :     spec.precision = 0;
     143                 :            : 
     144   [ +  -  +  + ]:         44 :     if (p != end && *p == '{') {
     145                 :          4 :       p = parse_spec_ref(p, end, spec.precision_ref);
     146                 :            :     } else {
     147   [ +  -  +  -  :         84 :       while (p != end && *p >= '0' && *p <= '9') {
                   +  + ]
     148         [ +  - ]:         44 :         if (spec.precision < 100000000) {
     149                 :         44 :           spec.precision = spec.precision * 10 + (*p - '0');
     150                 :            :         }
     151                 :            : 
     152                 :         44 :         ++p;
     153                 :            :       }
     154                 :            :     }
     155                 :            :   }
     156                 :            : 
     157         [ +  + ]:        224 :   if (p != end) {
     158         [ +  + ]:        223 :     switch (*p) {
     159                 :        128 :       case 'b':
     160                 :            :       case 'B':
     161                 :            :       case 'c':
     162                 :            :       case 'd':
     163                 :            :       case 'o':
     164                 :            :       case 'x':
     165                 :            :       case 'X':
     166                 :            :       case 'a':
     167                 :            :       case 'A':
     168                 :            :       case 'e':
     169                 :            :       case 'E':
     170                 :            :       case 'f':
     171                 :            :       case 'F':
     172                 :            :       case 'g':
     173                 :            :       case 'G':
     174                 :            :       case 's':
     175                 :            :       case 'p':
     176                 :            :       case '?':
     177                 :        128 :         spec.type = *p;
     178                 :        128 :         ++p;
     179                 :        128 :         break;
     180                 :         95 :       default:
     181                 :         95 :         break;
     182                 :            :     }
     183                 :            :   }
     184                 :            : 
     185                 :        224 :   return p;
     186                 :            : }
     187                 :            : 
     188                 :            : // NOLINTEND
     189                 :            : 
     190                 :            : }  // namespace detail
     191                 :            : }  // namespace format
     192                 :            : }  // namespace vlink

Generated by: LCOV version 1.14