Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions core/include/join/view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,16 @@ namespace join
* @brief get the first element.
* @return pointer to the first element.
*/
constexpr Type* data () const noexcept
constexpr Type* data () noexcept
{
return _data;
}

/**
* @brief get the first element.
* @return pointer to the first element.
*/
constexpr const Type* data () const noexcept
{
return _data;
}
Expand All @@ -95,7 +104,16 @@ namespace join
* @brief get an iterator to the first element.
* @return iterator to the first element.
*/
constexpr Type* begin () const noexcept
constexpr Type* begin () noexcept
{
return _data;
}

/**
* @brief get an iterator to the first element.
* @return iterator to the first element.
*/
constexpr const Type* begin () const noexcept
{
return _data;
}
Expand All @@ -104,17 +122,36 @@ namespace join
* @brief get an iterator past the last element.
* @return iterator past the last element.
*/
constexpr Type* end () const noexcept
constexpr Type* end () noexcept
{
return _data + _size;
}

/**
* @brief get an iterator past the last element.
* @return iterator past the last element.
*/
constexpr const Type* end () const noexcept
{
return _data + _size;
}

/**
* @brief access an element.
* @param pos element position.
* @return element.
*/
constexpr Type& operator[] (size_t pos) noexcept
{
return _data[pos];
}

/**
* @brief access an element.
* @param pos element position.
* @return element.
*/
constexpr Type& operator[] (size_t pos) const noexcept
constexpr const Type& operator[] (size_t pos) const noexcept
{
return _data[pos];
}
Expand Down
16 changes: 16 additions & 0 deletions core/tests/view_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ TEST (View, data)
int values[] = {1, 2, 3};
EXPECT_EQ (View<int> ().data (), nullptr);
EXPECT_EQ (View<int> (values, 3).data (), values);

const View<int> constant (values, 3);
static_assert (std::is_same_v<decltype (constant.data ()), const int*>);
EXPECT_EQ (constant.data (), values);
}

