C++ style
Apply c++ code format to all files!
This commit is contained in:
parent
7f31f70876
commit
4276afc4f4
43 changed files with 14589 additions and 10107 deletions
11
src/3rdparty/aligned_malloc.h
vendored
11
src/3rdparty/aligned_malloc.h
vendored
|
@ -39,17 +39,22 @@ extern "C" int posix_memalign(void **__memptr, size_t __alignment, size_t __size
|
||||||
#endif
|
#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);
|
return malloc(__size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(__align & (__align - 1)) && __align < sizeof(void*))
|
if(!(__align & (__align - 1)) && __align < sizeof(void*))
|
||||||
|
{
|
||||||
__align = sizeof(void*);
|
__align = sizeof(void*);
|
||||||
|
}
|
||||||
|
|
||||||
void* __mallocedMemory;
|
void* __mallocedMemory;
|
||||||
if (posix_memalign(&__mallocedMemory, __align, __size)) {
|
if(posix_memalign(&__mallocedMemory, __align, __size))
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
188
src/3rdparty/getopt/getopt.h
vendored
188
src/3rdparty/getopt/getopt.h
vendored
|
@ -141,7 +141,9 @@ _vwarnx(const char *fmt,va_list ap)
|
||||||
{
|
{
|
||||||
(void)fprintf(stderr, "%s: ", __progname);
|
(void)fprintf(stderr, "%s: ", __progname);
|
||||||
if(fmt != NULL)
|
if(fmt != NULL)
|
||||||
|
{
|
||||||
(void)vfprintf(stderr, fmt, ap);
|
(void)vfprintf(stderr, fmt, ap);
|
||||||
|
}
|
||||||
(void)fprintf(stderr, "\n");
|
(void)fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +165,8 @@ gcd(int a, int b)
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
c = a % b;
|
c = a % b;
|
||||||
while (c != 0) {
|
while(c != 0)
|
||||||
|
{
|
||||||
a = b;
|
a = b;
|
||||||
b = c;
|
b = c;
|
||||||
c = a % b;
|
c = a % b;
|
||||||
|
@ -192,14 +195,20 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||||
ncycle = gcd(nnonopts, nopts);
|
ncycle = gcd(nnonopts, nopts);
|
||||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||||
|
|
||||||
for (i = 0; i < ncycle; i++) {
|
for(i = 0; i < ncycle; i++)
|
||||||
|
{
|
||||||
cstart = panonopt_end + i;
|
cstart = panonopt_end + i;
|
||||||
pos = cstart;
|
pos = cstart;
|
||||||
for (j = 0; j < cyclelen; j++) {
|
for(j = 0; j < cyclelen; j++)
|
||||||
|
{
|
||||||
if(pos >= panonopt_end)
|
if(pos >= panonopt_end)
|
||||||
|
{
|
||||||
pos -= nnonopts;
|
pos -= nnonopts;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
pos += nopts;
|
pos += nopts;
|
||||||
|
}
|
||||||
swap = nargv[pos];
|
swap = nargv[pos];
|
||||||
/* LINTED const cast */
|
/* LINTED const cast */
|
||||||
((char**) nargv)[pos] = nargv[cstart];
|
((char**) nargv)[pos] = nargv[cstart];
|
||||||
|
@ -304,20 +313,28 @@ parse_long_options(char * const *nargv, const char *options,
|
||||||
|
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
if((has_equal = strchr(current_argv, '=')) != NULL)
|
||||||
|
{
|
||||||
/* argument found (--option=arg) */
|
/* argument found (--option=arg) */
|
||||||
current_argv_len = has_equal - current_argv;
|
current_argv_len = has_equal - current_argv;
|
||||||
has_equal++;
|
has_equal++;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
current_argv_len = strlen(current_argv);
|
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 */
|
/* find matching long option */
|
||||||
if(strncmp(current_argv, long_options[i].name,
|
if(strncmp(current_argv, long_options[i].name,
|
||||||
current_argv_len))
|
current_argv_len))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (strlen(long_options[i].name) == current_argv_len) {
|
if(strlen(long_options[i].name) == current_argv_len)
|
||||||
|
{
|
||||||
/* exact match */
|
/* exact match */
|
||||||
match = i;
|
match = i;
|
||||||
ambiguous = 0;
|
ambiguous = 0;
|
||||||
|
@ -328,14 +345,21 @@ parse_long_options(char * const *nargv, const char *options,
|
||||||
* a partial match of a single character.
|
* a partial match of a single character.
|
||||||
*/
|
*/
|
||||||
if(short_too && current_argv_len == 1)
|
if(short_too && current_argv_len == 1)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(match == -1) /* partial match */
|
if(match == -1) /* partial match */
|
||||||
|
{
|
||||||
match = i;
|
match = i;
|
||||||
|
}
|
||||||
else if(!IDENTICAL_INTERPRETATION(i, match))
|
else if(!IDENTICAL_INTERPRETATION(i, match))
|
||||||
|
{
|
||||||
ambiguous = 1;
|
ambiguous = 1;
|
||||||
}
|
}
|
||||||
if (ambiguous) {
|
}
|
||||||
|
if(ambiguous)
|
||||||
|
{
|
||||||
/* ambiguous abbreviation */
|
/* ambiguous abbreviation */
|
||||||
if(PRINT_ERROR)
|
if(PRINT_ERROR)
|
||||||
warnx(ambig, (int)current_argv_len,
|
warnx(ambig, (int)current_argv_len,
|
||||||
|
@ -343,9 +367,11 @@ parse_long_options(char * const *nargv, const char *options,
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
return (BADCH);
|
return (BADCH);
|
||||||
}
|
}
|
||||||
if (match != -1) { /* option found */
|
if(match != -1) /* option found */
|
||||||
|
{
|
||||||
if(long_options[match].has_arg == no_argument
|
if(long_options[match].has_arg == no_argument
|
||||||
&& has_equal) {
|
&& has_equal)
|
||||||
|
{
|
||||||
if(PRINT_ERROR)
|
if(PRINT_ERROR)
|
||||||
warnx(noarg, (int)current_argv_len,
|
warnx(noarg, (int)current_argv_len,
|
||||||
current_argv);
|
current_argv);
|
||||||
|
@ -353,17 +379,25 @@ parse_long_options(char * const *nargv, const char *options,
|
||||||
* XXX: GNU sets optopt to val regardless of flag
|
* 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;
|
optopt = long_options[match].val;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
|
}
|
||||||
return (BADARG);
|
return (BADARG);
|
||||||
}
|
}
|
||||||
if(long_options[match].has_arg == required_argument ||
|
if(long_options[match].has_arg == required_argument ||
|
||||||
long_options[match].has_arg == optional_argument) {
|
long_options[match].has_arg == optional_argument)
|
||||||
|
{
|
||||||
if(has_equal)
|
if(has_equal)
|
||||||
|
{
|
||||||
optarg = has_equal;
|
optarg = has_equal;
|
||||||
|
}
|
||||||
else if(long_options[match].has_arg ==
|
else if(long_options[match].has_arg ==
|
||||||
required_argument) {
|
required_argument)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* optional argument doesn't use next nargv
|
* optional argument doesn't use next nargv
|
||||||
*/
|
*/
|
||||||
|
@ -371,7 +405,8 @@ parse_long_options(char * const *nargv, const char *options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if((long_options[match].has_arg == required_argument)
|
if((long_options[match].has_arg == required_argument)
|
||||||
&& (optarg == NULL)) {
|
&& (optarg == NULL))
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Missing argument; leading ':' indicates no error
|
* Missing argument; leading ':' indicates no error
|
||||||
* should be generated.
|
* should be generated.
|
||||||
|
@ -383,29 +418,44 @@ parse_long_options(char * const *nargv, const char *options,
|
||||||
* XXX: GNU sets optopt to val regardless of flag
|
* 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;
|
optopt = long_options[match].val;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
|
}
|
||||||
--optind;
|
--optind;
|
||||||
return (BADARG);
|
return (BADARG);
|
||||||
}
|
}
|
||||||
} else { /* unknown option */
|
}
|
||||||
if (short_too) {
|
else /* unknown option */
|
||||||
|
{
|
||||||
|
if(short_too)
|
||||||
|
{
|
||||||
--optind;
|
--optind;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if(PRINT_ERROR)
|
if(PRINT_ERROR)
|
||||||
|
{
|
||||||
warnx(illoptstring, current_argv);
|
warnx(illoptstring, current_argv);
|
||||||
|
}
|
||||||
optopt = 0;
|
optopt = 0;
|
||||||
return (BADCH);
|
return (BADCH);
|
||||||
}
|
}
|
||||||
if(idx)
|
if(idx)
|
||||||
|
{
|
||||||
*idx = match;
|
*idx = match;
|
||||||
if (long_options[match].flag) {
|
}
|
||||||
|
if(long_options[match].flag)
|
||||||
|
{
|
||||||
*long_options[match].flag = long_options[match].val;
|
*long_options[match].flag = long_options[match].val;
|
||||||
return (0);
|
return (0);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return (long_options[match].val);
|
return (long_options[match].val);
|
||||||
|
}
|
||||||
#undef IDENTICAL_INTERPRETATION
|
#undef IDENTICAL_INTERPRETATION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,14 +472,18 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||||
static int posixly_correct = -1;
|
static int posixly_correct = -1;
|
||||||
|
|
||||||
if(options == NULL)
|
if(options == NULL)
|
||||||
|
{
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||||
* XXX using optreset. Work around this braindamage.
|
* XXX using optreset. Work around this braindamage.
|
||||||
*/
|
*/
|
||||||
if(optind == 0)
|
if(optind == 0)
|
||||||
|
{
|
||||||
optind = optreset = 1;
|
optind = optreset = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||||
|
@ -439,29 +493,43 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||||
* optreset != 0 for GNU compatibility.
|
* optreset != 0 for GNU compatibility.
|
||||||
*/
|
*/
|
||||||
if(posixly_correct == -1 || optreset != 0)
|
if(posixly_correct == -1 || optreset != 0)
|
||||||
|
{
|
||||||
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||||
|
}
|
||||||
if(*options == '-')
|
if(*options == '-')
|
||||||
|
{
|
||||||
flags |= FLAG_ALLARGS;
|
flags |= FLAG_ALLARGS;
|
||||||
|
}
|
||||||
else if(posixly_correct || *options == '+')
|
else if(posixly_correct || *options == '+')
|
||||||
|
{
|
||||||
flags &= ~FLAG_PERMUTE;
|
flags &= ~FLAG_PERMUTE;
|
||||||
|
}
|
||||||
if(*options == '+' || *options == '-')
|
if(*options == '+' || *options == '-')
|
||||||
|
{
|
||||||
options++;
|
options++;
|
||||||
|
}
|
||||||
|
|
||||||
optarg = NULL;
|
optarg = NULL;
|
||||||
if(optreset)
|
if(optreset)
|
||||||
|
{
|
||||||
nonopt_start = nonopt_end = -1;
|
nonopt_start = nonopt_end = -1;
|
||||||
|
}
|
||||||
start:
|
start:
|
||||||
if (optreset || !*place) { /* update scanning pointer */
|
if(optreset || !*place) /* update scanning pointer */
|
||||||
|
{
|
||||||
optreset = 0;
|
optreset = 0;
|
||||||
if (optind >= nargc) { /* end of argument vector */
|
if(optind >= nargc) /* end of argument vector */
|
||||||
|
{
|
||||||
place = EMSG;
|
place = EMSG;
|
||||||
if (nonopt_end != -1) {
|
if(nonopt_end != -1)
|
||||||
|
{
|
||||||
/* do permutation, if we have to */
|
/* do permutation, if we have to */
|
||||||
permute_args(nonopt_start, nonopt_end,
|
permute_args(nonopt_start, nonopt_end,
|
||||||
optind, nargv);
|
optind, nargv);
|
||||||
optind -= nonopt_end - nonopt_start;
|
optind -= nonopt_end - nonopt_start;
|
||||||
}
|
}
|
||||||
else if (nonopt_start != -1) {
|
else if(nonopt_start != -1)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If we skipped non-options, set optind
|
* If we skipped non-options, set optind
|
||||||
* to the first of them.
|
* to the first of them.
|
||||||
|
@ -472,9 +540,11 @@ start:
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if(*(place = nargv[optind]) != '-' ||
|
if(*(place = nargv[optind]) != '-' ||
|
||||||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
(place[1] == '\0' && strchr(options, '-') == NULL))
|
||||||
|
{
|
||||||
place = EMSG; /* found non-option */
|
place = EMSG; /* found non-option */
|
||||||
if (flags & FLAG_ALLARGS) {
|
if(flags & FLAG_ALLARGS)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* GNU extension:
|
* GNU extension:
|
||||||
* return non-option as argument to option 1
|
* return non-option as argument to option 1
|
||||||
|
@ -482,7 +552,8 @@ start:
|
||||||
optarg = nargv[optind++];
|
optarg = nargv[optind++];
|
||||||
return (INORDER);
|
return (INORDER);
|
||||||
}
|
}
|
||||||
if (!(flags & FLAG_PERMUTE)) {
|
if(!(flags & FLAG_PERMUTE))
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* If no permutation wanted, stop parsing
|
* If no permutation wanted, stop parsing
|
||||||
* at first non-option.
|
* at first non-option.
|
||||||
|
@ -491,8 +562,11 @@ start:
|
||||||
}
|
}
|
||||||
/* do permutation */
|
/* do permutation */
|
||||||
if(nonopt_start == -1)
|
if(nonopt_start == -1)
|
||||||
|
{
|
||||||
nonopt_start = optind;
|
nonopt_start = optind;
|
||||||
else if (nonopt_end != -1) {
|
}
|
||||||
|
else if(nonopt_end != -1)
|
||||||
|
{
|
||||||
permute_args(nonopt_start, nonopt_end,
|
permute_args(nonopt_start, nonopt_end,
|
||||||
optind, nargv);
|
optind, nargv);
|
||||||
nonopt_start = optind -
|
nonopt_start = optind -
|
||||||
|
@ -504,19 +578,23 @@ start:
|
||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
if(nonopt_start != -1 && nonopt_end == -1)
|
if(nonopt_start != -1 && nonopt_end == -1)
|
||||||
|
{
|
||||||
nonopt_end = optind;
|
nonopt_end = optind;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have "-" do nothing, if "--" we are done.
|
* 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++;
|
optind++;
|
||||||
place = EMSG;
|
place = EMSG;
|
||||||
/*
|
/*
|
||||||
* We found an option (--), so if we skipped
|
* We found an option (--), so if we skipped
|
||||||
* non-options, we have to permute.
|
* non-options, we have to permute.
|
||||||
*/
|
*/
|
||||||
if (nonopt_end != -1) {
|
if(nonopt_end != -1)
|
||||||
|
{
|
||||||
permute_args(nonopt_start, nonopt_end,
|
permute_args(nonopt_start, nonopt_end,
|
||||||
optind, nargv);
|
optind, nargv);
|
||||||
optind -= nonopt_end - nonopt_start;
|
optind -= nonopt_end - nonopt_start;
|
||||||
|
@ -533,16 +611,22 @@ start:
|
||||||
* 3) either the arg starts with -- we are getopt_long_only()
|
* 3) either the arg starts with -- we are getopt_long_only()
|
||||||
*/
|
*/
|
||||||
if(long_options != NULL && place != nargv[optind] &&
|
if(long_options != NULL && place != nargv[optind] &&
|
||||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
(*place == '-' || (flags & FLAG_LONGONLY)))
|
||||||
|
{
|
||||||
short_too = 0;
|
short_too = 0;
|
||||||
if(*place == '-')
|
if(*place == '-')
|
||||||
|
{
|
||||||
place++; /* --foo long option */
|
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 */
|
short_too = 1; /* could be short option too */
|
||||||
|
}
|
||||||
|
|
||||||
optchar = parse_long_options(nargv, options, long_options,
|
optchar = parse_long_options(nargv, options, long_options,
|
||||||
idx, short_too);
|
idx, short_too);
|
||||||
if (optchar != -1) {
|
if(optchar != -1)
|
||||||
|
{
|
||||||
place = EMSG;
|
place = EMSG;
|
||||||
return (optchar);
|
return (optchar);
|
||||||
}
|
}
|
||||||
|
@ -550,55 +634,83 @@ start:
|
||||||
|
|
||||||
if((optchar = (int) * place++) == (int)':' ||
|
if((optchar = (int) * place++) == (int)':' ||
|
||||||
(optchar == (int)'-' && *place != '\0') ||
|
(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
|
* If the user specified "-" and '-' isn't listed in
|
||||||
* options, return -1 (non-option) as per POSIX.
|
* options, return -1 (non-option) as per POSIX.
|
||||||
* Otherwise, it is an unknown option character (or ':').
|
* Otherwise, it is an unknown option character (or ':').
|
||||||
*/
|
*/
|
||||||
if(optchar == (int)'-' && *place == '\0')
|
if(optchar == (int)'-' && *place == '\0')
|
||||||
|
{
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
if(!*place)
|
if(!*place)
|
||||||
|
{
|
||||||
++optind;
|
++optind;
|
||||||
|
}
|
||||||
if(PRINT_ERROR)
|
if(PRINT_ERROR)
|
||||||
|
{
|
||||||
warnx(illoptchar, optchar);
|
warnx(illoptchar, optchar);
|
||||||
|
}
|
||||||
optopt = optchar;
|
optopt = optchar;
|
||||||
return (BADCH);
|
return (BADCH);
|
||||||
}
|
}
|
||||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
if(long_options != NULL && optchar == 'W' && oli[1] == ';')
|
||||||
|
{
|
||||||
/* -W long-option */
|
/* -W long-option */
|
||||||
if(*place) /* no space */
|
if(*place) /* no space */
|
||||||
/* NOTHING */;
|
/* NOTHING */;
|
||||||
else if (++optind >= nargc) { /* no arg */
|
else if(++optind >= nargc) /* no arg */
|
||||||
|
{
|
||||||
place = EMSG;
|
place = EMSG;
|
||||||
if(PRINT_ERROR)
|
if(PRINT_ERROR)
|
||||||
|
{
|
||||||
warnx(recargchar, optchar);
|
warnx(recargchar, optchar);
|
||||||
|
}
|
||||||
optopt = optchar;
|
optopt = optchar;
|
||||||
return (BADARG);
|
return (BADARG);
|
||||||
} else /* white space */
|
}
|
||||||
|
else /* white space */
|
||||||
|
{
|
||||||
place = nargv[optind];
|
place = nargv[optind];
|
||||||
|
}
|
||||||
optchar = parse_long_options(nargv, options, long_options,
|
optchar = parse_long_options(nargv, options, long_options,
|
||||||
idx, 0);
|
idx, 0);
|
||||||
place = EMSG;
|
place = EMSG;
|
||||||
return (optchar);
|
return (optchar);
|
||||||
}
|
}
|
||||||
if (*++oli != ':') { /* doesn't take argument */
|
if(*++oli != ':') /* doesn't take argument */
|
||||||
|
{
|
||||||
if(!*place)
|
if(!*place)
|
||||||
|
{
|
||||||
++optind;
|
++optind;
|
||||||
} else { /* takes (optional) argument */
|
}
|
||||||
|
}
|
||||||
|
else /* takes (optional) argument */
|
||||||
|
{
|
||||||
optarg = NULL;
|
optarg = NULL;
|
||||||
if(*place) /* no white space */
|
if(*place) /* no white space */
|
||||||
|
{
|
||||||
optarg = place;
|
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;
|
place = EMSG;
|
||||||
if(PRINT_ERROR)
|
if(PRINT_ERROR)
|
||||||
|
{
|
||||||
warnx(recargchar, optchar);
|
warnx(recargchar, optchar);
|
||||||
|
}
|
||||||
optopt = optchar;
|
optopt = optchar;
|
||||||
return (BADARG);
|
return (BADARG);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
optarg = nargv[optind];
|
optarg = nargv[optind];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
place = EMSG;
|
place = EMSG;
|
||||||
++optind;
|
++optind;
|
||||||
}
|
}
|
||||||
|
|
103
src/3rdparty/rapidjson/allocators.h
vendored
103
src/3rdparty/rapidjson/allocators.h
vendored
|
@ -59,24 +59,35 @@ concept Allocator {
|
||||||
/*! This class is just wrapper for standard C library memory routines.
|
/*! This class is just wrapper for standard C library memory routines.
|
||||||
\note implements Allocator concept
|
\note implements Allocator concept
|
||||||
*/
|
*/
|
||||||
class CrtAllocator {
|
class CrtAllocator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const bool kNeedFree = true;
|
static const bool kNeedFree = true;
|
||||||
void* Malloc(size_t size) {
|
void* Malloc(size_t size)
|
||||||
|
{
|
||||||
if(size) // behavior of malloc(0) is implementation defined.
|
if(size) // behavior of malloc(0) is implementation defined.
|
||||||
|
{
|
||||||
return std::malloc(size);
|
return std::malloc(size);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return NULL; // standardize to returning NULL.
|
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;
|
(void)originalSize;
|
||||||
if (newSize == 0) {
|
if(newSize == 0)
|
||||||
|
{
|
||||||
std::free(originalPtr);
|
std::free(originalPtr);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return std::realloc(originalPtr, newSize);
|
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
|
\note implements Allocator concept
|
||||||
*/
|
*/
|
||||||
template <typename BaseAllocator = CrtAllocator>
|
template <typename BaseAllocator = CrtAllocator>
|
||||||
class MemoryPoolAllocator {
|
class MemoryPoolAllocator
|
||||||
|
{
|
||||||
public:
|
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.
|
//! Constructor with chunkSize.
|
||||||
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
/*! \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 chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||||
\param baseAllocator The allocator for allocating memory chunks.
|
\param baseAllocator The allocator for allocating memory chunks.
|
||||||
*/
|
*/
|
||||||
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity,
|
||||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
BaseAllocator* baseAllocator = 0) :
|
||||||
|
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator),
|
||||||
|
ownBaseAllocator_(0)
|
||||||
{
|
{
|
||||||
RAPIDJSON_ASSERT(buffer != 0);
|
RAPIDJSON_ASSERT(buffer != 0);
|
||||||
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
|
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
|
||||||
|
@ -136,51 +151,67 @@ public:
|
||||||
//! Destructor.
|
//! Destructor.
|
||||||
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
|
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
|
||||||
*/
|
*/
|
||||||
~MemoryPoolAllocator() {
|
~MemoryPoolAllocator()
|
||||||
|
{
|
||||||
Clear();
|
Clear();
|
||||||
RAPIDJSON_DELETE(ownBaseAllocator_);
|
RAPIDJSON_DELETE(ownBaseAllocator_);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
||||||
void Clear() {
|
void Clear()
|
||||||
while (chunkHead_ && chunkHead_ != userBuffer_) {
|
{
|
||||||
|
while(chunkHead_ && chunkHead_ != userBuffer_)
|
||||||
|
{
|
||||||
ChunkHeader* next = chunkHead_->next;
|
ChunkHeader* next = chunkHead_->next;
|
||||||
baseAllocator_->Free(chunkHead_);
|
baseAllocator_->Free(chunkHead_);
|
||||||
chunkHead_ = next;
|
chunkHead_ = next;
|
||||||
}
|
}
|
||||||
if(chunkHead_ && chunkHead_ == userBuffer_)
|
if(chunkHead_ && chunkHead_ == userBuffer_)
|
||||||
|
{
|
||||||
chunkHead_->size = 0; // Clear user buffer
|
chunkHead_->size = 0; // Clear user buffer
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//! Computes the total capacity of allocated memory chunks.
|
//! Computes the total capacity of allocated memory chunks.
|
||||||
/*! \return total capacity in bytes.
|
/*! \return total capacity in bytes.
|
||||||
*/
|
*/
|
||||||
size_t Capacity() const {
|
size_t Capacity() const
|
||||||
|
{
|
||||||
size_t capacity = 0;
|
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;
|
capacity += c->capacity;
|
||||||
|
}
|
||||||
return capacity;
|
return capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Computes the memory blocks allocated.
|
//! Computes the memory blocks allocated.
|
||||||
/*! \return total used bytes.
|
/*! \return total used bytes.
|
||||||
*/
|
*/
|
||||||
size_t Size() const {
|
size_t Size() const
|
||||||
|
{
|
||||||
size_t size = 0;
|
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;
|
size += c->size;
|
||||||
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Allocates a memory block. (concept Allocator)
|
//! Allocates a memory block. (concept Allocator)
|
||||||
void* Malloc(size_t size) {
|
void* Malloc(size_t size)
|
||||||
|
{
|
||||||
if(!size)
|
if(!size)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
size = RAPIDJSON_ALIGN(size);
|
size = RAPIDJSON_ALIGN(size);
|
||||||
if(chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
if(chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
||||||
if(!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
if(!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
||||||
|
{
|
||||||
return NULL;
|
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;
|
chunkHead_->size += size;
|
||||||
|
@ -188,41 +219,59 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resizes a memory block (concept Allocator)
|
//! Resizes a memory block (concept Allocator)
|
||||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
|
||||||
|
{
|
||||||
if(originalPtr == 0)
|
if(originalPtr == 0)
|
||||||
|
{
|
||||||
return Malloc(newSize);
|
return Malloc(newSize);
|
||||||
|
}
|
||||||
|
|
||||||
if(newSize == 0)
|
if(newSize == 0)
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
originalSize = RAPIDJSON_ALIGN(originalSize);
|
originalSize = RAPIDJSON_ALIGN(originalSize);
|
||||||
newSize = RAPIDJSON_ALIGN(newSize);
|
newSize = RAPIDJSON_ALIGN(newSize);
|
||||||
|
|
||||||
// Do not shrink if new size is smaller than original
|
// Do not shrink if new size is smaller than original
|
||||||
if(originalSize >= newSize)
|
if(originalSize >= newSize)
|
||||||
|
{
|
||||||
return originalPtr;
|
return originalPtr;
|
||||||
|
}
|
||||||
|
|
||||||
// Simply expand it if it is the last allocation and there is sufficient space
|
// 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);
|
size_t increment = static_cast<size_t>(newSize - originalSize);
|
||||||
if (chunkHead_->size + increment <= chunkHead_->capacity) {
|
if(chunkHead_->size + increment <= chunkHead_->capacity)
|
||||||
|
{
|
||||||
chunkHead_->size += increment;
|
chunkHead_->size += increment;
|
||||||
return originalPtr;
|
return originalPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Realloc process: allocate and copy memory, do not free original buffer.
|
// Realloc process: allocate and copy memory, do not free original buffer.
|
||||||
if (void* newBuffer = Malloc(newSize)) {
|
if(void* newBuffer = Malloc(newSize))
|
||||||
|
{
|
||||||
if(originalSize)
|
if(originalSize)
|
||||||
|
{
|
||||||
std::memcpy(newBuffer, originalPtr, originalSize);
|
std::memcpy(newBuffer, originalPtr, originalSize);
|
||||||
|
}
|
||||||
return newBuffer;
|
return newBuffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//! Frees a memory block (concept Allocator)
|
//! 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:
|
private:
|
||||||
//! Copy constructor is not permitted.
|
//! Copy constructor is not permitted.
|
||||||
|
@ -234,10 +283,15 @@ private:
|
||||||
/*! \param capacity Capacity of the chunk in bytes.
|
/*! \param capacity Capacity of the chunk in bytes.
|
||||||
\return true if success.
|
\return true if success.
|
||||||
*/
|
*/
|
||||||
bool AddChunk(size_t capacity) {
|
bool AddChunk(size_t capacity)
|
||||||
|
{
|
||||||
if(!baseAllocator_)
|
if(!baseAllocator_)
|
||||||
|
{
|
||||||
ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(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->capacity = capacity;
|
||||||
chunk->size = 0;
|
chunk->size = 0;
|
||||||
chunk->next = chunkHead_;
|
chunk->next = chunkHead_;
|
||||||
|
@ -245,15 +299,18 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
|
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
|
||||||
|
|
||||||
//! Chunk header for perpending to each chunk.
|
//! Chunk header for perpending to each chunk.
|
||||||
/*! Chunks are stored as a singly linked list.
|
/*! 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 capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
||||||
size_t size; //!< Current size of allocated memory in bytes.
|
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.
|
||||||
|
|
1996
src/3rdparty/rapidjson/document.h
vendored
1996
src/3rdparty/rapidjson/document.h
vendored
File diff suppressed because it is too large
Load diff
349
src/3rdparty/rapidjson/encodedstream.h
vendored
349
src/3rdparty/rapidjson/encodedstream.h
vendored
|
@ -36,24 +36,51 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
\tparam InputByteStream Type of input byte stream. For example, FileReadStream.
|
\tparam InputByteStream Type of input byte stream. For example, FileReadStream.
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename InputByteStream>
|
template <typename Encoding, typename InputByteStream>
|
||||||
class EncodedInputStream {
|
class EncodedInputStream
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
EncodedInputStream(InputByteStream& is) : is_(is) {
|
EncodedInputStream(InputByteStream & is) : is_(is)
|
||||||
|
{
|
||||||
current_ = Encoding::TakeBOM(is_);
|
current_ = Encoding::TakeBOM(is_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ch Peek() const { return current_; }
|
Ch Peek() const
|
||||||
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
|
{
|
||||||
size_t Tell() const { return is_.Tell(); }
|
return current_;
|
||||||
|
}
|
||||||
|
Ch Take()
|
||||||
|
{
|
||||||
|
Ch c = current_;
|
||||||
|
current_ = Encoding::Take(is_);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
size_t Tell() const
|
||||||
|
{
|
||||||
|
return is_.Tell();
|
||||||
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch)
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
{
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
}
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(false);
|
||||||
|
}
|
||||||
|
Ch* PutBegin()
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t PutEnd(Ch*)
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncodedInputStream(const EncodedInputStream &);
|
EncodedInputStream(const EncodedInputStream &);
|
||||||
|
@ -65,24 +92,50 @@ private:
|
||||||
|
|
||||||
//! Specialized for UTF8 MemoryStream.
|
//! Specialized for UTF8 MemoryStream.
|
||||||
template <>
|
template <>
|
||||||
class EncodedInputStream<UTF8<>, MemoryStream> {
|
class EncodedInputStream<UTF8<>, MemoryStream>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef UTF8<>::Ch Ch;
|
typedef UTF8<>::Ch Ch;
|
||||||
|
|
||||||
EncodedInputStream(MemoryStream& is) : is_(is) {
|
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()) == 0xEFu)
|
||||||
if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
|
{
|
||||||
|
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
|
// Not implemented
|
||||||
void Put(Ch) {}
|
void Put(Ch) {}
|
||||||
void Flush() {}
|
void Flush() {}
|
||||||
Ch* PutBegin() { return 0; }
|
Ch* PutBegin()
|
||||||
size_t PutEnd(Ch*) { return 0; }
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t PutEnd(Ch*)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
MemoryStream & is_;
|
MemoryStream & is_;
|
||||||
|
|
||||||
|
@ -97,25 +150,55 @@ private:
|
||||||
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
|
\tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename OutputByteStream>
|
template <typename Encoding, typename OutputByteStream>
|
||||||
class EncodedOutputStream {
|
class EncodedOutputStream
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
|
EncodedOutputStream(OutputByteStream & os, bool putBOM = true) : os_(os)
|
||||||
|
{
|
||||||
if(putBOM)
|
if(putBOM)
|
||||||
|
{
|
||||||
Encoding::PutBOM(os_);
|
Encoding::PutBOM(os_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Put(Ch c) { Encoding::Put(os_, c); }
|
void Put(Ch c)
|
||||||
void Flush() { os_.Flush(); }
|
{
|
||||||
|
Encoding::Put(os_, c);
|
||||||
|
}
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
os_.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
Ch Peek() const
|
||||||
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
{
|
||||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
return 0;
|
||||||
size_t PutEnd(Ch*) { 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:
|
private:
|
||||||
EncodedOutputStream(const EncodedOutputStream &);
|
EncodedOutputStream(const EncodedOutputStream &);
|
||||||
|
@ -132,7 +215,8 @@ private:
|
||||||
\tparam InputByteStream type of input byte stream to be wrapped.
|
\tparam InputByteStream type of input byte stream to be wrapped.
|
||||||
*/
|
*/
|
||||||
template <typename CharType, typename InputByteStream>
|
template <typename CharType, typename InputByteStream>
|
||||||
class AutoUTFInputStream {
|
class AutoUTFInputStream
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
public:
|
public:
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
@ -142,7 +226,8 @@ public:
|
||||||
\param is input stream to be wrapped.
|
\param is input stream to be wrapped.
|
||||||
\param type UTF encoding type if it is not detected from the stream.
|
\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);
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
DetectType();
|
DetectType();
|
||||||
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
||||||
|
@ -150,25 +235,57 @@ public:
|
||||||
current_ = takeFunc_(*is_);
|
current_ = takeFunc_(*is_);
|
||||||
}
|
}
|
||||||
|
|
||||||
UTFType GetType() const { return type_; }
|
UTFType GetType() const
|
||||||
bool HasBOM() const { return hasBOM_; }
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
bool HasBOM() const
|
||||||
|
{
|
||||||
|
return hasBOM_;
|
||||||
|
}
|
||||||
|
|
||||||
Ch Peek() const { return current_; }
|
Ch Peek() const
|
||||||
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
|
{
|
||||||
size_t Tell() const { return is_->Tell(); }
|
return current_;
|
||||||
|
}
|
||||||
|
Ch Take()
|
||||||
|
{
|
||||||
|
Ch c = current_;
|
||||||
|
current_ = takeFunc_(*is_);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
size_t Tell() const
|
||||||
|
{
|
||||||
|
return is_->Tell();
|
||||||
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch)
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
{
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
}
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(false);
|
||||||
|
}
|
||||||
|
Ch* PutBegin()
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t PutEnd(Ch*)
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AutoUTFInputStream(const AutoUTFInputStream &);
|
AutoUTFInputStream(const AutoUTFInputStream &);
|
||||||
AutoUTFInputStream & operator=(const AutoUTFInputStream &);
|
AutoUTFInputStream & operator=(const AutoUTFInputStream &);
|
||||||
|
|
||||||
// Detect encoding type with BOM or RFC 4627
|
// Detect encoding type with BOM or RFC 4627
|
||||||
void DetectType() {
|
void DetectType()
|
||||||
|
{
|
||||||
// BOM (Byte Order Mark):
|
// BOM (Byte Order Mark):
|
||||||
// 00 00 FE FF UTF-32BE
|
// 00 00 FE FF UTF-32BE
|
||||||
// FF FE 00 00 UTF-32LE
|
// FF FE 00 00 UTF-32LE
|
||||||
|
@ -178,15 +295,52 @@ private:
|
||||||
|
|
||||||
const unsigned char* c = reinterpret_cast<const unsigned char*>(is_->Peek4());
|
const unsigned char* c = reinterpret_cast<const unsigned char*>(is_->Peek4());
|
||||||
if(!c)
|
if(!c)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
|
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
|
||||||
hasBOM_ = false;
|
hasBOM_ = false;
|
||||||
if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
|
if(bom == 0xFFFE0000)
|
||||||
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(); }
|
type_ = kUTF32BE;
|
||||||
else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
|
hasBOM_ = true;
|
||||||
else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
|
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
|
// RFC 4627: Section 3
|
||||||
// "Since the first two characters of a JSON text will always be ASCII
|
// "Since the first two characters of a JSON text will always be ASCII
|
||||||
|
@ -199,21 +353,40 @@ private:
|
||||||
// xx 00 xx 00 UTF-16LE
|
// xx 00 xx 00 UTF-16LE
|
||||||
// xx xx xx xx UTF-8
|
// 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);
|
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||||
switch (pattern) {
|
switch(pattern)
|
||||||
case 0x08: type_ = kUTF32BE; break;
|
{
|
||||||
case 0x0A: type_ = kUTF16BE; break;
|
case 0x08:
|
||||||
case 0x01: type_ = kUTF32LE; break;
|
type_ = kUTF32BE;
|
||||||
case 0x05: type_ = kUTF16LE; break;
|
break;
|
||||||
case 0x0F: type_ = kUTF8; break;
|
case 0x0A:
|
||||||
default: break; // Use type defined by user.
|
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.
|
// 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_ == kUTF16LE || type_ == kUTF16BE)
|
||||||
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
{
|
||||||
|
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);
|
||||||
|
@ -230,7 +403,8 @@ private:
|
||||||
\tparam OutputByteStream type of output byte stream to be wrapped.
|
\tparam OutputByteStream type of output byte stream to be wrapped.
|
||||||
*/
|
*/
|
||||||
template <typename CharType, typename OutputByteStream>
|
template <typename CharType, typename OutputByteStream>
|
||||||
class AutoUTFOutputStream {
|
class AutoUTFOutputStream
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
public:
|
public:
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
@ -241,37 +415,76 @@ public:
|
||||||
\param type UTF encoding type.
|
\param type UTF encoding type.
|
||||||
\param putBOM Whether to write BOM at the beginning of the stream.
|
\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);
|
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||||
|
|
||||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
// 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_ == kUTF16LE || type_ == kUTF16BE)
|
||||||
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
{
|
||||||
|
RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||||
|
}
|
||||||
|
if(type_ == kUTF32LE || type_ == kUTF32BE)
|
||||||
|
{
|
||||||
|
RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||||
|
}
|
||||||
|
|
||||||
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
||||||
putFunc_ = f[type_];
|
putFunc_ = f[type_];
|
||||||
|
|
||||||
if(putBOM)
|
if(putBOM)
|
||||||
|
{
|
||||||
PutBOM();
|
PutBOM();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UTFType GetType() const { return type_; }
|
UTFType GetType() const
|
||||||
|
{
|
||||||
|
return type_;
|
||||||
|
}
|
||||||
|
|
||||||
void Put(Ch c) { putFunc_(*os_, c); }
|
void Put(Ch c)
|
||||||
void Flush() { os_->Flush(); }
|
{
|
||||||
|
putFunc_(*os_, c);
|
||||||
|
}
|
||||||
|
void Flush()
|
||||||
|
{
|
||||||
|
os_->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
Ch Peek() const
|
||||||
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
{
|
||||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
return 0;
|
||||||
size_t PutEnd(Ch*) { 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:
|
private:
|
||||||
AutoUTFOutputStream(const AutoUTFOutputStream &);
|
AutoUTFOutputStream(const AutoUTFOutputStream &);
|
||||||
AutoUTFOutputStream & operator=(const AutoUTFOutputStream &);
|
AutoUTFOutputStream & operator=(const AutoUTFOutputStream &);
|
||||||
|
|
||||||
void PutBOM() {
|
void PutBOM()
|
||||||
|
{
|
||||||
typedef void (*PutBOMFunc)(OutputByteStream &);
|
typedef void (*PutBOMFunc)(OutputByteStream &);
|
||||||
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
|
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
|
||||||
f[type_](*os_);
|
f[type_](*os_);
|
||||||
|
|
362
src/3rdparty/rapidjson/encodings.h
vendored
362
src/3rdparty/rapidjson/encodings.h
vendored
|
@ -93,25 +93,32 @@ concept Encoding {
|
||||||
\note implements Encoding concept
|
\note implements Encoding concept
|
||||||
*/
|
*/
|
||||||
template<typename CharType = char>
|
template<typename CharType = char>
|
||||||
struct UTF8 {
|
struct UTF8
|
||||||
|
{
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
template<typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
static void Encode(OutputStream & os, unsigned codepoint)
|
||||||
|
{
|
||||||
if(codepoint <= 0x7F)
|
if(codepoint <= 0x7F)
|
||||||
|
{
|
||||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
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>(0xC0 | ((codepoint >> 6) & 0xFF)));
|
||||||
os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
|
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>(0xE0 | ((codepoint >> 12) & 0xFF)));
|
||||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||||
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||||
|
@ -121,19 +128,25 @@ struct UTF8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
|
||||||
|
{
|
||||||
if(codepoint <= 0x7F)
|
if(codepoint <= 0x7F)
|
||||||
|
{
|
||||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
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>(0xC0 | ((codepoint >> 6) & 0xFF)));
|
||||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
|
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>(0xE0 | ((codepoint >> 12) & 0xFF)));
|
||||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||||
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||||
|
@ -143,32 +156,66 @@ struct UTF8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
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 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 TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
#define TAIL() COPY(); TRANS(0x70)
|
#define TAIL() COPY(); TRANS(0x70)
|
||||||
typename InputStream::Ch c = is.Take();
|
typename InputStream::Ch c = is.Take();
|
||||||
if (!(c & 0x80)) {
|
if(!(c & 0x80))
|
||||||
|
{
|
||||||
*codepoint = static_cast<unsigned char>(c);
|
*codepoint = static_cast<unsigned char>(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
unsigned char type = GetRange(static_cast<unsigned char>(c));
|
||||||
if (type >= 32) {
|
if(type >= 32)
|
||||||
|
{
|
||||||
*codepoint = 0;
|
*codepoint = 0;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
|
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
|
||||||
}
|
}
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (type) {
|
switch(type)
|
||||||
case 2: TAIL(); return result;
|
{
|
||||||
case 3: TAIL(); TAIL(); return result;
|
case 2:
|
||||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
TAIL();
|
||||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
return result;
|
||||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
case 3:
|
||||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
TAIL();
|
||||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
TAIL();
|
||||||
default: return false;
|
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 COPY
|
||||||
#undef TRANS
|
#undef TRANS
|
||||||
|
@ -176,35 +223,69 @@ struct UTF8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
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 COPY() os.Put(c = is.Take())
|
||||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||||
#define TAIL() COPY(); TRANS(0x70)
|
#define TAIL() COPY(); TRANS(0x70)
|
||||||
Ch c;
|
Ch c;
|
||||||
COPY();
|
COPY();
|
||||||
if(!(c & 0x80))
|
if(!(c & 0x80))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
switch (GetRange(static_cast<unsigned char>(c))) {
|
switch(GetRange(static_cast<unsigned char>(c)))
|
||||||
case 2: TAIL(); return result;
|
{
|
||||||
case 3: TAIL(); TAIL(); return result;
|
case 2:
|
||||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
TAIL();
|
||||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
return result;
|
||||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
case 3:
|
||||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
TAIL();
|
||||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
TAIL();
|
||||||
default: return false;
|
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 COPY
|
||||||
#undef TRANS
|
#undef TRANS
|
||||||
#undef TAIL
|
#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/
|
// 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.
|
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
|
||||||
static const unsigned char type[] = {
|
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,
|
||||||
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,
|
||||||
|
@ -220,26 +301,38 @@ struct UTF8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
typename InputByteStream::Ch c = Take(is);
|
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();
|
c = is.Take();
|
||||||
if (static_cast<unsigned char>(c) != 0xBBu) return c;
|
if(static_cast<unsigned char>(c) != 0xBBu)
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
if (static_cast<unsigned char>(c) != 0xBFu) return c;
|
if(static_cast<unsigned char>(c) != 0xBFu)
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static Ch Take(InputByteStream& is) {
|
static Ch Take(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
return static_cast<Ch>(is.Take());
|
return static_cast<Ch>(is.Take());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream & os)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
|
||||||
|
@ -247,7 +340,8 @@ struct UTF8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
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);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
||||||
}
|
}
|
||||||
|
@ -266,20 +360,24 @@ struct UTF8 {
|
||||||
For streaming, use UTF16LE and UTF16BE, which handle endianness.
|
For streaming, use UTF16LE and UTF16BE, which handle endianness.
|
||||||
*/
|
*/
|
||||||
template<typename CharType = wchar_t>
|
template<typename CharType = wchar_t>
|
||||||
struct UTF16 {
|
struct UTF16
|
||||||
|
{
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
template<typename OutputStream>
|
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);
|
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
|
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||||
os.Put(static_cast<typename OutputStream::Ch>(codepoint));
|
os.Put(static_cast<typename OutputStream::Ch>(codepoint));
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
unsigned v = codepoint - 0x10000;
|
unsigned v = codepoint - 0x10000;
|
||||||
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||||
|
@ -289,13 +387,16 @@ struct UTF16 {
|
||||||
|
|
||||||
|
|
||||||
template<typename OutputStream>
|
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);
|
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
|
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
|
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
unsigned v = codepoint - 0x10000;
|
unsigned v = codepoint - 0x10000;
|
||||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||||
|
@ -304,14 +405,17 @@ struct UTF16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
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);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||||
typename InputStream::Ch c = is.Take();
|
typename InputStream::Ch c = is.Take();
|
||||||
if (c < 0xD800 || c > 0xDFFF) {
|
if(c < 0xD800 || c > 0xDFFF)
|
||||||
|
{
|
||||||
*codepoint = static_cast<unsigned>(c);
|
*codepoint = static_cast<unsigned>(c);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (c <= 0xDBFF) {
|
else if(c <= 0xDBFF)
|
||||||
|
{
|
||||||
*codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
|
*codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
|
||||||
c = is.Take();
|
c = is.Take();
|
||||||
*codepoint |= (static_cast<unsigned>(c) & 0x3FF);
|
*codepoint |= (static_cast<unsigned>(c) & 0x3FF);
|
||||||
|
@ -322,14 +426,18 @@ struct UTF16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
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 InputStream::Ch) >= 2);
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||||
typename InputStream::Ch c;
|
typename InputStream::Ch c;
|
||||||
os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
|
os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
|
||||||
if(c < 0xD800 || c > 0xDFFF)
|
if(c < 0xD800 || c > 0xDFFF)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
else if (c <= 0xDBFF) {
|
}
|
||||||
|
else if(c <= 0xDBFF)
|
||||||
|
{
|
||||||
os.Put(c = is.Take());
|
os.Put(c = is.Take());
|
||||||
return c >= 0xDC00 && c <= 0xDFFF;
|
return c >= 0xDC00 && c <= 0xDFFF;
|
||||||
}
|
}
|
||||||
|
@ -339,16 +447,19 @@ struct UTF16 {
|
||||||
|
|
||||||
//! UTF-16 little endian encoding.
|
//! UTF-16 little endian encoding.
|
||||||
template<typename CharType = wchar_t>
|
template<typename CharType = wchar_t>
|
||||||
struct UTF16LE : UTF16<CharType> {
|
struct UTF16LE : UTF16<CharType>
|
||||||
|
{
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
unsigned c = static_cast<uint8_t>(is.Take());
|
unsigned c = static_cast<uint8_t>(is.Take());
|
||||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
|
@ -356,14 +467,16 @@ struct UTF16LE : UTF16<CharType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream & os)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
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);
|
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) & 0xFFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 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.
|
//! UTF-16 big endian encoding.
|
||||||
template<typename CharType = wchar_t>
|
template<typename CharType = wchar_t>
|
||||||
struct UTF16BE : UTF16<CharType> {
|
struct UTF16BE : UTF16<CharType>
|
||||||
|
{
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
c |= static_cast<uint8_t>(is.Take());
|
c |= static_cast<uint8_t>(is.Take());
|
||||||
|
@ -389,14 +505,16 @@ struct UTF16BE : UTF16<CharType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream & os)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
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);
|
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) >> 8) & 0xFFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 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.
|
For streaming, use UTF32LE and UTF32BE, which handle endianness.
|
||||||
*/
|
*/
|
||||||
template<typename CharType = unsigned>
|
template<typename CharType = unsigned>
|
||||||
struct UTF32 {
|
struct UTF32
|
||||||
|
{
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
|
||||||
template<typename OutputStream>
|
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_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
os.Put(codepoint);
|
os.Put(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OutputStream>
|
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_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||||
PutUnsafe(os, codepoint);
|
PutUnsafe(os, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
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);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||||
Ch c = is.Take();
|
Ch c = is.Take();
|
||||||
*codepoint = c;
|
*codepoint = c;
|
||||||
|
@ -444,7 +566,8 @@ struct UTF32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
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);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||||
Ch c;
|
Ch c;
|
||||||
os.Put(c = is.Take());
|
os.Put(c = is.Take());
|
||||||
|
@ -454,16 +577,19 @@ struct UTF32 {
|
||||||
|
|
||||||
//! UTF-32 little endian enocoding.
|
//! UTF-32 little endian enocoding.
|
||||||
template<typename CharType = unsigned>
|
template<typename CharType = unsigned>
|
||||||
struct UTF32LE : UTF32<CharType> {
|
struct UTF32LE : UTF32<CharType>
|
||||||
|
{
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
unsigned c = static_cast<uint8_t>(is.Take());
|
unsigned c = static_cast<uint8_t>(is.Take());
|
||||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||||
|
@ -473,7 +599,8 @@ struct UTF32LE : UTF32<CharType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream & os)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||||
|
@ -482,7 +609,8 @@ struct UTF32LE : UTF32<CharType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
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);
|
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 & 0xFFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||||
|
@ -493,16 +621,19 @@ struct UTF32LE : UTF32<CharType> {
|
||||||
|
|
||||||
//! UTF-32 big endian encoding.
|
//! UTF-32 big endian encoding.
|
||||||
template<typename CharType = unsigned>
|
template<typename CharType = unsigned>
|
||||||
struct UTF32BE : UTF32<CharType> {
|
struct UTF32BE : UTF32<CharType>
|
||||||
|
{
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
CharType c = Take(is);
|
CharType c = Take(is);
|
||||||
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType Take(InputByteStream& is) {
|
static CharType Take(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||||
|
@ -512,7 +643,8 @@ struct UTF32BE : UTF32<CharType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream & os)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||||
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>
|
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);
|
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 >> 24) & 0xFFu));
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||||
|
@ -539,58 +672,67 @@ struct UTF32BE : UTF32<CharType> {
|
||||||
\note implements Encoding concept
|
\note implements Encoding concept
|
||||||
*/
|
*/
|
||||||
template<typename CharType = char>
|
template<typename CharType = char>
|
||||||
struct ASCII {
|
struct ASCII
|
||||||
|
{
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
enum { supportUnicode = 0 };
|
enum { supportUnicode = 0 };
|
||||||
|
|
||||||
template<typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
static void Encode(OutputStream & os, unsigned codepoint)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OutputStream>
|
template<typename OutputStream>
|
||||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
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());
|
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||||
*codepoint = c;
|
*codepoint = c;
|
||||||
return c <= 0X7F;
|
return c <= 0X7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
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());
|
uint8_t c = static_cast<uint8_t>(is.Take());
|
||||||
os.Put(static_cast<typename OutputStream::Ch>(c));
|
os.Put(static_cast<typename OutputStream::Ch>(c));
|
||||||
return c <= 0x7F;
|
return c <= 0x7F;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static CharType TakeBOM(InputByteStream& is) {
|
static CharType TakeBOM(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
uint8_t c = static_cast<uint8_t>(Take(is));
|
uint8_t c = static_cast<uint8_t>(Take(is));
|
||||||
return static_cast<Ch>(c);
|
return static_cast<Ch>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputByteStream>
|
template <typename InputByteStream>
|
||||||
static Ch Take(InputByteStream& is) {
|
static Ch Take(InputByteStream & is)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||||
return static_cast<Ch>(is.Take());
|
return static_cast<Ch>(is.Take());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
template <typename OutputByteStream>
|
||||||
static void PutBOM(OutputByteStream& os) {
|
static void PutBOM(OutputByteStream & os)
|
||||||
|
{
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
(void)os;
|
(void)os;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputByteStream>
|
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);
|
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||||
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
||||||
}
|
}
|
||||||
|
@ -600,7 +742,8 @@ struct ASCII {
|
||||||
// AutoUTF
|
// AutoUTF
|
||||||
|
|
||||||
//! Runtime-specified UTF encoding type of a stream.
|
//! Runtime-specified UTF encoding type of a stream.
|
||||||
enum UTFType {
|
enum UTFType
|
||||||
|
{
|
||||||
kUTF8 = 0, //!< UTF-8.
|
kUTF8 = 0, //!< UTF-8.
|
||||||
kUTF16LE = 1, //!< UTF-16 little endian.
|
kUTF16LE = 1, //!< UTF-16 little endian.
|
||||||
kUTF16BE = 2, //!< UTF-16 big 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().
|
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
|
||||||
*/
|
*/
|
||||||
template<typename CharType>
|
template<typename CharType>
|
||||||
struct AutoUTF {
|
struct AutoUTF
|
||||||
|
{
|
||||||
typedef CharType Ch;
|
typedef CharType Ch;
|
||||||
|
|
||||||
enum { supportUnicode = 1 };
|
enum { supportUnicode = 1 };
|
||||||
|
@ -620,28 +764,32 @@ struct AutoUTF {
|
||||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||||
|
|
||||||
template<typename OutputStream>
|
template<typename OutputStream>
|
||||||
RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
|
RAPIDJSON_FORCEINLINE static void Encode(OutputStream & os, unsigned codepoint)
|
||||||
|
{
|
||||||
typedef void (*EncodeFunc)(OutputStream &, unsigned);
|
typedef void (*EncodeFunc)(OutputStream &, unsigned);
|
||||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
||||||
(*f[os.GetType()])(os, codepoint);
|
(*f[os.GetType()])(os, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OutputStream>
|
template<typename OutputStream>
|
||||||
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream & os, unsigned codepoint)
|
||||||
|
{
|
||||||
typedef void (*EncodeFunc)(OutputStream &, unsigned);
|
typedef void (*EncodeFunc)(OutputStream &, unsigned);
|
||||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||||
(*f[os.GetType()])(os, codepoint);
|
(*f[os.GetType()])(os, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
|
RAPIDJSON_FORCEINLINE static bool Decode(InputStream & is, unsigned* codepoint)
|
||||||
|
{
|
||||||
typedef bool (*DecodeFunc)(InputStream &, unsigned*);
|
typedef bool (*DecodeFunc)(InputStream &, unsigned*);
|
||||||
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
|
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
|
||||||
return (*f[is.GetType()])(is, codepoint);
|
return (*f[is.GetType()])(is, codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream, typename OutputStream>
|
template <typename InputStream, typename OutputStream>
|
||||||
RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
RAPIDJSON_FORCEINLINE static bool Validate(InputStream & is, OutputStream & os)
|
||||||
|
{
|
||||||
typedef bool (*ValidateFunc)(InputStream &, OutputStream &);
|
typedef bool (*ValidateFunc)(InputStream &, OutputStream &);
|
||||||
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
|
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
|
||||||
return (*f[is.GetType()])(is, os);
|
return (*f[is.GetType()])(is, os);
|
||||||
|
@ -655,29 +803,37 @@ struct AutoUTF {
|
||||||
|
|
||||||
//! Encoding conversion.
|
//! Encoding conversion.
|
||||||
template<typename SourceEncoding, typename TargetEncoding>
|
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.
|
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
||||||
template<typename InputStream, typename OutputStream>
|
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;
|
unsigned codepoint;
|
||||||
if(!SourceEncoding::Decode(is, &codepoint))
|
if(!SourceEncoding::Decode(is, &codepoint))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
TargetEncoding::Encode(os, codepoint);
|
TargetEncoding::Encode(os, codepoint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputStream, typename OutputStream>
|
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;
|
unsigned codepoint;
|
||||||
if(!SourceEncoding::Decode(is, &codepoint))
|
if(!SourceEncoding::Decode(is, &codepoint))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
TargetEncoding::EncodeUnsafe(os, codepoint);
|
TargetEncoding::EncodeUnsafe(os, codepoint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Validate one Unicode codepoint from an encoded stream.
|
//! Validate one Unicode codepoint from an encoded stream.
|
||||||
template<typename InputStream, typename OutputStream>
|
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.
|
return Transcode(is, os); // Since source/target encoding is different, must transcode.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -688,21 +844,25 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
|
||||||
|
|
||||||
//! Specialization of Transcoder with same source and target encoding.
|
//! Specialization of Transcoder with same source and target encoding.
|
||||||
template<typename Encoding>
|
template<typename Encoding>
|
||||||
struct Transcoder<Encoding, Encoding> {
|
struct Transcoder<Encoding, Encoding>
|
||||||
|
{
|
||||||
template<typename InputStream, typename OutputStream>
|
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.
|
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputStream, typename OutputStream>
|
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.
|
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputStream, typename OutputStream>
|
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
|
return Encoding::Validate(is, os); // source/target encoding are the same
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
63
src/3rdparty/rapidjson/error/en.h
vendored
63
src/3rdparty/rapidjson/error/en.h
vendored
|
@ -33,35 +33,56 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
\note User can make a copy of this function for localization.
|
\note User can make a copy of this function for localization.
|
||||||
Using switch-case is safer for future modification of error codes.
|
Using switch-case is safer for future modification of error codes.
|
||||||
*/
|
*/
|
||||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
|
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode)
|
||||||
switch (parseErrorCode) {
|
{
|
||||||
case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
|
switch(parseErrorCode)
|
||||||
|
{
|
||||||
|
case kParseErrorNone:
|
||||||
|
return RAPIDJSON_ERROR_STRING("No error.");
|
||||||
|
|
||||||
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
|
case kParseErrorDocumentEmpty:
|
||||||
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
|
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 kParseErrorObjectMissName:
|
||||||
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
|
return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
|
||||||
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an 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 kParseErrorStringUnicodeEscapeInvalidHex:
|
||||||
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
|
||||||
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
|
case kParseErrorStringUnicodeSurrogateInvalid:
|
||||||
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
|
return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
||||||
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
|
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 kParseErrorNumberTooBig:
|
||||||
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
|
return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
|
||||||
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
|
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 kParseErrorTermination:
|
||||||
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
|
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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
52
src/3rdparty/rapidjson/error/error.h
vendored
52
src/3rdparty/rapidjson/error/error.h
vendored
|
@ -61,7 +61,8 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
/*! \ingroup RAPIDJSON_ERRORS
|
/*! \ingroup RAPIDJSON_ERRORS
|
||||||
\see GenericReader::Parse, GenericReader::GetParseErrorCode
|
\see GenericReader::Parse, GenericReader::GetParseErrorCode
|
||||||
*/
|
*/
|
||||||
enum ParseErrorCode {
|
enum ParseErrorCode
|
||||||
|
{
|
||||||
kParseErrorNone = 0, //!< No error.
|
kParseErrorNone = 0, //!< No error.
|
||||||
|
|
||||||
kParseErrorDocumentEmpty, //!< The document is empty.
|
kParseErrorDocumentEmpty, //!< The document is empty.
|
||||||
|
@ -103,7 +104,8 @@ enum ParseErrorCode {
|
||||||
\endcode
|
\endcode
|
||||||
\see GenericReader::Parse, GenericDocument::Parse
|
\see GenericReader::Parse, GenericDocument::Parse
|
||||||
*/
|
*/
|
||||||
struct ParseResult {
|
struct ParseResult
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
//! Default constructor, no error.
|
//! Default constructor, no error.
|
||||||
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
||||||
|
@ -111,23 +113,51 @@ public:
|
||||||
ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
|
ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
|
||||||
|
|
||||||
//! Get the error code.
|
//! Get the error code.
|
||||||
ParseErrorCode Code() const { return code_; }
|
ParseErrorCode Code() const
|
||||||
|
{
|
||||||
|
return code_;
|
||||||
|
}
|
||||||
//! Get the error offset, if \ref IsError(), 0 otherwise.
|
//! 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().
|
//! 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.
|
//! 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==(const ParseResult & that) const
|
||||||
bool operator==(ParseErrorCode code) const { return code_ == code; }
|
{
|
||||||
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
|
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.
|
//! Reset error code.
|
||||||
void Clear() { Set(kParseErrorNone); }
|
void Clear()
|
||||||
|
{
|
||||||
|
Set(kParseErrorNone);
|
||||||
|
}
|
||||||
//! Update error code and offset.
|
//! 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:
|
private:
|
||||||
ParseErrorCode code_;
|
ParseErrorCode code_;
|
||||||
|
|
60
src/3rdparty/rapidjson/filereadstream.h
vendored
60
src/3rdparty/rapidjson/filereadstream.h
vendored
|
@ -31,7 +31,8 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
/*!
|
/*!
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
class FileReadStream {
|
class FileReadStream
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef char Ch; //!< Character type (byte).
|
typedef char Ch; //!< Character type (byte).
|
||||||
|
|
||||||
|
@ -41,38 +42,71 @@ public:
|
||||||
\param buffer user-supplied buffer.
|
\param buffer user-supplied buffer.
|
||||||
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
\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(fp_ != 0);
|
||||||
RAPIDJSON_ASSERT(bufferSize >= 4);
|
RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||||
Read();
|
Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ch Peek() const { return *current_; }
|
Ch Peek() const
|
||||||
Ch Take() { Ch c = *current_; Read(); return c; }
|
{
|
||||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
return *current_;
|
||||||
|
}
|
||||||
|
Ch Take()
|
||||||
|
{
|
||||||
|
Ch c = *current_;
|
||||||
|
Read();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
size_t Tell() const
|
||||||
|
{
|
||||||
|
return count_ + static_cast<size_t>(current_ - buffer_);
|
||||||
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
void Put(Ch)
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
{
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
}
|
||||||
|
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.
|
// For encoding detection only.
|
||||||
const Ch* Peek4() const {
|
const Ch* Peek4() const
|
||||||
|
{
|
||||||
return (current_ + 4 <= bufferLast_) ? current_ : 0;
|
return (current_ + 4 <= bufferLast_) ? current_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Read() {
|
void Read()
|
||||||
|
{
|
||||||
if(current_ < bufferLast_)
|
if(current_ < bufferLast_)
|
||||||
|
{
|
||||||
++current_;
|
++current_;
|
||||||
else if (!eof_) {
|
}
|
||||||
|
else if(!eof_)
|
||||||
|
{
|
||||||
count_ += readCount_;
|
count_ += readCount_;
|
||||||
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
|
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
|
||||||
bufferLast_ = buffer_ + readCount_ - 1;
|
bufferLast_ = buffer_ + readCount_ - 1;
|
||||||
current_ = buffer_;
|
current_ = buffer_;
|
||||||
|
|
||||||
if (readCount_ < bufferSize_) {
|
if(readCount_ < bufferSize_)
|
||||||
|
{
|
||||||
buffer_[readCount_] = '\0';
|
buffer_[readCount_] = '\0';
|
||||||
++bufferLast_;
|
++bufferLast_;
|
||||||
eof_ = true;
|
eof_ = true;
|
||||||
|
|
63
src/3rdparty/rapidjson/filewritestream.h
vendored
63
src/3rdparty/rapidjson/filewritestream.h
vendored
|
@ -29,24 +29,32 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
/*!
|
/*!
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
class FileWriteStream {
|
class FileWriteStream
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef char Ch; //!< Character type. Only support char.
|
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);
|
RAPIDJSON_ASSERT(fp_ != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Put(char c) {
|
void Put(char c)
|
||||||
|
{
|
||||||
if(current_ >= bufferEnd_)
|
if(current_ >= bufferEnd_)
|
||||||
|
{
|
||||||
Flush();
|
Flush();
|
||||||
|
}
|
||||||
|
|
||||||
*current_++ = c;
|
*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_);
|
size_t avail = static_cast<size_t>(bufferEnd_ - current_);
|
||||||
while (n > avail) {
|
while(n > avail)
|
||||||
|
{
|
||||||
std::memset(current_, c, avail);
|
std::memset(current_, c, avail);
|
||||||
current_ += avail;
|
current_ += avail;
|
||||||
Flush();
|
Flush();
|
||||||
|
@ -54,16 +62,20 @@ public:
|
||||||
avail = static_cast<size_t>(bufferEnd_ - current_);
|
avail = static_cast<size_t>(bufferEnd_ - current_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n > 0) {
|
if(n > 0)
|
||||||
|
{
|
||||||
std::memset(current_, c, n);
|
std::memset(current_, c, n);
|
||||||
current_ += n;
|
current_ += n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Flush() {
|
void Flush()
|
||||||
if (current_ != buffer_) {
|
{
|
||||||
|
if(current_ != buffer_)
|
||||||
|
{
|
||||||
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
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
|
// failure deliberately ignored at this time
|
||||||
// added to avoid warn_unused_result build errors
|
// added to avoid warn_unused_result build errors
|
||||||
}
|
}
|
||||||
|
@ -72,11 +84,31 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
char Peek() const
|
||||||
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
{
|
||||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
return 0;
|
||||||
size_t PutEnd(char*) { 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:
|
private:
|
||||||
// Prohibit copy constructor & assignment operator.
|
// Prohibit copy constructor & assignment operator.
|
||||||
|
@ -91,7 +123,8 @@ private:
|
||||||
|
|
||||||
//! Implement specialized version of PutN() with memset() for better performance.
|
//! Implement specialized version of PutN() with memset() for better performance.
|
||||||
template<>
|
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);
|
stream.PutN(c, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
src/3rdparty/rapidjson/fwd.h
vendored
3
src/3rdparty/rapidjson/fwd.h
vendored
|
@ -144,7 +144,8 @@ template <
|
||||||
typename StateAllocator >
|
typename StateAllocator >
|
||||||
class GenericSchemaValidator;
|
class GenericSchemaValidator;
|
||||||
|
|
||||||
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
|
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator>
|
||||||
|
SchemaValidator;
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
|
205
src/3rdparty/rapidjson/internal/biginteger.h
vendored
205
src/3rdparty/rapidjson/internal/biginteger.h
vendored
|
@ -23,92 +23,132 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
class BigInteger {
|
class BigInteger
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef uint64_t Type;
|
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));
|
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;
|
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);
|
RAPIDJSON_ASSERT(length > 0);
|
||||||
digits_[0] = 0;
|
digits_[0] = 0;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
|
const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
|
||||||
while (length >= kMaxDigitPerIteration) {
|
while(length >= kMaxDigitPerIteration)
|
||||||
|
{
|
||||||
AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
|
AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
|
||||||
length -= kMaxDigitPerIteration;
|
length -= kMaxDigitPerIteration;
|
||||||
i += kMaxDigitPerIteration;
|
i += kMaxDigitPerIteration;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(length > 0)
|
if(length > 0)
|
||||||
|
{
|
||||||
AppendDecimal64(decimals + i, decimals + i + length);
|
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_;
|
count_ = rhs.count_;
|
||||||
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& operator=(uint64_t u) {
|
BigInteger & operator=(uint64_t u)
|
||||||
|
{
|
||||||
digits_[0] = u;
|
digits_[0] = u;
|
||||||
count_ = 1;
|
count_ = 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& operator+=(uint64_t u) {
|
BigInteger & operator+=(uint64_t u)
|
||||||
|
{
|
||||||
Type backup = digits_[0];
|
Type backup = digits_[0];
|
||||||
digits_[0] += u;
|
digits_[0] += u;
|
||||||
for (size_t i = 0; i < count_ - 1; i++) {
|
for(size_t i = 0; i < count_ - 1; i++)
|
||||||
|
{
|
||||||
if(digits_[i] >= backup)
|
if(digits_[i] >= backup)
|
||||||
|
{
|
||||||
return *this; // no carry
|
return *this; // no carry
|
||||||
|
}
|
||||||
backup = digits_[i + 1];
|
backup = digits_[i + 1];
|
||||||
digits_[i + 1] += 1;
|
digits_[i + 1] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last carry
|
// Last carry
|
||||||
if(digits_[count_ - 1] < backup)
|
if(digits_[count_ - 1] < backup)
|
||||||
|
{
|
||||||
PushBack(1);
|
PushBack(1);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& operator*=(uint64_t u) {
|
BigInteger & operator*=(uint64_t u)
|
||||||
if (u == 0) return *this = 0;
|
{
|
||||||
if (u == 1) return *this;
|
if(u == 0)
|
||||||
if (*this == 1) return *this = u;
|
{
|
||||||
|
return *this = 0;
|
||||||
|
}
|
||||||
|
if(u == 1)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if(*this == 1)
|
||||||
|
{
|
||||||
|
return *this = u;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t k = 0;
|
uint64_t k = 0;
|
||||||
for (size_t i = 0; i < count_; i++) {
|
for(size_t i = 0; i < count_; i++)
|
||||||
|
{
|
||||||
uint64_t hi;
|
uint64_t hi;
|
||||||
digits_[i] = MulAdd64(digits_[i], u, k, &hi);
|
digits_[i] = MulAdd64(digits_[i], u, k, &hi);
|
||||||
k = hi;
|
k = hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(k > 0)
|
if(k > 0)
|
||||||
|
{
|
||||||
PushBack(k);
|
PushBack(k);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& operator*=(uint32_t u) {
|
BigInteger & operator*=(uint32_t u)
|
||||||
if (u == 0) return *this = 0;
|
{
|
||||||
if (u == 1) return *this;
|
if(u == 0)
|
||||||
if (*this == 1) return *this = u;
|
{
|
||||||
|
return *this = 0;
|
||||||
|
}
|
||||||
|
if(u == 1)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if(*this == 1)
|
||||||
|
{
|
||||||
|
return *this = u;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t k = 0;
|
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 c = digits_[i] >> 32;
|
||||||
const uint64_t d = digits_[i] & 0xFFFFFFFF;
|
const uint64_t d = digits_[i] & 0xFFFFFFFF;
|
||||||
const uint64_t uc = u * c;
|
const uint64_t uc = u * c;
|
||||||
|
@ -120,47 +160,63 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(k > 0)
|
if(k > 0)
|
||||||
|
{
|
||||||
PushBack(k);
|
PushBack(k);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& operator<<=(size_t shift) {
|
BigInteger & operator<<=(size_t shift)
|
||||||
if (IsZero() || shift == 0) return *this;
|
{
|
||||||
|
if(IsZero() || shift == 0)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
size_t offset = shift / kTypeBit;
|
size_t offset = shift / kTypeBit;
|
||||||
size_t interShift = shift % kTypeBit;
|
size_t interShift = shift % kTypeBit;
|
||||||
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||||
|
|
||||||
if (interShift == 0) {
|
if(interShift == 0)
|
||||||
|
{
|
||||||
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
||||||
count_ += offset;
|
count_ += offset;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
digits_[count_] = 0;
|
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_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
|
||||||
|
}
|
||||||
digits_[offset] = digits_[0] << interShift;
|
digits_[offset] = digits_[0] << interShift;
|
||||||
count_ += offset;
|
count_ += offset;
|
||||||
if(digits_[count_])
|
if(digits_[count_])
|
||||||
|
{
|
||||||
count_++;
|
count_++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::memset(digits_, 0, offset * sizeof(Type));
|
std::memset(digits_, 0, offset * sizeof(Type));
|
||||||
|
|
||||||
return *this;
|
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;
|
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;
|
return count_ == 1 && digits_[0] == rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger& MultiplyPow5(unsigned exp) {
|
BigInteger & MultiplyPow5(unsigned exp)
|
||||||
static const uint32_t kPow5[12] = {
|
{
|
||||||
|
static const uint32_t kPow5[12] =
|
||||||
|
{
|
||||||
5,
|
5,
|
||||||
5 * 5,
|
5 * 5,
|
||||||
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 * 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;
|
if(exp == 0)
|
||||||
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
|
return *this;
|
||||||
if (exp > 0) *this *= kPow5[exp - 1];
|
}
|
||||||
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute absolute difference of this and rhs.
|
// Compute absolute difference of this and rhs.
|
||||||
// Assume this != rhs
|
// Assume this != rhs
|
||||||
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
bool Difference(const BigInteger & rhs, BigInteger* out) const
|
||||||
|
{
|
||||||
int cmp = Compare(rhs);
|
int cmp = Compare(rhs);
|
||||||
RAPIDJSON_ASSERT(cmp != 0);
|
RAPIDJSON_ASSERT(cmp != 0);
|
||||||
const BigInteger* a, *b; // Makes a > b
|
const BigInteger* a, *b; // Makes a > b
|
||||||
bool ret;
|
bool ret;
|
||||||
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
if(cmp < 0)
|
||||||
else { a = this; b = &rhs; ret = false; }
|
{
|
||||||
|
a = &rhs;
|
||||||
|
b = this;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a = this;
|
||||||
|
b = &rhs;
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
Type borrow = 0;
|
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;
|
Type d = a->digits_[i] - borrow;
|
||||||
if(i < b->count_)
|
if(i < b->count_)
|
||||||
|
{
|
||||||
d -= b->digits_[i];
|
d -= b->digits_[i];
|
||||||
|
}
|
||||||
borrow = (d > a->digits_[i]) ? 1 : 0;
|
borrow = (d > a->digits_[i]) ? 1 : 0;
|
||||||
out->digits_[i] = d;
|
out->digits_[i] = d;
|
||||||
if(d != 0)
|
if(d != 0)
|
||||||
|
{
|
||||||
out->count_ = i + 1;
|
out->count_ = i + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Compare(const BigInteger& rhs) const {
|
int Compare(const BigInteger & rhs) const
|
||||||
|
{
|
||||||
if(count_ != rhs.count_)
|
if(count_ != rhs.count_)
|
||||||
|
{
|
||||||
return count_ < rhs.count_ ? -1 : 1;
|
return count_ < rhs.count_ ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
for(size_t i = count_; i-- > 0;)
|
for(size_t i = count_; i-- > 0;)
|
||||||
if(digits_[i] != rhs.digits_[i])
|
if(digits_[i] != rhs.digits_[i])
|
||||||
|
{
|
||||||
return digits_[i] < rhs.digits_[i] ? -1 : 1;
|
return digits_[i] < rhs.digits_[i] ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetCount() const { return count_; }
|
size_t GetCount() const
|
||||||
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
|
{
|
||||||
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
|
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:
|
private:
|
||||||
void AppendDecimal64(const char* begin, const char* end) {
|
void AppendDecimal64(const char* begin, const char* end)
|
||||||
|
{
|
||||||
uint64_t u = ParseUint64(begin, end);
|
uint64_t u = ParseUint64(begin, end);
|
||||||
if(IsZero())
|
if(IsZero())
|
||||||
|
{
|
||||||
*this = u;
|
*this = u;
|
||||||
else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
unsigned exp = static_cast<unsigned>(end - begin);
|
unsigned exp = static_cast<unsigned>(end - begin);
|
||||||
(MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
|
(MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushBack(Type digit) {
|
void PushBack(Type digit)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(count_ < kCapacity);
|
RAPIDJSON_ASSERT(count_ < kCapacity);
|
||||||
digits_[count_++] = digit;
|
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;
|
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');
|
RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
|
||||||
r = r * 10u + static_cast<unsigned>(*p - '0');
|
r = r * 10u + static_cast<unsigned>(*p - '0');
|
||||||
}
|
}
|
||||||
|
@ -246,11 +352,14 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume a * b + k < 2^128
|
// 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)
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
uint64_t low = _umul128(a, b, outHigh) + k;
|
uint64_t low = _umul128(a, b, outHigh) + k;
|
||||||
if(low < k)
|
if(low < k)
|
||||||
|
{
|
||||||
(*outHigh)++;
|
(*outHigh)++;
|
||||||
|
}
|
||||||
return low;
|
return low;
|
||||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||||
__extension__ typedef unsigned __int128 uint128;
|
__extension__ typedef unsigned __int128 uint128;
|
||||||
|
@ -264,13 +373,17 @@ private:
|
||||||
x1 += (x0 >> 32); // can't give carry
|
x1 += (x0 >> 32); // can't give carry
|
||||||
x1 += x2;
|
x1 += x2;
|
||||||
if(x1 < x2)
|
if(x1 < x2)
|
||||||
|
{
|
||||||
x3 += (static_cast<uint64_t>(1) << 32);
|
x3 += (static_cast<uint64_t>(1) << 32);
|
||||||
|
}
|
||||||
uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
|
uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
|
||||||
uint64_t hi = x3 + (x1 >> 32);
|
uint64_t hi = x3 + (x1 >> 32);
|
||||||
|
|
||||||
lo += k;
|
lo += k;
|
||||||
if(lo < k)
|
if(lo < k)
|
||||||
|
{
|
||||||
hi++;
|
hi++;
|
||||||
|
}
|
||||||
*outHigh = hi;
|
*outHigh = hi;
|
||||||
return lo;
|
return lo;
|
||||||
#endif
|
#endif
|
||||||
|
|
66
src/3rdparty/rapidjson/internal/diyfp.h
vendored
66
src/3rdparty/rapidjson/internal/diyfp.h
vendored
|
@ -28,7 +28,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
|
@ -40,39 +41,48 @@ RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(padded)
|
RAPIDJSON_DIAG_OFF(padded)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct DiyFp {
|
struct DiyFp
|
||||||
|
{
|
||||||
DiyFp() : f(), e() {}
|
DiyFp() : f(), e() {}
|
||||||
|
|
||||||
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
|
||||||
|
|
||||||
explicit DiyFp(double d) {
|
explicit DiyFp(double d)
|
||||||
union {
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
double d;
|
double d;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
} u = { d };
|
} u = { d };
|
||||||
|
|
||||||
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
|
||||||
uint64_t significand = (u.u64 & kDpSignificandMask);
|
uint64_t significand = (u.u64 & kDpSignificandMask);
|
||||||
if (biased_e != 0) {
|
if(biased_e != 0)
|
||||||
|
{
|
||||||
f = significand + kDpHiddenBit;
|
f = significand + kDpHiddenBit;
|
||||||
e = biased_e - kDpExponentBias;
|
e = biased_e - kDpExponentBias;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
f = significand;
|
f = significand;
|
||||||
e = kDpMinExponent + 1;
|
e = kDpMinExponent + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DiyFp operator-(const DiyFp& rhs) const {
|
DiyFp operator-(const DiyFp & rhs) const
|
||||||
|
{
|
||||||
return DiyFp(f - rhs.f, e);
|
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)
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
uint64_t h;
|
uint64_t h;
|
||||||
uint64_t l = _umul128(f, rhs.f, &h);
|
uint64_t l = _umul128(f, rhs.f, &h);
|
||||||
if(l & (uint64_t(1) << 63)) // rounding
|
if(l & (uint64_t(1) << 63)) // rounding
|
||||||
|
{
|
||||||
h++;
|
h++;
|
||||||
|
}
|
||||||
return DiyFp(h, e + rhs.e + 64);
|
return DiyFp(h, e + rhs.e + 64);
|
||||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
|
||||||
__extension__ typedef unsigned __int128 uint128;
|
__extension__ typedef unsigned __int128 uint128;
|
||||||
|
@ -80,7 +90,9 @@ struct DiyFp {
|
||||||
uint64_t h = static_cast<uint64_t>(p >> 64);
|
uint64_t h = static_cast<uint64_t>(p >> 64);
|
||||||
uint64_t l = static_cast<uint64_t>(p);
|
uint64_t l = static_cast<uint64_t>(p);
|
||||||
if(l & (uint64_t(1) << 63)) // rounding
|
if(l & (uint64_t(1) << 63)) // rounding
|
||||||
|
{
|
||||||
h++;
|
h++;
|
||||||
|
}
|
||||||
return DiyFp(h, e + rhs.e + 64);
|
return DiyFp(h, e + rhs.e + 64);
|
||||||
#else
|
#else
|
||||||
const uint64_t M32 = 0xFFFFFFFF;
|
const uint64_t M32 = 0xFFFFFFFF;
|
||||||
|
@ -98,7 +110,8 @@ struct DiyFp {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DiyFp Normalize() const {
|
DiyFp Normalize() const
|
||||||
|
{
|
||||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||||
unsigned long index;
|
unsigned long index;
|
||||||
_BitScanReverse64(&index, f);
|
_BitScanReverse64(&index, f);
|
||||||
|
@ -108,7 +121,8 @@ struct DiyFp {
|
||||||
return DiyFp(f << s, e - s);
|
return DiyFp(f << s, e - s);
|
||||||
#else
|
#else
|
||||||
DiyFp res = *this;
|
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.f <<= 1;
|
||||||
res.e--;
|
res.e--;
|
||||||
}
|
}
|
||||||
|
@ -116,9 +130,11 @@ struct DiyFp {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DiyFp NormalizeBoundary() const {
|
DiyFp NormalizeBoundary() const
|
||||||
|
{
|
||||||
DiyFp res = *this;
|
DiyFp res = *this;
|
||||||
while (!(res.f & (kDpHiddenBit << 1))) {
|
while(!(res.f & (kDpHiddenBit << 1)))
|
||||||
|
{
|
||||||
res.f <<= 1;
|
res.f <<= 1;
|
||||||
res.e--;
|
res.e--;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +143,8 @@ struct DiyFp {
|
||||||
return res;
|
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 pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
|
||||||
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
|
||||||
mi.f <<= mi.e - pl.e;
|
mi.f <<= mi.e - pl.e;
|
||||||
|
@ -136,8 +153,10 @@ struct DiyFp {
|
||||||
*minus = mi;
|
*minus = mi;
|
||||||
}
|
}
|
||||||
|
|
||||||
double ToDouble() const {
|
double ToDouble() const
|
||||||
union {
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
double d;
|
double d;
|
||||||
uint64_t u64;
|
uint64_t u64;
|
||||||
} u;
|
} u;
|
||||||
|
@ -161,9 +180,11 @@ struct DiyFp {
|
||||||
int e;
|
int e;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
inline DiyFp GetCachedPowerByIndex(size_t index)
|
||||||
|
{
|
||||||
// 10^-348, 10^-340, ..., 10^340
|
// 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(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||||
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
||||||
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
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(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
||||||
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
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,
|
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
||||||
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
|
||||||
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
|
||||||
|
@ -223,13 +245,16 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
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;
|
//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
|
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
|
||||||
int k = static_cast<int>(dk);
|
int k = static_cast<int>(dk);
|
||||||
if(dk - k > 0.0)
|
if(dk - k > 0.0)
|
||||||
|
{
|
||||||
k++;
|
k++;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
unsigned index = static_cast<unsigned>((k >> 3) + 1);
|
||||||
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
|
||||||
|
@ -237,7 +262,8 @@ inline DiyFp GetCachedPower(int e, int* K) {
|
||||||
return GetCachedPowerByIndex(index);
|
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;
|
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||||
*outExp = -348 + static_cast<int>(index) * 8;
|
*outExp = -348 + static_cast<int>(index) * 8;
|
||||||
return GetCachedPowerByIndex(index);
|
return GetCachedPowerByIndex(index);
|
||||||
|
|
196
src/3rdparty/rapidjson/internal/dtoa.h
vendored
196
src/3rdparty/rapidjson/internal/dtoa.h
vendored
|
@ -24,40 +24,71 @@
|
||||||
#include "ieee754.h"
|
#include "ieee754.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
RAPIDJSON_DIAG_PUSH
|
RAPIDJSON_DIAG_PUSH
|
||||||
RAPIDJSON_DIAG_OFF(effc++)
|
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_OFF(array -
|
||||||
|
bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
|
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 &&
|
while(rest < wp_w && delta - rest >= ten_kappa &&
|
||||||
(rest + ten_kappa < wp_w || /// closer
|
(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]--;
|
buffer[len - 1]--;
|
||||||
rest += ten_kappa;
|
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.
|
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
||||||
if (n < 10) return 1;
|
if(n < 10)
|
||||||
if (n < 100) return 2;
|
{
|
||||||
if (n < 1000) return 3;
|
return 1;
|
||||||
if (n < 10000) return 4;
|
}
|
||||||
if (n < 100000) return 5;
|
if(n < 100)
|
||||||
if (n < 1000000) return 6;
|
{
|
||||||
if (n < 10000000) return 7;
|
return 2;
|
||||||
if (n < 100000000) return 8;
|
}
|
||||||
|
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()
|
// Will not reach 10 digits in DigitGen()
|
||||||
//if (n < 1000000000) return 9;
|
//if (n < 1000000000) return 9;
|
||||||
//return 10;
|
//return 10;
|
||||||
return 9;
|
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 };
|
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 one(uint64_t(1) << -Mp.e, Mp.e);
|
||||||
const DiyFp wp_w = Mp - W;
|
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]
|
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||||
*len = 0;
|
*len = 0;
|
||||||
|
|
||||||
while (kappa > 0) {
|
while(kappa > 0)
|
||||||
|
{
|
||||||
uint32_t d = 0;
|
uint32_t d = 0;
|
||||||
switch (kappa) {
|
switch(kappa)
|
||||||
case 9: d = p1 / 100000000; p1 %= 100000000; break;
|
{
|
||||||
case 8: d = p1 / 10000000; p1 %= 10000000; break;
|
case 9:
|
||||||
case 7: d = p1 / 1000000; p1 %= 1000000; break;
|
d = p1 / 100000000;
|
||||||
case 6: d = p1 / 100000; p1 %= 100000; break;
|
p1 %= 100000000;
|
||||||
case 5: d = p1 / 10000; p1 %= 10000; break;
|
break;
|
||||||
case 4: d = p1 / 1000; p1 %= 1000; break;
|
case 8:
|
||||||
case 3: d = p1 / 100; p1 %= 100; break;
|
d = p1 / 10000000;
|
||||||
case 2: d = p1 / 10; p1 %= 10; break;
|
p1 %= 10000000;
|
||||||
case 1: d = p1; p1 = 0; break;
|
break;
|
||||||
default:;
|
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));
|
buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
|
||||||
|
}
|
||||||
kappa--;
|
kappa--;
|
||||||
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
||||||
if (tmp <= delta) {
|
if(tmp <= delta)
|
||||||
|
{
|
||||||
*K += kappa;
|
*K += kappa;
|
||||||
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
|
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
|
||||||
return;
|
return;
|
||||||
|
@ -92,15 +156,19 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
||||||
}
|
}
|
||||||
|
|
||||||
// kappa = 0
|
// kappa = 0
|
||||||
for (;;) {
|
for(;;)
|
||||||
|
{
|
||||||
p2 *= 10;
|
p2 *= 10;
|
||||||
delta *= 10;
|
delta *= 10;
|
||||||
char d = static_cast<char>(p2 >> -one.e);
|
char d = static_cast<char>(p2 >> -one.e);
|
||||||
if(d || *len)
|
if(d || *len)
|
||||||
|
{
|
||||||
buffer[(*len)++] = static_cast<char>('0' + d);
|
buffer[(*len)++] = static_cast<char>('0' + d);
|
||||||
|
}
|
||||||
p2 &= one.f - 1;
|
p2 &= one.f - 1;
|
||||||
kappa--;
|
kappa--;
|
||||||
if (p2 < delta) {
|
if(p2 < delta)
|
||||||
|
{
|
||||||
*K += kappa;
|
*K += kappa;
|
||||||
int index = -static_cast<int>(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));
|
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
|
||||||
|
@ -109,7 +177,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
const DiyFp v(value);
|
||||||
DiyFp w_m, w_p;
|
DiyFp w_m, w_p;
|
||||||
v.NormalizedBoundaries(&w_m, &w_p);
|
v.NormalizedBoundaries(&w_m, &w_p);
|
||||||
|
@ -123,88 +192,115 @@ inline void Grisu2(double value, char* buffer, int* length, int* K) {
|
||||||
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* WriteExponent(int K, char* buffer) {
|
inline char* WriteExponent(int K, char* buffer)
|
||||||
if (K < 0) {
|
{
|
||||||
|
if(K < 0)
|
||||||
|
{
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
K = -K;
|
K = -K;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K >= 100) {
|
if(K >= 100)
|
||||||
|
{
|
||||||
*buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
|
*buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
|
||||||
K %= 100;
|
K %= 100;
|
||||||
const char* d = GetDigitsLut() + K * 2;
|
const char* d = GetDigitsLut() + K * 2;
|
||||||
*buffer++ = d[0];
|
*buffer++ = d[0];
|
||||||
*buffer++ = d[1];
|
*buffer++ = d[1];
|
||||||
}
|
}
|
||||||
else if (K >= 10) {
|
else if(K >= 10)
|
||||||
|
{
|
||||||
const char* d = GetDigitsLut() + K * 2;
|
const char* d = GetDigitsLut() + K * 2;
|
||||||
*buffer++ = d[0];
|
*buffer++ = d[0];
|
||||||
*buffer++ = d[1];
|
*buffer++ = d[1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
|
*buffer++ = static_cast<char>('0' + static_cast<char>(K));
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
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
|
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
||||||
|
|
||||||
if (0 <= k && kk <= 21) {
|
if(0 <= k && kk <= 21)
|
||||||
|
{
|
||||||
// 1234e7 -> 12340000000
|
// 1234e7 -> 12340000000
|
||||||
for(int i = length; i < kk; i++)
|
for(int i = length; i < kk; i++)
|
||||||
|
{
|
||||||
buffer[i] = '0';
|
buffer[i] = '0';
|
||||||
|
}
|
||||||
buffer[kk] = '.';
|
buffer[kk] = '.';
|
||||||
buffer[kk + 1] = '0';
|
buffer[kk + 1] = '0';
|
||||||
return &buffer[kk + 2];
|
return &buffer[kk + 2];
|
||||||
}
|
}
|
||||||
else if (0 < kk && kk <= 21) {
|
else if(0 < kk && kk <= 21)
|
||||||
|
{
|
||||||
// 1234e-2 -> 12.34
|
// 1234e-2 -> 12.34
|
||||||
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
|
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
|
||||||
buffer[kk] = '.';
|
buffer[kk] = '.';
|
||||||
if (0 > k + maxDecimalPlaces) {
|
if(0 > k + maxDecimalPlaces)
|
||||||
|
{
|
||||||
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
|
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
|
||||||
// Remove extra trailing zeros (at least one) after truncation.
|
// Remove extra trailing zeros (at least one) after truncation.
|
||||||
for(int i = kk + maxDecimalPlaces; i > kk + 1; i--)
|
for(int i = kk + maxDecimalPlaces; i > kk + 1; i--)
|
||||||
if(buffer[i] != '0')
|
if(buffer[i] != '0')
|
||||||
|
{
|
||||||
return &buffer[i + 1];
|
return &buffer[i + 1];
|
||||||
|
}
|
||||||
return &buffer[kk + 2]; // Reserve one zero
|
return &buffer[kk + 2]; // Reserve one zero
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return &buffer[length + 1];
|
return &buffer[length + 1];
|
||||||
}
|
}
|
||||||
else if (-6 < kk && kk <= 0) {
|
}
|
||||||
|
else if(-6 < kk && kk <= 0)
|
||||||
|
{
|
||||||
// 1234e-6 -> 0.001234
|
// 1234e-6 -> 0.001234
|
||||||
const int offset = 2 - kk;
|
const int offset = 2 - kk;
|
||||||
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
|
std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
buffer[1] = '.';
|
buffer[1] = '.';
|
||||||
for(int i = 2; i < offset; i++)
|
for(int i = 2; i < offset; i++)
|
||||||
|
{
|
||||||
buffer[i] = '0';
|
buffer[i] = '0';
|
||||||
if (length - kk > maxDecimalPlaces) {
|
}
|
||||||
|
if(length - kk > maxDecimalPlaces)
|
||||||
|
{
|
||||||
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
|
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
|
||||||
// Remove extra trailing zeros (at least one) after truncation.
|
// Remove extra trailing zeros (at least one) after truncation.
|
||||||
for(int i = maxDecimalPlaces + 1; i > 2; i--)
|
for(int i = maxDecimalPlaces + 1; i > 2; i--)
|
||||||
if(buffer[i] != '0')
|
if(buffer[i] != '0')
|
||||||
|
{
|
||||||
return &buffer[i + 1];
|
return &buffer[i + 1];
|
||||||
|
}
|
||||||
return &buffer[3]; // Reserve one zero
|
return &buffer[3]; // Reserve one zero
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return &buffer[length + offset];
|
return &buffer[length + offset];
|
||||||
}
|
}
|
||||||
else if (kk < -maxDecimalPlaces) {
|
}
|
||||||
|
else if(kk < -maxDecimalPlaces)
|
||||||
|
{
|
||||||
// Truncate to zero
|
// Truncate to zero
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
buffer[1] = '.';
|
buffer[1] = '.';
|
||||||
buffer[2] = '0';
|
buffer[2] = '0';
|
||||||
return &buffer[3];
|
return &buffer[3];
|
||||||
}
|
}
|
||||||
else if (length == 1) {
|
else if(length == 1)
|
||||||
|
{
|
||||||
// 1e30
|
// 1e30
|
||||||
buffer[1] = 'e';
|
buffer[1] = 'e';
|
||||||
return WriteExponent(kk - 1, &buffer[2]);
|
return WriteExponent(kk - 1, &buffer[2]);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// 1234e30 -> 1.234e33
|
// 1234e30 -> 1.234e33
|
||||||
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
|
std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
|
||||||
buffer[1] = '.';
|
buffer[1] = '.';
|
||||||
|
@ -213,19 +309,25 @@ inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
||||||
Double d(value);
|
Double d(value);
|
||||||
if (d.IsZero()) {
|
if(d.IsZero())
|
||||||
|
{
|
||||||
if(d.Sign())
|
if(d.Sign())
|
||||||
|
{
|
||||||
*buffer++ = '-'; // -0.0, Issue #289
|
*buffer++ = '-'; // -0.0, Issue #289
|
||||||
|
}
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
buffer[1] = '.';
|
buffer[1] = '.';
|
||||||
buffer[2] = '0';
|
buffer[2] = '0';
|
||||||
return &buffer[3];
|
return &buffer[3];
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (value < 0) {
|
{
|
||||||
|
if(value < 0)
|
||||||
|
{
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
|
|
86
src/3rdparty/rapidjson/internal/ieee754.h
vendored
86
src/3rdparty/rapidjson/internal/ieee754.h
vendored
|
@ -18,44 +18,93 @@
|
||||||
#include "../rapidjson.h"
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
class Double {
|
class Double
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Double() {}
|
Double() {}
|
||||||
Double(double d) : d_(d) {}
|
Double(double d) : d_(d) {}
|
||||||
Double(uint64_t u) : u_(u) {}
|
Double(uint64_t u) : u_(u) {}
|
||||||
|
|
||||||
double Value() const { return d_; }
|
double Value() const
|
||||||
uint64_t Uint64Value() const { return u_; }
|
{
|
||||||
|
return d_;
|
||||||
|
}
|
||||||
|
uint64_t Uint64Value() const
|
||||||
|
{
|
||||||
|
return u_;
|
||||||
|
}
|
||||||
|
|
||||||
double NextPositiveDouble() const {
|
double NextPositiveDouble() const
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(!Sign());
|
RAPIDJSON_ASSERT(!Sign());
|
||||||
return Double(u_ + 1).Value();
|
return Double(u_ + 1).Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sign() const { return (u_ & kSignMask) != 0; }
|
bool Sign() const
|
||||||
uint64_t Significand() const { return u_ & kSignificandMask; }
|
{
|
||||||
int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
|
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 IsNan() const
|
||||||
bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
|
{
|
||||||
bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
|
return (u_ & kExponentMask) == kExponentMask && Significand() != 0;
|
||||||
bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
|
}
|
||||||
bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 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(); }
|
uint64_t IntegerSignificand() const
|
||||||
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
{
|
||||||
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
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) {
|
static unsigned EffectiveSignificandSize(int order)
|
||||||
|
{
|
||||||
if(order >= -1021)
|
if(order >= -1021)
|
||||||
|
{
|
||||||
return 53;
|
return 53;
|
||||||
|
}
|
||||||
else if(order <= -1074)
|
else if(order <= -1074)
|
||||||
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return static_cast<unsigned>(order) + 1074;
|
return static_cast<unsigned>(order) + 1074;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kSignificandSize = 52;
|
static const int kSignificandSize = 52;
|
||||||
|
@ -66,7 +115,8 @@ private:
|
||||||
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||||
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||||
|
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
double d_;
|
double d_;
|
||||||
uint64_t u_;
|
uint64_t u_;
|
||||||
};
|
};
|
||||||
|
|
107
src/3rdparty/rapidjson/internal/itoa.h
vendored
107
src/3rdparty/rapidjson/internal/itoa.h
vendored
|
@ -18,10 +18,13 @@
|
||||||
#include "../rapidjson.h"
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
inline const char* GetDigitsLut() {
|
inline const char* GetDigitsLut()
|
||||||
static const char cDigitsLut[200] = {
|
{
|
||||||
|
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',
|
'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',
|
'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',
|
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
|
||||||
|
@ -36,22 +39,31 @@ inline const char* GetDigitsLut() {
|
||||||
return cDigitsLut;
|
return cDigitsLut;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char* u32toa(uint32_t value, char* buffer) {
|
inline char* u32toa(uint32_t value, char* buffer)
|
||||||
|
{
|
||||||
const char* cDigitsLut = GetDigitsLut();
|
const char* cDigitsLut = GetDigitsLut();
|
||||||
|
|
||||||
if (value < 10000) {
|
if(value < 10000)
|
||||||
|
{
|
||||||
const uint32_t d1 = (value / 100) << 1;
|
const uint32_t d1 = (value / 100) << 1;
|
||||||
const uint32_t d2 = (value % 100) << 1;
|
const uint32_t d2 = (value % 100) << 1;
|
||||||
|
|
||||||
if(value >= 1000)
|
if(value >= 1000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1];
|
*buffer++ = cDigitsLut[d1];
|
||||||
|
}
|
||||||
if(value >= 100)
|
if(value >= 100)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1 + 1];
|
*buffer++ = cDigitsLut[d1 + 1];
|
||||||
|
}
|
||||||
if(value >= 10)
|
if(value >= 10)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d2];
|
*buffer++ = cDigitsLut[d2];
|
||||||
|
}
|
||||||
*buffer++ = cDigitsLut[d2 + 1];
|
*buffer++ = cDigitsLut[d2 + 1];
|
||||||
}
|
}
|
||||||
else if (value < 100000000) {
|
else if(value < 100000000)
|
||||||
|
{
|
||||||
// value = bbbbcccc
|
// value = bbbbcccc
|
||||||
const uint32_t b = value / 10000;
|
const uint32_t b = value / 10000;
|
||||||
const uint32_t c = value % 10000;
|
const uint32_t c = value % 10000;
|
||||||
|
@ -63,11 +75,17 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||||
const uint32_t d4 = (c % 100) << 1;
|
const uint32_t d4 = (c % 100) << 1;
|
||||||
|
|
||||||
if(value >= 10000000)
|
if(value >= 10000000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1];
|
*buffer++ = cDigitsLut[d1];
|
||||||
|
}
|
||||||
if(value >= 1000000)
|
if(value >= 1000000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1 + 1];
|
*buffer++ = cDigitsLut[d1 + 1];
|
||||||
|
}
|
||||||
if(value >= 100000)
|
if(value >= 100000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d2];
|
*buffer++ = cDigitsLut[d2];
|
||||||
|
}
|
||||||
*buffer++ = cDigitsLut[d2 + 1];
|
*buffer++ = cDigitsLut[d2 + 1];
|
||||||
|
|
||||||
*buffer++ = cDigitsLut[d3];
|
*buffer++ = cDigitsLut[d3];
|
||||||
|
@ -75,19 +93,23 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||||
*buffer++ = cDigitsLut[d4];
|
*buffer++ = cDigitsLut[d4];
|
||||||
*buffer++ = cDigitsLut[d4 + 1];
|
*buffer++ = cDigitsLut[d4 + 1];
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// value = aabbbbcccc in decimal
|
// value = aabbbbcccc in decimal
|
||||||
|
|
||||||
const uint32_t a = value / 100000000; // 1 to 42
|
const uint32_t a = value / 100000000; // 1 to 42
|
||||||
value %= 100000000;
|
value %= 100000000;
|
||||||
|
|
||||||
if (a >= 10) {
|
if(a >= 10)
|
||||||
|
{
|
||||||
const unsigned i = a << 1;
|
const unsigned i = a << 1;
|
||||||
*buffer++ = cDigitsLut[i];
|
*buffer++ = cDigitsLut[i];
|
||||||
*buffer++ = cDigitsLut[i + 1];
|
*buffer++ = cDigitsLut[i + 1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t b = value / 10000; // 0 to 9999
|
const uint32_t b = value / 10000; // 0 to 9999
|
||||||
const uint32_t c = value % 10000; // 0 to 9999
|
const uint32_t c = value % 10000; // 0 to 9999
|
||||||
|
@ -110,9 +132,11 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||||
return buffer;
|
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);
|
uint32_t u = static_cast<uint32_t>(value);
|
||||||
if (value < 0) {
|
if(value < 0)
|
||||||
|
{
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
u = ~u + 1;
|
u = ~u + 1;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +144,8 @@ inline char* i32toa(int32_t value, char* buffer) {
|
||||||
return u32toa(u, buffer);
|
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 char* cDigitsLut = GetDigitsLut();
|
||||||
const uint64_t kTen8 = 100000000;
|
const uint64_t kTen8 = 100000000;
|
||||||
const uint64_t kTen9 = kTen8 * 10;
|
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 kTen15 = kTen8 * 10000000;
|
||||||
const uint64_t kTen16 = kTen8 * kTen8;
|
const uint64_t kTen16 = kTen8 * kTen8;
|
||||||
|
|
||||||
if (value < kTen8) {
|
if(value < kTen8)
|
||||||
|
{
|
||||||
uint32_t v = static_cast<uint32_t>(value);
|
uint32_t v = static_cast<uint32_t>(value);
|
||||||
if (v < 10000) {
|
if(v < 10000)
|
||||||
|
{
|
||||||
const uint32_t d1 = (v / 100) << 1;
|
const uint32_t d1 = (v / 100) << 1;
|
||||||
const uint32_t d2 = (v % 100) << 1;
|
const uint32_t d2 = (v % 100) << 1;
|
||||||
|
|
||||||
if(v >= 1000)
|
if(v >= 1000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1];
|
*buffer++ = cDigitsLut[d1];
|
||||||
|
}
|
||||||
if(v >= 100)
|
if(v >= 100)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1 + 1];
|
*buffer++ = cDigitsLut[d1 + 1];
|
||||||
|
}
|
||||||
if(v >= 10)
|
if(v >= 10)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d2];
|
*buffer++ = cDigitsLut[d2];
|
||||||
|
}
|
||||||
*buffer++ = cDigitsLut[d2 + 1];
|
*buffer++ = cDigitsLut[d2 + 1];
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
// value = bbbbcccc
|
// value = bbbbcccc
|
||||||
const uint32_t b = v / 10000;
|
const uint32_t b = v / 10000;
|
||||||
const uint32_t c = v % 10000;
|
const uint32_t c = v % 10000;
|
||||||
|
@ -158,11 +192,17 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
const uint32_t d4 = (c % 100) << 1;
|
const uint32_t d4 = (c % 100) << 1;
|
||||||
|
|
||||||
if(value >= 10000000)
|
if(value >= 10000000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1];
|
*buffer++ = cDigitsLut[d1];
|
||||||
|
}
|
||||||
if(value >= 1000000)
|
if(value >= 1000000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1 + 1];
|
*buffer++ = cDigitsLut[d1 + 1];
|
||||||
|
}
|
||||||
if(value >= 100000)
|
if(value >= 100000)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d2];
|
*buffer++ = cDigitsLut[d2];
|
||||||
|
}
|
||||||
*buffer++ = cDigitsLut[d2 + 1];
|
*buffer++ = cDigitsLut[d2 + 1];
|
||||||
|
|
||||||
*buffer++ = cDigitsLut[d3];
|
*buffer++ = cDigitsLut[d3];
|
||||||
|
@ -171,7 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
*buffer++ = cDigitsLut[d4 + 1];
|
*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 v0 = static_cast<uint32_t>(value / kTen8);
|
||||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||||
|
|
||||||
|
@ -194,21 +235,37 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
const uint32_t d8 = (c1 % 100) << 1;
|
const uint32_t d8 = (c1 % 100) << 1;
|
||||||
|
|
||||||
if(value >= kTen15)
|
if(value >= kTen15)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1];
|
*buffer++ = cDigitsLut[d1];
|
||||||
|
}
|
||||||
if(value >= kTen14)
|
if(value >= kTen14)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d1 + 1];
|
*buffer++ = cDigitsLut[d1 + 1];
|
||||||
|
}
|
||||||
if(value >= kTen13)
|
if(value >= kTen13)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d2];
|
*buffer++ = cDigitsLut[d2];
|
||||||
|
}
|
||||||
if(value >= kTen12)
|
if(value >= kTen12)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d2 + 1];
|
*buffer++ = cDigitsLut[d2 + 1];
|
||||||
|
}
|
||||||
if(value >= kTen11)
|
if(value >= kTen11)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d3];
|
*buffer++ = cDigitsLut[d3];
|
||||||
|
}
|
||||||
if(value >= kTen10)
|
if(value >= kTen10)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d3 + 1];
|
*buffer++ = cDigitsLut[d3 + 1];
|
||||||
|
}
|
||||||
if(value >= kTen9)
|
if(value >= kTen9)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d4];
|
*buffer++ = cDigitsLut[d4];
|
||||||
|
}
|
||||||
if(value >= kTen8)
|
if(value >= kTen8)
|
||||||
|
{
|
||||||
*buffer++ = cDigitsLut[d4 + 1];
|
*buffer++ = cDigitsLut[d4 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
*buffer++ = cDigitsLut[d5];
|
*buffer++ = cDigitsLut[d5];
|
||||||
*buffer++ = cDigitsLut[d5 + 1];
|
*buffer++ = cDigitsLut[d5 + 1];
|
||||||
|
@ -219,25 +276,31 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
*buffer++ = cDigitsLut[d8];
|
*buffer++ = cDigitsLut[d8];
|
||||||
*buffer++ = cDigitsLut[d8 + 1];
|
*buffer++ = cDigitsLut[d8 + 1];
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
|
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
|
||||||
value %= kTen16;
|
value %= kTen16;
|
||||||
|
|
||||||
if(a < 10)
|
if(a < 10)
|
||||||
|
{
|
||||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
||||||
else if (a < 100) {
|
}
|
||||||
|
else if(a < 100)
|
||||||
|
{
|
||||||
const uint32_t i = a << 1;
|
const uint32_t i = a << 1;
|
||||||
*buffer++ = cDigitsLut[i];
|
*buffer++ = cDigitsLut[i];
|
||||||
*buffer++ = cDigitsLut[i + 1];
|
*buffer++ = cDigitsLut[i + 1];
|
||||||
}
|
}
|
||||||
else if (a < 1000) {
|
else if(a < 1000)
|
||||||
|
{
|
||||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
|
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
|
||||||
|
|
||||||
const uint32_t i = (a % 100) << 1;
|
const uint32_t i = (a % 100) << 1;
|
||||||
*buffer++ = cDigitsLut[i];
|
*buffer++ = cDigitsLut[i];
|
||||||
*buffer++ = cDigitsLut[i + 1];
|
*buffer++ = cDigitsLut[i + 1];
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
const uint32_t i = (a / 100) << 1;
|
const uint32_t i = (a / 100) << 1;
|
||||||
const uint32_t j = (a % 100) << 1;
|
const uint32_t j = (a % 100) << 1;
|
||||||
*buffer++ = cDigitsLut[i];
|
*buffer++ = cDigitsLut[i];
|
||||||
|
@ -288,9 +351,11 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||||
return 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);
|
uint64_t u = static_cast<uint64_t>(value);
|
||||||
if (value < 0) {
|
if(value < 0)
|
||||||
|
{
|
||||||
*buffer++ = '-';
|
*buffer++ = '-';
|
||||||
u = ~u + 1;
|
u = ~u + 1;
|
||||||
}
|
}
|
||||||
|
|
73
src/3rdparty/rapidjson/internal/meta.h
vendored
73
src/3rdparty/rapidjson/internal/meta.h
vendored
|
@ -32,15 +32,20 @@ RAPIDJSON_DIAG_OFF(6334)
|
||||||
|
|
||||||
//@cond RAPIDJSON_INTERNAL
|
//@cond RAPIDJSON_INTERNAL
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
||||||
template <typename T> struct Void { typedef void Type; };
|
template <typename T> struct Void
|
||||||
|
{
|
||||||
|
typedef void Type;
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// BoolType, TrueType, FalseType
|
// BoolType, TrueType, FalseType
|
||||||
//
|
//
|
||||||
template <bool Cond> struct BoolType {
|
template <bool Cond> struct BoolType
|
||||||
|
{
|
||||||
static const bool Value = Cond;
|
static const bool Value = Cond;
|
||||||
typedef BoolType Type;
|
typedef BoolType Type;
|
||||||
};
|
};
|
||||||
|
@ -52,8 +57,20 @@ 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 <bool C> struct SelectIfImpl
|
||||||
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
|
{
|
||||||
|
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 <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 <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
|
||||||
|
|
||||||
|
@ -70,10 +87,19 @@ template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::V
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// AddConst, MaybeAddConst, RemoveConst
|
// AddConst, MaybeAddConst, RemoveConst
|
||||||
template <typename T> struct AddConst { typedef const T Type; };
|
template <typename T> struct AddConst
|
||||||
|
{
|
||||||
|
typedef const T Type;
|
||||||
|
};
|
||||||
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
|
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
|
||||||
template <typename T> struct RemoveConst<const T> { typedef T Type; };
|
{
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
template <typename T> struct RemoveConst<const T>
|
||||||
|
{
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -103,7 +129,8 @@ template <typename B, typename D> struct IsBaseOf
|
||||||
|
|
||||||
#else // simplified version adopted from Boost
|
#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(B) != 0);
|
||||||
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
||||||
|
|
||||||
|
@ -114,7 +141,8 @@ template<typename B, typename D> struct IsBaseOfImpl {
|
||||||
static Yes Check(const D*, T);
|
static Yes Check(const D*, T);
|
||||||
static No Check(const B*, int);
|
static No Check(const B*, int);
|
||||||
|
|
||||||
struct Host {
|
struct Host
|
||||||
|
{
|
||||||
operator const B* () const;
|
operator const B* () const;
|
||||||
operator const D* ();
|
operator const D* ();
|
||||||
};
|
};
|
||||||
|
@ -131,11 +159,23 @@ template <typename B, typename D> struct IsBaseOf
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// EnableIf / DisableIf
|
// EnableIf / DisableIf
|
||||||
//
|
//
|
||||||
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
|
template <bool Condition, typename T = void> struct EnableIfCond
|
||||||
template <typename T> struct EnableIfCond<false, T> { /* empty */ };
|
{
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
template <typename T> struct EnableIfCond<false, T>
|
||||||
|
{
|
||||||
|
/* empty */
|
||||||
|
};
|
||||||
|
|
||||||
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
|
template <bool Condition, typename T = void> struct DisableIfCond
|
||||||
template <typename T> struct DisableIfCond<true, T> { /* empty */ };
|
{
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
template <typename T> struct DisableIfCond<true, T>
|
||||||
|
{
|
||||||
|
/* empty */
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Condition, typename T = void>
|
template <typename Condition, typename T = void>
|
||||||
struct EnableIf : EnableIfCond<Condition::Value, T> {};
|
struct EnableIf : EnableIfCond<Condition::Value, T> {};
|
||||||
|
@ -146,7 +186,10 @@ struct DisableIf : DisableIfCond<Condition::Value, T> {};
|
||||||
// SFINAE helpers
|
// SFINAE helpers
|
||||||
struct SfinaeTag {};
|
struct SfinaeTag {};
|
||||||
template <typename T> struct RemoveSfinaeTag;
|
template <typename T> struct RemoveSfinaeTag;
|
||||||
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
|
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)>
|
||||||
|
{
|
||||||
|
typedef T Type;
|
||||||
|
};
|
||||||
|
|
||||||
#define RAPIDJSON_REMOVEFPTR_(type) \
|
#define RAPIDJSON_REMOVEFPTR_(type) \
|
||||||
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
||||||
|
|
9
src/3rdparty/rapidjson/internal/pow10.h
vendored
9
src/3rdparty/rapidjson/internal/pow10.h
vendored
|
@ -18,15 +18,18 @@
|
||||||
#include "../rapidjson.h"
|
#include "../rapidjson.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
//! Computes integer powers of 10 in double (10.0^n).
|
//! Computes integer powers of 10 in double (10.0^n).
|
||||||
/*! This function uses lookup table for fast and accurate results.
|
/*! This function uses lookup table for fast and accurate results.
|
||||||
\param n non-negative exponent. Must <= 308.
|
\param n non-negative exponent. Must <= 308.
|
||||||
\return 10.0^n
|
\return 10.0^n
|
||||||
*/
|
*/
|
||||||
inline double Pow10(int n) {
|
inline double Pow10(int n)
|
||||||
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
|
{
|
||||||
|
static const double e[] = // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
|
||||||
|
{
|
||||||
1e+0,
|
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+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+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,
|
||||||
|
|
352
src/3rdparty/rapidjson/internal/regex.h
vendored
352
src/3rdparty/rapidjson/internal/regex.h
vendored
|
@ -41,12 +41,14 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// GenericRegex
|
// GenericRegex
|
||||||
|
|
||||||
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
static const SizeType kRegexInvalidState = ~SizeType(
|
||||||
|
0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
||||||
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||||
|
|
||||||
//! Regular expression engine with subset of ECMAscript grammar.
|
//! Regular expression engine with subset of ECMAscript grammar.
|
||||||
|
@ -82,7 +84,8 @@ static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||||
https://swtch.com/~rsc/regexp/regexp1.html
|
https://swtch.com/~rsc/regexp/regexp1.html
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||||
class GenericRegex {
|
class GenericRegex
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
|
@ -95,36 +98,43 @@ public:
|
||||||
Parse(ds);
|
Parse(ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
~GenericRegex() {
|
~GenericRegex()
|
||||||
|
{
|
||||||
Allocator::Free(stateSet_);
|
Allocator::Free(stateSet_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid() const {
|
bool IsValid() const
|
||||||
|
{
|
||||||
return root_ != kRegexInvalidState;
|
return root_ != kRegexInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
bool Match(InputStream& is) const {
|
bool Match(InputStream & is) const
|
||||||
|
{
|
||||||
return SearchWithAnchoring(is, true, true);
|
return SearchWithAnchoring(is, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Match(const Ch* s) const {
|
bool Match(const Ch* s) const
|
||||||
|
{
|
||||||
GenericStringStream<Encoding> is(s);
|
GenericStringStream<Encoding> is(s);
|
||||||
return Match(is);
|
return Match(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
bool Search(InputStream& is) const {
|
bool Search(InputStream & is) const
|
||||||
|
{
|
||||||
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
|
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Search(const Ch* s) const {
|
bool Search(const Ch* s) const
|
||||||
|
{
|
||||||
GenericStringStream<Encoding> is(s);
|
GenericStringStream<Encoding> is(s);
|
||||||
return Search(is);
|
return Search(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Operator {
|
enum Operator
|
||||||
|
{
|
||||||
kZeroOrOne,
|
kZeroOrOne,
|
||||||
kZeroOrMore,
|
kZeroOrMore,
|
||||||
kOneOrMore,
|
kOneOrMore,
|
||||||
|
@ -137,20 +147,23 @@ private:
|
||||||
static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
|
static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
|
||||||
static const unsigned kRangeNegationFlag = 0x80000000;
|
static const unsigned kRangeNegationFlag = 0x80000000;
|
||||||
|
|
||||||
struct Range {
|
struct Range
|
||||||
|
{
|
||||||
unsigned start; //
|
unsigned start; //
|
||||||
unsigned end;
|
unsigned end;
|
||||||
SizeType next;
|
SizeType next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct State {
|
struct State
|
||||||
|
{
|
||||||
SizeType out; //!< Equals to kInvalid for matching state
|
SizeType out; //!< Equals to kInvalid for matching state
|
||||||
SizeType out1; //!< Equals to non-kInvalid for split
|
SizeType out1; //!< Equals to non-kInvalid for split
|
||||||
SizeType rangeStart;
|
SizeType rangeStart;
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Frag {
|
struct Frag
|
||||||
|
{
|
||||||
Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
|
Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
|
||||||
SizeType start;
|
SizeType start;
|
||||||
SizeType out; //!< link-list of all output states
|
SizeType out; //!< link-list of all output states
|
||||||
|
@ -158,49 +171,67 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename SourceStream>
|
template <typename SourceStream>
|
||||||
class DecodedStream {
|
class DecodedStream
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
DecodedStream(SourceStream & ss) : ss_(ss), codepoint_()
|
||||||
unsigned Peek() { return codepoint_; }
|
{
|
||||||
unsigned Take() {
|
Decode();
|
||||||
|
}
|
||||||
|
unsigned Peek()
|
||||||
|
{
|
||||||
|
return codepoint_;
|
||||||
|
}
|
||||||
|
unsigned Take()
|
||||||
|
{
|
||||||
unsigned c = codepoint_;
|
unsigned c = codepoint_;
|
||||||
if(c) // No further decoding when '\0'
|
if(c) // No further decoding when '\0'
|
||||||
|
{
|
||||||
Decode();
|
Decode();
|
||||||
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Decode() {
|
void Decode()
|
||||||
|
{
|
||||||
if(!Encoding::Decode(ss_, &codepoint_))
|
if(!Encoding::Decode(ss_, &codepoint_))
|
||||||
|
{
|
||||||
codepoint_ = 0;
|
codepoint_ = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SourceStream & ss_;
|
SourceStream & ss_;
|
||||||
unsigned codepoint_;
|
unsigned codepoint_;
|
||||||
};
|
};
|
||||||
|
|
||||||
State& GetState(SizeType index) {
|
State & GetState(SizeType index)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(index < stateCount_);
|
RAPIDJSON_ASSERT(index < stateCount_);
|
||||||
return states_.template Bottom<State>()[index];
|
return states_.template Bottom<State>()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const State& GetState(SizeType index) const {
|
const State & GetState(SizeType index) const
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(index < stateCount_);
|
RAPIDJSON_ASSERT(index < stateCount_);
|
||||||
return states_.template Bottom<State>()[index];
|
return states_.template Bottom<State>()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Range& GetRange(SizeType index) {
|
Range & GetRange(SizeType index)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(index < rangeCount_);
|
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||||
return ranges_.template Bottom<Range>()[index];
|
return ranges_.template Bottom<Range>()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Range& GetRange(SizeType index) const {
|
const Range & GetRange(SizeType index) const
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(index < rangeCount_);
|
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||||
return ranges_.template Bottom<Range>()[index];
|
return ranges_.template Bottom<Range>()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
void Parse(DecodedStream<InputStream>& ds) {
|
void Parse(DecodedStream<InputStream> & ds)
|
||||||
|
{
|
||||||
Allocator allocator;
|
Allocator allocator;
|
||||||
Stack<Allocator> operandStack(&allocator, 256); // Frag
|
Stack<Allocator> operandStack(&allocator, 256); // Frag
|
||||||
Stack<Allocator> operatorStack(&allocator, 256); // Operator
|
Stack<Allocator> operatorStack(&allocator, 256); // Operator
|
||||||
|
@ -209,8 +240,10 @@ private:
|
||||||
*atomCountStack.template Push<unsigned>() = 0;
|
*atomCountStack.template Push<unsigned>() = 0;
|
||||||
|
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
while (ds.Peek() != 0) {
|
while(ds.Peek() != 0)
|
||||||
switch (codepoint = ds.Take()) {
|
{
|
||||||
|
switch(codepoint = ds.Take())
|
||||||
|
{
|
||||||
case '^':
|
case '^':
|
||||||
anchorBegin_ = true;
|
anchorBegin_ = true;
|
||||||
break;
|
break;
|
||||||
|
@ -222,7 +255,9 @@ private:
|
||||||
case '|':
|
case '|':
|
||||||
while(!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
|
while(!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
|
||||||
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
*operatorStack.template Push<Operator>() = kAlternation;
|
*operatorStack.template Push<Operator>() = kAlternation;
|
||||||
*atomCountStack.template Top<unsigned>() = 0;
|
*atomCountStack.template Top<unsigned>() = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -235,9 +270,13 @@ private:
|
||||||
case ')':
|
case ')':
|
||||||
while(!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
|
while(!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
|
||||||
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if(operatorStack.Empty())
|
if(operatorStack.Empty())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
operatorStack.template Pop<Operator>(1);
|
operatorStack.template Pop<Operator>(1);
|
||||||
atomCountStack.template Pop<unsigned>(1);
|
atomCountStack.template Pop<unsigned>(1);
|
||||||
ImplicitConcatenation(atomCountStack, operatorStack);
|
ImplicitConcatenation(atomCountStack, operatorStack);
|
||||||
|
@ -245,37 +284,54 @@ private:
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
if(!Eval(operandStack, kZeroOrOne))
|
if(!Eval(operandStack, kZeroOrOne))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
if(!Eval(operandStack, kZeroOrMore))
|
if(!Eval(operandStack, kZeroOrMore))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
if(!Eval(operandStack, kOneOrMore))
|
if(!Eval(operandStack, kOneOrMore))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '{':
|
case '{':
|
||||||
{
|
{
|
||||||
unsigned n, m;
|
unsigned n, m;
|
||||||
if(!ParseUnsigned(ds, &n))
|
if(!ParseUnsigned(ds, &n))
|
||||||
return;
|
{
|
||||||
|
|
||||||
if (ds.Peek() == ',') {
|
|
||||||
ds.Take();
|
|
||||||
if (ds.Peek() == '}')
|
|
||||||
m = kInfinityQuantifier;
|
|
||||||
else if (!ParseUnsigned(ds, &m) || m < n)
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ds.Peek() == ',')
|
||||||
|
{
|
||||||
|
ds.Take();
|
||||||
|
if(ds.Peek() == '}')
|
||||||
|
{
|
||||||
|
m = kInfinityQuantifier;
|
||||||
|
}
|
||||||
|
else if(!ParseUnsigned(ds, &m) || m < n)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m = n;
|
m = n;
|
||||||
|
}
|
||||||
|
|
||||||
if(!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
|
if(!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
ds.Take();
|
ds.Take();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -289,7 +345,9 @@ private:
|
||||||
{
|
{
|
||||||
SizeType range;
|
SizeType range;
|
||||||
if(!ParseRange(ds, &range))
|
if(!ParseRange(ds, &range))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
|
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
|
||||||
GetState(s).rangeStart = range;
|
GetState(s).rangeStart = range;
|
||||||
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
||||||
|
@ -299,7 +357,9 @@ private:
|
||||||
|
|
||||||
case '\\': // Escape character
|
case '\\': // Escape character
|
||||||
if(!CharacterEscape(ds, &codepoint))
|
if(!CharacterEscape(ds, &codepoint))
|
||||||
|
{
|
||||||
return; // Unsupported escape character
|
return; // Unsupported escape character
|
||||||
|
}
|
||||||
// fall through to default
|
// fall through to default
|
||||||
|
|
||||||
default: // Pattern character
|
default: // Pattern character
|
||||||
|
@ -310,17 +370,21 @@ private:
|
||||||
|
|
||||||
while(!operatorStack.Empty())
|
while(!operatorStack.Empty())
|
||||||
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
if(!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Link the operand to matching state.
|
// Link the operand to matching state.
|
||||||
if (operandStack.GetSize() == sizeof(Frag)) {
|
if(operandStack.GetSize() == sizeof(Frag))
|
||||||
|
{
|
||||||
Frag* e = operandStack.template Pop<Frag>(1);
|
Frag* e = operandStack.template Pop<Frag>(1);
|
||||||
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
|
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
|
||||||
root_ = e->start;
|
root_ = e->start;
|
||||||
|
|
||||||
#if RAPIDJSON_REGEX_VERBOSE
|
#if RAPIDJSON_REGEX_VERBOSE
|
||||||
printf("root: %d\n", root_);
|
printf("root: %d\n", root_);
|
||||||
for (SizeType i = 0; i < stateCount_ ; i++) {
|
for(SizeType i = 0; i < stateCount_ ; i++)
|
||||||
|
{
|
||||||
State & s = GetState(i);
|
State & s = GetState(i);
|
||||||
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
|
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
|
||||||
}
|
}
|
||||||
|
@ -330,14 +394,16 @@ private:
|
||||||
|
|
||||||
// Preallocate buffer for SearchWithAnchoring()
|
// Preallocate buffer for SearchWithAnchoring()
|
||||||
RAPIDJSON_ASSERT(stateSet_ == 0);
|
RAPIDJSON_ASSERT(stateSet_ == 0);
|
||||||
if (stateCount_ > 0) {
|
if(stateCount_ > 0)
|
||||||
|
{
|
||||||
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
|
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
|
||||||
state0_.template Reserve<SizeType>(stateCount_);
|
state0_.template Reserve<SizeType>(stateCount_);
|
||||||
state1_.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>();
|
State* s = states_.template Push<State>();
|
||||||
s->out = out;
|
s->out = out;
|
||||||
s->out1 = out1;
|
s->out1 = out1;
|
||||||
|
@ -346,34 +412,45 @@ private:
|
||||||
return stateCount_++;
|
return stateCount_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
|
void PushOperand(Stack<Allocator> & operandStack, unsigned codepoint)
|
||||||
|
{
|
||||||
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
|
SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
|
||||||
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
*operandStack.template Push<Frag>() = Frag(s, s, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
|
void ImplicitConcatenation(Stack<Allocator> & atomCountStack, Stack<Allocator> & operatorStack)
|
||||||
|
{
|
||||||
if(*atomCountStack.template Top<unsigned>())
|
if(*atomCountStack.template Top<unsigned>())
|
||||||
|
{
|
||||||
*operatorStack.template Push<Operator>() = kConcatenation;
|
*operatorStack.template Push<Operator>() = kConcatenation;
|
||||||
|
}
|
||||||
(*atomCountStack.template Top<unsigned>())++;
|
(*atomCountStack.template Top<unsigned>())++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeType Append(SizeType l1, SizeType l2) {
|
SizeType Append(SizeType l1, SizeType l2)
|
||||||
|
{
|
||||||
SizeType old = l1;
|
SizeType old = l1;
|
||||||
while(GetState(l1).out != kRegexInvalidState)
|
while(GetState(l1).out != kRegexInvalidState)
|
||||||
|
{
|
||||||
l1 = GetState(l1).out;
|
l1 = GetState(l1).out;
|
||||||
|
}
|
||||||
GetState(l1).out = l2;
|
GetState(l1).out = l2;
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patch(SizeType l, SizeType s) {
|
void Patch(SizeType l, SizeType s)
|
||||||
for (SizeType next; l != kRegexInvalidState; l = next) {
|
{
|
||||||
|
for(SizeType next; l != kRegexInvalidState; l = next)
|
||||||
|
{
|
||||||
next = GetState(l).out;
|
next = GetState(l).out;
|
||||||
GetState(l).out = s;
|
GetState(l).out = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Eval(Stack<Allocator>& operandStack, Operator op) {
|
bool Eval(Stack<Allocator> & operandStack, Operator op)
|
||||||
switch (op) {
|
{
|
||||||
|
switch(op)
|
||||||
|
{
|
||||||
case kConcatenation:
|
case kConcatenation:
|
||||||
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
|
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
|
||||||
{
|
{
|
||||||
|
@ -385,7 +462,8 @@ private:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case kAlternation:
|
case kAlternation:
|
||||||
if (operandStack.GetSize() >= sizeof(Frag) * 2) {
|
if(operandStack.GetSize() >= sizeof(Frag) * 2)
|
||||||
|
{
|
||||||
Frag e2 = *operandStack.template Pop<Frag>(1);
|
Frag e2 = *operandStack.template Pop<Frag>(1);
|
||||||
Frag e1 = *operandStack.template Pop<Frag>(1);
|
Frag e1 = *operandStack.template Pop<Frag>(1);
|
||||||
SizeType s = NewState(e1.start, e2.start, 0);
|
SizeType s = NewState(e1.start, e2.start, 0);
|
||||||
|
@ -395,7 +473,8 @@ private:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case kZeroOrOne:
|
case kZeroOrOne:
|
||||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
if(operandStack.GetSize() >= sizeof(Frag))
|
||||||
|
{
|
||||||
Frag e = *operandStack.template Pop<Frag>(1);
|
Frag e = *operandStack.template Pop<Frag>(1);
|
||||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||||
*operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
|
*operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
|
||||||
|
@ -404,7 +483,8 @@ private:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case kZeroOrMore:
|
case kZeroOrMore:
|
||||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
if(operandStack.GetSize() >= sizeof(Frag))
|
||||||
|
{
|
||||||
Frag e = *operandStack.template Pop<Frag>(1);
|
Frag e = *operandStack.template Pop<Frag>(1);
|
||||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||||
Patch(e.out, s);
|
Patch(e.out, s);
|
||||||
|
@ -415,7 +495,8 @@ private:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
RAPIDJSON_ASSERT(op == kOneOrMore);
|
RAPIDJSON_ASSERT(op == kOneOrMore);
|
||||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
if(operandStack.GetSize() >= sizeof(Frag))
|
||||||
|
{
|
||||||
Frag e = *operandStack.template Pop<Frag>(1);
|
Frag e = *operandStack.template Pop<Frag>(1);
|
||||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||||
Patch(e.out, s);
|
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(n <= m);
|
||||||
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
|
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
|
||||||
|
|
||||||
if (n == 0) {
|
if(n == 0)
|
||||||
|
{
|
||||||
if(m == 0) // a{0} not support
|
if(m == 0) // a{0} not support
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
else if(m == kInfinityQuantifier)
|
else if(m == kInfinityQuantifier)
|
||||||
Eval(operandStack, kZeroOrMore); // a{0,} -> a*
|
{
|
||||||
else {
|
Eval(operandStack, kZeroOrMore);
|
||||||
|
} // a{0,} -> a*
|
||||||
|
else
|
||||||
|
{
|
||||||
Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
|
Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
|
||||||
for(unsigned i = 0; i < m - 1; i++)
|
for(unsigned i = 0; i < m - 1; i++)
|
||||||
CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
|
{
|
||||||
|
CloneTopOperand(operandStack);
|
||||||
|
} // a{0,5} -> a? a? a? a? a?
|
||||||
for(unsigned i = 0; i < m - 1; i++)
|
for(unsigned i = 0; i < m - 1; i++)
|
||||||
Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
|
{
|
||||||
|
Eval(operandStack, kConcatenation);
|
||||||
|
} // a{0,5} -> a?a?a?a?a?
|
||||||
}
|
}
|
||||||
return true;
|
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);
|
CloneTopOperand(operandStack);
|
||||||
|
}
|
||||||
|
|
||||||
if(m == kInfinityQuantifier)
|
if(m == kInfinityQuantifier)
|
||||||
Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
|
{
|
||||||
else if (m > n) {
|
Eval(operandStack, kOneOrMore);
|
||||||
|
} // a{3,} -> a a a+
|
||||||
|
else if(m > n)
|
||||||
|
{
|
||||||
CloneTopOperand(operandStack); // a{3,5} -> a a a a
|
CloneTopOperand(operandStack); // a{3,5} -> a a a a
|
||||||
Eval(operandStack, kZeroOrOne); // 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++)
|
for(unsigned i = n; i < m - 1; i++)
|
||||||
CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
|
{
|
||||||
|
CloneTopOperand(operandStack);
|
||||||
|
} // a{3,5} -> a a a a? a?
|
||||||
for(unsigned i = n; i < m; i++)
|
for(unsigned i = n; i < m; i++)
|
||||||
Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
|
{
|
||||||
|
Eval(operandStack, kConcatenation);
|
||||||
|
} // a{3,5} -> a a aa?a?
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < n - 1; i++)
|
for(unsigned i = 0; i < n - 1; i++)
|
||||||
Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
|
{
|
||||||
|
Eval(operandStack, kConcatenation);
|
||||||
|
} // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
|
||||||
|
|
||||||
return true;
|
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
|
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);
|
State* s = states_.template Push<State>(count);
|
||||||
memcpy(s, &GetState(src.minIndex), count * sizeof(State));
|
memcpy(s, &GetState(src.minIndex), count * sizeof(State));
|
||||||
for (SizeType j = 0; j < count; j++) {
|
for(SizeType j = 0; j < count; j++)
|
||||||
|
{
|
||||||
if(s[j].out != kRegexInvalidState)
|
if(s[j].out != kRegexInvalidState)
|
||||||
|
{
|
||||||
s[j].out += count;
|
s[j].out += count;
|
||||||
|
}
|
||||||
if(s[j].out1 != kRegexInvalidState)
|
if(s[j].out1 != kRegexInvalidState)
|
||||||
|
{
|
||||||
s[j].out1 += count;
|
s[j].out1 += count;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
*operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
|
*operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
|
||||||
stateCount_ += count;
|
stateCount_ += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
|
bool ParseUnsigned(DecodedStream<InputStream> & ds, unsigned* u)
|
||||||
|
{
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
if(ds.Peek() < '0' || ds.Peek() > '9')
|
if(ds.Peek() < '0' || ds.Peek() > '9')
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
while (ds.Peek() >= '0' && ds.Peek() <= '9') {
|
}
|
||||||
|
while(ds.Peek() >= '0' && ds.Peek() <= '9')
|
||||||
|
{
|
||||||
if(r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
|
if(r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
|
||||||
|
{
|
||||||
return false; // overflow
|
return false; // overflow
|
||||||
|
}
|
||||||
r = r * 10 + (ds.Take() - '0');
|
r = r * 10 + (ds.Take() - '0');
|
||||||
}
|
}
|
||||||
*u = r;
|
*u = r;
|
||||||
|
@ -497,49 +616,64 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
|
bool ParseRange(DecodedStream<InputStream> & ds, SizeType* range)
|
||||||
|
{
|
||||||
bool isBegin = true;
|
bool isBegin = true;
|
||||||
bool negate = false;
|
bool negate = false;
|
||||||
int step = 0;
|
int step = 0;
|
||||||
SizeType start = kRegexInvalidRange;
|
SizeType start = kRegexInvalidRange;
|
||||||
SizeType current = kRegexInvalidRange;
|
SizeType current = kRegexInvalidRange;
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
while ((codepoint = ds.Take()) != 0) {
|
while((codepoint = ds.Take()) != 0)
|
||||||
if (isBegin) {
|
{
|
||||||
|
if(isBegin)
|
||||||
|
{
|
||||||
isBegin = false;
|
isBegin = false;
|
||||||
if (codepoint == '^') {
|
if(codepoint == '^')
|
||||||
|
{
|
||||||
negate = true;
|
negate = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (codepoint) {
|
switch(codepoint)
|
||||||
|
{
|
||||||
case ']':
|
case ']':
|
||||||
if(start == kRegexInvalidRange)
|
if(start == kRegexInvalidRange)
|
||||||
|
{
|
||||||
return false; // Error: nothing inside []
|
return false; // Error: nothing inside []
|
||||||
if (step == 2) { // Add trailing '-'
|
}
|
||||||
|
if(step == 2) // Add trailing '-'
|
||||||
|
{
|
||||||
SizeType r = NewRange('-');
|
SizeType r = NewRange('-');
|
||||||
RAPIDJSON_ASSERT(current != kRegexInvalidRange);
|
RAPIDJSON_ASSERT(current != kRegexInvalidRange);
|
||||||
GetRange(current).next = r;
|
GetRange(current).next = r;
|
||||||
}
|
}
|
||||||
if(negate)
|
if(negate)
|
||||||
|
{
|
||||||
GetRange(start).start |= kRangeNegationFlag;
|
GetRange(start).start |= kRangeNegationFlag;
|
||||||
|
}
|
||||||
*range = start;
|
*range = start;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
if (ds.Peek() == 'b') {
|
if(ds.Peek() == 'b')
|
||||||
|
{
|
||||||
ds.Take();
|
ds.Take();
|
||||||
codepoint = 0x0008; // Escape backspace character
|
codepoint = 0x0008; // Escape backspace character
|
||||||
}
|
}
|
||||||
else if(!CharacterEscape(ds, &codepoint))
|
else if(!CharacterEscape(ds, &codepoint))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// fall through to default
|
// fall through to default
|
||||||
|
|
||||||
default:
|
default:
|
||||||
switch (step) {
|
switch(step)
|
||||||
|
{
|
||||||
case 1:
|
case 1:
|
||||||
if (codepoint == '-') {
|
if(codepoint == '-')
|
||||||
|
{
|
||||||
step++;
|
step++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -549,9 +683,13 @@ private:
|
||||||
{
|
{
|
||||||
SizeType r = NewRange(codepoint);
|
SizeType r = NewRange(codepoint);
|
||||||
if(current != kRegexInvalidRange)
|
if(current != kRegexInvalidRange)
|
||||||
|
{
|
||||||
GetRange(current).next = r;
|
GetRange(current).next = r;
|
||||||
|
}
|
||||||
if(start == kRegexInvalidRange)
|
if(start == kRegexInvalidRange)
|
||||||
|
{
|
||||||
start = r;
|
start = r;
|
||||||
|
}
|
||||||
current = r;
|
current = r;
|
||||||
}
|
}
|
||||||
step = 1;
|
step = 1;
|
||||||
|
@ -567,7 +705,8 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeType NewRange(unsigned codepoint) {
|
SizeType NewRange(unsigned codepoint)
|
||||||
|
{
|
||||||
Range* r = ranges_.template Push<Range>();
|
Range* r = ranges_.template Push<Range>();
|
||||||
r->start = r->end = codepoint;
|
r->start = r->end = codepoint;
|
||||||
r->next = kRegexInvalidRange;
|
r->next = kRegexInvalidRange;
|
||||||
|
@ -575,9 +714,11 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
|
bool CharacterEscape(DecodedStream<InputStream> & ds, unsigned* escapedCodepoint)
|
||||||
|
{
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
switch (codepoint = ds.Take()) {
|
switch(codepoint = ds.Take())
|
||||||
|
{
|
||||||
case '^':
|
case '^':
|
||||||
case '$':
|
case '$':
|
||||||
case '|':
|
case '|':
|
||||||
|
@ -592,19 +733,31 @@ private:
|
||||||
case '{':
|
case '{':
|
||||||
case '}':
|
case '}':
|
||||||
case '\\':
|
case '\\':
|
||||||
*escapedCodepoint = codepoint; return true;
|
*escapedCodepoint = codepoint;
|
||||||
case 'f': *escapedCodepoint = 0x000C; return true;
|
return true;
|
||||||
case 'n': *escapedCodepoint = 0x000A; return true;
|
case 'f':
|
||||||
case 'r': *escapedCodepoint = 0x000D; return true;
|
*escapedCodepoint = 0x000C;
|
||||||
case 't': *escapedCodepoint = 0x0009; return true;
|
return true;
|
||||||
case 'v': *escapedCodepoint = 0x000B; 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:
|
default:
|
||||||
return false; // Unsupported escape character
|
return false; // Unsupported escape character
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputStream>
|
template <typename InputStream>
|
||||||
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
|
bool SearchWithAnchoring(InputStream & is, bool anchorBegin, bool anchorEnd) const
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(IsValid());
|
RAPIDJSON_ASSERT(IsValid());
|
||||||
DecodedStream<InputStream> ds(is);
|
DecodedStream<InputStream> ds(is);
|
||||||
|
|
||||||
|
@ -615,11 +768,13 @@ private:
|
||||||
|
|
||||||
bool matched = AddState(*current, root_);
|
bool matched = AddState(*current, root_);
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
|
while(!current->Empty() && (codepoint = ds.Take()) != 0)
|
||||||
|
{
|
||||||
std::memset(stateSet_, 0, stateSetSize);
|
std::memset(stateSet_, 0, stateSetSize);
|
||||||
next->Clear();
|
next->Clear();
|
||||||
matched = false;
|
matched = false;
|
||||||
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
|
for(const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s)
|
||||||
|
{
|
||||||
const State & sr = GetState(*s);
|
const State & sr = GetState(*s);
|
||||||
if(sr.codepoint == codepoint ||
|
if(sr.codepoint == codepoint ||
|
||||||
sr.codepoint == kAnyCharacterClass ||
|
sr.codepoint == kAnyCharacterClass ||
|
||||||
|
@ -627,43 +782,56 @@ private:
|
||||||
{
|
{
|
||||||
matched = AddState(*next, sr.out) || matched;
|
matched = AddState(*next, sr.out) || matched;
|
||||||
if(!anchorEnd && matched)
|
if(!anchorEnd && matched)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(!anchorBegin)
|
if(!anchorBegin)
|
||||||
|
{
|
||||||
AddState(*next, root_);
|
AddState(*next, root_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
internal::Swap(current, next);
|
internal::Swap(current, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matched;
|
return matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetStateSetSize() const {
|
size_t GetStateSetSize() const
|
||||||
|
{
|
||||||
return (stateCount_ + 31) / 32 * 4;
|
return (stateCount_ + 31) / 32 * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return whether the added states is a match state
|
// 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);
|
RAPIDJSON_ASSERT(index != kRegexInvalidState);
|
||||||
|
|
||||||
const State & s = GetState(index);
|
const State & s = GetState(index);
|
||||||
if (s.out1 != kRegexInvalidState) { // Split
|
if(s.out1 != kRegexInvalidState) // Split
|
||||||
|
{
|
||||||
bool matched = AddState(l, s.out);
|
bool matched = AddState(l, s.out);
|
||||||
return AddState(l, s.out1) || matched;
|
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));
|
stateSet_[index >> 5] |= (1 << (index & 31));
|
||||||
*l.template PushUnsafe<SizeType>() = index;
|
*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;
|
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
|
||||||
while (rangeIndex != kRegexInvalidRange) {
|
while(rangeIndex != kRegexInvalidRange)
|
||||||
|
{
|
||||||
const Range & r = GetRange(rangeIndex);
|
const Range & r = GetRange(rangeIndex);
|
||||||
if(codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
|
if(codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
|
||||||
|
{
|
||||||
return yes;
|
return yes;
|
||||||
|
}
|
||||||
rangeIndex = r.next;
|
rangeIndex = r.next;
|
||||||
}
|
}
|
||||||
return !yes;
|
return !yes;
|
||||||
|
|
113
src/3rdparty/rapidjson/internal/stack.h
vendored
113
src/3rdparty/rapidjson/internal/stack.h
vendored
|
@ -24,7 +24,8 @@ RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Stack
|
// Stack
|
||||||
|
@ -33,11 +34,14 @@ namespace internal {
|
||||||
/*! \tparam Allocator Allocator for allocating stack memory.
|
/*! \tparam Allocator Allocator for allocating stack memory.
|
||||||
*/
|
*/
|
||||||
template <typename Allocator>
|
template <typename Allocator>
|
||||||
class Stack {
|
class Stack
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
// Optimization note: Do not allocate memory for stack_ in constructor.
|
// Optimization note: Do not allocate memory for stack_ in constructor.
|
||||||
// Do it lazily when first Push() -> Expand() -> Resize().
|
// 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
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
|
@ -58,12 +62,14 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
~Stack() {
|
~Stack()
|
||||||
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
Stack& operator=(Stack&& rhs) {
|
Stack & operator=(Stack && rhs)
|
||||||
|
{
|
||||||
if(&rhs != this)
|
if(&rhs != this)
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
@ -86,7 +92,8 @@ public:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
|
void Swap(Stack & rhs) RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
internal::Swap(allocator_, rhs.allocator_);
|
internal::Swap(allocator_, rhs.allocator_);
|
||||||
internal::Swap(ownAllocator_, rhs.ownAllocator_);
|
internal::Swap(ownAllocator_, rhs.ownAllocator_);
|
||||||
internal::Swap(stack_, rhs.stack_);
|
internal::Swap(stack_, rhs.stack_);
|
||||||
|
@ -95,10 +102,15 @@ public:
|
||||||
internal::Swap(initialCapacity_, rhs.initialCapacity_);
|
internal::Swap(initialCapacity_, rhs.initialCapacity_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() { stackTop_ = stack_; }
|
void Clear()
|
||||||
|
{
|
||||||
|
stackTop_ = stack_;
|
||||||
|
}
|
||||||
|
|
||||||
void ShrinkToFit() {
|
void ShrinkToFit()
|
||||||
if (Empty()) {
|
{
|
||||||
|
if(Empty())
|
||||||
|
{
|
||||||
// If the stack is empty, completely deallocate the memory.
|
// If the stack is empty, completely deallocate the memory.
|
||||||
Allocator::Free(stack_);
|
Allocator::Free(stack_);
|
||||||
stack_ = 0;
|
stack_ = 0;
|
||||||
|
@ -106,26 +118,33 @@ public:
|
||||||
stackEnd_ = 0;
|
stackEnd_ = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Resize(GetSize());
|
Resize(GetSize());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Optimization note: try to minimize the size of this function for force inline.
|
// 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.
|
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1)
|
||||||
|
{
|
||||||
// Expand the stack if needed
|
// Expand the stack if needed
|
||||||
if(RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
if(RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
||||||
|
{
|
||||||
Expand<T>(count);
|
Expand<T>(count);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1)
|
||||||
|
{
|
||||||
Reserve<T>(count);
|
Reserve<T>(count);
|
||||||
return PushUnsafe<T>(count);
|
return PushUnsafe<T>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
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_);
|
RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
|
||||||
T* ret = reinterpret_cast<T*>(stackTop_);
|
T* ret = reinterpret_cast<T*>(stackTop_);
|
||||||
stackTop_ += sizeof(T) * count;
|
stackTop_ += sizeof(T) * count;
|
||||||
|
@ -133,77 +152,113 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Pop(size_t count) {
|
T* Pop(size_t count)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||||
stackTop_ -= count * sizeof(T);
|
stackTop_ -= count * sizeof(T);
|
||||||
return reinterpret_cast<T*>(stackTop_);
|
return reinterpret_cast<T*>(stackTop_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Top() {
|
T* Top()
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T* Top() const {
|
const T* Top() const
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* End() { return reinterpret_cast<T*>(stackTop_); }
|
T* End()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(stackTop_);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T* End() const { return reinterpret_cast<T*>(stackTop_); }
|
const T* End() const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(stackTop_);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* Bottom() { return reinterpret_cast<T*>(stack_); }
|
T* Bottom()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(stack_);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
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;
|
return allocator_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator& GetAllocator() {
|
Allocator & GetAllocator()
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(allocator_);
|
RAPIDJSON_ASSERT(allocator_);
|
||||||
return *allocator_;
|
return *allocator_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Empty() const { return stackTop_ == stack_; }
|
bool Empty() const
|
||||||
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
|
{
|
||||||
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
|
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>
|
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.
|
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
|
||||||
size_t newCapacity;
|
size_t newCapacity;
|
||||||
if (stack_ == 0) {
|
if(stack_ == 0)
|
||||||
|
{
|
||||||
if(!allocator_)
|
if(!allocator_)
|
||||||
|
{
|
||||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
|
||||||
|
}
|
||||||
newCapacity = initialCapacity_;
|
newCapacity = initialCapacity_;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
newCapacity = GetCapacity();
|
newCapacity = GetCapacity();
|
||||||
newCapacity += (newCapacity + 1) / 2;
|
newCapacity += (newCapacity + 1) / 2;
|
||||||
}
|
}
|
||||||
size_t newSize = GetSize() + sizeof(T) * count;
|
size_t newSize = GetSize() + sizeof(T) * count;
|
||||||
if(newCapacity < newSize)
|
if(newCapacity < newSize)
|
||||||
|
{
|
||||||
newCapacity = newSize;
|
newCapacity = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
Resize(newCapacity);
|
Resize(newCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resize(size_t newCapacity) {
|
void Resize(size_t newCapacity)
|
||||||
|
{
|
||||||
const size_t size = GetSize(); // Backup the current size
|
const size_t size = GetSize(); // Backup the current size
|
||||||
stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
|
stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
|
||||||
stackTop_ = stack_ + size;
|
stackTop_ = stack_ + size;
|
||||||
stackEnd_ = stack_ + newCapacity;
|
stackEnd_ = stack_ + newCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Destroy() {
|
void Destroy()
|
||||||
|
{
|
||||||
Allocator::Free(stack_);
|
Allocator::Free(stack_);
|
||||||
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
|
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
|
||||||
}
|
}
|
||||||
|
|
19
src/3rdparty/rapidjson/internal/strfunc.h
vendored
19
src/3rdparty/rapidjson/internal/strfunc.h
vendored
|
@ -18,7 +18,8 @@
|
||||||
#include "../stream.h"
|
#include "../stream.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
//! Custom strlen() which works on different character types.
|
//! Custom strlen() which works on different character types.
|
||||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
||||||
|
@ -27,22 +28,30 @@ namespace internal {
|
||||||
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
|
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
|
||||||
*/
|
*/
|
||||||
template <typename Ch>
|
template <typename Ch>
|
||||||
inline SizeType StrLen(const Ch* s) {
|
inline SizeType StrLen(const Ch* s)
|
||||||
|
{
|
||||||
const Ch* p = s;
|
const Ch* p = s;
|
||||||
while (*p) ++p;
|
while(*p)
|
||||||
|
{
|
||||||
|
++p;
|
||||||
|
}
|
||||||
return SizeType(p - s);
|
return SizeType(p - s);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns number of code points in a encoded string.
|
//! Returns number of code points in a encoded string.
|
||||||
template<typename Encoding>
|
template<typename Encoding>
|
||||||
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
|
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount)
|
||||||
|
{
|
||||||
GenericStringStream<Encoding> is(s);
|
GenericStringStream<Encoding> is(s);
|
||||||
const typename Encoding::Ch* end = s + length;
|
const typename Encoding::Ch* end = s + length;
|
||||||
SizeType count = 0;
|
SizeType count = 0;
|
||||||
while (is.src_ < end) {
|
while(is.src_ < end)
|
||||||
|
{
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
if(!Encoding::Decode(is, &codepoint))
|
if(!Encoding::Decode(is, &codepoint))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
*outCount = count;
|
*outCount = count;
|
||||||
|
|
127
src/3rdparty/rapidjson/internal/strtod.h
vendored
127
src/3rdparty/rapidjson/internal/strtod.h
vendored
|
@ -21,37 +21,57 @@
|
||||||
#include "pow10.h"
|
#include "pow10.h"
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
inline double FastPath(double significand, int exp) {
|
inline double FastPath(double significand, int exp)
|
||||||
|
{
|
||||||
if(exp < -308)
|
if(exp < -308)
|
||||||
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
}
|
||||||
else if(exp >= 0)
|
else if(exp >= 0)
|
||||||
|
{
|
||||||
return significand * internal::Pow10(exp);
|
return significand * internal::Pow10(exp);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return significand / internal::Pow10(-exp);
|
return significand / internal::Pow10(-exp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline double StrtodNormalPrecision(double d, int p) {
|
inline double StrtodNormalPrecision(double d, int p)
|
||||||
if (p < -308) {
|
{
|
||||||
|
if(p < -308)
|
||||||
|
{
|
||||||
// Prevent expSum < -308, making Pow10(p) = 0
|
// Prevent expSum < -308, making Pow10(p) = 0
|
||||||
d = FastPath(d, -308);
|
d = FastPath(d, -308);
|
||||||
d = FastPath(d, p + 308);
|
d = FastPath(d, p + 308);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
d = FastPath(d, p);
|
d = FastPath(d, p);
|
||||||
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T Min3(T a, T b, T c) {
|
inline T Min3(T a, T b, T c)
|
||||||
|
{
|
||||||
T m = a;
|
T m = a;
|
||||||
if (m > b) m = b;
|
if(m > b)
|
||||||
if (m > c) m = c;
|
{
|
||||||
|
m = b;
|
||||||
|
}
|
||||||
|
if(m > c)
|
||||||
|
{
|
||||||
|
m = c;
|
||||||
|
}
|
||||||
return m;
|
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 Double db(b);
|
||||||
const uint64_t bInt = db.IntegerSignificand();
|
const uint64_t bInt = db.IntegerSignificand();
|
||||||
const int bExp = db.IntegerExponent();
|
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;
|
int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
|
||||||
|
|
||||||
// Adjust for decimal exponent
|
// Adjust for decimal exponent
|
||||||
if (dExp >= 0) {
|
if(dExp >= 0)
|
||||||
|
{
|
||||||
dS_Exp2 += dExp;
|
dS_Exp2 += dExp;
|
||||||
dS_Exp5 += dExp;
|
dS_Exp5 += dExp;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
bS_Exp2 -= dExp;
|
bS_Exp2 -= dExp;
|
||||||
bS_Exp5 -= dExp;
|
bS_Exp5 -= dExp;
|
||||||
hS_Exp2 -= dExp;
|
hS_Exp2 -= dExp;
|
||||||
|
@ -73,16 +95,22 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
||||||
|
|
||||||
// Adjust for binary exponent
|
// Adjust for binary exponent
|
||||||
if(bExp >= 0)
|
if(bExp >= 0)
|
||||||
|
{
|
||||||
bS_Exp2 += bExp;
|
bS_Exp2 += bExp;
|
||||||
else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
dS_Exp2 -= bExp;
|
dS_Exp2 -= bExp;
|
||||||
hS_Exp2 -= bExp;
|
hS_Exp2 -= bExp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust for half ulp exponent
|
// Adjust for half ulp exponent
|
||||||
if(hExp >= 0)
|
if(hExp >= 0)
|
||||||
|
{
|
||||||
hS_Exp2 += hExp;
|
hS_Exp2 += hExp;
|
||||||
else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
dS_Exp2 -= hExp;
|
dS_Exp2 -= hExp;
|
||||||
bS_Exp2 -= hExp;
|
bS_Exp2 -= hExp;
|
||||||
}
|
}
|
||||||
|
@ -108,36 +136,47 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
|
||||||
return delta.Compare(hS);
|
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
|
// Use fast path for string-to-double conversion if possible
|
||||||
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
|
// 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
|
// Fast Path Cases In Disguise
|
||||||
d *= internal::Pow10(p - 22);
|
d *= internal::Pow10(p - 22);
|
||||||
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);
|
*result = FastPath(d, p);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compute an approximation and see if it is within 1/2 ULP
|
// 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) {
|
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result)
|
||||||
|
{
|
||||||
uint64_t significand = 0;
|
uint64_t significand = 0;
|
||||||
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||||
for (; i < length; i++) {
|
for(; i < length; i++)
|
||||||
|
{
|
||||||
if(significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
if(significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i < length && decimals[i] >= '5') // Rounding
|
if(i < length && decimals[i] >= '5') // Rounding
|
||||||
|
{
|
||||||
significand++;
|
significand++;
|
||||||
|
}
|
||||||
|
|
||||||
size_t remaining = length - i;
|
size_t remaining = length - i;
|
||||||
const unsigned kUlpShift = 3;
|
const unsigned kUlpShift = 3;
|
||||||
|
@ -152,8 +191,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||||
|
|
||||||
int actualExp;
|
int actualExp;
|
||||||
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
||||||
if (actualExp != dExp) {
|
if(actualExp != dExp)
|
||||||
static const DiyFp kPow10[] = {
|
{
|
||||||
|
static const DiyFp kPow10[] =
|
||||||
|
{
|
||||||
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
||||||
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
||||||
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
||||||
|
@ -166,8 +207,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||||
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
||||||
v = v * kPow10[adjustment];
|
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;
|
error += kUlp / 2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
v = v * cachedPower;
|
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);
|
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||||
unsigned precisionSize = 64 - effectiveSignificandSize;
|
unsigned precisionSize = 64 - effectiveSignificandSize;
|
||||||
if (precisionSize + kUlpShift >= 64) {
|
if(precisionSize + kUlpShift >= 64)
|
||||||
|
{
|
||||||
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
|
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
|
||||||
v.f >>= scaleExp;
|
v.f >>= scaleExp;
|
||||||
v.e += 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));
|
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 precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
||||||
const uint64_t halfWay = (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++;
|
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.f >>= 1;
|
||||||
rounded.e++;
|
rounded.e++;
|
||||||
}
|
}
|
||||||
|
@ -200,44 +246,62 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||||
|
|
||||||
*result = rounded.ToDouble();
|
*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 BigInteger dInt(decimals, length);
|
||||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||||
Double a(approx);
|
Double a(approx);
|
||||||
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||||
if(cmp < 0)
|
if(cmp < 0)
|
||||||
|
{
|
||||||
return a.Value(); // within half ULP
|
return a.Value(); // within half ULP
|
||||||
else if (cmp == 0) {
|
}
|
||||||
|
else if(cmp == 0)
|
||||||
|
{
|
||||||
// Round towards even
|
// Round towards even
|
||||||
if(a.Significand() & 1)
|
if(a.Significand() & 1)
|
||||||
|
{
|
||||||
return a.NextPositiveDouble();
|
return a.NextPositiveDouble();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return a.Value();
|
return a.Value();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else // adjustment
|
else // adjustment
|
||||||
|
{
|
||||||
return a.NextPositiveDouble();
|
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(d >= 0.0);
|
||||||
RAPIDJSON_ASSERT(length >= 1);
|
RAPIDJSON_ASSERT(length >= 1);
|
||||||
|
|
||||||
double result;
|
double result;
|
||||||
if(StrtodFast(d, p, &result))
|
if(StrtodFast(d, p, &result))
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Trim leading zeros
|
// Trim leading zeros
|
||||||
while (*decimals == '0' && length > 1) {
|
while(*decimals == '0' && length > 1)
|
||||||
|
{
|
||||||
length--;
|
length--;
|
||||||
decimals++;
|
decimals++;
|
||||||
decimalPosition--;
|
decimalPosition--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trim trailing zeros
|
// Trim trailing zeros
|
||||||
while (decimals[length - 1] == '0' && length > 1) {
|
while(decimals[length - 1] == '0' && length > 1)
|
||||||
|
{
|
||||||
length--;
|
length--;
|
||||||
decimalPosition--;
|
decimalPosition--;
|
||||||
exp++;
|
exp++;
|
||||||
|
@ -245,7 +309,8 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
|
||||||
|
|
||||||
// Trim right-most digits
|
// Trim right-most digits
|
||||||
const int kMaxDecimalDigit = 780;
|
const int kMaxDecimalDigit = 780;
|
||||||
if (static_cast<int>(length) > kMaxDecimalDigit) {
|
if(static_cast<int>(length) > kMaxDecimalDigit)
|
||||||
|
{
|
||||||
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||||
exp += delta;
|
exp += delta;
|
||||||
decimalPosition -= static_cast<unsigned>(delta);
|
decimalPosition -= static_cast<unsigned>(delta);
|
||||||
|
@ -254,10 +319,14 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
|
||||||
|
|
||||||
// If too small, underflow to zero
|
// If too small, underflow to zero
|
||||||
if(int(length) + exp < -324)
|
if(int(length) + exp < -324)
|
||||||
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
if(StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
if(StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||||
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
||||||
|
|
6
src/3rdparty/rapidjson/internal/swap.h
vendored
6
src/3rdparty/rapidjson/internal/swap.h
vendored
|
@ -23,14 +23,16 @@ RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
namespace internal {
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
//! Custom swap() to avoid dependency on C++ <algorithm> header
|
//! 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.
|
/*! \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().
|
\note This has the same semantics as std::swap().
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
|
inline void Swap(T & a, T & b) RAPIDJSON_NOEXCEPT
|
||||||
|
{
|
||||||
T tmp = a;
|
T tmp = a;
|
||||||
a = b;
|
a = b;
|
||||||
b = tmp;
|
b = tmp;
|
||||||
|
|
52
src/3rdparty/rapidjson/istreamwrapper.h
vendored
52
src/3rdparty/rapidjson/istreamwrapper.h
vendored
|
@ -47,42 +47,68 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename StreamType>
|
template <typename StreamType>
|
||||||
class BasicIStreamWrapper {
|
class BasicIStreamWrapper
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename StreamType::char_type Ch;
|
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();
|
typename StreamType::int_type c = stream_.peek();
|
||||||
return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
|
return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
Ch Take() {
|
Ch Take()
|
||||||
|
{
|
||||||
typename StreamType::int_type c = stream_.get();
|
typename StreamType::int_type c = stream_.get();
|
||||||
if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
|
if(RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()))
|
||||||
|
{
|
||||||
count_++;
|
count_++;
|
||||||
return static_cast<Ch>(c);
|
return static_cast<Ch>(c);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// tellg() may return -1 when failed. So we count by ourself.
|
// 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; }
|
Ch* PutBegin()
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
{
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
RAPIDJSON_ASSERT(false);
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
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.
|
// For encoding detection only.
|
||||||
const Ch* Peek4() const {
|
const Ch* Peek4() const
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
|
RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
|
||||||
int i;
|
int i;
|
||||||
bool hasError = false;
|
bool hasError = false;
|
||||||
for (i = 0; i < 4; ++i) {
|
for(i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
typename StreamType::int_type c = stream_.get();
|
typename StreamType::int_type c = stream_.get();
|
||||||
if (c == StreamType::traits_type::eof()) {
|
if(c == StreamType::traits_type::eof())
|
||||||
|
{
|
||||||
hasError = true;
|
hasError = true;
|
||||||
stream_.clear();
|
stream_.clear();
|
||||||
break;
|
break;
|
||||||
|
@ -90,7 +116,9 @@ public:
|
||||||
peekBuffer_[i] = static_cast<Ch>(c);
|
peekBuffer_[i] = static_cast<Ch>(c);
|
||||||
}
|
}
|
||||||
for(--i; i >= 0; --i)
|
for(--i; i >= 0; --i)
|
||||||
|
{
|
||||||
stream_.putback(peekBuffer_[i]);
|
stream_.putback(peekBuffer_[i]);
|
||||||
|
}
|
||||||
return !hasError ? peekBuffer_ : 0;
|
return !hasError ? peekBuffer_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
src/3rdparty/rapidjson/memorybuffer.h
vendored
42
src/3rdparty/rapidjson/memorybuffer.h
vendored
|
@ -34,24 +34,45 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
template <typename Allocator = CrtAllocator>
|
template <typename Allocator = CrtAllocator>
|
||||||
struct GenericMemoryBuffer {
|
struct GenericMemoryBuffer
|
||||||
|
{
|
||||||
typedef char Ch; // byte
|
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 Flush() {}
|
||||||
|
|
||||||
void Clear() { stack_.Clear(); }
|
void Clear()
|
||||||
void ShrinkToFit() { stack_.ShrinkToFit(); }
|
{
|
||||||
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
|
stack_.Clear();
|
||||||
void Pop(size_t count) { stack_.template Pop<Ch>(count); }
|
}
|
||||||
|
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>();
|
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;
|
static const size_t kDefaultCapacity = 256;
|
||||||
mutable internal::Stack<Allocator> stack_;
|
mutable internal::Stack<Allocator> stack_;
|
||||||
|
@ -61,7 +82,8 @@ typedef GenericMemoryBuffer<> MemoryBuffer;
|
||||||
|
|
||||||
//! Implement specialized version of PutN() with memset() for better performance.
|
//! Implement specialized version of PutN() with memset() for better performance.
|
||||||
template<>
|
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));
|
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
43
src/3rdparty/rapidjson/memorystream.h
vendored
43
src/3rdparty/rapidjson/memorystream.h
vendored
|
@ -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().
|
3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
struct MemoryStream {
|
struct MemoryStream
|
||||||
|
{
|
||||||
typedef char Ch; // byte
|
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 Peek() const
|
||||||
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
|
{
|
||||||
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
|
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; }
|
Ch* PutBegin()
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
{
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
RAPIDJSON_ASSERT(false);
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
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.
|
// For encoding detection only.
|
||||||
const Ch* Peek4() const {
|
const Ch* Peek4() const
|
||||||
|
{
|
||||||
return Tell() + 4 <= size_ ? src_ : 0;
|
return Tell() + 4 <= size_ ? src_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
src/3rdparty/rapidjson/ostreamwrapper.h
vendored
39
src/3rdparty/rapidjson/ostreamwrapper.h
vendored
|
@ -42,25 +42,48 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename StreamType>
|
template <typename StreamType>
|
||||||
class BasicOStreamWrapper {
|
class BasicOStreamWrapper
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename StreamType::char_type Ch;
|
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);
|
stream_.put(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Flush() {
|
void Flush()
|
||||||
|
{
|
||||||
stream_.flush();
|
stream_.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not implemented
|
// Not implemented
|
||||||
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
char Peek() const
|
||||||
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
{
|
||||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
RAPIDJSON_ASSERT(false);
|
||||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
return 0;
|
||||||
size_t PutEnd(char*) { 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:
|
private:
|
||||||
BasicOStreamWrapper(const BasicOStreamWrapper &);
|
BasicOStreamWrapper(const BasicOStreamWrapper &);
|
||||||
|
|
710
src/3rdparty/rapidjson/pointer.h
vendored
710
src/3rdparty/rapidjson/pointer.h
vendored
File diff suppressed because it is too large
Load diff
169
src/3rdparty/rapidjson/prettywriter.h
vendored
169
src/3rdparty/rapidjson/prettywriter.h
vendored
|
@ -27,7 +27,8 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
//! Combination of PrettyWriter format flags.
|
//! Combination of PrettyWriter format flags.
|
||||||
/*! \see PrettyWriter::SetFormatOptions
|
/*! \see PrettyWriter::SetFormatOptions
|
||||||
*/
|
*/
|
||||||
enum PrettyFormatOptions {
|
enum PrettyFormatOptions
|
||||||
|
{
|
||||||
kFormatDefault = 0, //!< Default pretty formatting.
|
kFormatDefault = 0, //!< Default pretty formatting.
|
||||||
kFormatSingleLineArray = 1 //!< Format arrays on a single line.
|
kFormatSingleLineArray = 1 //!< Format arrays on a single line.
|
||||||
};
|
};
|
||||||
|
@ -40,7 +41,8 @@ enum PrettyFormatOptions {
|
||||||
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
\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>
|
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:
|
public:
|
||||||
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
|
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
|
||||||
typedef typename Base::Ch Ch;
|
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 allocator User supplied allocator. If it is null, it will create a private one.
|
||||||
\param levelDepth Initial capacity of stack.
|
\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) {}
|
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +65,8 @@ public:
|
||||||
\param indentCharCount Number of indent characters for each indentation level.
|
\param indentCharCount Number of indent characters for each indentation level.
|
||||||
\note The default indentation is 4 spaces.
|
\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');
|
RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
|
||||||
indentChar_ = indentChar;
|
indentChar_ = indentChar;
|
||||||
indentCharCount_ = indentCharCount;
|
indentCharCount_ = indentCharCount;
|
||||||
|
@ -72,7 +76,8 @@ public:
|
||||||
//! Set pretty writer formatting options.
|
//! Set pretty writer formatting options.
|
||||||
/*! \param options Formatting options.
|
/*! \param options Formatting options.
|
||||||
*/
|
*/
|
||||||
PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
|
PrettyWriter & SetFormatOptions(PrettyFormatOptions options)
|
||||||
|
{
|
||||||
formatOptions_ = options;
|
formatOptions_ = options;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -82,53 +87,91 @@ public:
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
|
bool Null()
|
||||||
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
|
{
|
||||||
bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
|
PrettyPrefix(kNullType);
|
||||||
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
|
return Base::WriteNull();
|
||||||
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
|
}
|
||||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
|
bool Bool(bool b)
|
||||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
|
{
|
||||||
|
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;
|
(void)copy;
|
||||||
PrettyPrefix(kNumberType);
|
PrettyPrefix(kNumberType);
|
||||||
return Base::WriteString(str, length);
|
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;
|
(void)copy;
|
||||||
PrettyPrefix(kStringType);
|
PrettyPrefix(kStringType);
|
||||||
return Base::WriteString(str, length);
|
return Base::WriteString(str, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#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()));
|
return String(str.data(), SizeType(str.size()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool StartObject() {
|
bool StartObject()
|
||||||
|
{
|
||||||
PrettyPrefix(kObjectType);
|
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();
|
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
|
#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()));
|
return Key(str.data(), SizeType(str.size()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool EndObject(SizeType memberCount = 0) {
|
bool EndObject(SizeType memberCount = 0)
|
||||||
|
{
|
||||||
(void)memberCount;
|
(void)memberCount;
|
||||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||||
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||||
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||||
|
|
||||||
if (!empty) {
|
if(!empty)
|
||||||
|
{
|
||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
|
@ -136,23 +179,28 @@ public:
|
||||||
(void)ret;
|
(void)ret;
|
||||||
RAPIDJSON_ASSERT(ret == true);
|
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();
|
Base::os_->Flush();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartArray() {
|
bool StartArray()
|
||||||
|
{
|
||||||
PrettyPrefix(kArrayType);
|
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();
|
return Base::WriteStartArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EndArray(SizeType memberCount = 0) {
|
bool EndArray(SizeType memberCount = 0)
|
||||||
|
{
|
||||||
(void)memberCount;
|
(void)memberCount;
|
||||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||||
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||||
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
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');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
|
@ -160,7 +208,9 @@ public:
|
||||||
(void)ret;
|
(void)ret;
|
||||||
RAPIDJSON_ASSERT(ret == true);
|
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();
|
Base::os_->Flush();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,8 +220,14 @@ public:
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Simpler but slower overload.
|
//! Simpler but slower overload.
|
||||||
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
bool String(const Ch* str)
|
||||||
bool Key(const Ch* str) { return Key(str, internal::StrLen(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.
|
\param type Type of the root of json.
|
||||||
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
|
\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); }
|
bool RawValue(const Ch* json, size_t length, Type type)
|
||||||
|
{
|
||||||
protected:
|
PrettyPrefix(type);
|
||||||
void PrettyPrefix(Type type) {
|
return Base::WriteRawValue(json, length);
|
||||||
(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)) {
|
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');
|
Base::os_->Put('\n');
|
||||||
WriteIndent();
|
WriteIndent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // in object
|
else // in object
|
||||||
if (level->valueCount > 0) {
|
{
|
||||||
if (level->valueCount % 2 == 0) {
|
if(level->valueCount > 0)
|
||||||
|
{
|
||||||
|
if(level->valueCount % 2 == 0)
|
||||||
|
{
|
||||||
Base::os_->Put(',');
|
Base::os_->Put(',');
|
||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
Base::os_->Put(':');
|
Base::os_->Put(':');
|
||||||
Base::os_->Put(' ');
|
Base::os_->Put(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Base::os_->Put('\n');
|
Base::os_->Put('\n');
|
||||||
|
}
|
||||||
|
|
||||||
if(level->valueCount % 2 == 0)
|
if(level->valueCount % 2 == 0)
|
||||||
|
{
|
||||||
WriteIndent();
|
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
|
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||||
|
}
|
||||||
level->valueCount++;
|
level->valueCount++;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
|
RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
|
||||||
Base::hasRoot_ = true;
|
Base::hasRoot_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteIndent() {
|
void WriteIndent()
|
||||||
|
{
|
||||||
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
||||||
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
|
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
|
||||||
}
|
}
|
||||||
|
|
8
src/3rdparty/rapidjson/rapidjson.h
vendored
8
src/3rdparty/rapidjson/rapidjson.h
vendored
|
@ -411,7 +411,10 @@ RAPIDJSON_NAMESPACE_END
|
||||||
#endif
|
#endif
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
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 {};
|
template<int x> struct StaticAssertTest {};
|
||||||
RAPIDJSON_NAMESPACE_END
|
RAPIDJSON_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -599,7 +602,8 @@ RAPIDJSON_NAMESPACE_END
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
//! Type of JSON value
|
//! Type of JSON value
|
||||||
enum Type {
|
enum Type
|
||||||
|
{
|
||||||
kNullType = 0, //!< null
|
kNullType = 0, //!< null
|
||||||
kFalseType = 1, //!< false
|
kFalseType = 1, //!< false
|
||||||
kTrueType = 2, //!< true
|
kTrueType = 2, //!< true
|
||||||
|
|
941
src/3rdparty/rapidjson/reader.h
vendored
941
src/3rdparty/rapidjson/reader.h
vendored
File diff suppressed because it is too large
Load diff
1269
src/3rdparty/rapidjson/schema.h
vendored
1269
src/3rdparty/rapidjson/schema.h
vendored
File diff suppressed because it is too large
Load diff
106
src/3rdparty/rapidjson/stream.h
vendored
106
src/3rdparty/rapidjson/stream.h
vendored
|
@ -70,7 +70,8 @@ concept Stream {
|
||||||
See TEST(Reader, CustomStringStream) in readertest.cpp for example.
|
See TEST(Reader, CustomStringStream) in readertest.cpp for example.
|
||||||
*/
|
*/
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
struct StreamTraits {
|
struct StreamTraits
|
||||||
|
{
|
||||||
//! Whether to make local copy of stream for optimization during parsing.
|
//! Whether to make local copy of stream for optimization during parsing.
|
||||||
/*!
|
/*!
|
||||||
By default, for safety, streams do not use local copy optimization.
|
By default, for safety, streams do not use local copy optimization.
|
||||||
|
@ -81,24 +82,29 @@ struct StreamTraits {
|
||||||
|
|
||||||
//! Reserve n characters for writing to a stream.
|
//! Reserve n characters for writing to a stream.
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline void PutReserve(Stream& stream, size_t count) {
|
inline void PutReserve(Stream & stream, size_t count)
|
||||||
|
{
|
||||||
(void)stream;
|
(void)stream;
|
||||||
(void)count;
|
(void)count;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Write character to a stream, presuming buffer is reserved.
|
//! Write character to a stream, presuming buffer is reserved.
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
|
inline void PutUnsafe(Stream & stream, typename Stream::Ch c)
|
||||||
|
{
|
||||||
stream.Put(c);
|
stream.Put(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Put N copies of a character to a stream.
|
//! Put N copies of a character to a stream.
|
||||||
template<typename Stream, typename Ch>
|
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);
|
PutReserve(stream, n);
|
||||||
for(size_t i = 0; i < n; i++)
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
PutUnsafe(stream, c);
|
PutUnsafe(stream, c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// StringStream
|
// StringStream
|
||||||
|
@ -107,26 +113,51 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
|
||||||
/*! \note implements Stream concept
|
/*! \note implements Stream concept
|
||||||
*/
|
*/
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct GenericStringStream {
|
struct GenericStringStream
|
||||||
|
{
|
||||||
typedef typename Encoding::Ch Ch;
|
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 Peek() const
|
||||||
Ch Take() { return *src_++; }
|
{
|
||||||
size_t Tell() const { return static_cast<size_t>(src_ - head_); }
|
return *src_;
|
||||||
|
}
|
||||||
|
Ch Take()
|
||||||
|
{
|
||||||
|
return *src_++;
|
||||||
|
}
|
||||||
|
size_t Tell() const
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(src_ - head_);
|
||||||
|
}
|
||||||
|
|
||||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
Ch* PutBegin()
|
||||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
{
|
||||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
RAPIDJSON_ASSERT(false);
|
||||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
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* src_; //!< Current read position.
|
||||||
const Ch* head_; //!< Original head of the string.
|
const Ch* head_; //!< Original head of the string.
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct StreamTraits<GenericStringStream<Encoding> > {
|
struct StreamTraits<GenericStringStream<Encoding>>
|
||||||
|
{
|
||||||
enum { copyOptimization = 1 };
|
enum { copyOptimization = 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,25 +172,53 @@ typedef GenericStringStream<UTF8<> > StringStream;
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct GenericInsituStringStream {
|
struct GenericInsituStringStream
|
||||||
|
{
|
||||||
typedef typename Encoding::Ch Ch;
|
typedef typename Encoding::Ch Ch;
|
||||||
|
|
||||||
GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {}
|
GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {}
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
Ch Peek() { return *src_; }
|
Ch Peek()
|
||||||
Ch Take() { return *src_++; }
|
{
|
||||||
size_t Tell() { return static_cast<size_t>(src_ - head_); }
|
return *src_;
|
||||||
|
}
|
||||||
|
Ch Take()
|
||||||
|
{
|
||||||
|
return *src_++;
|
||||||
|
}
|
||||||
|
size_t Tell()
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(src_ - head_);
|
||||||
|
}
|
||||||
|
|
||||||
// Write
|
// 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_; }
|
Ch* PutBegin()
|
||||||
size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
|
{
|
||||||
|
return dst_ = src_;
|
||||||
|
}
|
||||||
|
size_t PutEnd(Ch* begin)
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(dst_ - begin);
|
||||||
|
}
|
||||||
void Flush() {}
|
void Flush() {}
|
||||||
|
|
||||||
Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
|
Ch* Push(size_t count)
|
||||||
void Pop(size_t count) { dst_ -= count; }
|
{
|
||||||
|
Ch* begin = dst_;
|
||||||
|
dst_ += count;
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
void Pop(size_t count)
|
||||||
|
{
|
||||||
|
dst_ -= count;
|
||||||
|
}
|
||||||
|
|
||||||
Ch* src_;
|
Ch* src_;
|
||||||
Ch* dst_;
|
Ch* dst_;
|
||||||
|
@ -167,7 +226,8 @@ struct GenericInsituStringStream {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct StreamTraits<GenericInsituStringStream<Encoding> > {
|
struct StreamTraits<GenericInsituStringStream<Encoding>>
|
||||||
|
{
|
||||||
enum { copyOptimization = 1 };
|
enum { copyOptimization = 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
66
src/3rdparty/rapidjson/stringbuffer.h
vendored
66
src/3rdparty/rapidjson/stringbuffer.h
vendored
|
@ -38,39 +38,67 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
\note implements Stream concept
|
\note implements Stream concept
|
||||||
*/
|
*/
|
||||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||||
class GenericStringBuffer {
|
class GenericStringBuffer
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch;
|
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
|
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||||
GenericStringBuffer(GenericStringBuffer && rhs) : stack_(std::move(rhs.stack_)) {}
|
GenericStringBuffer(GenericStringBuffer && rhs) : stack_(std::move(rhs.stack_)) {}
|
||||||
GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
|
GenericStringBuffer & operator=(GenericStringBuffer && rhs)
|
||||||
|
{
|
||||||
if(&rhs != this)
|
if(&rhs != this)
|
||||||
|
{
|
||||||
stack_ = std::move(rhs.stack_);
|
stack_ = std::move(rhs.stack_);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
|
void Put(Ch c)
|
||||||
void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
|
{
|
||||||
|
*stack_.template Push<Ch>() = c;
|
||||||
|
}
|
||||||
|
void PutUnsafe(Ch c)
|
||||||
|
{
|
||||||
|
*stack_.template PushUnsafe<Ch>() = c;
|
||||||
|
}
|
||||||
void Flush() {}
|
void Flush() {}
|
||||||
|
|
||||||
void Clear() { stack_.Clear(); }
|
void Clear()
|
||||||
void ShrinkToFit() {
|
{
|
||||||
|
stack_.Clear();
|
||||||
|
}
|
||||||
|
void ShrinkToFit()
|
||||||
|
{
|
||||||
// Push and pop a null terminator. This is safe.
|
// Push and pop a null terminator. This is safe.
|
||||||
*stack_.template Push<Ch>() = '\0';
|
*stack_.template Push<Ch>() = '\0';
|
||||||
stack_.ShrinkToFit();
|
stack_.ShrinkToFit();
|
||||||
stack_.template Pop<Ch>(1);
|
stack_.template Pop<Ch>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
|
void Reserve(size_t count)
|
||||||
Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
|
{
|
||||||
Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
|
stack_.template Reserve<Ch>(count);
|
||||||
void Pop(size_t count) { stack_.template Pop<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.
|
// Push and pop a null terminator. This is safe.
|
||||||
*stack_.template Push<Ch>() = '\0';
|
*stack_.template Push<Ch>() = '\0';
|
||||||
stack_.template Pop<Ch>(1);
|
stack_.template Pop<Ch>(1);
|
||||||
|
@ -78,7 +106,10 @@ public:
|
||||||
return stack_.template Bottom<Ch>();
|
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;
|
static const size_t kDefaultCapacity = 256;
|
||||||
mutable internal::Stack<Allocator> stack_;
|
mutable internal::Stack<Allocator> stack_;
|
||||||
|
@ -93,18 +124,21 @@ private:
|
||||||
typedef GenericStringBuffer<UTF8<>> StringBuffer;
|
typedef GenericStringBuffer<UTF8<>> StringBuffer;
|
||||||
|
|
||||||
template<typename Encoding, typename Allocator>
|
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);
|
stream.Reserve(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Encoding, typename Allocator>
|
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);
|
stream.PutUnsafe(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Implement specialized version of PutN() with memset() for better performance.
|
//! Implement specialized version of PutN() with memset() for better performance.
|
||||||
template<>
|
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));
|
std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
351
src/3rdparty/rapidjson/writer.h
vendored
351
src/3rdparty/rapidjson/writer.h
vendored
|
@ -60,7 +60,8 @@ RAPIDJSON_NAMESPACE_BEGIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Combination of writeFlags
|
//! Combination of writeFlags
|
||||||
enum WriteFlag {
|
enum WriteFlag
|
||||||
|
{
|
||||||
kWriteNoFlags = 0, //!< No flags are set.
|
kWriteNoFlags = 0, //!< No flags are set.
|
||||||
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
|
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
|
||||||
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
|
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
|
||||||
|
@ -84,7 +85,8 @@ enum WriteFlag {
|
||||||
\note implements Handler concept
|
\note implements Handler concept
|
||||||
*/
|
*/
|
||||||
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
||||||
class Writer {
|
class Writer
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename SourceEncoding::Ch Ch;
|
typedef typename SourceEncoding::Ch Ch;
|
||||||
|
|
||||||
|
@ -97,11 +99,13 @@ public:
|
||||||
*/
|
*/
|
||||||
explicit
|
explicit
|
||||||
Writer(OutputStream & os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
Writer(OutputStream & os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||||
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
|
os_(&os), level_stack_(stackAllocator, levelDepth* sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces),
|
||||||
|
hasRoot_(false) {}
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
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.
|
//! Reset the writer with a new stream.
|
||||||
/*!
|
/*!
|
||||||
|
@ -121,7 +125,8 @@ public:
|
||||||
writer.EndObject();
|
writer.EndObject();
|
||||||
\endcode
|
\endcode
|
||||||
*/
|
*/
|
||||||
void Reset(OutputStream& os) {
|
void Reset(OutputStream & os)
|
||||||
|
{
|
||||||
os_ = &os;
|
os_ = &os;
|
||||||
hasRoot_ = false;
|
hasRoot_ = false;
|
||||||
level_stack_.Clear();
|
level_stack_.Clear();
|
||||||
|
@ -131,11 +136,13 @@ public:
|
||||||
/*!
|
/*!
|
||||||
A complete JSON has a complete root object or array.
|
A complete JSON has a complete root object or array.
|
||||||
*/
|
*/
|
||||||
bool IsComplete() const {
|
bool IsComplete() const
|
||||||
|
{
|
||||||
return hasRoot_ && level_stack_.Empty();
|
return hasRoot_ && level_stack_.Empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMaxDecimalPlaces() const {
|
int GetMaxDecimalPlaces() const
|
||||||
|
{
|
||||||
return maxDecimalPlaces_;
|
return maxDecimalPlaces_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +167,8 @@ public:
|
||||||
writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
|
writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
|
||||||
\endcode
|
\endcode
|
||||||
*/
|
*/
|
||||||
void SetMaxDecimalPlaces(int maxDecimalPlaces) {
|
void SetMaxDecimalPlaces(int maxDecimalPlaces)
|
||||||
|
{
|
||||||
maxDecimalPlaces_ = maxDecimalPlaces;
|
maxDecimalPlaces_ = maxDecimalPlaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,47 +177,83 @@ public:
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
|
bool Null()
|
||||||
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
|
{
|
||||||
bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
|
Prefix(kNullType);
|
||||||
bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
|
return EndValue(WriteNull());
|
||||||
bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
|
}
|
||||||
bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
|
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
|
//! Writes the given \c double value to the stream
|
||||||
/*!
|
/*!
|
||||||
\param d The value to be written.
|
\param d The value to be written.
|
||||||
\return Whether it is succeed.
|
\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;
|
(void)copy;
|
||||||
Prefix(kNumberType);
|
Prefix(kNumberType);
|
||||||
return EndValue(WriteString(str, length));
|
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;
|
(void)copy;
|
||||||
Prefix(kStringType);
|
Prefix(kStringType);
|
||||||
return EndValue(WriteString(str, length));
|
return EndValue(WriteString(str, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RAPIDJSON_HAS_STDSTRING
|
#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()));
|
return String(str.data(), SizeType(str.size()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool StartObject() {
|
bool StartObject()
|
||||||
|
{
|
||||||
Prefix(kObjectType);
|
Prefix(kObjectType);
|
||||||
new(level_stack_.template Push<Level>()) Level(false);
|
new(level_stack_.template Push<Level>()) Level(false);
|
||||||
return WriteStartObject();
|
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;
|
(void)memberCount;
|
||||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||||
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
|
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
|
||||||
|
@ -217,13 +261,15 @@ public:
|
||||||
return EndValue(WriteEndObject());
|
return EndValue(WriteEndObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartArray() {
|
bool StartArray()
|
||||||
|
{
|
||||||
Prefix(kArrayType);
|
Prefix(kArrayType);
|
||||||
new(level_stack_.template Push<Level>()) Level(true);
|
new(level_stack_.template Push<Level>()) Level(true);
|
||||||
return WriteStartArray();
|
return WriteStartArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EndArray(SizeType elementCount = 0) {
|
bool EndArray(SizeType elementCount = 0)
|
||||||
|
{
|
||||||
(void)elementCount;
|
(void)elementCount;
|
||||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||||
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
|
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
|
||||||
|
@ -236,8 +282,14 @@ public:
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
//! Simpler but slower overload.
|
//! Simpler but slower overload.
|
||||||
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
bool String(const Ch* str)
|
||||||
bool Key(const Ch* str) { return Key(str, internal::StrLen(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 length Length of the json.
|
||||||
\param type Type of the root of 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:
|
protected:
|
||||||
//! Information for each nested level
|
//! Information for each nested level
|
||||||
struct Level {
|
struct Level
|
||||||
|
{
|
||||||
Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
|
Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
|
||||||
size_t valueCount; //!< number of values in this level
|
size_t valueCount; //!< number of values in this level
|
||||||
bool inArray; //!< true if in array, otherwise in object
|
bool inArray; //!< true if in array, otherwise in object
|
||||||
|
@ -261,76 +318,119 @@ protected:
|
||||||
|
|
||||||
static const size_t kDefaultLevelDepth = 32;
|
static const size_t kDefaultLevelDepth = 32;
|
||||||
|
|
||||||
bool WriteNull() {
|
bool WriteNull()
|
||||||
|
{
|
||||||
PutReserve(*os_, 4);
|
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) {
|
bool WriteBool(bool b)
|
||||||
if (b) {
|
{
|
||||||
|
if(b)
|
||||||
|
{
|
||||||
PutReserve(*os_, 4);
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteInt(int i) {
|
bool WriteInt(int i)
|
||||||
|
{
|
||||||
char buffer[11];
|
char buffer[11];
|
||||||
const char* end = internal::i32toa(i, buffer);
|
const char* end = internal::i32toa(i, buffer);
|
||||||
PutReserve(*os_, static_cast<size_t>(end - 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));
|
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteUint(unsigned u) {
|
bool WriteUint(unsigned u)
|
||||||
|
{
|
||||||
char buffer[10];
|
char buffer[10];
|
||||||
const char* end = internal::u32toa(u, buffer);
|
const char* end = internal::u32toa(u, buffer);
|
||||||
PutReserve(*os_, static_cast<size_t>(end - 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));
|
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteInt64(int64_t i64) {
|
bool WriteInt64(int64_t i64)
|
||||||
|
{
|
||||||
char buffer[21];
|
char buffer[21];
|
||||||
const char* end = internal::i64toa(i64, buffer);
|
const char* end = internal::i64toa(i64, buffer);
|
||||||
PutReserve(*os_, static_cast<size_t>(end - 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));
|
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteUint64(uint64_t u64) {
|
bool WriteUint64(uint64_t u64)
|
||||||
|
{
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
char* end = internal::u64toa(u64, buffer);
|
char* end = internal::u64toa(u64, buffer);
|
||||||
PutReserve(*os_, static_cast<size_t>(end - 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));
|
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteDouble(double d) {
|
bool WriteDouble(double d)
|
||||||
if (internal::Double(d).IsNanOrInf()) {
|
{
|
||||||
|
if(internal::Double(d).IsNanOrInf())
|
||||||
|
{
|
||||||
if(!(writeFlags & kWriteNanAndInfFlag))
|
if(!(writeFlags & kWriteNanAndInfFlag))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
if (internal::Double(d).IsNan()) {
|
}
|
||||||
|
if(internal::Double(d).IsNan())
|
||||||
|
{
|
||||||
PutReserve(*os_, 3);
|
PutReserve(*os_, 3);
|
||||||
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
|
PutUnsafe(*os_, 'N');
|
||||||
|
PutUnsafe(*os_, 'a');
|
||||||
|
PutUnsafe(*os_, 'N');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (internal::Double(d).Sign()) {
|
if(internal::Double(d).Sign())
|
||||||
|
{
|
||||||
PutReserve(*os_, 9);
|
PutReserve(*os_, 9);
|
||||||
PutUnsafe(*os_, '-');
|
PutUnsafe(*os_, '-');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
PutReserve(*os_, 8);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,13 +438,17 @@ protected:
|
||||||
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
|
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
|
||||||
PutReserve(*os_, static_cast<size_t>(end - 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));
|
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||||
|
}
|
||||||
return true;
|
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 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
|
#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
|
//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', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
|
||||||
|
@ -357,28 +461,38 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
if(TargetEncoding::supportUnicode)
|
if(TargetEncoding::supportUnicode)
|
||||||
|
{
|
||||||
PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
|
PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
|
PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
|
||||||
|
}
|
||||||
|
|
||||||
PutUnsafe(*os_, '\"');
|
PutUnsafe(*os_, '\"');
|
||||||
GenericStringStream<SourceEncoding> is(str);
|
GenericStringStream<SourceEncoding> is(str);
|
||||||
while (ScanWriteUnescapedString(is, length)) {
|
while(ScanWriteUnescapedString(is, length))
|
||||||
|
{
|
||||||
const Ch c = is.Peek();
|
const Ch c = is.Peek();
|
||||||
if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
|
if(!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80)
|
||||||
|
{
|
||||||
// Unicode escaping
|
// Unicode escaping
|
||||||
unsigned codepoint;
|
unsigned codepoint;
|
||||||
if(RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
|
if(RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
PutUnsafe(*os_, '\\');
|
PutUnsafe(*os_, '\\');
|
||||||
PutUnsafe(*os_, 'u');
|
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 >> 12) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
|
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
|
||||||
PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 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);
|
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
||||||
// Surrogate pair
|
// Surrogate pair
|
||||||
unsigned s = codepoint - 0x010000;
|
unsigned s = codepoint - 0x010000;
|
||||||
|
@ -396,11 +510,14 @@ protected:
|
||||||
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();
|
is.Take();
|
||||||
PutUnsafe(*os_, '\\');
|
PutUnsafe(*os_, '\\');
|
||||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
|
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_, '0');
|
PutUnsafe(*os_, '0');
|
||||||
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
|
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
|
||||||
|
@ -410,54 +527,88 @@ protected:
|
||||||
else if(RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
else if(RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||||
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
||||||
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PutUnsafe(*os_, '\"');
|
PutUnsafe(*os_, '\"');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
|
bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding> & is, size_t length)
|
||||||
|
{
|
||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteStartObject() { os_->Put('{'); return true; }
|
bool WriteStartObject()
|
||||||
bool WriteEndObject() { os_->Put('}'); return true; }
|
{
|
||||||
bool WriteStartArray() { os_->Put('['); return true; }
|
os_->Put('{');
|
||||||
bool WriteEndArray() { os_->Put(']'); return true; }
|
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);
|
PutReserve(*os_, length);
|
||||||
for (size_t i = 0; i < length; i++) {
|
for(size_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(json[i] != '\0');
|
RAPIDJSON_ASSERT(json[i] != '\0');
|
||||||
PutUnsafe(*os_, json[i]);
|
PutUnsafe(*os_, json[i]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Prefix(Type type) {
|
void Prefix(Type type)
|
||||||
|
{
|
||||||
(void)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>();
|
Level* level = level_stack_.template Top<Level>();
|
||||||
if (level->valueCount > 0) {
|
if(level->valueCount > 0)
|
||||||
|
{
|
||||||
if(level->inArray)
|
if(level->inArray)
|
||||||
|
{
|
||||||
os_->Put(','); // add comma if it is not the first element in array
|
os_->Put(','); // add comma if it is not the first element in array
|
||||||
|
}
|
||||||
else // in object
|
else // in object
|
||||||
|
{
|
||||||
os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
|
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
|
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||||
|
}
|
||||||
level->valueCount++;
|
level->valueCount++;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
|
RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
|
||||||
hasRoot_ = true;
|
hasRoot_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush the value if it is the top level one.
|
// Flush the value if it is the top level one.
|
||||||
bool EndValue(bool ret) {
|
bool EndValue(bool ret)
|
||||||
|
{
|
||||||
if(RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
|
if(RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
|
||||||
|
{
|
||||||
os_->Flush();
|
os_->Flush();
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +626,8 @@ private:
|
||||||
// Full specialization for StringStream to prevent memory copying
|
// Full specialization for StringStream to prevent memory copying
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::WriteInt(int i) {
|
inline bool Writer<StringBuffer>::WriteInt(int i)
|
||||||
|
{
|
||||||
char* buffer = os_->Push(11);
|
char* buffer = os_->Push(11);
|
||||||
const char* end = internal::i32toa(i, buffer);
|
const char* end = internal::i32toa(i, buffer);
|
||||||
os_->Pop(static_cast<size_t>(11 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(11 - (end - buffer)));
|
||||||
|
@ -483,7 +635,8 @@ inline bool Writer<StringBuffer>::WriteInt(int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
|
inline bool Writer<StringBuffer>::WriteUint(unsigned u)
|
||||||
|
{
|
||||||
char* buffer = os_->Push(10);
|
char* buffer = os_->Push(10);
|
||||||
const char* end = internal::u32toa(u, buffer);
|
const char* end = internal::u32toa(u, buffer);
|
||||||
os_->Pop(static_cast<size_t>(10 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(10 - (end - buffer)));
|
||||||
|
@ -491,7 +644,8 @@ inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
|
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64)
|
||||||
|
{
|
||||||
char* buffer = os_->Push(21);
|
char* buffer = os_->Push(21);
|
||||||
const char* end = internal::i64toa(i64, buffer);
|
const char* end = internal::i64toa(i64, buffer);
|
||||||
os_->Pop(static_cast<size_t>(21 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(21 - (end - buffer)));
|
||||||
|
@ -499,7 +653,8 @@ inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
|
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u)
|
||||||
|
{
|
||||||
char* buffer = os_->Push(20);
|
char* buffer = os_->Push(20);
|
||||||
const char* end = internal::u64toa(u, buffer);
|
const char* end = internal::u64toa(u, buffer);
|
||||||
os_->Pop(static_cast<size_t>(20 - (end - buffer)));
|
os_->Pop(static_cast<size_t>(20 - (end - buffer)));
|
||||||
|
@ -507,24 +662,40 @@ inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
inline bool Writer<StringBuffer>::WriteDouble(double d)
|
||||||
if (internal::Double(d).IsNanOrInf()) {
|
{
|
||||||
|
if(internal::Double(d).IsNanOrInf())
|
||||||
|
{
|
||||||
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
|
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
|
||||||
if(!(kWriteDefaultFlags & kWriteNanAndInfFlag))
|
if(!(kWriteDefaultFlags & kWriteNanAndInfFlag))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
if (internal::Double(d).IsNan()) {
|
}
|
||||||
|
if(internal::Double(d).IsNan())
|
||||||
|
{
|
||||||
PutReserve(*os_, 3);
|
PutReserve(*os_, 3);
|
||||||
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
|
PutUnsafe(*os_, 'N');
|
||||||
|
PutUnsafe(*os_, 'a');
|
||||||
|
PutUnsafe(*os_, 'N');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (internal::Double(d).Sign()) {
|
if(internal::Double(d).Sign())
|
||||||
|
{
|
||||||
PutReserve(*os_, 9);
|
PutReserve(*os_, 9);
|
||||||
PutUnsafe(*os_, '-');
|
PutUnsafe(*os_, '-');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
PutReserve(*os_, 8);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,27 +707,39 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
||||||
|
|
||||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
|
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
|
||||||
template<>
|
template<>
|
||||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream & is, size_t length)
|
||||||
|
{
|
||||||
if(length < 16)
|
if(length < 16)
|
||||||
|
{
|
||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
|
}
|
||||||
|
|
||||||
if(!RAPIDJSON_LIKELY(is.Tell() < length))
|
if(!RAPIDJSON_LIKELY(is.Tell() < length))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const char* p = is.src_;
|
const char* p = is.src_;
|
||||||
const char* end = is.head_ + length;
|
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* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>
|
||||||
const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
|
(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)
|
if(nextAligned > end)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
while(p != nextAligned)
|
while(p != nextAligned)
|
||||||
if (*p < 0x20 || *p == '\"' || *p == '\\') {
|
if(*p < 0x20 || *p == '\"' || *p == '\\')
|
||||||
|
{
|
||||||
is.src_ = p;
|
is.src_ = p;
|
||||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
os_->PutUnsafe(*p++);
|
os_->PutUnsafe(*p++);
|
||||||
|
}
|
||||||
|
|
||||||
// The rest of string using SIMD
|
// The rest of string using SIMD
|
||||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||||
|
@ -566,14 +749,16 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||||
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[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 sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0]));
|
||||||
|
|
||||||
for (; p != endAligned; p += 16) {
|
for(; p != endAligned; p += 16)
|
||||||
|
{
|
||||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
|
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p));
|
||||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
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 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);
|
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
|
||||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
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;
|
SizeType len;
|
||||||
#ifdef _MSC_VER // Find the index of first escaped
|
#ifdef _MSC_VER // Find the index of first escaped
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
|
@ -584,7 +769,9 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||||
#endif
|
#endif
|
||||||
char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
|
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];
|
q[i] = p[i];
|
||||||
|
}
|
||||||
|
|
||||||
p += len;
|
p += len;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -33,18 +33,23 @@
|
||||||
|
|
||||||
void App::background()
|
void App::background()
|
||||||
{
|
{
|
||||||
if (m_options->affinity() != -1L) {
|
if(m_options->affinity() != -1L)
|
||||||
|
{
|
||||||
Cpu::setAffinity(-1, m_options->affinity());
|
Cpu::setAffinity(-1, m_options->affinity());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_options->background()) {
|
if(!m_options->background())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND hcon = GetConsoleWindow();
|
HWND hcon = GetConsoleWindow();
|
||||||
if (hcon) {
|
if(hcon)
|
||||||
|
{
|
||||||
ShowWindow(hcon, SW_HIDE);
|
ShowWindow(hcon, SW_HIDE);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
FreeConsole();
|
FreeConsole();
|
||||||
|
|
|
@ -32,7 +32,8 @@ Console::Console(IConsoleListener *listener)
|
||||||
m_tty.data = this;
|
m_tty.data = this;
|
||||||
uv_tty_init(uv_default_loop(), &m_tty, 0, 1);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,11 +52,13 @@ 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);
|
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]);
|
static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
src/Mem.h
28
src/Mem.h
|
@ -38,7 +38,8 @@ struct cryptonight_ctx;
|
||||||
class Mem
|
class Mem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Flags
|
||||||
|
{
|
||||||
HugepagesAvailable = 1,
|
HugepagesAvailable = 1,
|
||||||
HugepagesEnabled = 2,
|
HugepagesEnabled = 2,
|
||||||
Lock = 4
|
Lock = 4
|
||||||
|
@ -49,11 +50,26 @@ public:
|
||||||
static void* calloc(size_t num, size_t size);
|
static void* calloc(size_t num, size_t size);
|
||||||
static void release();
|
static void release();
|
||||||
|
|
||||||
static inline bool isDoubleHash() { return m_doubleHash; }
|
static inline bool isDoubleHash()
|
||||||
static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
|
{
|
||||||
static inline bool isHugepagesEnabled() { return (m_flags & HugepagesEnabled) != 0; }
|
return m_doubleHash;
|
||||||
static inline int flags() { return m_flags; }
|
}
|
||||||
static inline int threads() { return m_threads; }
|
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:
|
private:
|
||||||
static bool m_doubleHash;
|
static bool m_doubleHash;
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
App app(argc, argv);
|
App app(argc, argv);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue