Add numbers parsing
This commit is contained in:
@ -21,3 +21,4 @@ Checks:
|
||||
- "-cppcoreguidelines-pro-type-union-access"
|
||||
- "-*-copy-assignment-signature"
|
||||
- "-*-unconventional-assign-operator"
|
||||
- "-readability-math-missing-parentheses"
|
||||
|
@ -45,6 +45,24 @@ cc_library(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "parse_number",
|
||||
hdrs = [
|
||||
"parse_number.hpp",
|
||||
],
|
||||
srcs = [
|
||||
"parse_number_float.cpp",
|
||||
"parse_number.cpp",
|
||||
],
|
||||
deps = [
|
||||
"//asl/base",
|
||||
"//asl/types:status",
|
||||
":string_view",
|
||||
"//vendor/fast_float",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
[cc_test(
|
||||
name = "%s_tests" % name,
|
||||
srcs = [
|
||||
@ -54,6 +72,7 @@ cc_library(
|
||||
":string",
|
||||
":string_builder",
|
||||
":string_view",
|
||||
":parse_number",
|
||||
"//asl/tests:utils",
|
||||
"//asl/testing",
|
||||
],
|
||||
@ -61,4 +80,5 @@ cc_library(
|
||||
"string",
|
||||
"string_view",
|
||||
"string_builder",
|
||||
"parse_number",
|
||||
]]
|
||||
|
162
asl/strings/parse_number.cpp
Normal file
162
asl/strings/parse_number.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright 2025 Steven Le Rouzic
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "asl/strings/parse_number.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
|
||||
bool parse_float_impl(const char** begin, const char* end, float*);
|
||||
bool parse_double_impl(const char** begin, const char* end, double*);
|
||||
|
||||
} // namespace asl
|
||||
|
||||
asl::status_or<asl::parse_number_result<float>> asl::parse_float(asl::string_view sv)
|
||||
{
|
||||
const auto* begin = sv.data();
|
||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||
const auto* end = begin + sv.size();
|
||||
if (float value{}; parse_float_impl(&begin, end, &value))
|
||||
{
|
||||
return parse_number_result<float>{
|
||||
.value = value,
|
||||
.remaining = string_view{begin, end},
|
||||
};
|
||||
}
|
||||
return invalid_argument_error();
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<double>> asl::parse_double(asl::string_view sv)
|
||||
{
|
||||
const auto* begin = sv.data();
|
||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||
const auto* end = begin + sv.size();
|
||||
if (float value{}; parse_float_impl(&begin, end, &value))
|
||||
{
|
||||
return parse_number_result<double>{
|
||||
.value = value,
|
||||
.remaining = string_view{begin, end},
|
||||
};
|
||||
}
|
||||
return invalid_argument_error();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr int8_t kBase16Table[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
};
|
||||
|
||||
// @Todo Maybe monomorph this for common bases (2, 16, 10)?
|
||||
|
||||
template<typename T>
|
||||
asl::status_or<asl::parse_number_result<T>> parse_integer(asl::string_view sv, int base)
|
||||
{
|
||||
ASL_ASSERT(base >= 2 && base <= 16);
|
||||
|
||||
if (sv.is_empty()) { return asl::invalid_argument_error(); }
|
||||
|
||||
T value = 0;
|
||||
bool is_negative = false;
|
||||
|
||||
if (asl::is_signed_integer<T> && sv[0] == '-')
|
||||
{
|
||||
is_negative = true;
|
||||
sv = sv.substr(1);
|
||||
}
|
||||
|
||||
isize_t cursor = 0;
|
||||
while (cursor < sv.size())
|
||||
{
|
||||
// NOLINTNEXTLINE(*-array-index)
|
||||
int8_t digit = kBase16Table[static_cast<uint8_t>(sv[cursor])];
|
||||
if (digit < 0 || digit >= base) { break; }
|
||||
|
||||
if (__builtin_mul_overflow(value, static_cast<T>(base), &value))
|
||||
{
|
||||
return asl::invalid_argument_error("overflow");
|
||||
}
|
||||
|
||||
if (asl::is_signed_integer<T> && is_negative)
|
||||
{
|
||||
digit = static_cast<T>(-digit);
|
||||
}
|
||||
|
||||
if (__builtin_add_overflow(value, static_cast<T>(digit), &value))
|
||||
{
|
||||
return asl::invalid_argument_error("overflow");
|
||||
}
|
||||
|
||||
cursor += 1;
|
||||
}
|
||||
|
||||
if (cursor == 0)
|
||||
{
|
||||
return asl::invalid_argument_error();
|
||||
}
|
||||
|
||||
return asl::parse_number_result<T>{
|
||||
.value = value,
|
||||
.remaining = sv.substr(cursor),
|
||||
};
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
asl::status_or<asl::parse_number_result<uint8_t>> asl::parse_uint8(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<uint8_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<uint16_t>> asl::parse_uint16(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<uint16_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<uint32_t>> asl::parse_uint32(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<uint32_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<uint64_t>> asl::parse_uint64(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<uint64_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<int8_t>> asl::parse_int8(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<int8_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<int16_t>> asl::parse_int16(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<int16_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<int32_t>> asl::parse_int32(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<int32_t>(sv, base);
|
||||
}
|
||||
|
||||
asl::status_or<asl::parse_number_result<int64_t>> asl::parse_int64(string_view sv, int base)
|
||||
{
|
||||
return parse_integer<int64_t>(sv, base);
|
||||
}
|
||||
|
34
asl/strings/parse_number.hpp
Normal file
34
asl/strings/parse_number.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2025 Steven Le Rouzic
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "asl/types/status_or.hpp"
|
||||
#include "asl/strings/string_view.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct parse_number_result
|
||||
{
|
||||
T value;
|
||||
string_view remaining;
|
||||
};
|
||||
|
||||
status_or<parse_number_result<float>> parse_float(string_view);
|
||||
status_or<parse_number_result<double>> parse_double(string_view);
|
||||
|
||||
status_or<parse_number_result<uint8_t>> parse_uint8(string_view, int base = 10);
|
||||
status_or<parse_number_result<uint16_t>> parse_uint16(string_view, int base = 10);
|
||||
status_or<parse_number_result<uint32_t>> parse_uint32(string_view, int base = 10);
|
||||
status_or<parse_number_result<uint64_t>> parse_uint64(string_view, int base = 10);
|
||||
|
||||
status_or<parse_number_result<int8_t>> parse_int8(string_view, int base = 10);
|
||||
status_or<parse_number_result<int16_t>> parse_int16(string_view, int base = 10);
|
||||
status_or<parse_number_result<int32_t>> parse_int32(string_view, int base = 10);
|
||||
status_or<parse_number_result<int64_t>> parse_int64(string_view, int base = 10);
|
||||
|
||||
} // namespace asl
|
||||
|
30
asl/strings/parse_number_float.cpp
Normal file
30
asl/strings/parse_number_float.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2025 Steven Le Rouzic
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include <fast_float.h>
|
||||
|
||||
// We need to isolate fast_float.h completely from asl
|
||||
// because it conflicts with our redefinitions of things
|
||||
// from the STL. In this case it's operator new, but there
|
||||
// might be other conflicts.
|
||||
|
||||
namespace asl
|
||||
{
|
||||
|
||||
extern bool parse_float_impl(const char** begin, const char* end, float* value)
|
||||
{
|
||||
auto res = fast_float::from_chars(*begin, end, *value);
|
||||
*begin = res.ptr;
|
||||
return res.ec == std::errc{};
|
||||
}
|
||||
|
||||
extern bool parse_double_impl(const char** begin, const char* end, double* value)
|
||||
{
|
||||
auto res = fast_float::from_chars(*begin, end, *value);
|
||||
*begin = res.ptr;
|
||||
return res.ec == std::errc{};
|
||||
}
|
||||
|
||||
} // namespace asl
|
||||
|
24
asl/strings/parse_number_integer_table.py
Normal file
24
asl/strings/parse_number_integer_table.py
Normal file
@ -0,0 +1,24 @@
|
||||
a = ord('a')
|
||||
f = ord('f')
|
||||
A = ord('A')
|
||||
F = ord('F')
|
||||
n0 = ord('0')
|
||||
n9 = ord('9')
|
||||
|
||||
output = ""
|
||||
|
||||
for i in range(0, 16):
|
||||
for j in range(0, 16):
|
||||
v = i * 16 + j
|
||||
n = -1
|
||||
if v >= a and v <= f:
|
||||
n = v - a + 10
|
||||
elif v >= A and v <= F:
|
||||
n = v - A + 10
|
||||
elif v >= n0 and v <= n9:
|
||||
n = v - n0
|
||||
output += f"{n:>2}, "
|
||||
output += "\n"
|
||||
|
||||
print(output)
|
||||
|
203
asl/strings/parse_number_tests.cpp
Normal file
203
asl/strings/parse_number_tests.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright 2025 Steven Le Rouzic
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "asl/strings/parse_number.hpp"
|
||||
#include "asl/testing/testing.hpp"
|
||||
|
||||
// @Todo Once we have an equivalent of std::numeric_limits,
|
||||
// properly compare floating point values in these tests.
|
||||
|
||||
ASL_TEST(parse_float_error)
|
||||
{
|
||||
const asl::string_view sv = "this is not a number lmao";
|
||||
auto res = asl::parse_float(sv);
|
||||
ASL_TEST_EXPECT(!res.ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_float_empty)
|
||||
{
|
||||
const asl::string_view sv = "";
|
||||
auto res = asl::parse_float(sv);
|
||||
ASL_TEST_EXPECT(!res.ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_float_simple)
|
||||
{
|
||||
const asl::string_view sv = "3.1415";
|
||||
auto res = asl::parse_float(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 3.1415F);
|
||||
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
|
||||
}
|
||||
|
||||
ASL_TEST(parse_float_integer)
|
||||
{
|
||||
const asl::string_view sv = "31415";
|
||||
auto res = asl::parse_float(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 31415.0F);
|
||||
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
|
||||
}
|
||||
|
||||
ASL_TEST(parse_float_scientific)
|
||||
{
|
||||
const asl::string_view sv = "314.15e-2";
|
||||
auto res = asl::parse_float(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 3.1415F);
|
||||
ASL_TEST_EXPECT(res.value().remaining.size() == 0);
|
||||
}
|
||||
|
||||
ASL_TEST(parse_float_suffix)
|
||||
{
|
||||
const asl::string_view sv = "3.1415 yoyoyo";
|
||||
auto res = asl::parse_float(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 3.1415F);
|
||||
ASL_TEST_EXPECT(res.value().remaining == " yoyoyo");
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int)
|
||||
{
|
||||
const asl::string_view sv = "926473";
|
||||
auto res = asl::parse_uint32(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 926473);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int_negative)
|
||||
{
|
||||
const asl::string_view sv = "-926473";
|
||||
auto res = asl::parse_int32(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == -926473);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int_suffix)
|
||||
{
|
||||
const asl::string_view sv = "926473 what's this then";
|
||||
auto res = asl::parse_uint32(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 926473);
|
||||
ASL_TEST_EXPECT(res.value().remaining == " what's this then");
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint_with_minus)
|
||||
{
|
||||
const asl::string_view sv = "-926473";
|
||||
auto res = asl::parse_uint32(sv);
|
||||
ASL_TEST_EXPECT(!res.ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int_with_only_minus)
|
||||
{
|
||||
const asl::string_view sv = "-@";
|
||||
auto res = asl::parse_int32(sv);
|
||||
ASL_TEST_EXPECT(!res.ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint_invalid)
|
||||
{
|
||||
const asl::string_view sv = "abcd";
|
||||
auto res = asl::parse_uint32(sv);
|
||||
ASL_TEST_EXPECT(!res.ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint_empty)
|
||||
{
|
||||
const asl::string_view sv = "";
|
||||
auto res = asl::parse_uint32(sv);
|
||||
ASL_TEST_EXPECT(!res.ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint_overflow)
|
||||
{
|
||||
ASL_TEST_EXPECT(!asl::parse_uint16("80000").ok());
|
||||
ASL_TEST_EXPECT(!asl::parse_uint16("65536").ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint16_max)
|
||||
{
|
||||
const asl::string_view sv = "65535";
|
||||
auto res = asl::parse_uint16(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 65535);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint16_zero)
|
||||
{
|
||||
const asl::string_view sv = "0";
|
||||
auto res = asl::parse_uint16(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 0);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_uint16_zeros)
|
||||
{
|
||||
const asl::string_view sv = "00000";
|
||||
auto res = asl::parse_uint16(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 0);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int_overflow)
|
||||
{
|
||||
ASL_TEST_EXPECT(!asl::parse_int16("80000").ok());
|
||||
ASL_TEST_EXPECT(!asl::parse_int16("40000").ok());
|
||||
ASL_TEST_EXPECT(!asl::parse_int16("32768").ok());
|
||||
ASL_TEST_EXPECT(!asl::parse_int16("-80000").ok());
|
||||
ASL_TEST_EXPECT(!asl::parse_int16("-40000").ok());
|
||||
ASL_TEST_EXPECT(!asl::parse_int16("-32769").ok());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int16_max)
|
||||
{
|
||||
const asl::string_view sv = "32767";
|
||||
auto res = asl::parse_int16(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 32767);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_int16_min)
|
||||
{
|
||||
const asl::string_view sv = "-32768";
|
||||
auto res = asl::parse_int16(sv);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == -32768);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_hex)
|
||||
{
|
||||
const asl::string_view sv = "1000a";
|
||||
auto res = asl::parse_uint32(sv, 16);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 65546);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_bin)
|
||||
{
|
||||
const asl::string_view sv = "101010";
|
||||
auto res = asl::parse_uint32(sv, 2);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 42);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
||||
ASL_TEST(parse_oct)
|
||||
{
|
||||
const asl::string_view sv = "644";
|
||||
auto res = asl::parse_uint32(sv, 8);
|
||||
ASL_TEST_EXPECT(res.ok());
|
||||
ASL_TEST_EXPECT(res.value().value == 6 * 64 + 4 * 8 + 4);
|
||||
ASL_TEST_EXPECT(res.value().remaining.is_empty());
|
||||
}
|
||||
|
@ -28,6 +28,13 @@ public:
|
||||
, m_size{size}
|
||||
{}
|
||||
|
||||
constexpr string_view(const char* begin, const char* end)
|
||||
: m_data{begin}
|
||||
, m_size{end - begin}
|
||||
{
|
||||
ASL_ASSERT(begin <= end);
|
||||
}
|
||||
|
||||
template<isize_t kSize>
|
||||
constexpr string_view(const char (&str)[kSize]) // NOLINT(*explicit*)
|
||||
requires (kSize >= 1)
|
||||
|
2
vendor/dragonbox/BUILD.bazel
vendored
2
vendor/dragonbox/BUILD.bazel
vendored
@ -18,7 +18,7 @@ cc_library(
|
||||
name = "dragonbox",
|
||||
hdrs = ["dragonbox.h"],
|
||||
includes = ["."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
visibility = ["//asl:__subpackages__"],
|
||||
applicable_licenses = [
|
||||
":license",
|
||||
],
|
||||
|
25
vendor/fast_float/BUILD.bazel
vendored
Normal file
25
vendor/fast_float/BUILD.bazel
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright 2025 Steven Le Rouzic
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
load("@rules_license//rules:license.bzl", "license")
|
||||
|
||||
license(
|
||||
name = "license",
|
||||
license_kinds = [
|
||||
"@rules_license//licenses/spdx:MIT",
|
||||
],
|
||||
license_text = "LICENSE.txt",
|
||||
package_name = "fast_float",
|
||||
package_url = "https://github.com/fastfloat/fast_float",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "fast_float",
|
||||
hdrs = ["fast_float.h"],
|
||||
includes = ["."],
|
||||
visibility = ["//asl:__subpackages__"],
|
||||
applicable_licenses = [
|
||||
":license",
|
||||
],
|
||||
)
|
27
vendor/fast_float/LICENSE.txt
vendored
Normal file
27
vendor/fast_float/LICENSE.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 The fast_float authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
4443
vendor/fast_float/fast_float.h
vendored
Normal file
4443
vendor/fast_float/fast_float.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user