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 2016-08-25 15:46:54 +02:00
parent ee3e6f5741
commit 117008cfbc
16 changed files with 371 additions and 422 deletions

2
configure vendored
View File

@ -1762,7 +1762,7 @@ Optional Features:
--enable-stdcpp compile with stdc++ runtime overhead [default=yes]
--enable-debug compile for debugging [default=no]
--enable-unaligned compile for target that allows unaligned reads and writes [default=yes]
--enable-apexmem use apex_memmove written by Trevor Herselman in 2014 [default=yes]
--enable-apexmem use apex_memmove written by Trevor Herselman in 2014 [default=no]
--enable-thread enable build of thread support [default=yes]
--enable-pth always use GNU pth for threading [default=no]
--enable-examples enable building of examples [default=yes]

View File

@ -672,7 +672,7 @@ else
fi
AC_MSG_CHECKING(for apex memcpy/memmove)
AC_ARG_ENABLE(apexmem, [ --enable-apexmem use apex_memmove written by Trevor Herselman in 2014 [[default=yes]]])
AC_ARG_ENABLE(apexmem, [ --enable-apexmem use apex_memmove written by Trevor Herselman in 2014 [[default=no]]])
if test -z "$enable_apexmem"; then
enable_apexmem="no"

View File

@ -35,9 +35,9 @@
# ifndef LINUX_VERSION_CODE
# error "You need to use at least 2.0 Linux kernel."
# endif
# ifdef U_APEX_ENABLE
# include <ulib/base/apex/apex_memmove.h>
# endif
# ifdef U_APEX_ENABLE
# include <ulib/base/apex/apex_memmove.h>
# endif
#endif
#ifdef USE_LIBSSL

View File

@ -19,73 +19,103 @@
#undef GCC_VERSION
#include <ulib/base/base.h>
#define U_hash_size(n) (1U<<(n))
#define U_hash_mask(n) (U_hash_size(n)-1U)
/* get next prime number for container */
#define U_GET_NEXT_PRIME_NUMBER(sz) ((sz) <= 53U ? 97U : \
(sz) <= 97U ? 193U : \
(sz) <= 193U ? 389U : \
(sz) <= 389U ? 769U : \
(sz) <= 769U ? 1543U : \
(sz) <= 1543U ? 3079U : \
(sz) <= 3079U ? 6151U : \
(sz) <= 6151U ? 12289U : \
(sz) <= 12289U ? 24593U : \
(sz) <= 24593U ? 49157U : \
(sz) <= 49157U ? 98317U : \
(sz) <= 98317U ? 196613U : \
(sz) <= 196613U ? 393241U : \
(sz) <= 393241U ? 786433U : \
(sz) <= 786433U ? 1572869U : \
(sz) <= 1572869U ? 3145739U : \
(sz) <= 3145739U ? 6291469U : \
(sz) <= 6291469U ? 12582917U : \
(sz) <= 12582917U ? 25165843U : \
(sz) <= 25165843U ? 50331653U : \
(sz) <= 50331653U ? 100663319U : \
(sz) <= 100663319U ? 201326611U : \
(sz) <= 201326611U ? 402653189U : \
(sz) <= 402653189U ? 805306457U : \
(sz) <= 805306457U ? 805306457U : \
(sz) <= 1610612741U ? 3221225473U : 4294967291U)
#define U_GET_NEXT_PRIME_NUMBER(sz) \
((sz) <= 53U ? 97U : \
(sz) <= 97U ? 193U : \
(sz) <= 193U ? 389U : \
(sz) <= 389U ? 769U : \
(sz) <= 769U ? 1543U : \
(sz) <= 1543U ? 3079U : \
(sz) <= 3079U ? 6151U : \
(sz) <= 6151U ? 12289U : \
(sz) <= 12289U ? 24593U : \
(sz) <= 24593U ? 49157U : \
(sz) <= 49157U ? 98317U : \
(sz) <= 98317U ? 196613U : \
(sz) <= 196613U ? 393241U : \
(sz) <= 393241U ? 786433U : \
(sz) <= 786433U ? 1572869U : \
(sz) <= 1572869U ? 3145739U : \
(sz) <= 3145739U ? 6291469U : \
(sz) <= 6291469U ? 12582917U : \
(sz) <= 12582917U ? 25165843U : \
(sz) <= 25165843U ? 50331653U : \
(sz) <= 50331653U ? 100663319U : \
(sz) <= 100663319U ? 201326611U : \
(sz) <= 201326611U ? 402653189U : \
(sz) <= 402653189U ? 805306457U : \
(sz) <= 805306457U ? 805306457U : \
(sz) <= 1610612741U ? 3221225473U : 4294967291U)
#ifdef __cplusplus
extern "C" {
#endif
U_EXPORT uint32_t u_random( uint32_t val) __pure; /* quick 4byte hashing function */
/* hash variable-length key into 32-bit value */
static inline uint32_t u_xxhash32(const unsigned char* restrict t, uint32_t tlen) { return XXH32(t, tlen, u_seed_hash); }
static inline uint32_t u_xxhash64(const unsigned char* restrict t, uint32_t tlen)
{ return (uint32_t)(((XXH64(t, tlen, u_seed_hash) * (1578233944ULL << 32 | 194370989ULL)) + (20591ULL << 16)) >> 32); }
#ifdef USE_HARDWARE_CRC32
static inline uint32_t u_crc32(const unsigned char* restrict bp, uint32_t len)
{
U_INTERNAL_TRACE("u_crc32(%.*s,%u)", U_min(len,128), bp, len)
uint32_t h1 = 0xABAD1DEA;
# ifdef HAVE_ARCH64
while (len >= sizeof(uint64_t))
{
h1 = __builtin_ia32_crc32di(h1, u_get_unalignedp64(bp));
bp += sizeof(uint64_t);
len -= sizeof(uint64_t);
}
# endif
while (len >= sizeof(uint32_t))
{
h1 = __builtin_ia32_crc32si(h1, u_get_unalignedp32(bp));
bp += sizeof(uint32_t);
len -= sizeof(uint32_t);
}
if (len >= sizeof(uint16_t))
{
h1 = __builtin_ia32_crc32hi(h1, u_get_unalignedp16(bp));
bp += sizeof(uint16_t);
len -= sizeof(uint16_t);
}
if (len) h1 = __builtin_ia32_crc32qi(h1, *bp);
U_INTERNAL_PRINT("h1 = %u", h1)
U_INTERNAL_ASSERT_MAJOR(h1, 0)
return h1;
}
static inline uint32_t u_hash(const unsigned char* restrict t, uint32_t tlen) { return u_crc32(t, tlen); }
#elif defined(HAVE_ARCH64)
static inline uint32_t u_hash(const unsigned char* restrict t, uint32_t tlen) { return u_xxhash64(t, tlen); }
# else
static inline uint32_t u_hash(const unsigned char* restrict t, uint32_t tlen) { return u_xxhash32(t, tlen); }
#endif
U_EXPORT uint32_t u_hash_ignore_case(const unsigned char* restrict t, uint32_t tlen) __pure;
U_EXPORT uint32_t u_cdb_hash(const unsigned char* restrict t, uint32_t tlen, int flags) __pure;
U_EXPORT uint32_t u_random(uint32_t val) __pure; /* quick 4byte hashing function */
#ifdef HAVE_ARCH64
U_EXPORT uint32_t u_random64(uint64_t ptr) __pure;
#endif
static inline double u_randomd(uint32_t a) { return (1.0/4294967296.0) * u_random(a); } /* Map hash value into number 0.0 <= n < 1.0 */
/* hash variable-length key into 32-bit value */
U_EXPORT uint32_t murmurhash3_x86_32_ignore_case(unsigned char* restrict t, uint32_t tlen) __pure;
U_EXPORT uint32_t u_cdb_hash( unsigned char* restrict t, uint32_t tlen, int flags) __pure;
static inline uint32_t u_hash_ignore_case(unsigned char* restrict t, uint32_t tlen) { return murmurhash3_x86_32_ignore_case(t, tlen); }
#ifdef USE_HARDWARE_CRC32
U_EXPORT uint32_t u_crc32(unsigned char* restrict t, uint32_t tlen) __pure;
static inline uint32_t u_hash(unsigned char* restrict t, uint32_t tlen) { return u_crc32(t, tlen); }
#else
U_EXPORT uint32_t u_fhash(unsigned char* restrict t, uint32_t tlen) __pure;
# ifndef HAVE_ARCH64
U_EXPORT uint32_t u_hash(unsigned char* restrict t, uint32_t tlen) __pure;
# else
U_EXPORT uint32_t murmurhash3_x86_64(unsigned char* restrict t, uint32_t tlen) __pure;
static inline uint32_t u_hash_old(unsigned char* restrict t, uint32_t tlen) { return murmurhash3_x86_64(t, tlen); }
static inline uint32_t u_hash(unsigned char* restrict t, uint32_t tlen) { return (uint32_t)(((XXH64(t,tlen,u_seed_hash) * (1578233944ULL << 32 | 194370989ULL)) + (20591U << 16)) >> 32); }
# endif
#endif
#ifdef __cplusplus
}
#endif

