4#include <rapidjson/document.h> 
    5#include <rapidjson/stringbuffer.h> 
    6#include <rapidjson/writer.h> 
   21#define JSONIPC_ISLIKELY(expr)          __builtin_expect (bool (expr), 1) 
   22#define JSONIPC_UNLIKELY(expr)          __builtin_expect (bool (expr), 0) 
   23#define JSONIPC_WARNING(fmt,...)        do { fprintf (stderr, "%s:%d: warning: ", __FILE__, __LINE__); fprintf (stderr, fmt, __VA_ARGS__); fputs ("\n", stderr); } while (0) 
   24#define JSONIPC_ASSERT_RETURN(expr,...) do { if (JSONIPC_ISLIKELY (expr)) break; fprintf (stderr, "%s:%d: assertion failed: %s\n", __FILE__, __LINE__, #expr); return __VA_ARGS__; } while (0) 
   28#ifdef  JSONIPC_CUSTOM_SHARED_BASE 
   29using SharedBase = JSONIPC_CUSTOM_SHARED_BASE;
 
   39using JsonValue = rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >;
 
   40using JsonAllocator = rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>;
 
   41using StringBufferWriter = rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, rapidjson::CrtAllocator, rapidjson::kWriteNanAndInfNullFlag>;
 
   42static constexpr const unsigned  rapidjson_parse_flags =
 
   43  rapidjson::kParseFullPrecisionFlag |
 
   44  rapidjson::kParseCommentsFlag |
 
   45  rapidjson::kParseTrailingCommasFlag |
 
   46  rapidjson::kParseNanAndInfFlag |
 
   47  rapidjson::kParseEscapedApostropheFlag;
 
   52string_format (
const char *format, ...)
 
   56  static locale_t posix_c_locale = 
newlocale (LC_ALL_MASK, 
"C", NULL);
 
   57  locale_t saved_locale = 
uselocale (posix_c_locale);
 
   58  constexpr const size_t maxlen = 8192;
 
   59  char buffer[maxlen + 1 + 1] = { 0, };
 
   60  vsnprintf (buffer, maxlen, format, vargs);
 
   68template<
bool value> 
using REQUIRES = typename ::std::enable_if<value, bool>::type;
 
   71template<
bool value> 
using REQUIRESv = typename ::std::enable_if<value, void>::type;
 
   78static inline constexpr bool 
   79constexpr_equals (
const char *a, 
const char *b, 
size_t n)
 
   81  return n == 0 || (a[0] == b[0] && (a[0] == 0 || constexpr_equals (a + 1, b + 1, n - 1)));
 
   89string_demangle_cxx (
const char *mangled_identifier)
 
   92  char *malloced_result = abi::__cxa_demangle (mangled_identifier, NULL, NULL, &status);
 
   93  std::string result = malloced_result && !status ? malloced_result : mangled_identifier;
 
   95    free (malloced_result);
 
  132template<typename T, REQUIRES< Has___typename__<T>::value > = 
true> 
static inline std::string 
  133get___typename__ (
const T &o)
 
  135  return o.__typename__();
 
  137template<typename T, REQUIRES< !Has___typename__<T>::value > = 
true> 
static inline std::string 
  138get___typename__ (
const T &o)
 
  140  return rtti_typename (o);
 
  145  const char* what           () 
const noexcept override { 
return reason_; }
 
  146  int         code           () 
const noexcept          { 
return code_; }
 
  147  explicit    bad_invocation (
int code, 
const char *staticreason) noexcept :
 
  148    reason_ (staticreason), code_ (code) {}
 
  150  const char *
const reason_;
 
 
  156template<
typename> 
struct Class;
 
  176    auto &stack_ = stack();
 
  177    return stack_.empty() ? nullptr : stack_.back();
 
  183    Scope *scope = head();
 
  185      throw std::logic_error (
"Jsonipc::Scope::make_shared(): invalid Scope: nullptr");
 
  190        scope->localsp_->push_back (sptr);
 
  197    Scope *scope = head();
 
  199      throw std::logic_error (
"Jsonipc::Scope::instance_map(): invalid Scope: nullptr");
 
  200    return scope ? &scope->instance_map_ : 
nullptr;
 
  205    auto &stack_ = stack();
 
  206    stack_.erase (std::remove (stack_.begin(), stack_.end(), 
this), stack_.end());
 
 
  212template<
typename T, 
typename Enable = 
void>
 
  219  from_json (
const JsonValue &value, T fallback = T())
 
  221    if      (value.IsBool())    
return value.GetBool();
 
  222    else if (value.IsInt())     
return value.GetInt();
 
  223    else if (value.IsUint())    
return value.GetUint();
 
  224    else if (value.IsInt64())   
return value.GetInt64();
 
  225    else if (value.IsUint64())  
return value.GetUint64();
 
  226    else if (value.IsDouble())  
return value.GetDouble();
 
  227    else                        return fallback;        
 
  230  to_json (T i, JsonAllocator &allocator)
 
  232    return JsonValue (i);
 
 
  240  from_json (
const JsonValue &value, 
bool fallback = 
bool())
 
  245  to_json (
bool b, JsonAllocator &allocator)
 
  247    return JsonValue (b);
 
 
  255  from_json (
const JsonValue &value, T fallback = T())
 
  257    if      (value.IsBool())    
