diff --git a/Makefile.am b/Makefile.am index 9f26f169b..2e0da4449 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS = no-dependencies ## dist-shar dist-zip ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = cdb configure.help TODO LICENSE* README* *.spec* ulib.html \ +EXTRA_DIST = cdb configure.help TODO LICENSE* README* *.spec* \ ULib.m4 rpm.sh rpmpkgreq.lst rpmpkgreq.lst.suse openwrt \ doc/Doxyfile doc/readme.txt shtool *.awk .travis.yml autogen.sh nativejson-benchmark \ fuzz/http1-corpus fuzz/http2-corpus fuzz/build_libFuzzer.sh fuzz/Makefile.in fuzz/Makefile.am fuzz/uclient_fuzzer.cpp fuzz/uclient.cfg diff --git a/Makefile.in b/Makefile.in index 84988726d..f915c8c7e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -444,7 +444,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = no-dependencies ## dist-shar dist-zip ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = cdb configure.help TODO LICENSE* README* *.spec* ulib.html \ +EXTRA_DIST = cdb configure.help TODO LICENSE* README* *.spec* \ ULib.m4 rpm.sh rpmpkgreq.lst rpmpkgreq.lst.suse openwrt \ doc/Doxyfile doc/readme.txt shtool *.awk .travis.yml autogen.sh nativejson-benchmark \ fuzz/http1-corpus fuzz/http2-corpus fuzz/build_libFuzzer.sh fuzz/Makefile.in fuzz/Makefile.am fuzz/uclient_fuzzer.cpp fuzz/uclient.cfg diff --git a/README.md b/README.md index 120df351b..4a355c5a9 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The current version offers the following features : * [C Servlet Support](http://bellard.org/tcc/) with libtcc (if available) as a backend for dynamic code generation (experimental). * Support for running Ruby on Rails applications natively (experimental). * Support for running natively PHP applications whith a php (embedded) library (experimental). - * Support for load balance support between physical server via udp brodcast (experimental). + * Support for load balance between physical server via udp brodcast (experimental). * Preforking mode to improve concurrency with dedicated process for long-time request. * Support for Windows (without preforking). * Customizable builds (you can remove unneeded functionality). @@ -81,7 +81,7 @@ userver application server is since 10th round in the [TechEmpower's web framewo ## Getting Started With ULib (donated generously by jonathan kelly) -* [ulib.html](https://github.com/stefanocasazza/ULib/blob/master/ulib.html) +* [wiki](https://github.com/stefanocasazza/ULib/wiki/Getting-Started-With-ULib) ## Contributing diff --git a/include/ulib/container/vector.h b/include/ulib/container/vector.h index afc679e58..1bc5ac512 100644 --- a/include/ulib/container/vector.h +++ b/include/ulib/container/vector.h @@ -29,6 +29,7 @@ */ class UHTTP; +class UValue; class UThreadPool; class UHttpPlugIn; class UFileConfig; @@ -430,6 +431,7 @@ template <> class U_EXPORT UVector { private: U_DISALLOW_ASSIGN(UVector) + friend class UValue; friend class UThreadPool; template friend class UOrmTypeHandler; diff --git a/include/ulib/json/value.h b/include/ulib/json/value.h index 77f80b9f2..20251a602 100644 --- a/include/ulib/json/value.h +++ b/include/ulib/json/value.h @@ -59,6 +59,10 @@ #define U_JFIND(json,str,result) UValue::jfind(json,str,U_CONSTANT_SIZE(str),result) +#ifndef U_JSON_PARSE_STACK_SIZE +#define U_JSON_PARSE_STACK_SIZE 256 +#endif + class UTokenizer; class UValueIter; @@ -249,7 +253,7 @@ class U_EXPORT UValue { bool isNull() const { - U_TRACE_NO_PARAM(0+256, "UValue::isNull()") + U_TRACE_NO_PARAM(0, "UValue::isNull()") if (getTag() == NULL_VALUE) U_RETURN(true); @@ -258,7 +262,7 @@ class U_EXPORT UValue { bool isBool() const { - U_TRACE_NO_PARAM(0+256, "UValue::isBool()") + U_TRACE_NO_PARAM(0, "UValue::isBool()") int type = getTag(); @@ -282,7 +286,7 @@ class U_EXPORT UValue { bool isUInt() const { - U_TRACE_NO_PARAM(0+256, "UValue::isUInt()") + U_TRACE_NO_PARAM(0, "UValue::isUInt()") if (getTag() == UINT_VALUE) U_RETURN(true); @@ -300,7 +304,7 @@ class U_EXPORT UValue { bool isNumeric() const { - U_TRACE_NO_PARAM(0+256, "UValue::isNumeric()") + U_TRACE_NO_PARAM(0, "UValue::isNumeric()") if (getTag() <= UINT_VALUE) U_RETURN(true); @@ -309,7 +313,7 @@ class U_EXPORT UValue { bool isString() const { - U_TRACE_NO_PARAM(0+256, "UValue::isString()") + U_TRACE_NO_PARAM(0, "UValue::isString()") if (getTag() == STRING_VALUE) U_RETURN(true); @@ -318,7 +322,7 @@ class U_EXPORT UValue { bool isArray() const { - U_TRACE_NO_PARAM(0+256, "UValue::isArray()") + U_TRACE_NO_PARAM(0, "UValue::isArray()") if (getTag() == ARRAY_VALUE) U_RETURN(true); @@ -327,7 +331,7 @@ class U_EXPORT UValue { bool isObject() const { - U_TRACE_NO_PARAM(0+256, "UValue::isObject()") + U_TRACE_NO_PARAM(0, "UValue::isObject()") if (getTag() == OBJECT_VALUE) U_RETURN(true); @@ -443,34 +447,29 @@ class U_EXPORT UValue { U_INTERNAL_DUMP("result(%u) = %V", result.size(), result.rep) } - template void toJSON(const char* name, uint32_t sz, UJsonTypeHandler member) // it has a limited capacity to manage complex types + template static void toJSON(const UString& name, UJsonTypeHandler member) { - U_TRACE(0, "UValue::toJSON(%.*S,%u,%p)", sz, name, sz, &member) + U_TRACE(0, "UValue::toJSON(%V,%p)", name.rep, &member) - UString str(name+1, sz-2); + addString(name); - addJSON(str, member); + member.toJSON(); + } - if (pnode->toNode() == U_NULLPTR) - { - int pnode_tag = pnode->getTag(); + template static void toJSON(const char* name, uint32_t len, UJsonTypeHandler member) + { + U_TRACE(0, "UValue::toJSON(%.*S,%u,%p)", len, name, len, &member) - if (pnode_tag == ARRAY_VALUE || - pnode_tag == OBJECT_VALUE) - { - U_INTERNAL_DUMP("pnode->next = %p", pnode->next) + addString(name, len); - pnode->value.ival = getJsonValue(pnode_tag, pnode->next); - pnode->next = U_NULLPTR; - } - } + member.toJSON(); } - template void fromJSON(const char* name, uint32_t sz, UJsonTypeHandler member) + template void fromJSON(const char* name, uint32_t len, UJsonTypeHandler member) { - U_TRACE(0, "UValue::fromJSON(%.*S,%u,%p)", sz, name, sz, &member) + U_TRACE(0, "UValue::fromJSON(%.*S,%u,%p)", len, name, len, &member) - UValue* node = at(name+1, sz-2); + UValue* node = at(name+1, len-2); if (node) member.fromJSON(*node); else member.clear(); @@ -611,10 +610,53 @@ class U_EXPORT UValue { union jval pkey, // only if binded to an object value; - static UValue* pnode; static uint32_t size; static char* pstringify; // buffer to stringify json + typedef struct parser_stack_data { + uint64_t keys; + UValue* tails; + bool tags; + } parser_stack_data; + + static int pos; + static union jval o; + static parser_stack_data sd[U_JSON_PARSE_STACK_SIZE]; + + static void initParser() + { + U_TRACE_NO_PARAM(0, "UValue::initParser()") + + o = {0ULL}; + pos = -1; + } + + static void nextParser(); + + static void addString(const char* ptr, uint32_t sz) + { + U_TRACE(0, "UValue::addString(%.*S,%u)", sz, ptr, sz) + + if (sz) + { + UStringRep* rep; + + U_NEW(UStringRep, rep, UStringRep(ptr, sz)); + + o.ival = getJsonValue(STRING_VALUE, rep); + } + else + { + UStringRep::string_rep_null->hold(); + + o.ival = getJsonValue(STRING_VALUE, UStringRep::string_rep_null); + } + + nextParser(); + } + + static void addString(const UString& str) { addString(U_STRING_TO_PARAM(str)); } + #ifdef DEBUG static uint32_t cnt_real, cnt_mreal; #endif @@ -679,10 +721,10 @@ class U_EXPORT UValue { if (rep != UStringRep::string_rep_null) { - uint32_t sz = rep->size(); + uint32_t len = rep->size(); - U_MEMCPY(pstringify, rep->data(), sz); - pstringify += sz; + U_MEMCPY(pstringify, rep->data(), len); + pstringify += len; } *pstringify++ = '"'; @@ -832,44 +874,6 @@ class U_EXPORT UValue { static UString getString(uint64_t value); - template void addJSON(UJsonTypeHandler member) - { - U_TRACE(0, "UValue::addJSON(%p)", &member) - - UValue* node; - - U_NEW(UValue, node, UValue((UValue*)U_NULLPTR)); - - U_INTERNAL_DUMP("pnode = %p", pnode) - - if (pnode) - { - U_INTERNAL_DUMP("pnode->next = %p", pnode->next) - - pnode->next = node; - } - else - { - U_ASSERT(isArrayOrObject()) - - value.ival = UValue::getJsonValue(getTag(), node); - } - - member.toJSON(*(pnode = node)); - pnode = node; - } - - template void addJSON(const UString& name, UJsonTypeHandler member) - { - U_TRACE(0, "UValue::addJSON(%V,%p)", name.rep, &member) - - name.hold(); - - addJSON(member); - - pnode->pkey.ival = getJsonValue(STRING_VALUE, name.rep); - } - private: static int jread_skip(UTokenizer& tok) U_NO_EXPORT; static int jreadFindToken(UTokenizer& tok) U_NO_EXPORT; @@ -885,7 +889,7 @@ class U_EXPORT UValue { template friend class UVector; template friend class UHashMap; template friend class UJsonTypeHandler; - template friend void OBJ_to_JSON(T&, UValue&); + template friend void JSON_stringify(UString&, UValue&, T&); }; #if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX11) @@ -953,6 +957,9 @@ class U_EXPORT UJsonTypeHandler_Base { #define U_JSON_METHOD_HANDLER(name_object_member, type_object_member) \ "\"" #name_object_member "\"", sizeof(#name_object_member)+1, UJsonTypeHandler(name_object_member) +#define U_JSON_TYPE_HANDLER(name_object_member, type_object_member) \ + UValue::toJSON(#name_object_member, sizeof(#name_object_member)-1, UJsonTypeHandler(name_object_member)) + /** * Provide template specializations to support your own complex types * @@ -982,11 +989,11 @@ class U_EXPORT UJsonTypeHandler_Base { * json.toJSON(U_JSON_METHOD_HANDLER(firstName, UString)); * } * - * void Person::toJSON(UValue& json) + * void Person::toJSON() * { - * json.toJSON(U_JSON_METHOD_HANDLER(age, int)); - * json.toJSON(U_JSON_METHOD_HANDLER( lastName, UString)); - * json.toJSON(U_JSON_METHOD_HANDLER(firstName, UString)); + * U_JSON_TYPE_HANDLER(age, int); + * U_JSON_TYPE_HANDLER( lastName, UString); + * U_JSON_TYPE_HANDLER(firstName, UString); * } * * void Person::fromJSON(UValue& json) @@ -1024,13 +1031,28 @@ template class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Bas U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) // it has a limited capacity to manage complex types + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.setTag(UValue::OBJECT_VALUE); + ++UValue::pos; - ((T*)pval)->toJSON(json); + U_INTERNAL_ASSERT_MINOR(UValue::pos, U_JSON_PARSE_STACK_SIZE) + + UValue::sd[UValue::pos] = {0, U_NULLPTR, true}; + + ((T*)pval)->toJSON(); + + U_INTERNAL_DUMP("UValue::pos = %d UValue::sd[0].tags = %b UValue::sd[0].tails = %p UValue::sd[0].keys = 0x%x", + UValue::pos, UValue::sd[0].tags, UValue::sd[0].tails, UValue::sd[0].keys) + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + U_INTERNAL_ASSERT(UValue::sd[UValue::pos].tags) + U_INTERNAL_ASSERT_EQUALS(UValue::sd[UValue::pos].keys, 0) + + UValue::o.ival = UValue::listToValue(UValue::OBJECT_VALUE, UValue::sd[UValue::pos--].tails); + + if (UValue::pos != -1) UValue::nextParser(); } void fromJSON(UValue& json) @@ -1071,22 +1093,17 @@ template void JSON_OBJ_stringify(UString& str, T& obj) U_INTERNAL_DUMP("str(%u) = %V", str.size(), str.rep) } -template void OBJ_to_JSON(T& obj, UValue& json) +template void JSON_stringify(UString& str, UValue& json, T& obj) { - U_TRACE(0, "OBJ_to_JSON(%p,%p)", &obj, &json) + U_TRACE(0, "JSON_stringify(%V,%p,%p)", str.rep, &json, &obj) U_ASSERT(json.empty()) - UValue::pnode = U_NULLPTR; + UValue::initParser(); - UJsonTypeHandler(obj).toJSON(json); -} + UJsonTypeHandler(obj).toJSON(); -template void JSON_stringify(UString& str, UValue& json, T& obj) -{ - U_TRACE(0, "JSON_stringify(%V,%p,%p)", str.rep, &json, &obj) - - OBJ_to_JSON(obj, json); + json.value.ival = UValue::o.ival; UValue::stringify(str, json); } @@ -1111,11 +1128,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Base U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.value.ival = UValue::getJsonValue(UValue::NULL_VALUE, U_NULLPTR); + UValue::o.ival = UValue::getJsonValue(UValue::NULL_VALUE, U_NULLPTR); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1146,11 +1165,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Base U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") + + UValue::o.ival = UValue::getJsonValue(*(bool*)pval ? UValue::TRUE_VALUE : UValue::FALSE_VALUE, U_NULLPTR); - json.value.ival = UValue::getJsonValue(*(bool*)pval ? UValue::TRUE_VALUE : UValue::FALSE_VALUE, U_NULLPTR); + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1181,11 +1202,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Base U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.value.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(char*)pval & 0x00000000FFFFFFFFULL)); + UValue::o.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(char*)pval & 0x00000000FFFFFFFFULL)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1216,11 +1239,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHan U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") + + UValue::o.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(unsigned char*)pval & 0x00000000FFFFFFFFULL)); - json.value.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(unsigned char*)pval & 0x00000000FFFFFFFFULL)); + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1251,11 +1276,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Bas U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.value.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(short*)pval & 0x00000000FFFFFFFFULL)); + UValue::o.ival = UValue::getJsonValue(UValue::INT_VALUE, (void*)(*(short*)pval & 0x00000000FFFFFFFFULL)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1286,11 +1313,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHa U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") + + UValue::o.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(unsigned short*)pval & 0x00000000FFFFFFFFULL)); - json.value.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(unsigned short*)pval & 0x00000000FFFFFFFFULL)); + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1321,11 +1350,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Base U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.value.ival = UValue::getJsonValue(UValue::INT_VALUE, (void*)(*(int*)pval & 0x00000000FFFFFFFFULL)); + UValue::o.ival = UValue::getJsonValue(UValue::INT_VALUE, (void*)(*(int*)pval & 0x00000000FFFFFFFFULL)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1356,11 +1387,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHand U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") + + UValue::o.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(unsigned int*)pval & 0x00000000FFFFFFFFULL)); - json.value.ival = UValue::getJsonValue(UValue::UINT_VALUE, (void*)(*(unsigned int*)pval & 0x00000000FFFFFFFFULL)); + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1395,16 +1428,24 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Base U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") long l = *(long*)pval; - int type = (l > (long)UINT_MAX || l < (long)INT_MAX ? UValue::REAL_VALUE : - l > 0 ? UValue::UINT_VALUE : UValue::INT_VALUE); + U_INTERNAL_DUMP("pval = %ld", *(long*)pval) + +# if SIZEOF_LONG == 4 + int type = UValue::INT_VALUE; +# else + int type = (l > UINT_MAX || l < INT_MIN ? UValue::REAL_VALUE : + l > 0 ? UValue::UINT_VALUE : UValue::INT_VALUE); +# endif + + UValue::o.ival = UValue::getJsonValue(type, (void*)(l & 0x00000000FFFFFFFFULL)); - json.value.ival = UValue::getJsonValue(type, (void*)(l & 0x00000000FFFFFFFFULL)); + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1412,6 +1453,8 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Base U_TRACE(0, "UJsonTypeHandler::fromJSON(%p)", &json) *(long*)pval = json.getNumber(); + + U_INTERNAL_DUMP("pval = %ld", *(long*)pval) } }; @@ -1439,13 +1482,21 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHan U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") unsigned long l = *(unsigned long*)pval; - json.value.ival = UValue::getJsonValue(l > UINT_MAX ? UValue::REAL_VALUE : UValue::UINT_VALUE, (void*)(l & 0x00000000FFFFFFFFULL)); +# if SIZEOF_LONG == 4 + int type = UValue::UINT_VALUE; +# else + int type = (l > UINT_MAX ? UValue::REAL_VALUE : UValue::UINT_VALUE); +# endif + + UValue::o.ival = UValue::getJsonValue(type, (void*)(l & 0x00000000FFFFFFFFULL)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1476,16 +1527,18 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") long long l = *(long long*)pval; - int type = (l > UINT_MAX || l < INT_MAX ? UValue::REAL_VALUE : + int type = (l > UINT_MAX || l < INT_MIN ? UValue::REAL_VALUE : l > 0 ? UValue::UINT_VALUE : UValue::INT_VALUE); - json.value.ival = UValue::getJsonValue(type, (void*)(l & 0x00000000FFFFFFFFULL)); + UValue::o.ival = UValue::getJsonValue(type, (void*)(l & 0x00000000FFFFFFFFULL)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1516,13 +1569,15 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTy U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") unsigned long long l = *(unsigned long long*)pval; - json.value.ival = UValue::getJsonValue(l > UINT_MAX ? UValue::REAL_VALUE : UValue::UINT_VALUE, (void*)(l & 0x00000000FFFFFFFFULL)); + UValue::o.ival = UValue::getJsonValue(l > UINT_MAX ? UValue::REAL_VALUE : UValue::UINT_VALUE, (void*)(l & 0x00000000FFFFFFFFULL)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1553,11 +1608,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Bas U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") + + UValue::o.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrintf(*(float*)pval)); - json.value.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrintf(*(float*)pval)); + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1588,11 +1645,13 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_Ba U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.value.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrint(*(double*)pval)); + UValue::o.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrint(*(double*)pval)); + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1623,15 +1682,17 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandl U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") # ifdef HAVE_LRINTL - json.value.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrintl(*(long double*)pval)); + UValue::o.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrintl(*(long double*)pval)); # else - json.value.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrint(*(double*)pval)); + UValue::o.ival = UValue::getJsonValue(UValue::REAL_VALUE, (void*)lrint(*( double*)pval)); # endif + + UValue::nextParser(); } void fromJSON(UValue& json) @@ -1662,11 +1723,11 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandle U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.setString((UStringRep*)pval); + UValue::addString(U_STRING_TO_PARAM(*(UStringRep*)pval)); } void fromJSON(UValue& json) @@ -1677,7 +1738,7 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandle U_ASSERT(json.isString()) - U_INTERNAL_DUMP("pval(%p) = %p rep(%p) = %V", pval, pval, json.getPayload(), json.getPayload()) + U_INTERNAL_DUMP("pval(%p) = %p json(%p) = %V", pval, pval, json.getPayload(), json.getPayload()) U_ERROR("UJsonTypeHandler::fromJSON(): sorry, we cannot use UStringRep type from JSON type handler..."); } @@ -1705,11 +1766,11 @@ template <> class U_EXPORT UJsonTypeHandler : public UJsonTypeHandler_B U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") - json.setString(((UString*)pval)->rep); + UValue::addString(*(UString*)pval); } void fromJSON(UValue& json) @@ -1771,23 +1832,33 @@ template class U_EXPORT UJsonTypeHandler > : public UJsonT U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) - - json.setTag(UValue::ARRAY_VALUE); + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") uvector* pvec = (uvector*)pval; - if (pvec->_length) + if (pvec->_length == 0) UValue::o.ival = UValue::listToValue(UValue::ARRAY_VALUE, U_NULLPTR); + else { const void** ptr = pvec->vec; const void** end = pvec->vec + pvec->_length; -# ifndef HAVE_OLD_IOSTREAM - do { json.addJSON(UJsonTypeHandler(*(T*)(*ptr))); } while (++ptr < end); -# endif + ++UValue::pos; + + U_INTERNAL_ASSERT_MINOR(UValue::pos, U_JSON_PARSE_STACK_SIZE) + + UValue::sd[UValue::pos] = {0, U_NULLPTR, false}; + + do { UJsonTypeHandler(*(T*)(*ptr)).toJSON(); } while (++ptr < end); + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + U_INTERNAL_ASSERT_EQUALS(UValue::sd[UValue::pos].tags, false) + + UValue::o.ival = UValue::listToValue(UValue::ARRAY_VALUE, UValue::sd[UValue::pos--].tails); } + + if (UValue::pos != -1) UValue::nextParser(); } void fromJSON(UValue& json) @@ -1856,26 +1927,33 @@ template <> class U_EXPORT UJsonTypeHandler > : public UJsonTyp U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler>::toJSON(%p)", &json) - - json.setTag(UValue::ARRAY_VALUE); + U_TRACE_NO_PARAM(0, "UJsonTypeHandler>::toJSON()") uvectorbase* pvec = (uvectorbase*)pval; - if (pvec->_length) + if (pvec->_length == 0) UValue::o.ival = UValue::listToValue(UValue::ARRAY_VALUE, U_NULLPTR); + else { const void** ptr = pvec->vec; const void** end = pvec->vec + pvec->_length; - do { - UString item((const UStringRep*)(*ptr)); + ++UValue::pos; - json.addJSON(UJsonTypeHandler(item)); - } - while (++ptr < end); + U_INTERNAL_ASSERT_MINOR(UValue::pos, U_JSON_PARSE_STACK_SIZE) + + UValue::sd[UValue::pos] = {0, U_NULLPTR, false}; + + do { UValue::addString(U_STRING_TO_PARAM(*(const UStringRep*)(*ptr))); } while (++ptr < end); + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + U_INTERNAL_ASSERT_EQUALS(UValue::sd[UValue::pos].tags, false) + + UValue::o.ival = UValue::listToValue(UValue::ARRAY_VALUE, UValue::sd[UValue::pos--].tails); } + + if (UValue::pos != -1) UValue::nextParser(); } void fromJSON(UValue& json) @@ -1925,10 +2003,7 @@ template class U_EXPORT UJsonTypeHandler > : public UJson { json.push_back('{'); - do { - json.toJSON(pmap->getKey(), UJsonTypeHandler(*(pmap->elem()))); - } - while (pmap->next()); + do { json.toJSON(pmap->getKey(), UJsonTypeHandler(*(pmap->elem()))); } while (pmap->next()); json.setLastChar('}'); } @@ -1936,23 +2011,31 @@ template class U_EXPORT UJsonTypeHandler > : public UJson U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) - - json.setTag(UValue::OBJECT_VALUE); + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") uhashmap* pmap = (uhashmap*)pval; - if (pmap->first()) + if (pmap->first() == U_NULLPTR) UValue::o.ival = UValue::listToValue(UValue::OBJECT_VALUE, U_NULLPTR); + else { - do { -# ifndef HAVE_OLD_IOSTREAM - json.addJSON(pmap->getKey(), UJsonTypeHandler(*(pmap->elem()))); -# endif - } - while (pmap->next()); + ++UValue::pos; + + U_INTERNAL_ASSERT_MINOR(UValue::pos, U_JSON_PARSE_STACK_SIZE) + + UValue::sd[UValue::pos] = {0, U_NULLPTR, true}; + + do { UValue::toJSON(pmap->getKey(), *(pmap->elem())); } while (pmap->next()); + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + U_INTERNAL_ASSERT(UValue::sd[UValue::pos].tags) + U_INTERNAL_ASSERT_EQUALS(UValue::sd[UValue::pos].keys, 0) + + UValue::o.ival = UValue::listToValue(UValue::OBJECT_VALUE, UValue::sd[UValue::pos--].tails); } + + if (UValue::pos != -1) UValue::nextParser(); } void fromJSON(UValue& json) @@ -2010,10 +2093,7 @@ template <> class U_EXPORT UJsonTypeHandler > : public UJsonTy { json.push_back('{'); - do { - json.toJSON(pmap->getKey(), UJsonTypeHandler(*(UStringRep*)(pmap->elem()))); - } - while (pmap->next()); + do { json.toJSON(pmap->getKey(), UJsonTypeHandler(*(UStringRep*)(pmap->elem()))); } while (pmap->next()); json.setLastChar('}'); } @@ -2021,23 +2101,36 @@ template <> class U_EXPORT UJsonTypeHandler > : public UJsonTy U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler>::toJSON(%p)", &json) - - json.setTag(UValue::OBJECT_VALUE); + U_TRACE_NO_PARAM(0, "UJsonTypeHandler>::toJSON()") UHashMap* pmap = (UHashMap*)pval; - if (pmap->first()) + if (pmap->first() == U_NULLPTR) UValue::o.ival = UValue::listToValue(UValue::OBJECT_VALUE, U_NULLPTR); + else { + ++UValue::pos; + + U_INTERNAL_ASSERT_MINOR(UValue::pos, U_JSON_PARSE_STACK_SIZE) + + UValue::sd[UValue::pos] = {0, U_NULLPTR, true}; + do { - UString item((const UStringRep*)pmap->elem()); + UValue::addString(pmap->getKey()); - json.addJSON(pmap->getKey(), UJsonTypeHandler(item)); + UValue::addString(U_STRING_TO_PARAM(*(const UStringRep*)pmap->elem())); } while (pmap->next()); + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + U_INTERNAL_ASSERT(UValue::sd[UValue::pos].tags) + U_INTERNAL_ASSERT_EQUALS(UValue::sd[UValue::pos].keys, 0) + + UValue::o.ival = UValue::listToValue(UValue::OBJECT_VALUE, UValue::sd[UValue::pos--].tails); } + + if (UValue::pos != -1) UValue::nextParser(); } void fromJSON(UValue& json) @@ -2071,6 +2164,7 @@ template <> class U_EXPORT UJsonTypeHandler > : public UJsonTy #if defined(U_STDCPP_ENABLE) # include + template class U_EXPORT UJsonTypeHandler > : public UJsonTypeHandler_Base { public: typedef std::vector stdvector; @@ -2107,17 +2201,32 @@ template class U_EXPORT UJsonTypeHandler > : public UJs U_INTERNAL_DUMP("json(%u) = %V", json.size(), json.rep) } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "UJsonTypeHandler::toJSON(%p)", &json) - - json.setTag(UValue::ARRAY_VALUE); + U_TRACE_NO_PARAM(0, "UJsonTypeHandler::toJSON()") stdvector* pvec = (stdvector*)pval; -# ifndef HAVE_OLD_IOSTREAM - for (uint32_t i = 0, n = pvec->size(); i < n; ++i) json.addJSON(UJsonTypeHandler(pvec->at(i))); -# endif + uint32_t n = pvec->size(); + + if (n == 0) UValue::o.ival = UValue::listToValue(UValue::ARRAY_VALUE, U_NULLPTR); + else + { + ++UValue::pos; + + U_INTERNAL_ASSERT_MINOR(UValue::pos, U_JSON_PARSE_STACK_SIZE) + + UValue::sd[UValue::pos] = {0, U_NULLPTR, false}; + + for (uint32_t i = 0; i < n; ++i) UJsonTypeHandler(pvec->at(i)).toJSON(); + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + U_INTERNAL_ASSERT_EQUALS(UValue::sd[UValue::pos].tags, false) + + UValue::o.ival = UValue::listToValue(UValue::ARRAY_VALUE, UValue::sd[UValue::pos--].tails); + } + + if (UValue::pos != -1) UValue::nextParser(); } void fromJSON(UValue& json) diff --git a/src/ulib/json/value.cpp b/src/ulib/json/value.cpp index 332a84b83..0b218848c 100644 --- a/src/ulib/json/value.cpp +++ b/src/ulib/json/value.cpp @@ -15,10 +15,13 @@ #include #include -int UValue::jsonParseFlags; -char* UValue::pstringify; -UValue* UValue::pnode; -uint32_t UValue::size; +int UValue::pos; +int UValue::jsonParseFlags; +char* UValue::pstringify; +uint32_t UValue::size; +UValue::jval UValue::o; +UValue::parser_stack_data UValue::sd[U_JSON_PARSE_STACK_SIZE]; + #ifdef DEBUG uint32_t UValue::cnt_real; uint32_t UValue::cnt_mreal; @@ -234,7 +237,7 @@ uint32_t UValue::getMemberNames(UVector& members) const if (getTag() == OBJECT_VALUE) { UValue* element = toNode(); - uint32_t sz, n = members.size(); + uint32_t len, n = members.size(); while (element) { @@ -251,9 +254,9 @@ uint32_t UValue::getMemberNames(UVector& members) const element = element->next; } - sz = members.size() - n; + len = members.size() - n; - U_RETURN(sz); + U_RETURN(len); } U_RETURN(0); @@ -280,11 +283,11 @@ UString UValue::getString(uint64_t value) U_INTERNAL_ASSERT_EQUALS(type, UTF_VALUE) - uint32_t sz = rep->size(); + uint32_t len = rep->size(); - UString str(sz); + UString str(len); - UEscape::decode(rep->data(), sz, str); + UEscape::decode(rep->data(), len, str); U_RETURN_STRING(str); } @@ -295,11 +298,11 @@ void UValue::emitUTF(UStringRep* rep) const U_INTERNAL_DUMP("rep = %V", rep) - uint32_t sz = rep->size(); + uint32_t len = rep->size(); - UString str(sz); + UString str(len); - UEscape::decode(rep->data(), sz, str); + UEscape::decode(rep->data(), len, str); *pstringify++ = '"'; @@ -676,10 +679,6 @@ case_utf: emitUTF( (UStringRep*)getPayload()); return; pstringify += U_CONSTANT_SIZE("null"); } -#ifndef U_JSON_PARSE_STACK_SIZE -#define U_JSON_PARSE_STACK_SIZE 256 -#endif - bool UValue::parse(const UString& document) { U_TRACE(0, "UValue::parse(%V)", document.rep) @@ -784,28 +783,23 @@ bool UValue::parse(const UString& document) #ifdef DEBUG cnt_real = cnt_mreal = 0; + double tmp; #endif + double val; const char* p; - UStringRep* rep; unsigned char c; + UStringRep* rep; const char* start; + int gexponent, type; uint64_t integerPart; - union jval o = {0ULL}; - int pos = -1, gexponent, type; const char* s = document.data(); const char* end = s + (size = document.size()); uint32_t sz, significandDigit, decimalDigit, exponent; bool minus = false, colon = false, comma = false, separator = true; - struct stack_data { - uint64_t keys; - UValue* tails; - bool tags; - }; - - struct stack_data sd[U_JSON_PARSE_STACK_SIZE]; + initParser(); U_INTERNAL_DUMP("jsonParseFlags = %d", jsonParseFlags) @@ -880,9 +874,11 @@ loop: while (u__isspace(*s)) ++s; goto dquote; dquote_assign: - if ((sz = s++ - ++start)) + sz = s++ - ++start; + + if (sz) { - U_DUMP("type = (%d,%S) string(%u) = %.*S", type, getDataTypeDescription(type), sz, sz, start) + U_DUMP("type = (%d,%S)", type, getDataTypeDescription(type)) if ((jsonParseFlags & STRING_COPY) == 0) { @@ -1449,6 +1445,38 @@ next: U_INTERNAL_DUMP("next: comma = %b pos = %d colon = %b separator = %b s = % U_RETURN(false); } +void UValue::nextParser() +{ + U_TRACE_NO_PARAM(0, "UValue::nextParser()") + + U_INTERNAL_DUMP("UValue::pos = %d", UValue::pos) + + U_INTERNAL_ASSERT_DIFFERS(UValue::pos, -1) + + U_DUMP("sd[%d].tags = (%d,%S) sd[%d].tails = %p sd[%d].keys = 0x%x", pos, (sd[pos].tags ? OBJECT_VALUE : ARRAY_VALUE), + getDataTypeDescription((sd[pos].tags ? OBJECT_VALUE : ARRAY_VALUE)), pos, sd[pos].tails, pos, sd[pos].keys) + + if (sd[pos].tags == false) sd[pos].tails = insertAfter(sd[pos].tails, o.ival); + else + { + if (sd[pos].keys == 0) + { + sd[pos].keys = o.ival; + + U_INTERNAL_DUMP("sd[%d].keys = %V", pos, getPayload(sd[pos].keys)) + + return; + } + + sd[pos].tails = insertAfter(sd[pos].tails, o.ival); + + U_INTERNAL_ASSERT(isStringOrUTF(sd[pos].keys)) + + sd[pos].tails->pkey.ival = sd[pos].keys; + sd[pos].keys = 0; + } +} + // ======================================================================================================================= // An in-place JSON element reader (@see http://www.codeproject.com/Articles/885389/jRead-an-in-place-JSON-element-reader) // ======================================================================================================================= @@ -1665,11 +1693,11 @@ U_NO_EXPORT UString UValue::jread_string(UTokenizer& tok) const char* ptr = tok.getPointer(); const char* end = tok.getEnd(); const char* last = u_find_char(ptr, end, c); - uint32_t sz = (last < end ? last - ptr : 0); + uint32_t len = (last < end ? last - ptr : 0); - U_INTERNAL_DUMP("c = %C sz = %u", c, sz) + U_INTERNAL_DUMP("c = %C len = %u", c, len) - if (sz) (void) result.assign(ptr, sz); + if (len) (void) result.assign(ptr, len); if (last < end) tok.setPointer(last+1); diff --git a/src/ulib/net/server/plugin/usp/jsonrequest.usp b/src/ulib/net/server/plugin/usp/jsonrequest.usp index 951fc5906..61f7e0932 100644 --- a/src/ulib/net/server/plugin/usp/jsonrequest.usp +++ b/src/ulib/net/server/plugin/usp/jsonrequest.usp @@ -62,14 +62,14 @@ public: json.toJSON(U_JSON_METHOD_HANDLER(zip, uint32_t)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(0, "Request::toJSON(%p)", &json) + U_TRACE_NO_PARAM(0, "Request::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(user, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(t, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(forecast, uint32_t)); - json.toJSON(U_JSON_METHOD_HANDLER(zip, uint32_t)); + U_JSON_TYPE_HANDLER(user, UString); + U_JSON_TYPE_HANDLER(t, UString); + U_JSON_TYPE_HANDLER(forecast, uint32_t); + U_JSON_TYPE_HANDLER(zip, uint32_t); } void fromJSON(UValue& json) diff --git a/src/ulib/utility/http2.cpp b/src/ulib/utility/http2.cpp index 31070f062..bc7c22263 100644 --- a/src/ulib/utility/http2.cpp +++ b/src/ulib/utility/http2.cpp @@ -3511,7 +3511,11 @@ loop: U_DUMP("pStream->id = %u pStream->state = (%u, %s) pStream->headers(%u) = { // NB: to avoid GOAWAY frame with error (6, FRAME_SIZE_ERROR) in writeResponse()... - if (u_get_unalignedp32(u_clientimage_info.http_info.user_agent) == U_MULTICHAR_CONSTANT32('S','p','o','t')) + if (u_get_unalignedp64(u_clientimage_info.http_info.user_agent) == U_MULTICHAR_CONSTANT64('M','o','z','i','l','l','a','/')) + { + pConnection->bug_client = "Mozilla"; // Mozilla/5.0 (iPad; CPU OS 9_3_5 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G36 Safari/601.1 + } + else if (u_get_unalignedp32(u_clientimage_info.http_info.user_agent) == U_MULTICHAR_CONSTANT32('S','p','o','t')) { pConnection->bug_client = "Spot"; // "Spot/1.0 (iPhone; iOS 10.3.1; Scale/3.00)" } diff --git a/tests/ulib/README b/tests/ulib/README index c06b32e77..44910013e 100644 --- a/tests/ulib/README +++ b/tests/ulib/README @@ -4,8 +4,8 @@ Four Debian releases are available on the main site: Debian 7.11, or wheezy. Access this release through dists/oldstable Debian 7.11 was released Saturday, 4th June 2016. -Debian 8.7, or jessie. Access this release through dists/stable -Debian 8.7 was released Saturday, 14th January 2017. +Debian 8.8, or jessie. Access this release through dists/stable +Debian 8.8 was released Saturday, 6th May 2017. Testing, or stretch. Access this release through dists/testing. The current tested development snapshot is named stretch. Packages which diff --git a/tests/ulib/test_json.cpp b/tests/ulib/test_json.cpp index 2b3bbd4c2..74ab360a3 100644 --- a/tests/ulib/test_json.cpp +++ b/tests/ulib/test_json.cpp @@ -31,9 +31,10 @@ class Request { { U_TRACE_NO_PARAM(5, "Request::clear()") - table.clear(); - radius.clear(); - location.clear(); + + table.clear(); + radius.clear(); + location.clear(); fbPermissions.clear(); } @@ -47,14 +48,14 @@ class Request { json.toJSON(U_JSON_METHOD_HANDLER(fbPermissions, UVector)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Request::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Request::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(table, UHashMap)); - json.toJSON(U_JSON_METHOD_HANDLER(radius, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(location, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(fbPermissions, UVector)); + U_JSON_TYPE_HANDLER(table, UHashMap); + U_JSON_TYPE_HANDLER(radius, UString); + U_JSON_TYPE_HANDLER(location, UString); + U_JSON_TYPE_HANDLER(fbPermissions, UVector); } void fromJSON(UValue& json) @@ -82,7 +83,7 @@ class Request { return UObjectIO::buffer_output; } - return 0; + return U_NULLPTR; } #endif @@ -133,14 +134,14 @@ class Response { json.toJSON(U_JSON_METHOD_HANDLER(table, UHashMap)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Response::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Response::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(fbPermissions, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(type, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(token, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(table, UHashMap)); + U_JSON_TYPE_HANDLER(fbPermissions, UVector); + U_JSON_TYPE_HANDLER(type, UString); + U_JSON_TYPE_HANDLER(token, UString); + U_JSON_TYPE_HANDLER(table, UHashMap); } void fromJSON(UValue& json) @@ -168,7 +169,7 @@ class Response { return UObjectIO::buffer_output; } - return 0; + return U_NULLPTR; } #endif }; @@ -196,12 +197,12 @@ class Organization { json.toJSON(U_JSON_METHOD_HANDLER(index, UString)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Organization::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Organization::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(name, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(index, UString)); + U_JSON_TYPE_HANDLER(name, UString); + U_JSON_TYPE_HANDLER(index, UString); } void fromJSON(UValue& json) @@ -242,14 +243,14 @@ class Social { json.toJSON(U_JSON_METHOD_HANDLER(dateTime, int64_t)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Social::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Social::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(name, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(token, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(key, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(dateTime, int64_t)); + U_JSON_TYPE_HANDLER(name, UString); + U_JSON_TYPE_HANDLER(token, UString); + U_JSON_TYPE_HANDLER(key, unsigned); + U_JSON_TYPE_HANDLER(dateTime, int64_t); } void fromJSON(UValue& json) @@ -286,12 +287,12 @@ class StrangerSocial { json.toJSON(U_JSON_METHOD_HANDLER(key, unsigned)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "StrangerSocial::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "StrangerSocial::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(name, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(key, unsigned)); + U_JSON_TYPE_HANDLER(name, UString); + U_JSON_TYPE_HANDLER(key, unsigned); } void fromJSON(UValue& json) @@ -326,12 +327,12 @@ class Link { json.toJSON(U_JSON_METHOD_HANDLER(imageURL, UString)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Link::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Link::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(url, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(imageURL, UString)); + U_JSON_TYPE_HANDLER(url, UString); + U_JSON_TYPE_HANDLER(imageURL, UString); } void fromJSON(UValue& json) @@ -363,16 +364,16 @@ class LinkPreview { json.toJSON(U_JSON_METHOD_HANDLER(imageHeight, float)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "LinkPreview::toJSON(%p)", &json) - - json.toJSON(U_JSON_METHOD_HANDLER(imageURL, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(URL, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(title, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(domain, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(imageWidth, float)); - json.toJSON(U_JSON_METHOD_HANDLER(imageHeight, float)); + U_TRACE_NO_PARAM(5, "LinkPreview::toJSON()") + + U_JSON_TYPE_HANDLER(imageURL, UString); + U_JSON_TYPE_HANDLER(URL, UString); + U_JSON_TYPE_HANDLER(title, UString); + U_JSON_TYPE_HANDLER(domain, UString); + U_JSON_TYPE_HANDLER(imageWidth, float); + U_JSON_TYPE_HANDLER(imageHeight, float); } void fromJSON(UValue& json) @@ -414,19 +415,19 @@ class Message { json.toJSON(U_JSON_METHOD_HANDLER(readTime, int64_t)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Message::toJSON(%p)", &json) - - json.toJSON(U_JSON_METHOD_HANDLER(actor, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(target, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(content, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(linkPreviews, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(key, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(ping, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(becameActive, bool)); - json.toJSON(U_JSON_METHOD_HANDLER(dateTime, int64_t)); - json.toJSON(U_JSON_METHOD_HANDLER(readTime, int64_t)); + U_TRACE_NO_PARAM(5, "Message::toJSON()") + + U_JSON_TYPE_HANDLER(actor, UString); + U_JSON_TYPE_HANDLER(target, UString); + U_JSON_TYPE_HANDLER(content, UString); + U_JSON_TYPE_HANDLER(linkPreviews, UVector); + U_JSON_TYPE_HANDLER(key, unsigned); + U_JSON_TYPE_HANDLER(ping, UString); + U_JSON_TYPE_HANDLER(becameActive, bool); + U_JSON_TYPE_HANDLER(dateTime, int64_t); + U_JSON_TYPE_HANDLER(readTime, int64_t); } void fromJSON(UValue& json) @@ -476,23 +477,23 @@ class User { json.toJSON(U_JSON_METHOD_HANDLER(college, Organization)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "User::toJSON(%p)", &json) - - json.toJSON(U_JSON_METHOD_HANDLER(token, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(name, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(pic, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(applePushToken, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(directory, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(socials, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(links, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(points, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(spotCount, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(visibility, bool)); - json.toJSON(U_JSON_METHOD_HANDLER(aroundSince, int64_t)); - json.toJSON(U_JSON_METHOD_HANDLER(work, Organization)); - json.toJSON(U_JSON_METHOD_HANDLER(college, Organization)); + U_TRACE_NO_PARAM(5, "User::toJSON()") + + U_JSON_TYPE_HANDLER(token, UString); + U_JSON_TYPE_HANDLER(name, UString); + U_JSON_TYPE_HANDLER(pic, UString); + U_JSON_TYPE_HANDLER(applePushToken, UString); + U_JSON_TYPE_HANDLER(directory, UString); + U_JSON_TYPE_HANDLER(socials, UVector); + U_JSON_TYPE_HANDLER(links, UVector); + U_JSON_TYPE_HANDLER(points, unsigned); + U_JSON_TYPE_HANDLER(spotCount, unsigned); + U_JSON_TYPE_HANDLER(visibility, bool); + U_JSON_TYPE_HANDLER(aroundSince, int64_t); + U_JSON_TYPE_HANDLER(work, Organization); + U_JSON_TYPE_HANDLER(college, Organization); } void fromJSON(UValue& json) @@ -535,14 +536,14 @@ class Event { json.toJSON(U_JSON_METHOD_HANDLER(dateTime, int64_t)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Event::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Event::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(actor, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(target, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(key, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(dateTime, int64_t)); + U_JSON_TYPE_HANDLER(actor, UString); + U_JSON_TYPE_HANDLER(target, UString); + U_JSON_TYPE_HANDLER(key, unsigned); + U_JSON_TYPE_HANDLER(dateTime, int64_t); } void fromJSON(UValue& json) @@ -615,26 +616,26 @@ class ResponseLogin { json.toJSON(U_JSON_METHOD_HANDLER(college, Organization)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "ResponseLogin::toJSON(%p)", &json) - - json.toJSON(U_JSON_METHOD_HANDLER(spotCount, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(type, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(token, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(name, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(pic, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(directory, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(actives, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(nows, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(freeFileNames, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(links, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(users, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(messages, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(events, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(socials, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(work, Organization)); - json.toJSON(U_JSON_METHOD_HANDLER(college, Organization)); + U_TRACE_NO_PARAM(5, "ResponseLogin::toJSON()") + + U_JSON_TYPE_HANDLER(spotCount, unsigned); + U_JSON_TYPE_HANDLER(type, UString); + U_JSON_TYPE_HANDLER(token, UString); + U_JSON_TYPE_HANDLER(name, UString); + U_JSON_TYPE_HANDLER(pic, UString); + U_JSON_TYPE_HANDLER(directory, UString); + U_JSON_TYPE_HANDLER(actives, UVector); + U_JSON_TYPE_HANDLER(nows, UVector); + U_JSON_TYPE_HANDLER(freeFileNames, UVector); + U_JSON_TYPE_HANDLER(links, UVector); + U_JSON_TYPE_HANDLER(users, UVector); + U_JSON_TYPE_HANDLER(messages, UVector); + U_JSON_TYPE_HANDLER(events, UVector); + U_JSON_TYPE_HANDLER(socials, UVector); + U_JSON_TYPE_HANDLER(work, Organization); + U_JSON_TYPE_HANDLER(college, Organization); } void fromJSON(UValue& json) @@ -678,13 +679,13 @@ class ResponseSearch { json.toJSON(U_JSON_METHOD_HANDLER(organizations, UVector)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "ResponseSearch::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "ResponseSearch::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(type, UString)); - json.toJSON(U_JSON_METHOD_HANDLER(key, unsigned)); - json.toJSON(U_JSON_METHOD_HANDLER(organizations, UVector)); + U_JSON_TYPE_HANDLER(type, UString); + U_JSON_TYPE_HANDLER(key, unsigned); + U_JSON_TYPE_HANDLER(organizations, UVector); } void fromJSON(UValue& json) @@ -731,7 +732,7 @@ class Multiple { request.clear(); response.clear(); - presponse = 0; + presponse = U_NULLPTR; } void toJSON(UString& json) @@ -745,15 +746,15 @@ class Multiple { json.toJSON(U_JSON_METHOD_HANDLER(presponse, Response)); } - void toJSON(UValue& json) + void toJSON() { - U_TRACE(5, "Multiple::toJSON(%p)", &json) + U_TRACE_NO_PARAM(5, "Multiple::toJSON()") - json.toJSON(U_JSON_METHOD_HANDLER(organizations, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(vrequests, UVector)); - json.toJSON(U_JSON_METHOD_HANDLER(request, Request)); - json.toJSON(U_JSON_METHOD_HANDLER(response, Response)); - json.toJSON(U_JSON_METHOD_HANDLER(presponse, Response)); + U_JSON_TYPE_HANDLER(organizations, UVector); + U_JSON_TYPE_HANDLER(vrequests, UVector); + U_JSON_TYPE_HANDLER(request, Request); + U_JSON_TYPE_HANDLER(response, Response); + U_JSON_TYPE_HANDLER(presponse, Response); } void fromJSON(UValue& json) @@ -778,6 +779,7 @@ static void testMap() UString result, mapJson = U_STRING_FROM_CONSTANT("{\"key1\":\"riga 1\",\"key2\":\"riga 2\",\"key3\":\"riga 3\",\"key4\":\"riga 4\"}"); bool ok = JSON_parse(mapJson, x); + U_INTERNAL_ASSERT(ok) ok = (x["key1"] == U_STRING_FROM_CONSTANT("riga 1")); @@ -878,7 +880,6 @@ static void testRequest() UValue json_obj; Request request; const char* dump; - UString result, reqJson = U_STRING_FROM_CONSTANT("{\"table\":{\"type\":\"localesData\",\"token\":\"A619828KAIJ6D3\"},\"radius\":\"near\",\"location\":\"40.7831 N, 73.9712 W\",\"fbPermissions\":[\"public_profile\",\"user_friends\",\"email\"]}"); bool ok = JSON_parse(reqJson, request); @@ -979,9 +980,11 @@ static void testResponseLogin() U_ASSERT(response.college.name.empty()) U_ASSERT_EQUALS(response.socials[0]->key, 3) -// JSON_stringify(result, json_obj, response); + JSON_stringify(result, json_obj, response); + // (void) UFile::writeToTmp(U_STRING_TO_PARAM(result), O_RDWR | O_TRUNC, U_CONSTANT_TO_PARAM("test_json.%P"), 0); -// U_ASSERT_EQUALS( result, reqJson ) + + U_ASSERT_EQUALS( result.size(), reqJson.size() ) result.clear(); @@ -996,7 +999,6 @@ static void testResponseSearch() UValue json_obj; ResponseSearch response; -// {"type":"localesData","key":0,"organizations":[{},{},{},{},{},"Texas A&M University--Commerce","S267"]} UString result, reqJson = U_STRING_FROM_CONSTANT("{\"type\":\"localesData\",\"key\":0,\"organizations\":[{\"name\":\"Temple University\",\"index\":\"S119\"},{\"name\":\"Tennessee State University\",\"index\":\"S266\"},{\"name\":\"Tennessee Technological University\",\"index\":\"S224\"},{\"name\":\"Texas A&M University--College Station\",\"index\":\"S75\"},{\"name\":\"Texas A&M University--Commerce\",\"index\":\"S267\"}]}"); bool ok = JSON_parse(reqJson, response); @@ -1010,9 +1012,11 @@ static void testResponseSearch() U_ASSERT_EQUALS(response.organizations[4]->name, "Texas A&M University--Commerce") U_ASSERT_EQUALS(response.organizations[4]->index, "S267") -// JSON_stringify(result, json_obj, response); + JSON_stringify(result, json_obj, response); + // (void) UFile::writeToTmp(U_STRING_TO_PARAM(result), O_RDWR | O_TRUNC, U_CONSTANT_TO_PARAM("test_json.%P"), 0); -// U_ASSERT_EQUALS( result, reqJson ) + + U_ASSERT_EQUALS( result, reqJson ) result.clear(); @@ -1028,7 +1032,6 @@ static void testMultiple() UValue json_obj; const char* dump; Multiple multiple; -//{"organizations":[{},{},{},{},{},"Texas A&M University--Commerce","S267"],"vrequests":[],"request":{"table":{"type":"localesData","token":"A619828KAIJ6D3"},"radius":"near","location":"40.7831 N, 73.9712 W","fbPermissions":["public_profile","user_friends","email"]},"response":{"fbPermissions":["public_profile","user_friends","email"],"type":"startup","token":"","table":{"type":"localesData","token":"A619828KAIJ6D3"}},"presponse":{"fbPermissions":[],"type":"","token":"","table":{}}} UString result, reqJson = U_STRING_FROM_CONSTANT("{" "\"organizations\":[{\"name\":\"Temple University\",\"index\":\"S119\"},{\"name\":\"Tennessee State University\",\"index\":\"S266\"},{\"name\":\"Tennessee Technological University\",\"index\":\"S224\"},{\"name\":\"Texas A&M University--College Station\",\"index\":\"S75\"},{\"name\":\"Texas A&M University--Commerce\",\"index\":\"S267\"}]," "\"vrequests\":[]," @@ -1079,9 +1082,11 @@ static void testMultiple() U_INTERNAL_ASSERT(ok) -// JSON_stringify(result, json_obj, multiple); + JSON_stringify(result, json_obj, multiple); + // (void) UFile::writeToTmp(U_STRING_TO_PARAM(result), O_RDWR | O_TRUNC, U_CONSTANT_TO_PARAM("test_json.%P"), 0); -// U_ASSERT_EQUALS( result, reqJson ) + + U_ASSERT_EQUALS( result, reqJson ) result.clear(); diff --git a/ulib.html b/ulib.html deleted file mode 100644 index 8fc61e3c5..000000000 --- a/ulib.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - -ULib - - - - - - - - -
-

