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

OSGeo / gdal / 15899162844

26 Jun 2025 10:14AM UTC coverage: 71.088% (+0.004%) from 71.084%
15899162844

Pull #12623

github

web-flow
Merge c704a8392 into f5cb024d4
Pull Request #12623: gdal raster overview add: add a --overview-src option

209 of 244 new or added lines in 5 files covered. (85.66%)

96 existing lines in 44 files now uncovered.

574014 of 807474 relevant lines covered (71.09%)

250815.03 hits per line

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

62.07
/third_party/fast_float/parse_number.h
1
#ifndef FASTFLOAT_PARSE_NUMBER_H
2
#define FASTFLOAT_PARSE_NUMBER_H
3

4
#include "ascii_number.h"
5
#include "decimal_to_binary.h"
6
#include "digit_comparison.h"
7
#include "float_common.h"
8

9
#include <cmath>
10
#include <cstring>
11
#include <limits>
12
#include <system_error>
13
namespace fast_float {
14

15
namespace detail {
16
/**
17
 * Special case +inf, -inf, nan, infinity, -infinity.
18
 * The case comparisons could be made much faster given that we know that the
19
 * strings a null-free and fixed.
20
 **/
21
template <typename T, typename UC>
22
from_chars_result_t<UC> FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first,
815✔
23
                                                           UC const *last,
24
                                                           T &value) noexcept {
25
  from_chars_result_t<UC> answer{};
815✔
26
  answer.ptr = first;
815✔
27
  answer.ec = std::errc(); // be optimistic
815✔
28
  bool minusSign = false;
815✔
29
  if (*first ==
815✔
30
      UC('-')) { // assume first < last, so dereference without checks;
31
                 // C++17 20.19.3.(7.1) explicitly forbids '+' here
32
    minusSign = true;
404✔
33
    ++first;
404✔
34
  }
35
#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS // disabled by default
36
  if (*first == UC('+')) {
37
    ++first;
38
  }
39
#endif
40
  if (last - first >= 3) {
815✔
41
    if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {
5✔
42
      answer.ptr = (first += 3);
×
43
      value = minusSign ? -std::numeric_limits<T>::quiet_NaN()
×
44
                        : std::numeric_limits<T>::quiet_NaN();
×
45
      // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7,
46
      // C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan).
47
      if (first != last && *first == UC('(')) {
×
48
        for (UC const *ptr = first + 1; ptr != last; ++ptr) {
×
49
          if (*ptr == UC(')')) {
×
50
            answer.ptr = ptr + 1; // valid nan(n-char-seq-opt)
×
51
            break;
×
52
          } else if (!((UC('a') <= *ptr && *ptr <= UC('z')) ||
×
53
                       (UC('A') <= *ptr && *ptr <= UC('Z')) ||
×
54
                       (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_')))
×
55
            break; // forbidden char, not nan(n-char-seq-opt)
×
56
        }
57
      }
58
      return answer;
×
59
    }
60
    if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {
5✔
61
      if ((last - first >= 8) &&
×
62
          fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
×
63
        answer.ptr = first + 8;
×
64
      } else {
65
        answer.ptr = first + 3;
×
66
      }
67
      value = minusSign ? -std::numeric_limits<T>::infinity()
×
68
                        : std::numeric_limits<T>::infinity();
×
69
      return answer;
×
70
    }
71
  }
72
  answer.ec = std::errc::invalid_argument;
815✔
73
  return answer;
815✔
74
}
75

76
/**
77
 * Returns true if the floating-pointing rounding mode is to 'nearest'.
78
 * It is the default on most system. This function is meant to be inexpensive.
79
 * Credit : @mwalcott3
80
 */
81
fastfloat_really_inline bool rounds_to_nearest() noexcept {
82
  // https://lemire.me/blog/2020/06/26/gcc-not-nearest/
83
#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
84
  return false;
85
#endif
86
  // See
87
  // A fast function to check your floating-point rounding mode
88
  // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/
89
  //
90
  // This function is meant to be equivalent to :
91
  // prior: #include <cfenv>
92
  //  return fegetround() == FE_TONEAREST;
93
  // However, it is expected to be much faster than the fegetround()
94
  // function call.
95
  //
96
  // The volatile keywoard prevents the compiler from computing the function
97
  // at compile-time.
98
  // There might be other ways to prevent compile-time optimizations (e.g.,
99
  // asm). The value does not need to be std::numeric_limits<float>::min(), any
100
  // small value so that 1 + x should round to 1 would do (after accounting for
101
  // excess precision, as in 387 instructions).
102
  static volatile float fmin = std::numeric_limits<float>::min();
103
  float fmini = fmin; // we copy it so that it gets loaded at most once.
15,281,600✔
104
//
105
// Explanation:
106
// Only when fegetround() == FE_TONEAREST do we have that
107
// fmin + 1.0f == 1.0f - fmin.
108
//
109
// FE_UPWARD:
110
//  fmin + 1.0f > 1
111
//  1.0f - fmin == 1
112
//
113
// FE_DOWNWARD or  FE_TOWARDZERO:
114
//  fmin + 1.0f == 1
115
//  1.0f - fmin < 1
116
//
117
// Note: This may fail to be accurate if fast-math has been
118
// enabled, as rounding conventions may not apply.
119
#ifdef FASTFLOAT_VISUAL_STUDIO
120
#pragma warning(push)
121
//  todo: is there a VS warning?
122
//  see
123
//  https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013
124
#elif defined(__clang__)
125
#pragma clang diagnostic push
126
#pragma clang diagnostic ignored "-Wfloat-equal"
127
#elif defined(__GNUC__)
128
#pragma GCC diagnostic push
129
#pragma GCC diagnostic ignored "-Wfloat-equal"
130
#endif
131
  return (fmini + 1.0f == 1.0f - fmini);
15,281,600✔
132
#ifdef FASTFLOAT_VISUAL_STUDIO
133
#pragma warning(pop)
134
#elif defined(__clang__)
135
#pragma clang diagnostic pop
136
#elif defined(__GNUC__)
137
#pragma GCC diagnostic pop
138
#endif
139
}
140

141
} // namespace detail
142

143
template <typename T> struct from_chars_caller {
144
  template <typename UC>
145
  FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
146
  call(UC const *first, UC const *last, T &value,
224✔
147
       parse_options_t<UC> options) noexcept {
148
    return from_chars_advanced(first, last, value, options);
224✔
149
  }
150
};
151

152
#if __STDCPP_FLOAT32_T__ == 1
153
template <> struct from_chars_caller<std::float32_t> {
154
  template <typename UC>
155
  FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
156
  call(UC const *first, UC const *last, std::float32_t &value,
157
       parse_options_t<UC> options) noexcept {
158
    // if std::float32_t is defined, and we are in C++23 mode; macro set for
159
    // float32; set value to float due to equivalence between float and
160
    // float32_t
161
    float val;
162
    auto ret = from_chars_advanced(first, last, val, options);
163
    value = val;
164
    return ret;
165
  }
166
};
167
#endif
168

169
#if __STDCPP_FLOAT64_T__ == 1
170
template <> struct from_chars_caller<std::float64_t> {
171
  template <typename UC>
172
  FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
173
  call(UC const *first, UC const *last, std::float64_t &value,
174
       parse_options_t<UC> options) noexcept {
175
    // if std::float64_t is defined, and we are in C++23 mode; macro set for
176
    // float64; set value as double due to equivalence between double and
177
    // float64_t
178
    double val;
179
    auto ret = from_chars_advanced(first, last, val, options);
180
    value = val;
181
    return ret;
182
  }
183
};
184
#endif
185

186
template <typename T, typename UC, typename>
187
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
188
from_chars(UC const *first, UC const *last, T &value,
224✔
189
           chars_format fmt /*= chars_format::general*/) noexcept {
190
  return from_chars_caller<T>::call(first, last, value,
448✔
191
                                    parse_options_t<UC>(fmt));
224✔
192
}
193

194
/**
195
 * This function overload takes parsed_number_string_t structure that is created
196
 * and populated either by from_chars_advanced function taking chars range and
197
 * parsing options or other parsing custom function implemented by user.
198
 */
199
template <typename T, typename UC>
200
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
201
from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
15,342,600✔
202

203
  static_assert(is_supported_float_type<T>(),
204
                "only some floating-point types are supported");
205
  static_assert(is_supported_char_type<UC>(),
206
                "only char, wchar_t, char16_t and char32_t are supported");
207

208
  from_chars_result_t<UC> answer;
209

210
  answer.ec = std::errc(); // be optimistic
15,342,600✔
211
  answer.ptr = pns.lastmatch;
15,342,600✔
212
  // The implementation of the Clinger's fast path is convoluted because
213
  // we want round-to-nearest in all cases, irrespective of the rounding mode
214
  // selected on the thread.
215
  // We proceed optimistically, assuming that detail::rounds_to_nearest()
216
  // returns true.
217
  if (binary_format<T>::min_exponent_fast_path() <= pns.exponent &&
15,342,600✔
218
      pns.exponent <= binary_format<T>::max_exponent_fast_path() &&
30,684,100✔
219
      !pns.too_many_digits) {
15,341,500✔
220
    // Unfortunately, the conventional Clinger's fast path is only possible
221
    // when the system rounds to the nearest float.
222
    //
223
    // We expect the next branch to almost always be selected.
224
    // We could check it first (before the previous branch), but
225
    // there might be performance advantages at having the check
226
    // be last.
227
    if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) {
30,563,200✔
228
      // We have that fegetround() == FE_TONEAREST.
229
      // Next is Clinger's fast path.
230
      if (pns.mantissa <= binary_format<T>::max_mantissa_fast_path()) {
15,281,600✔
231
        value = T(pns.mantissa);
15,065,500✔
232
        if (pns.exponent < 0) {
15,065,500✔
233
          value = value / binary_format<T>::exact_power_of_ten(-pns.exponent);
13,675,400✔
234
        } else {
235
          value = value * binary_format<T>::exact_power_of_ten(pns.exponent);
1,390,110✔
236
        }
237
        if (pns.negative) {
15,065,500✔
238
          value = -value;
6,499,120✔
239
        }
240
        return answer;
15,065,500✔
241
      }
242
    } else {
243
      // We do not have that fegetround() == FE_TONEAREST.
244
      // Next is a modified Clinger's fast path, inspired by Jakub JelĂ­nek's
245
      // proposal
UNCOV
246
      if (pns.exponent >= 0 &&
×
247
          pns.mantissa <=
×
248
              binary_format<T>::max_mantissa_fast_path(pns.exponent)) {
×
249
#if defined(__clang__) || defined(FASTFLOAT_32BIT)
250
        // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD
251
        if (pns.mantissa == 0) {
252
          value = pns.negative ? T(-0.) : T(0.);
253
          return answer;
254
        }
255
#endif
256
        value = T(pns.mantissa) *
×
257
                binary_format<T>::exact_power_of_ten(pns.exponent);
×
258
        if (pns.negative) {
×
259
          value = -value;
×
260
        }
261
        return answer;
×
262
      }
263
    }
264
  }
265
  adjusted_mantissa am =
266
      compute_float<binary_format<T>>(pns.exponent, pns.mantissa);
277,138✔
267
  if (pns.too_many_digits && am.power2 >= 0) {
277,138✔
268
    if (am != compute_float<binary_format<T>>(pns.exponent, pns.mantissa + 1)) {
119,746✔
269
      am = compute_error<binary_format<T>>(pns.exponent, pns.mantissa);
×
270
    }
271
  }
272
  // If we called compute_float<binary_format<T>>(pns.exponent, pns.mantissa)
273
  // and we have an invalid power (am.power2 < 0), then we need to go the long
274
  // way around again. This is very uncommon.
275
  if (am.power2 < 0) {
277,138✔
276
    am = digit_comp<T>(pns, am);
×
277
  }
278
  to_float(pns.negative, am, value);
277,138✔
279
  // Test for over/underflow.
280
  if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) ||
554,276✔
281
      am.power2 == binary_format<T>::infinite_power()) {
277,138✔
282
    answer.ec = std::errc::result_out_of_range;
3✔
283
  }