View File

@ -152,9 +152,6 @@ U_EXPORT bool u_isNumber(const char* restrict s, uint32_t n) __pure;
U_EXPORT void u_printSize(char* restrict buffer, uint64_t bytes); /* print size using u_calcRate() */
U_EXPORT bool u_rmatch(const char* restrict haystack, uint32_t haystack_len, const char* restrict needle, uint32_t needle_len) __pure;
U_EXPORT uint32_t u_findEndHeader( const char* restrict s, uint32_t n) __pure; /* find sequence of U_CRLF2 or U_LF2 */
U_EXPORT uint32_t u_findEndHeader1(const char* restrict s, uint32_t n) __pure; /* find sequence of U_CRLF2 */
static inline void* u_find(const char* restrict a, uint32_t n1, const char* restrict b, uint32_t n2) /* check if string b is contained within string a */
{
U_INTERNAL_TRACE("u_find(%.*s,%u,%.*s,%u)", U_min(n1,128), a, n1, U_min(n2,128), b, n2)
@ -166,6 +163,21 @@ static inline void* u_find(const char* restrict a, uint32_t n1, const char* rest
return memmem(a, n1, b, n2);
}
static inline uint32_t u_findEndHeader1(const char* restrict s, uint32_t n) /* find sequence of U_CRLF2 */
{
void* p;
U_INTERNAL_TRACE("u_findEndHeader1(%.*s,%u)", U_min(n,128), s, n)
U_INTERNAL_ASSERT_POINTER(s)
p = memmem(s, n, U_CONSTANT_TO_PARAM(U_CRLF2));
return (p ? (const char*)p - s + U_CONSTANT_SIZE(U_CRLF2) : U_NOT_FOUND);
}
U_EXPORT uint32_t u_findEndHeader( const char* restrict s, uint32_t n) __pure; /* find sequence of U_CRLF2 or U_LF2 */
U_EXPORT bool u_endsWith(const char* restrict a, uint32_t n1, const char* restrict b, uint32_t n2) __pure; /* check if string a terminate with string b */
U_EXPORT bool u_startsWith(const char* restrict a, uint32_t n1, const char* restrict b, uint32_t n2) __pure; /* check if string a start with string b */

View File

@ -1214,4 +1214,49 @@ public:
}
};
#if defined(U_STDCPP_ENABLE)
# include <vector>
template <class T> class U_EXPORT UJsonTypeHandler<std::vector<T> > : public UJsonTypeHandler_Base {
public:
typedef std::vector<T> stdvector;
explicit UJsonTypeHandler(stdvector& val) : UJsonTypeHandler_Base(&val) {}
void toJSON(UValue& json)
{
U_TRACE(0, "UJsonTypeHandler<stdvector>::toJSON(%p)", &json)
U_ASSERT(json.isArray())
stdvector* pvec = (stdvector*)pval;
UValue* child;
for (uint32_t i = 0, n = pvec->size(); i < n; ++i)
{
U_NEW(UValue, child, UValue);
child->toJSON(UJsonTypeHandler<T>(pvec->at(i)));
UValue::appendNode(&json, child);
}
}
void fromJSON(UValue& json)
{
U_TRACE(0, "UJsonTypeHandler<stdvector>::fromJSON(%p)", &json)
U_ASSERT(json.isArray())
for (UValue* child = json.children.head; child; child = child->next)
{
T elem;
child->fromJSON(UJsonTypeHandler<T>(elem));
((stdvector*)pval)->push_back(elem);
}
}
};
#endif
#endif

