64 lines
2.5 KiB
C++
64 lines
2.5 KiB
C++
// mars::text -- lazily typed tokens for the flat tuning tables.
|
|
//
|
|
// A token is the raw bytes of one whitespace-delimited item (or the inside of
|
|
// a "quoted string"). Nothing is converted at parse time; kind() classifies a
|
|
// bareword the way the game data reads it (int / float / true|false / word)
|
|
// and the as_*() accessors convert on demand. Quoted tokens are always
|
|
// strings, even when they look numeric ("8" stays "8").
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace mars::text {
|
|
|
|
enum class ValueKind {
|
|
Int, // [+-]?digits
|
|
Float, // [+-]?(d+.d* | .d+ | d+)([eE][+-]?d+)? (and not Int)
|
|
Bool, // true / false, any case
|
|
Bareword, // any other unquoted token
|
|
String // a "quoted" token
|
|
};
|
|
|
|
// Classification of an unquoted token.
|
|
ValueKind classify(std::string_view bareword);
|
|
bool looks_like_int(std::string_view s);
|
|
bool looks_like_float(std::string_view s);
|
|
|
|
// Conversions; nullopt when the text does not have the requested shape
|
|
// (or, for parse_int, does not fit in 64 bits).
|
|
std::optional<std::int64_t> parse_int(std::string_view s);
|
|
std::optional<double> parse_float(std::string_view s); // accepts Int or Float shapes
|
|
std::optional<bool> parse_bool(std::string_view s);
|
|
|
|
struct Token {
|
|
std::string text;
|
|
bool quoted = false;
|
|
|
|
ValueKind kind() const { return quoted ? ValueKind::String : classify(text); }
|
|
std::optional<std::int64_t> as_int() const { return quoted ? std::nullopt : parse_int(text); }
|
|
std::optional<double> as_float() const { return quoted ? std::nullopt : parse_float(text); }
|
|
std::optional<bool> as_bool() const { return quoted ? std::nullopt : parse_bool(text); }
|
|
};
|
|
|
|
// A colour written as "r g b" or "r g b a" (any numeric components; the data
|
|
// uses 0-255 ints). a defaults to 1 when absent. `components` is 3 or 4.
|
|
struct Color {
|
|
double r = 0, g = 0, b = 0, a = 1;
|
|
int components = 0;
|
|
};
|
|
std::optional<Color> parse_color(std::string_view s);
|
|
|
|
// ASCII helpers shared by the readers (the data is cp1252; high bytes are
|
|
// never whitespace and never case-folded).
|
|
inline bool is_space(char c) {
|
|
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f';
|
|
}
|
|
std::string_view strip(std::string_view s);
|
|
std::string_view lstrip(std::string_view s);
|
|
std::string fold_case(std::string_view s); // ASCII lower-case copy
|
|
bool equals_fold(std::string_view a, std::string_view b); // ASCII case-insensitive
|
|
|
|
} // namespace mars::text
|