-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathencoder_string.cc
More file actions
150 lines (129 loc) · 5.35 KB
/
Copy pathencoder_string.cc
File metadata and controls
150 lines (129 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <sourcemeta/jsonbinpack/runtime_encoder.h>
#include <cassert> // assert
#include <cstdint> // std::uint8_t, std::uint16_t
#include <string> // std::stoul
namespace sourcemeta::jsonbinpack {
auto Encoder::UTF8_STRING_NO_LENGTH(const sourcemeta::core::JSON &document,
const struct UTF8_STRING_NO_LENGTH &options)
-> void {
assert(document.is_string());
const sourcemeta::core::JSON::String &value{document.to_string()};
this->put_string_utf8(value, options.size);
}
auto Encoder::FLOOR_VARINT_PREFIX_UTF8_STRING_SHARED(
const sourcemeta::core::JSON &document,
const struct FLOOR_VARINT_PREFIX_UTF8_STRING_SHARED &options) -> void {
assert(document.is_string());
const sourcemeta::core::JSON::String &value{document.to_string()};
const auto size{value.size()};
assert(document.byte_size() == size);
const auto shared{this->cache_.find(value, Cache::Type::Standalone)};
// (1) Write 0x00 if shared, else do nothing
if (shared.has_value()) {
this->put_byte(0);
}
// (2) Write length of the string + 1 (so it will never be zero)
this->put_varint(size - options.minimum + 1);
// (3) Write relative offset if shared, else write plain string
if (shared.has_value()) {
this->put_varint(this->position() - shared.value());
} else {
this->cache_.record(value, this->position(), Cache::Type::Standalone);
this->put_string_utf8(value, size);
}
}
auto Encoder::ROOF_VARINT_PREFIX_UTF8_STRING_SHARED(
const sourcemeta::core::JSON &document,
const struct ROOF_VARINT_PREFIX_UTF8_STRING_SHARED &options) -> void {
assert(document.is_string());
const sourcemeta::core::JSON::String &value{document.to_string()};
const auto size{value.size()};
assert(document.byte_size() == size);
assert(size <= options.maximum);
const auto shared{this->cache_.find(value, Cache::Type::Standalone)};
// (1) Write 0x00 if shared, else do nothing
if (shared.has_value()) {
this->put_byte(0);
}
// (2) Write length of the string + 1 (so it will never be zero)
this->put_varint(options.maximum - size + 1);
// (3) Write relative offset if shared, else write plain string
if (shared.has_value()) {
this->put_varint(this->position() - shared.value());
} else {
this->cache_.record(value, this->position(), Cache::Type::Standalone);
this->put_string_utf8(value, size);
}
}
auto Encoder::BOUNDED_8BIT_PREFIX_UTF8_STRING_SHARED(
const sourcemeta::core::JSON &document,
const struct BOUNDED_8BIT_PREFIX_UTF8_STRING_SHARED &options) -> void {
assert(document.is_string());
const sourcemeta::core::JSON::String &value{document.to_string()};
const auto size{value.size()};
assert(document.byte_size() == size);
assert(options.minimum <= options.maximum);
assert(sourcemeta::core::is_byte(options.maximum - options.minimum + 1));
assert(sourcemeta::core::is_within(size, options.minimum, options.maximum));
const auto shared{this->cache_.find(value, Cache::Type::Standalone)};
// (1) Write 0x00 if shared, else do nothing
if (shared.has_value()) {
this->put_byte(0);
}
// (2) Write length of the string + 1 (so it will never be zero)
this->put_byte(static_cast<std::uint8_t>(size - options.minimum + 1));
// (3) Write relative offset if shared, else write plain string
if (shared.has_value()) {
this->put_varint(this->position() - shared.value());
} else {
this->cache_.record(value, this->position(), Cache::Type::Standalone);
this->put_string_utf8(value, size);
}
}
auto Encoder::RFC3339_DATE_INTEGER_TRIPLET(
const sourcemeta::core::JSON &document,
const struct RFC3339_DATE_INTEGER_TRIPLET &) -> void {
assert(document.is_string());
const auto &value{document.to_string()};
assert(value.size() == 10);
assert(document.size() == value.size());
// As according to RFC3339: Internet Protocols MUST
// generate four digit years in dates.
const std::uint16_t year{
static_cast<std::uint16_t>(std::stoul(value.substr(0, 4)))};
const std::uint8_t month{
static_cast<std::uint8_t>(std::stoul(value.substr(5, 2)))};
const std::uint8_t day{
static_cast<std::uint8_t>(std::stoul(value.substr(8, 2)))};
assert(month >= 1 && month <= 12);
assert(day >= 1 && day <= 31);
this->put_word(year);
this->put_byte(month);
this->put_byte(day);
}
auto Encoder::PREFIX_VARINT_LENGTH_STRING_SHARED(
const sourcemeta::core::JSON &document,
const struct PREFIX_VARINT_LENGTH_STRING_SHARED &) -> void {
assert(document.is_string());
const sourcemeta::core::JSON::String &value{document.to_string()};
const auto shared{
this->cache_.find(value, Cache::Type::PrefixLengthVarintPlusOne)};
if (shared.has_value()) {
const auto new_offset{this->position()};
this->put_byte(0);
this->put_varint(this->position() - shared.value());
// Bump the context cache for locality purposes
this->cache_.record(value, new_offset,
Cache::Type::PrefixLengthVarintPlusOne);
} else {
const auto size{value.size()};
assert(document.byte_size() == size);
this->cache_.record(value, this->position(),
Cache::Type::PrefixLengthVarintPlusOne);
this->put_varint(size + 1);
// Also record a standalone variant of it
this->cache_.record(value, this->position(), Cache::Type::Standalone);
this->put_string_utf8(value, size);
}
}
} // namespace sourcemeta::jsonbinpack