Move the value reading helpers out of Opcode

This commit is contained in:
Jean Pierre Cimalando 2021-03-21 12:33:18 +01:00
parent 21ab7e471d
commit c610b1d62d
2 changed files with 102 additions and 32 deletions

View file

@ -147,21 +147,20 @@ absl::optional<T> readInt_(OpcodeSpec<T> spec, absl::string_view v)
{
using Limits = std::numeric_limits<T>;
size_t numberEnd = 0;
if (numberEnd < v.size() && (v[numberEnd] == '+' || v[numberEnd] == '-'))
++numberEnd;
while (numberEnd < v.size() && absl::ascii_isdigit(v[numberEnd]))
++numberEnd;
if (numberEnd == 0 && (spec.flags & kCanBeNote))
return readNoteValue(v);
v = v.substr(0, numberEnd);
int64_t returnedValue;
if (!absl::SimpleAtoi(v, &returnedValue))
bool readValueSuccess = false;
if (readLeadingInt(v, &returnedValue))
readValueSuccess = true;
if (!readValueSuccess && (spec.flags & kCanBeNote)) {
if (absl::optional<uint8_t> noteValue = readNoteValue(v)) {
returnedValue = *noteValue;
readValueSuccess = true;
}
}
if (!readValueSuccess)
return absl::nullopt;
if (returnedValue > static_cast<int64_t>(spec.bounds.getEnd())) {
@ -201,23 +200,8 @@ INSTANTIATE_FOR_INTEGRAL(int64_t)
template <typename T>
absl::optional<T> readFloat_(OpcodeSpec<T> spec, absl::string_view v)
{
size_t numberEnd = 0;
if (numberEnd < v.size() && (v[numberEnd] == '+' || v[numberEnd] == '-'))
++numberEnd;
while (numberEnd < v.size() && absl::ascii_isdigit(v[numberEnd]))
++numberEnd;
if (numberEnd < v.size() && v[numberEnd] == '.') {
++numberEnd;
while (numberEnd < v.size() && absl::ascii_isdigit(v[numberEnd]))
++numberEnd;
}
v = v.substr(0, numberEnd);
float returnedValue;
if (!absl::SimpleAtof(v, &returnedValue))
T returnedValue;
if (!readLeadingFloat(v, &returnedValue))
return absl::nullopt;
if (spec.flags & kWrapPhase)

View file

@ -11,7 +11,9 @@
*/
#pragma once
#include "absl/strings/string_view.h"
#include <absl/strings/ascii.h>
#include <absl/strings/numbers.h>
#include <absl/strings/string_view.h>
#include <cstdint>
/**
@ -101,3 +103,87 @@ uint64_t hashNumber(Int i, uint64_t h = Fnv1aBasis)
"The hashed object must be of arithmetic type");
return hash(absl::string_view(reinterpret_cast<const char*>(&i), sizeof(i)), h);
}
/**
* @brief Read a floating-point number from a string non-permissively
*
* @param[in] input a string to read from
* @param[out] result address of the value where the result is stored
* @return whether the conversion is successful
*/
template <class F>
bool readFloat(absl::string_view input, F* result);
template <>
inline bool readFloat<float>(absl::string_view input, float* result)
{
return absl::SimpleAtof(input, result);
}
template <>
inline bool readFloat<double>(absl::string_view input, double* result)
{
return absl::SimpleAtod(input, result);
}
/**
* @brief Read an integer from a string, permitting extra trailing characters.
*
* @param[in] input a string to read from
* @param[out] result address of the value where the result is stored
* @param[out] rest optional address which receives the unprocessed tail of the input
* @return whether the conversion is successful
*/
template <class I>
bool readLeadingInt(absl::string_view input, I* result, absl::string_view* rest = nullptr)
{
size_t numberEnd = 0;
if (numberEnd < input.size() && (input[numberEnd] == '+' || input[numberEnd] == '-'))
++numberEnd;
while (numberEnd < input.size() && absl::ascii_isdigit(input[numberEnd]))
++numberEnd;
if (!absl::SimpleAtoi(input.substr(0, numberEnd), result))
return false;
if (rest)
*rest = input.substr(numberEnd);
return true;
}
/**
* @brief Read a floating-point number from a string, permitting extra
* trailing characters.
*
* @param[in] input a string to read from
* @param[out] result address of the value where the result is stored
* @param[out] rest optional address which receives the unprocessed tail of the input
* @return whether the conversion is successful
*/
template <class F>
bool readLeadingFloat(absl::string_view input, F* result, absl::string_view* rest = nullptr)
{
size_t numberEnd = 0;
if (numberEnd < input.size() && (input[numberEnd] == '+' || input[numberEnd] == '-'))
++numberEnd;
while (numberEnd < input.size() && absl::ascii_isdigit(input[numberEnd]))
++numberEnd;
if (numberEnd < input.size() && input[numberEnd] == '.') {
++numberEnd;
while (numberEnd < input.size() && absl::ascii_isdigit(input[numberEnd]))
++numberEnd;
}
if (!readFloat(input.substr(0, numberEnd), result))
return false;
if (rest)
*rest = input.substr(numberEnd);
return true;
}