Skip to content

Commit

Permalink
Use CRTP
Browse files Browse the repository at this point in the history
  • Loading branch information
Cuda-Chen committed Jul 7, 2023
1 parent 6312513 commit 562e12b
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 77 deletions.
66 changes: 46 additions & 20 deletions include/simdjson/dom/serialization-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,26 +100,31 @@ char *fast_itoa(char *output, uint64_t value) noexcept {
std::memcpy(output, write_pointer, len);
return output + len;
}


} // anonymous namespace
namespace internal {

/***
* Minifier/formatter code.
**/

simdjson_inline void mini_formatter::number(uint64_t x) {
template<class formatter>
simdjson_inline void base_formatter<formatter>::number(uint64_t x) {
char number_buffer[24];
char *newp = fast_itoa(number_buffer, x);
buffer.insert(buffer.end(), number_buffer, newp);
}

simdjson_inline void mini_formatter::number(int64_t x) {
template<class formatter>
simdjson_inline void base_formatter<formatter>::number(int64_t x) {
char number_buffer[24];
char *newp = fast_itoa(number_buffer, x);
buffer.insert(buffer.end(), number_buffer, newp);
}

simdjson_inline void mini_formatter::number(double x) {
template<class formatter>
simdjson_inline void base_formatter<formatter>::number(double x) {
char number_buffer[24];
// Currently, passing the nullptr to the second argument is
// safe because our implementation does not check the second
Expand All @@ -128,31 +133,51 @@ simdjson_inline void mini_formatter::number(double x) {
buffer.insert(buffer.end(), number_buffer, newp);
}

simdjson_inline void mini_formatter::start_array() { one_char('['); }
simdjson_inline void mini_formatter::end_array() { one_char(']'); }
simdjson_inline void mini_formatter::start_object() { one_char('{'); }
simdjson_inline void mini_formatter::end_object() { one_char('}'); }
simdjson_inline void mini_formatter::comma() { one_char(','); }
template<class formatter>
simdjson_inline void base_formatter<formatter>::start_array() { one_char('['); }


template<class formatter>
simdjson_inline void base_formatter<formatter>::end_array() { one_char(']'); }

template<class formatter>
simdjson_inline void base_formatter<formatter>::start_object() { one_char('{'); }

template<class formatter>
simdjson_inline void base_formatter<formatter>::end_object() { one_char('}'); }

template<class formatter>
simdjson_inline void base_formatter<formatter>::comma() { one_char(','); }

simdjson_inline void mini_formatter::true_atom() {
template<class formatter>
simdjson_inline void base_formatter<formatter>::true_atom() {
const char * s = "true";
buffer.insert(buffer.end(), s, s + 4);
}
simdjson_inline void mini_formatter::false_atom() {

template<class formatter>
simdjson_inline void base_formatter<formatter>::false_atom() {
const char * s = "false";
buffer.insert(buffer.end(), s, s + 5);
}
simdjson_inline void mini_formatter::null_atom() {

template<class formatter>
simdjson_inline void base_formatter<formatter>::null_atom() {
const char * s = "null";
buffer.insert(buffer.end(), s, s + 4);
}
simdjson_inline void mini_formatter::one_char(char c) { buffer.push_back(c); }
simdjson_inline void mini_formatter::key(std::string_view unescaped) {

template<class formatter>
simdjson_inline void base_formatter<formatter>::one_char(char c) { buffer.push_back(c); }

template<class formatter>
simdjson_inline void base_formatter<formatter>::key(std::string_view unescaped) {
string(unescaped);
one_char(':');
}
simdjson_inline void mini_formatter::string(std::string_view unescaped) {

template<class formatter>
simdjson_inline void base_formatter<formatter>::string(std::string_view unescaped) {
one_char('\"');
size_t i = 0;
// Fast path for the case where we have no control character, no ", and no backslash.
Expand Down Expand Up @@ -231,11 +256,14 @@ simdjson_inline void mini_formatter::string(std::string_view unescaped) {
one_char('\"');
}

inline void mini_formatter::clear() {

template<class formatter>
inline void base_formatter<formatter>::clear() {
buffer.clear();
}

simdjson_inline std::string_view mini_formatter::str() const {
template<class formatter>
simdjson_inline std::string_view base_formatter<formatter>::str() const {
return std::string_view(buffer.data(), buffer.size());
}

Expand All @@ -257,11 +285,9 @@ simdjson_inline void pretty_formatter::print_newline() {
}

simdjson_inline void pretty_formatter::print_indents(size_t depth) {
if(indent_step <= 0)
if(this->indent_step <= 0)
return;
/*std::string tmp(indent_step * depth, ' ');
pretty_formatter::string(tmp);*/
for(size_t i = 0; i < indent_step * depth; i++)
for(size_t i = 0; i < this->indent_step * depth; i++)
one_char(' ');
}

Expand Down
119 changes: 62 additions & 57 deletions include/simdjson/dom/serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,54 +19,9 @@ namespace simdjson {
*/
namespace internal {

class mini_formatter;
class pretty_formatter;

/**
* @private The string_builder template allows us to construct
* a string from a document element. It is parametrized
* by a "formatter" which handles the details. Thus
* the string_builder template could support both minification
* and prettification, and various other tradeoffs.
*/
template <class formatter = mini_formatter>
class string_builder {
template<class formatter>
class base_formatter {
public:
/** Construct an initially empty builder, would print the empty string **/
string_builder() = default;
/** Append an element to the builder (to be printed) **/
inline void append(simdjson::dom::element value);
/** Append an array to the builder (to be printed) **/
inline void append(simdjson::dom::array value);
/** Append an object to the builder (to be printed) **/
inline void append(simdjson::dom::object value);
/** Reset the builder (so that it would print the empty string) **/
simdjson_inline void clear();
/**
* Get access to the string. The string_view is owned by the builder
* and it is invalid to use it after the string_builder has been
* destroyed.
* However you can make a copy of the string_view on memory that you
* own.
*/
simdjson_inline std::string_view str() const;
/** Append a key_value_pair to the builder (to be printed) **/
simdjson_inline void append(simdjson::dom::key_value_pair value);
private:
formatter format{};
};

/**
* @private This is the class that we expect to use with the string_builder
* template. It tries to produce a compact version of the JSON element
* as quickly as possible.
*/
class mini_formatter {
public:
mini_formatter() = default;

virtual ~mini_formatter() = default;

/** Add a comma **/
simdjson_inline void comma();
/** Start an array, prints [ **/
Expand Down Expand Up @@ -101,37 +56,87 @@ class mini_formatter {
**/
simdjson_inline std::string_view str() const;

simdjson_inline virtual void print_newline();
/** Prints one character **/
simdjson_inline void one_char(char c);

simdjson_inline virtual void print_indents(size_t depth);
simdjson_inline void call_print_newline() {
this->print_newline();
}

simdjson_inline virtual void print_space();
simdjson_inline void call_print_indents(size_t depth) {
this->print_indents(depth);
}

/** Prints one character **/
simdjson_inline void one_char(char c);
simdjson_inline void call_print_space() {
this->print_space();
}

private:
protected:
// implementation details (subject to change)
/** Backing buffer **/
std::vector<char> buffer{}; // not ideal!
};

class pretty_formatter : public mini_formatter {

/**
* @private This is the class that we expect to use with the string_builder
* template. It tries to produce a compact version of the JSON element
* as quickly as possible.
*/
class mini_formatter : public base_formatter<mini_formatter> {
public:
pretty_formatter() : mini_formatter() {}
simdjson_inline void print_newline();

simdjson_inline void print_indents(size_t depth);

//~pretty_formatter() {}
simdjson_inline void print_space();
};

class pretty_formatter : public base_formatter<pretty_formatter> {
public:
simdjson_inline void print_newline();

simdjson_inline void print_indents(size_t depth);

simdjson_inline void print_space();

private:
protected:
int indent_step = 4;
};

/**
* @private The string_builder template allows us to construct
* a string from a document element. It is parametrized
* by a "formatter" which handles the details. Thus
* the string_builder template could support both minification
* and prettification, and various other tradeoffs.
*/
template <class formatter = mini_formatter>
class string_builder {
public:
/** Construct an initially empty builder, would print the empty string **/
string_builder() = default;
/** Append an element to the builder (to be printed) **/
inline void append(simdjson::dom::element value);
/** Append an array to the builder (to be printed) **/
inline void append(simdjson::dom::array value);
/** Append an object to the builder (to be printed) **/
inline void append(simdjson::dom::object value);
/** Reset the builder (so that it would print the empty string) **/
simdjson_inline void clear();
/**
* Get access to the string. The string_view is owned by the builder
* and it is invalid to use it after the string_builder has been
* destroyed.
* However you can make a copy of the string_view on memory that you
* own.
*/
simdjson_inline std::string_view str() const;
/** Append a key_value_pair to the builder (to be printed) **/
simdjson_inline void append(simdjson::dom::key_value_pair value);
private:
formatter format{};
};

} // internal

Expand Down

0 comments on commit 562e12b

Please sign in to comment.