blob: 0e5972321b5f73f572bd79658811f003a95ed492 [file] [log] [blame]
/*
* Copyright (C) 2018 Sony Interactive Entertainment Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "KeyedDecoderGeneric.h"
#include "KeyedEncoderGeneric.h"
#include <wtf/HashMap.h>
#include <wtf/Variant.h>
#include <wtf/Vector.h>
#include <wtf/persistence/PersistentDecoder.h>
#include <wtf/text/StringHash.h>
namespace WebCore {
class KeyedDecoderGeneric::Dictionary {
WTF_MAKE_FAST_ALLOCATED;
public:
using Node = Variant<Vector<uint8_t>, bool, uint32_t, uint64_t, int32_t, int64_t, float, double, String, std::unique_ptr<Dictionary>, std::unique_ptr<Array>>;
template <typename T>
void add(const String& key, T&& value) { m_map.add(key, makeUnique<Node>(std::forward<T>(value))); }
Node& get(const String& key) { return *m_map.get(key); }
private:
HashMap<String, std::unique_ptr<Node>> m_map;
};
static bool readString(WTF::Persistence::Decoder& decoder, String& result)
{
size_t size;
if (!decoder.decode(size))
return false;
Vector<uint8_t> buffer(size);
if (!decoder.decodeFixedLengthData(buffer.data(), size))
return false;
result = String::fromUTF8(buffer.data(), size);
return true;
}
template<typename T>
static bool readSimpleValue(WTF::Persistence::Decoder& decoder, KeyedDecoderGeneric::Dictionary& dictionary)
{
String key;
bool ok = readString(decoder, key);
if (!ok)
return false;
T value;
ok = decoder.decode(value);
if (!ok)
return false;
dictionary.add(key, WTFMove(value));
return true;
}
std::unique_ptr<KeyedDecoder> KeyedDecoder::decoder(const uint8_t* data, size_t size)
{
return makeUnique<KeyedDecoderGeneric>(data, size);
}
KeyedDecoderGeneric::KeyedDecoderGeneric(const uint8_t* data, size_t size)
{
WTF::Persistence::Decoder decoder(data, size);
KeyedEncoderGeneric::Type type;
String key;
m_rootDictionary = makeUnique<Dictionary>();
m_dictionaryStack.append(m_rootDictionary.get());
bool ok = true;
while (ok && decoder.decodeEnum(type)) {
switch (type) {
case KeyedEncoderGeneric::Type::Bytes: {
ok = readString(decoder, key);
if (!ok)
break;
size_t size;
ok = decoder.decode(size);
if (!ok)
break;
Vector<uint8_t> buffer(size);
ok = decoder.decodeFixedLengthData(buffer.data(), size);
if (!ok)
break;
m_dictionaryStack.last()->add(key, WTFMove(buffer));
break;
}
case KeyedEncoderGeneric::Type::Bool:
ok = readSimpleValue<bool>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::UInt32:
ok = readSimpleValue<uint32_t>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::UInt64:
ok = readSimpleValue<uint64_t>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::Int32:
ok = readSimpleValue<int32_t>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::Int64:
ok = readSimpleValue<int64_t>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::Float:
ok = readSimpleValue<float>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::Double:
ok = readSimpleValue<double>(decoder, *m_dictionaryStack.last());
break;
case KeyedEncoderGeneric::Type::String: {
ok = readString(decoder, key);
if (!ok)
break;
String value;
ok = readString(decoder, value);
if (!ok)
break;
m_dictionaryStack.last()->add(key, WTFMove(value));
break;
}
case KeyedEncoderGeneric::Type::BeginObject: {
ok = readString(decoder, key);
if (!ok)
break;
auto* currentDictinary = m_dictionaryStack.last();
auto newDictionary = makeUnique<Dictionary>();
m_dictionaryStack.append(newDictionary.get());
currentDictinary->add(key, WTFMove(newDictionary));
break;
}
case KeyedEncoderGeneric::Type::EndObject:
m_dictionaryStack.removeLast();
break;
case KeyedEncoderGeneric::Type::BeginArray: {
ok = readString(decoder, key);
if (!ok)
break;
auto newArray = makeUnique<Array>();
m_arrayStack.append(newArray.get());
m_dictionaryStack.last()->add(key, WTFMove(newArray));
break;
}
case KeyedEncoderGeneric::Type::BeginArrayElement: {
auto newDictionary = makeUnique<Dictionary>();
m_dictionaryStack.append(newDictionary.get());
m_arrayStack.last()->append(WTFMove(newDictionary));
break;
}
case KeyedEncoderGeneric::Type::EndArrayElement:
m_dictionaryStack.removeLast();
break;
case KeyedEncoderGeneric::Type::EndArray:
m_arrayStack.removeLast();
break;
}
}
while (m_dictionaryStack.size() > 1)
m_dictionaryStack.removeLast();
while (!m_arrayStack.isEmpty())
m_arrayStack.removeLast();
}
bool KeyedDecoderGeneric::decodeBytes(const String& key, const uint8_t*& data, size_t& size)
{
auto* value = WTF::get_if<Vector<uint8_t>>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
data = value->data();
size = value->size();
return true;
}
bool KeyedDecoderGeneric::decodeBool(const String& key, bool& result)
{
auto* value = WTF::get_if<bool>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeUInt32(const String& key, uint32_t& result)
{
auto* value = WTF::get_if<uint32_t>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeUInt64(const String& key, uint64_t& result)
{
auto* value = WTF::get_if<uint64_t>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeInt32(const String& key, int32_t& result)
{
auto* value = WTF::get_if<int32_t>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeInt64(const String& key, int64_t& result)
{
auto* value = WTF::get_if<int64_t>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeFloat(const String& key, float& result)
{
auto* value = WTF::get_if<float>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeDouble(const String& key, double& result)
{
auto* value = WTF::get_if<double>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::decodeString(const String& key, String& result)
{
auto* value = WTF::get_if<String>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
result = *value;
return true;
}
bool KeyedDecoderGeneric::beginObject(const String& key)
{
auto* value = WTF::get_if<std::unique_ptr<Dictionary>>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
m_dictionaryStack.append(value->get());
return true;
}
void KeyedDecoderGeneric::endObject()
{
m_dictionaryStack.removeLast();
}
bool KeyedDecoderGeneric::beginArray(const String& key)
{
auto* value = WTF::get_if<std::unique_ptr<Array>>(m_dictionaryStack.last()->get(key));
if (!value)
return false;
m_arrayStack.append(value->get());
m_arrayIndexStack.append(0);
return true;
}
bool KeyedDecoderGeneric::beginArrayElement()
{
if (m_arrayIndexStack.last() >= m_arrayStack.last()->size())
return false;
auto dictionary = m_arrayStack.last()->at(m_arrayIndexStack.last()++).get();
m_dictionaryStack.append(dictionary);
return true;
}
void KeyedDecoderGeneric::endArrayElement()
{
m_dictionaryStack.removeLast();
}
void KeyedDecoderGeneric::endArray()
{
m_arrayStack.removeLast();
m_arrayIndexStack.removeLast();
}
} // namespace WebCore