return value.GetBool();
 
  258    else if (value.IsInt())     
return value.GetInt();
 
  259    else if (value.IsUint())    
return value.GetUint();
 
  260    else if (value.IsInt64())   
return value.GetInt64();
 
  261    else if (value.IsUint64())  
return value.GetUint64();
 
  262    else if (value.IsDouble())  
return value.GetDouble();
 
  263    else                        return fallback;        
 
  266  to_json (T f, JsonAllocator &allocator)
 
  268    return JsonValue (f);
 
 
  276  from_json (
const JsonValue &value, 
const char *fallback = 
"")
 
  278    return value.IsString() ? value.GetString() : fallback;
 
  281  to_json (
const char *str, 
size_t l, JsonAllocator &allocator)
 
  283    return str ? JsonValue (str, l, allocator) : JsonValue();
 
  286  to_json (
const char *str, JsonAllocator &allocator)
 
  288    return str ? JsonValue (str, 
strlen (str), allocator) : JsonValue();
 
 
  298    return value.IsString() ? 
std::string (value.GetString(), value.GetStringLength()) : fallback;
 
  301  to_json (
const std::string &s, JsonAllocator &allocator)
 
  303    return JsonValue (s.
data(), s.
size(), allocator);
 
 
  310template<
class T> 
struct DerivesVector<T, 
std::void_t< typename T::value_type, typename T::allocator_type >> :
 
  311  std::is_base_of< std::vector<typename T::value_type, typename T::allocator_type>, T > {};
 
 
  316template<
class T> 
struct DerivesPair<T, 
std::void_t< typename T::first_type, typename T::second_type >> :
 
  317  std::is_base_of< std::pair<typename T::first_type, typename T::second_type>, T > {};
 
 
  323  from_json (
const JsonValue &jarray)
 
  326    if (jarray.IsArray())
 
  328        vec.reserve (jarray.Size());
 
  329        for (
size_t i = 0; i < jarray.Size(); i++)
 
  335  to_json (
const T &vec, JsonAllocator &allocator)
 
  337    JsonValue jarray (rapidjson::kArrayType);
 
  338    jarray.Reserve (vec.size(), allocator);
 
  339    for (
size_t i = 0; i < vec.size(); ++i)
 
 
  349  from_json (
const JsonValue &jarray)
 
  352    if (jarray.IsArray() && jarray.Size() >= 2)
 
  360  to_json (
const T &pair, JsonAllocator &allocator)
 
  362    JsonValue jarray (rapidjson::kArrayType);
 
  363    jarray.Reserve (2, allocator);
 
 
  379template<
typename T> 
static inline auto 
  380from_json (
const JsonValue &value)
 
  387template<
typename T> 
static inline auto 
  388from_json (
const JsonValue &value, 
const T &fallback)
 
  389  -> 
decltype (Convert<T>::from_json (value, fallback))
 
  391  return Convert<T>::from_json (value, fallback);
 
  395template<
typename T> 
static inline JsonValue
 
  396to_json (
const T &value, JsonAllocator &allocator)
 
  398  return Convert<T>::to_json (value, allocator);
 
  402template<> 
inline JsonValue
 
  403to_json<const char*> (
const char *
const &value, JsonAllocator &allocator)
 
 
  409template<
size_t N> 
static inline auto 
  410to_json (
const char (&c)[N], JsonAllocator &allocator)
 
  412  return Convert<const char*>::to_json (c, N - 1, allocator);
 
  414template<
size_t N> 
static inline auto 
  415to_json (
const char (&c)[N], 
size_t l, JsonAllocator &allocator)
 
  417  return Convert<const char*>::to_json (c, l, allocator);
 
  422jsonvalue_to_string (
const JsonValue &value)
 
  424  rapidjson::StringBuffer buffer;
 
  425  StringBufferWriter writer (buffer);
 
  426  value.Accept (writer);
 
  427  const std::string output { buffer.GetString(), buffer.GetSize() };
 
  432template<
class T1, 
class T2 = 
bool, 
class T3 = 
bool, 
class T4 = 
bool> 
static inline std::string 
  433jsonobject_to_string (
const char *m1, T1 &&v1, 
const char *m2 = 0, T2 &&v2 = {},
 
  434                      const char *m3 = 0, T3 &&v3 = {}, 
const char *m4 = 0, T4 &&v4 = {})
 
  436  rapidjson::Document doc (rapidjson::kObjectType);
 
  437  auto &a = doc.GetAllocator();
 
  438  if (m1 && m1[0]) doc.AddMember (JsonValue (m1, a), to_json (v1, a), a);
 
  439  if (m2 && m2[0]) doc.AddMember (JsonValue (m2, a), to_json (v2, a), a);
 
  440  if (m3 && m3[0]) doc.AddMember (JsonValue (m3, a), to_json (v3, a), a);
 
  441  if (m4 && m4[0]) doc.AddMember (JsonValue (m4, a), to_json (v4, a), a);
 
  442  return jsonvalue_to_string (doc);
 
  451  explicit CallbackInfo (
const JsonValue &args, JsonAllocator *allocator = 
nullptr) :
 
  452    args_ (args), doc_ (allocator)
 
  454  const JsonValue& ntharg       (
size_t index)
 const { 
static JsonValue 
j0; 
return index < args_.Size() ? args_[index] : 
j0; }
 
  455  size_t           n_args       ()
 const                { 
return args_.Size(); }
 
  456  Closure*         find_closure (
const char *methodname);
 
  458  JsonAllocator&   allocator    ()                      { 
return doc_.GetAllocator(); }
 
  459  void             set_result   (JsonValue &result)     { result_ = result; have_result_ = 
true; } 
 
  460  JsonValue&       get_result   ()                      { 
return result_; }
 
  461  bool             have_result  ()
 const                { 
return have_result_; }
 
  462  rapidjson::Document& document ()                      { 
return doc_; }
 
  464  const JsonValue &args_;
 
  466  bool         have_result_ = 
false;
 
  467  rapidjson::Document doc_;
 
 
  474  using ReturnType = R;
 
 
  479template<
typename C, 
typename R, 
typename ...Args>
 
  485template<
typename C, 
typename R, 
typename ...Args>
 
  497template<
typename C, 
typename R>
 
  499  template<
typename D = C> 
using PointerType = R (D::*);
 
 
  513  template<
size_t INDEX>       
struct TupleElement<INDEX, false> { 
using Type = void; }; 
 
  514  template<
size_t INDEX>       
using  ArgType     = 
typename TupleElement<HAS_THIS + INDEX, (INDEX < N_ARGS)>::Type;
 
  517  template<
size_t INDEX> 
static ConvertType<INDEX>
 
  525    return (obj.*func) (arg_from_json<INDICES> (args)...);
 
 
  530template<
typename T, 
typename F> 
static inline typename FunctionTraits<F>::ReturnType
 
  531call_from_json (T &obj, 
const F &func, 
const CallbackInfo &args)
 
  533  using CallTraits = CallTraits<F>;
 
  544    operator< (
const TypeidKey &other) 
const noexcept 
  546      return tindex < other.tindex || (tindex == other.tindex && ptr < other.ptr);
 
  551    virtual TypeidKey typeid_key     () = 0;
 
  555    virtual Closure*    lookup_closure (
const char *method) = 0;
 
  556    virtual void        try_upcast     (
const std::string &baseclass, 
void *sptrB) = 0;
 
 
  562  register_wrapper (CreateWrapper createwrapper)
 
  564    wrapper_creators().push_back (createwrapper);
 
  577    TypeidKey typeid_key      ()
 override { 
return create_typeid_key (sptr_); }
 
  578    void      try_upcast      (
const std::string &baseclass, 
void *sptrB)
 override 
  583      return { 
typeid (T), sptr.get() };
 
 
  596  IdSet             *idset_ = 
nullptr;
 
  597  static size_t      next_counter() { 
static size_t counter_ = 0; 
return ++counter_; }
 
  599  delete_id (
size_t thisid)
 
  601    const auto w = wmap_.
find (thisid);
 
  602    if (w != wmap_.
end())
 
  604        Wrapper *wrapper = w->second;
 
  606        const auto t = typeid_map_.
find (wrapper->typeid_key());
 
  607        if (t != typeid_map_.
end())
 
  608          typeid_map_.
erase (t);
 
  611          idset_->
erase (thisid);
 
  622    idset_ = 
new IdSet();
 
  631        idset_->
