39{
40 if (start_idx < 0 ||
count <= 0)
return 0;
41
42 try {
43
44 auto ltrim = [](std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); };
45 auto rtrim = [](std::string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); };
46 ltrim(str);
47 rtrim(str);
48
49
50 if (str.size() >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { str.erase(0, 2); }
51
52
53 std::string hex;
54 hex.reserve(str.size());
55 for (char c : str) {
56 if (std::isxdigit(static_cast<unsigned char>(c))) hex.push_back(c);
57 }
58 if (hex.empty()) return 0;
59
60
61 const size_t total_bits = hex.size() * 4ULL;
62
63 const size_t ustart = static_cast<size_t>(start_idx);
64 if (ustart >= total_bits) return 0;
65
66 const int int_bits = std::numeric_limits<uint32_t>::digits;
67 const size_t need_bits =
static_cast<size_t>(std::min(
count, int_bits));
68
69
70 const size_t first_bit = ustart;
71 const size_t last_bit = std::min(ustart + need_bits, total_bits) - 1ULL;
72 if (last_bit < first_bit) return 0;
73
74 const size_t right_index = hex.size() - 1ULL;
75
76 const size_t first_nibble = first_bit / 4ULL;
77 const size_t last_nibble = last_bit / 4ULL;
78
79 const size_t start_idx = right_index - last_nibble;
80 const size_t end_idx = right_index - first_nibble;
81 if (end_idx < start_idx) return 0;
82
83 const size_t sub_len = end_idx - start_idx + 1ULL;
84 if (end_idx >= hex.size()) return 0;
85
86 const std::string sub_hex = hex.substr(start_idx, sub_len);
87
88 unsigned long long chunk = std::stoull(sub_hex, nullptr, 16);
89
90 const unsigned nibble_offset = static_cast<unsigned>(first_bit % 4ULL);
91 const unsigned long long shifted = (nibble_offset == 0U) ? chunk : (chunk >> nibble_offset);
92
93 uint32_t mask;
94 if (need_bits >= static_cast<size_t>(std::numeric_limits<uint32_t>::digits)) {
95 mask = std::numeric_limits<uint32_t>::max();
96 } else {
97 mask = static_cast<uint32_t>((1ULL << need_bits) - 1ULL);
98 }
99
100 const uint32_t val = static_cast<uint32_t>(shifted & mask);
101 return val;
102 } catch (const std::invalid_argument &) {
103 return 0;
104 } catch (const std::out_of_range &) {
105 return 0;
106 } catch (...) {
107 return 0;
108 }
109}