Skip to content

Commit

Permalink
- json: allow user-provided class read functions
Browse files Browse the repository at this point in the history
- json: simplify traits binding
- test: json: provide perfect-hash class reading for some of the tests (enable with CXON_USE_GPERF)
  • Loading branch information
oknenavin committed Jun 28, 2024
1 parent 756660d commit 5d60950
Show file tree
Hide file tree
Showing 8 changed files with 541 additions and 201 deletions.
4 changes: 2 additions & 2 deletions src/cxon/lang/common/cio/cio.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ namespace cxon { namespace cio { // key quoting helpers
template <typename X>
using is_unquoted_key_context = has_traits<X, key::unquoted_traits>;
template <typename X>
using unquoted_key_context = conditional_t<is_unquoted_key_context<X>::value, X, bind_traits_t<X, key::unquoted_traits>>;
using unquoted_key_context = bind_traits_t<X, key::unquoted_traits>;
template <typename X>
using is_quoted_key_context = has_traits<X, key::quoted_traits>;
template <typename X>
using quoted_key_context = conditional_t<is_quoted_key_context<X>::value, X, bind_traits_t<X, key::quoted_traits>>;
using quoted_key_context = bind_traits_t<X, key::quoted_traits>;

template <typename X>
using is_key_context = disjunction<is_unquoted_key_context<X>, is_quoted_key_context<X>>;
Expand Down
172 changes: 92 additions & 80 deletions src/cxon/lang/common/cio/class.hxx

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/cxon/lang/json/class.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ namespace cxon { // cio::val::sink read
using CXON_T_ = Type; \
static CXON_CXX17_CONSTEXPR auto fs = json::cls::make_fields(__VA_ARGS__); \
CXON_IF_CONSTEXPR (cio::cls::is_simple_key_class<Type>::value || cio::cls::are_simple_key_fields<X>(__VA_ARGS__)) { \
using Y = conditional_t<!has_traits<X, cio::key::simple_traits>::value, bind_traits_t<X, cio::key::simple_traits>, X>; \
using Y = bind_traits_t<X, cio::key::simple_traits>; \
return json::cls::read_fields<Y>(t, fs, i, e, cx); \
} \
else return json::cls::read_fields<X>(t, fs, i, e, cx); \
Expand All @@ -79,7 +79,7 @@ namespace cxon { // cio::val::sink read
using CXON_T_ = Type; \
static CXON_CXX17_CONSTEXPR auto fs = json::cls::make_fields(__VA_ARGS__); \
CXON_IF_CONSTEXPR (cio::cls::is_simple_key_class<Type>::value || cio::cls::are_simple_key_fields<X>(__VA_ARGS__)) { \
using Y = conditional_t<!has_traits<X, cio::key::simple_traits>::value, bind_traits_t<X, cio::key::simple_traits>, X>; \
using Y = bind_traits_t<X, cio::key::simple_traits>; \
return json::cls::write_fields<Y>(o, t, fs, cx); \
} \
else return json::cls::write_fields<X>(o, t, fs, cx); \
Expand All @@ -98,7 +98,7 @@ namespace cxon { // cio::val::sink read
using CXON_T_ = Type; ((void)((CXON_T_*)0)); \
static CXON_CXX17_CONSTEXPR auto fs = cxon::json::cls::make_fields(__VA_ARGS__); \
CXON_IF_CONSTEXPR (cxon::cio::cls::is_simple_key_class<Type>::value || cxon::cio::cls::are_simple_key_fields<X>(__VA_ARGS__)) { \
using Y = cxon::conditional_t<!cxon::has_traits<X, cxon::cio::key::simple_traits>::value, cxon::bind_traits_t<X, cxon::cio::key::simple_traits>, X>; \
using Y = cxon::bind_traits_t<X, cxon::cio::key::simple_traits>; \
return cxon::json::cls::read_fields<Y>(t, fs, i, e, cx); \
} \
else return cxon::json::cls::read_fields<X>(t, fs, i, e, cx); \
Expand All @@ -109,7 +109,7 @@ namespace cxon { // cio::val::sink read
using CXON_T_ = Type; ((void)((CXON_T_*)0)); \
static CXON_CXX17_CONSTEXPR auto fs = cxon::json::cls::make_fields(__VA_ARGS__); \
CXON_IF_CONSTEXPR (cxon::cio::cls::is_simple_key_class<Type>::value || cxon::cio::cls::are_simple_key_fields<X>(__VA_ARGS__)) { \
using Y = cxon::conditional_t<!cxon::has_traits<X, cxon::cio::key::simple_traits>::value, cxon::bind_traits_t<X, cxon::cio::key::simple_traits>, X>; \
using Y = cxon::bind_traits_t<X, cxon::cio::key::simple_traits>; \
return cxon::json::cls::write_fields<Y>(o, t, fs, cx); \
} \
else return cxon::json::cls::write_fields<X>(o, t, fs, cx); \
Expand Down
18 changes: 9 additions & 9 deletions src/cxon/utility.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,19 @@ namespace cxon {

// format traits

template <typename T, template <typename> class U>
struct has_traits : std::false_type {};
template <template <typename> class U, typename V>
struct has_traits<U<V>, U> : std::true_type {};
template <template <typename> class T, typename V, template <typename> class U>
struct has_traits<T<V>, U> : std::integral_constant<bool, has_traits<V, U>::value> {};

template <typename T, template <typename> class U>
struct bind_traits;
template <template <typename> class T, typename V, template <typename> class U>
struct bind_traits<T<V>, U> { using type = T<U<V>>; };
struct bind_traits<T<V>, U> { using type = T<U<V>>; };
template <typename T, template <typename> class U>
using bind_traits_t = typename bind_traits<T, U>::type;
using bind_traits_t = typename std::conditional<!has_traits<T, U>::value, typename bind_traits<T, U>::type, T>::type;

template <typename T, template <typename> class U>
struct unbind_traits { using type = T; };
Expand All @@ -96,13 +103,6 @@ namespace cxon {
template <typename T, template <typename> class D, template <typename> class A>
using rebind_traits_t = bind_traits_t<unbind_traits_t<T, D>, A>;

template <typename T, template <typename> class U>
struct has_traits : std::false_type {};
template <template <typename> class U, typename V>
struct has_traits<U<V>, U> : std::true_type {};
template <template <typename> class T, typename V, template <typename> class U>
struct has_traits<T<V>, U> : std::integral_constant<bool, has_traits<V, U>::value> {};

// type sequence

template <typename ...>
Expand Down
2 changes: 1 addition & 1 deletion test/src/json/json.node-time.native-gsoc_2018.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace test { namespace gsoc_2018 {
CXON_JSON_CLS_SIMPLE_KEY_MEMBER()
};

using object = cxon::ordered::object<std::string, participant>;
using object = cxon::ordered::object<unsigned, participant>;

}}

Expand Down
94 changes: 94 additions & 0 deletions test/src/json/json.node-time.native-instruments.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,100 @@ namespace test { namespace instruments {
CXON_JSON_CLS_FIELD_ASIS(volume_ramp_up)
)
CXON_JSON_CLS_SIMPLE_KEY_MEMBER()

# ifdef CXON_USE_GPERF
static unsigned hash(const char *str, std::size_t len) {
static const unsigned char asso_values[] = {
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 11, 39, 17, 39, 39,
39, 2, 0, 26, 39, 22, 39, 0, 39, 4, 0, 15, 0, 39, 39, 1, 39, 16, 0, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39
};
unsigned hval = (unsigned)len;
switch (hval) {
default:
hval += asso_values[static_cast<unsigned char>(str[8])];
CXON_FALLTHROUGH;
case 8: case 7: case 6: case 5: case 4:
break;
}
return hval;
}

template <typename X, typename II, typename Cx>
static bool read_field(instrument& t, const char *str, std::size_t len, II& i, II e, Cx& cx) {
enum {
TOTAL_KEYWORDS = 33,
MIN_WORD_LENGTH = 4,
MAX_WORD_LENGTH = 32,
MIN_HASH_VALUE = 4,
MAX_HASH_VALUE = 38
};

struct field {
using read = bool (*)(instrument&, II&, II, Cx&);
char const* name;
read call;
};

# define CXON_FIELD(field) {#field, [](instrument& t, II& i, II e, Cx& cx) -> bool { return cxon::cio::read_map_val<X>(t.field, i, e, cx); } }
static CXON_CXX17_CONSTEXPR field wordlist[] = {
{(char*)0}, {(char*)0}, {(char*)0}, {(char*)0},
CXON_FIELD(name),
{(char*)0},
CXON_FIELD(tuning),
CXON_FIELD(fadeout),
CXON_FIELD(note_map),
CXON_FIELD(midi_bank),
{(char*)0},
CXON_FIELD(default_pan),
CXON_FIELD(midi_channel),
CXON_FIELD(graph_insert),
CXON_FIELD(pitch_envelope),
CXON_FIELD(volume_envelope),
CXON_FIELD(pitch_pan_center),
CXON_FIELD(midi_drum_set),
CXON_FIELD(panning_envelope),
CXON_FIELD(default_filter_mode),
CXON_FIELD(pitch_pan_separation),
CXON_FIELD(default_filter_cutoff),
CXON_FIELD(duplicate_check_type),
CXON_FIELD(duplicate_note_action),
CXON_FIELD(default_filter_resonance),
CXON_FIELD(random_resonance_weight),
CXON_FIELD(new_note_action),
CXON_FIELD(sample_map),
CXON_FIELD(global_volume),
CXON_FIELD(default_filter_cutoff_enabled),
CXON_FIELD(pitch_to_tempo_lock),
CXON_FIELD(volume_ramp_up),
CXON_FIELD(default_filter_resonance_enabled),
CXON_FIELD(volume_ramp_down),
CXON_FIELD(random_pan_weight),
CXON_FIELD(random_volume_weight),
CXON_FIELD(random_cutoff_weight),
CXON_FIELD(legacy_filename),
CXON_FIELD(midi_program)
};
# undef CXON_FIELD

if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) {
unsigned int key = hash(str, len);
if (key <= MAX_HASH_VALUE && wordlist[key].call)
return wordlist[key].call(t, i, e, cx);
}
return false;
}
# endif // CXON_USE_GPERF
};

struct pattern_data {
Expand Down
Loading

0 comments on commit 5d60950

Please sign in to comment.