daily pastebin goal
9%
SHARE
TWEET

Untitled

a guest May 19th, 2017 41 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // WIP -- not done yet :)
  2.  
  3. #include <optional>
  4. #include <string_view>
  5. #include <unordered_map>
  6. #include <variant>
  7. #include <vector>
  8.  
  9. namespace json {
  10.  
  11. struct Wrapper;
  12. using Null = std::nullptr_t;
  13. using Bool = bool;
  14. using Number = double;
  15. using String = std::string_view;
  16. using Array = std::vector<Value>;
  17. using Object = std::unordered_map<String, Value>;
  18. using Value = std::variant<Bool, Number, String, Array, Object, Null>;
  19.  
  20. struct Wrapper {
  21.   operator Value& () { return v; }
  22.   operator const Value& () const { return v; }
  23. };
  24.  
  25. namespace detail {
  26.  
  27. std::optional<Object> parseObject() {
  28.   Object object;
  29.   if(!accept('{'))
  30.     return {};
  31.   if (expect('}'))
  32.     return object;
  33.   while (true) {
  34.     if (auto s = parseString(); s) {
  35.       if (!expect(':'))
  36.         return {};
  37.       if (auto v = parseValue(); v)
  38.         object.emplace(s, v);
  39.       else
  40.         return {};
  41.       if (expect(','))
  42.         continue;
  43.       if (expect('}')
  44.         return object;
  45.       return {};
  46.     }
  47.     return {};
  48.   }
  49. }
  50.  
  51. std::optional<Array> parseArray() {
  52.   Array array;
  53.   if (!accept('['))
  54.     return {};
  55.   if (expect(']'))
  56.     return array;
  57.   while (true) {
  58.     if (auto v = parseValue(); v) {
  59.       array.emplace_back(v);
  60.       if (expect(','))
  61.         continue;
  62.       if (expect(']'))
  63.         return array;
  64.       return {};
  65.     }
  66.     return {};
  67.   }
  68. }
  69.  
  70. std::optional<String> parseString() {
  71.   if (!accept('"'))
  72.     return {};
  73.   auto ptr = std::next(ctx.ptr());
  74.   unsigned length{0};
  75.   while (true) {
  76.     ctx.advance(1);
  77.     if (ctx.prev() != '\\' && ctx.curr() == '"')
  78.       return {ptr, length};
  79.     ++length;
  80.   }
  81.   return {};
  82. }
  83.  
  84. std::optional<Number> parseNumber() {
  85.   auto ptr = ctx.ptr();
  86.   accept('-');
  87.   if (!check(::isdigit))
  88.     return {};
  89.   while (check(::isdigit))
  90.     ;
  91.   if (accept('.')) {
  92.     if (!check(::isdigit))
  93.       return {};
  94.     while (check(::isdigit))
  95.       ;
  96.   }
  97.   if (accept('e') || accept('E')) {
  98.     accept('+') || accept('-');
  99.     if (!check(::isdigit))
  100.       return {};
  101.     while (check(::isdigit))
  102.       ;
  103.   }
  104.   String asString{ptr, ctx.ptr() - ptr};
  105.   return std::stod(asString);
  106. }
  107.  
  108. std::optional<Value> parseValue() {
  109.   if (accept("true"))
  110.     return bool{true};
  111.   if (accept("false"))
  112.     return bool{false};
  113.   if (accept("null"))
  114.     return nullptr;
  115.   if (auto n = parseNumber(); n)
  116.     return n;
  117.   if (auto s = parseString(); s)
  118.     return s;
  119.   if (auto o = parseObject(); o)
  120.     return o;
  121.   if (auto a = parseArray(); a)
  122.     return a;
  123.   return {};
  124. }
  125.  
  126. } // end namespace detail
  127.  
  128. std::optional<Object> parse() {
  129.   return detail::parseObject();
  130. }
  131.  
  132. } // end namespace json
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top