🚧 started UBJSON implementation
This commit is contained in:
parent
15b6421d07
commit
c9938ea838
405
src/json.hpp
405
src/json.hpp
@ -4534,6 +4534,27 @@ class binary_reader
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a JSON value from UBJSON input
|
||||
|
||||
@param[in] strict whether to expect the input to be consumed completed
|
||||
@return JSON value created from UBJSON input
|
||||
|
||||
@throw parse_error.110 if input ended unexpectedly or the end of file was
|
||||
not reached when @a strict was set to true
|
||||
@throw parse_error.112 if unsupported byte was read
|
||||
*/
|
||||
BasicJsonType parse_ubjson(const bool strict)
|
||||
{
|
||||
const auto res = parse_ubjson_internal();
|
||||
if (strict)
|
||||
{
|
||||
get();
|
||||
check_eof(true);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief determine system byte order
|
||||
|
||||
@ -5195,6 +5216,68 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@param[in] get_char whether a new character should be retrieved from the
|
||||
input (true, default) or whether the last read
|
||||
character should be considered instead
|
||||
*/
|
||||
BasicJsonType parse_ubjson_internal(const bool get_char = true)
|
||||
{
|
||||
switch (get_char ? get() : current)
|
||||
{
|
||||
case std::char_traits<char>::eof(): // EOF
|
||||
JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
|
||||
|
||||
case 'T': // true
|
||||
return true;
|
||||
case 'F': // false
|
||||
return false;
|
||||
|
||||
case 'Z': // null
|
||||
return nullptr;
|
||||
|
||||
case 'N': // no-op
|
||||
return parse_ubjson_internal(); // read next byte
|
||||
|
||||
case 'U':
|
||||
return get_number<uint8_t>();
|
||||
case 'i':
|
||||
return get_number<int8_t>();
|
||||
case 'I':
|
||||
return get_number<int16_t>();
|
||||
case 'l':
|
||||
return get_number<int32_t>();
|
||||
case 'L':
|
||||
return get_number<int64_t>();
|
||||
case 'd':
|
||||
return get_number<float>();
|
||||
case 'D':
|
||||
return get_number<double>();
|
||||
|
||||
case 'C': // char
|
||||
{
|
||||
get();
|
||||
check_eof();
|
||||
return std::string(1, static_cast<char>(current));
|
||||
}
|
||||
|
||||
case 'S': // string
|
||||
return get_ubjson_string();
|
||||
|
||||
case '[': // array
|
||||
return get_ubjson_array();
|
||||
|
||||
case '{': // object
|
||||
return get_ubjson_object();
|
||||
|
||||
default: // anything else
|
||||
std::stringstream ss;
|
||||
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
|
||||
JSON_THROW(parse_error::create(112, chars_read,
|
||||
"error reading UBJSON; last byte: 0x" + ss.str()));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief get next character from the input
|
||||
|
||||
@ -5495,6 +5578,80 @@ class binary_reader
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a UBJSON string
|
||||
|
||||
This function first reads starting bytes to determine the expected
|
||||
string length and then copies this number of bytes into a string.
|
||||
|
||||
@param[in] get_char whether a new character should be retrieved from the
|
||||
input (true, default) or whether the last read
|
||||
character should be considered instead
|
||||
|
||||
@return string
|
||||
|
||||
@throw parse_error.110 if input ended
|
||||
@throw parse_error.113 if an unexpected byte is read
|
||||
*/
|
||||
std::string get_ubjson_string(const bool get_char = true)
|
||||
{
|
||||
if (get_char)
|
||||
{
|
||||
get();
|
||||
}
|
||||
|
||||
check_eof();
|
||||
|
||||
switch (current)
|
||||
{
|
||||
case 'U':
|
||||
return get_string(get_number<uint8_t>());
|
||||
case 'i':
|
||||
return get_string(get_number<int8_t>());
|
||||
case 'I':
|
||||
return get_string(get_number<int16_t>());
|
||||
case 'l':
|
||||
return get_string(get_number<int32_t>());
|
||||
case 'L':
|
||||
return get_string(get_number<int64_t>());
|
||||
default:
|
||||
std::stringstream ss;
|
||||
ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
|
||||
JSON_THROW(parse_error::create(113, chars_read,
|
||||
"expected a UBJSON string; last byte: 0x" + ss.str()));
|
||||
}
|
||||
}
|
||||
|
||||
BasicJsonType get_ubjson_array()
|
||||
{
|
||||
BasicJsonType result = value_t::array;
|
||||
|
||||
while (get() != ']')
|
||||
{
|
||||
// skip no-op
|
||||
if (current == 'N')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
result.push_back(parse_ubjson_internal(false));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BasicJsonType get_ubjson_object()
|
||||
{
|
||||
BasicJsonType result = value_t::object;
|
||||
|
||||
while (get() != '}')
|
||||
{
|
||||
auto key = get_ubjson_string(false);
|
||||
result[std::move(key)] = parse_ubjson_internal();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief check if input ended
|
||||
@throw parse_error.110 if input ended
|
||||
@ -5678,23 +5835,23 @@ class binary_writer
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0x60 + N));
|
||||
}
|
||||
else if (N <= 0xFF)
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x78));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFF)
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x79));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x7A));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= 0xFFFFFFFFFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x7B));
|
||||
write_number(static_cast<uint64_t>(N));
|
||||
@ -5716,23 +5873,23 @@ class binary_writer
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0x80 + N));
|
||||
}
|
||||
else if (N <= 0xFF)
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x98));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFF)
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x99));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x9A));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= 0xFFFFFFFFFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0x9B));
|
||||
write_number(static_cast<uint64_t>(N));
|
||||
@ -5755,23 +5912,23 @@ class binary_writer
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0xA0 + N));
|
||||
}
|
||||
else if (N <= 0xFF)
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0xB8));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFF)
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0xB9));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0xBA));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= 0xFFFFFFFFFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(0xBB));
|
||||
write_number(static_cast<uint64_t>(N));
|
||||
@ -5939,19 +6096,19 @@ class binary_writer
|
||||
// fixstr
|
||||
write_number(static_cast<uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= 255)
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa->write_character(static_cast<CharType>(0xD9));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
}
|
||||
else if (N <= 65535)
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa->write_character(static_cast<CharType>(0xDA));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
}
|
||||
else if (N <= 4294967295)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
// str 32
|
||||
oa->write_character(static_cast<CharType>(0xDB));
|
||||
@ -5974,13 +6131,13 @@ class binary_writer
|
||||
// fixarray
|
||||
write_number(static_cast<uint8_t>(0x90 | N));
|
||||
}
|
||||
else if (N <= 0xFFFF)
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
{
|
||||
// array 16
|
||||
oa->write_character(static_cast<CharType>(0xDC));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
}
|
||||
else if (N <= 0xFFFFFFFF)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
// array 32
|
||||
oa->write_character(static_cast<CharType>(0xDD));
|
||||
@ -6004,13 +6161,13 @@ class binary_writer
|
||||
// fixmap
|
||||
write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
|
||||
}
|
||||
else if (N <= 65535)
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
{
|
||||
// map 16
|
||||
oa->write_character(static_cast<CharType>(0xDE));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
}
|
||||
else if (N <= 4294967295)
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
{
|
||||
// map 32
|
||||
oa->write_character(static_cast<CharType>(0xDF));
|
||||
@ -6031,6 +6188,110 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief[in] j JSON value to serialize
|
||||
*/
|
||||
void write_ubjson(const BasicJsonType& j, const bool use_count = false)
|
||||
{
|
||||
switch (j.type())
|
||||
{
|
||||
case value_t::null:
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('Z'));
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::boolean:
|
||||
{
|
||||
oa->write_character(j.m_value.boolean
|
||||
? static_cast<CharType>('T')
|
||||
: static_cast<CharType>('F'));
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_integer:
|
||||
{
|
||||
write_number_with_ubjson_prefix(j.m_value.number_integer);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
write_number_with_ubjson_prefix(j.m_value.number_unsigned);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_float:
|
||||
{
|
||||
write_number_with_ubjson_prefix(j.m_value.number_float);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('S'));
|
||||
write_number_with_ubjson_prefix(j.m_value.string->size());
|
||||
oa->write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
|
||||
j.m_value.string->size());
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('['));
|
||||
|
||||
if (use_count)
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('#'));
|
||||
write_number_with_ubjson_prefix(j.m_value.array->size());
|
||||
}
|
||||
|
||||
for (const auto& el : *j.m_value.array)
|
||||
{
|
||||
write_ubjson(el, use_count);
|
||||
}
|
||||
|
||||
if (not use_count)
|
||||
{
|
||||
oa->write_character(static_cast<CharType>(']'));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('{'));
|
||||
|
||||
if (use_count)
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('#'));
|
||||
write_number_with_ubjson_prefix(j.m_value.object->size());
|
||||
}
|
||||
|
||||
for (const auto& el : *j.m_value.object)
|
||||
{
|
||||
write_number_with_ubjson_prefix(el.first.size());
|
||||
oa->write_characters(
|
||||
reinterpret_cast<const CharType*>(el.first.c_str()),
|
||||
el.first.size());
|
||||
write_ubjson(el.second, use_count);
|
||||
}
|
||||
|
||||
if (not use_count)
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('}'));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
@brief write a number to output input
|
||||
@ -6058,6 +6319,82 @@ class binary_writer
|
||||
oa->write_characters(vec.data(), sizeof(NumberType));
|
||||
}
|
||||
|
||||
template<typename NumberType>
|
||||
void write_number_with_ubjson_prefix(const NumberType n)
|
||||
{
|
||||
if (std::is_floating_point<NumberType>::value)
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('D')); // float64
|
||||
write_number(n);
|
||||
}
|
||||
else if (std::is_unsigned<NumberType>::value)
|
||||
{
|
||||
if (n <= (std::numeric_limits<int8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('i')); // uint8
|
||||
write_number(static_cast<uint8_t>(n));
|
||||
}
|
||||
else if (n <= (std::numeric_limits<uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('U')); // uint8
|
||||
write_number(static_cast<uint8_t>(n));
|
||||
}
|
||||
else if (n <= (std::numeric_limits<int16_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('I')); // int16
|
||||
write_number(static_cast<int16_t>(n));
|
||||
}
|
||||
else if (n <= (std::numeric_limits<int32_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('l')); // int32
|
||||
write_number(static_cast<int32_t>(n));
|
||||
}
|
||||
else if (n <= (std::numeric_limits<int64_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('L')); // int64
|
||||
write_number(static_cast<int64_t>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: replace by exception
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('i')); // int8
|
||||
write_number(static_cast<int8_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<uint8_t>::min)() <= n and n <= (std::numeric_limits<uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('U')); // uint8
|
||||
write_number(static_cast<uint8_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('I')); // int16
|
||||
write_number(static_cast<int16_t>(n));
|
||||
}
|
||||
else if (-(std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('l')); // int32
|
||||
write_number(static_cast<int32_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
|
||||
{
|
||||
oa->write_character(static_cast<CharType>('L')); // int64
|
||||
write_number(static_cast<int64_t>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: replace by exception
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// whether we can assume little endianess
|
||||
const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
|
||||
@ -13511,6 +13848,23 @@ class basic_json
|
||||
binary_writer<char>(o).write_msgpack(j);
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> to_ubjson(const basic_json& j)
|
||||
{
|
||||
std::vector<uint8_t> result;
|
||||
to_ubjson(j, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o)
|
||||
{
|
||||
binary_writer<uint8_t>(o).write_ubjson(j);
|
||||
}
|
||||
|
||||
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o)
|
||||
{
|
||||
binary_writer<char>(o).write_ubjson(j);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a JSON value from an input in CBOR format
|
||||
|
||||
@ -13705,6 +14059,19 @@ class basic_json
|
||||
return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
|
||||
}
|
||||
|
||||
static basic_json from_ubjson(detail::input_adapter i,
|
||||
const bool strict = true)
|
||||
{
|
||||
return binary_reader(i).parse_ubjson(strict);
|
||||
}
|
||||
|
||||
template<typename A1, typename A2,
|
||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
||||
static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true)
|
||||
{
|
||||
return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_ubjson(strict);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
//////////////////////////
|
||||
|
@ -39,6 +39,7 @@ SOURCES = src/unit.cpp \
|
||||
src/unit-regression.cpp \
|
||||
src/unit-serialization.cpp \
|
||||
src/unit-testsuites.cpp \
|
||||
src/unit-ubjson.cpp \
|
||||
src/unit-unicode.cpp
|
||||
|
||||
OBJECTS = $(SOURCES:.cpp=.o)
|
||||
|
275
test/data/universal-binary-json-java/CouchDB4k.formatted.json
Normal file
275
test/data/universal-binary-json-java/CouchDB4k.formatted.json
Normal file
@ -0,0 +1,275 @@
|
||||
{
|
||||
"data3":"ColreUHAtuYoUOx1N4ZloouQt2o6ugnUT6eYtS10gu7niM8i0vEiNufpk1RlMQXaHXlIwQBDsMFDFUQcFeg2vW5eD259Xm",
|
||||
"data4":"zCxriJhL726WNNTdJJzurgSA8vKT6rHA0cFCb9koZcLUMXg4rmoXVPqIHWYaCV0ovl2t6xm7I1Hm36jXpLlXEb8fRfbwBeTW2V0OAsVqYH8eAT",
|
||||
"data0":"9EVqHm5ARqcEB5jq2D14U2bCJPyBY0JWDr1Tjh8gTB0sWUNjqYiWDxFzlx6S",
|
||||
"data7":"Bi1ujcgEvfADfBeyZudE7nwxc3Ik8qpYjsJIfKmwOMEbV2L3Bi0x2tcRpGuf4fiyvIbypDvJN1PPdQtfQW1Gv6zccXHwwZwKzUq6",
|
||||
"data5":{
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
275045,
|
||||
703447,
|
||||
50156,
|
||||
685803,
|
||||
147958,
|
||||
941747,
|
||||
905651,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
],
|
||||
"float1":76.572,
|
||||
"float2":83.5299,
|
||||
"nested1":{
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
275045,
|
||||
703447,
|
||||
50156,
|
||||
685803,
|
||||
147958,
|
||||
941747,
|
||||
905651,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
],
|
||||
"floats":[
|
||||
43121609.5543,
|
||||
99454976.3019,
|
||||
32945584.756,
|
||||
18122905.9212,
|
||||
45893183.44,
|
||||
63052200.6225,
|
||||
69032152.6897,
|
||||
3748217.6946,
|
||||
75449850.474,
|
||||
37111527.415,
|
||||
84852536.859,
|
||||
32906366.487,
|
||||
27027600.417,
|
||||
63874310.5614,
|
||||
39440408.51,
|
||||
97176857.1716,
|
||||
97438252.1171,
|
||||
49728043.5056,
|
||||
40818570.245,
|
||||
41415831.8949,
|
||||
24796297.4251,
|
||||
2819085.3449,
|
||||
84263963.4848,
|
||||
74503228.6878,
|
||||
67925677.403,
|
||||
4758851.9417,
|
||||
75227407.9214,
|
||||
76946667.8403,
|
||||
72518275.9469,
|
||||
94167085.9588,
|
||||
75883067.8321,
|
||||
27389831.6101,
|
||||
57987075.5053,
|
||||
1298995.2674,
|
||||
14590614.6939,
|
||||
45292214.2242,
|
||||
3332166.364,
|
||||
53784167.729,
|
||||
25193846.1867,
|
||||
81456965.477,
|
||||
68532032.39,
|
||||
73820009.7952,
|
||||
57736110.5717,
|
||||
37304166.7363,
|
||||
20054244.864,
|
||||
29746392.7397,
|
||||
86467624.6,
|
||||
45192685.8793,
|
||||
44008816.5186,
|
||||
1861872.8736,
|
||||
14595859.467,
|
||||
87795257.6703,
|
||||
57768720.8303,
|
||||
18290154.3126,
|
||||
45893183.44,
|
||||
63052200.6225,
|
||||
69032152.6897,
|
||||
3748217.6946,
|
||||
75449850.474,
|
||||
37111527.415,
|
||||
84852536.859,
|
||||
32906366.487,
|
||||
27027600.417,
|
||||
63874310.5614,
|
||||
39440408.51,
|
||||
97176857.1716,
|
||||
97438252.1171,
|
||||
49728043.5056,
|
||||
40818570.245,
|
||||
41415831.8949,
|
||||
24796297.4251,
|
||||
2819085.3449,
|
||||
84263963.4848,
|
||||
74503228.6878,
|
||||
67925677.403,
|
||||
4758851.9417,
|
||||
75227407.9214,
|
||||
76946667.8403,
|
||||
72518275.9469,
|
||||
94167085.9588,
|
||||
75883067.8321,
|
||||
27389831.6101,
|
||||
57987075.5053,
|
||||
1298995.2674,
|
||||
80858801.2712,
|
||||
98262252.4656,
|
||||
51612877.944,
|
||||
33397812.7835,
|
||||
36089655.3049,
|
||||
50164685.8153,
|
||||
16852105.5192,
|
||||
61171929.752,
|
||||
86376339.7175,
|
||||
73009014.5521,
|
||||
7397302.331,
|
||||
34345128.9589,
|
||||
98343269.4418,
|
||||
95039116.9058,
|
||||
44833102.5752,
|
||||
51052997.8873,
|
||||
22719195.6783,
|
||||
64883244.8699
|
||||
]
|
||||
},
|
||||
"nested2":{
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
275045,
|
||||
703447,
|
||||
50156,
|
||||
685803,
|
||||
147958,
|
||||
941747,
|
||||
905651,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
],
|
||||
"float1":76.572,
|
||||
"float2":83.5299
|
||||
}
|
||||
},
|
||||
"strings":[
|
||||
"edx5XzRkPVeEW2MBQzQMcUSuMI4FntjhlJ9VGhQaBHKPEazAaT",
|
||||
"2fQUbzRUax4A",
|
||||
"jURcBZ0vrJcmf2roZUMzZJQoTsKZDIdj7KhO7itskKvM80jBU9",
|
||||
"8jKLmo3N2zYdKyTyfTczfr2x6bPaarorlnTNJ7r8lIkiZyBvrP",
|
||||
"jbUeAVOdBSPzYmYhH0sabUHUH39O5e",
|
||||
"I8yAQKZsyZhMfpzWjArQU9pQ6PfU6b14q2eWvQjtCUdgAUxFjg",
|
||||
"97N8ZmGcxRZO4ZabzRRcY4KVHqxJwQ8qY",
|
||||
"0DtY1aWXmUfJENt9rYW9",
|
||||
"DtpBUEppPwMnWexi8eIIxlXRO3GUpPgeNFG9ONpWJYvk8xBkVj",
|
||||
"YsX8V2xOrTw6LhNIMMhO4F4VXFyXUXFr66L3sTkLWgFA9NZuBV",
|
||||
"fKYYthv8iFvaYoFoYZyB",
|
||||
"zGuLsPXoJqMbO4PcePteZfDMYFXdWtvNF8WvaplXypsd6"
|
||||
],
|
||||
"data1":"9EVqHm5ARqcEB5jq21v2g0jVcG9CXB0Abk7uAF4NHYyTzeF3TnHhpZBECD14U2bCJPyBY0JWDr1Tjh8gTB0sWUNjqYiWDxFzlx6S",
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
275045,
|
||||
703447,
|
||||
50156,
|
||||
685803,
|
||||
147958,
|
||||
941747,
|
||||
905651,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
],
|
||||
"more_nested":{
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
275045,
|
||||
703447,
|
||||
50156,
|
||||
685803,
|
||||
147958,
|
||||
941747,
|
||||
905651,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
],
|
||||
"float1":76.572,
|
||||
"float2":83.5299,
|
||||
"nested1":{
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
275045,
|
||||
703447,
|
||||
50156,
|
||||
685803,
|
||||
147958,
|
||||
941747,
|
||||
905651,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
]
|
||||
},
|
||||
"nested2":{
|
||||
"strings":[
|
||||
"2fQUbzRUax4A",
|
||||
"jURcBZ0vrJcmf2roZUMzZJQoTsKZDIdj7KhO7itskKvM80jBU9",
|
||||
"8jKLmo3N2zYdKyTyfTczfr2x6bPaarorlnTNJ7r8lIkiZyBvrP",
|
||||
"jbUeAVOdBSPzYmYhH0sabUHUH39O5e",
|
||||
"I8yAQKZsyZhMfpzWjArQU9pQ6PfU6b14q2eWvQjtCUdgAUxFjg",
|
||||
"97N8ZmGcxRZO4ZabzRRcY4KVHqxJwQ8qY",
|
||||
"0DtY1aWXmUfJENt9rYW9",
|
||||
"DtpBUEppPwMnWexi8eIIxlXRO3GUpPgeNFG9ONpWJYvk8xBkVj",
|
||||
"YsX8V2xOrTw6LhNIMMhO4F4VXFyXUXFr66L3sTkLWgFA9NZuBV",
|
||||
"fKYYthv8iFvaYoFoYZyB",
|
||||
"zGuLsPXoJqMbO4PcePteZfDMYFXdWtvNF8WvaplXypsd6"
|
||||
],
|
||||
"integers":[
|
||||
756509,
|
||||
116117,
|
||||
776378,
|
||||
57367,
|
||||
530248,
|
||||
312888,
|
||||
740951,
|
||||
988947,
|
||||
450154
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
BIN
test/data/universal-binary-json-java/CouchDB4k.ubj
Normal file
BIN
test/data/universal-binary-json-java/CouchDB4k.ubj
Normal file
Binary file not shown.
202
test/data/universal-binary-json-java/LICENSE
Normal file
202
test/data/universal-binary-json-java/LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,34 @@
|
||||
{
|
||||
"Media":{
|
||||
"uri":"http://javaone.com/keynote.mpg",
|
||||
"title":"Javaone Keynote",
|
||||
"width":640,
|
||||
"height":480,
|
||||
"format":"video/mpg4",
|
||||
"duration":18000000,
|
||||
"size":58982400,
|
||||
"bitrate":262144,
|
||||
"persons":[
|
||||
"Bill Gates",
|
||||
"Steve Jobs"
|
||||
],
|
||||
"player":"JAVA",
|
||||
"copyright":null
|
||||
},
|
||||
"Images":[
|
||||
{
|
||||
"uri":"http://javaone.com/keynote_large.jpg",
|
||||
"title":"Javaone Keynote",
|
||||
"width":1024,
|
||||
"height":768,
|
||||
"size":"LARGE"
|
||||
},
|
||||
{
|
||||
"uri":"http://javaone.com/keynote_small.jpg",
|
||||
"title":"Javaone Keynote",
|
||||
"width":320,
|
||||
"height":240,
|
||||
"size":"SMALL"
|
||||
}
|
||||
]
|
||||
}
|
BIN
test/data/universal-binary-json-java/MediaContent.ubj
Normal file
BIN
test/data/universal-binary-json-java/MediaContent.ubj
Normal file
Binary file not shown.
357
test/data/universal-binary-json-java/README
Normal file
357
test/data/universal-binary-json-java/README
Normal file
@ -0,0 +1,357 @@
|
||||
Universal Binary JSON Java Library
|
||||
http://ubjson.org
|
||||
|
||||
|
||||
About this project...
|
||||
---------------------
|
||||
This code base is actively under development and implements the latest
|
||||
specification of Universal Binary JSON (Draft 8).
|
||||
|
||||
I/O is handled through the following core classes:
|
||||
|
||||
* UBJOutputStream
|
||||
* UBJInputStream
|
||||
* UBJInputStreamParser
|
||||
|
||||
Additionally, if you are working with Java's NIO and need byte[]-based
|
||||
results, you can wrap any of the above I/O classes around one of the highly
|
||||
optimized custom byte[]-stream impls:
|
||||
|
||||
* ByteArrayInputStream (optimized for reuse, not from JDK)
|
||||
* ByteArrayOutputStream (optimized for reuse, not from JDK)
|
||||
|
||||
If you are working with NIO and want maximum performance by using (and reusing)
|
||||
direct ByteBuffers along with the UBJSON stream impls, take a look at the:
|
||||
|
||||
* ByteBufferInputStream
|
||||
* ByteBufferOutputStream
|
||||
|
||||
classes. You can wrap any ByteBuffer source or destination with this stream type,
|
||||
then wrap that stream type with a UBJSON stream impl and utilize the full
|
||||
potential of Java's NIO with Universal Binary JSON without giving yourself an
|
||||
ulcer.
|
||||
|
||||
This allows you to re-use the streams over and over again in a pool of reusable
|
||||
streams for high-performance I/O with no object creation and garbage collection
|
||||
overhead; a perfect match for high frequency NIO-based communication.
|
||||
|
||||
All of the core I/O classes have been stable for a while, with tweaks to make the
|
||||
performance tighter and the error messages more informative over the last few
|
||||
months.
|
||||
|
||||
More Java-convenient reflection-based I/O classes are available in the
|
||||
org.ubjson.io.reflect package, but they are under active development.
|
||||
|
||||
There are other efforts (like utilities) in other sub portions of the source
|
||||
tree. This project intends to eventually contain a multitude of UBJSON
|
||||
abstraction layers, I/O methods and utilities.
|
||||
|
||||
|
||||
Changelog
|
||||
---------
|
||||
02-10-12
|
||||
* Added ByteBuffer input and output stream impls as compliments to the
|
||||
re-usable byte[] stream impls.
|
||||
|
||||
Provides a fast translation layer between standard Java stream-IO and the
|
||||
new Buffer-based I/O in NIO (including transparent support for using
|
||||
ultra-fast direct ByteBuffers).
|
||||
|
||||
* Optimized some of the read/write methods by removing unnecessary bounds
|
||||
checks that are done by subsequent Input or Output stream impls themselves.
|
||||
|
||||
02-09-12
|
||||
* Fixed bug with readHugeAsBigInteger returning an invalid value and not
|
||||
treating the underlying bytes as a string-encoded value.
|
||||
|
||||
* Removed implicit buffer.flip() at the end of StreamDecoder; there is no
|
||||
way to know what the caller had planned for the buffer before reading all
|
||||
the data back out. Also the flip was in the wrong place and in the case of
|
||||
an empty decode request (length=0) the flip would not have been performed,
|
||||
providing the caller with a "full" buffer of nothing.
|
||||
|
||||
* Rewrote all readHugeXXX method impls; now huge's can be read in as a
|
||||
simple Number (BigInteger or BigDecimal) as well as raw bytes and even
|
||||
decoded chars. Additionally the methods can even accept and use existing
|
||||
buffers to write into to allow for tighter optimizations.
|
||||
|
||||
* Rewrote all readStringXXX methods using the same optimizations and
|
||||
flexibility that readHuge methods now use.
|
||||
|
||||
02-07-12
|
||||
More Memory and CPU optimizations across all the I/O impls.
|
||||
|
||||
* StreamDecoder was rewritten to no longer create a ByteBuffer on every
|
||||
invocation and instead re-use the same one to decode from on every single call.
|
||||
|
||||
* StreamDecoder now requires the call to pass in a CharBuffer instance to hold
|
||||
the result of the decode operation. This avoids the creation of a CharBuffer
|
||||
and allows for large-scale optimization by re-using existing buffers between
|
||||
calls.
|
||||
|
||||
* StreamEncoder was rewritten to no longer create a ByteBuffer on every
|
||||
invocation either and now re-uses the same single instance over and over
|
||||
again.
|
||||
|
||||
* UBJOutputStream writeHuge and writeString series of methods were all
|
||||
rewritten to accept a CharBuffer in the rawest form (no longer char[]) to stop
|
||||
hiding the fact that the underlying encode operation required one.
|
||||
|
||||
This gives the caller an opportunity to cache and re-use CharBuffers over
|
||||
and over again if they can; otherwise this just pushes the CharBuffer.wrap()
|
||||
call up to the caller instead of hiding it secretly in the method impl under
|
||||
the guise of accepting a raw char[] (that it couldn't use directly).
|
||||
|
||||
For callers that can re-use buffers, this will lead to big performance gains
|
||||
now that were previously impossible.
|
||||
|
||||
* UBJInputStream added readHuge and readString methods that accept an existing
|
||||
CharBuffer argument to make use of the optimizations made in the Stream encoder
|
||||
and decoder impls.
|
||||
|
||||
01-15-12
|
||||
Huge performance boost for deserialization!
|
||||
|
||||
StreamDecoder previously used separate read and write buffers for decoding
|
||||
bytes to chars including the resulting char[] that was returned to the caller.
|
||||
This design required at least 1 full array copy before returning a result in
|
||||
the best case and 2x full array copies before returning the result in the
|
||||
worst case.
|
||||
|
||||
The rewrite removed the need for a write buffer entire as well as ALL array
|
||||
copies; in the best OR worse case they never occur anymore.
|
||||
|
||||
Raw performance boost of roughly 25% in all UBJ I/O classes as a result.
|
||||
|
||||
12-01-11 through 01-24-12
|
||||
A large amount of work has continued on the core I/O classes (stream impls)
|
||||
to help make them not only faster and more robust, but also more helpful.
|
||||
When errors are encountered in the streams, they are reported along with the
|
||||
stream positions. This is critical for debugging problems with corrupt
|
||||
formats.
|
||||
|
||||
Also provided ByteArray I/O stream classes that have the potential to provide
|
||||
HUGE performance boosts for high frequency systems.
|
||||
|
||||
Both these classes (ByteArrayInputStream and ByteArrayOutputStream) are
|
||||
reusable and when wrapped by a UBJInputStream or UBJOutputStream, the top
|
||||
level UBJ streams implicitly become reusable as well.
|
||||
|
||||
Reusing the streams not only saves on object creation/GC cleanup but also
|
||||
allows the caller to re-use the temporary byte[] used to translate to and
|
||||
from the UBJ format, avoiding object churn entirely!
|
||||
|
||||
This optimized design was chosen to be intentionally performant when combined
|
||||
with NIO implementations as the ByteBuffer's can be used to wrap() existing
|
||||
outbound buffers (avoiding the most expensive part of a buffer) or use
|
||||
array() to get access to the underlying buffer that needs to be written to
|
||||
the stream.
|
||||
|
||||
In the case of direct ByteBuffers, there is no additional overhead added
|
||||
because the calls to get or put are required anyway to pull or push the
|
||||
values from the native memory location.
|
||||
|
||||
This approach allows the fastest implementation of Universal Binary JSON
|
||||
I/O possible in the JVM whether you are using the standard IO (stream)
|
||||
classes or the NIO (ByteBuffer) classes in the JDK.
|
||||
|
||||
Some ancillary work on UBJ-based command line utilities (viewers, converters,
|
||||
etc.) has begun as well.
|
||||
|
||||
11-28-11
|
||||
* Fixed UBJInputStreamParser implementation; nextType correctly implements
|
||||
logic to skip existing element (if called back to back) as well as validate
|
||||
the marker type it encounters before returning it to the caller.
|
||||
|
||||
* Modified IObjectReader contract; a Parser implementation is required to
|
||||
make traversing the UBJ stream possible without knowing what type of element
|
||||
is next.
|
||||
|
||||
11-27-11
|
||||
* Streamlined ByteArrayOutputStream implementation to ensure the capacity
|
||||
of the underlying byte[] is never grown unless absolutely necessary.
|
||||
|
||||
* Rewrote class Javadoc for ByteArrayOutputStream to include a code snippet
|
||||
on how to use it.
|
||||
|
||||
11-26-11
|
||||
* Fixed major bug in how 16, 32 and 64-bit integers are re-assembled when
|
||||
read back from binary representations.
|
||||
|
||||
* Added a numeric test to specifically catch this error if it ever pops up
|
||||
again.
|
||||
|
||||
* Optimized reading and writing of numeric values in Input and Output
|
||||
stream implementations.
|
||||
|
||||
* Optimized ObjectWriter implementation by streamlining the numeric read/write
|
||||
logic and removing the sub-optimal force-compression of on-disk storage.
|
||||
|
||||
* Fixed ObjectWriter to match exactly with the output written by
|
||||
UBJOutputStream.
|
||||
|
||||
* Normalized all testing between I/O classes so they use the same classes
|
||||
to ensure parity.
|
||||
|
||||
11-10-11
|
||||
* DRAFT 8 Spec Support Added.
|
||||
|
||||
* Added support for the END marker (readEnd) to the InputStreams which is
|
||||
required for proper unbounded-container support.
|
||||
|
||||
* Added support for the END marker (writeEnd) to UBJOutputStream.
|
||||
|
||||
UBJInputStreamParser must be used for properly support unbounded-containers
|
||||
because you never know when the 'E' will be encountered marking the end;
|
||||
so the caller needs to pay attention to the type marker that nextType()
|
||||
returns and respond accordingly.
|
||||
|
||||
* Added readHugeAsBytes to InputStream implementations, allowing the bytes
|
||||
used to represent a HUGE to be read in their raw form with no decoding.
|
||||
|
||||
This can save on processing as BigInteger and BigDecimal do their own decoding
|
||||
of byte[] directly.
|
||||
|
||||
* Added readHugeAsChars to InputStream implementations, allowing a HUGE
|
||||
value to be read in as a raw char[] without trying to decode it to a
|
||||
BigInteger or BigDecimal.
|
||||
|
||||
* Added writeHuge(char[]) to support writing out HUGE values directly from
|
||||
their raw char[] form without trying to decode from a BigInteger or
|
||||
BigDecimal.
|
||||
|
||||
* readArrayLength and readObjectLenght were modified to return -1 when an
|
||||
unbounded container length is encountered (255).
|
||||
|
||||
* Fixed UBJInputStreamParser.nextType to correctly skip past any NOOP
|
||||
markers found in the underlying stream before returning a valid next type.
|
||||
|
||||
* Normalized all reading of "next byte" to the singular
|
||||
UBJInputStream.nextMarker method -- correctly skips over NOOP until end of
|
||||
stream OR until the next valid marker byte, then returns it.
|
||||
|
||||
* Modified readNull behavior to have no return type. It is already designed
|
||||
to throw an exception when 'NULL' isn't found, no need for the additional
|
||||
return type.
|
||||
|
||||
* Began work on a simple abstract representation of the UBJ data types as
|
||||
objects that can be assembled into maps and lists and written/read easily
|
||||
using the IO package.
|
||||
|
||||
This is intended to be a higher level of abstraction than the IO streams,
|
||||
but lower level (and faster) than the reflection-based work that inspects
|
||||
user-provided classes.
|
||||
|
||||
* Refactored StreamDecoder and StreamEncoder into the core IO package,
|
||||
because they are part of core IO.
|
||||
|
||||
* Refactored StreamParser into the io.parser package to more clearly denote
|
||||
its relationship to the core IO classes. It is a slightly higher level
|
||||
abstraction ontop of the core IO, having it along side the core IO classes
|
||||
while .reflect was a subpackage was confusing and suggested that
|
||||
StreamParser was somehow intended as a swapable replacement for
|
||||
UBJInputStream which is not how it is intended to be used.
|
||||
|
||||
* Refactored org.ubjson.reflect to org.ubjson.io.reflect to more correctly
|
||||
communicate the relationship -- the reflection-based classes are built on
|
||||
the core IO classes and are just a higher abstraction to interact with UBJSON
|
||||
with.
|
||||
|
||||
* Renamed IDataType to IMarkerType to follow the naming convention for the
|
||||
marker bytes set forth by the spec doc.
|
||||
|
||||
|
||||
10-14-11
|
||||
* ObjectWriter rewritten and works correctly. Tested with the example test
|
||||
data and wrote out the compressed and uncompressed formats files correctly
|
||||
from their original object representation.
|
||||
|
||||
* Added support for reading and writing huge values as BigInteger as well
|
||||
as BigDecimal.
|
||||
|
||||
* Added automatic numeric storage compression support to ObjectWriter - based
|
||||
on the numeric value (regardless of type) the value will be stored as the
|
||||
smallest possible representation in the UBJ format if requested.
|
||||
|
||||
* Added mapping support for BigDecimal, BigInteger, AtomicInteger and
|
||||
AtomicLong to ObjectWriter.
|
||||
|
||||
* Added readNull and readBoolean to the UBJInputStream and
|
||||
UBJInputStreamParser implementations to make the API feel complete and feel
|
||||
more natural to use.
|
||||
|
||||
10-10-11
|
||||
* com.ubjson.io AND com.ubjson.io.charset are finalized against the
|
||||
Draft 8 specification.
|
||||
|
||||
* The lowest level UBJInput/OuputStream classes were tightened up to run as
|
||||
fast as possible showing an 800ns-per-op improvement in speed.
|
||||
|
||||
* Profiled core UBJInput/OuputStream classes using HPROF for a few million
|
||||
iterations and found no memory leaks and no performance traps; everything at
|
||||
that low level is as tight as it can be.
|
||||
|
||||
* Stream-parsing facilities were moved out of the overloaded UBJInputStream
|
||||
class and into their own subclass called UBJInputStreamParser which operates
|
||||
exactly like a pull-parsing scenario (calling nextType then switching on the
|
||||
value and pulling the appropriate value out of the stream).
|
||||
|
||||
* More example testing/benchmarking data checked into /test/java/com/ubjson/data
|
||||
|
||||
Will begin reworking the Reflection based Object mapping in the
|
||||
org.ubjson.reflect package now that the core IO classes are finalized.
|
||||
|
||||
* Removed all old scratch test files from the org.ubjson package, this was
|
||||
confusing.
|
||||
|
||||
09-27-11
|
||||
* Initial check-in of core IO classes to read/write spec.
|
||||
|
||||
|
||||
Status
|
||||
------
|
||||
Using the standard UBJInputStream, UBJInputStreamParser and UBJOutputStream
|
||||
implementations to manually read/write UBJ objects is stable and tuned for
|
||||
optimal performance.
|
||||
|
||||
Automatic mapping of objects to/from UBJ format via the reflection-based
|
||||
implementation is not tuned yet. Writing is implemented, but not tuned for
|
||||
optimal performance and reading still has to be written.
|
||||
|
||||
* org.ubjson.io - STABLE
|
||||
* org.ubjson.io.parser - STABLE
|
||||
* org.ubjson.io.reflect - ALPHA
|
||||
* org.ubjson.model - BETA
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
This library is released under the Apache 2 License. See LICENSE.
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
This project represents (the official?) Java implementations of the
|
||||
Universal Binary JSON specification: http://ubjson.org
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
Comming soon...
|
||||
|
||||
|
||||
Performance
|
||||
-----------
|
||||
Comming soon...
|
||||
|
||||
|
||||
Reference
|
||||
---------
|
||||
Universal Binary JSON Specification - http://ubjson.org
|
||||
JSON Specification - http://json.org
|
||||
|
||||
|
||||
Contact
|
||||
-------
|
||||
If you have questions, comments or bug reports for this software please contact
|
||||
us at: software@thebuzzmedia.com
|
@ -0,0 +1,80 @@
|
||||
{
|
||||
"id_str":"121769183821312000",
|
||||
"retweet_count":0,
|
||||
"in_reply_to_screen_name":null,
|
||||
"in_reply_to_user_id":null,
|
||||
"truncated":false,
|
||||
"retweeted":false,
|
||||
"possibly_sensitive":false,
|
||||
"in_reply_to_status_id_str":null,
|
||||
"entities":{
|
||||
"urls":[
|
||||
{
|
||||
"url":"http:\/\/t.co\/wtioKkFS",
|
||||
"display_url":"dlvr.it\/pWQy2",
|
||||
"indices":[
|
||||
33,
|
||||
53
|
||||
],
|
||||
"expanded_url":"http:\/\/dlvr.it\/pWQy2"
|
||||
}
|
||||
],
|
||||
"hashtags":[
|
||||
|
||||
],
|
||||
"user_mentions":[
|
||||
|
||||
]
|
||||
},
|
||||
"geo":null,
|
||||
"place":null,
|
||||
"coordinates":null,
|
||||
"created_at":"Thu Oct 06 02:10:10 +0000 2011",
|
||||
"in_reply_to_user_id_str":null,
|
||||
"user":{
|
||||
"id_str":"77029015",
|
||||
"profile_link_color":"009999",
|
||||
"protected":false,
|
||||
"url":"http:\/\/www.techday.co.nz\/",
|
||||
"screen_name":"techdaynz",
|
||||
"statuses_count":5144,
|
||||
"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1479058408\/techday_48_normal.jpg",
|
||||
"name":"TechDay",
|
||||
"default_profile_image":false,
|
||||
"default_profile":false,
|
||||
"profile_background_color":"131516",
|
||||
"lang":"en",
|
||||
"profile_background_tile":false,
|
||||
"utc_offset":43200,
|
||||
"description":"",
|
||||
"is_translator":false,
|
||||
"show_all_inline_media":false,
|
||||
"contributors_enabled":false,
|
||||
"profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/75893948\/Techday_Background.jpg",
|
||||
"created_at":"Thu Sep 24 20:02:01 +0000 2009",
|
||||
"profile_sidebar_fill_color":"efefef",
|
||||
"follow_request_sent":false,
|
||||
"friends_count":3215,
|
||||
"followers_count":3149,
|
||||
"time_zone":"Auckland",
|
||||
"favourites_count":0,
|
||||
"profile_sidebar_border_color":"eeeeee",
|
||||
"profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1479058408\/techday_48_normal.jpg",
|
||||
"following":false,
|
||||
"geo_enabled":false,
|
||||
"notifications":false,
|
||||
"profile_use_background_image":true,
|
||||
"listed_count":151,
|
||||
"verified":false,
|
||||
"profile_text_color":"333333",
|
||||
"location":"Ponsonby, Auckland, NZ",
|
||||
"id":77029015,
|
||||
"profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/75893948\/Techday_Background.jpg"
|
||||
},
|
||||
"contributors":null,
|
||||
"source":"\u003Ca href=\"http:\/\/dlvr.it\" rel=\"nofollow\"\u003Edlvr.it\u003C\/a\u003E",
|
||||
"in_reply_to_status_id":null,
|
||||
"favorited":false,
|
||||
"id":121769183821312000,
|
||||
"text":"Apple CEO's message to employees http:\/\/t.co\/wtioKkFS"
|
||||
}
|
BIN
test/data/universal-binary-json-java/TwitterTimeline.ubj
Normal file
BIN
test/data/universal-binary-json-java/TwitterTimeline.ubj
Normal file
Binary file not shown.
1
test/data/universal-binary-json-java/url.txt
Normal file
1
test/data/universal-binary-json-java/url.txt
Normal file
@ -0,0 +1 @@
|
||||
https://github.com/ubjson/universal-binary-json-java/tree/master/src/test/resources/org/ubjson
|
1593
test/src/unit-ubjson.cpp
Normal file
1593
test/src/unit-ubjson.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user