LCOV - code coverage report
Current view: top level - src/base - format.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 70 73 95.9 %
Date: 2026-06-27 19:56:04 Functions: 17 18 94.4 %
Branches: 22 28 78.6 %

           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 <cstdio>
      28                 :            : #include <cstring>
      29                 :            : #include <string_view>
      30                 :            : 
      31                 :            : namespace vlink {
      32                 :            : namespace format {
      33                 :            : namespace detail {
      34                 :            : 
      35                 :            : template <typename UIntT>
      36                 :         47 : inline static int count_digits(UIntT n) noexcept {
      37                 :         47 :   int count = 1;
      38                 :            : 
      39         [ +  + ]:        140 :   while (n >= 10) {
      40                 :         93 :     n /= 10;
      41                 :         93 :     ++count;
      42                 :            :   }
      43                 :            : 
      44                 :         47 :   return count;
      45                 :            : }
      46                 :            : 
      47                 :            : template <typename UIntT>
      48                 :         47 : inline static void write_int_digits(char* buf, UIntT value, int num_digits) noexcept {
      49                 :         47 :   char* end = buf + num_digits;
      50                 :            : 
      51         [ +  + ]:        140 :   while (value >= 10) {
      52                 :         93 :     auto digit = static_cast<unsigned>(value % 10);
      53                 :         93 :     *--end = static_cast<char>('0' + digit);
      54                 :         93 :     value /= 10;
      55                 :            :   }
      56                 :            : 
      57                 :         47 :   *--end = static_cast<char>('0' + value);
      58                 :         47 : }
      59                 :            : 
      60                 :            : // StringWriter
      61                 :         70 : StringWriter::StringWriter(char* buf, size_t size) noexcept : begin_(buf), ptr_(buf), end_(buf + size) {}
      62                 :            : 
      63                 :         70 : char* StringWriter::out() const noexcept { return ptr_; }
      64                 :            : 
      65                 :          0 : size_t StringWriter::written() const noexcept { return static_cast<size_t>(ptr_ - begin_); }
      66                 :            : 
      67                 :         70 : size_t StringWriter::total_size() const noexcept { return total_size_; }
      68                 :            : 
      69                 :        134 : void StringWriter::write(char c) {
      70                 :        134 :   ++total_size_;
      71                 :            : 
      72         [ +  + ]:        134 :   if VLIKELY (ptr_ < end_) {
      73                 :        122 :     *ptr_++ = c;
      74                 :            :   }
      75                 :        134 : }
      76                 :            : 
      77                 :         64 : void StringWriter::write(const char* s, size_t count) {
      78                 :         64 :   total_size_ += count;
      79                 :            : 
      80                 :         64 :   auto avail = static_cast<size_t>(end_ - ptr_);
      81         [ +  + ]:         64 :   size_t n = (count <= avail) ? count : avail;
      82                 :            : 
      83         [ +  + ]:         64 :   if VLIKELY (n > 0) {
      84                 :         61 :     std::memcpy(ptr_, s, n);
      85                 :         61 :     ptr_ += n;
      86                 :            :   }
      87                 :         64 : }
      88                 :            : 
      89                 :          4 : void StringWriter::write(std::string_view sv) { write(sv.data(), sv.size()); }
      90                 :            : 
      91                 :            : // NOLINTBEGIN
      92                 :         40 : size_t format_uint_to(char* buf, unsigned value) noexcept {
      93                 :         40 :   int num_digits = count_digits(value);
      94                 :         40 :   write_int_digits(buf, value, num_digits);
      95                 :            : 
      96                 :         40 :   return static_cast<size_t>(num_digits);
      97                 :            : }
      98                 :            : 
      99                 :         33 : size_t format_int_to(char* buf, int value) noexcept {
     100         [ +  + ]:         33 :   if (value < 0) {
     101                 :          4 :     buf[0] = '-';
     102                 :          4 :     unsigned u = static_cast<unsigned>(-(value + 1)) + 1;
     103                 :            : 
     104                 :          4 :     return 1 + format_uint_to(buf + 1, u);
     105                 :            :   }
     106                 :            : 
     107                 :         29 :   return format_uint_to(buf, static_cast<unsigned>(value));
     108                 :            : }
     109                 :            : 
     110                 :          7 : size_t format_ulong_long_to(char* buf, unsigned long long value) noexcept {
     111                 :          7 :   int num_digits = count_digits(value);
     112                 :          7 :   write_int_digits(buf, value, num_digits);
     113                 :            : 
     114                 :          7 :   return static_cast<size_t>(num_digits);
     115                 :            : }
     116                 :            : 
     117                 :          4 : size_t format_long_long_to(char* buf, long long value) noexcept {
     118         [ +  + ]:          4 :   if (value < 0) {
     119                 :          2 :     buf[0] = '-';
     120                 :          2 :     unsigned long long u = static_cast<unsigned long long>(-(value + 1)) + 1;
     121                 :            : 
     122                 :          2 :     return 1 + format_ulong_long_to(buf + 1, u);
     123                 :            :   }
     124                 :            : 
     125                 :          2 :   return format_ulong_long_to(buf, static_cast<unsigned long long>(value));
     126                 :            : }
     127                 :            : 
     128                 :          2 : size_t format_pointer_to(char* buf, const void* ptr) noexcept {
     129                 :            :   static constexpr const char kHexDigits[] = "0123456789abcdef";
     130                 :            :   static_assert(sizeof(uintptr_t) <= 8, "pointer size > 64bit not supported");
     131                 :            : 
     132                 :          2 :   buf[0] = '0';
     133                 :          2 :   buf[1] = 'x';
     134                 :            : 
     135                 :            :   char hex[16];
     136                 :          2 :   int i = 16;
     137                 :          2 :   auto value = reinterpret_cast<uintptr_t>(ptr);
     138                 :            : 
     139                 :            :   do {
     140                 :         13 :     hex[--i] = kHexDigits[value & 0xF];
     141                 :         13 :     value >>= 4;
     142         [ +  + ]:         13 :   } while (value != 0);
     143                 :            : 
     144                 :          2 :   size_t n = static_cast<size_t>(16 - i);
     145                 :          2 :   std::memcpy(buf + 2, hex + i, n);
     146                 :            : 
     147                 :          2 :   return 2 + n;
     148                 :            : }
     149                 :            : 
     150                 :          3 : size_t format_float_to(char* buf, size_t buflen, float value) noexcept {
     151                 :          3 :   int len = std::snprintf(buf, buflen, "%g", static_cast<double>(value));
     152                 :            : 
     153   [ +  -  +  -  :          3 :   if VLIKELY (len > 0 && static_cast<size_t>(len) < buflen) {
                   +  - ]
     154                 :          3 :     return static_cast<size_t>(len);
     155                 :            :   }
     156                 :            : 
     157                 :          0 :   return 0;
     158                 :            : }
     159                 :            : 
     160                 :          4 : size_t format_double_to(char* buf, size_t buflen, double value) noexcept {
     161                 :          4 :   int len = std::snprintf(buf, buflen, "%g", value);
     162                 :            : 
     163   [ +  -  +  -  :          4 :   if VLIKELY (len > 0 && static_cast<size_t>(len) < buflen) {
                   +  - ]
     164                 :          4 :     return static_cast<size_t>(len);
     165                 :            :   }
     166                 :            : 
     167                 :          0 :   return 0;
     168                 :            : }
     169                 :            : 
     170                 :            : // NOLINTEND
     171                 :            : 
     172                 :            : }  // namespace detail
     173                 :            : }  // namespace format
     174                 :            : }  // namespace vlink

Generated by: LCOV version 1.14