/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkJSON_DEFINED
#define SkJSON_DEFINED

#include "include/core/SkTypes.h"
#include "include/private/SkNoncopyable.h"
#include "src/core/SkArenaAlloc.h"

#include <cstdint>
#include <cstring>
#include <string_view>

class SkString;
class SkWStream;

namespace skjson {

/**
 *  A fast and likely non-conforming JSON parser.
 *
 *  Some known limitations/compromises:
 *
 *    -- single-precision FP numbers
 *
 *    -- missing string unescaping (no current users, could be easily added)
 *
 *
 *  Values are opaque, fixed-size (64 bits), immutable records.
 *
 *  They can be converted to facade types for type-specific functionality.
 *
 *  E.g.:
 *
 *     if (v.is<ArrayValue>()) {
 *         for (const auto& item : v.as<ArrayValue>()) {
 *             if (const NumberValue* n = item) {
 *                 printf("Found number: %f", **n);
 *             }
 *         }
 *     }
 *
 *     if (v.is<ObjectValue>()) {
 *         const StringValue* id = v.as<ObjectValue>()["id"];
 *         if (id) {
 *             printf("Found object ID: %s", id->begin());
 *         } else {
 *             printf("Missing object ID");
 *         }
 *     }
 */
class alignas(8) Value {
public:
    enum class Type {
        kNull,
        kBool,
        kNumber,
        kString,
        kArray,
        kObject,
    };

    /**
     * @return    The type of this value.
     */
    Type getType() const;

    /**
     * @return    True if the record matches the facade type T.
     */
    template <typename T>
    bool is() const { return this->getType() == T::kType; }

    /**
     * Unguarded conversion to facade types.
     *
     * @return    The record cast as facade type T&.
     */
    template <typename T>
    const T& as() const {
        SkASSERT(this->is<T>());
        return *reinterpret_cast<const T*>(this);
    }

    /**
     * Guarded conversion to facade types.
     *
     * @return    The record cast as facade type T*.
     */
    template <typename T>
    operator const T*() const {
        return this->is<T>() ? &this->as<T>() : nullptr;
    }

    /**
     * @return    The string representation of this value.
     */
    SkString toString() const;

protected:
    /*
      Value implementation notes:

        -- fixed 64-bit size

        -- 8-byte aligned

        -- union of:

             bool
             int32
             float
             char[8] (short string storage)
             external payload (tagged) pointer

         -- lowest 3 bits reserved for tag storage

     */
    enum class Tag : uint8_t {
        // n.b.: we picked kShortString == 0 on purpose,
        // to enable certain short-string optimizations.
        kShortString                  = 0b00000000,  // inline payload
        kNull                         = 0b00000001,  // no payload
        kBool                         = 0b00000010,  // inline payload
        kInt                          = 0b00000011,  // inline payload
        kFloat                        = 0b00000100,  // inline payload
        kString                       = 0b00000101,  // ptr to external storage
        kArray                        = 0b00000110,  // ptr to external storage
        kObject                       = 0b00000111,  // ptr to external storage
    };
    inline static constexpr uint8_t kTagMask = 0b00000111;

    void init_tagged(Tag);
    void init_tagged_pointer(Tag, void*);

    Tag getTag() const {
        return static_cast<Tag>(fData8[0] & kTagMask);
    }

    // Access the record payload as T.
    //
    // Since the tag is stored in the lower bits, we skip the first word whenever feasible.
    //
    // E.g. (U == unused)
    //
    //   uint8_t
    //    -----------------------------------------------------------------------
    //   |TAG| U  |  val8  |   U    |   U    |   U    |   U    |   U    |   U    |
    //    -----------------------------------------------------------------------
    //
    //   uint16_t
    //    -----------------------------------------------------------------------
    //   |TAG|      U      |      val16      |        U        |        U        |
    //    -----------------------------------------------------------------------
    //
    //   uint32_t
    //    -----------------------------------------------------------------------
    //   |TAG|             U                 |                val32              |
    //    -----------------------------------------------------------------------
    //
    //   T* (32b)
    //    -----------------------------------------------------------------------
    //   |TAG|             U                 |             T* (32bits)           |
    //    -----------------------------------------------------------------------
    //
    //   T* (64b)
    //    -----------------------------------------------------------------------
    //   |TAG|                        T* (61bits)                                |
    //    -----------------------------------------------------------------------
    //
    template <typename T>
    const T* cast() const {
        static_assert(sizeof (T) <=  sizeof(Value), "");
        static_assert(alignof(T) <= alignof(Value), "");

        return (sizeof(T) > sizeof(*this) / 2)
                ? reinterpret_cast<const T*>(this) + 0  // need all the bits
                : reinterpret_cast<const T*>(this) + 1; // skip the first word (where the tag lives)
    }

    template <typename T>
    T* cast() { return const_cast<T*>(const_cast<const Value*>(this)->cast<T>()); }

