blob: ffb24cc532f5c04ac3f5f60b6b7b11b775998fc0 [file] [log] [blame]
/*
* Copyright (C) 2013-2017 Apple Inc. All rights reserved.
*
* 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.
*/
#pragma once
#include <functional>
#include <wtf/Deque.h>
#include <wtf/Forward.h>
namespace WebCore {
class SharedBuffer;
class KeyedDecoder {
WTF_MAKE_FAST_ALLOCATED;
public:
WEBCORE_EXPORT static std::unique_ptr<KeyedDecoder> decoder(const uint8_t* data, size_t);
virtual ~KeyedDecoder() = default;
virtual WARN_UNUSED_RETURN bool decodeBytes(const String& key, const uint8_t*&, size_t&) = 0;
virtual WARN_UNUSED_RETURN bool decodeBool(const String& key, bool&) = 0;
virtual WARN_UNUSED_RETURN bool decodeUInt32(const String& key, uint32_t&) = 0;
virtual WARN_UNUSED_RETURN bool decodeUInt64(const String& key, uint64_t&) = 0;
virtual WARN_UNUSED_RETURN bool decodeInt32(const String& key, int32_t&) = 0;
virtual WARN_UNUSED_RETURN bool decodeInt64(const String& key, int64_t&) = 0;
virtual WARN_UNUSED_RETURN bool decodeFloat(const String& key, float&) = 0;
virtual WARN_UNUSED_RETURN bool decodeDouble(const String& key, double&) = 0;
virtual WARN_UNUSED_RETURN bool decodeString(const String& key, String&) = 0;
template<typename T> WARN_UNUSED_RETURN
bool decodeBytes(const String& key, Vector<T>& vector)
{
static_assert(sizeof(T) == 1);
size_t size;
const uint8_t* bytes;
if (!decodeBytes(key, bytes, size))
return false;
vector.resize(size);
std::copy(bytes, bytes + size, vector.data());
return true;
}
template<typename T, typename F> WARN_UNUSED_RETURN
bool decodeEnum(const String& key, T& value, F&& isValidEnumFunction)
{
static_assert(std::is_enum<T>::value, "T must be an enum type");
int64_t intValue;
if (!decodeInt64(key, intValue))
return false;
if (!isValidEnumFunction(static_cast<T>(intValue)))
return false;
value = static_cast<T>(intValue);
return true;
}
template<typename T, typename F> WARN_UNUSED_RETURN
bool decodeObject(const String& key, T& object, F&& function)
{
if (!beginObject(key))
return false;
bool result = function(*this, object);
endObject();
return result;
}
template<typename T, typename F> WARN_UNUSED_RETURN
bool decodeConditionalObject(const String& key, T& object, F&& function)
{
// FIXME: beginObject can return false for two reasons: either the
// key doesn't exist or the key refers to something that isn't an object.
// Because of this, decodeConditionalObject won't distinguish between a
// missing object or a value that isn't an object.
if (!beginObject(key))
return true;
bool result = function(*this, object);
endObject();
return result;
}
template<typename ContainerType, typename F> WARN_UNUSED_RETURN
bool decodeObjects(const String& key, ContainerType& objects, F&& function)
{
if (!beginArray(key))
return false;
bool result = true;
while (beginArrayElement()) {
typename ContainerType::ValueType element;
if (!function(*this, element)) {
result = false;
endArrayElement();
break;
}
objects.append(WTFMove(element));
endArrayElement();
}
endArray();
return result;
}
protected:
KeyedDecoder()
{
}
private:
virtual bool beginObject(const String& key) = 0;
virtual void endObject() = 0;
virtual bool beginArray(const String& key) = 0;
virtual bool beginArrayElement() = 0;
virtual void endArrayElement() = 0;
virtual void endArray() = 0;
};
class KeyedEncoder {
WTF_MAKE_FAST_ALLOCATED;
public:
WEBCORE_EXPORT static std::unique_ptr<KeyedEncoder> encoder();
virtual ~KeyedEncoder() = default;
virtual void encodeBytes(const String& key, const uint8_t*, size_t) = 0;
virtual void encodeBool(const String& key, bool) = 0;
virtual void encodeUInt32(const String& key, uint32_t) = 0;
virtual void encodeUInt64(const String& key, uint64_t) = 0;
virtual void encodeInt32(const String& key, int32_t) = 0;
virtual void encodeInt64(const String& key, int64_t) = 0;
virtual void encodeFloat(const String& key, float) = 0;
virtual void encodeDouble(const String& key, double) = 0;
virtual void encodeString(const String& key, const String&) = 0;
virtual RefPtr<SharedBuffer> finishEncoding() = 0;
template<typename T>
void encodeEnum(const String& key, T value)
{
static_assert(std::is_enum<T>::value, "T must be an enum type");
encodeInt64(key, static_cast<int64_t>(value));
}
template<typename T, typename F>
void encodeObject(const String& key, const T& object, F&& function)
{
beginObject(key);
function(*this, object);
endObject();
}
template<typename T, typename F>
void encodeConditionalObject(const String& key, const T* object, F&& function)
{
if (!object)
return;
encodeObject(key, *object, std::forward<F>(function));
}
template<typename T, typename F>
void encodeObjects(const String& key, T begin, T end, F&& function)
{
beginArray(key);
for (T it = begin; it != end; ++it) {
beginArrayElement();
function(*this, *it);
endArrayElement();
}
endArray();
}
protected:
KeyedEncoder()
{
}
private:
virtual void beginObject(const String& key) = 0;
virtual void endObject() = 0;
virtual void beginArray(const String& key) = 0;
virtual void beginArrayElement() = 0;
virtual void endArrayElement() = 0;
virtual void endArray() = 0;
};
} // namespace WebCore