git repos / blockattack-game

blame: source/misc/embedded_libs/fmt-8.1.1/test/scan.h

normal view · raw

f8deb5b9 Poul Sander 2022-01-15 13:55 1
// Formatting library for C++ - scanning API proof of concept
f8deb5b9 Poul Sander 2022-01-15 13:55 2
//
f8deb5b9 Poul Sander 2022-01-15 13:55 3
// Copyright (c) 2019 - present, Victor Zverovich
f8deb5b9 Poul Sander 2022-01-15 13:55 4
// All rights reserved.
f8deb5b9 Poul Sander 2022-01-15 13:55 5
//
f8deb5b9 Poul Sander 2022-01-15 13:55 6
// For the license information refer to format.h.
f8deb5b9 Poul Sander 2022-01-15 13:55 7
f8deb5b9 Poul Sander 2022-01-15 13:55 8
#include <array>
f8deb5b9 Poul Sander 2022-01-15 13:55 9
#include <cassert>
f8deb5b9 Poul Sander 2022-01-15 13:55 10
#include <climits>
f8deb5b9 Poul Sander 2022-01-15 13:55 11
f8deb5b9 Poul Sander 2022-01-15 13:55 12
#include "fmt/format.h"
f8deb5b9 Poul Sander 2022-01-15 13:55 13
f8deb5b9 Poul Sander 2022-01-15 13:55 14
FMT_BEGIN_NAMESPACE
f8deb5b9 Poul Sander 2022-01-15 13:55 15
template <typename T, typename Char = char> struct scanner {
f8deb5b9 Poul Sander 2022-01-15 13:55 16
  // A deleted default constructor indicates a disabled scanner.
f8deb5b9 Poul Sander 2022-01-15 13:55 17
  scanner() = delete;
f8deb5b9 Poul Sander 2022-01-15 13:55 18
};
f8deb5b9 Poul Sander 2022-01-15 13:55 19
f8deb5b9 Poul Sander 2022-01-15 13:55 20
class scan_parse_context {
f8deb5b9 Poul Sander 2022-01-15 13:55 21
 private:
f8deb5b9 Poul Sander 2022-01-15 13:55 22
  string_view format_;
f8deb5b9 Poul Sander 2022-01-15 13:55 23
f8deb5b9 Poul Sander 2022-01-15 13:55 24
 public:
f8deb5b9 Poul Sander 2022-01-15 13:55 25
  using iterator = string_view::iterator;
f8deb5b9 Poul Sander 2022-01-15 13:55 26
f8deb5b9 Poul Sander 2022-01-15 13:55 27
  explicit FMT_CONSTEXPR scan_parse_context(string_view format)
f8deb5b9 Poul Sander 2022-01-15 13:55 28
      : format_(format) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 29
f8deb5b9 Poul Sander 2022-01-15 13:55 30
  FMT_CONSTEXPR iterator begin() const { return format_.begin(); }
f8deb5b9 Poul Sander 2022-01-15 13:55 31
  FMT_CONSTEXPR iterator end() const { return format_.end(); }
f8deb5b9 Poul Sander 2022-01-15 13:55 32
f8deb5b9 Poul Sander 2022-01-15 13:55 33
  void advance_to(iterator it) {
f8deb5b9 Poul Sander 2022-01-15 13:55 34
    format_.remove_prefix(detail::to_unsigned(it - begin()));
f8deb5b9 Poul Sander 2022-01-15 13:55 35
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 36
};
f8deb5b9 Poul Sander 2022-01-15 13:55 37
f8deb5b9 Poul Sander 2022-01-15 13:55 38
struct scan_context {
f8deb5b9 Poul Sander 2022-01-15 13:55 39
 private:
f8deb5b9 Poul Sander 2022-01-15 13:55 40
  string_view input_;
f8deb5b9 Poul Sander 2022-01-15 13:55 41
f8deb5b9 Poul Sander 2022-01-15 13:55 42
 public:
f8deb5b9 Poul Sander 2022-01-15 13:55 43
  using iterator = const char*;
f8deb5b9 Poul Sander 2022-01-15 13:55 44
f8deb5b9 Poul Sander 2022-01-15 13:55 45
  explicit scan_context(string_view input) : input_(input) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 46
f8deb5b9 Poul Sander 2022-01-15 13:55 47
  iterator begin() const { return input_.data(); }
f8deb5b9 Poul Sander 2022-01-15 13:55 48
  iterator end() const { return begin() + input_.size(); }
f8deb5b9 Poul Sander 2022-01-15 13:55 49
f8deb5b9 Poul Sander 2022-01-15 13:55 50
  void advance_to(iterator it) {
f8deb5b9 Poul Sander 2022-01-15 13:55 51
    input_.remove_prefix(detail::to_unsigned(it - begin()));
f8deb5b9 Poul Sander 2022-01-15 13:55 52
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 53
};
f8deb5b9 Poul Sander 2022-01-15 13:55 54
f8deb5b9 Poul Sander 2022-01-15 13:55 55
namespace detail {
f8deb5b9 Poul Sander 2022-01-15 13:55 56
enum class scan_type {
f8deb5b9 Poul Sander 2022-01-15 13:55 57
  none_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 58
  int_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 59
  uint_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 60
  long_long_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 61
  ulong_long_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 62
  string_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 63
  string_view_type,
f8deb5b9 Poul Sander 2022-01-15 13:55 64
  custom_type
f8deb5b9 Poul Sander 2022-01-15 13:55 65
};
f8deb5b9 Poul Sander 2022-01-15 13:55 66
f8deb5b9 Poul Sander 2022-01-15 13:55 67
struct custom_scan_arg {
f8deb5b9 Poul Sander 2022-01-15 13:55 68
  void* value;
f8deb5b9 Poul Sander 2022-01-15 13:55 69
  void (*scan)(void* arg, scan_parse_context& parse_ctx, scan_context& ctx);
f8deb5b9 Poul Sander 2022-01-15 13:55 70
};
f8deb5b9 Poul Sander 2022-01-15 13:55 71
f8deb5b9 Poul Sander 2022-01-15 13:55 72
class scan_arg {
f8deb5b9 Poul Sander 2022-01-15 13:55 73
 public:
f8deb5b9 Poul Sander 2022-01-15 13:55 74
  scan_type type;
f8deb5b9 Poul Sander 2022-01-15 13:55 75
  union {
f8deb5b9 Poul Sander 2022-01-15 13:55 76
    int* int_value;
f8deb5b9 Poul Sander 2022-01-15 13:55 77
    unsigned* uint_value;
f8deb5b9 Poul Sander 2022-01-15 13:55 78
    long long* long_long_value;
f8deb5b9 Poul Sander 2022-01-15 13:55 79
    unsigned long long* ulong_long_value;
f8deb5b9 Poul Sander 2022-01-15 13:55 80
    std::string* string;
f8deb5b9 Poul Sander 2022-01-15 13:55 81
    fmt::string_view* string_view;
f8deb5b9 Poul Sander 2022-01-15 13:55 82
    custom_scan_arg custom;
f8deb5b9 Poul Sander 2022-01-15 13:55 83
    // TODO: more types
f8deb5b9 Poul Sander 2022-01-15 13:55 84
  };
f8deb5b9 Poul Sander 2022-01-15 13:55 85
f8deb5b9 Poul Sander 2022-01-15 13:55 86
  scan_arg() : type(scan_type::none_type) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 87
  scan_arg(int& value) : type(scan_type::int_type), int_value(&value) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 88
  scan_arg(unsigned& value) : type(scan_type::uint_type), uint_value(&value) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 89
  scan_arg(long long& value)
f8deb5b9 Poul Sander 2022-01-15 13:55 90
      : type(scan_type::long_long_type), long_long_value(&value) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 91
  scan_arg(unsigned long long& value)
f8deb5b9 Poul Sander 2022-01-15 13:55 92
      : type(scan_type::ulong_long_type), ulong_long_value(&value) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 93
  scan_arg(std::string& value) : type(scan_type::string_type), string(&value) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 94
  scan_arg(fmt::string_view& value)
f8deb5b9 Poul Sander 2022-01-15 13:55 95
      : type(scan_type::string_view_type), string_view(&value) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 96
  template <typename T> scan_arg(T& value) : type(scan_type::custom_type) {
f8deb5b9 Poul Sander 2022-01-15 13:55 97
    custom.value = &value;
f8deb5b9 Poul Sander 2022-01-15 13:55 98
    custom.scan = scan_custom_arg<T>;
f8deb5b9 Poul Sander 2022-01-15 13:55 99
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 100
f8deb5b9 Poul Sander 2022-01-15 13:55 101
 private:
f8deb5b9 Poul Sander 2022-01-15 13:55 102
  template <typename T>
f8deb5b9 Poul Sander 2022-01-15 13:55 103
  static void scan_custom_arg(void* arg, scan_parse_context& parse_ctx,
f8deb5b9 Poul Sander 2022-01-15 13:55 104
                              scan_context& ctx) {
f8deb5b9 Poul Sander 2022-01-15 13:55 105
    scanner<T> s;
f8deb5b9 Poul Sander 2022-01-15 13:55 106
    parse_ctx.advance_to(s.parse(parse_ctx));
f8deb5b9 Poul Sander 2022-01-15 13:55 107
    ctx.advance_to(s.scan(*static_cast<T*>(arg), ctx));
f8deb5b9 Poul Sander 2022-01-15 13:55 108
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 109
};
f8deb5b9 Poul Sander 2022-01-15 13:55 110
}  // namespace detail
f8deb5b9 Poul Sander 2022-01-15 13:55 111
f8deb5b9 Poul Sander 2022-01-15 13:55 112
struct scan_args {
f8deb5b9 Poul Sander 2022-01-15 13:55 113
  int size;
f8deb5b9 Poul Sander 2022-01-15 13:55 114
  const detail::scan_arg* data;
f8deb5b9 Poul Sander 2022-01-15 13:55 115
f8deb5b9 Poul Sander 2022-01-15 13:55 116
  template <size_t N>
f8deb5b9 Poul Sander 2022-01-15 13:55 117
  scan_args(const std::array<detail::scan_arg, N>& store)
f8deb5b9 Poul Sander 2022-01-15 13:55 118
      : size(N), data(store.data()) {
f8deb5b9 Poul Sander 2022-01-15 13:55 119
    static_assert(N < INT_MAX, "too many arguments");
f8deb5b9 Poul Sander 2022-01-15 13:55 120
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 121
};
f8deb5b9 Poul Sander 2022-01-15 13:55 122
f8deb5b9 Poul Sander 2022-01-15 13:55 123
namespace detail {
f8deb5b9 Poul Sander 2022-01-15 13:55 124
f8deb5b9 Poul Sander 2022-01-15 13:55 125
struct scan_handler : error_handler {
f8deb5b9 Poul Sander 2022-01-15 13:55 126
 private:
f8deb5b9 Poul Sander 2022-01-15 13:55 127
  scan_parse_context parse_ctx_;
f8deb5b9 Poul Sander 2022-01-15 13:55 128
  scan_context scan_ctx_;
f8deb5b9 Poul Sander 2022-01-15 13:55 129
  scan_args args_;
f8deb5b9 Poul Sander 2022-01-15 13:55 130
  int next_arg_id_;
f8deb5b9 Poul Sander 2022-01-15 13:55 131
  scan_arg arg_;
f8deb5b9 Poul Sander 2022-01-15 13:55 132
f8deb5b9 Poul Sander 2022-01-15 13:55 133
  template <typename T = unsigned> T read_uint() {
f8deb5b9 Poul Sander 2022-01-15 13:55 134
    T value = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 135
    auto it = scan_ctx_.begin(), end = scan_ctx_.end();
f8deb5b9 Poul Sander 2022-01-15 13:55 136
    while (it != end) {
f8deb5b9 Poul Sander 2022-01-15 13:55 137
      char c = *it++;
f8deb5b9 Poul Sander 2022-01-15 13:55 138
      if (c < '0' || c > '9') on_error("invalid input");
f8deb5b9 Poul Sander 2022-01-15 13:55 139
      // TODO: check overflow
f8deb5b9 Poul Sander 2022-01-15 13:55 140
      value = value * 10 + static_cast<unsigned>(c - '0');
f8deb5b9 Poul Sander 2022-01-15 13:55 141
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 142
    scan_ctx_.advance_to(it);
f8deb5b9 Poul Sander 2022-01-15 13:55 143
    return value;
f8deb5b9 Poul Sander 2022-01-15 13:55 144
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 145
f8deb5b9 Poul Sander 2022-01-15 13:55 146
  template <typename T = int> T read_int() {
f8deb5b9 Poul Sander 2022-01-15 13:55 147
    auto it = scan_ctx_.begin(), end = scan_ctx_.end();
f8deb5b9 Poul Sander 2022-01-15 13:55 148
    bool negative = it != end && *it == '-';
f8deb5b9 Poul Sander 2022-01-15 13:55 149
    if (negative) ++it;
f8deb5b9 Poul Sander 2022-01-15 13:55 150
    scan_ctx_.advance_to(it);
f8deb5b9 Poul Sander 2022-01-15 13:55 151
    const auto value = read_uint<typename std::make_unsigned<T>::type>();
f8deb5b9 Poul Sander 2022-01-15 13:55 152
    if (negative) return -static_cast<T>(value);
f8deb5b9 Poul Sander 2022-01-15 13:55 153
    return static_cast<T>(value);
f8deb5b9 Poul Sander 2022-01-15 13:55 154
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 155
f8deb5b9 Poul Sander 2022-01-15 13:55 156
 public:
f8deb5b9 Poul Sander 2022-01-15 13:55 157
  scan_handler(string_view format, string_view input, scan_args args)
f8deb5b9 Poul Sander 2022-01-15 13:55 158
      : parse_ctx_(format), scan_ctx_(input), args_(args), next_arg_id_(0) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 159
f8deb5b9 Poul Sander 2022-01-15 13:55 160
  const char* pos() const { return scan_ctx_.begin(); }
f8deb5b9 Poul Sander 2022-01-15 13:55 161
f8deb5b9 Poul Sander 2022-01-15 13:55 162
  void on_text(const char* begin, const char* end) {
f8deb5b9 Poul Sander 2022-01-15 13:55 163
    auto size = to_unsigned(end - begin);
f8deb5b9 Poul Sander 2022-01-15 13:55 164
    auto it = scan_ctx_.begin();
f8deb5b9 Poul Sander 2022-01-15 13:55 165
    if (it + size > scan_ctx_.end() ||
f8deb5b9 Poul Sander 2022-01-15 13:55 166
        !std::equal(begin, end, make_checked(it, size))) {
f8deb5b9 Poul Sander 2022-01-15 13:55 167
      on_error("invalid input");
f8deb5b9 Poul Sander 2022-01-15 13:55 168
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 169
    scan_ctx_.advance_to(it + size);
f8deb5b9 Poul Sander 2022-01-15 13:55 170
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 171
f8deb5b9 Poul Sander 2022-01-15 13:55 172
  FMT_CONSTEXPR int on_arg_id() { return on_arg_id(next_arg_id_++); }
f8deb5b9 Poul Sander 2022-01-15 13:55 173
  FMT_CONSTEXPR int on_arg_id(int id) {
f8deb5b9 Poul Sander 2022-01-15 13:55 174
    if (id >= args_.size) on_error("argument index out of range");
f8deb5b9 Poul Sander 2022-01-15 13:55 175
    arg_ = args_.data[id];
f8deb5b9 Poul Sander 2022-01-15 13:55 176
    return id;
f8deb5b9 Poul Sander 2022-01-15 13:55 177
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 178
  FMT_CONSTEXPR int on_arg_id(string_view id) {
f8deb5b9 Poul Sander 2022-01-15 13:55 179
    if (id.data()) on_error("invalid format");
f8deb5b9 Poul Sander 2022-01-15 13:55 180
    return 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 181
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 182
f8deb5b9 Poul Sander 2022-01-15 13:55 183
  void on_replacement_field(int, const char*) {
f8deb5b9 Poul Sander 2022-01-15 13:55 184
    auto it = scan_ctx_.begin(), end = scan_ctx_.end();
f8deb5b9 Poul Sander 2022-01-15 13:55 185
    switch (arg_.type) {
f8deb5b9 Poul Sander 2022-01-15 13:55 186
    case scan_type::int_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 187
      *arg_.int_value = read_int();
f8deb5b9 Poul Sander 2022-01-15 13:55 188
      break;
f8deb5b9 Poul Sander 2022-01-15 13:55 189
    case scan_type::uint_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 190
      *arg_.uint_value = read_uint();
f8deb5b9 Poul Sander 2022-01-15 13:55 191
      break;
f8deb5b9 Poul Sander 2022-01-15 13:55 192
    case scan_type::long_long_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 193
      *arg_.long_long_value = read_int<long long>();
f8deb5b9 Poul Sander 2022-01-15 13:55 194
      break;
f8deb5b9 Poul Sander 2022-01-15 13:55 195
    case scan_type::ulong_long_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 196
      *arg_.ulong_long_value = read_uint<unsigned long long>();
f8deb5b9 Poul Sander 2022-01-15 13:55 197
      break;
f8deb5b9 Poul Sander 2022-01-15 13:55 198
    case scan_type::string_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 199
      while (it != end && *it != ' ') arg_.string->push_back(*it++);
f8deb5b9 Poul Sander 2022-01-15 13:55 200
      scan_ctx_.advance_to(it);
f8deb5b9 Poul Sander 2022-01-15 13:55 201
      break;
f8deb5b9 Poul Sander 2022-01-15 13:55 202
    case scan_type::string_view_type: {
f8deb5b9 Poul Sander 2022-01-15 13:55 203
      auto s = it;
f8deb5b9 Poul Sander 2022-01-15 13:55 204
      while (it != end && *it != ' ') ++it;
f8deb5b9 Poul Sander 2022-01-15 13:55 205
      *arg_.string_view = fmt::string_view(s, to_unsigned(it - s));
f8deb5b9 Poul Sander 2022-01-15 13:55 206
      scan_ctx_.advance_to(it);
f8deb5b9 Poul Sander 2022-01-15 13:55 207
      break;
f8deb5b9 Poul Sander 2022-01-15 13:55 208
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 209
    case scan_type::none_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 210
    case scan_type::custom_type:
f8deb5b9 Poul Sander 2022-01-15 13:55 211
      assert(false);
f8deb5b9 Poul Sander 2022-01-15 13:55 212
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 213
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 214
f8deb5b9 Poul Sander 2022-01-15 13:55 215
  const char* on_format_specs(int, const char* begin, const char*) {
f8deb5b9 Poul Sander 2022-01-15 13:55 216
    if (arg_.type != scan_type::custom_type) return begin;
f8deb5b9 Poul Sander 2022-01-15 13:55 217
    parse_ctx_.advance_to(begin);
f8deb5b9 Poul Sander 2022-01-15 13:55 218
    arg_.custom.scan(arg_.custom.value, parse_ctx_, scan_ctx_);
f8deb5b9 Poul Sander 2022-01-15 13:55 219
    return parse_ctx_.begin();
f8deb5b9 Poul Sander 2022-01-15 13:55 220
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 221
};
f8deb5b9 Poul Sander 2022-01-15 13:55 222
}  // namespace detail
f8deb5b9 Poul Sander 2022-01-15 13:55 223
f8deb5b9 Poul Sander 2022-01-15 13:55 224
template <typename... Args>
f8deb5b9 Poul Sander 2022-01-15 13:55 225
std::array<detail::scan_arg, sizeof...(Args)> make_scan_args(Args&... args) {
f8deb5b9 Poul Sander 2022-01-15 13:55 226
  return {{args...}};
f8deb5b9 Poul Sander 2022-01-15 13:55 227
}
f8deb5b9 Poul Sander 2022-01-15 13:55 228
f8deb5b9 Poul Sander 2022-01-15 13:55 229
string_view::iterator vscan(string_view input, string_view format_str,
f8deb5b9 Poul Sander 2022-01-15 13:55 230
                            scan_args args) {
f8deb5b9 Poul Sander 2022-01-15 13:55 231
  detail::scan_handler h(format_str, input, args);
f8deb5b9 Poul Sander 2022-01-15 13:55 232
  detail::parse_format_string<false>(format_str, h);
f8deb5b9 Poul Sander 2022-01-15 13:55 233
  return input.begin() + (h.pos() - &*input.begin());
f8deb5b9 Poul Sander 2022-01-15 13:55 234
}
f8deb5b9 Poul Sander 2022-01-15 13:55 235
f8deb5b9 Poul Sander 2022-01-15 13:55 236
template <typename... Args>
f8deb5b9 Poul Sander 2022-01-15 13:55 237
string_view::iterator scan(string_view input, string_view format_str,
f8deb5b9 Poul Sander 2022-01-15 13:55 238
                           Args&... args) {
f8deb5b9 Poul Sander 2022-01-15 13:55 239
  return vscan(input, format_str, make_scan_args(args...));
f8deb5b9 Poul Sander 2022-01-15 13:55 240
}
f8deb5b9 Poul Sander 2022-01-15 13:55 241
FMT_END_NAMESPACE
1970-01-01 00:00 242