#include <iostream>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iomanip>
#include <string>
#include <vector>
#include <queue>
#include <inttypes.h>
#include <sys/resource.h>
#include <stdint.h>
#include <algorithm>
#include "../cujson_types.h"
#include "../cujson_error.h"
using namespace std;
class cuJSONIterator{
public:
uint8_t* inputJSON = nullptr; vector<int> resultSizes;
vector<int> resultSizesPrefix;
int32_t* structural;
int32_t* pair_pos;
int jsonDepth;
int bufferSize;
int totalResultSize;
int chunkCount;
int currentChunkIndex;
int fileSize;
token_type nodeType = OBJECT;
int node = 0;
std::string getKey(); std::string getValue(); int findKey(string key); int gotoKey(string key); int gotoArrayIndex(int index); int increamentIndex(int index);
char getChar(int structuralIdx); char getArtificalChar(int idx);
void reset(); void freeJson();
bool readFile(const char* file, uint8_t*& buffer, size_t& size);
int jumpOpeningForward(int idx); int jumpSpacesForward(int pos); int jumpSpacesBackward(int pos); int jumpForwardStructural(int idx);
int jumpValueBackward(int pos);
int jumpValueForward(int pos);
size_t len = 0;
cuJSONIterator(cuJSONResult* parsedTree, const char* filePath){
if(!readFile(filePath, inputJSON, len)){
cout << "Failed to Open File for Query!\n";
}
resultSizes = parsedTree->resultSizes;
resultSizesPrefix = parsedTree->resultSizesPrefix;
totalResultSize = parsedTree->totalResultSize;
structural = parsedTree->structural;
structural[0] = 0;
fileSize = parsedTree->fileSize;
structural[totalResultSize-1] = fileSize - 1;
pair_pos = parsedTree->pair_pos;
pair_pos[0] = totalResultSize-1;
jsonDepth = parsedTree->depth;
bufferSize = parsedTree->bufferSize;
chunkCount = parsedTree-> chunkCount;
currentChunkIndex = 0;
}
private: string getString(int start_index, int end_index); string getStringBackward(int end_index);
string getValueBackward(int start_index, int end_index, primitive_type& type);
int getValue(int index);
};
void cuJSONIterator::freeJson(){
free(inputJSON);
cudaFreeHost(structural);
}
char cuJSONIterator::getChar(int idx){
if(idx < 0 || idx >= totalResultSize || structural == NULL || inputJSON == NULL){
return '\0';
}
else if (idx == totalResultSize - 1) return ']';
else if (idx == 0) return '[';
int pos = structural[idx] - 1;
if(pos < 0 || (size_t)pos >= len){
return '\0';
}
else if(inputJSON[pos] == '\n'){
return ',';
}
else return inputJSON[pos];}
int cuJSONIterator::jumpOpeningForward(int idx){
if(idx < 0 || idx >= totalResultSize || pair_pos == NULL){
return -1;
}
int pairNode = pair_pos[idx];
if(pairNode < 0 || pairNode >= totalResultSize){
return -1;
}
return pairNode;
}
int cuJSONIterator::jumpSpacesForward(int pos){
int current_pos = pos;
while(inputJSON[current_pos] == ' '){
current_pos++;
}
return current_pos; }
int cuJSONIterator::jumpSpacesBackward(int pos){
int current_pos = pos;
while(inputJSON[current_pos] == ' '){
current_pos--;
}
return current_pos; }
int cuJSONIterator::jumpValueBackward(int pos){
int current_pos = pos - 1; while(inputJSON[current_pos] == ' ' || inputJSON[current_pos] == '"'){
if(inputJSON[current_pos] == '"'){
return current_pos-1; }
current_pos--; }
return current_pos; }
int cuJSONIterator::jumpValueForward(int pos){
int current_pos = pos + 1; while(inputJSON[current_pos] == ' ' || inputJSON[current_pos] == '"'){
if(inputJSON[current_pos] == '"'){
return current_pos+1; }
current_pos++; }
return current_pos; }
char cuJSONIterator::getArtificalChar(int idx){
if(idx == totalResultSize - 1) return ']';
else return '\0';
}
int cuJSONIterator::jumpForwardStructural(int idx){
int current_idx = idx + 1;
char current = getChar(current_idx);
while(current == '}' || current == ']' || current == getArtificalChar(current_idx)){
current_idx++;
current = getChar(current_idx);
}
return current_idx; }
bool cuJSONIterator::readFile(const char* file, uint8_t*& buffer, size_t& size) {
FILE* handle = fopen(file, "rb");
if (!handle) {
std::cerr << "File not found!" << std::endl;
return false;
}
fseek(handle, 0, SEEK_END);
size = ftell(handle);
fseek(handle, 0, SEEK_SET);
buffer = new uint8_t[size];
if (!buffer) {
std::cerr << "Memory allocation failed!" << std::endl;
fclose(handle);
return false;
}
size_t bytesRead = fread(buffer, 1, size, handle);
if (bytesRead != size) {
std::cerr << "Reading error!" << std::endl;
delete[] buffer;
fclose(handle);
return false;
}
fclose(handle);
return true;
}
void cuJSONIterator::reset(){
node = 0;
nodeType = OBJECT;
}
int cuJSONIterator::gotoArrayIndex(int index){
if(index < 0){
return 0;
}
if(totalResultSize <= 0 || structural == NULL || pair_pos == NULL || inputJSON == NULL){
return 0;
}
if(node < 0 || node >= totalResultSize){
return 0;
}
int total = index + 1;
int startNode = node;
int nextNode;
char currentNodeChar = getChar(startNode);
if(currentNodeChar == '\0'){
return 0;
}
if(currentNodeChar == ',' || currentNodeChar == '\n' || currentNodeChar == ':'){
if(startNode + 1 >= totalResultSize){
return 0;
}
startNode++;
currentNodeChar = getChar(startNode);
if(currentNodeChar == '\0'){
return 0;
}
}
nextNode = startNode + 1;
if(nextNode < 0 || nextNode >= totalResultSize){
return 0;
}
char nextNodeChar = getChar(nextNode);
if(nextNodeChar == '\0'){
return 0;
}
while( total != 1 && nextNodeChar != ']' && nextNode != totalResultSize - 1){
if(nextNode < 0 || nextNode >= totalResultSize){
return 0;
}
if(nextNodeChar == '[' || nextNodeChar == '{'){
int pairNode = jumpOpeningForward(nextNode);
if(pairNode <= nextNode || pairNode >= totalResultSize){
return 0;
}
nextNode = pairNode;
}
if(nextNodeChar == ',' || nextNodeChar == '\n'){
total--;
}
nextNode++;
if(nextNode < 0 || nextNode >= totalResultSize){
return 0;
}
nextNodeChar = getChar(nextNode);
if(nextNodeChar == '\0'){
return 0;
}
}
if(total == 1){
int targetNode = nextNode - 1; if(targetNode < 0 || targetNode >= totalResultSize){
return 0;
}
if(nextNodeChar == ']' && targetNode == startNode){
return 0;
}
node = targetNode;
if(nextNodeChar == '{'){
nodeType = OBJECT;
}
else if(nextNodeChar == '['){
nodeType = ARRAY;
node = nextNode;
return node;
}
else if(nextNodeChar == ',' || currentNodeChar == '\n' || nextNodeChar == ']'){
nodeType = VALUE;
}
return node; }
return 0; }
int cuJSONIterator::increamentIndex(int index){
node = node + index;
char currentNodeChar = getChar(node);
if(currentNodeChar == '{'){
nodeType = OBJECT;
}else if(currentNodeChar == '['){
nodeType = ARRAY;
}else if(currentNodeChar == ',' || currentNodeChar == '\n'){
nodeType = VALUE;
}else if(currentNodeChar == ':'){
nodeType = KEYVALUE;
}else if(currentNodeChar == ']' || currentNodeChar == '}'){
nodeType = CLOSING;
}else{
return 0;
}
return node; }
string cuJSONIterator::getString(int startPos, int endPos){ int length = 0;
string result;
startPos = jumpSpacesForward(startPos+1);
endPos = jumpSpacesBackward(endPos-1);
length = endPos - startPos - 1;
result.assign((char*)(inputJSON+startPos+1), abs(length)); return result;
}
int cuJSONIterator::findKey(string input_key){
char currentNodeChar = getChar(node);
int nextNode = node;
if(currentNodeChar == ':' || currentNodeChar == ',' || currentNodeChar == '\n'){ nextNode = nextNode + 1;
}
char nextPossibleNodeChar = getChar(node+1);
if( currentNodeChar == '[' && nextPossibleNodeChar == '{'){
currentNodeChar = nextPossibleNodeChar;
nextNode = node + 1;
}
if(getChar(nextNode) != '{'){
cout << "ERROR: Node is not an object to find key!" << endl;
return 0;
}
int endNode = jumpOpeningForward(nextNode); nextNode = nextNode+1;
char nextNodeChar = getChar(nextNode);
while (nextNode < endNode && nextNodeChar != '}')
{
if(nextNodeChar == '[' || nextNodeChar == '{'){ nextNode = jumpOpeningForward(nextNode);
}
if(nextNodeChar == ':'){ string key;
int endPos = structural[nextNode] - 1;
int startIdx = nextNode-1;
int startPos = structural[startIdx]-1;
key = getString(startPos, endPos);
if(key.compare(input_key)==0){
return nextNode - node; }
}
nextNode++;
nextNodeChar = getChar(nextNode);
}
return 0;
}
string cuJSONIterator::getKey(){
char currentNodeChar = getChar(node);
string key;
if(currentNodeChar == ':'){
int endIdx = node;
int endPos = structural[endIdx] - 1;
int startIdx = node - 1;
int startPos = structural[startIdx]-1;
key = getString(startPos, endPos); return key;
}else{
throw cujson_error{cujson_err::INTERNAL};
}
}
string cuJSONIterator::getValue(){
char currentNodeChar = getChar(node);
string value;
if(currentNodeChar == ',' || currentNodeChar == '\n' || currentNodeChar == ':'){
int startIdx = node + 1; int startPos, endIdx, endPos;
int nextNodeChar = getChar(startIdx);
if(nextNodeChar == '[' || nextNodeChar == '{'){ endIdx = jumpOpeningForward(startIdx);
startPos = structural[startIdx] - 1;
endPos = structural[endIdx]-1;
value = string((char*) inputJSON + startPos, endPos - startPos + 1);
return value;
}else{
endIdx = startIdx;
startIdx = node;
startPos = jumpValueForward ( structural[startIdx] - 1);
endPos = jumpValueBackward ( structural[endIdx] - 1);
value = string((char*) inputJSON + startPos, endPos - startPos + 1);
return value;
}
}else if(currentNodeChar == '['){
int startIdx = node + 1; int startPos, endIdx, endPos;
int nextNodeChar = getChar(startIdx);
if(nextNodeChar == '[' || nextNodeChar == '{'){ endIdx = jumpOpeningForward(startIdx);
startPos = structural[startIdx] - 1;
endPos = structural[endIdx] - 1;
value = string((char*) inputJSON + startPos, endPos - startPos + 1);
return value;
}else{
endIdx = startIdx;
startIdx = node;
startPos = jumpValueForward ( structural[startIdx] - 1);
endPos = jumpValueBackward ( structural[endIdx] - 1);
value = string((char*) inputJSON + startPos, endPos - startPos + 1);
return value;
}
}else{
cout << "ERROR: iterator is in wrong place." <<endl;
return value;
}
}
int cuJSONIterator::gotoKey(string key){
int index1 = findKey(key);
return increamentIndex(index1);
}