/**
Expand Down Expand Up @@ -100,6 +104,10 @@ TEST (View, begin)
View<int> view (values, 3);
EXPECT_EQ (view.begin (), values);
EXPECT_EQ (*view.begin (), 1);

const View<int> constant (values, 3);
static_assert (std::is_same_v<decltype (constant.begin ()), const int*>);
EXPECT_EQ (constant.begin (), values);
}

/**
Expand All @@ -111,6 +119,10 @@ TEST (View, end)
View<int> view (values, 3);
EXPECT_EQ (view.end (), values + 3);

const View<int> constant (values, 3);
static_assert (std::is_same_v<decltype (constant.end ()), const int*>);
EXPECT_EQ (constant.end (), values + 3);

int sum = 0;
for (int value : view)
{
Expand All @@ -130,6 +142,10 @@ TEST (View, at)
EXPECT_EQ (view[2], 3);
view[1] = 5;
EXPECT_EQ (values[1], 5);

const View<int> constant (values, 3);
static_assert (std::is_same_v<decltype (constant[1]), const int&>);
EXPECT_EQ (constant[1], 5);
}

/**
Expand Down
1 change: 0 additions & 1 deletion data/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ set(PUBLIC_HEADERS
)

set(SOURCES
src/value.cpp
src/sax_error.cpp
src/json.cpp
src/zstream.cpp
Expand Down
79 changes: 37 additions & 42 deletions data/include/join/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,8 +499,8 @@ namespace join
* @param object object to write.
* @return object members in insertion order.
*/
template <JsonWriteMode Mode = WriteMode>
const Object& members (const Object& object) const noexcept
template <typename Type, JsonWriteMode Mode = WriteMode>
const View<Type>& members (const View<Type>& object) const noexcept
requires (Mode == JsonWriteMode::None)
{
return object;
Expand All @@ -511,12 +511,12 @@ namespace join
* @param object object to write.
* @return sorted object members.
*/
template <JsonWriteMode Mode = WriteMode>
std::vector<std::reference_wrapper<const Member>> members (const Object& object) const
template <typename Type, JsonWriteMode Mode = WriteMode>
std::vector<std::reference_wrapper<const Type>> members (const View<Type>& object) const
requires (Mode == JsonWriteMode::Canonical)
{
std::vector<std::reference_wrapper<const Member>> sorted (object.begin (), object.end ());
std::sort (sorted.begin (), sorted.end (), [] (const Member& a, const Member& b) {
std::vector<std::reference_wrapper<const Type>> sorted (object.begin (), object.end ());
std::sort (sorted.begin (), sorted.end (), [] (const Type& a, const Type& b) {
if (!a.first.isString () || !b.first.isString ())
{
return !a.first.isString () && b.first.isString ();
Expand Down Expand Up @@ -783,27 +783,32 @@ namespace join
1000000000000000000ULL,
10000000000000000000ULL};

uint64_t high = value / 100000000;
uint64_t top = high / 100000000;
uint32_t mid = static_cast<uint32_t> (high - top * 100000000);
uint32_t low = static_cast<uint32_t> (value - high * 100000000);

char buffer[40];
std::memcpy (buffer, &details::digitPairs[(top / 100) * 2], 2);
std::memcpy (buffer + 2, &details::digitPairs[(top % 100) * 2], 2);
std::memcpy (buffer + 4, &details::digitPairs[(mid / 1000000) * 2], 2);
std::memcpy (buffer + 6, &details::digitPairs[(mid / 10000 % 100) * 2], 2);
std::memcpy (buffer + 8, &details::digitPairs[(mid / 100 % 100) * 2], 2);
std::memcpy (buffer + 10, &details::digitPairs[(mid % 100) * 2], 2);
std::memcpy (buffer + 12, &details::digitPairs[(low / 1000000) * 2], 2);
std::memcpy (buffer + 14, &details::digitPairs[(low / 10000 % 100) * 2], 2);
std::memcpy (buffer + 16, &details::digitPairs[(low / 100 % 100) * 2], 2);
std::memcpy (buffer + 18, &details::digitPairs[(low % 100) * 2], 2);

size_t length = ((64 - __builtin_clzll (value | 1)) * 1233) >> 12;
length += (value >= pow10[length]) + (value == 0);

appendDigits (buffer + 20 - length, length);
if (JOIN_UNLIKELY (sizeof (_buffer) - _size < 20))
{
flush ();
}

char* out = _buffer + _size + length;
while (value >= 100)
{
out -= 2;
std::memcpy (out, &details::digitPairs[(value % 100) * 2], 2);
value /= 100;
}

if (value >= 10)
{
std::memcpy (out - 2, &details::digitPairs[value * 2], 2);
}
else
{
*(out - 1) = static_cast<char> ('0' + value);
}

_size += length;
}

/**
Expand Down Expand Up @@ -931,21 +936,6 @@ namespace join
_size += size;
}

/**
* @brief append the digits of a number, read 20 bytes at a time.
* @param digits digits followed by enough readable bytes to read 20.
* @param length number of digits.
*/
inline void appendDigits (const char* digits, size_t length)
{
if (JOIN_UNLIKELY (sizeof (_buffer) - _size < 20))
{
flush ();
}
std::memcpy (_buffer + _size, digits, 20);
_size += length;
}

/**
* @brief write comma.
*/
Expand Down Expand Up @@ -1299,10 +1289,15 @@ namespace join
* @param value value receiving the document.
* @return 0 on success, -1 otherwise.
*/
template <typename ProbeType>
int read (ProbeType& document, Value& value)
template <typename ProbeType, typename Allocator>
int read (ProbeType& document, BasicValue<Allocator>& value)
{
return read (document, ValueBuilder (value));
int result = read (document, ValueBuilder (value));
if (JOIN_UNLIKELY (result != 0))
{
value = nullptr;
}
return result;
}

/**
Expand Down
31 changes: 25 additions & 6 deletions data/include/join/pack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,8 @@ namespace join
* @param object object to write.
* @return object members in insertion order.
*/
const Object& members (const Object& object) const noexcept
template <typename Type>
const View<Type>& members (const View<Type>& object) const noexcept
{
return object;
}
Expand Down Expand Up @@ -827,10 +828,15 @@ namespace join
* @param value value receiving the document.
* @return 0 on success, -1 otherwise.
*/
template <typename ProbeType>
int read (ProbeType& document, Value& value)
template <typename ProbeType, typename Allocator>
int read (ProbeType& document, BasicValue<Allocator>& value)
{
return read (document, ValueBuilder (value));
int result = read (document, ValueBuilder (value));
if (JOIN_UNLIKELY (result != 0))
{
value = nullptr;
}
return result;
}

/**
Expand Down Expand Up @@ -971,7 +977,7 @@ namespace join
* @return 0 on success, -1 otherwise.
*/
template <typename ProbeType, typename Handler>
int readArray (ProbeType& document, Handler& handler, size_t depth)
__attribute__ ((noinline)) int readArray (ProbeType& document, Handler& handler, size_t depth)
{
if (JOIN_UNLIKELY (depth == saxMaxDepth))
{
Expand Down Expand Up @@ -1026,7 +1032,7 @@ namespace join
* @return 0 on success, -1 otherwise.
*/
template <typename ProbeType, typename Handler>
int readObject (ProbeType& document, Handler& handler, size_t depth)
__attribute__ ((noinline)) int readObject (ProbeType& document, Handler& handler, size_t depth)
{
if (JOIN_UNLIKELY (depth == saxMaxDepth))
{
Expand Down Expand Up @@ -1161,6 +1167,19 @@ namespace join
len = static_cast<uint8_t> (document.get ()) & ~0xa0u;
}

if constexpr (std::is_same_v<ProbeType, dconv::StringProbe>)
{
if (JOIN_UNLIKELY (static_cast<size_t> (document.end () - document.tell ()) < len))
{
join::lastError = make_error_code (SaxErrc::Truncated);
return -1;
}

std::string_view output (document.tell (), len);
document.seek (document.tell () + len);
return isKey ? handler.setKey (output) : handler.setString (output);
}

thread_local std::string cache;
std::string output = std::move (cache);
output.clear ();
Expand Down
3 changes: 2 additions & 1 deletion data/include/join/sax.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ namespace join
* @param object object to write.
* @return object members in insertion order.
*/
const Object& members (const Object& object) const noexcept
template <typename Type>
const View<Type>& members (const View<Type>& object) const noexcept
{
return object;
}
Expand Down
Loading
Loading