284
  return answer;
277,138✔
285
}
286

287
template <typename T, typename UC>
288
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
289
from_chars_advanced(UC const *first, UC const *last, T &value,
15,387,500✔
290
                    parse_options_t<UC> options) noexcept {
291

292
  static_assert(is_supported_float_type<T>(),
293
                "only some floating-point types are supported");
294
  static_assert(is_supported_char_type<UC>(),
295
                "only char, wchar_t, char16_t and char32_t are supported");
296

297
  from_chars_result_t<UC> answer;
298
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
299
  while ((first != last) && fast_float::is_space(uint8_t(*first))) {
300
    first++;
301
  }
302
#endif
303
  if (first == last) {
15,387,500✔
304
    answer.ec = std::errc::invalid_argument;
44,090✔
305
    answer.ptr = first;
44,090✔
306
    return answer;
44,090✔
307
  }
308
  parsed_number_string_t<UC> pns =
309
      parse_number_string<UC>(first, last, options);
15,343,400✔
310
  if (!pns.valid) {
15,343,400✔
311
    if (options.format & chars_format::no_infnan) {
815✔
312
      answer.ec = std::errc::invalid_argument;
×
313
      answer.ptr = first;
×
314
      return answer;
×
315
    } else {
316
      return detail::parse_infnan(first, last, value);
815✔
317
    }
318
  }
319

320
  // call overload that takes parsed_number_string_t directly.
321
  return from_chars_advanced(pns, value);
15,342,600✔
322
}
323

324
template <typename T, typename UC, typename>
325
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
326
from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
327
  static_assert(is_supported_char_type<UC>(),
328
                "only char, wchar_t, char16_t and char32_t are supported");
329

330
  from_chars_result_t<UC> answer;
331
#ifdef FASTFLOAT_SKIP_WHITE_SPACE // disabled by default
332
  while ((first != last) && fast_float::is_space(uint8_t(*first))) {
333
    first++;
334
  }
335
#endif
336
  if (first == last || base < 2 || base > 36) {
337
    answer.ec = std::errc::invalid_argument;
338
    answer.ptr = first;
339
    return answer;
340
  }
341
  return parse_int_string(first, last, value, base);
342
}
343

344
} // namespace fast_float
345

346
#endif
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

© 2025 Coveralls, Inc