7 #ifndef GARLIC_UTILITY_H
8 #define GARLIC_UTILITY_H
30 template<GARLIC_VIEW L1, GARLIC_VIEW L2>
31 static inline std::enable_if_t<!is_comparable<L1, L2>::value,
bool>
33 if (layer1.is_int() && layer2.is_int() && layer1.get_int() == layer2.get_int())
return true;
34 else if (layer1.is_string() && layer2.is_string() && std::strcmp(layer1.get_cstr(), layer2.get_cstr()) == 0) {
37 else if (layer1.is_double() && layer2.is_double() && layer1.get_double() == layer2.get_double())
return true;
38 else if (layer1.is_bool() && layer2.is_bool() && layer1.get_bool() == layer2.get_bool())
return true;
39 else if (layer1.is_null() && layer2.is_null())
return true;
40 else if (layer1.is_list() && layer2.is_list()) {
42 layer1.begin_list(), layer1.end_list(),
43 layer2.begin_list(), layer2.end_list(),
44 [](
const auto& item1,
const auto& item2) { return cmp_layers(item1, item2); }
46 }
else if (layer1.is_object() && layer2.is_object()) {
48 layer1.begin_member(), layer1.end_member(),
49 layer2.begin_member(), layer2.end_member(),
50 [](
const auto& item1,
const auto& item2) {
51 return cmp_layers(item1.key, item2.key) && cmp_layers(item1.value, item2.value);
58 template<GARLIC_VIEW Layer1, GARLIC_VIEW Layer2>
59 static inline std::enable_if_t<is_comparable<Layer1, Layer2>::value,
bool>
60 cmp_layers(
const Layer1& layer1,
const Layer2& layer2) {
61 return layer1 == layer2;
82 using const_iterator = std::string_view::const_iterator;
103 template<
typename Callable>
105 std::string_view part = this->
next();
106 while (!part.empty()) {
116 bool found_word =
false;
118 for(; it < text_.end(); it++) {
120 if (found_word)
return get_substr(it);
123 if (!found_word) cursor_ = it;
127 if (found_word)
return get_substr(it);
132 std::string_view text_;
133 const_iterator cursor_;
135 std::string_view get_substr(
const const_iterator& it) {
136 auto old_cursor = cursor_;
138 return std::string_view{old_cursor, it};
149 template<GARLIC_VIEW LayerType,
typename Callable>
152 using view_type = decltype(value.get_view());
155 view_type cursor = value.get_view();
157 auto part = parts.
next();
162 if (cursor.is_object()) {
164 get_member(cursor, part, [&cursor, &found](
const auto& result) {
165 cursor = result.get_view();
169 }
else if (cursor.is_list()) {
171 if (std::from_chars(part.begin(), part.end(), position).ec == std::errc::invalid_argument)
174 get_item(cursor, position, [&cursor, &found](
const auto& result) {
175 cursor = result.get_view();
192 template<
typename OutputType, GARLIC_VIEW Layer>
193 static inline OutputType
194 safe_resolve(
const Layer& value, std::string_view key, OutputType default_value) {
196 safe_decode<OutputType>(result, [&default_value](
auto&& result){
197 default_value = result;
200 return default_value;
212 template<
typename OutputType, GARLIC_VIEW Layer,
typename Callable>
216 safe_decode<OutputType>(result, cb);
228 template<
typename OutputType, GARLIC_VIEW Layer>
229 static inline OutputType
230 resolve(
const Layer& value, std::string_view key, OutputType default_value) {
232 default_value = decode<OutputType>(result);
234 return default_value;
246 template<
typename OutputType, GARLIC_VIEW Layer,
typename Callable>
248 resolve_cb(
const Layer& value, std::string_view key, Callable&& cb) {
250 cb(decode<OutputType>(result, cb));
261 template<GARLIC_VIEW Layer,
typename Callable>
263 get_member(
const Layer& value,
const char* key, Callable&& cb) noexcept {
264 if(
auto it = value.find_member(key); it != value.end_member()) cb((*it).value);
268 template<GARLIC_VIEW Layer,
typename Callable>
270 get_member(
const Layer& value, std::string_view key, Callable&& cb) noexcept {
271 if(
auto it = value.find_member(key); it != value.end_member()) cb((*it).value);
282 template<GARLIC_VIEW Layer, std::
integral IndexType,
typename Callable>
283 static inline std::enable_if_t<std::__is_random_access_iter<ConstValueIteratorOf<Layer>>::value>
284 get_item(Layer&& layer, IndexType index, Callable&& cb) noexcept {
285 if (
auto it = layer.begin_list() += index; it < layer.end_list()) cb(*it);
289 template<GARLIC_VIEW Layer, std::
integral IndexType,
typename Callable>
290 static inline std::enable_if_t<!std::__is_random_access_iter<ConstValueIteratorOf<Layer>>::value>
291 get_item(Layer&& layer, IndexType index, Callable&& cb) noexcept {
292 auto it = layer.begin_list();
293 IndexType counter = 0;
294 while (it != layer.end_list()) {
295 if (counter == index) {
305 template<
typename Container,
typename ValueType,
typename Callable>
307 find(
const Container& container,
const ValueType& value, Callable&& cb) {
308 if (
auto it = container.find(value); it != container.end()) cb(*it);
317 template<
typename OutputType, GARLIC_VIEW Layer>
318 static inline OutputType
319 get(Layer&& layer,
const char* key) {
320 return decode<OutputType>((*layer.find_member(key)).value);
331 template<
typename OutputType, GARLIC_VIEW Layer, std::
integral IndexType>
332 static inline std::enable_if_t<std::__is_random_access_iter<ConstValueIteratorOf<Layer>>::value, OutputType>
333 get(Layer&& layer, IndexType index) {
334 return decode<OutputType>(layer.begin_list()[index]);
338 template<
typename OutputType, GARLIC_VIEW Layer, std::
integral IndexType>
339 static inline std::enable_if_t<!std::__is_random_access_iter<ConstValueIteratorOf<Layer>>::value, OutputType>
340 get(Layer&& layer, IndexType index) {
341 auto it = layer.begin_list();
346 return decode<OutputType>(*it);
355 template<
typename OutputType, GARLIC_VIEW Layer>
356 static inline OutputType
357 get(Layer&& layer,
const char* key, OutputType default_value) {
358 if (
auto it = layer.find_member(key); it != layer.end_member()) {
359 return decode<OutputType>((*it).value);
361 return default_value;
370 template<
typename OutputType, GARLIC_VIEW Layer, std::
integral IndexType>
371 static inline OutputType
372 get(Layer&& layer, IndexType index, OutputType default_value) {
373 get_item(layer, index, [&default_value](
const auto& result) {
374 default_value = decode<OutputType>(result);
376 return default_value;
387 template<
typename OutputType,
typename Callable, GARLIC_VIEW Layer>
389 get_cb(Layer&& layer,
const char* key, Callable&& cb) {
390 if (
auto it = layer.find_member(key); it != layer.end_member()) {
391 cb(decode<OutputType>((*it).value));
402 template<
typename OutputType, GARLIC_VIEW Layer, std::
integral IndexType,
typename Callable>
404 get_cb(Layer&& layer, IndexType index, Callable&& cb) {
405 get_item(layer, index, [&cb](
const auto& result){
406 cb(decode<OutputType>(result));
416 template<
typename OutputType, GARLIC_VIEW Layer>
417 static inline OutputType
418 safe_get(Layer&& layer,
const char* key, OutputType default_value) {
419 if (
auto it = layer.find_member(key); it != layer.end_member()) {
420 safe_decode<OutputType>(
422 [&default_value](
auto&& result) { default_value = result; });
424 return default_value;
433 template<
typename OutputType, GARLIC_VIEW Layer, std::
integral IndexType>
434 static inline OutputType
435 safe_get(Layer&& layer, IndexType index, OutputType default_value) {
436 get_item(layer, index, [&default_value](
const auto& result) {
437 safe_decode<OutputType>(result, [&default_value](
auto&& value){
438 default_value = value;
441 return default_value;
452 template<
typename OutputType, GARLIC_VIEW Layer,
typename Callable>
455 if (
auto it = layer.find_member(key); it != layer.end_member()) {
456 safe_decode<OutputType>((*it).value, cb);
467 template<
typename OutputType, GARLIC_VIEW Layer, std::
integral IndexType,
typename Callable>
470 get_item(layer, index, [&cb](
const auto& result) {
471 safe_decode<OutputType>(result, cb);
483 template<GARLIC_VIEW Layer, GARLIC_REF Output>
486 if (layer.is_double()) {
487 output.set_double(layer.get_double());
488 }
else if (layer.is_int()) {
489 output.set_int(layer.get_int());
490 }
else if (layer.is_bool()) {
491 output.set_bool(layer.get_bool());
492 }
else if (layer.is_string()) {
493 output.set_string(layer.get_cstr());
494 }
else if (layer.is_list()) {
496 for (
const auto& item : layer.get_list()) {
497 output.push_back_builder(
501 }
else if (layer.is_object()) {
503 for (
const auto& pair : layer.get_object()) {
504 output.add_member_builder(
506 [&pair](
auto ref) {
copy_layer(pair.value, ref); }
516 template<GARLIC_VIEW Layer>
517 static constexpr
bool has_random_access_list_iterator = std::__is_random_access_iter<ConstValueIteratorOf<Layer>>::value;
519 template<GARLIC_VIEW,
class =
void>
520 static constexpr
bool has_explicit_list_size_method =
false;
522 template<GARLIC_VIEW Layer>
523 static constexpr
bool has_explicit_list_size_method<Layer, decltype(std::declval<Layer>().list_size())> =
true;
526 template<GARLIC_VIEW Layer>
527 static inline std::enable_if_t<has_explicit_list_size_method<Layer>,
size_t>
528 list_size_impl(Layer&& layer) {
529 return layer.list_size();
533 template<GARLIC_VIEW Layer>
534 static inline std::enable_if_t<has_random_access_list_iterator<Layer> && !has_explicit_list_size_method<Layer>,
size_t>
535 list_size_impl(Layer&& layer) {
536 return layer.end_list() - layer.begin_list();
540 template<GARLIC_VIEW Layer>
541 static inline std::enable_if_t<!has_random_access_list_iterator<Layer> && !has_explicit_list_size_method<Layer>,
size_t>
542 list_size_impl(Layer&& layer) {
544 for (
auto it = layer.begin_list(); it != layer.end_list(); ++it)
549 template<GARLIC_VIEW,
class =
void>
550 static constexpr
bool has_explicit_string_length_method =
false;
552 template<GARLIC_VIEW Layer>
553 static constexpr
bool has_explicit_string_length_method<Layer, decltype(std::declval<Layer>().string_length())> =
true;
555 template<GARLIC_VIEW Layer>
556 static inline std::enable_if_t<has_explicit_string_length_method<Layer>,
size_t>
557 string_length_impl(Layer&& layer) {
558 return layer.string_length();
561 template<GARLIC_VIEW Layer>
562 static inline std::enable_if_t<!has_explicit_string_length_method<Layer>,
size_t>
563 string_length_impl(Layer&& layer) {
564 return strlen(layer.get_cstr());
574 template<GARLIC_VIEW Layer>
576 return internal::list_size_impl(layer);
584 template<GARLIC_VIEW Layer>
586 return internal::string_length_impl(layer);
590 template<
int BufferSize = 65536>
591 class FileStreamBuffer :
public std::streambuf {
593 FileStreamBuffer(FILE* file) : file_(file) {}
595 std::streambuf::int_type underflow()
override {
596 auto length = fread(read_buffer_, 1,
sizeof(read_buffer_), file_);
597 if (!length)
return traits_type::eof();
598 setg(read_buffer_, read_buffer_, read_buffer_ + length);
599 return traits_type::to_int_type(*gptr());
604 char read_buffer_[BufferSize];