    // Access the pointer payload.
    template <typename T>
    const T* ptr() const {
        static_assert(sizeof(uintptr_t)     == sizeof(Value) ||
                      sizeof(uintptr_t) * 2 == sizeof(Value), "");

        return (sizeof(uintptr_t) < sizeof(Value))
            // For 32-bit, pointers are stored unmodified.
            ? *this->cast<const T*>()
            // For 64-bit, we use the lower bits of the pointer as tag storage.
            : reinterpret_cast<T*>(*this->cast<uintptr_t>() & ~static_cast<uintptr_t>(kTagMask));
    }

private:
    inline static constexpr size_t kValueSize = 8;

    uint8_t fData8[kValueSize];

#if !defined(SK_CPU_LENDIAN)
    // The current value layout assumes LE and will take some tweaking for BE.
    static_assert(false, "Big-endian builds are not supported at this time.");
#endif
};

class NullValue final : public Value {
public:
    inline static constexpr Type kType = Type::kNull;

    NullValue();
};

class BoolValue final : public Value {
public:
    inline static constexpr Type kType = Type::kBool;

    explicit BoolValue(bool);

    bool operator *() const {
        SkASSERT(this->getTag() == Tag::kBool);
        return *this->cast<bool>();
    }
};

class NumberValue final : public Value {
public:
    inline static constexpr Type kType = Type::kNumber;

    explicit NumberValue(int32_t);
    explicit NumberValue(float);

    double operator *() const {
        SkASSERT(this->getTag() == Tag::kInt ||
                 this->getTag() == Tag::kFloat);

        return this->getTag() == Tag::kInt
            ? static_cast<double>(*this->cast<int32_t>())
            : static_cast<double>(*this->cast<float>());
    }
};

template <typename T, Value::Type vtype>
class VectorValue : public Value {
public:
    using ValueT = T;
    inline static constexpr Type kType = vtype;

    size_t size() const {
        SkASSERT(this->getType() == kType);
        return *this->ptr<size_t>();
    }

    const T* begin() const {
        SkASSERT(this->getType() == kType);
        const auto* size_ptr = this->ptr<size_t>();
        return reinterpret_cast<const T*>(size_ptr + 1);
    }

    const T* end() const {
        SkASSERT(this->getType() == kType);
        const auto* size_ptr = this->ptr<size_t>();
        return reinterpret_cast<const T*>(size_ptr + 1) + *size_ptr;
    }

    const T& operator[](size_t i) const {
        SkASSERT(this->getType() == kType);
        SkASSERT(i < this->size());

        return *(this->begin() + i);
    }
};

class ArrayValue final : public VectorValue<Value, Value::Type::kArray> {
public:
    ArrayValue(const Value* src, size_t size, SkArenaAlloc& alloc);
};

class StringValue final : public Value {
public:
    inline static constexpr Type kType = Type::kString;

    StringValue();
    StringValue(const char* src, size_t size, SkArenaAlloc& alloc);

    size_t size() const {
        switch (this->getTag()) {
        case Tag::kShortString:
            // We don't bother storing a length for short strings on the assumption
            // that strlen is fast in this case.  If this becomes problematic, we
            // can either go back to storing (7-len) in the tag byte or write a fast
            // short_strlen.
            return strlen(this->cast<char>());
        case Tag::kString:
            return this->cast<VectorValue<char, Value::Type::kString>>()->size();
        default:
            return 0;
        }
    }

    const char* begin() const {
        return this->getTag() == Tag::kShortString
            ? this->cast<char>()
            : this->cast<VectorValue<char, Value::Type::kString>>()->begin();
    }

    const char* end() const {
        return this->getTag() == Tag::kShortString
            ? strchr(this->cast<char>(), '\0')
            : this->cast<VectorValue<char, Value::Type::kString>>()->end();
    }

    std::string_view str() const {
        return std::string_view(this->begin(), this->size());
    }
};

struct Member {
    StringValue fKey;
          Value fValue;
};

class ObjectValue final : public VectorValue<Member, Value::Type::kObject> {
public:
    ObjectValue(const Member* src, size_t size, SkArenaAlloc& alloc);

    const  Value& operator[](const char*) const;

    const Member& operator[](size_t i) const {
        return this->VectorValue::operator[](i);
    }
};

class DOM final : public SkNoncopyable {
public:
    DOM(const char*, size_t);

    const Value& root() const { return fRoot; }

    void write(SkWStream*) const;

private:
    SkArenaAlloc fAlloc;
    Value        fRoot;
};

inline Value::Type Value::getType() const {
    switch (this->getTag()) {
    case Tag::kNull:        return Type::kNull;
    case Tag::kBool:        return Type::kBool;
    case Tag::kInt:         return Type::kNumber;
    case Tag::kFloat:       return Type::kNumber;
    case Tag::kShortString: return Type::kString;
    case Tag::kString:      return Type::kString;
    case Tag::kArray:       return Type::kArray;
    case Tag::kObject:      return Type::kObject;
    }

    SkASSERT(false); // unreachable
    return Type::kNull;
}

} // namespace skjson

#endif // SkJSON_DEFINED

