1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
This commit is contained in:
stefanocasazza 2019-03-19 15:21:10 +01:00
parent 4b4ee22cff
commit 63ee2126b2
8 changed files with 245 additions and 39 deletions

View File

@ -767,6 +767,34 @@ static inline unsigned long u_atoi(const char* restrict s)
#endif
}
static inline bool u_trim(const char** restrict s, uint32_t* n)
{
// skip white space from start
uint32_t _length = *n;
const char* restrict str = *s;
while (_length && u__isspace(*str))
{
++str;
--_length;
}
// skip white space from end
while (_length && u__isspace(str[_length-1])) --_length;
if (_length != *n)
{
*n = _length;
*s = str;
return true;
}
return false;
}
U_EXPORT int8_t u_log2(uint64_t value) __pure;
static inline unsigned u__octc2int(unsigned char c) { return ((c - '0') & 07); }

View File

@ -18,6 +18,10 @@
#include <math.h>
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX17)
# include <functional>
#endif
/**
* \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
*
@ -593,6 +597,12 @@ public:
static int jreadArrayStep(const UString& jarray, UString& result); // assumes jarray points at the start of an array or array element
// by Victor Stewart
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX17)
static void consumeFieldsAndValues(const UString& json, std::function<void(const UString&, const UString&)> consumer); // assumes perfect construction
#endif
#ifdef DEBUG
const char* dump(bool _reset) const;
@ -1063,6 +1073,7 @@ protected:
private:
static int jread_skip(UTokenizer& tok) U_NO_EXPORT;
static int jreadFindToken(UTokenizer& tok) U_NO_EXPORT;
static int jreadAdvanceAndFindToken(UTokenizer& tok) U_NO_EXPORT;
static UString jread_string(UTokenizer& tok) U_NO_EXPORT;
static UString jread_object(UTokenizer& tok) U_NO_EXPORT;

View File

@ -31,7 +31,7 @@ enum StringAllocationType {
};
enum StringAllocationIndex {
STR_ALLOCATE_INDEX_SOAP = 20,
STR_ALLOCATE_INDEX_SOAP = 21,
STR_ALLOCATE_INDEX_IMAP = STR_ALLOCATE_INDEX_SOAP+14,
STR_ALLOCATE_INDEX_SSI = STR_ALLOCATE_INDEX_IMAP+4,
STR_ALLOCATE_INDEX_NOCAT = STR_ALLOCATE_INDEX_SSI+2,
@ -810,7 +810,16 @@ public:
// for constant string
void trim();
void trim()
{
U_TRACE_NO_PARAM(0, "UStringRep::trim()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_EQUALS(_capacity, 0)
(void) u_trim(&str, &_length);
}
// if the string is quoted...
@ -1149,6 +1158,7 @@ public:
static const UString* str_false;
static const UString* str_response;
static const UString* str_zero;
static const UString* str_one;
static const UString* str_nostat;
static const UString* str_tsa;
static const UString* str_soap;
@ -1611,6 +1621,30 @@ public:
return substr(rep->str + pos, rep->fold(pos, n));
}
UString substrTrim(const char* t, uint32_t tlen) const
{
U_TRACE(0, "UString::substrTrim(%.*S,%u)", tlen, t, tlen)
if (tlen == 0 ||
(u_trim(&t, &tlen) && tlen == 0))
{
return *string_null;
}
UString result(rep, t, tlen);
U_RETURN_STRING(result);
}
UString substrTrim(uint32_t pos, uint32_t n = U_NOT_FOUND) const
{
U_TRACE(0, "UString::substrTrim(%u,%u)", pos, n)
U_INTERNAL_ASSERT(pos <= rep->_length)
return substrTrim(rep->str + pos, rep->fold(pos, n));
}
bool isSubStringOf(const UString& str) const { return rep->isSubStringOf(str.rep); }
// destructor

View File

@ -268,6 +268,28 @@ public:
U_RETURN_STRING(result);
}
UString substrTrim() const
{
U_TRACE_NO_PARAM(0, "UTokenizer::substrTrim()")
UString result;
if (s < end) result = str.substrTrim(str.distance(s));
U_RETURN_STRING(result);
}
UString substrTrim(const char* start) const
{
U_TRACE(0, "UTokenizer::substrTrim(%p)", start)
UString result;
if (start < end) result = str.substrTrim(start, s - start);
U_RETURN_STRING(result);
}
UString getTokenQueryParser();
int getTokenId(UString* ptoken);

View File

@ -1939,6 +1939,15 @@ U_NO_EXPORT int UValue::jreadFindToken(UTokenizer& tok)
U_RETURN(-1);
}
U_NO_EXPORT int UValue::jreadAdvanceAndFindToken(UTokenizer& tok)
{
U_TRACE(0, "UValue::jreadAdvanceAndFindToken(%p)", &tok)
tok.advance();
return jreadFindToken(tok);
}
U_NO_EXPORT int UValue::jread_skip(UTokenizer& tok)
{
U_TRACE(0, "UValue::jread_skip(%p)", &tok)
@ -2612,6 +2621,113 @@ int UValue::jreadArrayStep(const UString& jarray, UString& result)
U_RETURN(jTok);
}
// by Victor Stewart
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX17)
void UValue::consumeFieldsAndValues(const UString& json, std::function<void(const UString&, const UString&)> consumer) // assumes perfect construction
{
U_TRACE(0, "UValue::consumeFieldsAndValues(%V,%p)", json.rep, &consumer)
int jTok;
UTokenizer tok(json);
UString field, value;
const char* fieldStart;
const char* valueStart;
while ((jTok = jreadFindToken(tok)) != U_JR_EOL)
{
U_DUMP("jTok = (%d,%S)", jTok, getDataTypeDescription(jTok))
// all fields must be encapsulated by quotations
if (jTok != U_STRING_VALUE)
{
tok.advance(); // aka skip opening bracket and commas
continue;
}
fieldStart = tok.getPointer() + 1;
// find closing quotation
while (jreadAdvanceAndFindToken(tok) != U_STRING_VALUE) {};
// capture field name
field = tok.substr(fieldStart);
// skip til colon
while (jreadAdvanceAndFindToken(tok) != U_JR_COLON) {};
// skip past the colon it enters on
switch (jreadAdvanceAndFindToken(tok))
{
case U_REAL_VALUE:
{
// skip ahead til either we hit a space or a comma
valueStart = tok.getPointer();
while (jreadAdvanceAndFindToken(tok) != U_REAL_VALUE) {};
value = tok.substrTrim(valueStart); // possible space between end of value and comma
}
break;
case U_TRUE_VALUE: value = *UString::str_one; break;
case U_FALSE_VALUE: value = *UString::str_zero; break;
case U_STRING_VALUE:
{
valueStart = tok.getPointer() + 1;
while (jreadAdvanceAndFindToken(tok) != U_STRING_VALUE) {};
value = tok.substr(valueStart);
}
break;
case U_ARRAY_VALUE:
case U_OBJECT_VALUE:
{
int hunting = 1;
valueStart = tok.getPointer();
do {
switch (jreadAdvanceAndFindToken(tok))
{
case U_REAL_VALUE:
case U_TRUE_VALUE:
case U_FALSE_VALUE:
// case U_NULL_VALUE:
case U_STRING_VALUE:
case U_JR_COLON:
case U_JR_COMMA:
// case U_JR_QPARAM:
break;
case U_JR_EARRAY:
case U_JR_EOBJECT: --hunting; break;
case U_ARRAY_VALUE:
case U_OBJECT_VALUE: ++hunting; break;
}
}
while (hunting > 0);
// we are on the ending char/boundary of a container
tok.advance();
value = tok.substr(valueStart);
}
break;
}
consumer(field, value);
field.clear();
value.clear();
}
}
#endif
// DEBUG
#ifdef DEBUG

View File

@ -40,6 +40,7 @@ const UString* UString::str_true;
const UString* UString::str_false;
const UString* UString::str_response;
const UString* UString::str_zero;
const UString* UString::str_one;
const UString* UString::str_nostat;
const UString* UString::str_tsa;
const UString* UString::str_soap;
@ -181,9 +182,9 @@ const UString* UString::str_ULib;
#endif
#ifdef U_HTTP2_DISABLE
static ustringrep stringrep_storage[74] = {
static ustringrep stringrep_storage[75] = {
#else
static ustringrep stringrep_storage[138] = {
static ustringrep stringrep_storage[139] = {
#endif
{ U_STRINGREP_FROM_CONSTANT("host") },
{ U_STRINGREP_FROM_CONSTANT("chunked") },
@ -199,6 +200,7 @@ static ustringrep stringrep_storage[138] = {
{ U_STRINGREP_FROM_CONSTANT("false") },
{ U_STRINGREP_FROM_CONSTANT("response") },
{ U_STRINGREP_FROM_CONSTANT("0") },
{ U_STRINGREP_FROM_CONSTANT("1") },
{ U_STRINGREP_FROM_CONSTANT("/nostat") },
{ U_STRINGREP_FROM_CONSTANT("/tsa") },
{ U_STRINGREP_FROM_CONSTANT("/soap") },
@ -356,6 +358,7 @@ void UString::str_allocate(int which)
U_INTERNAL_ASSERT_EQUALS(str_false, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(str_response, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(str_zero, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(str_one, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(str_nostat, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(str_tsa, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(str_soap, U_NULLPTR)
@ -377,13 +380,14 @@ void UString::str_allocate(int which)
U_NEW_ULIB_STRING(str_false, UString(stringrep_storage+11));
U_NEW_ULIB_STRING(str_response, UString(stringrep_storage+12));
U_NEW_ULIB_STRING(str_zero, UString(stringrep_storage+13));
U_NEW_ULIB_STRING(str_nostat, UString(stringrep_storage+14));
U_NEW_ULIB_STRING(str_tsa, UString(stringrep_storage+15));
U_NEW_ULIB_STRING(str_soap, UString(stringrep_storage+16));
U_NEW_ULIB_STRING(str_path_root, UString(stringrep_storage+17));
U_NEW_ULIB_STRING(str_asterisk, UString(stringrep_storage+18));
U_NEW_ULIB_STRING(str_one, UString(stringrep_storage+14));
U_NEW_ULIB_STRING(str_nostat, UString(stringrep_storage+15));
U_NEW_ULIB_STRING(str_tsa, UString(stringrep_storage+16));
U_NEW_ULIB_STRING(str_soap, UString(stringrep_storage+17));
U_NEW_ULIB_STRING(str_path_root, UString(stringrep_storage+18));
U_NEW_ULIB_STRING(str_asterisk, UString(stringrep_storage+19));
uustringrep key1 = { stringrep_storage+19 };
uustringrep key1 = { stringrep_storage+20 };
pkey = key1.p2;
@ -530,7 +534,7 @@ void UString::str_allocate(int which)
else if ((which & STR_ALLOCATE_HTTP2) != 0)
{
U_INTERNAL_ASSERT_EQUALS(str_authority, U_NULLPTR)
U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 138)
U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 139)
U_NEW_ULIB_STRING(str_authority, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP2+0));
U_NEW_ULIB_STRING(str_method, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP2+1));
@ -598,7 +602,7 @@ void UString::str_allocate(int which)
U_NEW_ULIB_STRING(str_ULib, UString(stringrep_storage+STR_ALLOCATE_INDEX_HTTP2+63));
}
#else
U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 74)
U_INTERNAL_ASSERT_EQUALS(U_NUM_ELEMENTS(stringrep_storage), 75)
#endif
}
@ -1074,29 +1078,6 @@ uint32_t UStringRep::copy(char* s, uint32_t n, uint32_t pos) const
U_RETURN(n);
}
void UStringRep::trim()
{
U_TRACE_NO_PARAM(0, "UStringRep::trim()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_EQUALS(_capacity, 0)
// skip white space from start
while (_length && u__isspace(*str))
{
++str;
--_length;
}
U_INTERNAL_DUMP("_length = %u", _length)
// skip white space from end
while (_length && u__isspace(str[_length-1])) --_length;
}
__pure int UStringRep::compare(const UStringRep* rep, uint32_t depth) const
{
U_TRACE(0, "UStringRep::compare(%p,%u)", rep, depth)

View File

@ -1 +1 @@
04D1
04EC

View File

@ -138,6 +138,18 @@ U_EXPORT main (int argc, char* argv[], char* env[])
U_TRACE(5, "main(%d)", argc)
UString workingString;
// by Victor Stewart
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX17)
workingString = U_STRING_FROM_CONSTANT("{\"ABC\":{\"eventKey\":0,\"eventTime\":18212931298},\"XYZ\":{\"eventKey\":1,\"eventTime\":1111131298}}");
UValue::consumeFieldsAndValues(workingString, [&] (const UString& field, const UString& value) -> void {
u__printf(STDERR_FILENO, U_CONSTANT_TO_PARAM("field = %V\nvalue = %V\n"), field.rep, value.rep);
});
#endif
UValue json;
UCrono crono;
char buffer[4096];
@ -350,8 +362,8 @@ U_EXPORT main (int argc, char* argv[], char* env[])
int city;
double pricePoint;
UString workingString, query(U_STRING_FROM_CONSTANT("{ \"colorShifts\" : { \"H67\" : -1 }, \"name\" : \"Mr. Taka Ramen\", \"category\" : 39, \"grouping\" : 0,"
" \"bumpUp\" : false, \"businessID\" : \"B5401\", \"foundationColor\" : 3, \"coordinates\" : [ -73.9888983, 40.7212405 ] }"));
UString query(U_STRING_FROM_CONSTANT("{ \"colorShifts\" : { \"H67\" : -1 }, \"name\" : \"Mr. Taka Ramen\", \"category\" : 39, \"grouping\" : 0,"
" \"bumpUp\" : false, \"businessID\" : \"B5401\", \"foundationColor\" : 3, \"coordinates\" : [ -73.9888983, 40.7212405 ] }"));
(void) U_JFIND(U_STRING_FROM_CONSTANT("{ \"pricePoint\" : 2.48333333333333, \"socialWeight\" : 8.75832720587083, \"gender\" : 0, \"lessThan16\" : false }"),
"pricePoint", pricePoint);
@ -362,6 +374,8 @@ U_EXPORT main (int argc, char* argv[], char* env[])
U_INTERNAL_ASSERT_EQUALS(city, 0)
workingString.clear();
(void) UValue::jread(query, U_STRING_FROM_CONSTANT("{'coordinates' [0"), workingString);
U_INTERNAL_ASSERT_EQUALS(workingString, "-73.9888983")
@ -372,8 +386,8 @@ U_EXPORT main (int argc, char* argv[], char* env[])
U_INTERNAL_ASSERT_EQUALS(workingString, "[ -73.9888983, 40.7212405 ]")
result1.clear();
workingString.clear();
result1.clear();
(void) U_JFIND(U_STRING_FROM_CONSTANT("{\"saltedHash\":\"f66113b5ed33f961219c\",\"osVersion\":\"10.3.1\",\"socials\":[{\"name\":\"victor]},\"t\":\"createAccount\"}"),
"t", result1);