ULib

- -
-

1 Getting Started With ULib

-
-

-To help those curious souls that want to see if userver is a good fit for their needs I have recorded my own experiences below. -Firstly a huge thankyou to Stefano Casazza not only for making ULib but for all his patience in answering all my questions. -

-
- -
-

1.1 What is userver

-
-

-UServer is a extensible plugin based web server that is build on top of ULib. -

- -

-ULib is installed as a set of shared object libraries and header files (like Boost). -

-
-
- -
-

1.2 Get a copy of the ULib source code

- -
- -
-

1.3 configure your build

-
-

-For those of you like me who havn't had much experience playing with autotools read the config help or: -

- -

-./configure -h -

- -

-Having now decided on what features you need let ./configure do its magic. -

- -

-For example: -./configure –enable-debug –with-sqlite3 -

- -

-make -sudo make install -

-
-
- -
-

1.4 configure userver

-
-

-Assuming you haven't changed the PREFIX make will install userver to /usr/local -

- -

-At this point we need to configure /usr/local/etc/userver.cfg -The file is well annotated at a bare minimum setup the following values: -
- DOCUMENT_ROOT /var/www
- LOG_FILE userver.log
- PLUGIN "http"
- PLUGIN_DIR /usr/local/libexec
- ORM_DRIVER_DIR /usr/local/libexec
-

