Move the value reading helpers out of Opcode
This commit is contained in:
parent
21ab7e471d
commit
c610b1d62d
2 changed files with 102 additions and 32 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue