• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PeterCDMcLean / BitLib / 16383376446

19 Jul 2025 01:20AM UTC coverage: 78.092% (-0.5%) from 78.608%
16383376446

Pull #18

github

web-flow
Merge eb5f6b9bf into 02a1d27a8
Pull Request #18: From string

3310 of 4840 branches covered (68.39%)

Branch coverage included in aggregate %.

181 of 217 new or added lines in 12 files covered. (83.41%)

12 existing lines in 2 files now uncovered.

2404 of 2477 relevant lines covered (97.05%)

31964982.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/include/bitlib/bit-algorithms/to_from_string.hpp
1
// ================================= array_REF =================================== //
2
// Project:     The Experimental Bit Algorithms Library
3
// \file        to_string.hpp
4
// Description: Implementation of array_ref
5
// Creator:     Vincent Reverdy
6
// Contributor: Peter McLean [2025]
7
// License:     BSD 3-Clause License
8
// ========================================================================== //
9

10
#ifndef _BIT_TO_STRING_HPP_INCLUDED
11
#define _BIT_TO_STRING_HPP_INCLUDED
12

13
#include <array>
14
#include <bit>
15
#include <string>
16

17
#include "bitlib/bit-algorithms/accumulate.hpp"
18
#include "bitlib/bit-algorithms/count.hpp"
19
#include "bitlib/bit_concepts.hpp"
20