-
-
-

-This environment variables are for ORM management: -
- ORM_DRIVER "sqlite"
- ORM_OPTION "host=localhost user=user password=pass character-set=utf8 dbname=/path_to_db/dbname.db" -

-
-
- -
-

1.5 debug environment

-
-

-userver_tcp expects some environment variables for debug mode to save typing it is easiest to put these into a bash script like this: -

- -

-#!/bin/sh -

- -

- UTRACE="0 20M 0"
- UTRACE_SIGNAL="0 20M 0"
-#UOBJDUMP="0 10M 100"
-#USIMERR="error.sim"
- export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL -

- -

-userver_tcp -

-
-
- - -
-

1.6 Running your server (static pages)

-
-

-Once you have configured your userver.cfg and placed the relevant html documents in your docroot just execute the bash script above. -

- -

-Point your browser to localhost/filename you should now have a working server. -

-
-
- -
-

1.7 USP ULib Servlet Page (dynamic pages)

-
-

-userver offers a wide variety of ways to generate dynamic content we will be looking at USP method. -

- -

-A USP page is a multi-format document that permits c++ code to be embedded into html. -This document is then compiled into a shared object library that will be executed by userver. -

- -

-The document consists of overloaded html comment tags that the USP compiler will extract. -

-
-
- -
-