swap (preserve);
 
  635    auto contains = [] (
const auto &c, 
const auto &e) {
 
  636      return c.end() != c.find (e);
 
  638    size_t preserved = 0;
 
  639    for (
const size_t id : unused)
 
  649    return wmap_.
empty();
 
  657  clear (
const bool printdebug = 
false)
 
  667    for (
auto &pair : old)
 
  669        Wrapper *wrapper = pair.second;
 
  671          fprintf (stderr, 
"Jsonipc::~Wrapper: %s: $id=%zu\n", string_demangle_cxx (wrapper->typeid_key().tindex.name()).c_str(), pair.first);
 
  679    JSONIPC_ASSERT_RETURN (wmap_.
size() == 0); 
 
  680    JSONIPC_ASSERT_RETURN (typeid_map_.
size() == 0); 
 
  683  wrapper_to_json (Wrapper *wrapper, 
const size_t thisid, JsonAllocator &allocator)
 
  687    JsonValue jobject (rapidjson::kObjectType);
 
  688    jobject.AddMember (
"$id", thisid, allocator);
 
  689    jobject.AddMember (
"$class", JsonValue (wrapper->classname().c_str(), allocator), allocator);
 
  692  template<
typename T> 
static JsonValue
 
  695    InstanceMap *imap = Scope::instance_map();
 
  697    Wrapper *wrapper = 
nullptr;
 
  700        const TypeidKey tkey = InstanceWrapper<T>::create_typeid_key (sptr);
 
  701        auto it = imap->typeid_map_.find (tkey);
 
  702        if (it == imap->typeid_map_.end())
 
  704            thisid = next_counter();
 
  707              size_t basedepth = 0;
 
  708              for (
size_t i = 0; i < wcreators.size(); i++) {
 
  709                Wrapper *w = wcreators[i] (sptr, basedepth);
 
  717              wrapper = 
new InstanceWrapper<T> (sptr);
 
  718            imap->wmap_[thisid] = wrapper;
 
  719            imap->typeid_map_[tkey] = thisid;
 
  724            auto wt = imap->wmap_.find (thisid);
 
  725            wrapper = wt != imap->wmap_.end() ? wt->second : 
nullptr;
 
  729      imap->idset_->insert (thisid);
 
  736    return imap->wrapper_to_json (wrapper, thisid, allocator);
 
  739  wrapper_from_json (
const JsonValue &value)
 
  741    if (value.IsObject())
 
  743        auto it = value.FindMember (
"$id");
 
  744        if (it != value.MemberEnd())
 
  746            const size_t thisid = Convert<size_t>::from_json (it->value);
 
  749                auto tit = wmap_.
find (thisid);
 
  750                if (tit != wmap_.
end())
 
  758  scope_lookup_wrapper (
const JsonValue &value)
 
  760    InstanceMap *imap = Scope::instance_map();
 
  761    return imap ? imap->wrapper_from_json (value) : 
nullptr;
 
  764  scope_forget_id (
size_t thisid)
 
  766    InstanceMap *imap = Scope::instance_map();
 
  767    return imap->delete_id (thisid);
 
 
  772CallbackInfo::find_closure (
const char *methodname)
 
  774  const JsonValue &value = ntharg (0);
 
  775  InstanceMap::Wrapper *iw = InstanceMap::scope_lookup_wrapper (value);
 
  776  return iw ? iw->lookup_closure (methodname) : 
nullptr;
 
  780CallbackInfo::classname (
const std::string &fallback)
 const 
  782  const JsonValue &value = ntharg (0);
 
  783  InstanceMap::Wrapper *iw = InstanceMap::scope_lookup_wrapper (value);
 
  784  return iw ? iw->classname() : fallback;
 
  788Scope::Scope (InstanceMap &instance_map, ScopeLocalsP localsp) :
 
  789  instance_map_ (instance_map), localsp_ (localsp ? localsp : ScopeLocalsP (&scope_locals_, [] (ScopeLocals*) {}))
 
  791  auto &stack_ = stack();
 
  792  stack_.push_back (
this);
 
  808  template<typename T, REQUIRES< std::is_same<T, std::nullptr_t>::value> = 
true>
 
 
  819  auto is_identifier_char = [] (
int ch) {
 
  820    return ( (ch >= 
'A' && ch <= 
'Z') ||
 
  821             (ch >= 
'a' && ch <= 
'z') ||
 
  822             (ch >= 
'0' && ch <= 
'9') ||
 
  823             ch == 
'_' || ch == 
'$' );
 
  825  for (
size_t i = 0; i < 
string.size() && 
string[i]; ++i)
 
  826    if (is_identifier_char (
string[i]))
 
  827      normalized += 
string[i];
 
  828    else if (normalized.
size() && normalized[normalized.
size() - 1] != 
'.')
 
 
  835template<
class V> 
static inline unsigned 
  836js_initializer_index ()
 
  845  if constexpr (DerivesVector<T>::value)                                
return 5;
 
  846  if constexpr (DerivesPair<T>::value)                                  
return 5;
 
  850static constexpr const char *
const js_initializers[] = { 
"null", 
"0", 
"0.0", 
"false", 
"''", 
"[]", 
"{}" };
 
  856  const size_t last_colon = full_name.
rfind (
"::");
 
  857  return last_colon == std::string::npos ? full_name : full_name.
substr (last_colon + 2);
 
  860  static std::string name() { 
return short_name (rtti_typename<T>()); }
 
 
  869template<
typename T1, 
typename T2>
 
  885#define JSONIPC_MAP_TO_TYPESCRIPT(CXXTYPE,TSTYPE)                       \ 
  886  template<> struct ::Jsonipc::typescript_name< CXXTYPE >  { static std::string name() { return TSTYPE; } } 
  893  auto print_one_arg = [&] (
const std::string &type_name) {
 
  894    if (i > 0) s += 
", ";
 
  895    s += string_format (
"arg%d: %s", ++i, type_name.c_str());
 
  897  (print_one_arg (typescript_name<Args>::name()), ...); 
 
  901typescript_arg_names_list()
 
  905  auto append_arg_name = [&] (
const std::string &type_name) {
 
  908  (append_arg_name (typescript_name<Args>::name()), ...); 
 
  911template<
typename C, 
typename R, 
typename... Args> 
std::string 
  912typescript_call_impl (
const std::string &method_name)
 
  916  s += typescript_arg_list<Args...>();
 
  917  s += 
string_format (
"): Promise<%s>\n", typescript_name<R>::name().c_str());
 
  918  s += 
string_format (
"  { return Jsonipc.send (\"%s\", [this%s]); }\n",
 
  919                      method_name.
c_str(), typescript_arg_names_list<Args...>().c_str());
 
  922template<
typename T, 
typename Ret, 
typename... Args> 
std::string 
  923typescript_call (
const std::string &method_name, Ret (T::*func) (Args...))
 
  925  return typescript_call_impl<T, Ret, Args...> (method_name);
 
  927template<
typename T, 
typename Ret, 
typename... Args> 
std::string  
  928typescript_call (
const std::string &method_name, Ret (T::*func) (Args...) const)
 
  930  return typescript_call_impl<T, Ret, Args...> (method_name);
 
  935  enum Kind { ANY, ENUM, VALUE, RECORD, FIELD, CLASS, METHOD };
 
  939  size_t class_inherit_pos_ = 0;
 
  943    if (open_enum_.
size())
 
  945    if (open_record_.
size())
 
  947    if (open_class_.
size())
 
  950  template<
class, 
class = 
void> 
struct has_nested_T : 
std::false_type {}; 
 
  951  template<
typename U>          
struct has_nested_T<U, 
std::void_t<typename U::T>> : 
std::true_type {};
 
  952  template<
typename M>  
struct typescript_call_from_type; 
 
  953  template<
typename C, 
typename R, 
typename... Args>
 
  954  struct typescript_call_from_type<R (C::*)(Args...)> {
 
  958      return typescript_call_impl<C, R, Args...> (method_name);
 
  961  template<
typename C, 
typename R, 
typename... Args>
 
  962  struct typescript_call_from_type<R (C::*)(Args...) const> {
 
  966      return typescript_call_impl<C, R, Args...>(method_name);
 
  971  template<
typename T> 
void 
  975    open_enum_ = rtti_typename<typename std::decay<T>::type>();
 
  976    b_ += 
"export const " + short_name (open_enum_) + 
" = { // " + open_enum_ + 
"\n";
 
  978  template<
typename T> 
void 
  983    b_ += 
"  " + name + 
": \"" + full_js_name + 
"\", // " + 
std::to_string(
static_cast<underlying
>(v)) + 
"\n";
 
  988    b_ += 
"} as const;\n";
 
  989    const std::string shortname = short_name (open_enum_);
 
  990    b_ += 
"export type " + shortname + 
" = typeof " + shortname + 
"[keyof typeof " + shortname + 
"];\n";
 
  991    b_ += 
"Jsonipc.classes[\"" + open_enum_ + 
"\"] = " + shortname + 
";\n\n";
 
  994  template<
typename T> 
void 
  998    open_record_ = rtti_typename<typename std::decay<T>::type>();
 
  999    b_ += 
"export class " + short_name (open_record_) + 
" { // " + open_record_ + 
"\n";
 
 1001  template<
typename T, 
typename A> 
void 
 1005    const std::string default_value = js_initializers[js_initializer_index<A>()];
 
 1007    record_fields_.emplace_back (name, ts_type_name, default_value, as_cast);
 
 1012    for (
const auto &[field_name, ts_type_name, default_value, as_cast] : record_fields_)
 
 1013      b_ += 
"  " + field_name + 
": " + ts_type_name + 
";\n";
 
 1014    b_ += 
"  constructor (";
 
 1015    for (
size_t i = 0; i < record_fields_.size(); i++) {
 
 1016      const auto &[field_name, ts_type_name, default_value, as_cast] = record_fields_[i];
 
 1017      b_ += (i ? 
", " : 
"") + field_name + 
": " + ts_type_name + 
" = " + default_value;
 
 1019        b_ += 
" as " + as_cast;
 
 1022    for (
const auto &[field_name, ts_type_name, default_value, as_cast] : record_fields_)
 
 1023      b_ += 
"    this." + field_name + 
" = " + field_name + 
";\n";
 
 1026    const std::string shortname = short_name (open_record_);
 
 1027    b_ += 
"Jsonipc.classes[\"" + open_record_ + 
"\"] = " + shortname + 
";\n\n";
 
 1028    record_fields_.clear();
 
 1029    open_record_.
clear();
 
 1031  template<
typename T> 
void 
 1035    open_class_ = rtti_typename<typename std::decay<T>::type>();
 
 1036    const std::string shortname = short_name (open_class_);
 
 1037    b_ += 
"export class " + shortname + 
" // " + open_class_ + 
"\n";
 
 1038    class_inherit_pos_ = b_.
size();
 
 1040    b_ += 
"  constructor ($id)\n";
 
 1041    b_ += 
"  { super ($id); if (new.target === " + shortname + 
") Jsonipc.ofreeze (this); }\n";
 
 1043  template<
typename B> 
void 
 1046    const std::string base_class_ = rtti_typename<typename std::decay<B>::type>();
 
 1047    b_.
insert (class_inherit_pos_, 
"  extends Jsonipc.classes[\"" + base_class_ + 
"\"]\n");
 
 1049  template<
typename T, 
typename M> 
void 
 1052    b_ += typescript_call_from_type<M>::generate (name);
 
 1054  template<
typename T, 
typename R, 
typename A> 
void 
 1058    b_ += 
"  { return Jsonipc.get_reactive_prop.call (this, \"" + name + 
"\", " + js_initializers[js_initializer_index<R>()] + 
"); }\n";
 
 1060    b_ += 
"  { Jsonipc.send ('set/' + '" + name + 
"', [this, v]); }\n";
 
 1066    const std::string shortname = short_name (open_class_);
 
 1067    b_ += 
"Jsonipc.classes[\"" + open_class_ + 
"\"] = " + shortname + 
";\n\n";
 
 1068    open_class_.
clear();
 
 
 1086    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1087      g_binding_printer->enum_type<T> ();
 
 1091  set (T v, 
const char *valuename)
 
 1094    auto &entries_ = entries();
 
 1096    Entry e { normalized_typename, v };
 
 1097    entries_.push_back (e);
 
 1098    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1099      g_binding_printer->enum_value<T> (valuename, v);
 
 1105    return !entries().empty();
 
 1110    const auto &entries_ = entries();
 
 1111    for (
const auto &e : entries_)
 
 1120    auto c_isalnum = [] (
char c) {
 
 1121      return (c >= 
'A' && c <= 
'Z') || (c >= 
'a' && c <= 
'z') || (c >= 
'0' && c <= 
'9');
 
 1123    const auto &entries_ = entries();
 
 1124    for (
const auto &e : entries_)
 
 1125      if (name == e.name ||                                             
 
 1126          (name.
size() < e.name.size() &&                               
 
 1127           !c_isalnum (e.name[e.name.size() - name.
size() - 1]) &&      
 
 1128           e.name.compare (e.name.size() - name.
size(), name.
size(), name) == 0))
 
 1137    const auto &entries_ = entries();
 
 1138    for (
const auto &e : entries_)
 
 1139      enumvalues.push_back ({ 
int64_t (e.value), e.name });
 
 1143  struct Entry { 
const std::string name; T value; };
 
 1149    return rtti_typename<Type>();
 
 
 1158  from_json (
const JsonValue &value, T fallback = T())
 
 1160    if (value.IsString())
 
 1164        return EnumType::get_value (
string, fallback);
 
 1169  to_json (T evalue, JsonAllocator &allocator)
 
 1172    if (EnumType::has_names())
 
 1174        const std::string &name = EnumType::get_name (evalue);
 
 
 1189    make_serializable<T>();
 
 1190    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1191      g_binding_printer->record_type<T>();
 
 
 1194  template<typename A, REQUIRES< std::is_member_object_pointer<A>::value > = 
true> 
Serializable&
 
 1195  set (
const char *name, A attribute)
 
 1198    Accessors accessors;
 
 1199    accessors.setter = [attribute] (T &obj, 
const JsonValue &value) -> 
void      { obj.*attribute = from_json<SetterAttributeType> (value); };
 
 1200    accessors.getter = [attribute] (
const T &obj, JsonAllocator &a) -> JsonValue { 
return to_json (obj.*attribute, a); };
 
 1202    auto it = amap.find (name);
 
 1203    if (it != amap.end())
 
 1206    const std::string class_name = rtti_typename<T>();
 
 1207    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1208      g_binding_printer->field_member<T,SetterAttributeType> (name);
 
 
 1211  static bool               is_serializable     ()                              { 
return serialize_from_json_() && serialize_to_json_(); }
 
 1212  static JsonValue          serialize_to_json   (
const T &o, JsonAllocator &a)  { 
return serialize_to_json_() (o, a); }
 
 1221  static AccessorMap& accessormap() { 
static AccessorMap amap; 
return amap; }
 
 1222  template<
typename U> 
static void 
 1230      AccessorMap &amap = accessormap();
 
 1231      for (
const auto &field : value.GetObject())
 
 1233          const std::string field_name = field.name.GetString();
 
 1234          auto it = amap.
find (field_name);
 
 1235          if (it == amap.end())
 
 1237          Accessors &accessors = it->second;
 
 1238          accessors.setter (*obj, field.value);
 
 1242    serialize_from_json_() = sfj;
 
 1244    SerializeToJson stj = [] (
const T &object, JsonAllocator &allocator) -> JsonValue {
 
 1245      JsonValue jobject (rapidjson::kObjectType);               
 
 1246      AccessorMap &amap = accessormap();
 
 1247      for (
auto &it : amap)
 
 1250          Accessors &accessors = it.second;
 
 1251          JsonValue result = accessors.getter (
object, allocator);
 
 1252          jobject.AddMember (JsonValue (field_name.
c_str(), allocator), result, allocator);
 
 1256    serialize_to_json_() = stj;
 
 1259  using SerializeToJson = 
std::function<JsonValue (
const T&, JsonAllocator&)>;
 
 1260  static SerializeFromJson& serialize_from_json_ () { 
static SerializeFromJson impl; 
return impl; }
 
 1261  static SerializeToJson&   serialize_to_json_   () { 
static SerializeToJson impl; 
return impl; }
 
 
 1267  Class (
bool internal = 
false)
 
 1275      const size_t class_depth = Class::base_depth();
 
 1276      if (class_depth > basedepth) {
 
 1278        if (derived_sptr.get()) {
 
 1279          basedepth = class_depth;
 
 1285    InstanceMap::register_wrapper (create_wrapper);
 
 1286    if (!internal && JSONIPC_UNLIKELY (g_binding_printer))
 
 1287      g_binding_printer->class_type<T>();
 
 1290  template<
typename B> 
Class&
 
 1294    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1295      g_binding_printer->inherit_type<B>();
 
 1299  template<typename F, REQUIRES< std::is_member_function_pointer<F>::value > = 
true> 
Class&
 
 1300  set (
const char *name, 
const F &method)
 
 1302    add_member_function_closure (name, make_closure (method));
 
 1303     if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1304      g_binding_printer->method_member<T,F> (name);
 
 
 1308  template<
typename R, 
typename A, 
typename C, 
typename VB> 
Class&
 
 1309  set (
const char *name, R (C::*get) () const, VB (C::*
set) (A))
 
 1312    JSONIPC_ASSERT_RETURN (get && 
set, *
this);
 
 1313    add_member_function_closure (
std::string (
"get/") + name, make_closure (get));
 
 1314    add_member_function_closure (
std::string (
"set/") + name, make_closure (
set));
 
 1315    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1316      g_binding_printer->field_accessor<T,R,A> (name);
 
 
 1319  template<typename F, REQUIRES< std::is_member_function_pointer<F>::value > = 
true> 
Class&
 
 1320  set_d (
const char *name, 
const F &method, 
const DefaultsList &dflts)
 
 1323    JSONIPC_ASSERT_RETURN (dflts.size() <= N_ARGS, *
this);
 
 1324    add_member_function_closure (name, make_closure (method));
 
 1325    if (JSONIPC_UNLIKELY (g_binding_printer))
 
 1326      g_binding_printer->method_member<T,F> (name);
 
 1332    return typename_of<T>();
 
 1335  object_from_json (
const JsonValue &value)
 
 1337    InstanceMap::Wrapper *iw = InstanceMap::scope_lookup_wrapper (value);
 
 1341        iw->try_upcast (classname(), &base_sptr);
 
 1352    return rtti_typename<Type>();
 
 1354  template<
typename F>
 
 1356  template<typename F, REQUIRES< HasVoidReturn<F>::value > = 
true> Closure
 
 1357  make_closure (
const F &method)
 
 1359    return [method] (
const CallbackInfo &cbi) {
 
 1360      const bool HAS_THIS = 
true;
 
 1361      if (HAS_THIS + CallTraits<F>::N_ARGS != cbi.n_args())
 
 1366      call_from_json (*instance, method, cbi);
 
 1369  template<typename F, REQUIRES< !HasVoidReturn<F>::value > = 
true> Closure
 
 1370  make_closure (
const F &method)
 
 1372    return [method] (CallbackInfo &cbi) {
 
 1373      const bool HAS_THIS = 
true;
 
 1374      if (HAS_THIS + CallTraits<F>::N_ARGS != cbi.n_args())
 
 1380      rv = to_json (call_from_json (*instance, method, cbi), cbi.allocator());
 
 1381      cbi.set_result (rv);
 
 1385  add_member_function_closure (
const std::string &name, Closure &&closure)
 
 1387    MethodMap &
mmap = methodmap();
 
 1388    auto it = 
mmap.find (name);
 
 1389    if (it != 
mmap.end())
 
 1394  static MethodMap& methodmap() { 
static MethodMap methodmap_; 
return methodmap_; }
 
 1399    Closure*  (*lookup_closure) (
const char*) = NULL;
 
 1402  template<
typename B> 
void 
 1405    BaseVec &bvec = basevec();
 
 1406    BaseInfo binfo { typename_of<B>(), Class<B>::base_depth, &upcast_impl<B>, &Class<B>::lookup_closure, };
 
 1407    for (
const auto &it : bvec)
 
 1408      if (it.basetypename == binfo.basetypename)
 
 1409        throw 
std::runtime_error (
"duplicate base registration: " + binfo.basetypename);
 
 1410    bvec.push_back (binfo);
 
 1411    Class<B> bclass (
true); 
 
 1413  static BaseVec&   basevec  () { 
static BaseVec basevec_;     
return basevec_; }
 
 1414  template<
typename B> 
static bool 
 1418    return Class<B>::try_upcast (bptr, baseclass, sptrB);
 
 1424    const BaseVec &bvec = basevec();
 
 1426    for (
const auto &binfo : bvec)
 
 1428        const size_t b = binfo.base_depth();
 
 1435  lookup_closure (
const char *methodname)
 
 1437    MethodMap &
mmap = methodmap();
 
 1438    auto it = 
mmap.find (methodname);
 
 1439    if (it != 
mmap.end())
 
 1441    const BaseVec &bvec = basevec();
 
 1442    for (
const auto &base : bvec)
 
 1444        Closure *closure = base.lookup_closure (methodname);
 
 1453    if (classname() == baseclass)
 
 1459    const BaseVec &bvec = basevec();
 
 1460    for (
const auto &it : bvec)
 
 1461      if (it.upcast_impl (sptr, baseclass, sptrB))
 
 
 1468template<
typename T, 
typename Enable = 
void>
 
 1487  from_json (
const JsonValue &value)
 
 1502        const std::string impltype = rtti_typename (*sptr);
 
 1503        JsonValue result = InstanceMap::scope_wrap_object<ClassType> (sptr, allocator);
 
 
 1512forget_json_id (
size_t id)
 
 1514  InstanceMap::scope_forget_id (
id);
 
 1522  from_json (
const JsonValue &value)
 
 1527  to_json (
const T *obj, JsonAllocator &allocator)
 
 
 1548  from_json (
const JsonValue &value)
 
 1556  to_json (
const T &
object, JsonAllocator &allocator)
 
 
 1567    extra_methods[methodname] = closure;
 
 1573    rapidjson::Document document;
 
 1574    document.Parse<rapidjson_parse_flags> (message.
data(), message.
size());
 
 1577      if (document.HasParseError())
 
 1578        return create_error (
id, -32700, 
"Parse error");
 
 1579      const char *methodname = 
nullptr;
 
 1580      const JsonValue *args = 
nullptr;
 
 1581      for (
const auto &m : document.GetObject())
 
 1583          id = from_json<size_t> (m.value, 0);
 
 1584        else if (m.name == 
"method")
 
 1585          methodname = from_json<const char*> (m.value);
 
 1586        else if (m.name == 
"params" && m.value.IsArray())
 
 1588      if (!
id || !methodname || !args || !args->IsArray())
 
 1589        return create_error (
id, -32600, 
"Invalid Request");
 
 1591      Closure *closure = cbi.find_closure (methodname);
 
 1594          const auto it = extra_methods.find (methodname);
 
 1595          if (it != extra_methods.end())
 
 1596            closure = &it->second;
 
 1597          else if (
strcmp (methodname, 
"Jsonipc/handshake") == 0)
 
 1600              closure = &initialize;
 
 1604        return create_error (
id, -32601, 
"Method not found: " + cbi.classname (
"<unknown-this>") + 
"['" + methodname + 
"']");
 
 1606      return create_reply (
id, cbi.get_result(), !cbi.have_result(), cbi.document());
 
 1608      return create_error (
id, exc.code(), exc.what());
 
 1614  create_reply (
size_t id, JsonValue &result, 
bool skip_result, rapidjson::Document &d)
 
 1616    auto &a = d.GetAllocator();
 
 1618    d.AddMember (
"id", 
id, a);
 
 1619    d.AddMember (
"result", result, a); 
 
 1620    rapidjson::StringBuffer buffer;
 
 1621    StringBufferWriter writer (buffer);
 
 1623    std::string output { buffer.GetString(), buffer.GetSize() };
 
 1627  create_error (
size_t id, 
int errorcode, 
const std::string &message)
 
 1629    rapidjson::Document d (rapidjson::kObjectType);
 
 1630    auto &a = d.GetAllocator();
 
 1631    d.AddMember (
"id", 
id ? JsonValue (
id) : JsonValue(), a);
 
 1632    JsonValue error (rapidjson::kObjectType);
 
 1633    error.AddMember (
"code", errorcode, a);
 
 1634    error.AddMember (
"message", JsonValue (message.
c_str(), a).Move(), a);
 
 1635    d.AddMember (
"error", error, a); 
 
 1636    rapidjson::StringBuffer buffer;
 
 1637    rapidjson::Writer<rapidjson::StringBuffer> writer (buffer);
 
 1639    std::string output { buffer.GetString(), buffer.GetSize() };
 
 1645    cbi.set_result (to_json (0x00000001, cbi.allocator()).Move());
 
 
 1652JSONIPC_MAP_TO_TYPESCRIPT (
void,          
"void");
 
 1653JSONIPC_MAP_TO_TYPESCRIPT (
bool,          
"boolean");
 
 1654JSONIPC_MAP_TO_TYPESCRIPT (::int8_t,      
"number");
 
 1655JSONIPC_MAP_TO_TYPESCRIPT (::uint8_t,     
"number");
 
 1656JSONIPC_MAP_TO_TYPESCRIPT (::int32_t,     
"number");
 
 1657JSONIPC_MAP_TO_TYPESCRIPT (::uint32_t,    
"number");
 
 1658JSONIPC_MAP_TO_TYPESCRIPT (::int64_t,     
"number");
 
 1659JSONIPC_MAP_TO_TYPESCRIPT (::uint64_t,    
"number");
 
 1660JSONIPC_MAP_TO_TYPESCRIPT (
float,         
"number");
 
 1661JSONIPC_MAP_TO_TYPESCRIPT (
double,        
"number");
 
 1662JSONIPC_MAP_TO_TYPESCRIPT (
const char*,   
"string");
 
Keep track of temporary instances during IpcDispatcher::dispatch_message().
 
std::string normalize_typename(const std::string &string)
Yield the Javascript identifier name by substituting ':+' with '.'.
 
typename ::std::enable_if< value, bool >::type REQUIRES
REQUIRES<value> - Simplified version of std::enable_if<cond,bool>::type to use SFINAE in function tem...
 
typename ::std::enable_if< value, void >::type REQUIRESv
REQUIRESv<value> - Simplified version of std::enable_if<cond,void>::type to use SFINAE in struct temp...
 
bool contains(const C &container, const std::function< bool(typename C::value_type const &value)> &pred)
Returns true if container element for which pred() is true.
 
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
 
const char * string_demangle_cxx(const char *mangled_identifier) noexcept
Demangle identifier via libcc.
 
Template class providing conversion helpers for JsonValue to indexed C++ function argument.
 
Context for calling C++ functions from Json.
 
Class & set(const char *name, R(C::*get)() const, VB(C::*set)(A))
Add a member object accessors.
 
Class & set(const char *name, const F &method)
Add a member function pointer.
 
Template class providing C++ <-> JsonValue conversions for various types.
 
Wrapper for function argument default value constants.
 
DerivesPair<T> - Check if T derives from std::pair<>.
 
DerivesSharedPtr<T> - Check if T derives from std::shared_ptr<>.
 
DerivesVector<T> - Check if T derives from std::vector<>.
 
Template class providing return type and argument type information for functions.
 
Has___typename__<T> - Check if T provides a __typename__() method.
 
Has_setget<T> - Check if type T provides methods set() and get()
 
Has_shared_from_this<T> - Check if t.shared_from_this() yields a std::shared_ptr<>.
 
Template class to identify std::shared_ptr<> classes.
 
Template class to identify wrappable classes.
 
Common base type for polymorphic classes managed by std::shared_ptr<>.
 
Jsonipc wrapper type for objects that support field-wise serialization to/from JSON.
 
Serializable & set(const char *name, A attribute)
Add a member object pointer.
 
Serializable()
Allow object handles to be streamed to/from Javascript, needs a Scope for temporaries.
 
Jsonipc exception that is relayed to caller when thrown during invocations.