View File

@ -1583,7 +1583,24 @@ public:
uint32_t find(const char* s, uint32_t pos, uint32_t s_len, uint32_t how_much = U_NOT_FOUND) const __pure;
uint32_t find(const UString& str, uint32_t pos = 0, uint32_t how_much = U_NOT_FOUND) const { return find(str.data(), pos, str.size(), how_much); }
uint32_t find(unsigned char c, uint32_t pos = 0) const __pure;
uint32_t find(unsigned char c, uint32_t pos = 0) const
{
U_TRACE(0, "UString::find(%C,%u)", c, pos)
uint32_t sz = size(),
ret = U_NOT_FOUND;
if (pos < sz)
{
const char* str = rep->str;
void* p = (void*) memchr(str + pos, c, sz - pos);
if (p) ret = (const char*)p - str;
}
U_RETURN(ret);
}
// The `rfind' function searches from end to beginning string for a specified string (possibly a single character)
// and returns its starting position. You can supply the parameter pos to specify the position where search must begin

View File

@ -214,7 +214,7 @@ public:
// convert tabs to spaces
static UString expandTab(const char* s, uint32_t n, int tab = 3);
static UString expandTab(const UString& s, int tab = 3) { return expandTab(U_STRING_TO_PARAM(s), tab); }
static UString expandTab(const UString& s, int tab = 3) { return expandTab(U_STRING_TO_PARAM(s), tab); }
// expand path (~/... and ~user/... plus $var and $var/...)
@ -223,18 +223,19 @@ public:
// prepare for environment variables (check if some of them need quoting...)
static UString prepareForEnvironmentVar(const UString& env) { return prepareForEnvironmentVar(U_STRING_TO_PARAM(env)); }
static UString prepareForEnvironmentVar(const char* s, uint32_t n);
static UString prepareForEnvironmentVar(const UString& env) { return prepareForEnvironmentVar(U_STRING_TO_PARAM(env)); }
// expand environment variables
static UString getEnvironmentVar(const UString& name, const UString* env) { return getEnvironmentVar(U_STRING_TO_PARAM(name), env); }
static UString getEnvironmentVar(const char* s, uint32_t n, const UString* env);
static UString getEnvironmentVar(const UString& name, const UString* env) { return getEnvironmentVar(U_STRING_TO_PARAM(name), env); }
// recursively expand environment variables if needed
static UString expandEnvironmentVar(const UString& s, const UString* env) { return expandEnvironmentVar(U_STRING_TO_PARAM(s), env); }
static UString expandEnvironmentVar(const char* s, uint32_t n, const UString* env);
static UString expandEnvironmentVar(const UString& s, const UString* env) { return expandEnvironmentVar(U_STRING_TO_PARAM(s), env); }
// eval expression
@ -255,58 +256,45 @@ public:
static UString removeEscape(const char* s, uint32_t n);
static UString insertEscape(const char* s, uint32_t n, char delimiter = '"');
static UString removeEscape(const UString& s)
{
U_TRACE(0, "UStringExt::removeEscape(%V)", s.rep)
uint32_t sz = s.size();
const char* str = s.data();
void* ptr = (void*) memchr(str, '\\', sz);
return (ptr ? removeEscape(str, sz) : s);
}
static UString insertEscape(const UString& s, char delimiter = '"')
{
U_TRACE(0, "UStringExt::insertEscape(%V,%C)", s.rep, delimiter)
uint32_t sz = s.size();
const char* str = s.data();
void* ptr = (void*) memchr(str, delimiter, sz);
return (ptr ? insertEscape(str, sz, delimiter) : s);
}
static UString removeEscape(const UString& s) { return removeEscape(U_STRING_TO_PARAM(s)); }
static UString insertEscape(const UString& s, char delimiter = '"') { return insertEscape(U_STRING_TO_PARAM(s), delimiter); }
// Returns a string that has whitespace removed from the start and the end (leading and trailing)
static UString trim(const char* s, uint32_t n);
static UString trim(const UString& s) { return trim(U_STRING_TO_PARAM(s)); }
// Returns a string that has any printable character which is not a space or
// an alphanumeric character removed from the start and the end (leading and trailing)
static UString trimPunctuation(const char* s, uint32_t n);
static UString trimPunctuation(const UString& s) { return trimPunctuation(U_STRING_TO_PARAM(s)); }
// returns a string that has whitespace removed from the start and the end, and
// which has each sequence of internal whitespace replaced with a single space
static UString simplifyWhiteSpace(const char* s, uint32_t n);
static UString simplifyWhiteSpace(const UString& s) { return simplifyWhiteSpace(U_STRING_TO_PARAM(s)); }
// returns a string that has suppressed all whitespace
static UString removeWhiteSpace(const char* s, uint32_t n);
static UString removeWhiteSpace(const UString& s) { return removeWhiteSpace(U_STRING_TO_PARAM(s)); }
// returns a string that has suppressed repeated empty lines
static UString removeEmptyLine(const char* s, uint32_t n);
static UString removeEmptyLine(const UString& s) { return removeEmptyLine(U_STRING_TO_PARAM(s)); }
// Minifies CSS/JS by removing comments and whitespaces
static UString minifyCssJs(const char* s, uint32_t n);
static UString minifyCssJs(const UString& s) { return minifyCssJs(U_STRING_TO_PARAM(s)); }
// ----------------------------------------------------------------------------------------

View File

@ -88,51 +88,9 @@ __pure uint32_t u_random64(uint64_t ptr)
}
#endif
#ifdef USE_HARDWARE_CRC32
__pure uint32_t u_crc32(unsigned char* restrict bp, uint32_t len)
{
U_INTERNAL_TRACE("u_crc32(%.*s,%u)", U_min(len,128), bp, len)
uint32_t h1 = 0xABAD1DEA;
# ifdef HAVE_ARCH64
while (len >= sizeof(uint64_t))
{
h1 = __builtin_ia32_crc32di(h1, u_get_unalignedp64(bp));
bp += sizeof(uint64_t);
len -= sizeof(uint64_t);
}
# endif
while (len >= sizeof(uint32_t))
{
h1 = __builtin_ia32_crc32si(h1, u_get_unalignedp32(bp));
bp += sizeof(uint32_t);
len -= sizeof(uint32_t);
}
if (len >= sizeof(uint16_t))
{
h1 = __builtin_ia32_crc32hi(h1, u_get_unalignedp16(bp));
bp += sizeof(uint16_t);
len -= sizeof(uint16_t);
}
if (len) h1 = __builtin_ia32_crc32qi(h1, *bp);
U_INTERNAL_PRINT("h1 = %u", h1)
U_INTERNAL_ASSERT_MAJOR(h1, 0)
return h1;
}
#endif
/* the famous DJB hash function for strings */
__pure uint32_t u_cdb_hash(unsigned char* restrict t, uint32_t tlen, int flags)
__pure uint32_t u_cdb_hash(const unsigned char* restrict t, uint32_t tlen, int flags)
{
uint32_t h;
@ -149,185 +107,12 @@ __pure uint32_t u_cdb_hash(unsigned char* restrict t, uint32_t tlen, int flags)
return h;
}
/* MurmurHash3 was written by Austin Appleby */
static inline uint32_t rotl32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); }
#if !defined(USE_HARDWARE_CRC32) && defined(HAVE_ARCH64)
static inline uint64_t rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (64 - r)); }
static inline uint64_t fmix64(uint64_t k)
__pure uint32_t u_hash_ignore_case(const unsigned char* restrict data, uint32_t len)
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccdULL;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53ULL;
k ^= k >> 33;
return k;
}
/* Block read - if your platform needs to do endian-swapping or can only handle aligned reads, do the conversion here */
#define getblock64(p,i) u_get_unalignedp64(p+i)
__pure uint32_t murmurhash3_x86_64(unsigned char* restrict bp, uint32_t len)
{
U_INTERNAL_TRACE("murmurhash3_x86_64(%.*s,%u,%d)", U_min(len,128), bp, len)
int i;
uint64_t h1, h2, k1, k2;
const int nblocks = len / 16;
const uint64_t c1 = 0x87c37b91114253d5ULL,
c2 = 0x4cf5ad432745937fULL;
const uint8_t* tail = (const uint8_t*)(bp + nblocks*16);
const uint64_t* blocks = (const uint64_t*)bp;
h1 = h2 = u_seed_hash; /* seed */
/* body */
for (i = 0; i < nblocks; ++i)
{
k1 = getblock64(blocks,i*2+0);
k2 = getblock64(blocks,i*2+1);
k1 *= c1; k1 = rotl64(k1,31); k1 *= c2; h1 ^= k1;
h1 = rotl64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = rotl64(k2,33); k2 *= c1; h2 ^= k2;
h2 = rotl64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
/* tail */
k1 = k2 = 0;
switch (len & 15)
{
case 15: k2 ^= (uint64_t)tail[14] << 48;
case 14: k2 ^= (uint64_t)tail[13] << 40;
case 13: k2 ^= (uint64_t)tail[12] << 32;
case 12: k2 ^= (uint64_t)tail[11] << 24;
case 11: k2 ^= (uint64_t)tail[10] << 16;
case 10: k2 ^= (uint64_t)tail[ 9] << 8;
case 9: k2 ^= (uint64_t)tail[ 8];
k2 *= c2; k2 = rotl64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= (uint64_t)tail[ 7] << 56;
case 7: k1 ^= (uint64_t)tail[ 6] << 48;
case 6: k1 ^= (uint64_t)tail[ 5] << 40;
case 5: k1 ^= (uint64_t)tail[ 4] << 32;
case 4: k1 ^= (uint64_t)tail[ 3] << 24;
case 3: k1 ^= (uint64_t)tail[ 2] << 16;
case 2: k1 ^= (uint64_t)tail[ 1] << 8;
case 1: k1 ^= (uint64_t)tail[ 0];
k1 *= c1; k1 = rotl64(k1,31); k1 *= c2; h1 ^= k1;
}
/* finalization */
h1 ^= (uint64_t)len;
h2 ^= (uint64_t)len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
U_INTERNAL_PRINT("h2 = %llu %u", h2, (uint32_t)h2)
U_INTERNAL_ASSERT_MAJOR(h2, 0)
return (uint32_t)h2;
}
#endif
static inline uint32_t fmix32(uint32_t h)
{
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
/* Block read - if your platform needs to do endian-swapping or can only handle aligned reads, do the conversion here */
#define getblock32(p,i) u_get_unalignedp32(p+i)
__pure uint32_t murmurhash3_x86_32_ignore_case(unsigned char* restrict bp, uint32_t len)
{
int i;
union uucflag u;
uint32_t h1, k1;
const int nblocks = len / 4;
const uint32_t c1 = 0xcc9e2d51,
c2 = 0x1b873593;
const uint8_t* tail = (const uint8_t*)(bp + nblocks*4);
const uint32_t* blocks = (const uint32_t*)tail;
U_INTERNAL_TRACE("murmurhash3_x86_32_ignore_case(%.*s,%u)", U_min(len,128), bp, len)
h1 = u_seed_hash; /* seed */
/* body */
i = -nblocks;
for (; i; ++i)
{
u.u = getblock32(blocks,i);
u.c[0] = u__tolower(u.c[0]);
u.c[1] = u__tolower(u.c[1]);
u.c[2] = u__tolower(u.c[2]);
u.c[3] = u__tolower(u.c[3]);
k1 = u.u;
k1 *= c1;
k1 = rotl32(k1,15);
k1 *= c2;
h1 ^= k1;
h1 = rotl32(h1,13);
h1 = h1*5+0xe6546b64;
}
/* tail */
k1 = 0;
switch (len & 3)
{
case 3: k1 ^= u__tolower(tail[2]) << 16;
case 2: k1 ^= u__tolower(tail[1]) << 8;
case 1: k1 ^= u__tolower(tail[0]);
k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
}
/* finalization */
h1 ^= len;
h1 = fmix32(h1);
U_INTERNAL_PRINT("h1 = %u", h1)
U_INTERNAL_ASSERT_MAJOR(h1, 0)
return h1;
}
#if !defined(USE_HARDWARE_CRC32)
# define get16bits(p) u_get_unalignedp16(p)
__pure uint32_t u_fhash(unsigned char* restrict data, uint32_t len)
{
uint32_t tmp, hash = len, rem = len & 3;
U_INTERNAL_TRACE("u_fhash(%.*s,%u,%d)", U_min(len,128), data, len)
U_INTERNAL_TRACE("u_hash_ignore_case(%.*s,%u,%d)", U_min(len,128), data, len)
len >>= 2;
@ -335,8 +120,14 @@ __pure uint32_t u_fhash(unsigned char* restrict data, uint32_t len)
for (; len > 0; --len)
{
hash += get16bits(data);
tmp = (get16bits(data+2) << 11) ^ hash;
u.u = u_get_unalignedp32(data);
u.c[0] = u__tolower(u.c[0]);
u.c[1] = u__tolower(u.c[1]);
u.c[2] = u__tolower(u.c[2]);
u.c[3] = u__tolower(u.c[3]);
hash += u_get_unalignedp16(&u.lo);
tmp = (u_get_unalignedp16(&u.hi) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2 * sizeof(uint16_t);
hash += hash >> 11;
@ -348,16 +139,24 @@ __pure uint32_t u_fhash(unsigned char* restrict data, uint32_t len)
{
case 3:
{
hash += get16bits(data);
u.lo = u_get_unalignedp16(data);
u.c[0] = u__tolower(u.c[0]);
u.c[1] = u__tolower(u.c[1]);
hash += u_get_unalignedp16(&u.lo);
hash ^= hash << 16;
hash ^= ((signed char)data[sizeof(uint16_t)]) << 18;
hash ^= ((signed char)u__tolower(data[sizeof(uint16_t)])) << 18;
hash += hash >> 11;
}
break;
case 2:
{
hash += get16bits(data);
u.lo = u_get_unalignedp16(data);
u.c[0] = u__tolower(u.c[0]);
u.c[1] = u__tolower(u.c[1]);
hash += u_get_unalignedp16(&u.lo);
hash ^= hash << 11;
hash += hash >> 17;
}
@ -365,7 +164,7 @@ __pure uint32_t u_fhash(unsigned char* restrict data, uint32_t len)
case 1:
{
hash += (signed char)*data;
hash += (signed char)u__tolower(*data);
hash ^= hash << 10;
hash += hash >> 1;
}
@ -383,15 +182,33 @@ __pure uint32_t u_fhash(unsigned char* restrict data, uint32_t len)
return hash;
}
#if !defined(HAVE_ARCH64)
__pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
/* MurmurHash3 was written by Austin Appleby
#define getblock32(p,i) u_get_unalignedp32(p+i)
#define getblock64(p,i) u_get_unalignedp64(p+i)
//#if !defined(USE_HARDWARE_CRC32) && !defined(HAVE_ARCH64)
static inline uint32_t rotl32(uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); }
static inline uint32_t fmix32(uint32_t h)
{
U_INTERNAL_TRACE("u_hash(%.*s,%u,%d)", U_min(len,128), bp, len)
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
__pure uint32_t murmurhash3_x86_32(const unsigned char* restrict bp, uint32_t len)
{
U_INTERNAL_TRACE("murmurhash3_x86_32(%.*s,%u,%d)", U_min(len,128), bp, len)
uint8_t* tail;
int i, nblocks;
uint32_t* blocks;
uint32_t c1, c2, k1, h1 = u_seed_hash; /* seed */
uint32_t c1, c2, k1, h1 = u_seed_hash; // seed
if (len > 16)
{
@ -408,9 +225,9 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
tail = (uint8_t*)(bp + nblocks*16);
blocks = (uint32_t*)tail;
h2 = h3 = h4 = h1; /* seed */
h2 = h3 = h4 = h1; // seed
/* body */
// body
for (i = -nblocks; i; ++i)
{
@ -429,7 +246,7 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
h4 = rotl32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
}
/* tail */
// tail
k1 = k2 = k3 = k4 = 0;
@ -459,7 +276,7 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
}
/* finalization */
// finalization
h1 ^= (uint32_t)len; h2 ^= (uint32_t)len;
h3 ^= (uint32_t)len; h4 ^= (uint32_t)len;
@ -490,7 +307,7 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
tail = (uint8_t*)(bp + nblocks*4);
blocks = (uint32_t*)tail;
/* body */
// body
i = -nblocks;
@ -507,7 +324,7 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
h1 = h1*5+0xe6546b64;
}
/* tail */
// tail
k1 = 0;
@ -519,7 +336,7 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
}
/* finalization */
// finalization
h1 ^= len;
h1 = fmix32(h1);
@ -530,5 +347,92 @@ __pure uint32_t u_hash(unsigned char* restrict bp, uint32_t len)
return h1;
}
#endif
#endif
//#endif
//#if !defined(USE_HARDWARE_CRC32) && defined(HAVE_ARCH64)
static inline uint64_t rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (64 - r)); }
static inline uint64_t fmix64(uint64_t k)
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccdULL;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53ULL;
k ^= k >> 33;
return k;
}
__pure uint32_t murmurhash3_x86_64(const unsigned char* restrict bp, uint32_t len)
{
U_INTERNAL_TRACE("murmurhash3_x86_64(%.*s,%u,%d)", U_min(len,128), bp, len)
int i;
uint64_t h1, h2, k1, k2;
const int nblocks = len / 16;
const uint64_t c1 = 0x87c37b91114253d5ULL,
c2 = 0x4cf5ad432745937fULL;
const uint8_t* tail = (const uint8_t*)(bp + nblocks*16);
const uint64_t* blocks = (const uint64_t*)bp;
h1 = h2 = u_seed_hash; // seed
// body
for (i = 0; i < nblocks; ++i)
{
k1 = getblock64(blocks,i*2+0);
k2 = getblock64(blocks,i*2+1);
k1 *= c1; k1 = rotl64(k1,31); k1 *= c2; h1 ^= k1;
h1 = rotl64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = rotl64(k2,33); k2 *= c1; h2 ^= k2;
h2 = rotl64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
// tail
k1 = k2 = 0;
switch (len & 15)
{
case 15: k2 ^= (uint64_t)tail[14] << 48;
case 14: k2 ^= (uint64_t)tail[13] << 40;
case 13: k2 ^= (uint64_t)tail[12] << 32;
case 12: k2 ^= (uint64_t)tail[11] << 24;
case 11: k2 ^= (uint64_t)tail[10] << 16;
case 10: k2 ^= (uint64_t)tail[ 9] << 8;
case 9: k2 ^= (uint64_t)tail[ 8];
k2 *= c2; k2 = rotl64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= (uint64_t)tail[ 7] << 56;
case 7: k1 ^= (uint64_t)tail[ 6] << 48;
case 6: k1 ^= (uint64_t)tail[ 5] << 40;
case 5: k1 ^= (uint64_t)tail[ 4] << 32;
case 4: k1 ^= (uint64_t)tail[ 3] << 24;
case 3: k1 ^= (uint64_t)tail[ 2] << 16;
case 2: k1 ^= (uint64_t)tail[ 1] << 8;
case 1: k1 ^= (uint64_t)tail[ 0];
k1 *= c1; k1 = rotl64(k1,31); k1 *= c2; h1 ^= k1;
}
// finalization
h1 ^= (uint64_t)len;
h2 ^= (uint64_t)len;
h1 += h2;
h2 += h1;
h1 = fmix64(h1);
h2 = fmix64(h2);
h1 += h2;
h2 += h1;
U_INTERNAL_PRINT("h2 = %llu %u", h2, (uint32_t)h2)
U_INTERNAL_ASSERT_MAJOR(h2, 0)
return (uint32_t)h2;
}
//#endif
*/

View File

@ -572,41 +572,6 @@ char* u_getPathRelativ(const char* restrict path, uint32_t* restrict ptr_path_le
return (char*)path;
}
/* find sequence of U_CRLF2 */
__pure uint32_t u_findEndHeader1(const char* restrict str, uint32_t n)
{
const char* restrict p;
const char* restrict end = str + n;
const char* restrict ptr = str;
uint32_t pos, endHeader = U_NOT_FOUND;
U_INTERNAL_TRACE("u_findEndHeader1(%.*s,%u)", U_min(n,128), str, n)
U_INTERNAL_ASSERT_POINTER(str)
while (ptr < end)
{
p = (const char* restrict) memchr(ptr, '\r', end - ptr);
if (p == 0) break;
if (u_get_unalignedp32(p) == U_MULTICHAR_CONSTANT32('\r','\n','\r','\n'))
{
pos = p - str + 4;
if (pos <= n) endHeader = pos;
break;
}
ptr = p + 1;
}
return endHeader;
}
/* find sequence of U_LF2 or U_CRLF2 */
__pure uint32_t u_findEndHeader(const char* restrict str, uint32_t n)

View File

@ -849,7 +849,7 @@ void ULog::logResponse(const UString& data, const char* name, const char* format
{
u_printf_string_max_length = u_findEndHeader1(ptr, sz);
if (u_printf_string_max_length == -1) u_printf_string_max_length = U_min(sz,2000);
if ((uint32_t)u_printf_string_max_length == U_NOT_FOUND) u_printf_string_max_length = U_min(sz,2000);
U_INTERNAL_ASSERT_MAJOR(u_printf_string_max_length, 0)
}

View File

@ -1551,9 +1551,9 @@ bool UClientImage_Base::writeResponse()
U_INTERNAL_ASSERT_EQUALS(nrequest, 0)
#if defined(USE_LIBSSL) || defined(_MSWINDOWS_)
iBytesWrite = USocketExt::writev( socket, iov_vec+idx, iovcnt, ncount, 0);
iBytesWrite = USocketExt::writev( socket, iov_vec+idx, iovcnt, ncount, U_ClientImage_pipeline ? U_TIMEOUT_MS : 0);
#else
iBytesWrite = USocketExt::_writev(socket, iov_vec+idx, iovcnt, ncount, 0);
iBytesWrite = USocketExt::_writev(socket, iov_vec+idx, iovcnt, ncount, U_ClientImage_pipeline ? U_TIMEOUT_MS : 0);
#endif
}

View File

@ -3360,7 +3360,7 @@ void UServer_Base::runLoop(const char* user)
socket->setTcpNoDelay();
socket->setTcpFastOpen();
socket->setTcpDeferAccept();
if (bssl == false) socket->setBufferSND(min_size_for_sendfile);
if (bssl == false) socket->setBufferSND(500 * 1024); // 500k: for major size we assume is better to use sendfile()
if (set_tcp_keep_alive ) socket->setTcpKeepAlive();
# endif
if (tcp_linger_set > -2) socket->setTcpLinger(tcp_linger_set);

View File

@ -1642,29 +1642,6 @@ __pure uint32_t UString::findnocase(const char* s, uint32_t pos, uint32_t s_len,
U_RETURN(U_NOT_FOUND);
}
__pure uint32_t UString::find(unsigned char c, uint32_t pos) const
{
U_TRACE(0, "UString::find(%C,%u)", c, pos)
uint32_t sz = size(),
ret = U_NOT_FOUND;
const char* str = rep->str;
if (pos < sz)
{
uint32_t how_much = (sz - pos);
// U_INTERNAL_DUMP("how_much = %u", how_much)
void* p = (void*) memchr(str + pos, c, how_much);
if (p) ret = (const char*)p - str;
}
U_RETURN(ret);
}
// rfind() instead of starting at the beginning of the string and searching for the text's first occurence, starts its search at the end and returns the last occurence
__pure uint32_t UString::rfind(unsigned char c, uint32_t pos) const
@ -1679,11 +1656,9 @@ __pure uint32_t UString::rfind(unsigned char c, uint32_t pos) const
if (xpos > pos) xpos = pos;
const char* str = rep->str;
for (++xpos; xpos-- > 0; )
{
if (str[xpos] == c) U_RETURN(xpos);
if (rep->str[xpos] == c) U_RETURN(xpos);
}
}
@ -1700,10 +1675,8 @@ __pure uint32_t UString::rfind(const char* s, uint32_t pos, uint32_t n) const
{
pos = U_min(sz - n, pos);
const char* str = rep->str;
do {
if (memcmp(str + pos, s, n) == 0) U_RETURN(pos);
if (memcmp(rep->str + pos, s, n) == 0) U_RETURN(pos);
}
while (pos-- > 0);
}
@ -1720,13 +1693,9 @@ __pure uint32_t UString::find_first_of(const char* s, uint32_t pos, uint32_t n)
if (n)
{
uint32_t sz = size();
const char* str = rep->str;
for (; pos < sz; ++pos)
for (; pos < size(); ++pos)
{
if (memchr(s, str[pos], n)) U_RETURN(pos);
if (memchr(s, rep->str[pos], n)) U_RETURN(pos);
}
}
@ -1743,10 +1712,8 @@ __pure uint32_t UString::find_last_of(const char* s, uint32_t pos, uint32_t n) c
{
if (--sz > pos) sz = pos;
const char* str = rep->str;
do {
if (memchr(s, str[sz], n)) U_RETURN(sz);
if (memchr(s, rep->str[sz], n)) U_RETURN(sz);
}
while (sz-- != 0);
}
@ -1765,11 +1732,9 @@ __pure uint32_t UString::find_first_not_of(const char* s, uint32_t pos, uint32_t
uint32_t sz = size(),
xpos = pos;
const char* str = rep->str;
for (; xpos < sz; ++xpos)
{
if (memchr(s, str[xpos], n) == 0) U_RETURN(xpos);
if (memchr(s, rep->str[xpos], n) == 0) U_RETURN(xpos);
}
}
@ -1804,10 +1769,8 @@ __pure uint32_t UString::find_last_not_of(const char* s, uint32_t pos, uint32_t
{
if (--sz > pos) sz = pos;
const char* str = rep->str;
do {
if (memchr(s, str[sz], n) == 0) U_RETURN(sz);
if (memchr(s, rep->str[sz], n) == 0) U_RETURN(sz);
}
while (sz-- != 0);
}

View File

@ -804,10 +804,6 @@ UString UStringExt::insertEscape(const char* s, uint32_t n, char delimiter)
{
U_TRACE(0, "UStringExt::insertEscape(%.*S,%u,%C)", n, s, n, delimiter)
U_INTERNAL_ASSERT_MAJOR_MSG(n,0,"elaborazione su stringa vuota: inserire if empty()...")
U_INTERNAL_ASSERT_POINTER(memchr(s, delimiter, n))
char* p;
uint32_t sz, sz1 = 0;
UString result(n * 2);
@ -855,10 +851,6 @@ UString UStringExt::removeEscape(const char* s, uint32_t n)
{
U_TRACE(0, "UStringExt::removeEscape(%.*S,%u,%C)", n, s, n)
U_INTERNAL_ASSERT_MAJOR_MSG(n,0,"elaborazione su stringa vuota: inserire if empty()...")
U_INTERNAL_ASSERT_POINTER(memchr(s, '\\', n))
char* p;
UString result(n);
uint32_t sz, sz1 = 0;

View File

@ -93,7 +93,8 @@ static void testQuery(const UString& json, const char* cquery, const UString& ex
int dataType = UValue::jread(json, query, result);
cout.write(buffer, u__snprintf(buffer, sizeof(buffer), "dataType = (%d %S) query = %V result(%u) = %V UValue::jread_elements = %d UValue::jread_error = (%d %S)\n",
dataType, UValue::getDataTypeDescription(dataType), query.rep, result.size(), result.rep, UValue::jread_elements, UValue::jread_error, UValue::getJReadErrorDescription()));
dataType, UValue::getDataTypeDescription(dataType), query.rep, result.size(), result.rep, UValue::jread_elements, UValue::jread_error,
UValue::getJReadErrorDescription()));
U_INTERNAL_ASSERT_EQUALS(result, expected)
}
@ -108,6 +109,7 @@ static void testVector()
UString result, vecJson = U_STRING_FROM_CONSTANT("[\"riga 1\",\"riga 2\",\"riga 3\",\"riga 4\"]");
ok = JSON_parse(vecJson, y);
U_INTERNAL_ASSERT(ok)
ok = (y[0] == U_STRING_FROM_CONSTANT("riga 1"));
@ -122,6 +124,7 @@ static void testVector()
y.clear();
ok = JSON_parse(vecJson, y);
U_INTERNAL_ASSERT(ok)
ok = (y[0] == U_STRING_FROM_CONSTANT("riga 1"));
@ -135,7 +138,7 @@ static void testVector()
result = JSON_stringify(json_vec, y);
U_ASSERT( result == vecJson )
U_ASSERT_EQUALS( result, vecJson )
}
static void testMap()
@ -148,6 +151,7 @@ static void testMap()
UString result, mapJson = U_STRING_FROM_CONSTANT("{\"key1\":\"riga 1\",\"key2\":\"riga 2\",\"key3\":\"riga 3\",\"key4\":\"riga 4\"}");
ok = JSON_parse(mapJson, x);
U_INTERNAL_ASSERT(ok)
ok = (x["key1"] == U_STRING_FROM_CONSTANT("riga 1"));
@ -162,6 +166,7 @@ static void testMap()
x.clear();
ok = JSON_parse(mapJson, x);
U_INTERNAL_ASSERT(ok)
ok = (x["key1"] == U_STRING_FROM_CONSTANT("riga 1"));
@ -175,7 +180,7 @@ static void testMap()
result = JSON_stringify(json_obj, x);
U_ASSERT( result.size() == mapJson.size() )
U_ASSERT_EQUALS( result.size(), mapJson.size() )
}
static void testObject()
@ -188,6 +193,7 @@ static void testObject()
UString result, reqJson = U_STRING_FROM_CONSTANT("{\"token\":\"A619828KAIJ6D3\",\"type\":\"localesData\",\"radius\":\"near\",\"location\":\"40.7831 N, 73.9712 W\"}");
ok = JSON_parse(reqJson, request);
U_INTERNAL_ASSERT(ok)
U_DUMP_OBJECT(request)
@ -198,6 +204,7 @@ static void testObject()
U_INTERNAL_ASSERT_EQUALS(request.location, "40.7831 N, 73.9712 W")
ok = JSON_parse(reqJson, request);
U_INTERNAL_ASSERT(ok)
U_DUMP_OBJECT(request)
@ -209,7 +216,7 @@ static void testObject()
result = JSON_stringify(json_obj, request);
U_ASSERT( result == reqJson )
U_ASSERT_EQUALS( result, reqJson )
}
int
@ -219,6 +226,32 @@ U_EXPORT main (int argc, char* argv[])
U_TRACE(5, "main(%d)", argc)
#if defined(U_STDCPP_ENABLE) && defined(HAVE_CXX11) && defined(U_COMPILER_RANGE_FOR)
UValue json_vec(ARRAY_VALUE);
std::vector<unsigned int> v = {0, 1, 2, 3, 4, 5};
UString vecJson = U_STRING_FROM_CONSTANT("[0,1,2,3,4,5]");
U_ASSERT_EQUALS( JSON_stringify(json_vec, v), vecJson)
v.clear();
bool ok = JSON_parse(vecJson, v);
U_INTERNAL_ASSERT(ok)
ok = (v[0] == 0);
U_INTERNAL_ASSERT(ok)
ok = (v[1] == 1);
U_INTERNAL_ASSERT(ok)
ok = (v[2] == 2);
U_INTERNAL_ASSERT(ok)
ok = (v[3] == 3);
U_INTERNAL_ASSERT(ok)
ok = (v[4] == 4);
U_INTERNAL_ASSERT(ok)
ok = (v[5] == 5);
U_INTERNAL_ASSERT(ok)
#endif
UValue json;
UCrono crono;
char buffer[4096];