21
namespace bit {
22

23
namespace string {
24

25
template <std::size_t Base>
UNCOV
26
constexpr auto make_digit_map() {
UNCOV
27
  static_assert((Base >= 2) && ((Base & (Base - 1)) == 0), "Base must be power of 2 >= 2");
UNCOV
28
  static_assert(Base <= 64, "Base too large for simple char mapping");
UNCOV
29

NEW
30
  ::std::array<char, Base> map{};
UNCOV
31
  for (std::size_t i = 0; i < Base; ++i) {
UNCOV
32
    map[i] = (i < 10) ? ('0' + i) : ('A' + (i - 10));
UNCOV
33
  }
UNCOV
34
  return map;
UNCOV
35
}
36

37
template <std::size_t Base>
38
constexpr auto make_from_digit_map() {
39
  static_assert((Base >= 2) && ((Base & (Base - 1)) == 0), "Base must be power of 2 >= 2");
40
  static_assert(Base <= 64, "Base too large for simple char mapping");
41

42
  ::std::array<char, 128> map{};
43
  for (std::size_t i = 0; i < 128; ++i) {
44
    map[i] = ~0;
45
    if (i >= '0' && i <= '9') {
46
      map[i] = i - '0';
47
    }
48
    if (i >= 'a' && i <= 'z') {
49
      map[i] = (i - 'a') + 10;
50
    }
51
    if (i >= 'A' && i <= 'Z') {
52
      map[i] = (i - 'A') + 10;
53
    }
54
  }
55
  return map;
56
}
57

58
struct metadata_t {
59
  size_t base;
60
  bool is_signed;
61
  std::endian endian;
62
  bool str_sign_extend_zeros;
63
};
64

65
constexpr metadata_t typical(size_t base = 10, bool str_sign_extend_zeros = false) {
66
  return {
67
      .base = base,
68
      .is_signed = false,
69
      .endian = std::endian::big,
70
      .str_sign_extend_zeros = str_sign_extend_zeros};
71
}
72

73
}  // namespace string
74

75
template <string::metadata_t meta = string::typical(), typename RandomAccessIt>
76
constexpr std::string to_string(const bit_iterator<RandomAccessIt>& first, const bit_iterator<RandomAccessIt>& last, std::string prefix = "") {
8✔
77
  static_assert(meta.endian == std::endian::big, "Only bit big endian support (MSB on the left)");
4✔
78
  if constexpr (std::has_single_bit(meta.base)) {
4✔
79
    constexpr const auto base_bits = std::bit_width(meta.base - 1);
8✔
80

81
    int skip_leading_bits = meta.str_sign_extend_zeros ? 0 : count_msb(first, last, bit0);
8✔
82

83
    int str_len = (distance(first, last) - skip_leading_bits);
8✔
84
    str_len = (str_len + base_bits - 1) / base_bits;  // Round up to nearest base digit
8✔
85
    if (0 == str_len) {
8!
UNCOV
86
      return prefix + "0";
×
UNCOV
87
    }
88
    std::string& str = prefix;
8✔
89
    str.resize(str.length() + str_len);
8✔
90

91
    static constexpr auto base_digits = string::make_digit_map<meta.base>();
4✔
92

93
    return accumulate(
12✔
94
        policy::AccumulateNoInitialSubword{},
4✔
95
        first, last - skip_leading_bits, (str.data() + str_len),
12✔
96
        [](char* acc, auto word, const size_t bits = bitsof<decltype(word)>()) {
8✔
97
          const int characters = ((bits + base_bits - 1) / base_bits);
8✔
98
          acc -= characters;
8✔
99
          for (int i = characters - 1; i >= 0; i--) {
72✔
100
            acc[i] = base_digits[word & (meta.base - 1)];
64✔
101
            word >>= base_bits;
64✔
102
          }
32✔
103
          return acc;
8✔
104
        });
16✔
105
  } else {
106
    return "not_implented_yet";
107
  }
108
}
4✔
109

110
template <string::metadata_t meta = string::typical()>
111
constexpr std::string to_string(const bit_sized_range auto& bits, std::string prefix = "") {
8✔
112
  return to_string<meta>(bits.begin(), bits.end(), prefix);
12✔
113
}
4✔
114
#if 0
115
template <string::metadata_t meta = string::typical(), typename Policy = policy::typical<uintptr_t>, typename RandomAccessIt>
116
constexpr size_t pessimistic_bits_for_string(
117
    const char* str_first, const char* str_last) {
118
  const char* it = str_first;
119
  for (; (it != str_last) && (*it == '0'); ++it) {
120
  }
121
  const size_t non_zero_str_len = str_last - it;
122
  if (non_zero_str_len == 0) {
123
    return meta.is_signed ? 1 : 0;  // All zeros
124
  }
125
  if constexpr (std::has_single_bit(meta.base)) {
126
    constexpr const auto base_bits = std::bit_width(meta.base - 1);
127
    static constexpr auto base_from_digits = string::make_from_digit_map<meta.base>();
128
    return non_zero_str_len * base_bits + meta.is_signed;
129
  } else {
130
    constexpr double base_in_base2 = std::log2(meta.base);
131

132
    return static_cast<size_t>(std::floor(base_in_base2 * non_zero_str_len)) + 1 + meta.is_signed;
133
  }
134
}
135

136
template <string::metadata_t meta = string::typical(), typename Policy = policy::typical<uintptr_t>, typename RandomAccessIt>
137
constexpr void from_string(
138
    Policy,
139
    const char* str_first, const char* str_last,
140
    bit_iterator<RandomAccessIt> bit_first, bit_iterator<RandomAccessIt> bit_last) {
141
  const auto str_len = str_last - str_first;
142
  const auto store_bits = distance(bit_first, bit_last);
143
  if constexpr (std::has_single_bit(meta.base)) {
144
    constexpr const auto base_bits = std::bit_width(meta.base - 1);
145
    static constexpr auto base_from_digits = string::make_from_digit_map<meta.base>();
146
    constexpr const auto str_bits = str_len * base_bits;
147
    if (store_bits < str_bits) {
148
      Policy::truncation::template from_string<std::dynamic_extent>(
149
          str_first, str_last, str_cur, bit_first, bit_last);
150
    } else if (store_bits > str_bits) {
151
      Policy::extension::template from_string<std::dynamic_extent>(
152
          str_first, str_last, str_cur, bit_first, bit_last);
153
    } else {
154
      char str_cur = str_last - 1;
155
      bit_iterator<RandomAccessIt> bit_cur = bit_first;
156
      while (str_cur >= str_first) {
157
        str_cur--;
158
      }
159
    }
160
  }
161
}
162
#endif
163
/*
164
Commenting this out temporarily as the reference to bit_vector/bit_array messes up include dependency DAG
165

166
template <string::metadata_t meta = string::typical()>
167
constexpr bit_vector<> from_string(const char* first, const char* last) {
168
  static_assert(meta.endian == std::endian::big, "Only bit big endian support (MSB on the left)");
169
  if constexpr (std::has_single_bit(meta.base)) {
170
    constexpr const auto base_bits = std::bit_width(meta.base - 1);
171
    static constexpr auto base_from_digits = string::make_from_digit_map<meta.base>();
172

173
    bit_vector<> vec;
174

175
    last--;
176
    while (last >= first) {
177
      uint64_t work = 0;
178
      size_t bits = 0;
179
      for (; (bits < bitsof<uint64_t>()) && (last >= first); last--) {
180
        char c = *last;
181
        // TODO: This should be a policy
182
        if (c >= base_from_digits.size()) {
183
          continue;
184
        }
185
        auto digit = base_from_digits[c];
186
        // TODO: This should be a policy
187
        if (~0 == digit) {
188
          continue;
189
        }
190
        work |= (digit << bits);
191
        bits += base_bits;
192
      }
193
      if (bits) {
194
        vec.append_range(bit_array<>(bits, work));
195
      }
196
    }
197
    return vec;
198
  } else {
199
    //from_string base 10 not implemented yet;
200
  }
201
}
202

203
template <string::metadata_t meta = string::typical()>
204
constexpr bit_vector<> from_string(const std::string& str) {
205
  return from_string<meta>(str.c_str(), str.c_str() + str.length());
206
}
207
*/
208

209
}  // namespace bit
210

211
#endif // _BIT_TO_STRING_HPP_INCLUDED
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc