[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/StephenChips/cppjson/main/cppjson/parse.cpp [Back]  [Original]

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "cppjson.hpp"

using std::isdigit;
using std::logic_error;
using std::pair;
using std::string;

pair parseJSON(const string &input, string::size_type index);
pair parseJSONObject(const string &input, string::size_type index);
pair parseJSONArray(const string &input, string::size_type index);
pair parseStringLiteral(const string &input, string::size_type index);
pair parseJSONNumber(const string &input, string::size_type index);
string::size_type expectString(const string &input, string::size_type index, const string &keyword);
string::size_type skipWhitespaces(const string &input, string::size_type index);
inline bool isHexLiteral(const string &input, string::size_type index);
inline bool isOctalLiteral(const string &input, string::size_type index);
std::pair parseUTF16EscapedValue(const string &input, string::size_type index);
inline bool isLeadSurrogate(char16_t v);
inline bool isTrailSurrogate(char16_t v);
char32_t calculateCodepoint(char16_t leadSurroatge, char16_t trailSurrogate);
void writeAsUTF8CodeUnits(std::ostringstream &oss, char32_t codepoint);
void writeHexValueToBuffer(char buf[], const string &input, string::size_type index);

JSON parse(const string &str)
{
    auto result = parseJSON(str, 0);
    auto end = skipWhitespaces(str, result.second);
    if (end != str.size())
        throw SyntaxError();
    return result.first;
}

pair parseJSON(const string &input, string::size_type index)
{
    index = skipWhitespaces(input, index);
    auto ch = input[index];
    if (ch == '{')
        return parseJSONObject(input, index);
    else if (ch == '[')
        return parseJSONArray(input, index);
    else if (ch == '"')
    {
        auto result = parseStringLiteral(input, index);
        return std::make_pair(JSON(result.first), result.second);
    }
    else if (isdigit(ch) || ch == '-')
        return parseJSONNumber(input, index);
    else if (ch == 't')
    {
        index = expectString(input, index, "true");
        return std::make_pair(JSON(true), index);
    }
    else if (ch == 'f')
    {
        index = expectString(input, index, "false");
        return std::make_pair(JSON(false), index);
    }
    else if (ch == 'n')
    {
        index = expectString(input, index, "null");
        return std::make_pair(JSON(nullptr), index);
    }
    else
        throw SyntaxError();
}

// The program looked ahead the next character first, and confirmed the what
// JSON value would be next, before it actually calls the function to parse a
// value, so the initial `index` value must points to the first character of
// a JSON value, hence we can simply skip it without checking.

pair parseJSONObject(const string &input, string::size_type index)
{
    std::map result;
    index = skipWhitespaces(input, index + 1);

    if (index == input.size())
        throw SyntaxError();
    if (input[index] == '}')
        return std::make_pair(JSON(result), index + 1);

    while (true)
    {
        index = skipWhitespaces(input, index);
        auto objectKey = parseStringLiteral(input, index);
        index = skipWhitespaces(input, objectKey.second);
        index = expectString(input, index, ":");
        index = skipWhitespaces(input, index);
        auto objectValue = parseJSON(input, index);
        index = skipWhitespaces(input, objectValue.second);

        if (input[index] == '}')
        {
            result[objectKey.first] = objectValue.first;
            return std::make_pair(JSON(result), index + 1);
        }
        else if (input[index] == ',')
        {
            result[objectKey.first] = objectValue.first;
            index++;
        }
        else
            throw SyntaxError();
    }

    throw SyntaxError();
}

pair parseJSONArray(const string &input, string::size_type index)
{
    std::vector result;
    index = skipWhitespaces(input, index + 1);

    if (index == input.size())
        throw SyntaxError();
    if (input[index] == ']')
        return std::make_pair(JSON(result), index + 1);

    while (true)
    {
        auto jsonVal = parseJSON(input, index);
        index = skipWhitespaces(input, jsonVal.second);

        if (index == input.size())
            throw SyntaxError();
        else if (input[index] == ']')
        {
            result.push_back(jsonVal.first);
            return std::make_pair(JSON(result), index + 1);
        }
        else if (input[index] == ',')
        {
            result.push_back(jsonVal.first);
            index = skipWhitespaces(input, index + 1);
        }
        else
            throw SyntaxError();
    }
}

pair parseStringLiteral(const string &input, string::size_type index)
{
    // Skip the double-quote at the begining
    index++;

    string::size_type start = index;
    std::ostringstream oss;

    while (index != input.size())
    {
        if (input[index] == '\\')
        {
            if (index + 1 >= input.size())
                throw SyntaxError();

            oss 

Web Proxy Viewer  |  New URL  |  Original Page