Edit

kc3-lang/angle/src/libANGLE/serializer/JsonSerializer.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2021-09-02 10:31:13
    Hash : 2f3e4db8
    Message : Capture/Replay: Serialize trace metadata to a JSON file. This will allow us to remove more code auto-generation for the trace tests. The trace info now can be loaded directly from JSON instead of from the autogenerated information. Bug: angleproject:5133 Change-Id: I04e22b9279b19282df274bc8defcd363d0449111 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3140218 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Tim Van Patten <timvp@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com>

  • src/libANGLE/serializer/JsonSerializer.cpp
  • //
    // Copyright 2021 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // JsonSerializer.cpp: Implementation of a JSON based serializer
    // Note that for binary blob data only a checksum is stored so that
    // a lossless  deserialization is not supported.
    
    #include "JsonSerializer.h"
    
    #include "common/debug.h"
    
    #include <anglebase/sha1.h>
    #include <rapidjson/document.h>
    #include <rapidjson/filewritestream.h>
    #include <rapidjson/ostreamwrapper.h>
    #include <rapidjson/prettywriter.h>
    
    namespace angle
    {
    
    namespace js = rapidjson;
    
    JsonSerializer::JsonSerializer() : mDoc(js::kObjectType), mAllocator(mDoc.GetAllocator()) {}
    
    JsonSerializer::~JsonSerializer() {}
    
    void JsonSerializer::startDocument(const std::string &name)
    {
        startGroup(name);
    }
    
    void JsonSerializer::startGroup(const std::string &name)
    {
        mGroupValueStack.push(SortedValueGroup());
        mGroupNameStack.push(name);
    }
    
    void JsonSerializer::endGroup()
    {
        ASSERT(mGroupValueStack.size() >= 2);
        ASSERT(!mGroupNameStack.empty());
    
        SortedValueGroup &group = mGroupValueStack.top();
        std::string &name       = mGroupNameStack.top();
    
        SortedValueGroup::value_type new_entry = std::make_pair(name, makeValueGroup(group));
    
        mGroupValueStack.pop();
        mGroupNameStack.pop();
    
        mGroupValueStack.top().insert(std::move(new_entry));
    }
    
    void JsonSerializer::addBlob(const std::string &name, const uint8_t *blob, size_t length)
    {
        unsigned char hash[angle::base::kSHA1Length];
        angle::base::SHA1HashBytes(blob, length, hash);
        std::ostringstream os;
    
        // Since we don't want to de-serialize the data we just store a checksum of the blob
        os << "SHA1:";
        static constexpr char kASCII[] = "0123456789ABCDEF";
        for (size_t i = 0; i < angle::base::kSHA1Length; ++i)
        {
            os << kASCII[hash[i] & 0xf] << kASCII[hash[i] >> 4];
        }
    
        std::ostringstream hashName;
        hashName << name << "-hash";
        addString(hashName.str(), os.str());
    
        std::vector<uint8_t> data((length < 16) ? length : static_cast<size_t>(16));
        std::copy(blob, blob + data.size(), data.begin());
    
        std::ostringstream rawName;
        rawName << name << "-raw[0-" << data.size() - 1 << ']';
        addVector(rawName.str(), data);
    }
    
    void JsonSerializer::addCString(const std::string &name, const char *value)
    {
        rapidjson::Value tag(name.c_str(), mAllocator);
        rapidjson::Value val(value, mAllocator);
        mGroupValueStack.top().insert(std::make_pair(name, std::move(val)));
    }
    
    void JsonSerializer::addString(const std::string &name, const std::string &value)
    {
        addCString(name, value.c_str());
    }
    
    void JsonSerializer::addVectorOfStrings(const std::string &name,
                                            const std::vector<std::string> &value)
    {
        rapidjson::Value arrayValue(rapidjson::kArrayType);
        arrayValue.SetArray();
    
        for (const std::string &v : value)
        {
            rapidjson::Value str(v.c_str(), mAllocator);
            arrayValue.PushBack(str, mAllocator);
        }
    
        mGroupValueStack.top().insert(std::make_pair(name, std::move(arrayValue)));
    }
    
    void JsonSerializer::addBool(const std::string &name, bool value)
    {
        rapidjson::Value boolValue(value);
        mGroupValueStack.top().insert(std::make_pair(name, std::move(boolValue)));
    }
    
    const char *JsonSerializer::data() const
    {
        return mResult.c_str();
    }
    
    std::vector<uint8_t> JsonSerializer::getData() const
    {
        return std::vector<uint8_t>(mResult.begin(), mResult.end());
    }
    
    void JsonSerializer::endDocument()
    {
        // finalize last group
        ASSERT(!mGroupValueStack.empty());
        ASSERT(!mGroupNameStack.empty());
    
        rapidjson::Value nameValue(mGroupNameStack.top().c_str(), mAllocator);
        mDoc.AddMember(nameValue, makeValueGroup(mGroupValueStack.top()), mAllocator);
    
        mGroupValueStack.pop();
        mGroupNameStack.pop();
        ASSERT(mGroupValueStack.empty());
        ASSERT(mGroupNameStack.empty());
    
        std::stringstream os;
        js::OStreamWrapper osw(os);
        js::PrettyWriter<js::OStreamWrapper> prettyOs(osw);
        mDoc.Accept(prettyOs);
        mResult = os.str();
    }
    
    size_t JsonSerializer::length() const
    {
        return mResult.length();
    }
    
    rapidjson::Value JsonSerializer::makeValueGroup(SortedValueGroup &group)
    {
        rapidjson::Value valueGroup(js::kObjectType);
        for (auto &it : group)
        {
            rapidjson::Value tag(it.first.c_str(), mAllocator);
            valueGroup.AddMember(tag, it.second, mAllocator);
        }
        return valueGroup;
    }
    
    }  // namespace angle