C++ style

Apply c++ code format  to all files!
This commit is contained in:
enWILLYado 2018-02-17 20:15:48 +01:00
parent 7f31f70876
commit 4276afc4f4
43 changed files with 14589 additions and 10107 deletions

View file

@ -29,27 +29,32 @@
#ifndef __cplusplus
extern int posix_memalign(void **__memptr, size_t __alignment, size_t __size);
extern int posix_memalign(void** __memptr, size_t __alignment, size_t __size);
#else
// Some systems (e.g. those with GNU libc) declare posix_memalign with an
// exception specifier. Via an "egregious workaround" in
// Sema::CheckEquivalentExceptionSpec, Clang accepts the following as a valid
// redeclaration of glibc's declaration.
extern "C" int posix_memalign(void **__memptr, size_t __alignment, size_t __size);
extern "C" int posix_memalign(void** __memptr, size_t __alignment, size_t __size);
#endif
static __inline__ void *__attribute__((__always_inline__, __malloc__)) _mm_malloc(size_t __size, size_t __align)
static __inline__ void* __attribute__((__always_inline__, __malloc__)) _mm_malloc(size_t __size,
size_t __align)
{
if (__align == 1) {
if(__align == 1)
{
return malloc(__size);
}
if (!(__align & (__align - 1)) && __align < sizeof(void *))
__align = sizeof(void *);
if(!(__align & (__align - 1)) && __align < sizeof(void*))
{
__align = sizeof(void*);
}
void *__mallocedMemory;
if (posix_memalign(&__mallocedMemory, __align, __size)) {
void* __mallocedMemory;
if(posix_memalign(&__mallocedMemory, __align, __size))
{
return 0;
}
@ -57,7 +62,7 @@ static __inline__ void *__attribute__((__always_inline__, __malloc__)) _mm_mallo
}
static __inline__ void __attribute__((__always_inline__)) _mm_free(void *__p)
static __inline__ void __attribute__((__always_inline__)) _mm_free(void* __p)
{
free(__p);
}

View file

@ -8,25 +8,25 @@
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
@ -82,7 +82,7 @@ int optopt = '?'; /* character checked for validity */
#undef optreset /* see getopt.h */
#define optreset __mingw_optreset
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
char* optarg; /* argument associated with option */
#endif
//extern int optind; /* index of first non-option in argv */
@ -106,7 +106,7 @@ char *optarg; /* argument associated with option */
#ifndef __CYGWIN__
#define __progname __argv[0]
#else
extern char __declspec(dllimport) *__progname;
extern char __declspec(dllimport)* __progname;
#endif
#ifdef __CYGWIN__
@ -115,14 +115,14 @@ static char EMSG[] = "";
#define EMSG ""
#endif
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int getopt_internal(int, char* const*, const char*,
const struct option*, int*, int);
static int parse_long_options(char* const*, const char*,
const struct option*, int*, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static void permute_args(int, int, int, char* const*);
static char *place = EMSG; /* option letter processing */
static char* place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
@ -137,20 +137,22 @@ static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
static void
_vwarnx(const char *fmt,va_list ap)
_vwarnx(const char* fmt, va_list ap)
{
(void)fprintf(stderr,"%s: ",__progname);
if (fmt != NULL)
(void)vfprintf(stderr,fmt,ap);
(void)fprintf(stderr,"\n");
(void)fprintf(stderr, "%s: ", __progname);
if(fmt != NULL)
{
(void)vfprintf(stderr, fmt, ap);
}
(void)fprintf(stderr, "\n");
}
static void
warnx(const char *fmt,...)
warnx(const char* fmt, ...)
{
va_list ap;
va_start(ap,fmt);
_vwarnx(fmt,ap);
va_start(ap, fmt);
_vwarnx(fmt, ap);
va_end(ap);
}
@ -163,7 +165,8 @@ gcd(int a, int b)
int c;
c = a % b;
while (c != 0) {
while(c != 0)
{
a = b;
b = c;
c = a % b;
@ -179,10 +182,10 @@ gcd(int a, int b)
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
char* const* nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
char* swap;
/*
* compute lengths of blocks and number and size of cycles
@ -192,19 +195,25 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
for(i = 0; i < ncycle; i++)
{
cstart = panonopt_end + i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
for(j = 0; j < cyclelen; j++)
{
if(pos >= panonopt_end)
{
pos -= nnonopts;
}
else
{
pos += nopts;
}
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
((char**) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
((char**)nargv)[cstart] = swap;
}
}
}
@ -217,7 +226,7 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
getopt(int nargc, char* const* nargv, const char* options)
{
/*
@ -267,9 +276,9 @@ extern "C" {
struct option /* specification for a long form option... */
{
const char *name; /* option name, without leading hyphens */
const char* name; /* option name, without leading hyphens */
int has_arg; /* does it take an argument? */
int *flag; /* where to save its status, or NULL */
int* flag; /* where to save its status, or NULL */
int val; /* its associated status value */
};
@ -286,10 +295,10 @@ enum /* permitted values for its `has_arg' field... */
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
parse_long_options(char* const* nargv, const char* options,
const struct option* long_options, int* idx, int short_too)
{
char *current_argv, *has_equal;
char* current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
@ -304,20 +313,28 @@ parse_long_options(char * const *nargv, const char *options,
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
if((has_equal = strchr(current_argv, '=')) != NULL)
{
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
}
else
{
current_argv_len = strlen(current_argv);
}
for (i = 0; long_options[i].name; i++) {
for(i = 0; long_options[i].name; i++)
{
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
if(strncmp(current_argv, long_options[i].name,
current_argv_len))
{
continue;
}
if (strlen(long_options[i].name) == current_argv_len) {
if(strlen(long_options[i].name) == current_argv_len)
{
/* exact match */
match = i;
ambiguous = 0;
@ -327,85 +344,118 @@ parse_long_options(char * const *nargv, const char *options,
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
if(short_too && current_argv_len == 1)
{
continue;
}
if (match == -1) /* partial match */
if(match == -1) /* partial match */
{
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
}
else if(!IDENTICAL_INTERPRETATION(i, match))
{
ambiguous = 1;
}
if (ambiguous) {
}
if(ambiguous)
{
/* ambiguous abbreviation */
if (PRINT_ERROR)
if(PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
if(match != -1) /* option found */
{
if(long_options[match].has_arg == no_argument
&& has_equal)
{
if(PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
if(long_options[match].flag == NULL)
{
optopt = long_options[match].val;
}
else
{
optopt = 0;
}
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
if(long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument)
{
if(has_equal)
{
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
}
else if(long_options[match].has_arg ==
required_argument)
{
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
if((long_options[match].has_arg == required_argument)
&& (optarg == NULL))
{
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
if(PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
if(long_options[match].flag == NULL)
{
optopt = long_options[match].val;
}
else
{
optopt = 0;
}
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
}
else /* unknown option */
{
if(short_too)
{
--optind;
return (-1);
}
if (PRINT_ERROR)
if(PRINT_ERROR)
{
warnx(illoptstring, current_argv);
}
optopt = 0;
return (BADCH);
}
if (idx)
if(idx)
{
*idx = match;
if (long_options[match].flag) {
}
if(long_options[match].flag)
{
*long_options[match].flag = long_options[match].val;
return (0);
} else
}
else
{
return (long_options[match].val);
}
#undef IDENTICAL_INTERPRETATION
}
@ -414,22 +464,26 @@ parse_long_options(char * const *nargv, const char *options,
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
getopt_internal(int nargc, char* const* nargv, const char* options,
const struct option* long_options, int* idx, int flags)
{
char *oli; /* option letter list index */
char* oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
if(options == NULL)
{
return (-1);
}
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
if(optind == 0)
{
optind = optreset = 1;
}
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
@ -438,30 +492,44 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
* optreset != 0 for GNU compatibility.
*/
if (posixly_correct == -1 || optreset != 0)
if(posixly_correct == -1 || optreset != 0)
{
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
}
if(*options == '-')
{
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
}
else if(posixly_correct || *options == '+')
{
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
}
if(*options == '+' || *options == '-')
{
options++;
}
optarg = NULL;
if (optreset)
if(optreset)
{
nonopt_start = nonopt_end = -1;
}
start:
if (optreset || !*place) { /* update scanning pointer */
if(optreset || !*place) /* update scanning pointer */
{
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
if(optind >= nargc) /* end of argument vector */
{
place = EMSG;
if (nonopt_end != -1) {
if(nonopt_end != -1)
{
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
else if(nonopt_start != -1)
{
/*
* If we skipped non-options, set optind
* to the first of them.
@ -471,10 +539,12 @@ start:
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
if(*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL))
{
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
if(flags & FLAG_ALLARGS)
{
/*
* GNU extension:
* return non-option as argument to option 1
@ -482,7 +552,8 @@ start:
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
if(!(flags & FLAG_PERMUTE))
{
/*
* If no permutation wanted, stop parsing
* at first non-option.
@ -490,9 +561,12 @@ start:
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
if(nonopt_start == -1)
{
nonopt_start = optind;
else if (nonopt_end != -1) {
}
else if(nonopt_end != -1)
{
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
@ -503,20 +577,24 @@ start:
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
if(nonopt_start != -1 && nonopt_end == -1)
{
nonopt_end = optind;
}
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
if(place[1] != '\0' && *++place == '-' && place[1] == '\0')
{
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
if(nonopt_end != -1)
{
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
@ -532,73 +610,107 @@ start:
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
if(long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY)))
{
short_too = 0;
if (*place == '-')
if(*place == '-')
{
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
}
else if(*place != ':' && strchr(options, *place) != NULL)
{
short_too = 1; /* could be short option too */
}
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
if(optchar != -1)
{
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
if((optchar = (int) * place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = (char*)strchr(options, optchar)) == NULL) {
(oli = (char*)strchr(options, optchar)) == NULL)
{
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
if(optchar == (int)'-' && *place == '\0')
{
return (-1);
if (!*place)
}
if(!*place)
{
++optind;
if (PRINT_ERROR)
}
if(PRINT_ERROR)
{
warnx(illoptchar, optchar);
}
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
if(long_options != NULL && optchar == 'W' && oli[1] == ';')
{
/* -W long-option */
if (*place) /* no space */
if(*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
else if(++optind >= nargc) /* no arg */
{
place = EMSG;
if (PRINT_ERROR)
if(PRINT_ERROR)
{
warnx(recargchar, optchar);
}
optopt = optchar;
return (BADARG);
} else /* white space */
}
else /* white space */
{
place = nargv[optind];
}
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
if(*++oli != ':') /* doesn't take argument */
{
if(!*place)
{
++optind;
} else { /* takes (optional) argument */
}
}
else /* takes (optional) argument */
{
optarg = NULL;
if (*place) /* no white space */
if(*place) /* no white space */
{
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
}
else if(oli[1] != ':') /* arg not optional */
{
if(++optind >= nargc) /* no arg */
{
place = EMSG;
if (PRINT_ERROR)
if(PRINT_ERROR)
{
warnx(recargchar, optchar);
}
optopt = optchar;
return (BADARG);
} else
}
else
{
optarg = nargv[optind];
}
}
place = EMSG;
++optind;
}
@ -611,8 +723,8 @@ start:
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
getopt_long(int nargc, char* const* nargv, const char* options,
const struct option* long_options, int* idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
@ -624,12 +736,12 @@ getopt_long(int nargc, char * const *nargv, const char *options,
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
getopt_long_only(int nargc, char* const* nargv, const char* options,
const struct option* long_options, int* idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
FLAG_PERMUTE | FLAG_LONGONLY));
}
//extern int getopt_long(int nargc, char * const *nargv, const char *options,

View file

@ -59,24 +59,35 @@ concept Allocator {
/*! This class is just wrapper for standard C library memory routines.
\note implements Allocator concept
*/
class CrtAllocator {
class CrtAllocator
{
public:
static const bool kNeedFree = true;
void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
void* Malloc(size_t size)
{
if(size) // behavior of malloc(0) is implementation defined.
{
return std::malloc(size);
}
else
{
return NULL; // standardize to returning NULL.
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
(void)originalSize;
if (newSize == 0) {
if(newSize == 0)
{
std::free(originalPtr);
return NULL;
}
return std::realloc(originalPtr, newSize);
}
static void Free(void *ptr) { std::free(ptr); }
static void Free(void* ptr)
{
std::free(ptr);
}
};
///////////////////////////////////////////////////////////////////////////////
@ -99,9 +110,11 @@ public:
\note implements Allocator concept
*/
template <typename BaseAllocator = CrtAllocator>
class MemoryPoolAllocator {
class MemoryPoolAllocator
{
public:
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
static const bool kNeedFree =
false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
//! Constructor with chunkSize.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
@ -122,8 +135,10 @@ public:
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity,
BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator),
ownBaseAllocator_(0)
{
RAPIDJSON_ASSERT(buffer != 0);
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
@ -136,108 +151,147 @@ public:
//! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
~MemoryPoolAllocator() {
~MemoryPoolAllocator()
{
Clear();
RAPIDJSON_DELETE(ownBaseAllocator_);
}
//! Deallocates all memory chunks, excluding the user-supplied buffer.
void Clear() {
while (chunkHead_ && chunkHead_ != userBuffer_) {
void Clear()
{
while(chunkHead_ && chunkHead_ != userBuffer_)
{
ChunkHeader* next = chunkHead_->next;
baseAllocator_->Free(chunkHead_);
chunkHead_ = next;
}
if (chunkHead_ && chunkHead_ == userBuffer_)
if(chunkHead_ && chunkHead_ == userBuffer_)
{
chunkHead_->size = 0; // Clear user buffer
}
}
//! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes.
*/
size_t Capacity() const {
size_t Capacity() const
{
size_t capacity = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
for(ChunkHeader* c = chunkHead_; c != 0; c = c->next)
{
capacity += c->capacity;
}
return capacity;
}
//! Computes the memory blocks allocated.
/*! \return total used bytes.
*/
size_t Size() const {
size_t Size() const
{
size_t size = 0;
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
for(ChunkHeader* c = chunkHead_; c != 0; c = c->next)
{
size += c->size;
}
return size;
}
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
if (!size)
void* Malloc(size_t size)
{
if(!size)
{
return NULL;
}
size = RAPIDJSON_ALIGN(size);
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
if(chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
if(!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
{
return NULL;
}
void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
void* buffer = reinterpret_cast<char*>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
chunkHead_->size += size;
return buffer;
}
//! Resizes a memory block (concept Allocator)
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
if (originalPtr == 0)
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
if(originalPtr == 0)
{
return Malloc(newSize);
}
if (newSize == 0)
if(newSize == 0)
{
return NULL;
}
originalSize = RAPIDJSON_ALIGN(originalSize);
newSize = RAPIDJSON_ALIGN(newSize);
// Do not shrink if new size is smaller than original
if (originalSize >= newSize)
if(originalSize >= newSize)
{
return originalPtr;
}
// Simply expand it if it is the last allocation and there is sufficient space
if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
if(originalPtr == reinterpret_cast<char*>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(
ChunkHeader)) + chunkHead_->size - originalSize)
{
size_t increment = static_cast<size_t>(newSize - originalSize);
if (chunkHead_->size + increment <= chunkHead_->capacity) {
if(chunkHead_->size + increment <= chunkHead_->capacity)
{
chunkHead_->size += increment;
return originalPtr;
}
}
// Realloc process: allocate and copy memory, do not free original buffer.
if (void* newBuffer = Malloc(newSize)) {
if (originalSize)
if(void* newBuffer = Malloc(newSize))
{
if(originalSize)
{
std::memcpy(newBuffer, originalPtr, originalSize);
}
return newBuffer;
}
else
{
return NULL;
}
}
//! Frees a memory block (concept Allocator)
static void Free(void *ptr) { (void)ptr; } // Do nothing
static void Free(void* ptr)
{
(void)ptr; // Do nothing
}
private:
//! Copy constructor is not permitted.
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
MemoryPoolAllocator(const MemoryPoolAllocator & rhs) /* = delete */;
//! Copy assignment operator is not permitted.
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
MemoryPoolAllocator & operator=(const MemoryPoolAllocator & rhs) /* = delete */;
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
bool AddChunk(size_t capacity)
{
if(!baseAllocator_)
{
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
}
if(ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(
ChunkHeader)) + capacity)))
{
chunk->capacity = capacity;
chunk->size = 0;
chunk->next = chunkHead_;
@ -245,23 +299,26 @@ private:
return true;
}
else
{
return false;
}
}
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
//! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list.
*/
struct ChunkHeader {
struct ChunkHeader
{
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader *next; //!< Next chunk in the linked list.
ChunkHeader* next; //!< Next chunk in the linked list.
};
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
ChunkHeader* chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
void *userBuffer_; //!< User supplied buffer.
void* userBuffer_; //!< User supplied buffer.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
};

File diff suppressed because it is too large Load diff

View file

@ -36,59 +36,112 @@ RAPIDJSON_NAMESPACE_BEGIN
\tparam InputByteStream Type of input byte stream. For example, FileReadStream.
*/
template <typename Encoding, typename InputByteStream>
class EncodedInputStream {
class EncodedInputStream
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public:
typedef typename Encoding::Ch Ch;
EncodedInputStream(InputByteStream& is) : is_(is) {
EncodedInputStream(InputByteStream & is) : is_(is)
{
current_ = Encoding::TakeBOM(is_);
}
Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
size_t Tell() const { return is_.Tell(); }
Ch Peek() const
{
return current_;
}
Ch Take()
{
Ch c = current_;
current_ = Encoding::Take(is_);
return c;
}
size_t Tell() const
{
return is_.Tell();
}
// Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch)
{
RAPIDJSON_ASSERT(false);
}
void Flush()
{
RAPIDJSON_ASSERT(false);
}
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
EncodedInputStream(const EncodedInputStream&);
EncodedInputStream& operator=(const EncodedInputStream&);
EncodedInputStream(const EncodedInputStream &);
EncodedInputStream & operator=(const EncodedInputStream &);
InputByteStream& is_;
InputByteStream & is_;
Ch current_;
};
//! Specialized for UTF8 MemoryStream.
template <>
class EncodedInputStream<UTF8<>, MemoryStream> {
class EncodedInputStream<UTF8<>, MemoryStream>
{
public:
typedef UTF8<>::Ch Ch;
EncodedInputStream(MemoryStream& is) : is_(is) {
if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
EncodedInputStream(MemoryStream & is) : is_(is)
{
if(static_cast<unsigned char>(is_.Peek()) == 0xEFu)
{
is_.Take();
}
if(static_cast<unsigned char>(is_.Peek()) == 0xBBu)
{
is_.Take();
}
if(static_cast<unsigned char>(is_.Peek()) == 0xBFu)
{
is_.Take();
}
}
Ch Peek() const
{
return is_.Peek();
}
Ch Take()
{
return is_.Take();
}
size_t Tell() const
{
return is_.Tell();
}
Ch Peek() const { return is_.Peek(); }
Ch Take() { return is_.Take(); }
size_t Tell() const { return is_.Tell(); }
// Not implemented
void Put(Ch) {}
void Flush() {}
Ch* PutBegin() { return 0; }
size_t PutEnd(Ch*) { return 0; }
Ch* PutBegin()
{
return 0;
}
size_t PutEnd(Ch*)
{
return 0;
}
MemoryStream& is_;
MemoryStream & is_;
private:
EncodedInputStream(const EncodedInputStream&);
EncodedInputStream& operator=(const EncodedInputStream&);
EncodedInputStream(const EncodedInputStream &);
EncodedInputStream & operator=(const EncodedInputStream &);
};
//! Output byte stream wrapper with statically bound encoding.
@ -97,31 +150,61 @@ private:
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
*/
template <typename Encoding, typename OutputByteStream>
class EncodedOutputStream {
class EncodedOutputStream
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public:
typedef typename Encoding::Ch Ch;
EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
if (putBOM)
EncodedOutputStream(OutputByteStream & os, bool putBOM = true) : os_(os)
{
if(putBOM)
{
Encoding::PutBOM(os_);
}
}
void Put(Ch c) { Encoding::Put(os_, c); }
void Flush() { os_.Flush(); }
void Put(Ch c)
{
Encoding::Put(os_, c);
}
void Flush()
{
os_.Flush();
}
// Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
Ch Peek() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
Ch Take()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
EncodedOutputStream(const EncodedOutputStream&);
EncodedOutputStream& operator=(const EncodedOutputStream&);
EncodedOutputStream(const EncodedOutputStream &);
EncodedOutputStream & operator=(const EncodedOutputStream &);
OutputByteStream& os_;
OutputByteStream & os_;
};
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
@ -132,7 +215,8 @@ private:
\tparam InputByteStream type of input byte stream to be wrapped.
*/
template <typename CharType, typename InputByteStream>
class AutoUTFInputStream {
class AutoUTFInputStream
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public:
typedef CharType Ch;
@ -142,7 +226,8 @@ public:
\param is input stream to be wrapped.
\param type UTF encoding type if it is not detected from the stream.
*/
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
AutoUTFInputStream(InputByteStream & is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false)
{
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
DetectType();
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
@ -150,25 +235,57 @@ public:
current_ = takeFunc_(*is_);
}
UTFType GetType() const { return type_; }
bool HasBOM() const { return hasBOM_; }
UTFType GetType() const
{
return type_;
}
bool HasBOM() const
{
return hasBOM_;
}
Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
size_t Tell() const { return is_->Tell(); }
Ch Peek() const
{
return current_;
}
Ch Take()
{
Ch c = current_;
current_ = takeFunc_(*is_);
return c;
}
size_t Tell() const
{
return is_->Tell();
}
// Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch)
{
RAPIDJSON_ASSERT(false);
}
void Flush()
{
RAPIDJSON_ASSERT(false);
}
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
AutoUTFInputStream(const AutoUTFInputStream&);
AutoUTFInputStream& operator=(const AutoUTFInputStream&);
AutoUTFInputStream(const AutoUTFInputStream &);
AutoUTFInputStream & operator=(const AutoUTFInputStream &);
// Detect encoding type with BOM or RFC 4627
void DetectType() {
void DetectType()
{
// BOM (Byte Order Mark):
// 00 00 FE FF UTF-32BE
// FF FE 00 00 UTF-32LE
@ -176,17 +293,54 @@ private:
// FF FE UTF-16LE
// EF BB BF UTF-8
const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
if (!c)
const unsigned char* c = reinterpret_cast<const unsigned char*>(is_->Peek4());
if(!c)
{
return;
}
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
hasBOM_ = false;
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
if(bom == 0xFFFE0000)
{
type_ = kUTF32BE;
hasBOM_ = true;
is_->Take();
is_->Take();
is_->Take();
is_->Take();
}
else if(bom == 0x0000FEFF)
{
type_ = kUTF32LE;
hasBOM_ = true;
is_->Take();
is_->Take();
is_->Take();
is_->Take();
}
else if((bom & 0xFFFF) == 0xFFFE)
{
type_ = kUTF16BE;
hasBOM_ = true;
is_->Take();
is_->Take();
}
else if((bom & 0xFFFF) == 0xFEFF)
{
type_ = kUTF16LE;
hasBOM_ = true;
is_->Take();
is_->Take();
}
else if((bom & 0xFFFFFF) == 0xBFBBEF)
{
type_ = kUTF8;
hasBOM_ = true;
is_->Take();
is_->Take();
is_->Take();
}
// RFC 4627: Section 3
// "Since the first two characters of a JSON text will always be ASCII
@ -199,24 +353,43 @@ private:
// xx 00 xx 00 UTF-16LE
// xx xx xx xx UTF-8
if (!hasBOM_) {
if(!hasBOM_)
{
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
switch (pattern) {
case 0x08: type_ = kUTF32BE; break;
case 0x0A: type_ = kUTF16BE; break;
case 0x01: type_ = kUTF32LE; break;
case 0x05: type_ = kUTF16LE; break;
case 0x0F: type_ = kUTF8; break;
default: break; // Use type defined by user.
switch(pattern)
{
case 0x08:
type_ = kUTF32BE;
break;
case 0x0A:
type_ = kUTF16BE;
break;
case 0x01:
type_ = kUTF32LE;
break;
case 0x05:
type_ = kUTF16LE;
break;
case 0x0F:
type_ = kUTF8;
break;
default:
break; // Use type defined by user.
}
}
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
if(type_ == kUTF16LE || type_ == kUTF16BE)
{
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
}
if(type_ == kUTF32LE || type_ == kUTF32BE)
{
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
}
}
typedef Ch (*TakeFunc)(InputByteStream& is);
typedef Ch(*TakeFunc)(InputByteStream & is);
InputByteStream* is_;
UTFType type_;
Ch current_;
@ -230,7 +403,8 @@ private:
\tparam OutputByteStream type of output byte stream to be wrapped.
*/
template <typename CharType, typename OutputByteStream>
class AutoUTFOutputStream {
class AutoUTFOutputStream
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public:
typedef CharType Ch;
@ -241,43 +415,82 @@ public:
\param type UTF encoding type.
\param putBOM Whether to write BOM at the beginning of the stream.
*/
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
AutoUTFOutputStream(OutputByteStream & os, UTFType type, bool putBOM) : os_(&os), type_(type)
{
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
if(type_ == kUTF16LE || type_ == kUTF16BE)
{
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
}
if(type_ == kUTF32LE || type_ == kUTF32BE)
{
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
}
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
putFunc_ = f[type_];
if (putBOM)
if(putBOM)
{
PutBOM();
}
}
UTFType GetType() const { return type_; }
UTFType GetType() const
{
return type_;
}
void Put(Ch c) { putFunc_(*os_, c); }
void Flush() { os_->Flush(); }
void Put(Ch c)
{
putFunc_(*os_, c);
}
void Flush()
{
os_->Flush();
}
// Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
Ch Peek() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
Ch Take()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
AutoUTFOutputStream(const AutoUTFOutputStream&);
AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
AutoUTFOutputStream(const AutoUTFOutputStream &);
AutoUTFOutputStream & operator=(const AutoUTFOutputStream &);
void PutBOM() {
typedef void (*PutBOMFunc)(OutputByteStream&);
void PutBOM()
{
typedef void (*PutBOMFunc)(OutputByteStream &);
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
f[type_](*os_);
}
typedef void (*PutFunc)(OutputByteStream&, Ch);
typedef void (*PutFunc)(OutputByteStream &, Ch);
OutputByteStream* os_;
UTFType type_;

View file

@ -93,25 +93,32 @@ concept Encoding {
\note implements Encoding concept
*/
template<typename CharType = char>
struct UTF8 {
struct UTF8
{
typedef CharType Ch;
enum { supportUnicode = 1 };
template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F)
static void Encode(OutputStream & os, unsigned codepoint)
{
if(codepoint <= 0x7F)
{
os.Put(static_cast<Ch>(codepoint & 0xFF));
else if (codepoint <= 0x7FF) {
}
else if(codepoint <= 0x7FF)
{
os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
}
else if (codepoint <= 0xFFFF) {
else if(codepoint <= 0xFFFF)
{
os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
}
else {
else
{
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
@ -121,19 +128,25 @@ struct UTF8 {
}
template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F)
static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
{
if(codepoint <= 0x7F)
{
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
else if (codepoint <= 0x7FF) {
}
else if(codepoint <= 0x7FF)
{
PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
}
else if (codepoint <= 0xFFFF) {
else if(codepoint <= 0xFFFF)
{
PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
}
else {
else
{
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
@ -143,32 +156,66 @@ struct UTF8 {
}
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
static bool Decode(InputStream & is, unsigned* codepoint)
{
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define TAIL() COPY(); TRANS(0x70)
typename InputStream::Ch c = is.Take();
if (!(c & 0x80)) {
if(!(c & 0x80))
{
*codepoint = static_cast<unsigned char>(c);
return true;
}
unsigned char type = GetRange(static_cast<unsigned char>(c));
if (type >= 32) {
if(type >= 32)
{
*codepoint = 0;
} else {
}
else
{
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
}
bool result = true;
switch (type) {
case 2: TAIL(); return result;
case 3: TAIL(); TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result;
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
case 6: TAIL(); TAIL(); TAIL(); return result;
case 10: COPY(); TRANS(0x20); TAIL(); return result;
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
default: return false;
switch(type)
{
case 2:
TAIL();
return result;
case 3:
TAIL();
TAIL();
return result;
case 4:
COPY();
TRANS(0x50);
TAIL();
return result;
case 5:
COPY();
TRANS(0x10);
TAIL();
TAIL();
return result;
case 6:
TAIL();
TAIL();
TAIL();
return result;
case 10:
COPY();
TRANS(0x20);
TAIL();
return result;
case 11:
COPY();
TRANS(0x60);
TAIL();
TAIL();
return result;
default:
return false;
}
#undef COPY
#undef TRANS
@ -176,70 +223,116 @@ struct UTF8 {
}
template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) {
static bool Validate(InputStream & is, OutputStream & os)
{
#define COPY() os.Put(c = is.Take())
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define TAIL() COPY(); TRANS(0x70)
Ch c;
COPY();
if (!(c & 0x80))
if(!(c & 0x80))
{
return true;
}
bool result = true;
switch (GetRange(static_cast<unsigned char>(c))) {
case 2: TAIL(); return result;
case 3: TAIL(); TAIL(); return result;
case 4: COPY(); TRANS(0x50); TAIL(); return result;
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
case 6: TAIL(); TAIL(); TAIL(); return result;
case 10: COPY(); TRANS(0x20); TAIL(); return result;
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
default: return false;
switch(GetRange(static_cast<unsigned char>(c)))
{
case 2:
TAIL();
return result;
case 3:
TAIL();
TAIL();
return result;
case 4:
COPY();
TRANS(0x50);
TAIL();
return result;
case 5:
COPY();
TRANS(0x10);
TAIL();
TAIL();
return result;
case 6:
TAIL();
TAIL();
TAIL();
return result;
case 10:
COPY();
TRANS(0x20);
TAIL();
return result;
case 11:
COPY();
TRANS(0x60);
TAIL();
TAIL();
return result;
default:
return false;
}
#undef COPY
#undef TRANS
#undef TAIL
}
static unsigned char GetRange(unsigned char c) {
static unsigned char GetRange(unsigned char c)
{
// Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
static const unsigned char type[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
static const unsigned char type[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 11, 6, 6, 6, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
};
return type[c];
}
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
static CharType TakeBOM(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
typename InputByteStream::Ch c = Take(is);
if (static_cast<unsigned char>(c) != 0xEFu) return c;
if(static_cast<unsigned char>(c) != 0xEFu)
{
return c;
}
c = is.Take();
if (static_cast<unsigned char>(c) != 0xBBu) return c;
if(static_cast<unsigned char>(c) != 0xBBu)
{
return c;
}
c = is.Take();
if (static_cast<unsigned char>(c) != 0xBFu) return c;
if(static_cast<unsigned char>(c) != 0xBFu)
{
return c;
}
c = is.Take();
return c;
}
template <typename InputByteStream>
static Ch Take(InputByteStream& is) {
static Ch Take(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
return static_cast<Ch>(is.Take());
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
static void PutBOM(OutputByteStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
@ -247,7 +340,8 @@ struct UTF8 {
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, Ch c) {
static void Put(OutputByteStream & os, Ch c)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(c));
}
@ -266,20 +360,24 @@ struct UTF8 {
For streaming, use UTF16LE and UTF16BE, which handle endianness.
*/
template<typename CharType = wchar_t>
struct UTF16 {
struct UTF16
{
typedef CharType Ch;
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
enum { supportUnicode = 1 };
template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) {
static void Encode(OutputStream & os, unsigned codepoint)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
if (codepoint <= 0xFFFF) {
if(codepoint <= 0xFFFF)
{
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
os.Put(static_cast<typename OutputStream::Ch>(codepoint));
}
else {
else
{
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
@ -289,13 +387,16 @@ struct UTF16 {
template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
if (codepoint <= 0xFFFF) {
if(codepoint <= 0xFFFF)
{
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
}
else {
else
{
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000;
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
@ -304,14 +405,17 @@ struct UTF16 {
}
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
static bool Decode(InputStream & is, unsigned* codepoint)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
typename InputStream::Ch c = is.Take();
if (c < 0xD800 || c > 0xDFFF) {
if(c < 0xD800 || c > 0xDFFF)
{
*codepoint = static_cast<unsigned>(c);
return true;
}
else if (c <= 0xDBFF) {
else if(c <= 0xDBFF)
{
*codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
c = is.Take();
*codepoint |= (static_cast<unsigned>(c) & 0x3FF);
@ -322,14 +426,18 @@ struct UTF16 {
}
template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) {
static bool Validate(InputStream & is, OutputStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
typename InputStream::Ch c;
os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
if (c < 0xD800 || c > 0xDFFF)
if(c < 0xD800 || c > 0xDFFF)
{
return true;
else if (c <= 0xDBFF) {
}
else if(c <= 0xDBFF)
{
os.Put(c = is.Take());
return c >= 0xDC00 && c <= 0xDFFF;
}
@ -339,16 +447,19 @@ struct UTF16 {
//! UTF-16 little endian encoding.
template<typename CharType = wchar_t>
struct UTF16LE : UTF16<CharType> {
struct UTF16LE : UTF16<CharType>
{
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
static CharType TakeBOM(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is);
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
}
template <typename InputByteStream>
static CharType Take(InputByteStream& is) {
static CharType Take(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<uint8_t>(is.Take());
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
@ -356,14 +467,16 @@ struct UTF16LE : UTF16<CharType> {
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
static void PutBOM(OutputByteStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, CharType c) {
static void Put(OutputByteStream & os, CharType c)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
@ -372,16 +485,19 @@ struct UTF16LE : UTF16<CharType> {
//! UTF-16 big endian encoding.
template<typename CharType = wchar_t>
struct UTF16BE : UTF16<CharType> {
struct UTF16BE : UTF16<CharType>
{
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
static CharType TakeBOM(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is);
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
}
template <typename InputByteStream>
static CharType Take(InputByteStream& is) {
static CharType Take(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
c |= static_cast<uint8_t>(is.Take());
@ -389,14 +505,16 @@ struct UTF16BE : UTF16<CharType> {
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
static void PutBOM(OutputByteStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, CharType c) {
static void Put(OutputByteStream & os, CharType c)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
@ -415,28 +533,32 @@ struct UTF16BE : UTF16<CharType> {
For streaming, use UTF32LE and UTF32BE, which handle endianness.
*/
template<typename CharType = unsigned>
struct UTF32 {
struct UTF32
{
typedef CharType Ch;
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
enum { supportUnicode = 1 };
template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) {
static void Encode(OutputStream & os, unsigned codepoint)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
os.Put(codepoint);
}
template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
PutUnsafe(os, codepoint);
}
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
static bool Decode(InputStream & is, unsigned* codepoint)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
Ch c = is.Take();
*codepoint = c;
@ -444,7 +566,8 @@ struct UTF32 {
}
template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) {
static bool Validate(InputStream & is, OutputStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
Ch c;
os.Put(c = is.Take());
@ -454,16 +577,19 @@ struct UTF32 {
//! UTF-32 little endian enocoding.
template<typename CharType = unsigned>
struct UTF32LE : UTF32<CharType> {
struct UTF32LE : UTF32<CharType>
{
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
static CharType TakeBOM(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is);
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
}
template <typename InputByteStream>
static CharType Take(InputByteStream& is) {
static CharType Take(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<uint8_t>(is.Take());
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
@ -473,7 +599,8 @@ struct UTF32LE : UTF32<CharType> {
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
static void PutBOM(OutputByteStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
@ -482,7 +609,8 @@ struct UTF32LE : UTF32<CharType> {
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, CharType c) {
static void Put(OutputByteStream & os, CharType c)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
@ -493,16 +621,19 @@ struct UTF32LE : UTF32<CharType> {
//! UTF-32 big endian encoding.
template<typename CharType = unsigned>
struct UTF32BE : UTF32<CharType> {
struct UTF32BE : UTF32<CharType>
{
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
static CharType TakeBOM(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
CharType c = Take(is);
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
}
template <typename InputByteStream>
static CharType Take(InputByteStream& is) {
static CharType Take(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
@ -512,7 +643,8 @@ struct UTF32BE : UTF32<CharType> {
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
static void PutBOM(OutputByteStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
@ -521,7 +653,8 @@ struct UTF32BE : UTF32<CharType> {
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, CharType c) {
static void Put(OutputByteStream & os, CharType c)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
@ -539,58 +672,67 @@ struct UTF32BE : UTF32<CharType> {
\note implements Encoding concept
*/
template<typename CharType = char>
struct ASCII {
struct ASCII
{
typedef CharType Ch;
enum { supportUnicode = 0 };
template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) {
static void Encode(OutputStream & os, unsigned codepoint)
{
RAPIDJSON_ASSERT(codepoint <= 0x7F);
os.Put(static_cast<Ch>(codepoint & 0xFF));
}
template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
{
RAPIDJSON_ASSERT(codepoint <= 0x7F);
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
}
template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) {
static bool Decode(InputStream & is, unsigned* codepoint)
{
uint8_t c = static_cast<uint8_t>(is.Take());
*codepoint = c;
return c <= 0X7F;
}
template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) {
static bool Validate(InputStream & is, OutputStream & os)
{
uint8_t c = static_cast<uint8_t>(is.Take());
os.Put(static_cast<typename OutputStream::Ch>(c));
return c <= 0x7F;
}
template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) {
static CharType TakeBOM(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
uint8_t c = static_cast<uint8_t>(Take(is));
return static_cast<Ch>(c);
}
template <typename InputByteStream>
static Ch Take(InputByteStream& is) {
static Ch Take(InputByteStream & is)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
return static_cast<Ch>(is.Take());
}
template <typename OutputByteStream>
static void PutBOM(OutputByteStream& os) {
static void PutBOM(OutputByteStream & os)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
(void)os;
}
template <typename OutputByteStream>
static void Put(OutputByteStream& os, Ch c) {
static void Put(OutputByteStream & os, Ch c)
{
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
os.Put(static_cast<typename OutputByteStream::Ch>(c));
}
@ -600,7 +742,8 @@ struct ASCII {
// AutoUTF
//! Runtime-specified UTF encoding type of a stream.
enum UTFType {
enum UTFType
{
kUTF8 = 0, //!< UTF-8.
kUTF16LE = 1, //!< UTF-16 little endian.
kUTF16BE = 2, //!< UTF-16 big endian.
@ -612,7 +755,8 @@ enum UTFType {
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
*/
template<typename CharType>
struct AutoUTF {
struct AutoUTF
{
typedef CharType Ch;
enum { supportUnicode = 1 };
@ -620,29 +764,33 @@ struct AutoUTF {
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
template<typename OutputStream>
RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
RAPIDJSON_FORCEINLINE static void Encode(OutputStream & os, unsigned codepoint)
{
typedef void (*EncodeFunc)(OutputStream &, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
(*f[os.GetType()])(os, codepoint);
}
template<typename OutputStream>
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned);
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
{
typedef void (*EncodeFunc)(OutputStream &, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
(*f[os.GetType()])(os, codepoint);
}
template <typename InputStream>
RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
RAPIDJSON_FORCEINLINE static bool Decode(InputStream & is, unsigned* codepoint)
{
typedef bool (*DecodeFunc)(InputStream &, unsigned*);
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
return (*f[is.GetType()])(is, codepoint);
}
template <typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
RAPIDJSON_FORCEINLINE static bool Validate(InputStream & is, OutputStream & os)
{
typedef bool (*ValidateFunc)(InputStream &, OutputStream &);
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
return (*f[is.GetType()])(is, os);
}
@ -655,54 +803,66 @@ struct AutoUTF {
//! Encoding conversion.
template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder {
struct Transcoder
{
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream & is, OutputStream & os)
{
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
if(!SourceEncoding::Decode(is, &codepoint))
{
return false;
}
TargetEncoding::Encode(os, codepoint);
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream & is, OutputStream & os)
{
unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint))
if(!SourceEncoding::Decode(is, &codepoint))
{
return false;
}
TargetEncoding::EncodeUnsafe(os, codepoint);
return true;
}
//! Validate one Unicode codepoint from an encoded stream.
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
RAPIDJSON_FORCEINLINE static bool Validate(InputStream & is, OutputStream & os)
{
return Transcode(is, os); // Since source/target encoding is different, must transcode.
}
};
// Forward declaration.
template<typename Stream>
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
inline void PutUnsafe(Stream & stream, typename Stream::Ch c);
//! Specialization of Transcoder with same source and target encoding.
template<typename Encoding>
struct Transcoder<Encoding, Encoding> {
struct Transcoder<Encoding, Encoding>
{
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
RAPIDJSON_FORCEINLINE static bool Transcode(InputStream & is, OutputStream & os)
{
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream & is, OutputStream & os)
{
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true;
}
template<typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
RAPIDJSON_FORCEINLINE static bool Validate(InputStream & is, OutputStream & os)
{
return Encoding::Validate(is, os); // source/target encoding are the same
}
};

View file

@ -19,51 +19,72 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(covered-switch-default)
RAPIDJSON_DIAG_OFF(switch - enum)
RAPIDJSON_DIAG_OFF(covered - switch - default)
#endif
RAPIDJSON_NAMESPACE_BEGIN
RAPIDJSON_NAMESPACE_BEGIN
//! Maps error code of parsing into error message.
/*!
//! Maps error code of parsing into error message.
/*!
\ingroup RAPIDJSON_ERRORS
\param parseErrorCode Error code obtained in parsing.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
switch (parseErrorCode) {
case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
*/
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode)
{
switch(parseErrorCode)
{
case kParseErrorNone:
return RAPIDJSON_ERROR_STRING("No error.");
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorDocumentEmpty:
return RAPIDJSON_ERROR_STRING("The document is empty.");
case kParseErrorDocumentRootNotSingular:
return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
case kParseErrorValueInvalid:
return RAPIDJSON_ERROR_STRING("Invalid value.");
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
case kParseErrorObjectMissName:
return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
case kParseErrorObjectMissColon:
return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
case kParseErrorObjectMissCommaOrCurlyBracket:
return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
case kParseErrorArrayMissCommaOrSquareBracket:
return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
case kParseErrorStringUnicodeEscapeInvalidHex:
return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
case kParseErrorStringUnicodeSurrogateInvalid:
return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
case kParseErrorStringEscapeInvalid:
return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
case kParseErrorStringMissQuotationMark:
return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
case kParseErrorStringInvalidEncoding:
return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
case kParseErrorNumberTooBig:
return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
case kParseErrorNumberMissFraction:
return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
case kParseErrorNumberMissExponent:
return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
case kParseErrorTermination:
return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
case kParseErrorUnspecificSyntaxError:
return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
default:
return RAPIDJSON_ERROR_STRING("Unknown error.");
}
}
}
RAPIDJSON_NAMESPACE_END

View file

@ -61,7 +61,8 @@ RAPIDJSON_NAMESPACE_BEGIN
/*! \ingroup RAPIDJSON_ERRORS
\see GenericReader::Parse, GenericReader::GetParseErrorCode
*/
enum ParseErrorCode {
enum ParseErrorCode
{
kParseErrorNone = 0, //!< No error.
kParseErrorDocumentEmpty, //!< The document is empty.
@ -103,7 +104,8 @@ enum ParseErrorCode {
\endcode
\see GenericReader::Parse, GenericDocument::Parse
*/
struct ParseResult {
struct ParseResult
{
public:
//! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {}
@ -111,23 +113,51 @@ public:
ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
//! Get the error code.
ParseErrorCode Code() const { return code_; }
ParseErrorCode Code() const
{
return code_;
}
//! Get the error offset, if \ref IsError(), 0 otherwise.
size_t Offset() const { return offset_; }
size_t Offset() const
{
return offset_;
}
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
operator bool() const { return !IsError(); }
operator bool() const
{
return !IsError();
}
//! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; }
bool IsError() const
{
return code_ != kParseErrorNone;
}
bool operator==(const ParseResult& that) const { return code_ == that.code_; }
bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
bool operator==(const ParseResult & that) const
{
return code_ == that.code_;
}
bool operator==(ParseErrorCode code) const
{
return code_ == code;
}
friend bool operator==(ParseErrorCode code, const ParseResult & err)
{
return code == err.code_;
}
//! Reset error code.
void Clear() { Set(kParseErrorNone); }
void Clear()
{
Set(kParseErrorNone);
}
//! Update error code and offset.
void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
void Set(ParseErrorCode code, size_t offset = 0)
{
code_ = code;
offset_ = offset;
}
private:
ParseErrorCode code_;

View file

@ -21,8 +21,8 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(missing-noreturn)
RAPIDJSON_DIAG_OFF(unreachable - code)
RAPIDJSON_DIAG_OFF(missing - noreturn)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -31,7 +31,8 @@ RAPIDJSON_NAMESPACE_BEGIN
/*!
\note implements Stream concept
*/
class FileReadStream {
class FileReadStream
{
public:
typedef char Ch; //!< Character type (byte).
@ -41,38 +42,71 @@ public:
\param buffer user-supplied buffer.
\param bufferSize size of buffer in bytes. Must >=4 bytes.
*/
FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer),
bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false)
{
RAPIDJSON_ASSERT(fp_ != 0);
RAPIDJSON_ASSERT(bufferSize >= 4);
Read();
}
Ch Peek() const { return *current_; }
Ch Take() { Ch c = *current_; Read(); return c; }
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
Ch Peek() const
{
return *current_;
}
Ch Take()
{
Ch c = *current_;
Read();
return c;
}
size_t Tell() const
{
return count_ + static_cast<size_t>(current_ - buffer_);
}
// Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch)
{
RAPIDJSON_ASSERT(false);
}
void Flush()
{
RAPIDJSON_ASSERT(false);
}
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
// For encoding detection only.
const Ch* Peek4() const {
const Ch* Peek4() const
{
return (current_ + 4 <= bufferLast_) ? current_ : 0;
}
private:
void Read() {
if (current_ < bufferLast_)
void Read()
{
if(current_ < bufferLast_)
{
++current_;
else if (!eof_) {
}
else if(!eof_)
{
count_ += readCount_;
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
bufferLast_ = buffer_ + readCount_ - 1;
current_ = buffer_;
if (readCount_ < bufferSize_) {
if(readCount_ < bufferSize_)
{
buffer_[readCount_] = '\0';
++bufferLast_;
eof_ = true;
@ -81,10 +115,10 @@ private:
}
std::FILE* fp_;
Ch *buffer_;
Ch* buffer_;
size_t bufferSize_;
Ch *bufferLast_;
Ch *current_;
Ch* bufferLast_;
Ch* current_;
size_t readCount_;
size_t count_; //!< Number of characters read
bool eof_;

View file

@ -20,7 +20,7 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(unreachable - code)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -29,24 +29,32 @@ RAPIDJSON_NAMESPACE_BEGIN
/*!
\note implements Stream concept
*/
class FileWriteStream {
class FileWriteStream
{
public:
typedef char Ch; //!< Character type. Only support char.
FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer),
bufferEnd_(buffer + bufferSize), current_(buffer_)
{
RAPIDJSON_ASSERT(fp_ != 0);
}
void Put(char c) {
if (current_ >= bufferEnd_)
void Put(char c)
{
if(current_ >= bufferEnd_)
{
Flush();
}
*current_++ = c;
}
void PutN(char c, size_t n) {
void PutN(char c, size_t n)
{
size_t avail = static_cast<size_t>(bufferEnd_ - current_);
while (n > avail) {
while(n > avail)
{
std::memset(current_, c, avail);
current_ += avail;
Flush();
@ -54,16 +62,20 @@ public:
avail = static_cast<size_t>(bufferEnd_ - current_);
}
if (n > 0) {
if(n > 0)
{
std::memset(current_, c, n);
current_ += n;
}
}
void Flush() {
if (current_ != buffer_) {
void Flush()
{
if(current_ != buffer_)
{
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
if (result < static_cast<size_t>(current_ - buffer_)) {
if(result < static_cast<size_t>(current_ - buffer_))
{
// failure deliberately ignored at this time
// added to avoid warn_unused_result build errors
}
@ -72,26 +84,47 @@ public:
}
// Not implemented
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
char Take() { RAPIDJSON_ASSERT(false); return 0; }
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
char Peek() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
char Take()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
char* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(char*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
// Prohibit copy constructor & assignment operator.
FileWriteStream(const FileWriteStream&);
FileWriteStream& operator=(const FileWriteStream&);
FileWriteStream(const FileWriteStream &);
FileWriteStream & operator=(const FileWriteStream &);
std::FILE* fp_;
char *buffer_;
char *bufferEnd_;
char *current_;
char* buffer_;
char* bufferEnd_;
char* current_;
};
//! Implement specialized version of PutN() with memset() for better performance.
template<>
inline void PutN(FileWriteStream& stream, char c, size_t n) {
inline void PutN(FileWriteStream & stream, char c, size_t n)
{
stream.PutN(c, n);
}

View file

@ -46,12 +46,12 @@ class MemoryPoolAllocator;
template <typename Encoding>
struct GenericStringStream;
typedef GenericStringStream<UTF8<char> > StringStream;
typedef GenericStringStream<UTF8<char>> StringStream;
template <typename Encoding>
struct GenericInsituStringStream;
typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
typedef GenericInsituStringStream<UTF8<char>> InsituStringStream;
// stringbuffer.h
@ -113,7 +113,7 @@ struct GenericStringRef;
template <typename Encoding, typename Allocator>
class GenericValue;
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator>> Value;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
@ -141,10 +141,11 @@ typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocume
template <
typename SchemaDocumentType,
typename OutputHandler,
typename StateAllocator>
typename StateAllocator >
class GenericSchemaValidator;
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator>
SchemaValidator;
RAPIDJSON_NAMESPACE_END

View file

@ -23,92 +23,132 @@
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
class BigInteger {
public:
class BigInteger
{
public:
typedef uint64_t Type;
BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
BigInteger(const BigInteger & rhs) : count_(rhs.count_)
{
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
}
explicit BigInteger(uint64_t u) : count_(1) {
explicit BigInteger(uint64_t u) : count_(1)
{
digits_[0] = u;
}
BigInteger(const char* decimals, size_t length) : count_(1) {
BigInteger(const char* decimals, size_t length) : count_(1)
{
RAPIDJSON_ASSERT(length > 0);
digits_[0] = 0;
size_t i = 0;
const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
while (length >= kMaxDigitPerIteration) {
while(length >= kMaxDigitPerIteration)
{
AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
length -= kMaxDigitPerIteration;
i += kMaxDigitPerIteration;
}
if (length > 0)
if(length > 0)
{
AppendDecimal64(decimals + i, decimals + i + length);
}
}
BigInteger& operator=(const BigInteger &rhs)
BigInteger & operator=(const BigInteger & rhs)
{
if(this != &rhs)
{
if (this != &rhs) {
count_ = rhs.count_;
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
}
return *this;
}
BigInteger& operator=(uint64_t u) {
BigInteger & operator=(uint64_t u)
{
digits_[0] = u;
count_ = 1;
return *this;
}
BigInteger& operator+=(uint64_t u) {
BigInteger & operator+=(uint64_t u)
{
Type backup = digits_[0];
digits_[0] += u;
for (size_t i = 0; i < count_ - 1; i++) {
if (digits_[i] >= backup)
for(size_t i = 0; i < count_ - 1; i++)
{
if(digits_[i] >= backup)
{
return *this; // no carry
}
backup = digits_[i + 1];
digits_[i + 1] += 1;
}
// Last carry
if (digits_[count_ - 1] < backup)
if(digits_[count_ - 1] < backup)
{
PushBack(1);
}
return *this;
}
BigInteger& operator*=(uint64_t u) {
if (u == 0) return *this = 0;
if (u == 1) return *this;
if (*this == 1) return *this = u;
BigInteger & operator*=(uint64_t u)
{
if(u == 0)
{
return *this = 0;
}
if(u == 1)
{
return *this;
}
if(*this == 1)
{
return *this = u;
}
uint64_t k = 0;
for (size_t i = 0; i < count_; i++) {
for(size_t i = 0; i < count_; i++)
{
uint64_t hi;
digits_[i] = MulAdd64(digits_[i], u, k, &hi);
k = hi;
}
if (k > 0)
if(k > 0)
{
PushBack(k);
}
return *this;
}
BigInteger& operator*=(uint32_t u) {
if (u == 0) return *this = 0;
if (u == 1) return *this;
if (*this == 1) return *this = u;
BigInteger & operator*=(uint32_t u)
{
if(u == 0)
{
return *this = 0;
}
if(u == 1)
{
return *this;
}
if(*this == 1)
{
return *this = u;
}
uint64_t k = 0;
for (size_t i = 0; i < count_; i++) {
for(size_t i = 0; i < count_; i++)
{
const uint64_t c = digits_[i] >> 32;
const uint64_t d = digits_[i] & 0xFFFFFFFF;
const uint64_t uc = u * c;
@ -119,48 +159,64 @@ public:
k = p1 >> 32;
}
if (k > 0)
if(k > 0)
{
PushBack(k);
}
return *this;
}
BigInteger& operator<<=(size_t shift) {
if (IsZero() || shift == 0) return *this;
BigInteger & operator<<=(size_t shift)
{
if(IsZero() || shift == 0)
{
return *this;
}
size_t offset = shift / kTypeBit;
size_t interShift = shift % kTypeBit;
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
if (interShift == 0) {
if(interShift == 0)
{
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
count_ += offset;
}
else {
else
{
digits_[count_] = 0;
for (size_t i = count_; i > 0; i--)
for(size_t i = count_; i > 0; i--)
{
digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
}
digits_[offset] = digits_[0] << interShift;
count_ += offset;
if (digits_[count_])
if(digits_[count_])
{
count_++;
}
}
std::memset(digits_, 0, offset * sizeof(Type));
return *this;
}
bool operator==(const BigInteger& rhs) const {
bool operator==(const BigInteger & rhs) const
{
return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
}
bool operator==(const Type rhs) const {
bool operator==(const Type rhs) const
{
return count_ == 1 && digits_[0] == rhs;
}
BigInteger& MultiplyPow5(unsigned exp) {
static const uint32_t kPow5[12] = {
BigInteger & MultiplyPow5(unsigned exp)
{
static const uint32_t kPow5[12] =
{
5,
5 * 5,
5 * 5 * 5,
@ -174,71 +230,121 @@ public:
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
};
if (exp == 0) return *this;
for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
if (exp > 0) *this *= kPow5[exp - 1];
if(exp == 0)
{
return *this;
}
for(; exp >= 27; exp -= 27)
{
*this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
}
for(; exp >= 13; exp -= 13)
{
*this *= static_cast<uint32_t>(1220703125u); // 5^13
}
if(exp > 0)
{
*this *= kPow5[exp - 1];
}
return *this;
}
// Compute absolute difference of this and rhs.
// Assume this != rhs
bool Difference(const BigInteger& rhs, BigInteger* out) const {
bool Difference(const BigInteger & rhs, BigInteger* out) const
{
int cmp = Compare(rhs);
RAPIDJSON_ASSERT(cmp != 0);
const BigInteger *a, *b; // Makes a > b
const BigInteger* a, *b; // Makes a > b
bool ret;
if (cmp < 0) { a = &rhs; b = this; ret = true; }
else { a = this; b = &rhs; ret = false; }
if(cmp < 0)
{
a = &rhs;
b = this;
ret = true;
}
else
{
a = this;
b = &rhs;
ret = false;
}
Type borrow = 0;
for (size_t i = 0; i < a->count_; i++) {
for(size_t i = 0; i < a->count_; i++)
{
Type d = a->digits_[i] - borrow;
if (i < b->count_)
if(i < b->count_)
{
d -= b->digits_[i];
}
borrow = (d > a->digits_[i]) ? 1 : 0;
out->digits_[i] = d;
if (d != 0)
if(d != 0)
{
out->count_ = i + 1;
}
}
return ret;
}
int Compare(const BigInteger& rhs) const {
if (count_ != rhs.count_)
int Compare(const BigInteger & rhs) const
{
if(count_ != rhs.count_)
{
return count_ < rhs.count_ ? -1 : 1;
}
for (size_t i = count_; i-- > 0;)
if (digits_[i] != rhs.digits_[i])
for(size_t i = count_; i-- > 0;)
if(digits_[i] != rhs.digits_[i])
{
return digits_[i] < rhs.digits_[i] ? -1 : 1;
}
return 0;
}
size_t GetCount() const { return count_; }
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
size_t GetCount() const
{
return count_;
}
Type GetDigit(size_t index) const
{
RAPIDJSON_ASSERT(index < count_);
return digits_[index];
}
bool IsZero() const
{
return count_ == 1 && digits_[0] == 0;
}
private:
void AppendDecimal64(const char* begin, const char* end) {
private:
void AppendDecimal64(const char* begin, const char* end)
{
uint64_t u = ParseUint64(begin, end);
if (IsZero())
if(IsZero())
{
*this = u;
else {
}
else
{
unsigned exp = static_cast<unsigned>(end - begin);
(MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
}
}
void PushBack(Type digit) {
void PushBack(Type digit)
{
RAPIDJSON_ASSERT(count_ < kCapacity);
digits_[count_++] = digit;
}
static uint64_t ParseUint64(const char* begin, const char* end) {
static uint64_t ParseUint64(const char* begin, const char* end)
{
uint64_t r = 0;
for (const char* p = begin; p != end; ++p) {
for(const char* p = begin; p != end; ++p)
{
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
r = r * 10u + static_cast<unsigned>(*p - '0');
}
@ -246,11 +352,14 @@ private:
}
// Assume a * b + k < 2^128
static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh)
{
#if defined(_MSC_VER) && defined(_M_AMD64)
uint64_t low = _umul128(a, b, outHigh) + k;
if (low < k)
if(low < k)
{
(*outHigh)++;
}
return low;
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
__extension__ typedef unsigned __int128 uint128;
@ -263,14 +372,18 @@ private:
uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
x1 += (x0 >> 32); // can't give carry
x1 += x2;
if (x1 < x2)
if(x1 < x2)
{
x3 += (static_cast<uint64_t>(1) << 32);
}
uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
uint64_t hi = x3 + (x1 >> 32);
lo += k;
if (lo < k)
if(lo < k)
{
hi++;
}
*outHigh = hi;
return lo;
#endif
@ -282,7 +395,7 @@ private:
Type digits_[kCapacity];
size_t count_;
};
};
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -28,59 +28,71 @@
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
#endif
struct DiyFp {
struct DiyFp
{
DiyFp() : f(), e() {}
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
explicit DiyFp(double d) {
union {
explicit DiyFp(double d)
{
union
{
double d;
uint64_t u64;
} u = { d };
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
uint64_t significand = (u.u64 & kDpSignificandMask);
if (biased_e != 0) {
if(biased_e != 0)
{
f = significand + kDpHiddenBit;
e = biased_e - kDpExponentBias;
}
else {
else
{
f = significand;
e = kDpMinExponent + 1;
}
}
DiyFp operator-(const DiyFp& rhs) const {
DiyFp operator-(const DiyFp & rhs) const
{
return DiyFp(f - rhs.f, e);
}
DiyFp operator*(const DiyFp& rhs) const {
DiyFp operator*(const DiyFp & rhs) const
{
#if defined(_MSC_VER) && defined(_M_AMD64)
uint64_t h;
uint64_t l = _umul128(f, rhs.f, &h);
if (l & (uint64_t(1) << 63)) // rounding
if(l & (uint64_t(1) << 63)) // rounding
{
h++;
}
return DiyFp(h, e + rhs.e + 64);
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
__extension__ typedef unsigned __int128 uint128;
uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
uint64_t h = static_cast<uint64_t>(p >> 64);
uint64_t l = static_cast<uint64_t>(p);
if (l & (uint64_t(1) << 63)) // rounding
if(l & (uint64_t(1) << 63)) // rounding
{
h++;
}
return DiyFp(h, e + rhs.e + 64);
#else
const uint64_t M32 = 0xFFFFFFFF;
@ -98,7 +110,8 @@ struct DiyFp {
#endif
}
DiyFp Normalize() const {
DiyFp Normalize() const
{
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, f);
@ -108,7 +121,8 @@ struct DiyFp {
return DiyFp(f << s, e - s);
#else
DiyFp res = *this;
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
while(!(res.f & (static_cast<uint64_t>(1) << 63)))
{
res.f <<= 1;
res.e--;
}
@ -116,9 +130,11 @@ struct DiyFp {
#endif
}
DiyFp NormalizeBoundary() const {
DiyFp NormalizeBoundary() const
{
DiyFp res = *this;
while (!(res.f & (kDpHiddenBit << 1))) {
while(!(res.f & (kDpHiddenBit << 1)))
{
res.f <<= 1;
res.e--;
}
@ -127,7 +143,8 @@ struct DiyFp {
return res;
}
void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const
{
DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
mi.f <<= mi.e - pl.e;
@ -136,11 +153,13 @@ struct DiyFp {
*minus = mi;
}
double ToDouble() const {
union {
double ToDouble() const
{
union
{
double d;
uint64_t u64;
}u;
} u;
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
static_cast<uint64_t>(e + kDpExponentBias);
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
@ -159,11 +178,13 @@ struct DiyFp {
uint64_t f;
int e;
};
};
inline DiyFp GetCachedPowerByIndex(size_t index) {
inline DiyFp GetCachedPowerByIndex(size_t index)
{
// 10^-348, 10^-340, ..., 10^340
static const uint64_t kCachedPowers_F[] = {
static const uint64_t kCachedPowers_F[] =
{
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
@ -209,7 +230,8 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
};
static const int16_t kCachedPowers_E[] = {
static const int16_t kCachedPowers_E[] =
{
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
@ -221,35 +243,39 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
907, 933, 960, 986, 1013, 1039, 1066
};
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
}
}
inline DiyFp GetCachedPower(int e, int* K) {
inline DiyFp GetCachedPower(int e, int* K)
{
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
int k = static_cast<int>(dk);
if (dk - k > 0.0)
if(dk - k > 0.0)
{
k++;
}
unsigned index = static_cast<unsigned>((k >> 3) + 1);
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
return GetCachedPowerByIndex(index);
}
}
inline DiyFp GetCachedPower10(int exp, int *outExp) {
inline DiyFp GetCachedPower10(int exp, int* outExp)
{
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
*outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index);
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
RAPIDJSON_DIAG_POP
#endif
#ifdef __clang__
RAPIDJSON_DIAG_POP
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_POP
RAPIDJSON_DIAG_OFF(padded)
#endif
} // namespace internal

View file

@ -24,40 +24,71 @@
#include "ieee754.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_OFF(array -
bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
#endif
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
while (rest < wp_w && delta - rest >= ten_kappa &&
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa,
uint64_t wp_w)
{
while(rest < wp_w && delta - rest >= ten_kappa &&
(rest + ten_kappa < wp_w || /// closer
wp_w - rest > rest + ten_kappa - wp_w)) {
wp_w - rest > rest + ten_kappa - wp_w))
{
buffer[len - 1]--;
rest += ten_kappa;
}
}
}
inline unsigned CountDecimalDigit32(uint32_t n) {
inline unsigned CountDecimalDigit32(uint32_t n)
{
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if(n < 10)
{
return 1;
}
if(n < 100)
{
return 2;
}
if(n < 1000)
{
return 3;
}
if(n < 10000)
{
return 4;
}
if(n < 100000)
{
return 5;
}
if(n < 1000000)
{
return 6;
}
if(n < 10000000)
{
return 7;
}
if(n < 100000000)
{
return 8;
}
// Will not reach 10 digits in DigitGen()
//if (n < 1000000000) return 9;
//return 10;
return 9;
}
}
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
inline void DigitGen(const DiyFp & W, const DiyFp & Mp, uint64_t delta, char* buffer, int* len, int* K)
{
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
const DiyFp wp_w = Mp - W;
@ -66,25 +97,58 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0;
while (kappa > 0) {
while(kappa > 0)
{
uint32_t d = 0;
switch (kappa) {
case 9: d = p1 / 100000000; p1 %= 100000000; break;
case 8: d = p1 / 10000000; p1 %= 10000000; break;
case 7: d = p1 / 1000000; p1 %= 1000000; break;
case 6: d = p1 / 100000; p1 %= 100000; break;
case 5: d = p1 / 10000; p1 %= 10000; break;
case 4: d = p1 / 1000; p1 %= 1000; break;
case 3: d = p1 / 100; p1 %= 100; break;
case 2: d = p1 / 10; p1 %= 10; break;
case 1: d = p1; p1 = 0; break;
default:;
switch(kappa)
{
case 9:
d = p1 / 100000000;
p1 %= 100000000;
break;
case 8:
d = p1 / 10000000;
p1 %= 10000000;
break;
case 7:
d = p1 / 1000000;
p1 %= 1000000;
break;
case 6:
d = p1 / 100000;
p1 %= 100000;
break;
case 5:
d = p1 / 10000;
p1 %= 10000;
break;
case 4:
d = p1 / 1000;
p1 %= 1000;
break;
case 3:
d = p1 / 100;
p1 %= 100;
break;
case 2:
d = p1 / 10;
p1 %= 10;
break;
case 1:
d = p1;
p1 = 0;
break;
default:
;
}
if (d || *len)
if(d || *len)
{
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
}
kappa--;
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
if (tmp <= delta) {
if(tmp <= delta)
{
*K += kappa;
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
return;
@ -92,24 +156,29 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
}
// kappa = 0
for (;;) {
for(;;)
{
p2 *= 10;
delta *= 10;
char d = static_cast<char>(p2 >> -one.e);
if (d || *len)
if(d || *len)
{
buffer[(*len)++] = static_cast<char>('0' + d);
}
p2 &= one.f - 1;
kappa--;
if (p2 < delta) {
if(p2 < delta)
{
*K += kappa;
int index = -static_cast<int>(kappa);
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
return;
}
}
}
}
inline void Grisu2(double value, char* buffer, int* length, int* K) {
inline void Grisu2(double value, char* buffer, int* length, int* K)
{
const DiyFp v(value);
DiyFp w_m, w_p;
v.NormalizedBoundaries(&w_m, &w_p);
@ -121,111 +190,144 @@ inline void Grisu2(double value, char* buffer, int* length, int* K) {
Wm.f++;
Wp.f--;
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
}
}
inline char* WriteExponent(int K, char* buffer) {
if (K < 0) {
inline char* WriteExponent(int K, char* buffer)
{
if(K < 0)
{
*buffer++ = '-';
K = -K;
}
if (K >= 100) {
if(K >= 100)
{
*buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
K %= 100;
const char* d = GetDigitsLut() + K * 2;
*buffer++ = d[0];
*buffer++ = d[1];
}
else if (K >= 10) {
else if(K >= 10)
{
const char* d = GetDigitsLut() + K * 2;
*buffer++ = d[0];
*buffer++ = d[1];
}
else
{
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
}
return buffer;
}
}
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces)
{
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
if (0 <= k && kk <= 21) {
if(0 <= k && kk <= 21)
{
// 1234e7 -> 12340000000
for (int i = length; i < kk; i++)
for(int i = length; i < kk; i++)
{
buffer[i] = '0';
}
buffer[kk] = '.';
buffer[kk + 1] = '0';
return &buffer[kk + 2];
}
else if (0 < kk && kk <= 21) {
else if(0 < kk && kk <= 21)
{
// 1234e-2 -> 12.34
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
buffer[kk] = '.';
if (0 > k + maxDecimalPlaces) {
if(0 > k + maxDecimalPlaces)
{
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
// Remove extra trailing zeros (at least one) after truncation.
for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
if (buffer[i] != '0')
for(int i = kk + maxDecimalPlaces; i > kk + 1; i--)
if(buffer[i] != '0')
{
return &buffer[i + 1];
}
return &buffer[kk + 2]; // Reserve one zero
}
else
{
return &buffer[length + 1];
}
else if (-6 < kk && kk <= 0) {
}
else if(-6 < kk && kk <= 0)
{
// 1234e-6 -> 0.001234
const int offset = 2 - kk;
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
buffer[0] = '0';
buffer[1] = '.';
for (int i = 2; i < offset; i++)
for(int i = 2; i < offset; i++)
{
buffer[i] = '0';
if (length - kk > maxDecimalPlaces) {
}
if(length - kk > maxDecimalPlaces)
{
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
// Remove extra trailing zeros (at least one) after truncation.
for (int i = maxDecimalPlaces + 1; i > 2; i--)
if (buffer[i] != '0')
for(int i = maxDecimalPlaces + 1; i > 2; i--)
if(buffer[i] != '0')
{
return &buffer[i + 1];
}
return &buffer[3]; // Reserve one zero
}
else
{
return &buffer[length + offset];
}
else if (kk < -maxDecimalPlaces) {
}
else if(kk < -maxDecimalPlaces)
{
// Truncate to zero
buffer[0] = '0';
buffer[1] = '.';
buffer[2] = '0';
return &buffer[3];
}
else if (length == 1) {
else if(length == 1)
{
// 1e30
buffer[1] = 'e';
return WriteExponent(kk - 1, &buffer[2]);
}
else {
else
{
// 1234e30 -> 1.234e33
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
buffer[1] = '.';
buffer[length + 1] = 'e';
return WriteExponent(kk - 1, &buffer[0 + length + 2]);
}
}
}
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324)
{
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
Double d(value);
if (d.IsZero()) {
if (d.Sign())
if(d.IsZero())
{
if(d.Sign())
{
*buffer++ = '-'; // -0.0, Issue #289
}
buffer[0] = '0';
buffer[1] = '.';
buffer[2] = '0';
return &buffer[3];
}
else {
if (value < 0) {
else
{
if(value < 0)
{
*buffer++ = '-';
value = -value;
}
@ -233,10 +335,10 @@ inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
Grisu2(value, buffer, &length, &K);
return Prettify(buffer, length, K, maxDecimalPlaces);
}
}
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
RAPIDJSON_DIAG_POP
#endif
} // namespace internal

View file

@ -18,46 +18,95 @@
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
class Double {
public:
class Double
{
public:
Double() {}
Double(double d) : d_(d) {}
Double(uint64_t u) : u_(u) {}
double Value() const { return d_; }
uint64_t Uint64Value() const { return u_; }
double Value() const
{
return d_;
}
uint64_t Uint64Value() const
{
return u_;
}
double NextPositiveDouble() const {
double NextPositiveDouble() const
{
RAPIDJSON_ASSERT(!Sign());
return Double(u_ + 1).Value();
}
bool Sign() const { return (u_ & kSignMask) != 0; }
uint64_t Significand() const { return u_ & kSignificandMask; }
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
static unsigned EffectiveSignificandSize(int order) {
if (order >= -1021)
return 53;
else if (order <= -1074)
return 0;
else
return static_cast<unsigned>(order) + 1074;
bool Sign() const
{
return (u_ & kSignMask) != 0;
}
uint64_t Significand() const
{
return u_ & kSignificandMask;
}
int Exponent() const
{
return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias);
}
private:
bool IsNan() const
{
return (u_ & kExponentMask) == kExponentMask && Significand() != 0;
}
bool IsInf() const
{
return (u_ & kExponentMask) == kExponentMask && Significand() == 0;
}
bool IsNanOrInf() const
{
return (u_ & kExponentMask) == kExponentMask;
}
bool IsNormal() const
{
return (u_ & kExponentMask) != 0 || Significand() == 0;
}
bool IsZero() const
{
return (u_ & (kExponentMask | kSignificandMask)) == 0;
}
uint64_t IntegerSignificand() const
{
return IsNormal() ? Significand() | kHiddenBit : Significand();
}
int IntegerExponent() const
{
return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize;
}
uint64_t ToBias() const
{
return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask;
}
static unsigned EffectiveSignificandSize(int order)
{
if(order >= -1021)
{
return 53;
}
else if(order <= -1074)
{
return 0;
}
else
{
return static_cast<unsigned>(order) + 1074;
}
}
private:
static const int kSignificandSize = 52;
static const int kExponentBias = 0x3FF;
static const int kDenormalExponent = 1 - kExponentBias;
@ -66,11 +115,12 @@ private:
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
union {
union
{
double d_;
uint64_t u_;
};
};
};
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -18,40 +18,52 @@
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
inline const char* GetDigitsLut() {
static const char cDigitsLut[200] = {
'0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
'1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
'2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
'3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
'4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
'5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
'6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
'7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
'8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
'9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
inline const char* GetDigitsLut()
{
static const char cDigitsLut[200] =
{
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
};
return cDigitsLut;
}
}
inline char* u32toa(uint32_t value, char* buffer) {
inline char* u32toa(uint32_t value, char* buffer)
{
const char* cDigitsLut = GetDigitsLut();
if (value < 10000) {
if(value < 10000)
{
const uint32_t d1 = (value / 100) << 1;
const uint32_t d2 = (value % 100) << 1;
if (value >= 1000)
if(value >= 1000)
{
*buffer++ = cDigitsLut[d1];
if (value >= 100)
}
if(value >= 100)
{
*buffer++ = cDigitsLut[d1 + 1];
if (value >= 10)
}
if(value >= 10)
{
*buffer++ = cDigitsLut[d2];
}
*buffer++ = cDigitsLut[d2 + 1];
}
else if (value < 100000000) {
else if(value < 100000000)
{
// value = bbbbcccc
const uint32_t b = value / 10000;
const uint32_t c = value % 10000;
@ -62,12 +74,18 @@ inline char* u32toa(uint32_t value, char* buffer) {
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
if (value >= 10000000)
if(value >= 10000000)
{
*buffer++ = cDigitsLut[d1];
if (value >= 1000000)
}
if(value >= 1000000)
{
*buffer++ = cDigitsLut[d1 + 1];
if (value >= 100000)
}
if(value >= 100000)
{
*buffer++ = cDigitsLut[d2];
}
*buffer++ = cDigitsLut[d2 + 1];
*buffer++ = cDigitsLut[d3];
@ -75,19 +93,23 @@ inline char* u32toa(uint32_t value, char* buffer) {
*buffer++ = cDigitsLut[d4];
*buffer++ = cDigitsLut[d4 + 1];
}
else {
else
{
// value = aabbbbcccc in decimal
const uint32_t a = value / 100000000; // 1 to 42
value %= 100000000;
if (a >= 10) {
if(a >= 10)
{
const unsigned i = a << 1;
*buffer++ = cDigitsLut[i];
*buffer++ = cDigitsLut[i + 1];
}
else
{
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
}
const uint32_t b = value / 10000; // 0 to 9999
const uint32_t c = value % 10000; // 0 to 9999
@ -108,19 +130,22 @@ inline char* u32toa(uint32_t value, char* buffer) {
*buffer++ = cDigitsLut[d4 + 1];
}
return buffer;
}
}
inline char* i32toa(int32_t value, char* buffer) {
inline char* i32toa(int32_t value, char* buffer)
{
uint32_t u = static_cast<uint32_t>(value);
if (value < 0) {
if(value < 0)
{
*buffer++ = '-';
u = ~u + 1;
}
return u32toa(u, buffer);
}
}
inline char* u64toa(uint64_t value, char* buffer) {
inline char* u64toa(uint64_t value, char* buffer)
{
const char* cDigitsLut = GetDigitsLut();
const uint64_t kTen8 = 100000000;
const uint64_t kTen9 = kTen8 * 10;
@ -132,21 +157,30 @@ inline char* u64toa(uint64_t value, char* buffer) {
const uint64_t kTen15 = kTen8 * 10000000;
const uint64_t kTen16 = kTen8 * kTen8;
if (value < kTen8) {
if(value < kTen8)
{
uint32_t v = static_cast<uint32_t>(value);
if (v < 10000) {
if(v < 10000)
{
const uint32_t d1 = (v / 100) << 1;
const uint32_t d2 = (v % 100) << 1;
if (v >= 1000)
if(v >= 1000)
{
*buffer++ = cDigitsLut[d1];
if (v >= 100)
}
if(v >= 100)
{
*buffer++ = cDigitsLut[d1 + 1];
if (v >= 10)
}
if(v >= 10)
{
*buffer++ = cDigitsLut[d2];
}
*buffer++ = cDigitsLut[d2 + 1];
}
else {
else
{
// value = bbbbcccc
const uint32_t b = v / 10000;
const uint32_t c = v % 10000;
@ -157,12 +191,18 @@ inline char* u64toa(uint64_t value, char* buffer) {
const uint32_t d3 = (c / 100) << 1;
const uint32_t d4 = (c % 100) << 1;
if (value >= 10000000)
if(value >= 10000000)
{
*buffer++ = cDigitsLut[d1];
if (value >= 1000000)
}
if(value >= 1000000)
{
*buffer++ = cDigitsLut[d1 + 1];
if (value >= 100000)
}
if(value >= 100000)
{
*buffer++ = cDigitsLut[d2];
}
*buffer++ = cDigitsLut[d2 + 1];
*buffer++ = cDigitsLut[d3];
@ -171,7 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d4 + 1];
}
}
else if (value < kTen16) {
else if(value < kTen16)
{
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
@ -193,22 +234,38 @@ inline char* u64toa(uint64_t value, char* buffer) {
const uint32_t d7 = (c1 / 100) << 1;
const uint32_t d8 = (c1 % 100) << 1;
if (value >= kTen15)
if(value >= kTen15)
{
*buffer++ = cDigitsLut[d1];
if (value >= kTen14)
}
if(value >= kTen14)
{
*buffer++ = cDigitsLut[d1 + 1];
if (value >= kTen13)
}
if(value >= kTen13)
{
*buffer++ = cDigitsLut[d2];
if (value >= kTen12)
}
if(value >= kTen12)
{
*buffer++ = cDigitsLut[d2 + 1];
if (value >= kTen11)
}
if(value >= kTen11)
{
*buffer++ = cDigitsLut[d3];
if (value >= kTen10)
}
if(value >= kTen10)
{
*buffer++ = cDigitsLut[d3 + 1];
if (value >= kTen9)
}
if(value >= kTen9)
{
*buffer++ = cDigitsLut[d4];
if (value >= kTen8)
}
if(value >= kTen8)
{
*buffer++ = cDigitsLut[d4 + 1];
}
*buffer++ = cDigitsLut[d5];
*buffer++ = cDigitsLut[d5 + 1];
@ -219,25 +276,31 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d8];
*buffer++ = cDigitsLut[d8 + 1];
}
else {
else
{
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
value %= kTen16;
if (a < 10)
if(a < 10)
{
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
else if (a < 100) {
}
else if(a < 100)
{
const uint32_t i = a << 1;
*buffer++ = cDigitsLut[i];
*buffer++ = cDigitsLut[i + 1];
}
else if (a < 1000) {
else if(a < 1000)
{
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
const uint32_t i = (a % 100) << 1;
*buffer++ = cDigitsLut[i];
*buffer++ = cDigitsLut[i + 1];
}
else {
else
{
const uint32_t i = (a / 100) << 1;
const uint32_t j = (a % 100) << 1;
*buffer++ = cDigitsLut[i];
@ -286,17 +349,19 @@ inline char* u64toa(uint64_t value, char* buffer) {
}
return buffer;
}
}
inline char* i64toa(int64_t value, char* buffer) {
inline char* i64toa(int64_t value, char* buffer)
{
uint64_t u = static_cast<uint64_t>(value);
if (value < 0) {
if(value < 0)
{
*buffer++ = '-';
u = ~u + 1;
}
return u64toa(u, buffer);
}
}
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -32,121 +32,164 @@ RAPIDJSON_DIAG_OFF(6334)
//@cond RAPIDJSON_INTERNAL
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
template <typename T> struct Void { typedef void Type; };
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
template <typename T> struct Void
{
typedef void Type;
};
///////////////////////////////////////////////////////////////////////////////
// BoolType, TrueType, FalseType
//
template <bool Cond> struct BoolType {
///////////////////////////////////////////////////////////////////////////////
// BoolType, TrueType, FalseType
//
template <bool Cond> struct BoolType
{
static const bool Value = Cond;
typedef BoolType Type;
};
typedef BoolType<true> TrueType;
typedef BoolType<false> FalseType;
};
typedef BoolType<true> TrueType;
typedef BoolType<false> FalseType;
///////////////////////////////////////////////////////////////////////////////
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
//
///////////////////////////////////////////////////////////////////////////////
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
//
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
template <bool C> struct SelectIfImpl
{
template <typename T1, typename T2> struct Apply
{
typedef T1 Type;
};
};
template <> struct SelectIfImpl<false>
{
template <typename T1, typename T2> struct Apply
{
typedef T2 Type;
};
};
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1, T2> {};
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
template <> struct AndExprCond<true, true> : TrueType {};
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
template <> struct OrExprCond<false, false> : FalseType {};
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
template <> struct AndExprCond<true, true> : TrueType {};
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
template <> struct OrExprCond<false, false> : FalseType {};
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
template <typename C> struct BoolExpr : SelectIf<C, TrueType, FalseType>::Type {};
template <typename C> struct NotExpr : SelectIf<C, FalseType, TrueType>::Type {};
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
///////////////////////////////////////////////////////////////////////////////
// AddConst, MaybeAddConst, RemoveConst
template <typename T> struct AddConst { typedef const T Type; };
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
template <typename T> struct RemoveConst { typedef T Type; };
template <typename T> struct RemoveConst<const T> { typedef T Type; };
///////////////////////////////////////////////////////////////////////////////
// AddConst, MaybeAddConst, RemoveConst
template <typename T> struct AddConst
{
typedef const T Type;
};
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
template <typename T> struct RemoveConst
{
typedef T Type;
};
template <typename T> struct RemoveConst<const T>
{
typedef T Type;
};
///////////////////////////////////////////////////////////////////////////////
// IsSame, IsConst, IsMoreConst, IsPointer
//
template <typename T, typename U> struct IsSame : FalseType {};
template <typename T> struct IsSame<T, T> : TrueType {};
///////////////////////////////////////////////////////////////////////////////
// IsSame, IsConst, IsMoreConst, IsPointer
//
template <typename T, typename U> struct IsSame : FalseType {};
template <typename T> struct IsSame<T, T> : TrueType {};
template <typename T> struct IsConst : FalseType {};
template <typename T> struct IsConst<const T> : TrueType {};
template <typename T> struct IsConst : FalseType {};
template <typename T> struct IsConst<const T> : TrueType {};
template <typename CT, typename T>
struct IsMoreConst
template <typename CT, typename T>
struct IsMoreConst
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
template <typename T> struct IsPointer : FalseType {};
template <typename T> struct IsPointer<T*> : TrueType {};
template <typename T> struct IsPointer : FalseType {};
template <typename T> struct IsPointer<T*> : TrueType {};
///////////////////////////////////////////////////////////////////////////////
// IsBaseOf
//
///////////////////////////////////////////////////////////////////////////////
// IsBaseOf
//
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
template <typename B, typename D> struct IsBaseOf
: BoolType< ::std::is_base_of<B,D>::value> {};
template <typename B, typename D> struct IsBaseOf
: BoolType<::std::is_base_of<B, D>::value> {};
#else // simplified version adopted from Boost
template<typename B, typename D> struct IsBaseOfImpl {
template<typename B, typename D> struct IsBaseOfImpl
{
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
typedef char (&Yes)[1];
typedef char (&No) [2];
typedef char(&Yes)[1];
typedef char(&No) [2];
template <typename T>
static Yes Check(const D*, T);
static No Check(const B*, int);
struct Host {
operator const B*() const;
operator const D*();
struct Host
{
operator const B* () const;
operator const D* ();
};
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
};
};
template <typename B, typename D> struct IsBaseOf
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
template <typename B, typename D> struct IsBaseOf
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D>>>::Type {};
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
//////////////////////////////////////////////////////////////////////////
// EnableIf / DisableIf
//
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
template <typename T> struct EnableIfCond<false, T> { /* empty */ };
//////////////////////////////////////////////////////////////////////////
// EnableIf / DisableIf
//
template <bool Condition, typename T = void> struct EnableIfCond
{
typedef T Type;
};
template <typename T> struct EnableIfCond<false, T>
{
/* empty */
};
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
template <typename T> struct DisableIfCond<true, T> { /* empty */ };
template <bool Condition, typename T = void> struct DisableIfCond
{
typedef T Type;
};
template <typename T> struct DisableIfCond<true, T>
{
/* empty */
};
template <typename Condition, typename T = void>
struct EnableIf : EnableIfCond<Condition::Value, T> {};
template <typename Condition, typename T = void>
struct EnableIf : EnableIfCond<Condition::Value, T> {};
template <typename Condition, typename T = void>
struct DisableIf : DisableIfCond<Condition::Value, T> {};
template <typename Condition, typename T = void>
struct DisableIf : DisableIfCond<Condition::Value, T> {};
// SFINAE helpers
struct SfinaeTag {};
template <typename T> struct RemoveSfinaeTag;
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
// SFINAE helpers
struct SfinaeTag {};
template <typename T> struct RemoveSfinaeTag;
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)>
{
typedef T Type;
};
#define RAPIDJSON_REMOVEFPTR_(type) \
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \

View file

@ -18,36 +18,39 @@
#include "../rapidjson.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
//! Computes integer powers of 10 in double (10.0^n).
/*! This function uses lookup table for fast and accurate results.
//! Computes integer powers of 10 in double (10.0^n).
/*! This function uses lookup table for fast and accurate results.
\param n non-negative exponent. Must <= 308.
\return 10.0^n
*/
inline double Pow10(int n) {
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
*/
inline double Pow10(int n)
{
static const double e[] = // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
{
1e+0,
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119, 1e+120,
1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140,
1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160,
1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179, 1e+180,
1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199, 1e+200,
1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219, 1e+220,
1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240,
1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260,
1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269, 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279, 1e+280,
1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299, 1e+300,
1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308
};
RAPIDJSON_ASSERT(n >= 0 && n <= 308);
return e[n];
}
}
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -22,35 +22,37 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
RAPIDJSON_DIAG_OFF(switch - enum)
RAPIDJSON_DIAG_OFF(implicit - fallthrough)
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
#ifndef RAPIDJSON_REGEX_VERBOSE
#define RAPIDJSON_REGEX_VERBOSE 0
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
RAPIDJSON_NAMESPACE_BEGIN
namespace internal
{
///////////////////////////////////////////////////////////////////////////////
// GenericRegex
///////////////////////////////////////////////////////////////////////////////
// GenericRegex
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
static const SizeType kRegexInvalidRange = ~SizeType(0);
static const SizeType kRegexInvalidState = ~SizeType(
0); //!< Represents an invalid index in GenericRegex::State::out, out1
static const SizeType kRegexInvalidRange = ~SizeType(0);
//! Regular expression engine with subset of ECMAscript grammar.
/*!
//! Regular expression engine with subset of ECMAscript grammar.
/*!
Supported regular expression syntax:
- \c ab Concatenation
- \c a|b Alternation
@ -80,10 +82,11 @@ static const SizeType kRegexInvalidRange = ~SizeType(0);
\note This is a Thompson NFA engine, implemented with reference to
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
https://swtch.com/~rsc/regexp/regexp1.html
*/
template <typename Encoding, typename Allocator = CrtAllocator>
class GenericRegex {
public:
*/
template <typename Encoding, typename Allocator = CrtAllocator>
class GenericRegex
{
public:
typedef typename Encoding::Ch Ch;
GenericRegex(const Ch* source, Allocator* allocator = 0) :
@ -91,40 +94,47 @@ public:
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
{
GenericStringStream<Encoding> ss(source);
DecodedStream<GenericStringStream<Encoding> > ds(ss);
DecodedStream<GenericStringStream<Encoding>> ds(ss);
Parse(ds);
}
~GenericRegex() {
~GenericRegex()
{
Allocator::Free(stateSet_);
}
bool IsValid() const {
bool IsValid() const
{
return root_ != kRegexInvalidState;
}
template <typename InputStream>
bool Match(InputStream& is) const {
bool Match(InputStream & is) const
{
return SearchWithAnchoring(is, true, true);
}
bool Match(const Ch* s) const {
bool Match(const Ch* s) const
{
GenericStringStream<Encoding> is(s);
return Match(is);
}
template <typename InputStream>
bool Search(InputStream& is) const {
bool Search(InputStream & is) const
{
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
}
bool Search(const Ch* s) const {
bool Search(const Ch* s) const
{
GenericStringStream<Encoding> is(s);
return Search(is);
}
private:
enum Operator {
private:
enum Operator
{
kZeroOrOne,
kZeroOrMore,
kOneOrMore,
@ -137,20 +147,23 @@ private:
static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
static const unsigned kRangeNegationFlag = 0x80000000;
struct Range {
struct Range
{
unsigned start; //
unsigned end;
SizeType next;
};
struct State {
struct State
{
SizeType out; //!< Equals to kInvalid for matching state
SizeType out1; //!< Equals to non-kInvalid for split
SizeType rangeStart;
unsigned codepoint;
};
struct Frag {
struct Frag
{
Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
SizeType start;
SizeType out; //!< link-list of all output states
@ -158,49 +171,67 @@ private:
};
template <typename SourceStream>
class DecodedStream {
class DecodedStream
{
public:
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
unsigned Peek() { return codepoint_; }
unsigned Take() {
unsigned c = codepoint_;
if (c) // No further decoding when '\0'
DecodedStream(SourceStream & ss) : ss_(ss), codepoint_()
{
Decode();
}
unsigned Peek()
{
return codepoint_;
}
unsigned Take()
{
unsigned c = codepoint_;
if(c) // No further decoding when '\0'
{
Decode();
}
return c;
}
private:
void Decode() {
if (!Encoding::Decode(ss_, &codepoint_))
void Decode()
{
if(!Encoding::Decode(ss_, &codepoint_))
{
codepoint_ = 0;
}
}
SourceStream& ss_;
SourceStream & ss_;
unsigned codepoint_;
};
State& GetState(SizeType index) {
State & GetState(SizeType index)
{
RAPIDJSON_ASSERT(index < stateCount_);
return states_.template Bottom<State>()[index];
}
const State& GetState(SizeType index) const {
const State & GetState(SizeType index) const
{
RAPIDJSON_ASSERT(index < stateCount_);
return states_.template Bottom<State>()[index];
}
Range& GetRange(SizeType index) {
Range & GetRange(SizeType index)
{
RAPIDJSON_ASSERT(index < rangeCount_);
return ranges_.template Bottom<Range>()[index];
}
const Range& GetRange(SizeType index) const {
const Range & GetRange(SizeType index) const
{
RAPIDJSON_ASSERT(index < rangeCount_);
return ranges_.template Bottom<Range>()[index];
}
template <typename InputStream>
void Parse(DecodedStream<InputStream>& ds) {
void Parse(DecodedStream<InputStream> & ds)
{
Allocator allocator;
Stack<Allocator> operandStack(&allocator, 256); // Frag
Stack<Allocator> operatorStack(&allocator, 256); // Operator
@ -209,8 +240,10 @@ private:
*atomCountStack.template Push<unsigned>() = 0;
unsigned codepoint;
while (ds.Peek() != 0) {
switch (codepoint = ds.Take()) {
while(ds.Peek() != 0)
{
switch(codepoint = ds.Take())
{
case '^':
anchorBegin_ = true;
break;
@ -220,9 +253,11 @@ private:
break;
case '|':
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
while(!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
{
return;
}
*operatorStack.template Push<Operator>() = kAlternation;
*atomCountStack.template Top<unsigned>() = 0;
break;
@ -233,49 +268,70 @@ private:
break;
case ')':
while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
while(!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
{
return;
if (operatorStack.Empty())
}
if(operatorStack.Empty())
{
return;
}
operatorStack.template Pop<Operator>(1);
atomCountStack.template Pop<unsigned>(1);
ImplicitConcatenation(atomCountStack, operatorStack);
break;
case '?':
if (!Eval(operandStack, kZeroOrOne))
if(!Eval(operandStack, kZeroOrOne))
{
return;
}
break;
case '*':
if (!Eval(operandStack, kZeroOrMore))
if(!Eval(operandStack, kZeroOrMore))
{
return;
}
break;
case '+':
if (!Eval(operandStack, kOneOrMore))
if(!Eval(operandStack, kOneOrMore))
{
return;
}
break;
case '{':
{
unsigned n, m;
if (!ParseUnsigned(ds, &n))
return;
if (ds.Peek() == ',') {
ds.Take();
if (ds.Peek() == '}')
m = kInfinityQuantifier;
else if (!ParseUnsigned(ds, &m) || m < n)
if(!ParseUnsigned(ds, &n))
{
return;
}
else
m = n;
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
if(ds.Peek() == ',')
{
ds.Take();
if(ds.Peek() == '}')
{
m = kInfinityQuantifier;
}
else if(!ParseUnsigned(ds, &m) || m < n)
{
return;
}
}
else
{
m = n;
}
if(!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
{
return;
}
ds.Take();
}
break;
@ -288,8 +344,10 @@ private:
case '[':
{
SizeType range;
if (!ParseRange(ds, &range))
if(!ParseRange(ds, &range))
{
return;
}
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
GetState(s).rangeStart = range;
*operandStack.template Push<Frag>() = Frag(s, s, s);
@ -298,8 +356,10 @@ private:
break;
case '\\': // Escape character
if (!CharacterEscape(ds, &codepoint))
if(!CharacterEscape(ds, &codepoint))
{
return; // Unsupported escape character
}
// fall through to default
default: // Pattern character
@ -308,20 +368,24 @@ private:
}
}
while (!operatorStack.Empty())
if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
while(!operatorStack.Empty())
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
{
return;
}
// Link the operand to matching state.
if (operandStack.GetSize() == sizeof(Frag)) {
if(operandStack.GetSize() == sizeof(Frag))
{
Frag* e = operandStack.template Pop<Frag>(1);
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
root_ = e->start;
#if RAPIDJSON_REGEX_VERBOSE
printf("root: %d\n", root_);
for (SizeType i = 0; i < stateCount_ ; i++) {
State& s = GetState(i);
for(SizeType i = 0; i < stateCount_ ; i++)
{
State & s = GetState(i);
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
}
printf("\n");
@ -330,14 +394,16 @@ private:
// Preallocate buffer for SearchWithAnchoring()
RAPIDJSON_ASSERT(stateSet_ == 0);
if (stateCount_ > 0) {
if(stateCount_ > 0)
{
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
state0_.template Reserve<SizeType>(stateCount_);
state1_.template Reserve<SizeType>(stateCount_);
}
}
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint)
{
State* s = states_.template Push<State>();
s->out = out;
s->out1 = out1;
@ -346,34 +412,45 @@ private:
return stateCount_++;
}
void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
void PushOperand(Stack<Allocator> & operandStack, unsigned codepoint)
{
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
*operandStack.template Push<Frag>() = Frag(s, s, s);
}
void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
if (*atomCountStack.template Top<unsigned>())
void ImplicitConcatenation(Stack<Allocator> & atomCountStack, Stack<Allocator> & operatorStack)
{
if(*atomCountStack.template Top<unsigned>())
{
*operatorStack.template Push<Operator>() = kConcatenation;
}
(*atomCountStack.template Top<unsigned>())++;
}
SizeType Append(SizeType l1, SizeType l2) {
SizeType Append(SizeType l1, SizeType l2)
{
SizeType old = l1;
while (GetState(l1).out != kRegexInvalidState)
while(GetState(l1).out != kRegexInvalidState)
{
l1 = GetState(l1).out;
}
GetState(l1).out = l2;
return old;
}
void Patch(SizeType l, SizeType s) {
for (SizeType next; l != kRegexInvalidState; l = next) {
void Patch(SizeType l, SizeType s)
{
for(SizeType next; l != kRegexInvalidState; l = next)
{
next = GetState(l).out;
GetState(l).out = s;
}
}
bool Eval(Stack<Allocator>& operandStack, Operator op) {
switch (op) {
bool Eval(Stack<Allocator> & operandStack, Operator op)
{
switch(op)
{
case kConcatenation:
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
{
@ -385,7 +462,8 @@ private:
return true;
case kAlternation:
if (operandStack.GetSize() >= sizeof(Frag) * 2) {
if(operandStack.GetSize() >= sizeof(Frag) * 2)
{
Frag e2 = *operandStack.template Pop<Frag>(1);
Frag e1 = *operandStack.template Pop<Frag>(1);
SizeType s = NewState(e1.start, e2.start, 0);
@ -395,7 +473,8 @@ private:
return false;
case kZeroOrOne:
if (operandStack.GetSize() >= sizeof(Frag)) {
if(operandStack.GetSize() >= sizeof(Frag))
{
Frag e = *operandStack.template Pop<Frag>(1);
SizeType s = NewState(kRegexInvalidState, e.start, 0);
*operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
@ -404,7 +483,8 @@ private:
return false;
case kZeroOrMore:
if (operandStack.GetSize() >= sizeof(Frag)) {
if(operandStack.GetSize() >= sizeof(Frag))
{
Frag e = *operandStack.template Pop<Frag>(1);
SizeType s = NewState(kRegexInvalidState, e.start, 0);
Patch(e.out, s);
@ -415,7 +495,8 @@ private:
default:
RAPIDJSON_ASSERT(op == kOneOrMore);
if (operandStack.GetSize() >= sizeof(Frag)) {
if(operandStack.GetSize() >= sizeof(Frag))
{
Frag e = *operandStack.template Pop<Frag>(1);
SizeType s = NewState(kRegexInvalidState, e.start, 0);
Patch(e.out, s);
@ -426,70 +507,108 @@ private:
}
}
bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
bool EvalQuantifier(Stack<Allocator> & operandStack, unsigned n, unsigned m)
{
RAPIDJSON_ASSERT(n <= m);
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
if (n == 0) {
if (m == 0) // a{0} not support
if(n == 0)
{
if(m == 0) // a{0} not support
{
return false;
else if (m == kInfinityQuantifier)
Eval(operandStack, kZeroOrMore); // a{0,} -> a*
else {
}
else if(m == kInfinityQuantifier)
{
Eval(operandStack, kZeroOrMore);
} // a{0,} -> a*
else
{
Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
for (unsigned i = 0; i < m - 1; i++)
CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
for (unsigned i = 0; i < m - 1; i++)
Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
for(unsigned i = 0; i < m - 1; i++)
{
CloneTopOperand(operandStack);
} // a{0,5} -> a? a? a? a? a?
for(unsigned i = 0; i < m - 1; i++)
{
Eval(operandStack, kConcatenation);
} // a{0,5} -> a?a?a?a?a?
}
return true;
}
for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
for(unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
{
CloneTopOperand(operandStack);
}
if (m == kInfinityQuantifier)
Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
else if (m > n) {
if(m == kInfinityQuantifier)
{
Eval(operandStack, kOneOrMore);
} // a{3,} -> a a a+
else if(m > n)
{
CloneTopOperand(operandStack); // a{3,5} -> a a a a
Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
for (unsigned i = n; i < m - 1; i++)
CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
for (unsigned i = n; i < m; i++)
Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
for(unsigned i = n; i < m - 1; i++)
{
CloneTopOperand(operandStack);
} // a{3,5} -> a a a a? a?
for(unsigned i = n; i < m; i++)
{
Eval(operandStack, kConcatenation);
} // a{3,5} -> a a aa?a?
}
for (unsigned i = 0; i < n - 1; i++)
Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
for(unsigned i = 0; i < n - 1; i++)
{
Eval(operandStack, kConcatenation);
} // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
return true;
}
static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
static SizeType Min(SizeType a, SizeType b)
{
return a < b ? a : b;
}
void CloneTopOperand(Stack<Allocator>& operandStack) {
void CloneTopOperand(Stack<Allocator> & operandStack)
{
const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
SizeType count = stateCount_ -
src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
State* s = states_.template Push<State>(count);
memcpy(s, &GetState(src.minIndex), count * sizeof(State));
for (SizeType j = 0; j < count; j++) {
if (s[j].out != kRegexInvalidState)
for(SizeType j = 0; j < count; j++)
{
if(s[j].out != kRegexInvalidState)
{
s[j].out += count;
if (s[j].out1 != kRegexInvalidState)
}
if(s[j].out1 != kRegexInvalidState)
{
s[j].out1 += count;
}
}
*operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
stateCount_ += count;
}
template <typename InputStream>
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
bool ParseUnsigned(DecodedStream<InputStream> & ds, unsigned* u)
{
unsigned r = 0;
if (ds.Peek() < '0' || ds.Peek() > '9')
if(ds.Peek() < '0' || ds.Peek() > '9')
{
return false;
while (ds.Peek() >= '0' && ds.Peek() <= '9') {
if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
}
while(ds.Peek() >= '0' && ds.Peek() <= '9')
{
if(r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
{
return false; // overflow
}
r = r * 10 + (ds.Take() - '0');
}
*u = r;
@ -497,49 +616,64 @@ private:
}
template <typename InputStream>
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
bool ParseRange(DecodedStream<InputStream> & ds, SizeType* range)
{
bool isBegin = true;
bool negate = false;
int step = 0;
SizeType start = kRegexInvalidRange;
SizeType current = kRegexInvalidRange;
unsigned codepoint;
while ((codepoint = ds.Take()) != 0) {
if (isBegin) {
while((codepoint = ds.Take()) != 0)
{
if(isBegin)
{
isBegin = false;
if (codepoint == '^') {
if(codepoint == '^')
{
negate = true;
continue;
}
}
switch (codepoint) {
switch(codepoint)
{
case ']':
if (start == kRegexInvalidRange)
if(start == kRegexInvalidRange)
{
return false; // Error: nothing inside []
if (step == 2) { // Add trailing '-'
}
if(step == 2) // Add trailing '-'
{
SizeType r = NewRange('-');
RAPIDJSON_ASSERT(current != kRegexInvalidRange);
GetRange(current).next = r;
}
if (negate)
if(negate)
{
GetRange(start).start |= kRangeNegationFlag;
}
*range = start;
return true;
case '\\':
if (ds.Peek() == 'b') {
if(ds.Peek() == 'b')
{
ds.Take();
codepoint = 0x0008; // Escape backspace character
}
else if (!CharacterEscape(ds, &codepoint))
else if(!CharacterEscape(ds, &codepoint))
{
return false;
}
// fall through to default
default:
switch (step) {
switch(step)
{
case 1:
if (codepoint == '-') {
if(codepoint == '-')
{
step++;
break;
}
@ -548,10 +682,14 @@ private:
case 0:
{
SizeType r = NewRange(codepoint);
if (current != kRegexInvalidRange)
if(current != kRegexInvalidRange)
{
GetRange(current).next = r;
if (start == kRegexInvalidRange)
}
if(start == kRegexInvalidRange)
{
start = r;
}
current = r;
}
step = 1;
@ -567,7 +705,8 @@ private:
return false;
}
SizeType NewRange(unsigned codepoint) {
SizeType NewRange(unsigned codepoint)
{
Range* r = ranges_.template Push<Range>();
r->start = r->end = codepoint;
r->next = kRegexInvalidRange;
@ -575,9 +714,11 @@ private:
}
template <typename InputStream>
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
bool CharacterEscape(DecodedStream<InputStream> & ds, unsigned* escapedCodepoint)
{
unsigned codepoint;
switch (codepoint = ds.Take()) {
switch(codepoint = ds.Take())
{
case '^':
case '$':
case '|':
@ -592,78 +733,105 @@ private:
case '{':
case '}':
case '\\':
*escapedCodepoint = codepoint; return true;
case 'f': *escapedCodepoint = 0x000C; return true;
case 'n': *escapedCodepoint = 0x000A; return true;
case 'r': *escapedCodepoint = 0x000D; return true;
case 't': *escapedCodepoint = 0x0009; return true;
case 'v': *escapedCodepoint = 0x000B; return true;
*escapedCodepoint = codepoint;
return true;
case 'f':
*escapedCodepoint = 0x000C;
return true;
case 'n':
*escapedCodepoint = 0x000A;
return true;
case 'r':
*escapedCodepoint = 0x000D;
return true;
case 't':
*escapedCodepoint = 0x0009;
return true;
case 'v':
*escapedCodepoint = 0x000B;
return true;
default:
return false; // Unsupported escape character
}
}
template <typename InputStream>
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
bool SearchWithAnchoring(InputStream & is, bool anchorBegin, bool anchorEnd) const
{
RAPIDJSON_ASSERT(IsValid());
DecodedStream<InputStream> ds(is);
state0_.Clear();
Stack<Allocator> *current = &state0_, *next = &state1_;
Stack<Allocator>* current = &state0_, *next = &state1_;
const size_t stateSetSize = GetStateSetSize();
std::memset(stateSet_, 0, stateSetSize);
bool matched = AddState(*current, root_);
unsigned codepoint;
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
while(!current->Empty() && (codepoint = ds.Take()) != 0)
{
std::memset(stateSet_, 0, stateSetSize);
next->Clear();
matched = false;
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
const State& sr = GetState(*s);
if (sr.codepoint == codepoint ||
for(const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s)
{
const State & sr = GetState(*s);
if(sr.codepoint == codepoint ||
sr.codepoint == kAnyCharacterClass ||
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{
matched = AddState(*next, sr.out) || matched;
if (!anchorEnd && matched)
if(!anchorEnd && matched)
{
return true;
}
if (!anchorBegin)
}
if(!anchorBegin)
{
AddState(*next, root_);
}
}
internal::Swap(current, next);
}
return matched;
}
size_t GetStateSetSize() const {
size_t GetStateSetSize() const
{
return (stateCount_ + 31) / 32 * 4;
}
// Return whether the added states is a match state
bool AddState(Stack<Allocator>& l, SizeType index) const {
bool AddState(Stack<Allocator> & l, SizeType index) const
{
RAPIDJSON_ASSERT(index != kRegexInvalidState);
const State& s = GetState(index);
if (s.out1 != kRegexInvalidState) { // Split
const State & s = GetState(index);
if(s.out1 != kRegexInvalidState) // Split
{
bool matched = AddState(l, s.out);
return AddState(l, s.out1) || matched;
}
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
else if(!(stateSet_[index >> 5] & (1 << (index & 31))))
{
stateSet_[index >> 5] |= (1 << (index & 31));
*l.template PushUnsafe<SizeType>() = index;
}
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
return s.out ==
kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
}
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const
{
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
while (rangeIndex != kRegexInvalidRange) {
const Range& r = GetRange(rangeIndex);
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
while(rangeIndex != kRegexInvalidRange)
{
const Range & r = GetRange(rangeIndex);
if(codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
{
return yes;
}
rangeIndex = r.next;
}
return !yes;
@ -683,11 +851,11 @@ private:
mutable Stack<Allocator> state1_;
bool anchorBegin_;
bool anchorEnd_;
};
};
typedef GenericRegex<UTF8<> > Regex;
typedef GenericRegex<UTF8<>> Regex;
} // namespace internal
} // namespace internal
RAPIDJSON_NAMESPACE_END
#ifdef __clang__

View file

@ -20,28 +20,32 @@
#if defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++98-compat)
RAPIDJSON_DIAG_OFF(c++98 - compat)
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
///////////////////////////////////////////////////////////////////////////////
// Stack
///////////////////////////////////////////////////////////////////////////////
// Stack
//! A type-unsafe stack for storing different types of data.
/*! \tparam Allocator Allocator for allocating stack memory.
*/
template <typename Allocator>
class Stack {
public:
//! A type-unsafe stack for storing different types of data.
/*! \tparam Allocator Allocator for allocating stack memory.
*/
template <typename Allocator>
class Stack
{
public:
// Optimization note: Do not allocate memory for stack_ in constructor.
// Do it lazily when first Push() -> Expand() -> Resize().
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0),
stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity)
{
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
Stack(Stack&& rhs)
Stack(Stack && rhs)
: allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_),
stack_(rhs.stack_),
@ -58,13 +62,15 @@ public:
}
#endif
~Stack() {
~Stack()
{
Destroy();
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
Stack& operator=(Stack&& rhs) {
if (&rhs != this)
Stack & operator=(Stack && rhs)
{
if(&rhs != this)
{
Destroy();
@ -86,7 +92,8 @@ public:
}
#endif
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
void Swap(Stack & rhs) RAPIDJSON_NOEXCEPT
{
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(stack_, rhs.stack_);
@ -95,10 +102,15 @@ public:
internal::Swap(initialCapacity_, rhs.initialCapacity_);
}
void Clear() { stackTop_ = stack_; }
void Clear()
{
stackTop_ = stack_;
}
void ShrinkToFit() {
if (Empty()) {
void ShrinkToFit()
{
if(Empty())
{
// If the stack is empty, completely deallocate the memory.
Allocator::Free(stack_);
stack_ = 0;
@ -106,26 +118,33 @@ public:
stackEnd_ = 0;
}
else
{
Resize(GetSize());
}
}
// Optimization note: try to minimize the size of this function for force inline.
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
template<typename T>
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1)
{
// Expand the stack if needed
if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
if(RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
{
Expand<T>(count);
}
}
template<typename T>
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1)
{
Reserve<T>(count);
return PushUnsafe<T>(count);
}
template<typename T>
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1)
{
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
T* ret = reinterpret_cast<T*>(stackTop_);
stackTop_ += sizeof(T) * count;
@ -133,92 +152,128 @@ public:
}
template<typename T>
T* Pop(size_t count) {
T* Pop(size_t count)
{
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
stackTop_ -= count * sizeof(T);
return reinterpret_cast<T*>(stackTop_);
}
template<typename T>
T* Top() {
T* Top()
{
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
}
template<typename T>
const T* Top() const {
const T* Top() const
{
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
}
template<typename T>
T* End() { return reinterpret_cast<T*>(stackTop_); }
T* End()
{
return reinterpret_cast<T*>(stackTop_);
}
template<typename T>
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
const T* End() const
{
return reinterpret_cast<T*>(stackTop_);
}
template<typename T>
T* Bottom() { return reinterpret_cast<T*>(stack_); }
T* Bottom()
{
return reinterpret_cast<T*>(stack_);
}
template<typename T>
const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
const T* Bottom() const
{
return reinterpret_cast<T*>(stack_);
}
bool HasAllocator() const {
bool HasAllocator() const
{
return allocator_ != 0;
}
Allocator& GetAllocator() {
Allocator & GetAllocator()
{
RAPIDJSON_ASSERT(allocator_);
return *allocator_;
}
bool Empty() const { return stackTop_ == stack_; }
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
bool Empty() const
{
return stackTop_ == stack_;
}
size_t GetSize() const
{
return static_cast<size_t>(stackTop_ - stack_);
}
size_t GetCapacity() const
{
return static_cast<size_t>(stackEnd_ - stack_);
}
private:
private:
template<typename T>
void Expand(size_t count) {
void Expand(size_t count)
{
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
size_t newCapacity;
if (stack_ == 0) {
if (!allocator_)
if(stack_ == 0)
{
if(!allocator_)
{
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
newCapacity = initialCapacity_;
} else {
}
else
{
newCapacity = GetCapacity();
newCapacity += (newCapacity + 1) / 2;
}
size_t newSize = GetSize() + sizeof(T) * count;
if (newCapacity < newSize)
if(newCapacity < newSize)
{
newCapacity = newSize;
}
Resize(newCapacity);
}
void Resize(size_t newCapacity) {
void Resize(size_t newCapacity)
{
const size_t size = GetSize(); // Backup the current size
stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
stackTop_ = stack_ + size;
stackEnd_ = stack_ + newCapacity;
}
void Destroy() {
void Destroy()
{
Allocator::Free(stack_);
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
}
// Prohibit copy constructor & assignment operator.
Stack(const Stack&);
Stack& operator=(const Stack&);
Stack(const Stack &);
Stack & operator=(const Stack &);
Allocator* allocator_;
Allocator* ownAllocator_;
char *stack_;
char *stackTop_;
char *stackEnd_;
char* stack_;
char* stackTop_;
char* stackEnd_;
size_t initialCapacity_;
};
};
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -18,36 +18,45 @@
#include "../stream.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
//! Custom strlen() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
//! Custom strlen() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
\param s Null-terminated input string.
\return Number of characters in the string.
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
*/
template <typename Ch>
inline SizeType StrLen(const Ch* s) {
*/
template <typename Ch>
inline SizeType StrLen(const Ch* s)
{
const Ch* p = s;
while (*p) ++p;
while(*p)
{
++p;
}
return SizeType(p - s);
}
}
//! Returns number of code points in a encoded string.
template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
//! Returns number of code points in a encoded string.
template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount)
{
GenericStringStream<Encoding> is(s);
const typename Encoding::Ch* end = s + length;
SizeType count = 0;
while (is.src_ < end) {
while(is.src_ < end)
{
unsigned codepoint;
if (!Encoding::Decode(is, &codepoint))
if(!Encoding::Decode(is, &codepoint))
{
return false;
}
count++;
}
*outCount = count;
return true;
}
}
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -21,37 +21,57 @@
#include "pow10.h"
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
inline double FastPath(double significand, int exp) {
if (exp < -308)
inline double FastPath(double significand, int exp)
{
if(exp < -308)
{
return 0.0;
else if (exp >= 0)
}
else if(exp >= 0)
{
return significand * internal::Pow10(exp);
}
else
{
return significand / internal::Pow10(-exp);
}
}
}
inline double StrtodNormalPrecision(double d, int p) {
if (p < -308) {
inline double StrtodNormalPrecision(double d, int p)
{
if(p < -308)
{
// Prevent expSum < -308, making Pow10(p) = 0
d = FastPath(d, -308);
d = FastPath(d, p + 308);
}
else
{
d = FastPath(d, p);
}
return d;
}
}
template <typename T>
inline T Min3(T a, T b, T c) {
template <typename T>
inline T Min3(T a, T b, T c)
{
T m = a;
if (m > b) m = b;
if (m > c) m = c;
if(m > b)
{
m = b;
}
if(m > c)
{
m = c;
}
return m;
}
}
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
inline int CheckWithinHalfULP(double b, const BigInteger & d, int dExp)
{
const Double db(b);
const uint64_t bInt = db.IntegerSignificand();
const int bExp = db.IntegerExponent();
@ -60,11 +80,13 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
// Adjust for decimal exponent
if (dExp >= 0) {
if(dExp >= 0)
{
dS_Exp2 += dExp;
dS_Exp5 += dExp;
}
else {
else
{
bS_Exp2 -= dExp;
bS_Exp5 -= dExp;
hS_Exp2 -= dExp;
@ -72,17 +94,23 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
}
// Adjust for binary exponent
if (bExp >= 0)
if(bExp >= 0)
{
bS_Exp2 += bExp;
else {
}
else
{
dS_Exp2 -= bExp;
hS_Exp2 -= bExp;
}
// Adjust for half ulp exponent
if (hExp >= 0)
if(hExp >= 0)
{
hS_Exp2 += hExp;
else {
}
else
{
dS_Exp2 -= hExp;
bS_Exp2 -= hExp;
}
@ -106,38 +134,49 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
dS.Difference(bS, &delta);
return delta.Compare(hS);
}
}
inline bool StrtodFast(double d, int p, double* result) {
inline bool StrtodFast(double d, int p, double* result)
{
// Use fast path for string-to-double conversion if possible
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
if (p > 22 && p < 22 + 16) {
if(p > 22 && p < 22 + 16)
{
// Fast Path Cases In Disguise
d *= internal::Pow10(p - 22);
p = 22;
}
if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
if(p >= -22 && p <= 22 && d <= 9007199254740991.0) // 2^53 - 1
{
*result = FastPath(d, p);
return true;
}
else
{
return false;
}
}
}
// Compute an approximation and see if it is within 1/2 ULP
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
// Compute an approximation and see if it is within 1/2 ULP
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result)
{
uint64_t significand = 0;
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
for (; i < length; i++) {
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
for(; i < length; i++)
{
if(significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
{
break;
}
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
}
if (i < length && decimals[i] >= '5') // Rounding
if(i < length && decimals[i] >= '5') // Rounding
{
significand++;
}
size_t remaining = length - i;
const unsigned kUlpShift = 3;
@ -152,8 +191,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
int actualExp;
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
if (actualExp != dExp) {
static const DiyFp kPow10[] = {
if(actualExp != dExp)
{
static const DiyFp kPow10[] =
{
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
@ -165,9 +206,11 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
int adjustment = dExp - actualExp - 1;
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
v = v * kPow10[adjustment];
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
if(length + static_cast<unsigned>(adjustment) > 19u) // has more digits than decimal digits in 64-bit
{
error += kUlp / 2;
}
}
v = v * cachedPower;
@ -179,7 +222,8 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
unsigned precisionSize = 64 - effectiveSignificandSize;
if (precisionSize + kUlpShift >= 64) {
if(precisionSize + kUlpShift >= 64)
{
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp;
v.e += scaleExp;
@ -190,9 +234,11 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
if(precisionBits >= halfWay + static_cast<unsigned>(error))
{
rounded.f++;
if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
if(rounded.f & (DiyFp::kDpHiddenBit << 1)) // rounding overflows mantissa (issue #340)
{
rounded.f >>= 1;
rounded.e++;
}
@ -200,44 +246,62 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
*result = rounded.ToDouble();
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
}
return halfWay - static_cast<unsigned>(error) >= precisionBits ||
precisionBits >= halfWay + static_cast<unsigned>(error);
}
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition,
int exp)
{
const BigInteger dInt(decimals, length);
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
Double a(approx);
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
if (cmp < 0)
if(cmp < 0)
{
return a.Value(); // within half ULP
else if (cmp == 0) {
}
else if(cmp == 0)
{
// Round towards even
if (a.Significand() & 1)
if(a.Significand() & 1)
{
return a.NextPositiveDouble();
}
else
{
return a.Value();
}
}
else // adjustment
{
return a.NextPositiveDouble();
}
}
}
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition,
int exp)
{
RAPIDJSON_ASSERT(d >= 0.0);
RAPIDJSON_ASSERT(length >= 1);
double result;
if (StrtodFast(d, p, &result))
if(StrtodFast(d, p, &result))
{
return result;
}
// Trim leading zeros
while (*decimals == '0' && length > 1) {
while(*decimals == '0' && length > 1)
{
length--;
decimals++;
decimalPosition--;
}
// Trim trailing zeros
while (decimals[length - 1] == '0' && length > 1) {
while(decimals[length - 1] == '0' && length > 1)
{
length--;
decimalPosition--;
exp++;
@ -245,7 +309,8 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
// Trim right-most digits
const int kMaxDecimalDigit = 780;
if (static_cast<int>(length) > kMaxDecimalDigit) {
if(static_cast<int>(length) > kMaxDecimalDigit)
{
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
exp += delta;
decimalPosition -= static_cast<unsigned>(delta);
@ -253,15 +318,19 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
}
// If too small, underflow to zero
if (int(length) + exp < -324)
if(int(length) + exp < -324)
{
return 0.0;
}
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
if(StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
{
return result;
}
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
}
}
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -19,22 +19,24 @@
#if defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++98-compat)
RAPIDJSON_DIAG_OFF(c++98 - compat)
#endif
RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
namespace internal
{
//! Custom swap() to avoid dependency on C++ <algorithm> header
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
//! Custom swap() to avoid dependency on C++ <algorithm> header
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
\note This has the same semantics as std::swap().
*/
template <typename T>
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
*/
template <typename T>
inline void Swap(T & a, T & b) RAPIDJSON_NOEXCEPT
{
T tmp = a;
a = b;
b = tmp;
}
}
} // namespace internal
RAPIDJSON_NAMESPACE_END

View file

@ -47,58 +47,86 @@ RAPIDJSON_NAMESPACE_BEGIN
*/
template <typename StreamType>
class BasicIStreamWrapper {
class BasicIStreamWrapper
{
public:
typedef typename StreamType::char_type Ch;
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
BasicIStreamWrapper(StreamType & stream) : stream_(stream), count_(), peekBuffer_() {}
Ch Peek() const {
Ch Peek() const
{
typename StreamType::int_type c = stream_.peek();
return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
}
Ch Take() {
Ch Take()
{
typename StreamType::int_type c = stream_.get();
if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
if(RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()))
{
count_++;
return static_cast<Ch>(c);
}
else
{
return '\0';
}
}
// tellg() may return -1 when failed. So we count by ourself.
size_t Tell() const { return count_; }
size_t Tell() const
{
return count_;
}
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
void Put(Ch)
{
RAPIDJSON_ASSERT(false);
}
void Flush()
{
RAPIDJSON_ASSERT(false);
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
// For encoding detection only.
const Ch* Peek4() const {
const Ch* Peek4() const
{
RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
int i;
bool hasError = false;
for (i = 0; i < 4; ++i) {
for(i = 0; i < 4; ++i)
{
typename StreamType::int_type c = stream_.get();
if (c == StreamType::traits_type::eof()) {
if(c == StreamType::traits_type::eof())
{
hasError = true;
stream_.clear();
break;
}
peekBuffer_[i] = static_cast<Ch>(c);
}
for (--i; i >= 0; --i)
for(--i; i >= 0; --i)
{
stream_.putback(peekBuffer_[i]);
}
return !hasError ? peekBuffer_ : 0;
}
private:
BasicIStreamWrapper(const BasicIStreamWrapper&);
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
BasicIStreamWrapper(const BasicIStreamWrapper &);
BasicIStreamWrapper & operator=(const BasicIStreamWrapper &);
StreamType& stream_;
StreamType & stream_;
size_t count_; //!< Number of characters read. Note:
mutable Ch peekBuffer_[4];
};

View file

@ -34,24 +34,45 @@ RAPIDJSON_NAMESPACE_BEGIN
\note implements Stream concept
*/
template <typename Allocator = CrtAllocator>
struct GenericMemoryBuffer {
struct GenericMemoryBuffer
{
typedef char Ch; // byte
GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator,
capacity) {}
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
void Put(Ch c)
{
*stack_.template Push<Ch>() = c;
}
void Flush() {}
void Clear() { stack_.Clear(); }
void ShrinkToFit() { stack_.ShrinkToFit(); }
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
void Pop(size_t count) { stack_.template Pop<Ch>(count); }
void Clear()
{
stack_.Clear();
}
void ShrinkToFit()
{
stack_.ShrinkToFit();
}
Ch* Push(size_t count)
{
return stack_.template Push<Ch>(count);
}
void Pop(size_t count)
{
stack_.template Pop<Ch>(count);
}
const Ch* GetBuffer() const {
const Ch* GetBuffer() const
{
return stack_.template Bottom<Ch>();
}
size_t GetSize() const { return stack_.GetSize(); }
size_t GetSize() const
{
return stack_.GetSize();
}
static const size_t kDefaultCapacity = 256;
mutable internal::Stack<Allocator> stack_;
@ -61,7 +82,8 @@ typedef GenericMemoryBuffer<> MemoryBuffer;
//! Implement specialized version of PutN() with memset() for better performance.
template<>
inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
inline void PutN(MemoryBuffer & memoryBuffer, char c, size_t n)
{
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
}

View file

@ -19,8 +19,8 @@
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(missing-noreturn)
RAPIDJSON_DIAG_OFF(unreachable - code)
RAPIDJSON_DIAG_OFF(missing - noreturn)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -37,22 +37,47 @@ RAPIDJSON_NAMESPACE_BEGIN
3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
\note implements Stream concept
*/
struct MemoryStream {
struct MemoryStream
{
typedef char Ch; // byte
MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
MemoryStream(const Ch* src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
Ch Peek() const
{
return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_;
}
Ch Take()
{
return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++;
}
size_t Tell() const
{
return static_cast<size_t>(src_ - begin_);
}
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
void Put(Ch)
{
RAPIDJSON_ASSERT(false);
}
void Flush()
{
RAPIDJSON_ASSERT(false);
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
// For encoding detection only.
const Ch* Peek4() const {
const Ch* Peek4() const
{
return Tell() + 4 <= size_ ? src_ : 0;
}

View file

@ -42,31 +42,54 @@ RAPIDJSON_NAMESPACE_BEGIN
*/
template <typename StreamType>
class BasicOStreamWrapper {
class BasicOStreamWrapper
{
public:
typedef typename StreamType::char_type Ch;
BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
BasicOStreamWrapper(StreamType & stream) : stream_(stream) {}
void Put(Ch c) {
void Put(Ch c)
{
stream_.put(c);
}
void Flush() {
void Flush()
{
stream_.flush();
}
// Not implemented
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
char Take() { RAPIDJSON_ASSERT(false); return 0; }
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
char Peek() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
char Take()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const
{
RAPIDJSON_ASSERT(false);
return 0;
}
char* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(char*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
private:
BasicOStreamWrapper(const BasicOStreamWrapper&);
BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
BasicOStreamWrapper(const BasicOStreamWrapper &);
BasicOStreamWrapper & operator=(const BasicOStreamWrapper &);
StreamType& stream_;
StreamType & stream_;
};
typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,8 @@ RAPIDJSON_NAMESPACE_BEGIN
//! Combination of PrettyWriter format flags.
/*! \see PrettyWriter::SetFormatOptions
*/
enum PrettyFormatOptions {
enum PrettyFormatOptions
{
kFormatDefault = 0, //!< Default pretty formatting.
kFormatSingleLineArray = 1 //!< Format arrays on a single line.
};
@ -40,7 +41,8 @@ enum PrettyFormatOptions {
\tparam StackAllocator Type of allocator for allocating memory of stack.
*/
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags>
{
public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef typename Base::Ch Ch;
@ -50,7 +52,8 @@ public:
\param allocator User supplied allocator. If it is null, it will create a private one.
\param levelDepth Initial capacity of stack.
*/
explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
explicit PrettyWriter(OutputStream & os, StackAllocator* allocator = 0,
size_t levelDepth = Base::kDefaultLevelDepth) :
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
@ -62,7 +65,8 @@ public:
\param indentCharCount Number of indent characters for each indentation level.
\note The default indentation is 4 spaces.
*/
PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
PrettyWriter & SetIndent(Ch indentChar, unsigned indentCharCount)
{
RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
indentChar_ = indentChar;
indentCharCount_ = indentCharCount;
@ -72,7 +76,8 @@ public:
//! Set pretty writer formatting options.
/*! \param options Formatting options.
*/
PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
PrettyWriter & SetFormatOptions(PrettyFormatOptions options)
{
formatOptions_ = options;
return *this;
}
@ -82,85 +87,130 @@ public:
*/
//@{
bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
bool Null()
{
PrettyPrefix(kNullType);
return Base::WriteNull();
}
bool Bool(bool b)
{
PrettyPrefix(b ? kTrueType : kFalseType);
return Base::WriteBool(b);
}
bool Int(int i)
{
PrettyPrefix(kNumberType);
return Base::WriteInt(i);
}
bool Uint(unsigned u)
{
PrettyPrefix(kNumberType);
return Base::WriteUint(u);
}
bool Int64(int64_t i64)
{
PrettyPrefix(kNumberType);
return Base::WriteInt64(i64);
}
bool Uint64(uint64_t u64)
{
PrettyPrefix(kNumberType);
return Base::WriteUint64(u64);
}
bool Double(double d)
{
PrettyPrefix(kNumberType);
return Base::WriteDouble(d);
}
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
bool RawNumber(const Ch* str, SizeType length, bool copy = false)
{
(void)copy;
PrettyPrefix(kNumberType);
return Base::WriteString(str, length);
}
bool String(const Ch* str, SizeType length, bool copy = false) {
bool String(const Ch* str, SizeType length, bool copy = false)
{
(void)copy;
PrettyPrefix(kStringType);
return Base::WriteString(str, length);
}
#if RAPIDJSON_HAS_STDSTRING
bool String(const std::basic_string<Ch>& str) {
bool String(const std::basic_string<Ch> & str)
{
return String(str.data(), SizeType(str.size()));
}
#endif
bool StartObject() {
bool StartObject()
{
PrettyPrefix(kObjectType);
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
new(Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
return Base::WriteStartObject();
}
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
bool Key(const Ch* str, SizeType length, bool copy = false)
{
return String(str, length, copy);
}
#if RAPIDJSON_HAS_STDSTRING
bool Key(const std::basic_string<Ch>& str) {
bool Key(const std::basic_string<Ch> & str)
{
return Key(str.data(), SizeType(str.size()));
}
#endif
bool EndObject(SizeType memberCount = 0) {
bool EndObject(SizeType memberCount = 0)
{
(void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
if (!empty) {
if(!empty)
{
Base::os_->Put('\n');
WriteIndent();
}
bool ret = Base::WriteEndObject();
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
if(Base::level_stack_.Empty()) // end of json text
{
Base::os_->Flush();
}
return true;
}
bool StartArray() {
bool StartArray()
{
PrettyPrefix(kArrayType);
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
new(Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
return Base::WriteStartArray();
}
bool EndArray(SizeType memberCount = 0) {
bool EndArray(SizeType memberCount = 0)
{
(void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
if(!empty && !(formatOptions_ & kFormatSingleLineArray))
{
Base::os_->Put('\n');
WriteIndent();
}
bool ret = Base::WriteEndArray();
(void)ret;
RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text
if(Base::level_stack_.Empty()) // end of json text
{
Base::os_->Flush();
}
return true;
}
@ -170,8 +220,14 @@ public:
//@{
//! Simpler but slower overload.
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
bool String(const Ch* str)
{
return String(str, internal::StrLen(str));
}
bool Key(const Ch* str)
{
return Key(str, internal::StrLen(str));
}
//@}
@ -184,54 +240,77 @@ public:
\param type Type of the root of json.
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
*/
bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
protected:
void PrettyPrefix(Type type) {
(void)type;
if (Base::level_stack_.GetSize() != 0) { // this value is not at root
typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
if (level->inArray) {
if (level->valueCount > 0) {
Base::os_->Put(','); // add comma if it is not the first element in array
if (formatOptions_ & kFormatSingleLineArray)
Base::os_->Put(' ');
bool RawValue(const Ch* json, size_t length, Type type)
{
PrettyPrefix(type);
return Base::WriteRawValue(json, length);
}
if (!(formatOptions_ & kFormatSingleLineArray)) {
protected:
void PrettyPrefix(Type type)
{
(void)type;
if(Base::level_stack_.GetSize() != 0) // this value is not at root
{
typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
if(level->inArray)
{
if(level->valueCount > 0)
{
Base::os_->Put(','); // add comma if it is not the first element in array
if(formatOptions_ & kFormatSingleLineArray)
{
Base::os_->Put(' ');
}
}
if(!(formatOptions_ & kFormatSingleLineArray))
{
Base::os_->Put('\n');
WriteIndent();
}
}
else { // in object
if (level->valueCount > 0) {
if (level->valueCount % 2 == 0) {
else // in object
{
if(level->valueCount > 0)
{
if(level->valueCount % 2 == 0)
{
Base::os_->Put(',');
Base::os_->Put('\n');
}
else {
else
{
Base::os_->Put(':');
Base::os_->Put(' ');
}
}
else
{
Base::os_->Put('\n');
}
if (level->valueCount % 2 == 0)
if(level->valueCount % 2 == 0)
{
WriteIndent();
}
if (!level->inArray && level->valueCount % 2 == 0)
}
if(!level->inArray && level->valueCount % 2 == 0)
{
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
}
level->valueCount++;
}
else {
else
{
RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
Base::hasRoot_ = true;
}
}
void WriteIndent() {
void WriteIndent()
{
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
}
@ -242,8 +321,8 @@ protected:
private:
// Prohibit copy constructor & assignment operator.
PrettyWriter(const PrettyWriter&);
PrettyWriter& operator=(const PrettyWriter&);
PrettyWriter(const PrettyWriter &);
PrettyWriter & operator=(const PrettyWriter &);
};
RAPIDJSON_NAMESPACE_END

View file

@ -411,7 +411,10 @@ RAPIDJSON_NAMESPACE_END
#endif
RAPIDJSON_NAMESPACE_BEGIN
template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
template <> struct STATIC_ASSERTION_FAILURE<true>
{
enum { value = 1 };
};
template<int x> struct StaticAssertTest {};
RAPIDJSON_NAMESPACE_END
@ -475,7 +478,7 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
#define RAPIDJSON_MULTILINEMACRO_END \
} while((void)0, 0)
} while((void)0, 0)
// adopted from Boost
#define RAPIDJSON_VERSION_CODE(x,y,z) \
@ -599,7 +602,8 @@ RAPIDJSON_NAMESPACE_END
RAPIDJSON_NAMESPACE_BEGIN
//! Type of JSON value
enum Type {
enum Type
{
kNullType = 0, //!< null
kFalseType = 1, //!< false
kTrueType = 2, //!< true

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -70,7 +70,8 @@ concept Stream {
See TEST(Reader, CustomStringStream) in readertest.cpp for example.
*/
template<typename Stream>
struct StreamTraits {
struct StreamTraits
{
//! Whether to make local copy of stream for optimization during parsing.
/*!
By default, for safety, streams do not use local copy optimization.
@ -81,23 +82,28 @@ struct StreamTraits {
//! Reserve n characters for writing to a stream.
template<typename Stream>
inline void PutReserve(Stream& stream, size_t count) {
inline void PutReserve(Stream & stream, size_t count)
{
(void)stream;
(void)count;
}
//! Write character to a stream, presuming buffer is reserved.
template<typename Stream>
inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
inline void PutUnsafe(Stream & stream, typename Stream::Ch c)
{
stream.Put(c);
}
//! Put N copies of a character to a stream.
template<typename Stream, typename Ch>
inline void PutN(Stream& stream, Ch c, size_t n) {
inline void PutN(Stream & stream, Ch c, size_t n)
{
PutReserve(stream, n);
for (size_t i = 0; i < n; i++)
for(size_t i = 0; i < n; i++)
{
PutUnsafe(stream, c);
}
}
///////////////////////////////////////////////////////////////////////////////
@ -107,31 +113,56 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
/*! \note implements Stream concept
*/
template <typename Encoding>
struct GenericStringStream {
struct GenericStringStream
{
typedef typename Encoding::Ch Ch;
GenericStringStream(const Ch *src) : src_(src), head_(src) {}
GenericStringStream(const Ch* src) : src_(src), head_(src) {}
Ch Peek() const { return *src_; }
Ch Take() { return *src_++; }
size_t Tell() const { return static_cast<size_t>(src_ - head_); }
Ch Peek() const
{
return *src_;
}
Ch Take()
{
return *src_++;
}
size_t Tell() const
{
return static_cast<size_t>(src_ - head_);
}
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
Ch* PutBegin()
{
RAPIDJSON_ASSERT(false);
return 0;
}
void Put(Ch)
{
RAPIDJSON_ASSERT(false);
}
void Flush()
{
RAPIDJSON_ASSERT(false);
}
size_t PutEnd(Ch*)
{
RAPIDJSON_ASSERT(false);
return 0;
}
const Ch* src_; //!< Current read position.
const Ch* head_; //!< Original head of the string.
};
template <typename Encoding>
struct StreamTraits<GenericStringStream<Encoding> > {
struct StreamTraits<GenericStringStream<Encoding>>
{
enum { copyOptimization = 1 };
};
//! String stream with UTF8 encoding.
typedef GenericStringStream<UTF8<> > StringStream;
typedef GenericStringStream<UTF8<>> StringStream;
///////////////////////////////////////////////////////////////////////////////
// InsituStringStream
@ -141,25 +172,53 @@ typedef GenericStringStream<UTF8<> > StringStream;
\note implements Stream concept
*/
template <typename Encoding>
struct GenericInsituStringStream {
struct GenericInsituStringStream
{
typedef typename Encoding::Ch Ch;
GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {}
// Read
Ch Peek() { return *src_; }
Ch Take() { return *src_++; }
size_t Tell() { return static_cast<size_t>(src_ - head_); }
Ch Peek()
{
return *src_;
}
Ch Take()
{
return *src_++;
}
size_t Tell()
{
return static_cast<size_t>(src_ - head_);
}
// Write
void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
void Put(Ch c)
{
RAPIDJSON_ASSERT(dst_ != 0);
*dst_++ = c;
}
Ch* PutBegin() { return dst_ = src_; }
size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
Ch* PutBegin()
{
return dst_ = src_;
}
size_t PutEnd(Ch* begin)
{
return static_cast<size_t>(dst_ - begin);
}
void Flush() {}
Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
void Pop(size_t count) { dst_ -= count; }
Ch* Push(size_t count)
{
Ch* begin = dst_;
dst_ += count;
return begin;
}
void Pop(size_t count)
{
dst_ -= count;
}
Ch* src_;
Ch* dst_;
@ -167,12 +226,13 @@ struct GenericInsituStringStream {
};
template <typename Encoding>
struct StreamTraits<GenericInsituStringStream<Encoding> > {
struct StreamTraits<GenericInsituStringStream<Encoding>>
{
enum { copyOptimization = 1 };
};
//! Insitu string stream with UTF8 encoding.
typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
typedef GenericInsituStringStream<UTF8<>> InsituStringStream;
RAPIDJSON_NAMESPACE_END

View file

@ -26,7 +26,7 @@
#if defined(__clang__)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++98-compat)
RAPIDJSON_DIAG_OFF(c++98 - compat)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -38,39 +38,67 @@ RAPIDJSON_NAMESPACE_BEGIN
\note implements Stream concept
*/
template <typename Encoding, typename Allocator = CrtAllocator>
class GenericStringBuffer {
class GenericStringBuffer
{
public:
typedef typename Encoding::Ch Ch;
GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator,
capacity) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
if (&rhs != this)
GenericStringBuffer(GenericStringBuffer && rhs) : stack_(std::move(rhs.stack_)) {}
GenericStringBuffer & operator=(GenericStringBuffer && rhs)
{
if(&rhs != this)
{
stack_ = std::move(rhs.stack_);
}
return *this;
}
#endif
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
void Put(Ch c)
{
*stack_.template Push<Ch>() = c;
}
void PutUnsafe(Ch c)
{
*stack_.template PushUnsafe<Ch>() = c;
}
void Flush() {}
void Clear() { stack_.Clear(); }
void ShrinkToFit() {
void Clear()
{
stack_.Clear();
}
void ShrinkToFit()
{
// Push and pop a null terminator. This is safe.
*stack_.template Push<Ch>() = '\0';
stack_.ShrinkToFit();
stack_.template Pop<Ch>(1);
}
void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
void Pop(size_t count) { stack_.template Pop<Ch>(count); }
void Reserve(size_t count)
{
stack_.template Reserve<Ch>(count);
}
Ch* Push(size_t count)
{
return stack_.template Push<Ch>(count);
}
Ch* PushUnsafe(size_t count)
{
return stack_.template PushUnsafe<Ch>(count);
}
void Pop(size_t count)
{
stack_.template Pop<Ch>(count);
}
const Ch* GetString() const {
const Ch* GetString() const
{
// Push and pop a null terminator. This is safe.
*stack_.template Push<Ch>() = '\0';
stack_.template Pop<Ch>(1);
@ -78,33 +106,39 @@ public:
return stack_.template Bottom<Ch>();
}
size_t GetSize() const { return stack_.GetSize(); }
size_t GetSize() const
{
return stack_.GetSize();
}
static const size_t kDefaultCapacity = 256;
mutable internal::Stack<Allocator> stack_;
private:
// Prohibit copy constructor & assignment operator.
GenericStringBuffer(const GenericStringBuffer&);
GenericStringBuffer& operator=(const GenericStringBuffer&);
GenericStringBuffer(const GenericStringBuffer &);
GenericStringBuffer & operator=(const GenericStringBuffer &);
};
//! String buffer with UTF8 encoding
typedef GenericStringBuffer<UTF8<> > StringBuffer;
typedef GenericStringBuffer<UTF8<>> StringBuffer;
template<typename Encoding, typename Allocator>
inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
inline void PutReserve(GenericStringBuffer<Encoding, Allocator> & stream, size_t count)
{
stream.Reserve(count);
}
template<typename Encoding, typename Allocator>
inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator> & stream, typename Encoding::Ch c)
{
stream.PutUnsafe(c);
}
//! Implement specialized version of PutN() with memset() for better performance.
template<>
inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
inline void PutN(GenericStringBuffer<UTF8<>> & stream, char c, size_t n)
{
std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
}

View file

@ -41,7 +41,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#ifdef __clang__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(unreachable - code)
#endif
RAPIDJSON_NAMESPACE_BEGIN
@ -60,7 +60,8 @@ RAPIDJSON_NAMESPACE_BEGIN
#endif
//! Combination of writeFlags
enum WriteFlag {
enum WriteFlag
{
kWriteNoFlags = 0, //!< No flags are set.
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
@ -84,7 +85,8 @@ enum WriteFlag {
\note implements Handler concept
*/
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class Writer {
class Writer
{
public:
typedef typename SourceEncoding::Ch Ch;
@ -96,12 +98,14 @@ public:
\param levelDepth Initial capacity of stack.
*/
explicit
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
Writer(OutputStream & os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(&os), level_stack_(stackAllocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces),
hasRoot_(false) {}
explicit
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
os_(0), level_stack_(allocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces),
hasRoot_(false) {}
//! Reset the writer with a new stream.
/*!
@ -121,7 +125,8 @@ public:
writer.EndObject();
\endcode
*/
void Reset(OutputStream& os) {
void Reset(OutputStream & os)
{
os_ = &os;
hasRoot_ = false;
level_stack_.Clear();
@ -131,11 +136,13 @@ public:
/*!
A complete JSON has a complete root object or array.
*/
bool IsComplete() const {
bool IsComplete() const
{
return hasRoot_ && level_stack_.Empty();
}
int GetMaxDecimalPlaces() const {
int GetMaxDecimalPlaces() const
{
return maxDecimalPlaces_;
}
@ -160,7 +167,8 @@ public:
writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
\endcode
*/
void SetMaxDecimalPlaces(int maxDecimalPlaces) {
void SetMaxDecimalPlaces(int maxDecimalPlaces)
{
maxDecimalPlaces_ = maxDecimalPlaces;
}
@ -169,47 +177,83 @@ public:
*/
//@{
bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
bool Null()
{
Prefix(kNullType);
return EndValue(WriteNull());
}
bool Bool(bool b)
{
Prefix(b ? kTrueType : kFalseType);
return EndValue(WriteBool(b));
}
bool Int(int i)
{
Prefix(kNumberType);
return EndValue(WriteInt(i));
}
bool Uint(unsigned u)
{
Prefix(kNumberType);
return EndValue(WriteUint(u));
}
bool Int64(int64_t i64)
{
Prefix(kNumberType);
return EndValue(WriteInt64(i64));
}
bool Uint64(uint64_t u64)
{
Prefix(kNumberType);
return EndValue(WriteUint64(u64));
}
//! Writes the given \c double value to the stream
/*!
\param d The value to be written.
\return Whether it is succeed.
*/
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
bool Double(double d)
{
Prefix(kNumberType);
return EndValue(WriteDouble(d));
}
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
bool RawNumber(const Ch* str, SizeType length, bool copy = false)
{
(void)copy;
Prefix(kNumberType);
return EndValue(WriteString(str, length));
}
bool String(const Ch* str, SizeType length, bool copy = false) {
bool String(const Ch* str, SizeType length, bool copy = false)
{
(void)copy;
Prefix(kStringType);
return EndValue(WriteString(str, length));
}
#if RAPIDJSON_HAS_STDSTRING
bool String(const std::basic_string<Ch>& str) {
bool String(const std::basic_string<Ch> & str)
{
return String(str.data(), SizeType(str.size()));
}
#endif
bool StartObject() {
bool StartObject()
{
Prefix(kObjectType);
new (level_stack_.template Push<Level>()) Level(false);
new(level_stack_.template Push<Level>()) Level(false);
return WriteStartObject();
}
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
bool Key(const Ch* str, SizeType length, bool copy = false)
{
return String(str, length, copy);
}
bool EndObject(SizeType memberCount = 0) {
bool EndObject(SizeType memberCount = 0)
{
(void)memberCount;
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
@ -217,13 +261,15 @@ public:
return EndValue(WriteEndObject());
}
bool StartArray() {
bool StartArray()
{
Prefix(kArrayType);
new (level_stack_.template Push<Level>()) Level(true);
new(level_stack_.template Push<Level>()) Level(true);
return WriteStartArray();
}
bool EndArray(SizeType elementCount = 0) {
bool EndArray(SizeType elementCount = 0)
{
(void)elementCount;
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
@ -236,8 +282,14 @@ public:
//@{
//! Simpler but slower overload.
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
bool String(const Ch* str)
{
return String(str, internal::StrLen(str));
}
bool Key(const Ch* str)
{
return Key(str, internal::StrLen(str));
}
//@}
@ -249,11 +301,16 @@ public:
\param length Length of the json.
\param type Type of the root of json.
*/
bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
bool RawValue(const Ch* json, size_t length, Type type)
{
Prefix(type);
return EndValue(WriteRawValue(json, length));
}
protected:
//! Information for each nested level
struct Level {
struct Level
{
Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
size_t valueCount; //!< number of values in this level
bool inArray; //!< true if in array, otherwise in object
@ -261,124 +318,181 @@ protected:
static const size_t kDefaultLevelDepth = 32;
bool WriteNull() {
bool WriteNull()
{
PutReserve(*os_, 4);
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'u');
PutUnsafe(*os_, 'l');
PutUnsafe(*os_, 'l');
return true;
}
bool WriteBool(bool b) {
if (b) {
bool WriteBool(bool b)
{
if(b)
{
PutReserve(*os_, 4);
PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'r');
PutUnsafe(*os_, 'u');
PutUnsafe(*os_, 'e');
}
else {
else
{
PutReserve(*os_, 5);
PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'l');
PutUnsafe(*os_, 's');
PutUnsafe(*os_, 'e');
}
return true;
}
bool WriteInt(int i) {
bool WriteInt(int i)
{
char buffer[11];
const char* end = internal::i32toa(i, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p)
for(const char* p = buffer; p != end; ++p)
{
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
}
return true;
}
bool WriteUint(unsigned u) {
bool WriteUint(unsigned u)
{
char buffer[10];
const char* end = internal::u32toa(u, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p)
for(const char* p = buffer; p != end; ++p)
{
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
}
return true;
}
bool WriteInt64(int64_t i64) {
bool WriteInt64(int64_t i64)
{
char buffer[21];
const char* end = internal::i64toa(i64, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p)
for(const char* p = buffer; p != end; ++p)
{
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
}
return true;
}
bool WriteUint64(uint64_t u64) {
bool WriteUint64(uint64_t u64)
{
char buffer[20];
char* end = internal::u64toa(u64, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p)
for(char* p = buffer; p != end; ++p)
{
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
}
return true;
}
bool WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf()) {
if (!(writeFlags & kWriteNanAndInfFlag))
bool WriteDouble(double d)
{
if(internal::Double(d).IsNanOrInf())
{
if(!(writeFlags & kWriteNanAndInfFlag))
{
return false;
if (internal::Double(d).IsNan()) {
}
if(internal::Double(d).IsNan())
{
PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'N');
return true;
}
if (internal::Double(d).Sign()) {
if(internal::Double(d).Sign())
{
PutReserve(*os_, 9);
PutUnsafe(*os_, '-');
}
else
{
PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
}
PutUnsafe(*os_, 'I');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'y');
return true;
}
char buffer[25];
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p)
for(char* p = buffer; p != end; ++p)
{
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
}
return true;
}
bool WriteString(const Ch* str, SizeType length) {
bool WriteString(const Ch* str, SizeType length)
{
static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static const char escape[256] = {
static const char escape[256] =
{
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
//0 1 2 3 4 5 6 7 8 9 A B C D E F
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
Z16, Z16, // 30~4F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
#undef Z16
};
if (TargetEncoding::supportUnicode)
if(TargetEncoding::supportUnicode)
{
PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
}
else
{
PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
}
PutUnsafe(*os_, '\"');
GenericStringStream<SourceEncoding> is(str);
while (ScanWriteUnescapedString(is, length)) {
while(ScanWriteUnescapedString(is, length))
{
const Ch c = is.Peek();
if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
if(!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80)
{
// Unicode escaping
unsigned codepoint;
if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
if(RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
{
return false;
}
PutUnsafe(*os_, '\\');
PutUnsafe(*os_, 'u');
if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
if(codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF))
{
PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint) & 15]);
}
else {
else
{
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
// Surrogate pair
unsigned s = codepoint - 0x010000;
@ -387,77 +501,114 @@ protected:
PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
PutUnsafe(*os_, hexDigits[(lead ) & 15]);
PutUnsafe(*os_, hexDigits[(lead) & 15]);
PutUnsafe(*os_, '\\');
PutUnsafe(*os_, 'u');
PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
PutUnsafe(*os_, hexDigits[(trail ) & 15]);
PutUnsafe(*os_, hexDigits[(trail) & 15]);
}
}
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
else if((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) &&
RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))
{
is.Take();
PutUnsafe(*os_, '\\');
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
if (escape[static_cast<unsigned char>(c)] == 'u') {
if(escape[static_cast<unsigned char>(c)] == 'u')
{
PutUnsafe(*os_, '0');
PutUnsafe(*os_, '0');
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
}
}
else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
else if(RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
{
return false;
}
}
PutUnsafe(*os_, '\"');
return true;
}
bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding> & is, size_t length)
{
return RAPIDJSON_LIKELY(is.Tell() < length);
}
bool WriteStartObject() { os_->Put('{'); return true; }
bool WriteEndObject() { os_->Put('}'); return true; }
bool WriteStartArray() { os_->Put('['); return true; }
bool WriteEndArray() { os_->Put(']'); return true; }
bool WriteStartObject()
{
os_->Put('{');
return true;
}
bool WriteEndObject()
{
os_->Put('}');
return true;
}
bool WriteStartArray()
{
os_->Put('[');
return true;
}
bool WriteEndArray()
{
os_->Put(']');
return true;
}
bool WriteRawValue(const Ch* json, size_t length) {
bool WriteRawValue(const Ch* json, size_t length)
{
PutReserve(*os_, length);
for (size_t i = 0; i < length; i++) {
for(size_t i = 0; i < length; i++)
{
RAPIDJSON_ASSERT(json[i] != '\0');
PutUnsafe(*os_, json[i]);
}
return true;
}
void Prefix(Type type) {
void Prefix(Type type)
{
(void)type;
if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
if(RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) // this value is not at root
{
Level* level = level_stack_.template Top<Level>();
if (level->valueCount > 0) {
if (level->inArray)
if(level->valueCount > 0)
{
if(level->inArray)
{
os_->Put(','); // add comma if it is not the first element in array
}
else // in object
{
os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
}
if (!level->inArray && level->valueCount % 2 == 0)
}
if(!level->inArray && level->valueCount % 2 == 0)
{
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
}
level->valueCount++;
}
else {
else
{
RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
hasRoot_ = true;
}
}
// Flush the value if it is the top level one.
bool EndValue(bool ret) {
if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
bool EndValue(bool ret)
{
if(RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
{
os_->Flush();
}
return ret;
}
@ -468,67 +619,87 @@ protected:
private:
// Prohibit copy constructor & assignment operator.
Writer(const Writer&);
Writer& operator=(const Writer&);
Writer(const Writer &);
Writer & operator=(const Writer &);
};
// Full specialization for StringStream to prevent memory copying
template<>
inline bool Writer<StringBuffer>::WriteInt(int i) {
char *buffer = os_->Push(11);
inline bool Writer<StringBuffer>::WriteInt(int i)
{
char* buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer);
os_->Pop(static_cast<size_t>(11 - (end - buffer)));
return true;
}
template<>
inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
char *buffer = os_->Push(10);
inline bool Writer<StringBuffer>::WriteUint(unsigned u)
{
char* buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer);
os_->Pop(static_cast<size_t>(10 - (end - buffer)));
return true;
}
template<>
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
char *buffer = os_->Push(21);
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64)
{
char* buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer);
os_->Pop(static_cast<size_t>(21 - (end - buffer)));
return true;
}
template<>
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
char *buffer = os_->Push(20);
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u)
{
char* buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer);
os_->Pop(static_cast<size_t>(20 - (end - buffer)));
return true;
}
template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf()) {
inline bool Writer<StringBuffer>::WriteDouble(double d)
{
if(internal::Double(d).IsNanOrInf())
{
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
if(!(kWriteDefaultFlags & kWriteNanAndInfFlag))
{
return false;
if (internal::Double(d).IsNan()) {
}
if(internal::Double(d).IsNan())
{
PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'N');
return true;
}
if (internal::Double(d).Sign()) {
if(internal::Double(d).Sign())
{
PutReserve(*os_, 9);
PutUnsafe(*os_, '-');
}
else
{
PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
}
PutUnsafe(*os_, 'I');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'y');
return true;
}
char *buffer = os_->Push(25);
char* buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
os_->Pop(static_cast<size_t>(25 - (end - buffer)));
return true;
@ -536,44 +707,58 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
template<>
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
if (length < 16)
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream & is, size_t length)
{
if(length < 16)
{
return RAPIDJSON_LIKELY(is.Tell() < length);
}
if (!RAPIDJSON_LIKELY(is.Tell() < length))
if(!RAPIDJSON_LIKELY(is.Tell() < length))
{
return false;
}
const char* p = is.src_;
const char* end = is.head_ + length;
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
if (nextAligned > end)
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>
(p) + 15) & static_cast<size_t>(~15));
const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>
(~15));
if(nextAligned > end)
{
return true;
}
while (p != nextAligned)
if (*p < 0x20 || *p == '\"' || *p == '\\') {
while(p != nextAligned)
if(*p < 0x20 || *p == '\"' || *p == '\\')
{
is.src_ = p;
return RAPIDJSON_LIKELY(is.Tell() < length);
}
else
{
os_->PutUnsafe(*p++);
}
// The rest of string using SIMD
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
for (; p != endAligned; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
for(; p != endAligned; p += 16)
{
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
if(RAPIDJSON_UNLIKELY(r != 0)) // some of characters is escaped
{
SizeType len;
#ifdef _MSC_VER // Find the index of first escaped
unsigned long offset;
@ -583,13 +768,15 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
len = static_cast<SizeType>(__builtin_ffs(r) - 1);
#endif
char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
for (size_t i = 0; i < len; i++)
for(size_t i = 0; i < len; i++)
{
q[i] = p[i];
}
p += len;
break;
}
_mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
_mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s);
}
is.src_ = p;

View file

@ -40,7 +40,7 @@ class Options;
class App : public IConsoleListener
{
public:
App(int argc, char **argv);
App(int argc, char** argv);
~App();
int exec();
@ -52,14 +52,14 @@ private:
void background();
void close();
static void onSignal(uv_signal_t *handle, int signum);
static void onSignal(uv_signal_t* handle, int signum);
static App *m_self;
static App* m_self;
Console *m_console;
Httpd *m_httpd;
Network *m_network;
Options *m_options;
Console* m_console;
Httpd* m_httpd;
Network* m_network;
Options* m_options;
uv_signal_t m_sigHUP;
uv_signal_t m_sigINT;
uv_signal_t m_sigTERM;

View file

@ -33,18 +33,23 @@
void App::background()
{
if (m_options->affinity() != -1L) {
if(m_options->affinity() != -1L)
{
Cpu::setAffinity(-1, m_options->affinity());
}
if (!m_options->background()) {
if(!m_options->background())
{
return;
}
HWND hcon = GetConsoleWindow();
if (hcon) {
if(hcon)
{
ShowWindow(hcon, SW_HIDE);
} else {
}
else
{
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
CloseHandle(h);
FreeConsole();

View file

@ -26,13 +26,14 @@
#include "interfaces/IConsoleListener.h"
Console::Console(IConsoleListener *listener)
Console::Console(IConsoleListener* listener)
: m_listener(listener)
{
m_tty.data = this;
uv_tty_init(uv_default_loop(), &m_tty, 0, 1);
if (!uv_is_readable(reinterpret_cast<uv_stream_t*>(&m_tty))) {
if(!uv_is_readable(reinterpret_cast<uv_stream_t*>(&m_tty)))
{
return;
}
@ -41,7 +42,7 @@ Console::Console(IConsoleListener *listener)
}
void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
void Console::onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
auto console = static_cast<Console*>(handle->data);
buf->len = 1;
@ -49,13 +50,15 @@ void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t
}
void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
void Console::onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
if (nread < 0) {
if(nread < 0)
{
return uv_close(reinterpret_cast<uv_handle_t*>(stream), nullptr);
}
if (nread == 1) {
if(nread == 1)
{
static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]);
}
}

View file

@ -34,14 +34,14 @@ class IConsoleListener;
class Console
{
public:
Console(IConsoleListener *listener);
Console(IConsoleListener* listener);
private:
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
static void onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
static void onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
char m_buf[1];
IConsoleListener *m_listener;
IConsoleListener* m_listener;
uv_tty_t m_tty;
};

View file

@ -38,22 +38,38 @@ struct cryptonight_ctx;
class Mem
{
public:
enum Flags {
enum Flags
{
HugepagesAvailable = 1,
HugepagesEnabled = 2,
Lock = 4
};
static bool allocate(int algo, int threads, bool doubleHash, bool enabled);
static cryptonight_ctx *create(int threadId);
static void *calloc(size_t num, size_t size);
static cryptonight_ctx* create(int threadId);
static void* calloc(size_t num, size_t size);
static void release();
static inline bool isDoubleHash() { return m_doubleHash; }
static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
static inline bool isHugepagesEnabled() { return (m_flags & HugepagesEnabled) != 0; }
static inline int flags() { return m_flags; }
static inline int threads() { return m_threads; }
static inline bool isDoubleHash()
{
return m_doubleHash;
}
static inline bool isHugepagesAvailable()
{
return (m_flags & HugepagesAvailable) != 0;
}
static inline bool isHugepagesEnabled()
{
return (m_flags & HugepagesEnabled) != 0;
}
static inline int flags()
{
return m_flags;
}
static inline int threads()
{
return m_threads;
}
private:
static bool m_doubleHash;
@ -61,10 +77,10 @@ private:
static int m_flags;
static int m_threads;
static size_t m_offset;
VAR_ALIGN(16, static uint8_t *m_memory);
VAR_ALIGN(16, static uint8_t* m_memory);
# ifndef XMRIG_NO_AEON
static cryptonight_ctx *createLite(int threadId);
static cryptonight_ctx* createLite(int threadId);
# endif
};

View file

@ -41,7 +41,7 @@ void Handle::join()
}
void Handle::start(void (*callback) (void *))
void Handle::start(void (*callback)(void*))
{
uv_thread_create(&m_thread, callback, this);
}

View file

@ -24,7 +24,8 @@
#include "App.h"
int main(int argc, char **argv) {
int main(int argc, char** argv)
{
App app(argc, argv);
return app.exec();