Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include "parse_result.h"
- #include <array>
- #include <glog/logging.h>
- #include <iostream>
- #include <string_view>
- namespace NPriv {
- using StrPos = int32_t;
- using RollingHash = uint64_t;
- template <size_t keyLen, size_t windowSize>
- struct Key {
- static_assert(keyLen == windowSize, ""); // In this case we just need to compare the only element
- static constexpr StrPos KeyLen = keyLen;
- static constexpr StrPos WINDOW_SIZE = windowSize;
- const RollingHash keyHash;
- StrPos relPos = 0; // historical "sequence" start position, relative to the beginning of json
- Key(const std::string_view key, StrPos initialRelPos): keyHash(calcHashFrom(key, 0)), relPos(initialRelPos) {}
- StrPos findIn(const std::string_view json, StrPos prevKeyPos) const {
- StrPos absKeyPos;
- for(StrPos left = std::min<StrPos>(prevKeyPos + relPos, json.size() - KeyLen), right = left + 1;
- left >= 0 || right + KeyLen <= json.size();
- --left, ++right) {
- if(left >= 0 && keyHash == calcHashFrom(json, left)) {
- absKeyPos = left;
- break;
- }
- if(right + KeyLen <= json.size() && keyHash == calcHashFrom(json, right)) {
- absKeyPos = right;
- break;
- }
- }
- LOG_IF(FATAL, absKeyPos == -1) << "Failed to find a key even after multiple attempts";
- return absKeyPos;
- }
- private:
- static constexpr int getShift(int pos) {
- constexpr int POW = 5;
- return POW * (1 + pos);
- }
- static RollingHash calcHashFrom(const std::string_view str, const StrPos start) {
- RollingHash hash = 0;
- StrPos windowEnd = start;
- for(; windowEnd - start != WINDOW_SIZE; ++windowEnd)
- hash += RollingHash(str[windowEnd]) << getShift(windowEnd - start);
- return hash;
- }
- };
- } // namespace NPriv
- class JsonParser /*AlaVolnitskyBin*/ {
- public:
- ParseRes parse(std::string_view json) {
- return {.seq = parseInt64KeyAndUpdateRelPos(json, 0, seqKey),
- .bid = parseDoubleKeyAndUpdateRelPos(json, seqKey.relPos, bidKey),
- .ask = parseDoubleKeyAndUpdateRelPos(json, seqKey.relPos + bidKey.relPos, askKey)};
- }
- private:
- using StrPos = NPriv::StrPos;
- static constexpr StrPos WINDOW_SIZE = 4;
- static constexpr std::string_view SEQUENCE = "nce\""; // "\"sequence\""
- static constexpr std::string_view BID = "bid\""; // "\"best_bid\""
- static constexpr std::string_view ASK = "ask\""; // "\"best_ask\""
- NPriv::Key<SEQUENCE.size(), WINDOW_SIZE> seqKey = {SEQUENCE, 0};
- NPriv::Key<BID.size(), WINDOW_SIZE> bidKey = {BID, SEQUENCE.size() + 1};
- NPriv::Key<ASK.size(), WINDOW_SIZE> askKey = {ASK, BID.size() + 1};
- static StrPos skipColonSpaces(std::string_view json, StrPos start) {
- for(start = start; start != json.size() && (json[start] == ':' || json[start] == ' '); ++start)
- ;
- return start;
- }
- static StrPos skipColonSpacesQuotes(std::string_view json, StrPos start) {
- for(start = start; start != json.size() && (json[start] == ':' || json[start] == ' ' || json[start] == '"'); ++start)
- ;
- return start;
- }
- static int64_t toInt(std::string_view str, StrPos start) {
- int64_t result = 0;
- for(; start != str.size() && str[start] >= '0' && str[start] <= '9'; ++start)
- result = result * 10 + str[start] - '0';
- return result;
- }
- static Float toDouble(std::string_view str, StrPos start) {
- int64_t result = 0;
- int64_t factor = 1;
- for(; start != str.size() && str[start] >= '0' && str[start] <= '9'; ++start)
- result = result * 10 + (str[start] - '0');
- if(start != str.size() && str[start] == '.') [[likely]] {
- ++start;
- for(; start != str.size() && str[start] >= '0' && str[start] <= '9'; ++start) {
- result = result * 10 + (str[start] - '0');
- factor *= 10;
- }
- }
- return (Float)result / (Float)factor;
- }
- template <class TKey>
- static int64_t parseInt64KeyAndUpdateRelPos(std::string_view json, const StrPos prevKeyPos, TKey &key) {
- const StrPos absKeyPos = key.findIn(json, prevKeyPos);
- // std::cout << "Found key at position: " << absKeyPos << ": " << std::string_view(json.data() + absKeyPos, TKey::KeyLen)
- // << std::endl;
- key.relPos = absKeyPos - prevKeyPos;
- const StrPos start = skipColonSpaces(json, absKeyPos + TKey::KeyLen);
- return toInt(json, start);
- }
- template <class TKey>
- static Float parseDoubleKeyAndUpdateRelPos(std::string_view json, const StrPos prevKeyPos, TKey &key) {
- const StrPos absKeyPos = key.findIn(json, prevKeyPos);
- // std::cout << "Found key: " << " at position: " << absKeyPos << ": "
- // << std::string_view(json.data() + absKeyPos, TKey::KeyLen) << " of json:\n"
- // << json << std::endl;
- key.relPos = absKeyPos - prevKeyPos;
- const StrPos start = skipColonSpacesQuotes(json, absKeyPos + TKey::KeyLen);
- return toDouble(json, start);
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement