Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2023
572
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.35 KB | Software | 0 0
  1. #pragma once
  2. #include "parse_result.h"
  3.  
  4. #include <array>
  5. #include <glog/logging.h>
  6. #include <iostream>
  7. #include <string_view>
  8.  
  9. namespace NPriv {
  10.  
  11.    using StrPos      = int32_t;
  12.    using RollingHash = uint64_t;
  13.  
  14.    template <size_t keyLen, size_t windowSize>
  15.    struct Key {
  16.       static_assert(keyLen == windowSize, "");   // In this case we just need to compare the only element
  17.       static constexpr StrPos KeyLen      = keyLen;
  18.       static constexpr StrPos WINDOW_SIZE = windowSize;
  19.  
  20.       const RollingHash keyHash;
  21.       StrPos            relPos = 0;   // historical "sequence" start position, relative to the beginning of json
  22.  
  23.       Key(const std::string_view key, StrPos initialRelPos): keyHash(calcHashFrom(key, 0)), relPos(initialRelPos) {}
  24.  
  25.       StrPos findIn(const std::string_view json, StrPos prevKeyPos) const {
  26.          StrPos absKeyPos;
  27.  
  28.          for(StrPos left = std::min<StrPos>(prevKeyPos + relPos, json.size() - KeyLen), right = left + 1;
  29.              left >= 0 || right + KeyLen <= json.size();
  30.              --left, ++right) {
  31.             if(left >= 0 && keyHash == calcHashFrom(json, left)) {
  32.                absKeyPos = left;
  33.                break;
  34.             }
  35.             if(right + KeyLen <= json.size() && keyHash == calcHashFrom(json, right)) {
  36.                absKeyPos = right;
  37.                break;
  38.             }
  39.          }
  40.          LOG_IF(FATAL, absKeyPos == -1) << "Failed to find a key even after multiple attempts";
  41.          return absKeyPos;
  42.       }
  43.  
  44.    private:
  45.       static constexpr int getShift(int pos) {
  46.          constexpr int POW = 5;
  47.          return POW * (1 + pos);
  48.       }
  49.       static RollingHash calcHashFrom(const std::string_view str, const StrPos start) {
  50.          RollingHash hash      = 0;
  51.          StrPos      windowEnd = start;
  52.          for(; windowEnd - start != WINDOW_SIZE; ++windowEnd)
  53.             hash += RollingHash(str[windowEnd]) << getShift(windowEnd - start);
  54.          return hash;
  55.       }
  56.    };
  57. }   // namespace NPriv
  58.  
  59.  
  60.  
  61. class JsonParser /*AlaVolnitskyBin*/ {
  62. public:
  63.    ParseRes parse(std::string_view json) {
  64.       return {.seq = parseInt64KeyAndUpdateRelPos(json, 0, seqKey),
  65.               .bid = parseDoubleKeyAndUpdateRelPos(json, seqKey.relPos, bidKey),
  66.               .ask = parseDoubleKeyAndUpdateRelPos(json, seqKey.relPos + bidKey.relPos, askKey)};
  67.    }
  68.  
  69. private:
  70.    using StrPos                                         = NPriv::StrPos;
  71.    static constexpr StrPos                  WINDOW_SIZE = 4;
  72.    static constexpr std::string_view        SEQUENCE    = "nce\"";   // "\"sequence\""
  73.    static constexpr std::string_view        BID         = "bid\"";   // "\"best_bid\""
  74.    static constexpr std::string_view        ASK         = "ask\"";   // "\"best_ask\""
  75.    NPriv::Key<SEQUENCE.size(), WINDOW_SIZE> seqKey      = {SEQUENCE, 0};
  76.    NPriv::Key<BID.size(), WINDOW_SIZE>      bidKey      = {BID, SEQUENCE.size() + 1};
  77.    NPriv::Key<ASK.size(), WINDOW_SIZE>      askKey      = {ASK, BID.size() + 1};
  78.  
  79.  
  80.    static StrPos skipColonSpaces(std::string_view json, StrPos start) {
  81.       for(start = start; start != json.size() && (json[start] == ':' || json[start] == ' '); ++start)
  82.          ;
  83.       return start;
  84.    }
  85.    static StrPos skipColonSpacesQuotes(std::string_view json, StrPos start) {
  86.       for(start = start; start != json.size() && (json[start] == ':' || json[start] == ' ' || json[start] == '"'); ++start)
  87.          ;
  88.       return start;
  89.    }
  90.    static int64_t toInt(std::string_view str, StrPos start) {
  91.       int64_t result = 0;
  92.       for(; start != str.size() && str[start] >= '0' && str[start] <= '9'; ++start)
  93.          result = result * 10 + str[start] - '0';
  94.       return result;
  95.    }
  96.    static Float toDouble(std::string_view str, StrPos start) {
  97.       int64_t result = 0;
  98.       int64_t factor = 1;
  99.  
  100.       for(; start != str.size() && str[start] >= '0' && str[start] <= '9'; ++start)
  101.          result = result * 10 + (str[start] - '0');
  102.  
  103.       if(start != str.size() && str[start] == '.') [[likely]] {
  104.          ++start;
  105.          for(; start != str.size() && str[start] >= '0' && str[start] <= '9'; ++start) {
  106.             result = result * 10 + (str[start] - '0');
  107.             factor *= 10;
  108.          }
  109.       }
  110.       return (Float)result / (Float)factor;
  111.    }
  112.  
  113.    template <class TKey>
  114.    static int64_t parseInt64KeyAndUpdateRelPos(std::string_view json, const StrPos prevKeyPos, TKey &key) {
  115.       const StrPos absKeyPos = key.findIn(json, prevKeyPos);
  116.       // std::cout << "Found key at position: " << absKeyPos << ": " << std::string_view(json.data() + absKeyPos, TKey::KeyLen)
  117.       //           << std::endl;
  118.       key.relPos         = absKeyPos - prevKeyPos;
  119.       const StrPos start = skipColonSpaces(json, absKeyPos + TKey::KeyLen);
  120.       return toInt(json, start);
  121.    }
  122.    template <class TKey>
  123.    static Float parseDoubleKeyAndUpdateRelPos(std::string_view json, const StrPos prevKeyPos, TKey &key) {
  124.       const StrPos absKeyPos = key.findIn(json, prevKeyPos);
  125.       // std::cout << "Found key: " << " at position: " << absKeyPos << ": "
  126.       //           << std::string_view(json.data() + absKeyPos, TKey::KeyLen) << " of json:\n"
  127.       //           << json << std::endl;
  128.       key.relPos         = absKeyPos - prevKeyPos;
  129.       const StrPos start = skipColonSpacesQuotes(json, absKeyPos + TKey::KeyLen);
  130.       return toDouble(json, start);
  131.    }
  132. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement