诸暨麻将添加redis
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

467 linhas
15 KiB

  1. // Formatting library for C++ - experimental format string compilation
  2. //
  3. // Copyright (c) 2012 - present, Victor Zverovich and fmt contributors
  4. // All rights reserved.
  5. //
  6. // For the license information refer to format.h.
  7. #ifndef FMT_COMPILE_H_
  8. #define FMT_COMPILE_H_
  9. #include <vector>
  10. #include "format.h"
  11. FMT_BEGIN_NAMESPACE
  12. namespace internal {
  13. template <typename Char> struct format_part {
  14. public:
  15. struct named_argument_id {
  16. FMT_CONSTEXPR named_argument_id(internal::string_view_metadata id)
  17. : id(id) {}
  18. internal::string_view_metadata id;
  19. };
  20. struct argument_id {
  21. FMT_CONSTEXPR argument_id() : argument_id(0u) {}
  22. FMT_CONSTEXPR argument_id(unsigned id)
  23. : which(which_arg_id::index), val(id) {}
  24. FMT_CONSTEXPR argument_id(internal::string_view_metadata id)
  25. : which(which_arg_id::named_index), val(id) {}
  26. enum class which_arg_id { index, named_index };
  27. which_arg_id which;
  28. union value {
  29. FMT_CONSTEXPR value() : index(0u) {}
  30. FMT_CONSTEXPR value(unsigned id) : index(id) {}
  31. FMT_CONSTEXPR value(internal::string_view_metadata id)
  32. : named_index(id) {}
  33. unsigned index;
  34. internal::string_view_metadata named_index;
  35. } val;
  36. };
  37. struct specification {
  38. FMT_CONSTEXPR specification() : arg_id(0u) {}
  39. FMT_CONSTEXPR specification(unsigned id) : arg_id(id) {}
  40. FMT_CONSTEXPR specification(internal::string_view_metadata id)
  41. : arg_id(id) {}
  42. argument_id arg_id;
  43. internal::dynamic_format_specs<Char> parsed_specs;
  44. };
  45. FMT_CONSTEXPR format_part()
  46. : which(kind::argument_id), end_of_argument_id(0u), val(0u) {}
  47. FMT_CONSTEXPR format_part(internal::string_view_metadata text)
  48. : which(kind::text), end_of_argument_id(0u), val(text) {}
  49. FMT_CONSTEXPR format_part(unsigned id)
  50. : which(kind::argument_id), end_of_argument_id(0u), val(id) {}
  51. FMT_CONSTEXPR format_part(named_argument_id arg_id)
  52. : which(kind::named_argument_id), end_of_argument_id(0u), val(arg_id) {}
  53. FMT_CONSTEXPR format_part(specification spec)
  54. : which(kind::specification), end_of_argument_id(0u), val(spec) {}
  55. enum class kind { argument_id, named_argument_id, text, specification };
  56. kind which;
  57. std::size_t end_of_argument_id;
  58. union value {
  59. FMT_CONSTEXPR value() : arg_id(0u) {}
  60. FMT_CONSTEXPR value(unsigned id) : arg_id(id) {}
  61. FMT_CONSTEXPR value(named_argument_id named_id)
  62. : named_arg_id(named_id.id) {}
  63. FMT_CONSTEXPR value(internal::string_view_metadata t) : text(t) {}
  64. FMT_CONSTEXPR value(specification s) : spec(s) {}
  65. unsigned arg_id;
  66. internal::string_view_metadata named_arg_id;
  67. internal::string_view_metadata text;
  68. specification spec;
  69. } val;
  70. };
  71. template <typename Char, typename PartsContainer>
  72. class format_preparation_handler : public internal::error_handler {
  73. private:
  74. using part = format_part<Char>;
  75. public:
  76. using iterator = typename basic_string_view<Char>::iterator;
  77. FMT_CONSTEXPR format_preparation_handler(basic_string_view<Char> format,
  78. PartsContainer& parts)
  79. : parts_(parts), format_(format), parse_context_(format) {}
  80. FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
  81. if (begin == end) return;
  82. const auto offset = begin - format_.data();
  83. const auto size = end - begin;
  84. parts_.push_back(part(string_view_metadata(offset, size)));
  85. }
  86. FMT_CONSTEXPR void on_arg_id() {
  87. parts_.push_back(part(parse_context_.next_arg_id()));
  88. }
  89. FMT_CONSTEXPR void on_arg_id(unsigned id) {
  90. parse_context_.check_arg_id(id);
  91. parts_.push_back(part(id));
  92. }
  93. FMT_CONSTEXPR void on_arg_id(basic_string_view<Char> id) {
  94. const auto view = string_view_metadata(format_, id);
  95. const auto arg_id = typename part::named_argument_id(view);
  96. parts_.push_back(part(arg_id));
  97. }
  98. FMT_CONSTEXPR void on_replacement_field(const Char* ptr) {
  99. parts_.back().end_of_argument_id = ptr - format_.begin();
  100. }
  101. FMT_CONSTEXPR const Char* on_format_specs(const Char* begin,
  102. const Char* end) {
  103. const auto specs_offset = to_unsigned(begin - format_.begin());
  104. using parse_context = basic_parse_context<Char>;
  105. internal::dynamic_format_specs<Char> parsed_specs;
  106. dynamic_specs_handler<parse_context> handler(parsed_specs, parse_context_);
  107. begin = parse_format_specs(begin, end, handler);
  108. if (*begin != '}') on_error("missing '}' in format string");
  109. auto& last_part = parts_.back();
  110. auto specs = last_part.which == part::kind::argument_id
  111. ? typename part::specification(last_part.val.arg_id)
  112. : typename part::specification(last_part.val.named_arg_id);
  113. specs.parsed_specs = parsed_specs;
  114. last_part = part(specs);
  115. last_part.end_of_argument_id = specs_offset;
  116. return begin;
  117. }
  118. private:
  119. PartsContainer& parts_;
  120. basic_string_view<Char> format_;
  121. basic_parse_context<Char> parse_context_;
  122. };
  123. template <typename Format, typename PreparedPartsProvider, typename... Args>
  124. class prepared_format {
  125. public:
  126. using char_type = char_t<Format>;
  127. using format_part_t = format_part<char_type>;
  128. constexpr prepared_format(Format f)
  129. : format_(std::move(f)), parts_provider_(to_string_view(format_)) {}
  130. prepared_format() = delete;
  131. using context = buffer_context<char_type>;
  132. template <typename Range, typename Context>
  133. auto vformat_to(Range out, basic_format_args<Context> args) const ->
  134. typename Context::iterator {
  135. const auto format_view = internal::to_string_view(format_);
  136. basic_parse_context<char_type> parse_ctx(format_view);
  137. Context ctx(out.begin(), args);
  138. const auto& parts = parts_provider_.parts();
  139. for (auto part_it = parts.begin(); part_it != parts.end(); ++part_it) {
  140. const auto& part = *part_it;
  141. const auto& value = part.val;
  142. switch (part.which) {
  143. case format_part_t::kind::text: {
  144. const auto text = value.text.to_view(format_view.data());
  145. auto output = ctx.out();
  146. auto&& it = internal::reserve(output, text.size());
  147. it = std::copy_n(text.begin(), text.size(), it);
  148. ctx.advance_to(output);
  149. } break;
  150. case format_part_t::kind::argument_id: {
  151. advance_parse_context_to_specification(parse_ctx, part);
  152. format_arg<Range>(parse_ctx, ctx, value.arg_id);
  153. } break;
  154. case format_part_t::kind::named_argument_id: {
  155. advance_parse_context_to_specification(parse_ctx, part);
  156. const auto named_arg_id =
  157. value.named_arg_id.to_view(format_view.data());
  158. format_arg<Range>(parse_ctx, ctx, named_arg_id);
  159. } break;
  160. case format_part_t::kind::specification: {
  161. const auto& arg_id_value = value.spec.arg_id.val;
  162. const auto arg = value.spec.arg_id.which ==
  163. format_part_t::argument_id::which_arg_id::index
  164. ? ctx.arg(arg_id_value.index)
  165. : ctx.arg(arg_id_value.named_index.to_view(
  166. to_string_view(format_).data()));
  167. auto specs = value.spec.parsed_specs;
  168. handle_dynamic_spec<internal::width_checker>(
  169. specs.width, specs.width_ref, ctx, format_view.begin());
  170. handle_dynamic_spec<internal::precision_checker>(
  171. specs.precision, specs.precision_ref, ctx, format_view.begin());
  172. check_prepared_specs(specs, arg.type());
  173. advance_parse_context_to_specification(parse_ctx, part);
  174. ctx.advance_to(
  175. visit_format_arg(arg_formatter<Range>(ctx, nullptr, &specs), arg));
  176. } break;
  177. }
  178. }
  179. return ctx.out();
  180. }
  181. private:
  182. void advance_parse_context_to_specification(
  183. basic_parse_context<char_type>& parse_ctx,
  184. const format_part_t& part) const {
  185. const auto view = to_string_view(format_);
  186. const auto specification_begin = view.data() + part.end_of_argument_id;
  187. advance_to(parse_ctx, specification_begin);
  188. }
  189. template <typename Range, typename Context, typename Id>
  190. void format_arg(basic_parse_context<char_type>& parse_ctx, Context& ctx,
  191. Id arg_id) const {
  192. parse_ctx.check_arg_id(arg_id);
  193. const auto stopped_at =
  194. visit_format_arg(arg_formatter<Range>(ctx), ctx.arg(arg_id));
  195. ctx.advance_to(stopped_at);
  196. }
  197. template <typename Char>
  198. void check_prepared_specs(const basic_format_specs<Char>& specs,
  199. internal::type arg_type) const {
  200. internal::error_handler h;
  201. numeric_specs_checker<internal::error_handler> checker(h, arg_type);
  202. if (specs.align == align::numeric) checker.require_numeric_argument();
  203. if (specs.sign != sign::none) checker.check_sign();
  204. if (specs.alt) checker.require_numeric_argument();
  205. if (specs.precision >= 0) checker.check_precision();
  206. }
  207. private:
  208. Format format_;
  209. PreparedPartsProvider parts_provider_;
  210. };
  211. template <typename Char> struct part_counter {
  212. unsigned num_parts = 0;
  213. FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
  214. if (begin != end) ++num_parts;
  215. }
  216. FMT_CONSTEXPR void on_arg_id() { ++num_parts; }
  217. FMT_CONSTEXPR void on_arg_id(unsigned) { ++num_parts; }
  218. FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) { ++num_parts; }
  219. FMT_CONSTEXPR void on_replacement_field(const Char*) {}
  220. FMT_CONSTEXPR const Char* on_format_specs(const Char* begin,
  221. const Char* end) {
  222. // Find the matching brace.
  223. unsigned braces_counter = 0;
  224. for (; begin != end; ++begin) {
  225. if (*begin == '{') {
  226. ++braces_counter;
  227. } else if (*begin == '}') {
  228. if (braces_counter == 0u) break;
  229. --braces_counter;
  230. }
  231. }
  232. return begin;
  233. }
  234. FMT_CONSTEXPR void on_error(const char*) {}
  235. };
  236. template <typename Format> class compiletime_prepared_parts_type_provider {
  237. private:
  238. using char_type = char_t<Format>;
  239. static FMT_CONSTEXPR unsigned count_parts() {
  240. FMT_CONSTEXPR_DECL const auto text = to_string_view(Format{});
  241. part_counter<char_type> counter;
  242. internal::parse_format_string</*IS_CONSTEXPR=*/true>(text, counter);
  243. return counter.num_parts;
  244. }
  245. // Workaround for old compilers. Compiletime parts preparation will not be
  246. // performed with them anyway.
  247. #if FMT_USE_CONSTEXPR
  248. static FMT_CONSTEXPR_DECL const unsigned number_of_format_parts =
  249. compiletime_prepared_parts_type_provider::count_parts();
  250. #else
  251. static const unsigned number_of_format_parts = 0u;
  252. #endif
  253. public:
  254. template <unsigned N> struct format_parts_array {
  255. using value_type = format_part<char_type>;
  256. FMT_CONSTEXPR format_parts_array() : arr{} {}
  257. FMT_CONSTEXPR value_type& operator[](unsigned ind) { return arr[ind]; }
  258. FMT_CONSTEXPR const value_type* begin() const { return arr; }
  259. FMT_CONSTEXPR const value_type* end() const { return begin() + N; }
  260. private:
  261. value_type arr[N];
  262. };
  263. struct empty {
  264. // Parts preparator will search for it
  265. using value_type = format_part<char_type>;
  266. };
  267. using type = conditional_t<number_of_format_parts != 0,
  268. format_parts_array<number_of_format_parts>, empty>;
  269. };
  270. template <typename Parts> class compiletime_prepared_parts_collector {
  271. private:
  272. using format_part = typename Parts::value_type;
  273. public:
  274. FMT_CONSTEXPR explicit compiletime_prepared_parts_collector(Parts& parts)
  275. : parts_{parts}, counter_{0u} {}
  276. FMT_CONSTEXPR void push_back(format_part part) { parts_[counter_++] = part; }
  277. FMT_CONSTEXPR format_part& back() { return parts_[counter_ - 1]; }
  278. private:
  279. Parts& parts_;
  280. unsigned counter_;
  281. };
  282. template <typename PartsContainer, typename Char>
  283. FMT_CONSTEXPR PartsContainer prepare_parts(basic_string_view<Char> format) {
  284. PartsContainer parts;
  285. internal::parse_format_string</*IS_CONSTEXPR=*/false>(
  286. format, format_preparation_handler<Char, PartsContainer>(format, parts));
  287. return parts;
  288. }
  289. template <typename PartsContainer, typename Char>
  290. FMT_CONSTEXPR PartsContainer
  291. prepare_compiletime_parts(basic_string_view<Char> format) {
  292. using collector = compiletime_prepared_parts_collector<PartsContainer>;
  293. PartsContainer parts;
  294. collector c(parts);
  295. internal::parse_format_string</*IS_CONSTEXPR=*/true>(
  296. format, format_preparation_handler<Char, collector>(format, c));
  297. return parts;
  298. }
  299. template <typename PartsContainer> class runtime_parts_provider {
  300. public:
  301. runtime_parts_provider() = delete;
  302. template <typename Char>
  303. runtime_parts_provider(basic_string_view<Char> format)
  304. : parts_(prepare_parts<PartsContainer>(format)) {}
  305. const PartsContainer& parts() const { return parts_; }
  306. private:
  307. PartsContainer parts_;
  308. };
  309. template <typename Format, typename PartsContainer>
  310. struct compiletime_parts_provider {
  311. compiletime_parts_provider() = delete;
  312. template <typename Char>
  313. FMT_CONSTEXPR compiletime_parts_provider(basic_string_view<Char>) {}
  314. const PartsContainer& parts() const {
  315. static FMT_CONSTEXPR_DECL const PartsContainer prepared_parts =
  316. prepare_compiletime_parts<PartsContainer>(
  317. internal::to_string_view(Format{}));
  318. return prepared_parts;
  319. }
  320. };
  321. } // namespace internal
  322. #if FMT_USE_CONSTEXPR
  323. template <typename... Args, typename S,
  324. FMT_ENABLE_IF(is_compile_string<S>::value)>
  325. FMT_CONSTEXPR auto compile(S format_str) -> internal::prepared_format<
  326. S,
  327. internal::compiletime_parts_provider<
  328. S,
  329. typename internal::compiletime_prepared_parts_type_provider<S>::type>,
  330. Args...> {
  331. return format_str;
  332. }
  333. #endif
  334. template <typename... Args, typename Char, size_t N>
  335. auto compile(const Char (&format_str)[N]) -> internal::prepared_format<
  336. std::basic_string<Char>,
  337. internal::runtime_parts_provider<std::vector<internal::format_part<Char>>>,
  338. Args...> {
  339. return std::basic_string<Char>(format_str, N - 1);
  340. }
  341. template <typename CompiledFormat, typename... Args,
  342. typename Char = typename CompiledFormat::char_type>
  343. std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
  344. basic_memory_buffer<Char> buffer;
  345. using range = internal::buffer_range<Char>;
  346. using context = buffer_context<Char>;
  347. cf.template vformat_to<range, context>(range(buffer),
  348. {make_format_args<context>(args...)});
  349. return to_string(buffer);
  350. }
  351. template <typename OutputIt, typename CompiledFormat, typename... Args>
  352. OutputIt format_to(OutputIt out, const CompiledFormat& cf,
  353. const Args&... args) {
  354. using char_type = typename CompiledFormat::char_type;
  355. using range = internal::output_range<OutputIt, char_type>;
  356. using context = format_context_t<OutputIt, char_type>;
  357. return cf.template vformat_to<range, context>(
  358. range(out), {make_format_args<context>(args...)});
  359. }
  360. template <typename OutputIt, typename CompiledFormat, typename... Args,
  361. FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
  362. format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
  363. const CompiledFormat& cf,
  364. const Args&... args) {
  365. auto it =
  366. format_to(internal::truncating_iterator<OutputIt>(out, n), cf, args...);
  367. return {it.base(), it.count()};
  368. }
  369. template <typename CompiledFormat, typename... Args>
  370. std::size_t formatted_size(const CompiledFormat& cf, const Args&... args) {
  371. return fmt::format_to(
  372. internal::counting_iterator<typename CompiledFormat::char_type>(),
  373. cf, args...)
  374. .count();
  375. }
  376. FMT_END_NAMESPACE
  377. #endif // FMT_COMPILE_H_