1.8 Tags

-
-

-Have a look at the examples in the ULib source directory ULib/src/ulib/net/server/plugin/usp for usage but in very simple terms. -

-
- -
-

1.8.1 c++ header file .h

-
-

-<!–#declaration -–> -

-
-
- -
-

1.8.2 c++ code file .cpp

-
-

-<!–#code -UString name = U_STRING_FROM_CONSTANT("Hello World"); -–> -

-
-
- -
-

1.8.3 html template

-
-

-<h1>Hello <!–#xmlputs name –></h1> -

-
-
-
- -
-

1.9 Compiling

-
-

-Once you have written your .usp file it needs to be compiled. -I found it easiest to navigate to the folder where the file.usp was saved and execute the compilation in the shell for example: -

- -

-cd /srv/http/servlet -/usr/local/bin/usp_compile.sh test -

- -

-Please note that usp_compile.sh wants the usp file without the extension. -The shell script will call the relevant programs to generate c++ code from the usp file and finally call gcc and libtool to create a shared library.Any compilation errors will be output to console and no .so file will be generated. -

- -

-It would be trivial to execute usp_compile as a custom command from most IDEs. -

-
-
- -
-

1.10 Test

-
-

-Now point your browser to localhost/nameofusp and userver will execute the USP file. -

-
-
- -
-

1.11 SECURITY

-
-

-As with all web servers do not run them as the root user. -This introduction has been written to give you an idea of the ULib/UServer workflow. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. It is your responsibility to secure your web server and follow sound security conscious programming practices. -

-
-
- - -
-

Author: nemsys

-

Created: 2017-05-07 Sun 13:21

-

Emacs 25.2.1 (Org mode 8.2.10)

-

Validate

-
- -