start repository for mobilisis tariff-calculation
This commit is contained in:
		
							
								
								
									
										1
									
								
								library/include/mobilisis/.gdb_history
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								library/include/mobilisis/.gdb_history
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
p 500.0/600*45
 | 
			
		||||
							
								
								
									
										1
									
								
								library/include/mobilisis/Header.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								library/include/mobilisis/Header.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
							
								
								
									
										9
									
								
								library/include/mobilisis/active_time_range.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								library/include/mobilisis/active_time_range.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "tariff_time_range.h"
 | 
			
		||||
 | 
			
		||||
struct ActiveTimeRange {
 | 
			
		||||
	bool isActive;
 | 
			
		||||
    TariffTimeRange timeRange;
 | 
			
		||||
    ActiveTimeRange() : isActive(false) {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										35
									
								
								library/include/mobilisis/calculate_price.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								library/include/mobilisis/calculate_price.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
#ifndef CALCULATE_PRICE_H
 | 
			
		||||
#define CALCULATE_PRICE_H
 | 
			
		||||
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
class Configuration;
 | 
			
		||||
 | 
			
		||||
typedef Configuration parking_tariff_t;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct price_t {
 | 
			
		||||
    uint32_t units;
 | 
			
		||||
    double netto;
 | 
			
		||||
    double brutto;
 | 
			
		||||
    double vat_percentage;
 | 
			
		||||
    double vat;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool init_tariff(parking_tariff_t **tariff, char const *config_file);
 | 
			
		||||
void free_tariff(parking_tariff_t *tariff);
 | 
			
		||||
int get_zone_nr();
 | 
			
		||||
 | 
			
		||||
bool compute_price_for_parking_ticket(parking_tariff_t *tariff,
 | 
			
		||||
                                      time_t start_parking_time,
 | 
			
		||||
                                      time_t end_parking_time,
 | 
			
		||||
                                      struct price_t *price);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
} // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // CALCULATE_PRICE_H
 | 
			
		||||
							
								
								
									
										29
									
								
								library/include/mobilisis/calculator_functions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								library/include/mobilisis/calculator_functions.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include "configuration.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
class Calculator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets duration in seconds from cost
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="tariff_cfg">Pointer to configuration</param>
 | 
			
		||||
	/// <param name="vehicle_type">Type of vehicle</param>
 | 
			
		||||
	/// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z)</param>
 | 
			
		||||
	/// <param name="price"></param>
 | 
			
		||||
	/// <returns>Returns duration in seconds (data type: double)</returns>
 | 
			
		||||
	std::string GetDurationFromCost(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double price, bool nextDay = false, bool prepaid = false);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	///  Gets cost from duration in seconds
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="tariff_cfg">Pointer to configuration</param>
 | 
			
		||||
	/// <param name="vehicle_type">Type of vehicle</param>
 | 
			
		||||
	/// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z) </param>
 | 
			
		||||
	/// <param name="durationMin">Duration of parking in minutes</param>
 | 
			
		||||
	/// <returns>Returns cost (data type: double)</returns>
 | 
			
		||||
	double GetCostFromDuration(Configuration* cfg, uint8_t vehicle_type, char const* start_datetime, double durationMin, bool nextDay = false, bool prepaid = false);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										58
									
								
								library/include/mobilisis/configuration.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								library/include/mobilisis/configuration.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <variant>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <rapidjson/rapidjson.h>
 | 
			
		||||
#include <rapidjson/document.h>
 | 
			
		||||
#include <rapidjson/error/en.h>
 | 
			
		||||
#include "member_type.h"
 | 
			
		||||
#include "currency.h"
 | 
			
		||||
#include "duration.h"
 | 
			
		||||
#include "payment_mtd.h"
 | 
			
		||||
#include "payment_opt.h"
 | 
			
		||||
#include "spec_days.h"
 | 
			
		||||
#include "payment_opt.h"
 | 
			
		||||
#include "weekdays.h"
 | 
			
		||||
#include "weekdays_worktime.h"
 | 
			
		||||
#include "spec_days_worktime.h"
 | 
			
		||||
#include "member_type.h"
 | 
			
		||||
#include "period_year.h"
 | 
			
		||||
#include "payment_rate.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace rapidjson;
 | 
			
		||||
 | 
			
		||||
class Configuration
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	ATBCurrency Currency;
 | 
			
		||||
	ATBDuration duration;
 | 
			
		||||
 | 
			
		||||
	multimap<int, ATBDuration> Duration;
 | 
			
		||||
	multimap<int, ATBPaymentMethod> PaymentMethod;
 | 
			
		||||
	multimap<int, ATBPaymentRate> PaymentRate;
 | 
			
		||||
	multimap<int, ATBSpecialDaysWorktime> SpecialDaysWorktime;
 | 
			
		||||
	multimap<int, ATBSpecialDays> SpecialDays;
 | 
			
		||||
	multimap<int, ATBWeekDays> WeekDays;
 | 
			
		||||
	multimap<int, ATBPeriodYear> YearPeriod;
 | 
			
		||||
	multimap<int, ATBWeekDaysWorktime> WeekDaysWorktime;
 | 
			
		||||
	multimap<int, ATBPaymentOption> PaymentOption;
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Parse JSON string
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="json"></param>
 | 
			
		||||
	/// <returns>Returns operation status bool (OK | FAIL) </returns>
 | 
			
		||||
	bool ParseJson(Configuration* cfg, const char* json);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Identify type of JSON member
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="member_name"></param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	MemberType IdentifyJsonMember(const char* member_name);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										12
									
								
								library/include/mobilisis/currency.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								library/include/mobilisis/currency.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBCurrency
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pcu_id;
 | 
			
		||||
	std::string pcu_sign;
 | 
			
		||||
	std::string pcu_major;
 | 
			
		||||
	std::string pcu_minor;
 | 
			
		||||
	bool pcu_active;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								library/include/mobilisis/day_of_week.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								library/include/mobilisis/day_of_week.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
enum DayOfWeek
 | 
			
		||||
{
 | 
			
		||||
	Saturday = 0x06,
 | 
			
		||||
	Sunday = 0x01,
 | 
			
		||||
	Monday = 0x02,
 | 
			
		||||
	Tuesday = 0x02,
 | 
			
		||||
	Wednesday = 0x03,
 | 
			
		||||
	Thursday = 0x04,
 | 
			
		||||
	Friday = 0x05,
 | 
			
		||||
	UndefinedDay = 0xFF
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										10
									
								
								library/include/mobilisis/duration.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								library/include/mobilisis/duration.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBDuration
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pun_id;
 | 
			
		||||
	std::string pun_label;
 | 
			
		||||
	int pun_duration;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										0
									
								
								library/include/mobilisis/log.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								library/include/mobilisis/log.h
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										16
									
								
								library/include/mobilisis/member_type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								library/include/mobilisis/member_type.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
enum MemberType
 | 
			
		||||
{
 | 
			
		||||
	UnknownType = 0xFF,
 | 
			
		||||
	CurrencyType = 0x00,
 | 
			
		||||
	PaymentMethodType = 0x01,
 | 
			
		||||
	PaymentRateType = 0x20,
 | 
			
		||||
	PaymentOptionType = 0x03,
 | 
			
		||||
	DurationType = 0x04,
 | 
			
		||||
	WeekDaysType = 0x05,
 | 
			
		||||
	WeekDaysWorkTimeType = 0x06,
 | 
			
		||||
	SpecialDaysWorktimeType = 0x07,
 | 
			
		||||
	SpecialDaysType = 0x08,
 | 
			
		||||
	PeriodYearType = 0x09
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										10
									
								
								library/include/mobilisis/payment_method.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								library/include/mobilisis/payment_method.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
enum PaymentMethod
 | 
			
		||||
{
 | 
			
		||||
	Undefined = 0xFF,
 | 
			
		||||
	Progressive = 0x01,
 | 
			
		||||
	Degressive = 0x02,
 | 
			
		||||
	Linear = 0x03,
 | 
			
		||||
	Steps = 0x04
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										9
									
								
								library/include/mobilisis/payment_mtd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								library/include/mobilisis/payment_mtd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBPaymentMethod
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pme_id;
 | 
			
		||||
	std::string pme_label;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										17
									
								
								library/include/mobilisis/payment_opt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								library/include/mobilisis/payment_opt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBPaymentOption
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pop_id;
 | 
			
		||||
	std::string pop_label;
 | 
			
		||||
	int pop_payment_method_id;
 | 
			
		||||
	std::string pop_day_end_time;
 | 
			
		||||
	std::string pop_day_night_end_time;
 | 
			
		||||
	double pop_price_night;
 | 
			
		||||
	double pop_min_time;
 | 
			
		||||
	double pop_max_time;
 | 
			
		||||
	double pop_min_price;
 | 
			
		||||
	int pop_carry_over;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										9
									
								
								library/include/mobilisis/payment_option.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								library/include/mobilisis/payment_option.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Payment option is related to payment_method_id (e.g. option 1 = linear)
 | 
			
		||||
enum PaymentOption
 | 
			
		||||
{
 | 
			
		||||
	Option1 = 0x03,
 | 
			
		||||
	Option2 = 0x02,
 | 
			
		||||
	Option3 = 0x01
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										9
									
								
								library/include/mobilisis/payment_rate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								library/include/mobilisis/payment_rate.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
class ATBPaymentRate
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pra_payment_option_id;
 | 
			
		||||
	int pra_payment_unit_id;
 | 
			
		||||
	double pra_price;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								library/include/mobilisis/period_year.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								library/include/mobilisis/period_year.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBPeriodYear
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pye_id;
 | 
			
		||||
	std::string pye_label;
 | 
			
		||||
	int pye_start_month;
 | 
			
		||||
	int pye_start_day;
 | 
			
		||||
	int pye_end_month;
 | 
			
		||||
	int pye_end_day;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								library/include/mobilisis/spec_days.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								library/include/mobilisis/spec_days.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBSpecialDays
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int ped_id;
 | 
			
		||||
	std::string ped_label;
 | 
			
		||||
	std::string ped_date_start;
 | 
			
		||||
	std::string ped_date_end;
 | 
			
		||||
	int ped_period_special_day_id;
 | 
			
		||||
	int ped_year;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										12
									
								
								library/include/mobilisis/spec_days_worktime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								library/include/mobilisis/spec_days_worktime.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBSpecialDaysWorktime
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pedwt_id;
 | 
			
		||||
	int pedwt_period_exc_day_id;
 | 
			
		||||
	std::string pedwt_time_from;
 | 
			
		||||
	std::string pedwt_time_to;
 | 
			
		||||
	double pedwt_price;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										34
									
								
								library/include/mobilisis/tariff_calc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								library/include/mobilisis/tariff_calc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include "tariff_cfg.h"
 | 
			
		||||
#include "tariff_utils.h"
 | 
			
		||||
#include "tariff_payment_method.h"
 | 
			
		||||
#include "tariff_vehicle_types.h"
 | 
			
		||||
#include "tariff_time_range.h"
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Definition of TariffCalculator class
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffCalculator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Gets duration in seconds from cost
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="tariff_cfg">Pointer to configuration</param>
 | 
			
		||||
	/// <param name="vehicle_type">Type of vehicle</param>
 | 
			
		||||
	/// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z)</param>
 | 
			
		||||
	/// <param name="price"></param>
 | 
			
		||||
	/// <returns>Returns duration in seconds (data type: double)</returns>
 | 
			
		||||
    double GetDurationFromCost(TariffConfiguration* tariff_cfg, uint8_t vehicle_type, char const *start_datetime, double price);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	///  Gets cost from duration in seconds
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="tariff_cfg">Pointer to configuration</param>
 | 
			
		||||
	/// <param name="vehicle_type">Type of vehicle</param>
 | 
			
		||||
	/// <param name="start_datetime">Date/time of payment to be conducted in ISO8601 format (e.g. 2022-12-25T08:00:00Z) </param>
 | 
			
		||||
	/// <param name="durationMin">Duration of parking in minutes</param>
 | 
			
		||||
	/// <returns>Returns cost (data type: double)</returns>
 | 
			
		||||
    double GetCostFromDuration(TariffConfiguration* tariff_cfg, uint8_t vehicle_type, char const *start_datetime, double durationMin);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										58
									
								
								library/include/mobilisis/tariff_cfg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								library/include/mobilisis/tariff_cfg.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <variant>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <rapidjson/rapidjson.h>
 | 
			
		||||
#include <rapidjson/document.h>
 | 
			
		||||
#include <rapidjson/error/en.h>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include "tariff_currency.h"
 | 
			
		||||
#include "tariff_duration.h"
 | 
			
		||||
#include "tariff_payment_mtd.h"
 | 
			
		||||
#include "tariff_payment_opt.h"
 | 
			
		||||
#include "tariff_spec_days.h"
 | 
			
		||||
#include "tariff_payment_opt.h"
 | 
			
		||||
#include "tariff_weekdays.h"
 | 
			
		||||
#include "tariff_weekdays_worktime.h"
 | 
			
		||||
#include "tariff_spec_days_worktime.h"
 | 
			
		||||
#include "tariff_member_type.h"
 | 
			
		||||
#include "tariff_period_year.h"
 | 
			
		||||
#include "tariff_payment_rate.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace rapidjson;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Tariff configuration class
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffConfiguration
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	vector<TariffCurrency> Currency;
 | 
			
		||||
	vector<TariffDuration> Duration;
 | 
			
		||||
	vector<TariffPaymentMethod> PaymentMethod;
 | 
			
		||||
	vector<TariffPaymentRate> PaymentRate;
 | 
			
		||||
	vector<TariffSpecialDaysWorktime> SpecialDaysWorktime;
 | 
			
		||||
	vector<TariffSpecialDays> SpecialDays;
 | 
			
		||||
	vector<TariffWeekDays> WeekDays;
 | 
			
		||||
	vector<TariffPeriodYear> YearPeriod;
 | 
			
		||||
	vector<TariffWeekDaysWorktime> WeekDaysWorktime;
 | 
			
		||||
	vector<TariffPaymentOption> PaymentOption;
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Parse JSON string
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="json"></param>
 | 
			
		||||
	/// <returns>Returns operation status bool (OK | FAIL) </returns>
 | 
			
		||||
	bool ParseJson(TariffConfiguration* tariff_cfg, const char* json);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Identify type of JSON member
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="member_name"></param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	MemberType IdentifyJsonMember(const char* member_name);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										18
									
								
								library/include/mobilisis/tariff_currency.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								library/include/mobilisis/tariff_currency.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
#ifndef TARIFF_CURRENCY_H_INCLUDED
 | 
			
		||||
#define TARIFF_CURRENCY_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Currency data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffCurrency
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pcu_id;
 | 
			
		||||
	std::string pcu_sign;
 | 
			
		||||
	std::string pcu_major;
 | 
			
		||||
	std::string pcu_minor;
 | 
			
		||||
	bool pcu_active;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_CURRENCY_H_INCLUDED
 | 
			
		||||
							
								
								
									
										19
									
								
								library/include/mobilisis/tariff_day_of_week.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								library/include/mobilisis/tariff_day_of_week.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
#ifndef TARIFF_DAY_OF_WEEK_H_INCLUDED
 | 
			
		||||
#define TARIFF_DAY_OF_WEEK_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Day of week enumeration
 | 
			
		||||
 | 
			
		||||
enum DayOfWeek
 | 
			
		||||
{
 | 
			
		||||
	Saturday = 0x00,
 | 
			
		||||
	Sunday = 0x01,
 | 
			
		||||
	Monday = 0x02,
 | 
			
		||||
	Tuesday = 0x03,
 | 
			
		||||
	Wednesday = 0x04,
 | 
			
		||||
	Thursday = 0x05,
 | 
			
		||||
	Friday = 0x06
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_DAY_OF_WEEK_H_INCLUDED
 | 
			
		||||
							
								
								
									
										12
									
								
								library/include/mobilisis/tariff_duration.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								library/include/mobilisis/tariff_duration.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Duration data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffDuration
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pun_id;
 | 
			
		||||
	std::string pun_label;
 | 
			
		||||
	int pun_duration;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										78
									
								
								library/include/mobilisis/tariff_log.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								library/include/mobilisis/tariff_log.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#ifndef TARIFF_LOG_INCLUDED_H
 | 
			
		||||
#define TARIFF_LOG_INCLUDED_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#define DBG_LEVEL_DEBUG     0
 | 
			
		||||
#define DBG_LEVEL_INFO      1
 | 
			
		||||
#define DBG_LEVEL_WARN      2
 | 
			
		||||
#define DBG_LEVEL_CRITICAL  3
 | 
			
		||||
#define DBG_LEVEL_ERROR     4
 | 
			
		||||
#define DBG_LEVEL_FATAL     5
 | 
			
		||||
 | 
			
		||||
void setDebugLevel(int level);
 | 
			
		||||
int getDebugLevel();
 | 
			
		||||
 | 
			
		||||
static void print() {
 | 
			
		||||
    std::cerr << "\n";
 | 
			
		||||
    if (getDebugLevel() == DBG_LEVEL_FATAL) {
 | 
			
		||||
        exit(-1);
 | 
			
		||||
    }
 | 
			
		||||
} // termination version
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void print(const Arg1& arg1, Args&&... args) {
 | 
			
		||||
    std::cerr << arg1;
 | 
			
		||||
    print(args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void LOG_DEBUG(const Arg1& arg1, Args&&... args) {
 | 
			
		||||
    if (getDebugLevel() <= DBG_LEVEL_DEBUG) {
 | 
			
		||||
        std::cerr << "DEBUG " << arg1;
 | 
			
		||||
        print(args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void LOG_INFO(const Arg1& arg1, Args&&... args) {
 | 
			
		||||
    if (getDebugLevel() <= DBG_LEVEL_INFO) {
 | 
			
		||||
        std::cerr << "INFO " << arg1;
 | 
			
		||||
        print(args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void LOG_WARNING(const Arg1& arg1, const Args&&... args) {
 | 
			
		||||
    if (getDebugLevel() <= DBG_LEVEL_WARN) {
 | 
			
		||||
        std::cerr << "WARNING " << arg1;
 | 
			
		||||
        print(args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void LOG_CRITICAL(const Arg1& arg1, const Args&&... args) {
 | 
			
		||||
    if (getDebugLevel() <= DBG_LEVEL_CRITICAL) {
 | 
			
		||||
        std::cerr << "CRITICAL " << arg1;
 | 
			
		||||
        print(args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void LOG_ERROR(const Arg1& arg1, const Args&&... args) {
 | 
			
		||||
    if (getDebugLevel() <= DBG_LEVEL_ERROR) {
 | 
			
		||||
        std::cerr << "ERROR " << arg1;
 | 
			
		||||
        print(args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Arg1, typename... Args>
 | 
			
		||||
static void LOG_FATAL(const Arg1& arg1, const Args&&... args) {
 | 
			
		||||
    if (getDebugLevel() <= DBG_LEVEL_FATAL) {
 | 
			
		||||
        std::cerr << "FATAL " << arg1;
 | 
			
		||||
        print(args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif //  TARIFF_LOG_INCLUDED_H
 | 
			
		||||
							
								
								
									
										19
									
								
								library/include/mobilisis/tariff_member_type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								library/include/mobilisis/tariff_member_type.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// JSON configuration member type enumeration
 | 
			
		||||
/// </summary>
 | 
			
		||||
enum MemberType
 | 
			
		||||
{
 | 
			
		||||
	Unknown = 0xFF,
 | 
			
		||||
	Currency = 0x00,
 | 
			
		||||
	PaymentMethod = 0x01,
 | 
			
		||||
	PaymentRate = 0x20,
 | 
			
		||||
	PaymentOption = 0x03,
 | 
			
		||||
	Duration = 0x04,
 | 
			
		||||
	WeekDays = 0x05,
 | 
			
		||||
	WeekDaysWorkTime = 0x06,
 | 
			
		||||
	SpecialDaysWorktime = 0x07,
 | 
			
		||||
	SpecialDays = 0x08,
 | 
			
		||||
	PeriodYear = 0x09
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										13
									
								
								library/include/mobilisis/tariff_payment_method.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								library/include/mobilisis/tariff_payment_method.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Payment method (byte represents payment option id)
 | 
			
		||||
/// </summary>
 | 
			
		||||
enum PaymentMethod
 | 
			
		||||
{
 | 
			
		||||
	Undefined = 0xFF,
 | 
			
		||||
	Progressive = 0x01,
 | 
			
		||||
	Degressive = 0x02,
 | 
			
		||||
	Linear = 0x03,
 | 
			
		||||
	Steps = 0x04
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										15
									
								
								library/include/mobilisis/tariff_payment_mtd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								library/include/mobilisis/tariff_payment_mtd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
#ifndef TARIFF_PAYMENT_MTH_H_INCLUDED
 | 
			
		||||
#define TARIFF_PAYMENT_MTH_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Payment method data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffPaymentMethod
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pme_id;
 | 
			
		||||
	std::string pme_label;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_PAYMENT_MTH_H_INCLUDED
 | 
			
		||||
							
								
								
									
										21
									
								
								library/include/mobilisis/tariff_payment_opt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								library/include/mobilisis/tariff_payment_opt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
//#pragma once
 | 
			
		||||
#ifndef TARIFF_PAYMENT_OPT_H_INCLUDED
 | 
			
		||||
#define TARIFF_PAYMENT_OPT_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Vehicly type data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffPaymentOption
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pop_id;
 | 
			
		||||
	std::string pop_label;
 | 
			
		||||
	int pop_payment_method_id;
 | 
			
		||||
	std::string pop_day_end_time;
 | 
			
		||||
	std::string pop_day_night_end_time;
 | 
			
		||||
	double pop_price_night;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_PAYMENT_OPT_H_INCLUDED
 | 
			
		||||
							
								
								
									
										17
									
								
								library/include/mobilisis/tariff_payment_rate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								library/include/mobilisis/tariff_payment_rate.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
#ifndef TARIFF_PAYMENT_RATE_H_INCLUDED
 | 
			
		||||
#define TARIFF_PAYMENT_RATE_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Payment option data
 | 
			
		||||
/// </summary>
 | 
			
		||||
// class TariffPaymentRate
 | 
			
		||||
struct TariffPaymentRate
 | 
			
		||||
{
 | 
			
		||||
// public:
 | 
			
		||||
	int pra_payment_option_id;
 | 
			
		||||
	int pra_payment_unit_id;
 | 
			
		||||
	double pra_price;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_PAYMENT_RATE_H_INCLUDED
 | 
			
		||||
							
								
								
									
										15
									
								
								library/include/mobilisis/tariff_period_year.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								library/include/mobilisis/tariff_period_year.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Year period definition
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffPeriodYear
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pye_id;
 | 
			
		||||
	std::string pye_label;
 | 
			
		||||
	int pye_start_month;
 | 
			
		||||
	int pye_start_day;
 | 
			
		||||
	int pye_end_month;
 | 
			
		||||
	int pye_end_day;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										14
									
								
								library/include/mobilisis/tariff_spec_days.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								library/include/mobilisis/tariff_spec_days.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Special days data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffSpecialDays
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int ped_id;
 | 
			
		||||
	std::string ped_label;
 | 
			
		||||
	std::string ped_date_start;
 | 
			
		||||
	std::string ped_date_end;
 | 
			
		||||
	int ped_period_special_day_id;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										14
									
								
								library/include/mobilisis/tariff_spec_days_worktime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								library/include/mobilisis/tariff_spec_days_worktime.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Range data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffSpecialDaysWorktime
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pedwt_id;
 | 
			
		||||
	int pedwt_period_exc_day_id;
 | 
			
		||||
	std::string pedwt_time_from;
 | 
			
		||||
	std::string pedwt_time_to;
 | 
			
		||||
	double pedwt_price;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										17
									
								
								library/include/mobilisis/tariff_time_range.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								library/include/mobilisis/tariff_time_range.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
#ifndef TARIFF_TIME_RANGE_H_INCLUDED
 | 
			
		||||
#define TARIFF_TIME_RANGE_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Time range definition
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffTimeRange {
 | 
			
		||||
public:
 | 
			
		||||
	time_t time_from;
 | 
			
		||||
    time_t time_to;
 | 
			
		||||
    TariffTimeRange() : time_from(0), time_to(0) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_TIME_RANGE_H_INCLUDED
 | 
			
		||||
							
								
								
									
										95
									
								
								library/include/mobilisis/tariff_utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								library/include/mobilisis/tariff_utils.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
#ifndef TARIFF_UTILS_H_INCLUDED
 | 
			
		||||
#define TARIFF_UTILS_H_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include "tariff_day_of_week.h"
 | 
			
		||||
#include "tariff_cfg.h"
 | 
			
		||||
#include "tariff_time_range.h"
 | 
			
		||||
#include "active_time_range.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <locale.h>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Definition of TariffUtilities class
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffUtils {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Validate parking ticket
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="initial"></param>
 | 
			
		||||
    /// <param name="durationMin"></param>
 | 
			
		||||
    /// <param name="time_range"></param>
 | 
			
		||||
    /// <param name="isSpecialDay"></param>
 | 
			
		||||
    /// <param name="spec_day_id"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    static bool
 | 
			
		||||
    ValidateParkingTicket(TariffConfiguration const *tariff_cfg,
 | 
			
		||||
                          time_t initial, int durationMin,
 | 
			
		||||
                          double price, TariffTimeRange time_range,
 | 
			
		||||
                          bool isSpecialDay, int spec_day_id);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Check if time is in range between start and end of active payment hours
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="tariff_cfg">Tariff configuration</param>
 | 
			
		||||
    /// <param name="datetimeStr">Current datetime string</param>
 | 
			
		||||
    /// <param name="isSpecialDay">Special day flag</param>
 | 
			
		||||
    /// <param name="spec_day_id">Special day ID</param>
 | 
			
		||||
    /// <returns>Returns if parking time range is active</returns>
 | 
			
		||||
    static ActiveTimeRange
 | 
			
		||||
    isParkingTimeRangeActive(TariffConfiguration *tariff_cfg,
 | 
			
		||||
                             std::string datetimeStr, bool isSpecialDay,
 | 
			
		||||
                             int spec_day_id);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Get day of week from current date (Zeller's Algorithm), 
 | 
			
		||||
    ///     starting day is Sunday
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="date"></param>
 | 
			
		||||
    /// <returns></returns>
 | 
			
		||||
    static DayOfWeek GetDayOfWeek(struct tm const *t);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Identifies special day (e.g. Christmas)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="tariff_cfg">Pointer to tariff configuration data</param>
 | 
			
		||||
    /// <param name="date">Date to be validated</param>
 | 
			
		||||
    /// <param name="date">Reference to special day ID</param>
 | 
			
		||||
    /// <returns>Returns if the date is a special day</returns>
 | 
			
		||||
    static bool IsSpecialDay(TariffConfiguration const *tariff_cfg, const char *dateTimeStr, int& specialDayId);
 | 
			
		||||
 | 
			
		||||
    static bool PriceForSpecialDay(TariffConfiguration const* tariff_cfg, int specialDayId, double *price);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Date and time parse helper function
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>Returns time (tm) structure</returns>
 | 
			
		||||
    static bool DateTimeToStructTm(const char* dateTimeStr, struct tm *t);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Date parse helper function
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>Returns time (tm) structure</returns>
 | 
			
		||||
    static bool DateToStructTm(char const* dateStr, struct tm *t);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Time parse helper function
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>Returns time (tm) structure</returns>
 | 
			
		||||
    static bool TimeToStructTm(const char* timeStr, struct tm *t);
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Get current local time
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>Returns time_t structure</returns>
 | 
			
		||||
    static time_t GetCurrentLocalTime();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // TARIFF_UTILS_H_INCLUDED
 | 
			
		||||
							
								
								
									
										11
									
								
								library/include/mobilisis/tariff_vehicle_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								library/include/mobilisis/tariff_vehicle_types.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Vehicle type enumeration (byte represents payment method id)
 | 
			
		||||
/// </summary>
 | 
			
		||||
enum PaymentOption
 | 
			
		||||
{
 | 
			
		||||
	Car = 0x03,
 | 
			
		||||
	HeavyVehicle = 0x02,
 | 
			
		||||
	Daily = 0x01
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										12
									
								
								library/include/mobilisis/tariff_weekdays.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								library/include/mobilisis/tariff_weekdays.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Weekdays data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffWeekDays
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pdiw_id;
 | 
			
		||||
	std::string pdiw_label;
 | 
			
		||||
	int pdiw_index;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										14
									
								
								library/include/mobilisis/tariff_weekdays_worktime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								library/include/mobilisis/tariff_weekdays_worktime.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// #pragma once
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Weekdays worktime data
 | 
			
		||||
/// </summary>
 | 
			
		||||
class TariffWeekDaysWorktime
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pwd_id;
 | 
			
		||||
	int pwd_period_week_day_id;
 | 
			
		||||
	int pwd_period_day_in_week_id;
 | 
			
		||||
	std::string pwd_time_from;
 | 
			
		||||
	std::string pwd_time_to;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										8
									
								
								library/include/mobilisis/time_range.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								library/include/mobilisis/time_range.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "time_range_header.h"
 | 
			
		||||
 | 
			
		||||
struct TimeRange {
 | 
			
		||||
public:
 | 
			
		||||
	bool IsActive;
 | 
			
		||||
	ATBTimeRange TimeRangeStructure;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										8
									
								
								library/include/mobilisis/time_range_header.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								library/include/mobilisis/time_range_header.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
class ATBTimeRange {
 | 
			
		||||
public:
 | 
			
		||||
	time_t time_from;
 | 
			
		||||
	time_t time_to;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										72
									
								
								library/include/mobilisis/utilities.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								library/include/mobilisis/utilities.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
 | 
			
		||||
#include "day_of_week.h"
 | 
			
		||||
#include "configuration.h"
 | 
			
		||||
#include "time_range.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
class Utilities {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Get day of week from current date (Zeller's Algorithm), starting day is Sunday
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="date"></param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	static DayOfWeek GetDayOfWeek(struct tm* tm);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Date and time parse helper function
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Returns time (tm) structure</returns>
 | 
			
		||||
	static struct tm DateTimeToStructTm(const char* dateTimeStr);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Date parse helper function
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Returns time (tm) structure</returns>
 | 
			
		||||
	static struct tm DateToStructTm(const char* dateStr);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Time parse helper function
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Returns time (tm) structure</returns>
 | 
			
		||||
	static struct tm TimeToStructTm(const char* timeStr, int year, int mon, int mday, int wday);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Get current local time
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <returns>Returns time_t structure</returns>
 | 
			
		||||
	static time_t GetCurrentLocalTime();
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Zeller's algorithm for determining day of week
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	static int ZellersAlgorithm(int day, int month, int year);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	///  Checks if current datetime is in range between start and end month of parking worktime
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="tariff_cfg"></param>
 | 
			
		||||
	/// <param name="currentDateTime"></param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	static bool IsYearPeriodActive(Configuration* cfg, struct tm* currentDateTime);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Check permissions
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	static bool CheckSpecialDay(Configuration* cfg, const char* currentDateTimeStr, int* specialDayId, double* specialDayPrice);
 | 
			
		||||
 | 
			
		||||
	/// <summary>
 | 
			
		||||
	/// Calculates price per unit
 | 
			
		||||
	/// </summary>
 | 
			
		||||
	/// <param name="pra_price"></param>
 | 
			
		||||
	/// <returns></returns>
 | 
			
		||||
	static double CalculatePricePerUnit(double pra_price);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										10
									
								
								library/include/mobilisis/weekdays.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								library/include/mobilisis/weekdays.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBWeekDays
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pdiw_id;
 | 
			
		||||
	std::string pdiw_label;
 | 
			
		||||
	int pdiw_index;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										12
									
								
								library/include/mobilisis/weekdays_worktime.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								library/include/mobilisis/weekdays_worktime.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
class ATBWeekDaysWorktime
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int pwd_id;
 | 
			
		||||
	int pwd_period_week_day_id;
 | 
			
		||||
	int pwd_period_day_in_week_id;
 | 
			
		||||
	std::string pwd_time_from;
 | 
			
		||||
	std::string pwd_time_to;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										693
									
								
								library/include/rapidjson/allocators.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										693
									
								
								library/include/rapidjson/allocators.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,693 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ALLOCATORS_H_
 | 
			
		||||
#define RAPIDJSON_ALLOCATORS_H_
 | 
			
		||||
 | 
			
		||||
#include "rapidjson.h"
 | 
			
		||||
#include "internal/meta.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <limits>
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Allocator
 | 
			
		||||
 | 
			
		||||
/*! \class rapidjson::Allocator
 | 
			
		||||
    \brief Concept for allocating, resizing and freeing memory block.
 | 
			
		||||
    
 | 
			
		||||
    Note that Malloc() and Realloc() are non-static but Free() is static.
 | 
			
		||||
    
 | 
			
		||||
    So if an allocator need to support Free(), it needs to put its pointer in 
 | 
			
		||||
    the header of memory block.
 | 
			
		||||
 | 
			
		||||
\code
 | 
			
		||||
concept Allocator {
 | 
			
		||||
    static const bool kNeedFree;    //!< Whether this allocator needs to call Free().
 | 
			
		||||
 | 
			
		||||
    // Allocate a memory block.
 | 
			
		||||
    // \param size of the memory block in bytes.
 | 
			
		||||
    // \returns pointer to the memory block.
 | 
			
		||||
    void* Malloc(size_t size);
 | 
			
		||||
 | 
			
		||||
    // Resize a memory block.
 | 
			
		||||
    // \param originalPtr The pointer to current memory block. Null pointer is permitted.
 | 
			
		||||
    // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
 | 
			
		||||
    // \param newSize the new size in bytes.
 | 
			
		||||
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
 | 
			
		||||
 | 
			
		||||
    // Free a memory block.
 | 
			
		||||
    // \param pointer to the memory block. Null pointer is permitted.
 | 
			
		||||
    static void Free(void *ptr);
 | 
			
		||||
};
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief User-defined kDefaultChunkCapacity definition.
 | 
			
		||||
 | 
			
		||||
    User can define this as any \c size that is a power of 2.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
 | 
			
		||||
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// CrtAllocator
 | 
			
		||||
 | 
			
		||||
//! C-runtime library allocator.
 | 
			
		||||
/*! This class is just wrapper for standard C library memory routines.
 | 
			
		||||
    \note implements Allocator concept
 | 
			
		||||
*/
 | 
			
		||||
class CrtAllocator {
 | 
			
		||||
public:
 | 
			
		||||
    static const bool kNeedFree = true;
 | 
			
		||||
    void* Malloc(size_t size) { 
 | 
			
		||||
        if (size) //  behavior of malloc(0) is implementation defined.
 | 
			
		||||
            return RAPIDJSON_MALLOC(size);
 | 
			
		||||
        else
 | 
			
		||||
            return NULL; // standardize to returning NULL.
 | 
			
		||||
    }
 | 
			
		||||
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
 | 
			
		||||
        (void)originalSize;
 | 
			
		||||
        if (newSize == 0) {
 | 
			
		||||
            RAPIDJSON_FREE(originalPtr);
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
        return RAPIDJSON_REALLOC(originalPtr, newSize);
 | 
			
		||||
    }
 | 
			
		||||
    static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
 | 
			
		||||
 | 
			
		||||
    bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// MemoryPoolAllocator
 | 
			
		||||
 | 
			
		||||
//! Default memory allocator used by the parser and DOM.
 | 
			
		||||
/*! This allocator allocate memory blocks from pre-allocated memory chunks. 
 | 
			
		||||
 | 
			
		||||
    It does not free memory blocks. And Realloc() only allocate new memory.
 | 
			
		||||
 | 
			
		||||
    The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
 | 
			
		||||
 | 
			
		||||
    User may also supply a buffer as the first chunk.
 | 
			
		||||
 | 
			
		||||
    If the user-buffer is full then additional chunks are allocated by BaseAllocator.
 | 
			
		||||
 | 
			
		||||
    The user-buffer is not deallocated by this allocator.
 | 
			
		||||
 | 
			
		||||
    \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
 | 
			
		||||
    \note implements Allocator concept
 | 
			
		||||
*/
 | 
			
		||||
template <typename BaseAllocator = CrtAllocator>
 | 
			
		||||
class MemoryPoolAllocator {
 | 
			
		||||
    //! Chunk header for perpending to each chunk.
 | 
			
		||||
    /*! Chunks are stored as a singly linked list.
 | 
			
		||||
    */
 | 
			
		||||
    struct ChunkHeader {
 | 
			
		||||
        size_t capacity;    //!< Capacity of the chunk in bytes (excluding the header itself).
 | 
			
		||||
        size_t size;        //!< Current size of allocated memory in bytes.
 | 
			
		||||
        ChunkHeader *next;  //!< Next chunk in the linked list.
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct SharedData {
 | 
			
		||||
        ChunkHeader *chunkHead;  //!< Head of the chunk linked-list. Only the head chunk serves allocation.
 | 
			
		||||
        BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
 | 
			
		||||
        size_t refcount;
 | 
			
		||||
        bool ownBuffer;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
 | 
			
		||||
    static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
 | 
			
		||||
 | 
			
		||||
    static inline ChunkHeader *GetChunkHead(SharedData *shared)
 | 
			
		||||
    {
 | 
			
		||||
        return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
 | 
			
		||||
    }
 | 
			
		||||
    static inline uint8_t *GetChunkBuffer(SharedData *shared)
 | 
			
		||||
    {
 | 
			
		||||
        return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    static const bool kNeedFree = false;    //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
 | 
			
		||||
    static const bool kRefCounted = true;   //!< Tell users that this allocator is reference counted on copy
 | 
			
		||||
 | 
			
		||||
    //! Constructor with chunkSize.
 | 
			
		||||
    /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
 | 
			
		||||
        \param baseAllocator The allocator for allocating memory chunks.
 | 
			
		||||
    */
 | 
			
		||||
    explicit
 | 
			
		||||
    MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 
 | 
			
		||||
        chunk_capacity_(chunkSize),
 | 
			
		||||
        baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
 | 
			
		||||
        shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_ASSERT(baseAllocator_ != 0);
 | 
			
		||||
        RAPIDJSON_ASSERT(shared_ != 0);
 | 
			
		||||
        if (baseAllocator) {
 | 
			
		||||
            shared_->ownBaseAllocator = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            shared_->ownBaseAllocator = baseAllocator_;
 | 
			
		||||
        }
 | 
			
		||||
        shared_->chunkHead = GetChunkHead(shared_);
 | 
			
		||||
        shared_->chunkHead->capacity = 0;
 | 
			
		||||
        shared_->chunkHead->size = 0;
 | 
			
		||||
        shared_->chunkHead->next = 0;
 | 
			
		||||
        shared_->ownBuffer = true;
 | 
			
		||||
        shared_->refcount = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Constructor with user-supplied buffer.
 | 
			
		||||
    /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
 | 
			
		||||
 | 
			
		||||
        The user buffer will not be deallocated when this allocator is destructed.
 | 
			
		||||
 | 
			
		||||
        \param buffer User supplied buffer.
 | 
			
		||||
        \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
 | 
			
		||||
        \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
 | 
			
		||||
        \param baseAllocator The allocator for allocating memory chunks.
 | 
			
		||||
    */
 | 
			
		||||
    MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
 | 
			
		||||
        chunk_capacity_(chunkSize),
 | 
			
		||||
        baseAllocator_(baseAllocator),
 | 
			
		||||
        shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
 | 
			
		||||
        shared_->chunkHead = GetChunkHead(shared_);
 | 
			
		||||
        shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
 | 
			
		||||
        shared_->chunkHead->size = 0;
 | 
			
		||||
        shared_->chunkHead->next = 0;
 | 
			
		||||
        shared_->ownBaseAllocator = 0;
 | 
			
		||||
        shared_->ownBuffer = false;
 | 
			
		||||
        shared_->refcount = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        chunk_capacity_(rhs.chunk_capacity_),
 | 
			
		||||
        baseAllocator_(rhs.baseAllocator_),
 | 
			
		||||
        shared_(rhs.shared_)
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        ++shared_->refcount;
 | 
			
		||||
    }
 | 
			
		||||
    MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
			
		||||
        ++rhs.shared_->refcount;
 | 
			
		||||
        this->~MemoryPoolAllocator();
 | 
			
		||||
        baseAllocator_ = rhs.baseAllocator_;
 | 
			
		||||
        chunk_capacity_ = rhs.chunk_capacity_;
 | 
			
		||||
        shared_ = rhs.shared_;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        chunk_capacity_(rhs.chunk_capacity_),
 | 
			
		||||
        baseAllocator_(rhs.baseAllocator_),
 | 
			
		||||
        shared_(rhs.shared_)
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
			
		||||
        rhs.shared_ = 0;
 | 
			
		||||
    }
 | 
			
		||||
    MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
			
		||||
        this->~MemoryPoolAllocator();
 | 
			
		||||
        baseAllocator_ = rhs.baseAllocator_;
 | 
			
		||||
        chunk_capacity_ = rhs.chunk_capacity_;
 | 
			
		||||
        shared_ = rhs.shared_;
 | 
			
		||||
        rhs.shared_ = 0;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //! Destructor.
 | 
			
		||||
    /*! This deallocates all memory chunks, excluding the user-supplied buffer.
 | 
			
		||||
    */
 | 
			
		||||
    ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        if (!shared_) {
 | 
			
		||||
            // do nothing if moved
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (shared_->refcount > 1) {
 | 
			
		||||
            --shared_->refcount;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        Clear();
 | 
			
		||||
        BaseAllocator *a = shared_->ownBaseAllocator;
 | 
			
		||||
        if (shared_->ownBuffer) {
 | 
			
		||||
            baseAllocator_->Free(shared_);
 | 
			
		||||
        }
 | 
			
		||||
        RAPIDJSON_DELETE(a);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Deallocates all memory chunks, excluding the first/user one.
 | 
			
		||||
    void Clear() RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        for (;;) {
 | 
			
		||||
            ChunkHeader* c = shared_->chunkHead;
 | 
			
		||||
            if (!c->next) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            shared_->chunkHead = c->next;
 | 
			
		||||
            baseAllocator_->Free(c);
 | 
			
		||||
        }
 | 
			
		||||
        shared_->chunkHead->size = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Computes the total capacity of allocated memory chunks.
 | 
			
		||||
    /*! \return total capacity in bytes.
 | 
			
		||||
    */
 | 
			
		||||
    size_t Capacity() const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        size_t capacity = 0;
 | 
			
		||||
        for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
 | 
			
		||||
            capacity += c->capacity;
 | 
			
		||||
        return capacity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Computes the memory blocks allocated.
 | 
			
		||||
    /*! \return total used bytes.
 | 
			
		||||
    */
 | 
			
		||||
    size_t Size() const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        size_t size = 0;
 | 
			
		||||
        for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
 | 
			
		||||
            size += c->size;
 | 
			
		||||
        return size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Whether the allocator is shared.
 | 
			
		||||
    /*! \return true or false.
 | 
			
		||||
    */
 | 
			
		||||
    bool Shared() const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        return shared_->refcount > 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Allocates a memory block. (concept Allocator)
 | 
			
		||||
    void* Malloc(size_t size) {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        if (!size)
 | 
			
		||||
            return NULL;
 | 
			
		||||
 | 
			
		||||
        size = RAPIDJSON_ALIGN(size);
 | 
			
		||||
        if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
 | 
			
		||||
            if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
 | 
			
		||||
                return NULL;
 | 
			
		||||
 | 
			
		||||
        void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
 | 
			
		||||
        shared_->chunkHead->size += size;
 | 
			
		||||
        return buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Resizes a memory block (concept Allocator)
 | 
			
		||||
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
 | 
			
		||||
        if (originalPtr == 0)
 | 
			
		||||
            return Malloc(newSize);
 | 
			
		||||
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        if (newSize == 0)
 | 
			
		||||
            return NULL;
 | 
			
		||||
 | 
			
		||||
        originalSize = RAPIDJSON_ALIGN(originalSize);
 | 
			
		||||
        newSize = RAPIDJSON_ALIGN(newSize);
 | 
			
		||||
 | 
			
		||||
        // Do not shrink if new size is smaller than original
 | 
			
		||||
        if (originalSize >= newSize)
 | 
			
		||||
            return originalPtr;
 | 
			
		||||
 | 
			
		||||
        // Simply expand it if it is the last allocation and there is sufficient space
 | 
			
		||||
        if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
 | 
			
		||||
            size_t increment = static_cast<size_t>(newSize - originalSize);
 | 
			
		||||
            if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
 | 
			
		||||
                shared_->chunkHead->size += increment;
 | 
			
		||||
                return originalPtr;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Realloc process: allocate and copy memory, do not free original buffer.
 | 
			
		||||
        if (void* newBuffer = Malloc(newSize)) {
 | 
			
		||||
            if (originalSize)
 | 
			
		||||
                std::memcpy(newBuffer, originalPtr, originalSize);
 | 
			
		||||
            return newBuffer;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Frees a memory block (concept Allocator)
 | 
			
		||||
    static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
 | 
			
		||||
 | 
			
		||||
    //! Compare (equality) with another MemoryPoolAllocator
 | 
			
		||||
    bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
 | 
			
		||||
        return shared_ == rhs.shared_;
 | 
			
		||||
    }
 | 
			
		||||
    //! Compare (inequality) with another MemoryPoolAllocator
 | 
			
		||||
    bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        return !operator==(rhs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    //! Creates a new chunk.
 | 
			
		||||
    /*! \param capacity Capacity of the chunk in bytes.
 | 
			
		||||
        \return true if success.
 | 
			
		||||
    */
 | 
			
		||||
    bool AddChunk(size_t capacity) {
 | 
			
		||||
        if (!baseAllocator_)
 | 
			
		||||
            shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
 | 
			
		||||
        if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
 | 
			
		||||
            chunk->capacity = capacity;
 | 
			
		||||
            chunk->size = 0;
 | 
			
		||||
            chunk->next = shared_->chunkHead;
 | 
			
		||||
            shared_->chunkHead = chunk;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static inline void* AlignBuffer(void* buf, size_t &size)
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
 | 
			
		||||
        const uintptr_t mask = sizeof(void*) - 1;
 | 
			
		||||
        const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
 | 
			
		||||
        if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
 | 
			
		||||
            const uintptr_t abuf = (ubuf + mask) & ~mask;
 | 
			
		||||
            RAPIDJSON_ASSERT(size >= abuf - ubuf);
 | 
			
		||||
            buf = reinterpret_cast<void*>(abuf);
 | 
			
		||||
            size -= abuf - ubuf;
 | 
			
		||||
        }
 | 
			
		||||
        return buf;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t chunk_capacity_;     //!< The minimum capacity of chunk when they are allocated.
 | 
			
		||||
    BaseAllocator* baseAllocator_;  //!< base allocator for allocating memory chunks.
 | 
			
		||||
    SharedData *shared_;        //!< The shared data of the allocator
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace internal {
 | 
			
		||||
    template<typename, typename = void>
 | 
			
		||||
    struct IsRefCounted :
 | 
			
		||||
        public FalseType
 | 
			
		||||
    { };
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
 | 
			
		||||
        public TrueType
 | 
			
		||||
    { };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T, typename A>
 | 
			
		||||
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
 | 
			
		||||
{
 | 
			
		||||
    RAPIDJSON_NOEXCEPT_ASSERT(old_n <= std::numeric_limits<size_t>::max() / sizeof(T) && new_n <= std::numeric_limits<size_t>::max() / sizeof(T));
 | 
			
		||||
    return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T, typename A>
 | 
			
		||||
inline T *Malloc(A& a, size_t n = 1)
 | 
			
		||||
{
 | 
			
		||||
    return Realloc<T, A>(a, NULL, 0, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T, typename A>
 | 
			
		||||
inline void Free(A& a, T *p, size_t n = 1)
 | 
			
		||||
{
 | 
			
		||||
    static_cast<void>(Realloc<T, A>(a, p, n, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename T, typename BaseAllocator = CrtAllocator>
 | 
			
		||||
class StdAllocator :
 | 
			
		||||
    public std::allocator<T>
 | 
			
		||||
{
 | 
			
		||||
    typedef std::allocator<T> allocator_type;
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
    typedef std::allocator_traits<allocator_type> traits_type;
 | 
			
		||||
#else
 | 
			
		||||
    typedef allocator_type traits_type;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    typedef BaseAllocator BaseAllocatorType;
 | 
			
		||||
 | 
			
		||||
    StdAllocator() RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(),
 | 
			
		||||
        baseAllocator_()
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(rhs),
 | 
			
		||||
        baseAllocator_(rhs.baseAllocator_)
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    template<typename U>
 | 
			
		||||
    StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(rhs),
 | 
			
		||||
        baseAllocator_(rhs.baseAllocator_)
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(std::move(rhs)),
 | 
			
		||||
        baseAllocator_(std::move(rhs.baseAllocator_))
 | 
			
		||||
    { }
 | 
			
		||||
#endif
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
    using propagate_on_container_move_assignment = std::true_type;
 | 
			
		||||
    using propagate_on_container_swap = std::true_type;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* implicit */
 | 
			
		||||
    StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(),
 | 
			
		||||
        baseAllocator_(allocator)
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    ~StdAllocator() RAPIDJSON_NOEXCEPT
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    template<typename U>
 | 
			
		||||
    struct rebind {
 | 
			
		||||
        typedef StdAllocator<U, BaseAllocator> other;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    typedef typename traits_type::size_type         size_type;
 | 
			
		||||
    typedef typename traits_type::difference_type   difference_type;
 | 
			
		||||
 | 
			
		||||
    typedef typename traits_type::value_type        value_type;
 | 
			
		||||
    typedef typename traits_type::pointer           pointer;
 | 
			
		||||
    typedef typename traits_type::const_pointer     const_pointer;
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
 | 
			
		||||
    typedef typename std::add_lvalue_reference<value_type>::type &reference;
 | 
			
		||||
    typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
 | 
			
		||||
 | 
			
		||||
    pointer address(reference r) const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return std::addressof(r);
 | 
			
		||||
    }
 | 
			
		||||
    const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return std::addressof(r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_type max_size() const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return traits_type::max_size(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename ...Args>
 | 
			
		||||
    void construct(pointer p, Args&&... args)
 | 
			
		||||
    {
 | 
			
		||||
        traits_type::construct(*this, p, std::forward<Args>(args)...);
 | 
			
		||||
    }
 | 
			
		||||
    void destroy(pointer p)
 | 
			
		||||
    {
 | 
			
		||||
        traits_type::destroy(*this, p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#else // !RAPIDJSON_HAS_CXX11
 | 
			
		||||
 | 
			
		||||
    typedef typename allocator_type::reference       reference;
 | 
			
		||||
    typedef typename allocator_type::const_reference const_reference;
 | 
			
		||||
 | 
			
		||||
    pointer address(reference r) const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return allocator_type::address(r);
 | 
			
		||||
    }
 | 
			
		||||
    const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return allocator_type::address(r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_type max_size() const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return allocator_type::max_size();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void construct(pointer p, const_reference r)
 | 
			
		||||
    {
 | 
			
		||||
        allocator_type::construct(p, r);
 | 
			
		||||
    }
 | 
			
		||||
    void destroy(pointer p)
 | 
			
		||||
    {
 | 
			
		||||
        allocator_type::destroy(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif // !RAPIDJSON_HAS_CXX11
 | 
			
		||||
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    U* allocate(size_type n = 1, const void* = 0)
 | 
			
		||||
    {
 | 
			
		||||
        return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
 | 
			
		||||
    }
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    void deallocate(U* p, size_type n = 1)
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pointer allocate(size_type n = 1, const void* = 0)
 | 
			
		||||
    {
 | 
			
		||||
        return allocate<value_type>(n);
 | 
			
		||||
    }
 | 
			
		||||
    void deallocate(pointer p, size_type n = 1)
 | 
			
		||||
    {
 | 
			
		||||
        deallocate<value_type>(p, n);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
    using is_always_equal = std::is_empty<BaseAllocator>;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    template<typename U>
 | 
			
		||||
    bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return baseAllocator_ == rhs.baseAllocator_;
 | 
			
		||||
    }
 | 
			
		||||
    template<typename U>
 | 
			
		||||
    bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        return !operator==(rhs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! rapidjson Allocator concept
 | 
			
		||||
    static const bool kNeedFree = BaseAllocator::kNeedFree;
 | 
			
		||||
    static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
 | 
			
		||||
    void* Malloc(size_t size)
 | 
			
		||||
    {
 | 
			
		||||
        return baseAllocator_.Malloc(size);
 | 
			
		||||
    }
 | 
			
		||||
    void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
 | 
			
		||||
    {
 | 
			
		||||
        return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
 | 
			
		||||
    }
 | 
			
		||||
    static void Free(void *ptr) RAPIDJSON_NOEXCEPT
 | 
			
		||||
    {
 | 
			
		||||
        BaseAllocator::Free(ptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    template <typename, typename>
 | 
			
		||||
    friend class StdAllocator; // access to StdAllocator<!T>.*
 | 
			
		||||
 | 
			
		||||
    BaseAllocator baseAllocator_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
 | 
			
		||||
template <typename BaseAllocator>
 | 
			
		||||
class StdAllocator<void, BaseAllocator> :
 | 
			
		||||
    public std::allocator<void>
 | 
			
		||||
{
 | 
			
		||||
    typedef std::allocator<void> allocator_type;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    typedef BaseAllocator BaseAllocatorType;
 | 
			
		||||
 | 
			
		||||
    StdAllocator() RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(),
 | 
			
		||||
        baseAllocator_()
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(rhs),
 | 
			
		||||
        baseAllocator_(rhs.baseAllocator_)
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    template<typename U>
 | 
			
		||||
    StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(rhs),
 | 
			
		||||
        baseAllocator_(rhs.baseAllocator_)
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    /* implicit */
 | 
			
		||||
    StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
 | 
			
		||||
        allocator_type(),
 | 
			
		||||
        baseAllocator_(baseAllocator)
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    ~StdAllocator() RAPIDJSON_NOEXCEPT
 | 
			
		||||
    { }
 | 
			
		||||
 | 
			
		||||
    template<typename U>
 | 
			
		||||
    struct rebind {
 | 
			
		||||
        typedef StdAllocator<U, BaseAllocator> other;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    typedef typename allocator_type::value_type value_type;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    template <typename, typename>
 | 
			
		||||
    friend class StdAllocator; // access to StdAllocator<!T>.*
 | 
			
		||||
 | 
			
		||||
    BaseAllocator baseAllocator_;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_ENCODINGS_H_
 | 
			
		||||
							
								
								
									
										78
									
								
								library/include/rapidjson/cursorstreamwrapper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								library/include/rapidjson/cursorstreamwrapper.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_
 | 
			
		||||
#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//! Cursor stream wrapper for counting line and column number if error exists.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam InputStream     Any stream that implements Stream Concept
 | 
			
		||||
*/
 | 
			
		||||
template <typename InputStream, typename Encoding = UTF8<> >
 | 
			
		||||
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    CursorStreamWrapper(InputStream& is):
 | 
			
		||||
        GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
 | 
			
		||||
 | 
			
		||||
    // counting line and column number
 | 
			
		||||
    Ch Take() {
 | 
			
		||||
        Ch ch = this->is_.Take();
 | 
			
		||||
        if(ch == '\n') {
 | 
			
		||||
            line_ ++;
 | 
			
		||||
            col_ = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            col_ ++;
 | 
			
		||||
        }
 | 
			
		||||
        return ch;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Get the error line number, if error exists.
 | 
			
		||||
    size_t GetLine() const { return line_; }
 | 
			
		||||
    //! Get the error column number, if error exists.
 | 
			
		||||
    size_t GetColumn() const { return col_; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    size_t line_;   //!< Current Line
 | 
			
		||||
    size_t col_;    //!< Current Column
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
 | 
			
		||||
							
								
								
									
										3043
									
								
								library/include/rapidjson/document.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3043
									
								
								library/include/rapidjson/document.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										299
									
								
								library/include/rapidjson/encodedstream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								library/include/rapidjson/encodedstream.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,299 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
 | 
			
		||||
#define RAPIDJSON_ENCODEDSTREAM_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include "memorystream.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Input byte stream wrapper with a statically bound encoding.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
 | 
			
		||||
    \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
 | 
			
		||||
*/
 | 
			
		||||
template <typename Encoding, typename InputByteStream>
 | 
			
		||||
class EncodedInputStream {
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    EncodedInputStream(InputByteStream& is) : is_(is) { 
 | 
			
		||||
        current_ = Encoding::TakeBOM(is_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return current_; }
 | 
			
		||||
    Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
 | 
			
		||||
    size_t Tell() const { return is_.Tell(); }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    void Flush() { RAPIDJSON_ASSERT(false); } 
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    EncodedInputStream(const EncodedInputStream&);
 | 
			
		||||
    EncodedInputStream& operator=(const EncodedInputStream&);
 | 
			
		||||
 | 
			
		||||
    InputByteStream& is_;
 | 
			
		||||
    Ch current_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Specialized for UTF8 MemoryStream.
 | 
			
		||||
template <>
 | 
			
		||||
class EncodedInputStream<UTF8<>, MemoryStream> {
 | 
			
		||||
public:
 | 
			
		||||
    typedef UTF8<>::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    EncodedInputStream(MemoryStream& is) : is_(is) {
 | 
			
		||||
        if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
 | 
			
		||||
        if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
 | 
			
		||||
        if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
 | 
			
		||||
    }
 | 
			
		||||
    Ch Peek() const { return is_.Peek(); }
 | 
			
		||||
    Ch Take() { return is_.Take(); }
 | 
			
		||||
    size_t Tell() const { return is_.Tell(); }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    void Put(Ch) {}
 | 
			
		||||
    void Flush() {} 
 | 
			
		||||
    Ch* PutBegin() { return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { return 0; }
 | 
			
		||||
 | 
			
		||||
    MemoryStream& is_;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    EncodedInputStream(const EncodedInputStream&);
 | 
			
		||||
    EncodedInputStream& operator=(const EncodedInputStream&);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Output byte stream wrapper with statically bound encoding.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
 | 
			
		||||
    \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
 | 
			
		||||
*/
 | 
			
		||||
template <typename Encoding, typename OutputByteStream>
 | 
			
		||||
class EncodedOutputStream {
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { 
 | 
			
		||||
        if (putBOM)
 | 
			
		||||
            Encoding::PutBOM(os_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Put(Ch c) { Encoding::Put(os_, c);  }
 | 
			
		||||
    void Flush() { os_.Flush(); }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
 | 
			
		||||
    Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
 | 
			
		||||
    size_t Tell() const { RAPIDJSON_ASSERT(false);  return 0; }
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    EncodedOutputStream(const EncodedOutputStream&);
 | 
			
		||||
    EncodedOutputStream& operator=(const EncodedOutputStream&);
 | 
			
		||||
 | 
			
		||||
    OutputByteStream& os_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
 | 
			
		||||
 | 
			
		||||
//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam CharType Type of character for reading.
 | 
			
		||||
    \tparam InputByteStream type of input byte stream to be wrapped.
 | 
			
		||||
*/
 | 
			
		||||
template <typename CharType, typename InputByteStream>
 | 
			
		||||
class AutoUTFInputStream {
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
public:
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
 | 
			
		||||
    //! Constructor.
 | 
			
		||||
    /*!
 | 
			
		||||
        \param is input stream to be wrapped.
 | 
			
		||||
        \param type UTF encoding type if it is not detected from the stream.
 | 
			
		||||
    */
 | 
			
		||||
    AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
 | 
			
		||||
        RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);        
 | 
			
		||||
        DetectType();
 | 
			
		||||
        static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
 | 
			
		||||
        takeFunc_ = f[type_];
 | 
			
		||||
        current_ = takeFunc_(*is_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UTFType GetType() const { return type_; }
 | 
			
		||||
    bool HasBOM() const { return hasBOM_; }
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return current_; }
 | 
			
		||||
    Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
 | 
			
		||||
    size_t Tell() const { return is_->Tell(); }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    void Flush() { RAPIDJSON_ASSERT(false); } 
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    AutoUTFInputStream(const AutoUTFInputStream&);
 | 
			
		||||
    AutoUTFInputStream& operator=(const AutoUTFInputStream&);
 | 
			
		||||
 | 
			
		||||
    // Detect encoding type with BOM or RFC 4627
 | 
			
		||||
    void DetectType() {
 | 
			
		||||
        // BOM (Byte Order Mark):
 | 
			
		||||
        // 00 00 FE FF  UTF-32BE
 | 
			
		||||
        // FF FE 00 00  UTF-32LE
 | 
			
		||||
        // FE FF        UTF-16BE
 | 
			
		||||
        // FF FE        UTF-16LE
 | 
			
		||||
        // EF BB BF     UTF-8
 | 
			
		||||
 | 
			
		||||
        const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
 | 
			
		||||
        if (!c)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
 | 
			
		||||
        hasBOM_ = false;
 | 
			
		||||
        if (bom == 0xFFFE0000)                  { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
 | 
			
		||||
        else if (bom == 0x0000FEFF)             { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
 | 
			
		||||
        else if ((bom & 0xFFFF) == 0xFFFE)      { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take();                           }
 | 
			
		||||
        else if ((bom & 0xFFFF) == 0xFEFF)      { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take();                           }
 | 
			
		||||
        else if ((bom & 0xFFFFFF) == 0xBFBBEF)  { type_ = kUTF8;    hasBOM_ = true; is_->Take(); is_->Take(); is_->Take();              }
 | 
			
		||||
 | 
			
		||||
        // RFC 4627: Section 3
 | 
			
		||||
        // "Since the first two characters of a JSON text will always be ASCII
 | 
			
		||||
        // characters [RFC0020], it is possible to determine whether an octet
 | 
			
		||||
        // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
 | 
			
		||||
        // at the pattern of nulls in the first four octets."
 | 
			
		||||
        // 00 00 00 xx  UTF-32BE
 | 
			
		||||
        // 00 xx 00 xx  UTF-16BE
 | 
			
		||||
        // xx 00 00 00  UTF-32LE
 | 
			
		||||
        // xx 00 xx 00  UTF-16LE
 | 
			
		||||
        // xx xx xx xx  UTF-8
 | 
			
		||||
 | 
			
		||||
        if (!hasBOM_) {
 | 
			
		||||
            int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
 | 
			
		||||
            switch (pattern) {
 | 
			
		||||
            case 0x08: type_ = kUTF32BE; break;
 | 
			
		||||
            case 0x0A: type_ = kUTF16BE; break;
 | 
			
		||||
            case 0x01: type_ = kUTF32LE; break;
 | 
			
		||||
            case 0x05: type_ = kUTF16LE; break;
 | 
			
		||||
            case 0x0F: type_ = kUTF8;    break;
 | 
			
		||||
            default: break; // Use type defined by user.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
 | 
			
		||||
        if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
 | 
			
		||||
        if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef Ch (*TakeFunc)(InputByteStream& is);
 | 
			
		||||
    InputByteStream* is_;
 | 
			
		||||
    UTFType type_;
 | 
			
		||||
    Ch current_;
 | 
			
		||||
    TakeFunc takeFunc_;
 | 
			
		||||
    bool hasBOM_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam CharType Type of character for writing.
 | 
			
		||||
    \tparam OutputByteStream type of output byte stream to be wrapped.
 | 
			
		||||
*/
 | 
			
		||||
template <typename CharType, typename OutputByteStream>
 | 
			
		||||
class AutoUTFOutputStream {
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
public:
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
 | 
			
		||||
    //! Constructor.
 | 
			
		||||
    /*!
 | 
			
		||||
        \param os output stream to be wrapped.
 | 
			
		||||
        \param type UTF encoding type.
 | 
			
		||||
        \param putBOM Whether to write BOM at the beginning of the stream.
 | 
			
		||||
    */
 | 
			
		||||
    AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
 | 
			
		||||
        RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
 | 
			
		||||
 | 
			
		||||
        // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
 | 
			
		||||
        if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
 | 
			
		||||
        if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
 | 
			
		||||
 | 
			
		||||
        static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
 | 
			
		||||
        putFunc_ = f[type_];
 | 
			
		||||
 | 
			
		||||
        if (putBOM)
 | 
			
		||||
            PutBOM();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UTFType GetType() const { return type_; }
 | 
			
		||||
 | 
			
		||||
    void Put(Ch c) { putFunc_(*os_, c); }
 | 
			
		||||
    void Flush() { os_->Flush(); } 
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
 | 
			
		||||
    Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
 | 
			
		||||
    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    AutoUTFOutputStream(const AutoUTFOutputStream&);
 | 
			
		||||
    AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
 | 
			
		||||
 | 
			
		||||
    void PutBOM() { 
 | 
			
		||||
        typedef void (*PutBOMFunc)(OutputByteStream&);
 | 
			
		||||
        static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
 | 
			
		||||
        f[type_](*os_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef void (*PutFunc)(OutputByteStream&, Ch);
 | 
			
		||||
 | 
			
		||||
    OutputByteStream* os_;
 | 
			
		||||
    UTFType type_;
 | 
			
		||||
    PutFunc putFunc_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#undef RAPIDJSON_ENCODINGS_FUNC
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_FILESTREAM_H_
 | 
			
		||||
							
								
								
									
										716
									
								
								library/include/rapidjson/encodings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										716
									
								
								library/include/rapidjson/encodings.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,716 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ENCODINGS_H_
 | 
			
		||||
#define RAPIDJSON_ENCODINGS_H_
 | 
			
		||||
 | 
			
		||||
#include "rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
			
		||||
#elif defined(__GNUC__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(overflow)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Encoding
 | 
			
		||||
 | 
			
		||||
/*! \class rapidjson::Encoding
 | 
			
		||||
    \brief Concept for encoding of Unicode characters.
 | 
			
		||||
 | 
			
		||||
\code
 | 
			
		||||
concept Encoding {
 | 
			
		||||
    typename Ch;    //! Type of character. A "character" is actually a code unit in unicode's definition.
 | 
			
		||||
 | 
			
		||||
    enum { supportUnicode = 1 }; // or 0 if not supporting unicode
 | 
			
		||||
 | 
			
		||||
    //! \brief Encode a Unicode codepoint to an output stream.
 | 
			
		||||
    //! \param os Output stream.
 | 
			
		||||
    //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void Encode(OutputStream& os, unsigned codepoint);
 | 
			
		||||
 | 
			
		||||
    //! \brief Decode a Unicode codepoint from an input stream.
 | 
			
		||||
    //! \param is Input stream.
 | 
			
		||||
    //! \param codepoint Output of the unicode codepoint.
 | 
			
		||||
    //! \return true if a valid codepoint can be decoded from the stream.
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    static bool Decode(InputStream& is, unsigned* codepoint);
 | 
			
		||||
 | 
			
		||||
    //! \brief Validate one Unicode codepoint from an encoded stream.
 | 
			
		||||
    //! \param is Input stream to obtain codepoint.
 | 
			
		||||
    //! \param os Output for copying one codepoint.
 | 
			
		||||
    //! \return true if it is valid.
 | 
			
		||||
    //! \note This function just validating and copying the codepoint without actually decode it.
 | 
			
		||||
    template <typename InputStream, typename OutputStream>
 | 
			
		||||
    static bool Validate(InputStream& is, OutputStream& os);
 | 
			
		||||
 | 
			
		||||
    // The following functions are deal with byte streams.
 | 
			
		||||
 | 
			
		||||
    //! Take a character from input byte stream, skip BOM if exist.
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is);
 | 
			
		||||
 | 
			
		||||
    //! Take a character from input byte stream.
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static Ch Take(InputByteStream& is);
 | 
			
		||||
 | 
			
		||||
    //! Put BOM to output byte stream.
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os);
 | 
			
		||||
 | 
			
		||||
    //! Put a character to output byte stream.
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, Ch c);
 | 
			
		||||
};
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// UTF8
 | 
			
		||||
 | 
			
		||||
//! UTF-8 encoding.
 | 
			
		||||
/*! http://en.wikipedia.org/wiki/UTF-8
 | 
			
		||||
    http://tools.ietf.org/html/rfc3629
 | 
			
		||||
    \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
 | 
			
		||||
    \note implements Encoding concept
 | 
			
		||||
*/
 | 
			
		||||
template<typename CharType = char>
 | 
			
		||||
struct UTF8 {
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
 | 
			
		||||
    enum { supportUnicode = 1 };
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void Encode(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        if (codepoint <= 0x7F) 
 | 
			
		||||
            os.Put(static_cast<Ch>(codepoint & 0xFF));
 | 
			
		||||
        else if (codepoint <= 0x7FF) {
 | 
			
		||||
            os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
 | 
			
		||||
            os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
 | 
			
		||||
        }
 | 
			
		||||
        else if (codepoint <= 0xFFFF) {
 | 
			
		||||
            os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
 | 
			
		||||
            os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
 | 
			
		||||
            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
			
		||||
            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 >> 6) & 0x3F)));
 | 
			
		||||
            os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        if (codepoint <= 0x7F) 
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
 | 
			
		||||
        else if (codepoint <= 0x7FF) {
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
 | 
			
		||||
        }
 | 
			
		||||
        else if (codepoint <= 0xFFFF) {
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
			
		||||
            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 >> 6) & 0x3F)));
 | 
			
		||||
            PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    static bool Decode(InputStream& is, unsigned* codepoint) {
 | 
			
		||||
#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
 | 
			
		||||
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 | 
			
		||||
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
 | 
			
		||||
        typename InputStream::Ch c = is.Take();
 | 
			
		||||
        if (!(c & 0x80)) {
 | 
			
		||||
            *codepoint = static_cast<unsigned char>(c);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        unsigned char type = GetRange(static_cast<unsigned char>(c));
 | 
			
		||||
        if (type >= 32) {
 | 
			
		||||
            *codepoint = 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
 | 
			
		||||
        }
 | 
			
		||||
        bool result = true;
 | 
			
		||||
        switch (type) {
 | 
			
		||||
        case 2: RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        default: return false;
 | 
			
		||||
        }
 | 
			
		||||
#undef RAPIDJSON_COPY
 | 
			
		||||
#undef RAPIDJSON_TRANS
 | 
			
		||||
#undef RAPIDJSON_TAIL
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream, typename OutputStream>
 | 
			
		||||
    static bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
#define RAPIDJSON_COPY() os.Put(c = is.Take())
 | 
			
		||||
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
 | 
			
		||||
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
 | 
			
		||||
        Ch c;
 | 
			
		||||
        RAPIDJSON_COPY();
 | 
			
		||||
        if (!(c & 0x80))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        bool result = true;
 | 
			
		||||
        switch (GetRange(static_cast<unsigned char>(c))) {
 | 
			
		||||
        case 2: RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
 | 
			
		||||
        default: return false;
 | 
			
		||||
        }
 | 
			
		||||
#undef RAPIDJSON_COPY
 | 
			
		||||
#undef RAPIDJSON_TRANS
 | 
			
		||||
#undef RAPIDJSON_TAIL
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static unsigned char GetRange(unsigned char c) {
 | 
			
		||||
        // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
 | 
			
		||||
        // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
 | 
			
		||||
        static const unsigned char type[] = {
 | 
			
		||||
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 | 
			
		||||
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 | 
			
		||||
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 | 
			
		||||
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 | 
			
		||||
            0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
 | 
			
		||||
            0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
 | 
			
		||||
            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
 | 
			
		||||
            0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
 | 
			
		||||
            8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
 | 
			
		||||
            10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
 | 
			
		||||
        };
 | 
			
		||||
        return type[c];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        typename InputByteStream::Ch c = Take(is);
 | 
			
		||||
        if (static_cast<unsigned char>(c) != 0xEFu) return c;
 | 
			
		||||
        c = is.Take();
 | 
			
		||||
        if (static_cast<unsigned char>(c) != 0xBBu) return c;
 | 
			
		||||
        c = is.Take();
 | 
			
		||||
        if (static_cast<unsigned char>(c) != 0xBFu) return c;
 | 
			
		||||
        c = is.Take();
 | 
			
		||||
        return c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static Ch Take(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        return static_cast<Ch>(is.Take());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, Ch c) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(c));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// UTF16
 | 
			
		||||
 | 
			
		||||
//! UTF-16 encoding.
 | 
			
		||||
/*! http://en.wikipedia.org/wiki/UTF-16
 | 
			
		||||
    http://tools.ietf.org/html/rfc2781
 | 
			
		||||
    \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
 | 
			
		||||
    \note implements Encoding concept
 | 
			
		||||
 | 
			
		||||
    \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
 | 
			
		||||
    For streaming, use UTF16LE and UTF16BE, which handle endianness.
 | 
			
		||||
*/
 | 
			
		||||
template<typename CharType = wchar_t>
 | 
			
		||||
struct UTF16 {
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
 | 
			
		||||
 | 
			
		||||
    enum { supportUnicode = 1 };
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void Encode(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
 | 
			
		||||
        if (codepoint <= 0xFFFF) {
 | 
			
		||||
            RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair 
 | 
			
		||||
            os.Put(static_cast<typename OutputStream::Ch>(codepoint));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
			
		||||
            unsigned v = codepoint - 0x10000;
 | 
			
		||||
            os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
 | 
			
		||||
            os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
 | 
			
		||||
        if (codepoint <= 0xFFFF) {
 | 
			
		||||
            RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair 
 | 
			
		||||
            PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
			
		||||
            unsigned v = codepoint - 0x10000;
 | 
			
		||||
            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
 | 
			
		||||
            PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    static bool Decode(InputStream& is, unsigned* codepoint) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
 | 
			
		||||
        typename InputStream::Ch c = is.Take();
 | 
			
		||||
        if (c < 0xD800 || c > 0xDFFF) {
 | 
			
		||||
            *codepoint = static_cast<unsigned>(c);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        else if (c <= 0xDBFF) {
 | 
			
		||||
            *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
 | 
			
		||||
            c = is.Take();
 | 
			
		||||
            *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
 | 
			
		||||
            *codepoint += 0x10000;
 | 
			
		||||
            return c >= 0xDC00 && c <= 0xDFFF;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream, typename OutputStream>
 | 
			
		||||
    static bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
 | 
			
		||||
        typename InputStream::Ch c;
 | 
			
		||||
        os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
 | 
			
		||||
        if (c < 0xD800 || c > 0xDFFF)
 | 
			
		||||
            return true;
 | 
			
		||||
        else if (c <= 0xDBFF) {
 | 
			
		||||
            os.Put(c = is.Take());
 | 
			
		||||
            return c >= 0xDC00 && c <= 0xDFFF;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! UTF-16 little endian encoding.
 | 
			
		||||
template<typename CharType = wchar_t>
 | 
			
		||||
struct UTF16LE : UTF16<CharType> {
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        CharType c = Take(is);
 | 
			
		||||
        return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType Take(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        unsigned c = static_cast<uint8_t>(is.Take());
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 | 
			
		||||
        return static_cast<CharType>(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, CharType c) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! UTF-16 big endian encoding.
 | 
			
		||||
template<typename CharType = wchar_t>
 | 
			
		||||
struct UTF16BE : UTF16<CharType> {
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        CharType c = Take(is);
 | 
			
		||||
        return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType Take(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
 | 
			
		||||
        return static_cast<CharType>(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, CharType c) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// UTF32
 | 
			
		||||
 | 
			
		||||
//! UTF-32 encoding. 
 | 
			
		||||
/*! http://en.wikipedia.org/wiki/UTF-32
 | 
			
		||||
    \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
 | 
			
		||||
    \note implements Encoding concept
 | 
			
		||||
 | 
			
		||||
    \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
 | 
			
		||||
    For streaming, use UTF32LE and UTF32BE, which handle endianness.
 | 
			
		||||
*/
 | 
			
		||||
template<typename CharType = unsigned>
 | 
			
		||||
struct UTF32 {
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
 | 
			
		||||
 | 
			
		||||
    enum { supportUnicode = 1 };
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void Encode(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
 | 
			
		||||
        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
			
		||||
        os.Put(codepoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
 | 
			
		||||
        RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
 | 
			
		||||
        PutUnsafe(os, codepoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    static bool Decode(InputStream& is, unsigned* codepoint) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
 | 
			
		||||
        Ch c = is.Take();
 | 
			
		||||
        *codepoint = c;
 | 
			
		||||
        return c <= 0x10FFFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream, typename OutputStream>
 | 
			
		||||
    static bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
 | 
			
		||||
        Ch c;
 | 
			
		||||
        os.Put(c = is.Take());
 | 
			
		||||
        return c <= 0x10FFFF;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! UTF-32 little endian enocoding.
 | 
			
		||||
template<typename CharType = unsigned>
 | 
			
		||||
struct UTF32LE : UTF32<CharType> {
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        CharType c = Take(is);
 | 
			
		||||
        return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType Take(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        unsigned c = static_cast<uint8_t>(is.Take());
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
 | 
			
		||||
        return static_cast<CharType>(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, CharType c) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! UTF-32 big endian encoding.
 | 
			
		||||
template<typename CharType = unsigned>
 | 
			
		||||
struct UTF32BE : UTF32<CharType> {
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        CharType c = Take(is);
 | 
			
		||||
        return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType Take(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
 | 
			
		||||
        c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
 | 
			
		||||
        return static_cast<CharType>(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, CharType c) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// ASCII
 | 
			
		||||
 | 
			
		||||
//! ASCII encoding.
 | 
			
		||||
/*! http://en.wikipedia.org/wiki/ASCII
 | 
			
		||||
    \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
 | 
			
		||||
    \note implements Encoding concept
 | 
			
		||||
*/
 | 
			
		||||
template<typename CharType = char>
 | 
			
		||||
struct ASCII {
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
 | 
			
		||||
    enum { supportUnicode = 0 };
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void Encode(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        RAPIDJSON_ASSERT(codepoint <= 0x7F);
 | 
			
		||||
        os.Put(static_cast<Ch>(codepoint & 0xFF));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        RAPIDJSON_ASSERT(codepoint <= 0x7F);
 | 
			
		||||
        PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    static bool Decode(InputStream& is, unsigned* codepoint) {
 | 
			
		||||
        uint8_t c = static_cast<uint8_t>(is.Take());
 | 
			
		||||
        *codepoint = c;
 | 
			
		||||
        return c <= 0X7F;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream, typename OutputStream>
 | 
			
		||||
    static bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
        uint8_t c = static_cast<uint8_t>(is.Take());
 | 
			
		||||
        os.Put(static_cast<typename OutputStream::Ch>(c));
 | 
			
		||||
        return c <= 0x7F;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static CharType TakeBOM(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        uint8_t c = static_cast<uint8_t>(Take(is));
 | 
			
		||||
        return static_cast<Ch>(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputByteStream>
 | 
			
		||||
    static Ch Take(InputByteStream& is) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
 | 
			
		||||
        return static_cast<Ch>(is.Take());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void PutBOM(OutputByteStream& os) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        (void)os;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename OutputByteStream>
 | 
			
		||||
    static void Put(OutputByteStream& os, Ch c) {
 | 
			
		||||
        RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
 | 
			
		||||
        os.Put(static_cast<typename OutputByteStream::Ch>(c));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// AutoUTF
 | 
			
		||||
 | 
			
		||||
//! Runtime-specified UTF encoding type of a stream.
 | 
			
		||||
enum UTFType {
 | 
			
		||||
    kUTF8 = 0,      //!< UTF-8.
 | 
			
		||||
    kUTF16LE = 1,   //!< UTF-16 little endian.
 | 
			
		||||
    kUTF16BE = 2,   //!< UTF-16 big endian.
 | 
			
		||||
    kUTF32LE = 3,   //!< UTF-32 little endian.
 | 
			
		||||
    kUTF32BE = 4    //!< UTF-32 big endian.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
 | 
			
		||||
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
 | 
			
		||||
*/
 | 
			
		||||
template<typename CharType>
 | 
			
		||||
struct AutoUTF {
 | 
			
		||||
    typedef CharType Ch;
 | 
			
		||||
 | 
			
		||||
    enum { supportUnicode = 1 };
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        typedef void (*EncodeFunc)(OutputStream&, unsigned);
 | 
			
		||||
        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
 | 
			
		||||
        (*f[os.GetType()])(os, codepoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
 | 
			
		||||
        typedef void (*EncodeFunc)(OutputStream&, unsigned);
 | 
			
		||||
        static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
 | 
			
		||||
        (*f[os.GetType()])(os, codepoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
 | 
			
		||||
        typedef bool (*DecodeFunc)(InputStream&, unsigned*);
 | 
			
		||||
        static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
 | 
			
		||||
        return (*f[is.GetType()])(is, codepoint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
        typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
 | 
			
		||||
        static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
 | 
			
		||||
        return (*f[is.GetType()])(is, os);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#undef RAPIDJSON_ENCODINGS_FUNC
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Transcoder
 | 
			
		||||
 | 
			
		||||
//! Encoding conversion.
 | 
			
		||||
template<typename SourceEncoding, typename TargetEncoding>
 | 
			
		||||
struct Transcoder {
 | 
			
		||||
    //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
 | 
			
		||||
    template<typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        if (!SourceEncoding::Decode(is, &codepoint))
 | 
			
		||||
            return false;
 | 
			
		||||
        TargetEncoding::Encode(os, codepoint);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        if (!SourceEncoding::Decode(is, &codepoint))
 | 
			
		||||
            return false;
 | 
			
		||||
        TargetEncoding::EncodeUnsafe(os, codepoint);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Validate one Unicode codepoint from an encoded stream.
 | 
			
		||||
    template<typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
        return Transcode(is, os);   // Since source/target encoding is different, must transcode.
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Forward declaration.
 | 
			
		||||
template<typename Stream>
 | 
			
		||||
inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
 | 
			
		||||
 | 
			
		||||
//! Specialization of Transcoder with same source and target encoding.
 | 
			
		||||
template<typename Encoding>
 | 
			
		||||
struct Transcoder<Encoding, Encoding> {
 | 
			
		||||
    template<typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
 | 
			
		||||
        os.Put(is.Take());  // Just copy one code unit. This semantic is different from primary template class.
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template<typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
 | 
			
		||||
        PutUnsafe(os, is.Take());  // Just copy one code unit. This semantic is different from primary template class.
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template<typename InputStream, typename OutputStream>
 | 
			
		||||
    static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
 | 
			
		||||
        return Encoding::Validate(is, os);  // source/target encoding are the same
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_ENCODINGS_H_
 | 
			
		||||
							
								
								
									
										169
									
								
								library/include/rapidjson/error/en.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								library/include/rapidjson/error/en.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ERROR_EN_H_
 | 
			
		||||
#define RAPIDJSON_ERROR_EN_H_
 | 
			
		||||
 | 
			
		||||
#include "error.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(switch-enum)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(covered-switch-default)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Maps error code of parsing into error message.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \param parseErrorCode Error code obtained in parsing.
 | 
			
		||||
    \return the error message.
 | 
			
		||||
    \note User can make a copy of this function for localization.
 | 
			
		||||
        Using switch-case is safer for future modification of error codes.
 | 
			
		||||
*/
 | 
			
		||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
 | 
			
		||||
    switch (parseErrorCode) {
 | 
			
		||||
        case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING("No error.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorDocumentEmpty:                  return RAPIDJSON_ERROR_STRING("The document is empty.");
 | 
			
		||||
        case kParseErrorDocumentRootNotSingular:        return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
 | 
			
		||||
        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
 | 
			
		||||
        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
 | 
			
		||||
        case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
 | 
			
		||||
        case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
 | 
			
		||||
        case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
 | 
			
		||||
        case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
 | 
			
		||||
        case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
 | 
			
		||||
        case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
 | 
			
		||||
 | 
			
		||||
        case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
 | 
			
		||||
        case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
 | 
			
		||||
 | 
			
		||||
        default:                                        return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Maps error code of validation into error message.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \param validateErrorCode Error code obtained from validator.
 | 
			
		||||
    \return the error message.
 | 
			
		||||
    \note User can make a copy of this function for localization.
 | 
			
		||||
        Using switch-case is safer for future modification of error codes.
 | 
			
		||||
*/
 | 
			
		||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
 | 
			
		||||
    switch (validateErrorCode) {
 | 
			
		||||
        case kValidateErrors:                           return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
 | 
			
		||||
        case kValidateErrorNone:                        return RAPIDJSON_ERROR_STRING("No error.");
 | 
			
		||||
 | 
			
		||||
        case kValidateErrorMultipleOf:                  return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
 | 
			
		||||
        case kValidateErrorMaximum:                     return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
 | 
			
		||||
        case kValidateErrorExclusiveMaximum:            return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
 | 
			
		||||
        case kValidateErrorMinimum:                     return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
 | 
			
		||||
        case kValidateErrorExclusiveMinimum:            return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
 | 
			
		||||
 | 
			
		||||
        case kValidateErrorMaxLength:                   return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
 | 
			
		||||
        case kValidateErrorMinLength:                   return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
 | 
			
		||||
        case kValidateErrorPattern:                     return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
 | 
			
		||||
 | 
			
		||||
        case kValidateErrorMaxItems:                    return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
 | 
			
		||||
        case kValidateErrorMinItems:                    return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
 | 
			
		||||
        case kValidateErrorUniqueItems:                 return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
 | 
			
		||||
        case kValidateErrorAdditionalItems:             return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
 | 
			
		||||
 | 
			
		||||
        case kValidateErrorMaxProperties:               return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
 | 
			
		||||
        case kValidateErrorMinProperties:               return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
 | 
			
		||||
        case kValidateErrorRequired:                    return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
 | 
			
		||||
        case kValidateErrorAdditionalProperties:        return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
 | 
			
		||||
        case kValidateErrorPatternProperties:           return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
 | 
			
		||||
        case kValidateErrorDependencies:                return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
 | 
			
		||||
 | 
			
		||||
        case kValidateErrorEnum:                        return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
 | 
			
		||||
        case kValidateErrorType:                        return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
 | 
			
		||||
 | 
			
		||||
        case kValidateErrorOneOf:                       return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
 | 
			
		||||
        case kValidateErrorOneOfMatch:                  return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'.");
 | 
			
		||||
        case kValidateErrorAllOf:                       return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
 | 
			
		||||
        case kValidateErrorAnyOf:                       return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
 | 
			
		||||
        case kValidateErrorNot:                         return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
 | 
			
		||||
 | 
			
		||||
        default:                                        return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Maps error code of schema document compilation into error message.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \param schemaErrorCode Error code obtained from compiling the schema document.
 | 
			
		||||
    \return the error message.
 | 
			
		||||
    \note User can make a copy of this function for localization.
 | 
			
		||||
        Using switch-case is safer for future modification of error codes.
 | 
			
		||||
*/
 | 
			
		||||
  inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) {
 | 
			
		||||
      switch (schemaErrorCode) {
 | 
			
		||||
          case kSchemaErrorNone:                        return RAPIDJSON_ERROR_STRING("No error.");
 | 
			
		||||
 | 
			
		||||
          case kSchemaErrorStartUnknown:                return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document.");
 | 
			
		||||
          case kSchemaErrorRefPlainName:                return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer.");
 | 
			
		||||
          case kSchemaErrorRefInvalid:                  return RAPIDJSON_ERROR_STRING("$ref must not be an empty string.");
 | 
			
		||||
          case kSchemaErrorRefPointerInvalid:           return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'.");
 | 
			
		||||
          case kSchemaErrorRefUnknown:                  return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document.");
 | 
			
		||||
          case kSchemaErrorRefCyclical:                 return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical.");
 | 
			
		||||
          case kSchemaErrorRefNoRemoteProvider:         return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider.");
 | 
			
		||||
          case kSchemaErrorRefNoRemoteSchema:           return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema.");
 | 
			
		||||
          case kSchemaErrorRegexInvalid:                return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'.");
 | 
			
		||||
 | 
			
		||||
          default:                                      return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//! Maps error code of pointer parse into error message.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \param pointerParseErrorCode Error code obtained from pointer parse.
 | 
			
		||||
    \return the error message.
 | 
			
		||||
    \note User can make a copy of this function for localization.
 | 
			
		||||
        Using switch-case is safer for future modification of error codes.
 | 
			
		||||
*/
 | 
			
		||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) {
 | 
			
		||||
    switch (pointerParseErrorCode) {
 | 
			
		||||
        case kPointerParseErrorNone:                       return RAPIDJSON_ERROR_STRING("No error.");
 | 
			
		||||
 | 
			
		||||
        case kPointerParseErrorTokenMustBeginWithSolidus:  return RAPIDJSON_ERROR_STRING("A token must begin with a '/'.");
 | 
			
		||||
        case kPointerParseErrorInvalidEscape:              return RAPIDJSON_ERROR_STRING("Invalid escape.");
 | 
			
		||||
        case kPointerParseErrorInvalidPercentEncoding:     return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment.");
 | 
			
		||||
        case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment.");
 | 
			
		||||
 | 
			
		||||
        default:                                           return RAPIDJSON_ERROR_STRING("Unknown error.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_ERROR_EN_H_
 | 
			
		||||
							
								
								
									
										278
									
								
								library/include/rapidjson/error/error.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								library/include/rapidjson/error/error.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,278 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ERROR_ERROR_H_
 | 
			
		||||
#define RAPIDJSON_ERROR_ERROR_H_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*! \file error.h */
 | 
			
		||||
 | 
			
		||||
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_ERROR_CHARTYPE
 | 
			
		||||
 | 
			
		||||
//! Character type of error messages.
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    The default character type is \c char.
 | 
			
		||||
    On Windows, user can define this macro as \c TCHAR for supporting both
 | 
			
		||||
    unicode/non-unicode settings.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_ERROR_CHARTYPE
 | 
			
		||||
#define RAPIDJSON_ERROR_CHARTYPE char
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_ERROR_STRING
 | 
			
		||||
 | 
			
		||||
//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    By default this conversion macro does nothing.
 | 
			
		||||
    On Windows, user can define this macro as \c _T(x) for supporting both
 | 
			
		||||
    unicode/non-unicode settings.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_ERROR_STRING
 | 
			
		||||
#define RAPIDJSON_ERROR_STRING(x) x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// ParseErrorCode
 | 
			
		||||
 | 
			
		||||
//! Error code of parsing.
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \see GenericReader::Parse, GenericReader::GetParseErrorCode
 | 
			
		||||
*/
 | 
			
		||||
enum ParseErrorCode {
 | 
			
		||||
    kParseErrorNone = 0,                        //!< No error.
 | 
			
		||||
 | 
			
		||||
    kParseErrorDocumentEmpty,                   //!< The document is empty.
 | 
			
		||||
    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.
 | 
			
		||||
 | 
			
		||||
    kParseErrorValueInvalid,                    //!< Invalid value.
 | 
			
		||||
 | 
			
		||||
    kParseErrorObjectMissName,                  //!< Missing a name for object member.
 | 
			
		||||
    kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member.
 | 
			
		||||
    kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member.
 | 
			
		||||
 | 
			
		||||
    kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element.
 | 
			
		||||
 | 
			
		||||
    kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\u escape in string.
 | 
			
		||||
    kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid.
 | 
			
		||||
    kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string.
 | 
			
		||||
    kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string.
 | 
			
		||||
    kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string.
 | 
			
		||||
 | 
			
		||||
    kParseErrorNumberTooBig,                    //!< Number too big to be stored in double.
 | 
			
		||||
    kParseErrorNumberMissFraction,              //!< Miss fraction part in number.
 | 
			
		||||
    kParseErrorNumberMissExponent,              //!< Miss exponent in number.
 | 
			
		||||
 | 
			
		||||
    kParseErrorTermination,                     //!< Parsing was terminated.
 | 
			
		||||
    kParseErrorUnspecificSyntaxError            //!< Unspecific syntax error.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Result of parsing (wraps ParseErrorCode)
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \code
 | 
			
		||||
        Document doc;
 | 
			
		||||
        ParseResult ok = doc.Parse("[42]");
 | 
			
		||||
        if (!ok) {
 | 
			
		||||
            fprintf(stderr, "JSON parse error: %s (%u)",
 | 
			
		||||
                    GetParseError_En(ok.Code()), ok.Offset());
 | 
			
		||||
            exit(EXIT_FAILURE);
 | 
			
		||||
        }
 | 
			
		||||
    \endcode
 | 
			
		||||
    \see GenericReader::Parse, GenericDocument::Parse
 | 
			
		||||
*/
 | 
			
		||||
struct ParseResult {
 | 
			
		||||
    //!! Unspecified boolean type
 | 
			
		||||
    typedef bool (ParseResult::*BooleanType)() const;
 | 
			
		||||
public:
 | 
			
		||||
    //! Default constructor, no error.
 | 
			
		||||
    ParseResult() : code_(kParseErrorNone), offset_(0) {}
 | 
			
		||||
    //! Constructor to set an error.
 | 
			
		||||
    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
 | 
			
		||||
 | 
			
		||||
    //! Get the error code.
 | 
			
		||||
    ParseErrorCode Code() const { return code_; }
 | 
			
		||||
    //! Get the error offset, if \ref IsError(), 0 otherwise.
 | 
			
		||||
    size_t Offset() const { return offset_; }
 | 
			
		||||
 | 
			
		||||
    //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
 | 
			
		||||
    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
 | 
			
		||||
    //! Whether the result is an error.
 | 
			
		||||
    bool IsError() const { return code_ != kParseErrorNone; }
 | 
			
		||||
 | 
			
		||||
    bool operator==(const ParseResult& that) const { return code_ == that.code_; }
 | 
			
		||||
    bool operator==(ParseErrorCode code) const { return code_ == code; }
 | 
			
		||||
    friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
 | 
			
		||||
 | 
			
		||||
    bool operator!=(const ParseResult& that) const { return !(*this == that); }
 | 
			
		||||
    bool operator!=(ParseErrorCode code) const { return !(*this == code); }
 | 
			
		||||
    friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
 | 
			
		||||
 | 
			
		||||
    //! Reset error code.
 | 
			
		||||
    void Clear() { Set(kParseErrorNone); }
 | 
			
		||||
    //! Update error code and offset.
 | 
			
		||||
    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    ParseErrorCode code_;
 | 
			
		||||
    size_t offset_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Function pointer type of GetParseError().
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
 | 
			
		||||
    This is the prototype for \c GetParseError_X(), where \c X is a locale.
 | 
			
		||||
    User can dynamically change locale in runtime, e.g.:
 | 
			
		||||
\code
 | 
			
		||||
    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
 | 
			
		||||
    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// ValidateErrorCode
 | 
			
		||||
 | 
			
		||||
//! Error codes when validating.
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \see GenericSchemaValidator
 | 
			
		||||
*/
 | 
			
		||||
enum ValidateErrorCode {
 | 
			
		||||
    kValidateErrors    = -1,                   //!< Top level error code when kValidateContinueOnErrorsFlag set.
 | 
			
		||||
    kValidateErrorNone = 0,                    //!< No error.
 | 
			
		||||
 | 
			
		||||
    kValidateErrorMultipleOf,                  //!< Number is not a multiple of the 'multipleOf' value.
 | 
			
		||||
    kValidateErrorMaximum,                     //!< Number is greater than the 'maximum' value.
 | 
			
		||||
    kValidateErrorExclusiveMaximum,            //!< Number is greater than or equal to the 'maximum' value.
 | 
			
		||||
    kValidateErrorMinimum,                     //!< Number is less than the 'minimum' value.
 | 
			
		||||
    kValidateErrorExclusiveMinimum,            //!< Number is less than or equal to the 'minimum' value.
 | 
			
		||||
 | 
			
		||||
    kValidateErrorMaxLength,                   //!< String is longer than the 'maxLength' value.
 | 
			
		||||
    kValidateErrorMinLength,                   //!< String is longer than the 'maxLength' value.
 | 
			
		||||
    kValidateErrorPattern,                     //!< String does not match the 'pattern' regular expression.
 | 
			
		||||
 | 
			
		||||
    kValidateErrorMaxItems,                    //!< Array is longer than the 'maxItems' value.
 | 
			
		||||
    kValidateErrorMinItems,                    //!< Array is shorter than the 'minItems' value.
 | 
			
		||||
    kValidateErrorUniqueItems,                 //!< Array has duplicate items but 'uniqueItems' is true.
 | 
			
		||||
    kValidateErrorAdditionalItems,             //!< Array has additional items that are not allowed by the schema.
 | 
			
		||||
 | 
			
		||||
    kValidateErrorMaxProperties,               //!< Object has more members than 'maxProperties' value.
 | 
			
		||||
    kValidateErrorMinProperties,               //!< Object has less members than 'minProperties' value.
 | 
			
		||||
    kValidateErrorRequired,                    //!< Object is missing one or more members required by the schema.
 | 
			
		||||
    kValidateErrorAdditionalProperties,        //!< Object has additional members that are not allowed by the schema.
 | 
			
		||||
    kValidateErrorPatternProperties,           //!< See other errors.
 | 
			
		||||
    kValidateErrorDependencies,                //!< Object has missing property or schema dependencies.
 | 
			
		||||
 | 
			
		||||
    kValidateErrorEnum,                        //!< Property has a value that is not one of its allowed enumerated values.
 | 
			
		||||
    kValidateErrorType,                        //!< Property has a type that is not allowed by the schema.
 | 
			
		||||
 | 
			
		||||
    kValidateErrorOneOf,                       //!< Property did not match any of the sub-schemas specified by 'oneOf'.
 | 
			
		||||
    kValidateErrorOneOfMatch,                  //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
 | 
			
		||||
    kValidateErrorAllOf,                       //!< Property did not match all of the sub-schemas specified by 'allOf'.
 | 
			
		||||
    kValidateErrorAnyOf,                       //!< Property did not match any of the sub-schemas specified by 'anyOf'.
 | 
			
		||||
    kValidateErrorNot                          //!< Property matched the sub-schema specified by 'not'.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Function pointer type of GetValidateError().
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
 | 
			
		||||
    This is the prototype for \c GetValidateError_X(), where \c X is a locale.
 | 
			
		||||
    User can dynamically change locale in runtime, e.g.:
 | 
			
		||||
\code
 | 
			
		||||
    GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
 | 
			
		||||
    const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// SchemaErrorCode
 | 
			
		||||
 | 
			
		||||
//! Error codes when validating.
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \see GenericSchemaValidator
 | 
			
		||||
*/
 | 
			
		||||
enum SchemaErrorCode {
 | 
			
		||||
    kSchemaErrorNone = 0,                      //!< No error.
 | 
			
		||||
 | 
			
		||||
    kSchemaErrorStartUnknown,                  //!< Pointer to start of schema does not resolve to a location in the document
 | 
			
		||||
    kSchemaErrorRefPlainName,                  //!< $ref fragment must be a JSON pointer
 | 
			
		||||
    kSchemaErrorRefInvalid,                    //!< $ref must not be an empty string
 | 
			
		||||
    kSchemaErrorRefPointerInvalid,             //!< $ref fragment is not a valid JSON pointer at offset
 | 
			
		||||
    kSchemaErrorRefUnknown,                    //!< $ref does not resolve to a location in the target document
 | 
			
		||||
    kSchemaErrorRefCyclical,                   //!< $ref is cyclical
 | 
			
		||||
    kSchemaErrorRefNoRemoteProvider,           //!< $ref is remote but there is no remote provider
 | 
			
		||||
    kSchemaErrorRefNoRemoteSchema,             //!< $ref is remote but the remote provider did not return a schema
 | 
			
		||||
    kSchemaErrorRegexInvalid                   //!< Invalid regular expression in 'pattern' or 'patternProperties'
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Function pointer type of GetSchemaError().
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
 | 
			
		||||
    This is the prototype for \c GetSchemaError_X(), where \c X is a locale.
 | 
			
		||||
    User can dynamically change locale in runtime, e.g.:
 | 
			
		||||
\code
 | 
			
		||||
    GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever
 | 
			
		||||
    const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode());
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode);
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// PointerParseErrorCode
 | 
			
		||||
 | 
			
		||||
//! Error code of JSON pointer parsing.
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
    \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
 | 
			
		||||
*/
 | 
			
		||||
enum PointerParseErrorCode {
 | 
			
		||||
    kPointerParseErrorNone = 0,                     //!< The parse is successful
 | 
			
		||||
 | 
			
		||||
    kPointerParseErrorTokenMustBeginWithSolidus,    //!< A token must begin with a '/'
 | 
			
		||||
    kPointerParseErrorInvalidEscape,                //!< Invalid escape
 | 
			
		||||
    kPointerParseErrorInvalidPercentEncoding,       //!< Invalid percent encoding in URI fragment
 | 
			
		||||
    kPointerParseErrorCharacterMustPercentEncode    //!< A character must percent encoded in URI fragment
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Function pointer type of GetPointerParseError().
 | 
			
		||||
/*! \ingroup RAPIDJSON_ERRORS
 | 
			
		||||
 | 
			
		||||
    This is the prototype for \c GetPointerParseError_X(), where \c X is a locale.
 | 
			
		||||
    User can dynamically change locale in runtime, e.g.:
 | 
			
		||||
\code
 | 
			
		||||
    GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever
 | 
			
		||||
    const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode());
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_ERROR_ERROR_H_
 | 
			
		||||
							
								
								
									
										99
									
								
								library/include/rapidjson/filereadstream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								library/include/rapidjson/filereadstream.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_FILEREADSTREAM_H_
 | 
			
		||||
#define RAPIDJSON_FILEREADSTREAM_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(unreachable-code)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(missing-noreturn)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! File byte stream for input using fread().
 | 
			
		||||
/*!
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
class FileReadStream {
 | 
			
		||||
public:
 | 
			
		||||
    typedef char Ch;    //!< Character type (byte).
 | 
			
		||||
 | 
			
		||||
    //! Constructor.
 | 
			
		||||
    /*!
 | 
			
		||||
        \param fp File pointer opened for read.
 | 
			
		||||
        \param buffer user-supplied buffer.
 | 
			
		||||
        \param bufferSize size of buffer in bytes. Must >=4 bytes.
 | 
			
		||||
    */
 | 
			
		||||
    FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 
 | 
			
		||||
        RAPIDJSON_ASSERT(fp_ != 0);
 | 
			
		||||
        RAPIDJSON_ASSERT(bufferSize >= 4);
 | 
			
		||||
        Read();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return *current_; }
 | 
			
		||||
    Ch Take() { Ch c = *current_; Read(); return c; }
 | 
			
		||||
    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    void Flush() { RAPIDJSON_ASSERT(false); } 
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
    // For encoding detection only.
 | 
			
		||||
    const Ch* Peek4() const {
 | 
			
		||||
        return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void Read() {
 | 
			
		||||
        if (current_ < bufferLast_)
 | 
			
		||||
            ++current_;
 | 
			
		||||
        else if (!eof_) {
 | 
			
		||||
            count_ += readCount_;
 | 
			
		||||
            readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
 | 
			
		||||
            bufferLast_ = buffer_ + readCount_ - 1;
 | 
			
		||||
            current_ = buffer_;
 | 
			
		||||
 | 
			
		||||
            if (readCount_ < bufferSize_) {
 | 
			
		||||
                buffer_[readCount_] = '\0';
 | 
			
		||||
                ++bufferLast_;
 | 
			
		||||
                eof_ = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::FILE* fp_;
 | 
			
		||||
    Ch *buffer_;
 | 
			
		||||
    size_t bufferSize_;
 | 
			
		||||
    Ch *bufferLast_;
 | 
			
		||||
    Ch *current_;
 | 
			
		||||
    size_t readCount_;
 | 
			
		||||
    size_t count_;  //!< Number of characters read
 | 
			
		||||
    bool eof_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_FILESTREAM_H_
 | 
			
		||||
							
								
								
									
										104
									
								
								library/include/rapidjson/filewritestream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								library/include/rapidjson/filewritestream.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
 | 
			
		||||
#define RAPIDJSON_FILEWRITESTREAM_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(unreachable-code)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Wrapper of C file stream for output using fwrite().
 | 
			
		||||
/*!
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
class FileWriteStream {
 | 
			
		||||
public:
 | 
			
		||||
    typedef char Ch;    //!< Character type. Only support char.
 | 
			
		||||
 | 
			
		||||
    FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { 
 | 
			
		||||
        RAPIDJSON_ASSERT(fp_ != 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Put(char c) { 
 | 
			
		||||
        if (current_ >= bufferEnd_)
 | 
			
		||||
            Flush();
 | 
			
		||||
 | 
			
		||||
        *current_++ = c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void PutN(char c, size_t n) {
 | 
			
		||||
        size_t avail = static_cast<size_t>(bufferEnd_ - current_);
 | 
			
		||||
        while (n > avail) {
 | 
			
		||||
            std::memset(current_, c, avail);
 | 
			
		||||
            current_ += avail;
 | 
			
		||||
            Flush();
 | 
			
		||||
            n -= avail;
 | 
			
		||||
            avail = static_cast<size_t>(bufferEnd_ - current_);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (n > 0) {
 | 
			
		||||
            std::memset(current_, c, n);
 | 
			
		||||
            current_ += n;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Flush() {
 | 
			
		||||
        if (current_ != buffer_) {
 | 
			
		||||
            size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
 | 
			
		||||
            if (result < static_cast<size_t>(current_ - buffer_)) {
 | 
			
		||||
                // failure deliberately ignored at this time
 | 
			
		||||
                // added to avoid warn_unused_result build errors
 | 
			
		||||
            }
 | 
			
		||||
            current_ = buffer_;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    char Take() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // Prohibit copy constructor & assignment operator.
 | 
			
		||||
    FileWriteStream(const FileWriteStream&);
 | 
			
		||||
    FileWriteStream& operator=(const FileWriteStream&);
 | 
			
		||||
 | 
			
		||||
    std::FILE* fp_;
 | 
			
		||||
    char *buffer_;
 | 
			
		||||
    char *bufferEnd_;
 | 
			
		||||
    char *current_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Implement specialized version of PutN() with memset() for better performance.
 | 
			
		||||
template<>
 | 
			
		||||
inline void PutN(FileWriteStream& stream, char c, size_t n) {
 | 
			
		||||
    stream.PutN(c, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_FILESTREAM_H_
 | 
			
		||||
							
								
								
									
										151
									
								
								library/include/rapidjson/fwd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								library/include/rapidjson/fwd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_FWD_H_
 | 
			
		||||
#define RAPIDJSON_FWD_H_
 | 
			
		||||
 | 
			
		||||
#include "rapidjson.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
// encodings.h
 | 
			
		||||
 | 
			
		||||
template<typename CharType> struct UTF8;
 | 
			
		||||
template<typename CharType> struct UTF16;
 | 
			
		||||
template<typename CharType> struct UTF16BE;
 | 
			
		||||
template<typename CharType> struct UTF16LE;
 | 
			
		||||
template<typename CharType> struct UTF32;
 | 
			
		||||
template<typename CharType> struct UTF32BE;
 | 
			
		||||
template<typename CharType> struct UTF32LE;
 | 
			
		||||
template<typename CharType> struct ASCII;
 | 
			
		||||
template<typename CharType> struct AutoUTF;
 | 
			
		||||
 | 
			
		||||
template<typename SourceEncoding, typename TargetEncoding>
 | 
			
		||||
struct Transcoder;
 | 
			
		||||
 | 
			
		||||
// allocators.h
 | 
			
		||||
 | 
			
		||||
class CrtAllocator;
 | 
			
		||||
 | 
			
		||||
template <typename BaseAllocator>
 | 
			
		||||
class MemoryPoolAllocator;
 | 
			
		||||
 | 
			
		||||
// stream.h
 | 
			
		||||
 | 
			
		||||
template <typename Encoding>
 | 
			
		||||
struct GenericStringStream;
 | 
			
		||||
 | 
			
		||||
typedef GenericStringStream<UTF8<char> > StringStream;
 | 
			
		||||
 | 
			
		||||
template <typename Encoding>
 | 
			
		||||
struct GenericInsituStringStream;
 | 
			
		||||
 | 
			
		||||
typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
 | 
			
		||||
 | 
			
		||||
// stringbuffer.h
 | 
			
		||||
 | 
			
		||||
template <typename Encoding, typename Allocator>
 | 
			
		||||
class GenericStringBuffer;
 | 
			
		||||
 | 
			
		||||
typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
 | 
			
		||||
 | 
			
		||||
// filereadstream.h
 | 
			
		||||
 | 
			
		||||
class FileReadStream;
 | 
			
		||||
 | 
			
		||||
// filewritestream.h
 | 
			
		||||
 | 
			
		||||
class FileWriteStream;
 | 
			
		||||
 | 
			
		||||
// memorybuffer.h
 | 
			
		||||
 | 
			
		||||
template <typename Allocator>
 | 
			
		||||
struct GenericMemoryBuffer;
 | 
			
		||||
 | 
			
		||||
typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
 | 
			
		||||
 | 
			
		||||
// memorystream.h
 | 
			
		||||
 | 
			
		||||
struct MemoryStream;
 | 
			
		||||
 | 
			
		||||
// reader.h
 | 
			
		||||
 | 
			
		||||
template<typename Encoding, typename Derived>
 | 
			
		||||
struct BaseReaderHandler;
 | 
			
		||||
 | 
			
		||||
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
 | 
			
		||||
class GenericReader;
 | 
			
		||||
 | 
			
		||||
typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
 | 
			
		||||
 | 
			
		||||
// writer.h
 | 
			
		||||
 | 
			
		||||
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
 | 
			
		||||
class Writer;
 | 
			
		||||
 | 
			
		||||
// prettywriter.h
 | 
			
		||||
 | 
			
		||||
template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
 | 
			
		||||
class PrettyWriter;
 | 
			
		||||
 | 
			
		||||
// document.h
 | 
			
		||||
 | 
			
		||||
template <typename Encoding, typename Allocator> 
 | 
			
		||||
class GenericMember;
 | 
			
		||||
 | 
			
		||||
template <bool Const, typename Encoding, typename Allocator>
 | 
			
		||||
class GenericMemberIterator;
 | 
			
		||||
 | 
			
		||||
template<typename CharType>
 | 
			
		||||
struct GenericStringRef;
 | 
			
		||||
 | 
			
		||||
template <typename Encoding, typename Allocator> 
 | 
			
		||||
class GenericValue;
 | 
			
		||||
 | 
			
		||||
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
 | 
			
		||||
 | 
			
		||||
template <typename Encoding, typename Allocator, typename StackAllocator>
 | 
			
		||||
class GenericDocument;
 | 
			
		||||
 | 
			
		||||
typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
 | 
			
		||||
 | 
			
		||||
// pointer.h
 | 
			
		||||
 | 
			
		||||
template <typename ValueType, typename Allocator>
 | 
			
		||||
class GenericPointer;
 | 
			
		||||
 | 
			
		||||
typedef GenericPointer<Value, CrtAllocator> Pointer;
 | 
			
		||||
 | 
			
		||||
// schema.h
 | 
			
		||||
 | 
			
		||||
template <typename SchemaDocumentType>
 | 
			
		||||
class IGenericRemoteSchemaDocumentProvider;
 | 
			
		||||
 | 
			
		||||
template <typename ValueT, typename Allocator>
 | 
			
		||||
class GenericSchemaDocument;
 | 
			
		||||
 | 
			
		||||
typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
 | 
			
		||||
typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
 | 
			
		||||
 | 
			
		||||
template <
 | 
			
		||||
    typename SchemaDocumentType,
 | 
			
		||||
    typename OutputHandler,
 | 
			
		||||
    typename StateAllocator>
 | 
			
		||||
class GenericSchemaValidator;
 | 
			
		||||
 | 
			
		||||
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_RAPIDJSONFWD_H_
 | 
			
		||||
							
								
								
									
										297
									
								
								library/include/rapidjson/internal/biginteger.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								library/include/rapidjson/internal/biginteger.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,297 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_BIGINTEGER_H_
 | 
			
		||||
#define RAPIDJSON_BIGINTEGER_H_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
 | 
			
		||||
#include <intrin.h> // for _umul128
 | 
			
		||||
#if !defined(_ARM64EC_)
 | 
			
		||||
#pragma intrinsic(_umul128)
 | 
			
		||||
#else
 | 
			
		||||
#pragma comment(lib,"softintrin")
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
class BigInteger {
 | 
			
		||||
public:
 | 
			
		||||
    typedef uint64_t Type;
 | 
			
		||||
 | 
			
		||||
    BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
 | 
			
		||||
        std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit BigInteger(uint64_t u) : count_(1) {
 | 
			
		||||
        digits_[0] = u;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename Ch>
 | 
			
		||||
    BigInteger(const Ch* decimals, size_t length) : count_(1) {
 | 
			
		||||
        RAPIDJSON_ASSERT(length > 0);
 | 
			
		||||
        digits_[0] = 0;
 | 
			
		||||
        size_t i = 0;
 | 
			
		||||
        const size_t kMaxDigitPerIteration = 19;  // 2^64 = 18446744073709551616 > 10^19
 | 
			
		||||
        while (length >= kMaxDigitPerIteration) {
 | 
			
		||||
            AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
 | 
			
		||||
            length -= kMaxDigitPerIteration;
 | 
			
		||||
            i += kMaxDigitPerIteration;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (length > 0)
 | 
			
		||||
            AppendDecimal64(decimals + i, decimals + i + length);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    BigInteger& operator=(const BigInteger &rhs)
 | 
			
		||||
    {
 | 
			
		||||
        if (this != &rhs) {
 | 
			
		||||
            count_ = rhs.count_;
 | 
			
		||||
            std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    BigInteger& operator=(uint64_t u) {
 | 
			
		||||
        digits_[0] = u;            
 | 
			
		||||
        count_ = 1;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BigInteger& operator+=(uint64_t u) {
 | 
			
		||||
        Type backup = digits_[0];
 | 
			
		||||
        digits_[0] += u;
 | 
			
		||||
        for (size_t i = 0; i < count_ - 1; i++) {
 | 
			
		||||
            if (digits_[i] >= backup)
 | 
			
		||||
                return *this; // no carry
 | 
			
		||||
            backup = digits_[i + 1];
 | 
			
		||||
            digits_[i + 1] += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Last carry
 | 
			
		||||
        if (digits_[count_ - 1] < backup)
 | 
			
		||||
            PushBack(1);
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BigInteger& operator*=(uint64_t u) {
 | 
			
		||||
        if (u == 0) return *this = 0;
 | 
			
		||||
        if (u == 1) return *this;
 | 
			
		||||
        if (*this == 1) return *this = u;
 | 
			
		||||
 | 
			
		||||
        uint64_t k = 0;
 | 
			
		||||
        for (size_t i = 0; i < count_; i++) {
 | 
			
		||||
            uint64_t hi;
 | 
			
		||||
            digits_[i] = MulAdd64(digits_[i], u, k, &hi);
 | 
			
		||||
            k = hi;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (k > 0)
 | 
			
		||||
            PushBack(k);
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BigInteger& operator*=(uint32_t u) {
 | 
			
		||||
        if (u == 0) return *this = 0;
 | 
			
		||||
        if (u == 1) return *this;
 | 
			
		||||
        if (*this == 1) return *this = u;
 | 
			
		||||
 | 
			
		||||
        uint64_t k = 0;
 | 
			
		||||
        for (size_t i = 0; i < count_; i++) {
 | 
			
		||||
            const uint64_t c = digits_[i] >> 32;
 | 
			
		||||
            const uint64_t d = digits_[i] & 0xFFFFFFFF;
 | 
			
		||||
            const uint64_t uc = u * c;
 | 
			
		||||
            const uint64_t ud = u * d;
 | 
			
		||||
            const uint64_t p0 = ud + k;
 | 
			
		||||
            const uint64_t p1 = uc + (p0 >> 32);
 | 
			
		||||
            digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
 | 
			
		||||
            k = p1 >> 32;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (k > 0)
 | 
			
		||||
            PushBack(k);
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BigInteger& operator<<=(size_t shift) {
 | 
			
		||||
        if (IsZero() || shift == 0) return *this;
 | 
			
		||||
 | 
			
		||||
        size_t offset = shift / kTypeBit;
 | 
			
		||||
        size_t interShift = shift % kTypeBit;
 | 
			
		||||
        RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
 | 
			
		||||
 | 
			
		||||
        if (interShift == 0) {
 | 
			
		||||
            std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
 | 
			
		||||
            count_ += offset;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            digits_[count_] = 0;
 | 
			
		||||
            for (size_t i = count_; i > 0; i--)
 | 
			
		||||
                digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
 | 
			
		||||
            digits_[offset] = digits_[0] << interShift;
 | 
			
		||||
            count_ += offset;
 | 
			
		||||
            if (digits_[count_])
 | 
			
		||||
                count_++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::memset(digits_, 0, offset * sizeof(Type));
 | 
			
		||||
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator==(const BigInteger& rhs) const {
 | 
			
		||||
        return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator==(const Type rhs) const {
 | 
			
		||||
        return count_ == 1 && digits_[0] == rhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    BigInteger& MultiplyPow5(unsigned exp) {
 | 
			
		||||
        static const uint32_t kPow5[12] = {
 | 
			
		||||
            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 * 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;
 | 
			
		||||
        for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
 | 
			
		||||
        for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
 | 
			
		||||
        if (exp > 0)                 *this *= kPow5[exp - 1];
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Compute absolute difference of this and rhs.
 | 
			
		||||
    // Assume this != rhs
 | 
			
		||||
    bool Difference(const BigInteger& rhs, BigInteger* out) const {
 | 
			
		||||
        int cmp = Compare(rhs);
 | 
			
		||||
        RAPIDJSON_ASSERT(cmp != 0);
 | 
			
		||||
        const BigInteger *a, *b;  // Makes a > b
 | 
			
		||||
        bool ret;
 | 
			
		||||
        if (cmp < 0) { a = &rhs; b = this; ret = true; }
 | 
			
		||||
        else         { a = this; b = &rhs; ret = false; }
 | 
			
		||||
 | 
			
		||||
        Type borrow = 0;
 | 
			
		||||
        for (size_t i = 0; i < a->count_; i++) {
 | 
			
		||||
            Type d = a->digits_[i] - borrow;
 | 
			
		||||
            if (i < b->count_)
 | 
			
		||||
                d -= b->digits_[i];
 | 
			
		||||
            borrow = (d > a->digits_[i]) ? 1 : 0;
 | 
			
		||||
            out->digits_[i] = d;
 | 
			
		||||
            if (d != 0)
 | 
			
		||||
                out->count_ = i + 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int Compare(const BigInteger& rhs) const {
 | 
			
		||||
        if (count_ != rhs.count_)
 | 
			
		||||
            return count_ < rhs.count_ ? -1 : 1;
 | 
			
		||||
 | 
			
		||||
        for (size_t i = count_; i-- > 0;)
 | 
			
		||||
            if (digits_[i] != rhs.digits_[i])
 | 
			
		||||
                return digits_[i] < rhs.digits_[i] ? -1 : 1;
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t GetCount() const { return count_; }
 | 
			
		||||
    Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
 | 
			
		||||
    bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    template<typename Ch>
 | 
			
		||||
    void AppendDecimal64(const Ch* begin, const Ch* end) {
 | 
			
		||||
        uint64_t u = ParseUint64(begin, end);
 | 
			
		||||
        if (IsZero())
 | 
			
		||||
            *this = u;
 | 
			
		||||
        else {
 | 
			
		||||
            unsigned exp = static_cast<unsigned>(end - begin);
 | 
			
		||||
            (MultiplyPow5(exp) <<= exp) += u;   // *this = *this * 10^exp + u
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void PushBack(Type digit) {
 | 
			
		||||
        RAPIDJSON_ASSERT(count_ < kCapacity);
 | 
			
		||||
        digits_[count_++] = digit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename Ch>
 | 
			
		||||
    static uint64_t ParseUint64(const Ch* begin, const Ch* end) {
 | 
			
		||||
        uint64_t r = 0;
 | 
			
		||||
        for (const Ch* p = begin; p != end; ++p) {
 | 
			
		||||
            RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9'));
 | 
			
		||||
            r = r * 10u + static_cast<unsigned>(*p - Ch('0'));
 | 
			
		||||
        }
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Assume a * b + k < 2^128
 | 
			
		||||
    static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
 | 
			
		||||
#if defined(_MSC_VER) && defined(_M_AMD64)
 | 
			
		||||
        uint64_t low = _umul128(a, b, outHigh) + k;
 | 
			
		||||
        if (low < k)
 | 
			
		||||
            (*outHigh)++;
 | 
			
		||||
        return low;
 | 
			
		||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
 | 
			
		||||
        __extension__ typedef unsigned __int128 uint128;
 | 
			
		||||
        uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
 | 
			
		||||
        p += k;
 | 
			
		||||
        *outHigh = static_cast<uint64_t>(p >> 64);
 | 
			
		||||
        return static_cast<uint64_t>(p);
 | 
			
		||||
#else
 | 
			
		||||
        const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
 | 
			
		||||
        uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
 | 
			
		||||
        x1 += (x0 >> 32); // can't give carry
 | 
			
		||||
        x1 += x2;
 | 
			
		||||
        if (x1 < x2)
 | 
			
		||||
            x3 += (static_cast<uint64_t>(1) << 32);
 | 
			
		||||
        uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
 | 
			
		||||
        uint64_t hi = x3 + (x1 >> 32);
 | 
			
		||||
 | 
			
		||||
        lo += k;
 | 
			
		||||
        if (lo < k)
 | 
			
		||||
            hi++;
 | 
			
		||||
        *outHigh = hi;
 | 
			
		||||
        return lo;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static const size_t kBitCount = 3328;  // 64bit * 54 > 10^1000
 | 
			
		||||
    static const size_t kCapacity = kBitCount / sizeof(Type);
 | 
			
		||||
    static const size_t kTypeBit = sizeof(Type) * 8;
 | 
			
		||||
 | 
			
		||||
    Type digits_[kCapacity];
 | 
			
		||||
    size_t count_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_BIGINTEGER_H_
 | 
			
		||||
							
								
								
									
										71
									
								
								library/include/rapidjson/internal/clzll.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								library/include/rapidjson/internal/clzll.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_CLZLL_H_
 | 
			
		||||
#define RAPIDJSON_CLZLL_H_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(UNDER_CE)
 | 
			
		||||
#include <intrin.h>
 | 
			
		||||
#if defined(_WIN64)
 | 
			
		||||
#pragma intrinsic(_BitScanReverse64)
 | 
			
		||||
#else
 | 
			
		||||
#pragma intrinsic(_BitScanReverse)
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
inline uint32_t clzll(uint64_t x) {
 | 
			
		||||
    // Passing 0 to __builtin_clzll is UB in GCC and results in an
 | 
			
		||||
    // infinite loop in the software implementation.
 | 
			
		||||
    RAPIDJSON_ASSERT(x != 0);
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(UNDER_CE)
 | 
			
		||||
    unsigned long r = 0;
 | 
			
		||||
#if defined(_WIN64)
 | 
			
		||||
    _BitScanReverse64(&r, x);
 | 
			
		||||
#else
 | 
			
		||||
    // Scan the high 32 bits.
 | 
			
		||||
    if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
 | 
			
		||||
        return 63 - (r + 32);
 | 
			
		||||
 | 
			
		||||
    // Scan the low 32 bits.
 | 
			
		||||
    _BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF));
 | 
			
		||||
#endif // _WIN64
 | 
			
		||||
 | 
			
		||||
    return 63 - r;
 | 
			
		||||
#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
 | 
			
		||||
    // __builtin_clzll wrapper
 | 
			
		||||
    return static_cast<uint32_t>(__builtin_clzll(x));
 | 
			
		||||
#else
 | 
			
		||||
    // naive version
 | 
			
		||||
    uint32_t r = 0;
 | 
			
		||||
    while (!(x & (static_cast<uint64_t>(1) << 63))) {
 | 
			
		||||
        x <<= 1;
 | 
			
		||||
        ++r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return r;
 | 
			
		||||
#endif // _MSC_VER
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_CLZLL_H_
 | 
			
		||||
							
								
								
									
										261
									
								
								library/include/rapidjson/internal/diyfp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								library/include/rapidjson/internal/diyfp.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,261 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
 | 
			
		||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
 | 
			
		||||
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_DIYFP_H_
 | 
			
		||||
#define RAPIDJSON_DIYFP_H_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
#include "clzll.h"
 | 
			
		||||
#include <limits>
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
 | 
			
		||||
#include <intrin.h>
 | 
			
		||||
#if !defined(_ARM64EC_)
 | 
			
		||||
#pragma intrinsic(_umul128)
 | 
			
		||||
#else
 | 
			
		||||
#pragma comment(lib,"softintrin")
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct DiyFp {
 | 
			
		||||
    DiyFp() : f(), e() {}
 | 
			
		||||
 | 
			
		||||
    DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
 | 
			
		||||
 | 
			
		||||
    explicit DiyFp(double d) {
 | 
			
		||||
        union {
 | 
			
		||||
            double d;
 | 
			
		||||
            uint64_t u64;
 | 
			
		||||
        } u = { d };
 | 
			
		||||
 | 
			
		||||
        int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
 | 
			
		||||
        uint64_t significand = (u.u64 & kDpSignificandMask);
 | 
			
		||||
        if (biased_e != 0) {
 | 
			
		||||
            f = significand + kDpHiddenBit;
 | 
			
		||||
            e = biased_e - kDpExponentBias;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            f = significand;
 | 
			
		||||
            e = kDpMinExponent + 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DiyFp operator-(const DiyFp& rhs) const {
 | 
			
		||||
        return DiyFp(f - rhs.f, e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DiyFp operator*(const DiyFp& rhs) const {
 | 
			
		||||
#if defined(_MSC_VER) && defined(_M_AMD64)
 | 
			
		||||
        uint64_t h;
 | 
			
		||||
        uint64_t l = _umul128(f, rhs.f, &h);
 | 
			
		||||
        if (l & (uint64_t(1) << 63)) // rounding
 | 
			
		||||
            h++;
 | 
			
		||||
        return DiyFp(h, e + rhs.e + 64);
 | 
			
		||||
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
 | 
			
		||||
        __extension__ typedef unsigned __int128 uint128;
 | 
			
		||||
        uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
 | 
			
		||||
        uint64_t h = static_cast<uint64_t>(p >> 64);
 | 
			
		||||
        uint64_t l = static_cast<uint64_t>(p);
 | 
			
		||||
        if (l & (uint64_t(1) << 63)) // rounding
 | 
			
		||||
            h++;
 | 
			
		||||
        return DiyFp(h, e + rhs.e + 64);
 | 
			
		||||
#else
 | 
			
		||||
        const uint64_t M32 = 0xFFFFFFFF;
 | 
			
		||||
        const uint64_t a = f >> 32;
 | 
			
		||||
        const uint64_t b = f & M32;
 | 
			
		||||
        const uint64_t c = rhs.f >> 32;
 | 
			
		||||
        const uint64_t d = rhs.f & M32;
 | 
			
		||||
        const uint64_t ac = a * c;
 | 
			
		||||
        const uint64_t bc = b * c;
 | 
			
		||||
        const uint64_t ad = a * d;
 | 
			
		||||
        const uint64_t bd = b * d;
 | 
			
		||||
        uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
 | 
			
		||||
        tmp += 1U << 31;  /// mult_round
 | 
			
		||||
        return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DiyFp Normalize() const {
 | 
			
		||||
        int s = static_cast<int>(clzll(f));
 | 
			
		||||
        return DiyFp(f << s, e - s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DiyFp NormalizeBoundary() const {
 | 
			
		||||
        DiyFp res = *this;
 | 
			
		||||
        while (!(res.f & (kDpHiddenBit << 1))) {
 | 
			
		||||
            res.f <<= 1;
 | 
			
		||||
            res.e--;
 | 
			
		||||
        }
 | 
			
		||||
        res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
 | 
			
		||||
        res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
 | 
			
		||||
        return res;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
 | 
			
		||||
        DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
 | 
			
		||||
        DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
 | 
			
		||||
        mi.f <<= mi.e - pl.e;
 | 
			
		||||
        mi.e = pl.e;
 | 
			
		||||
        *plus = pl;
 | 
			
		||||
        *minus = mi;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double ToDouble() const {
 | 
			
		||||
        union {
 | 
			
		||||
            double d;
 | 
			
		||||
            uint64_t u64;
 | 
			
		||||
        }u;
 | 
			
		||||
        RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
 | 
			
		||||
        if (e < kDpDenormalExponent) {
 | 
			
		||||
            // Underflow.
 | 
			
		||||
            return 0.0;
 | 
			
		||||
        }
 | 
			
		||||
        if (e >= kDpMaxExponent) {
 | 
			
		||||
            // Overflow.
 | 
			
		||||
            return std::numeric_limits<double>::infinity();
 | 
			
		||||
        }
 | 
			
		||||
        const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
 | 
			
		||||
            static_cast<uint64_t>(e + kDpExponentBias);
 | 
			
		||||
        u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
 | 
			
		||||
        return u.d;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static const int kDiySignificandSize = 64;
 | 
			
		||||
    static const int kDpSignificandSize = 52;
 | 
			
		||||
    static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
 | 
			
		||||
    static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
 | 
			
		||||
    static const int kDpMinExponent = -kDpExponentBias;
 | 
			
		||||
    static const int kDpDenormalExponent = -kDpExponentBias + 1;
 | 
			
		||||
    static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
 | 
			
		||||
    static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
 | 
			
		||||
    static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
 | 
			
		||||
 | 
			
		||||
    uint64_t f;
 | 
			
		||||
    int e;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline DiyFp GetCachedPowerByIndex(size_t index) {
 | 
			
		||||
    // 10^-348, 10^-340, ..., 10^340
 | 
			
		||||
    static const uint64_t kCachedPowers_F[] = {
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
 | 
			
		||||
        RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
 | 
			
		||||
    };
 | 
			
		||||
    static const int16_t kCachedPowers_E[] = {
 | 
			
		||||
        -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007,  -980,
 | 
			
		||||
        -954,  -927,  -901,  -874,  -847,  -821,  -794,  -768,  -741,  -715,
 | 
			
		||||
        -688,  -661,  -635,  -608,  -582,  -555,  -529,  -502,  -475,  -449,
 | 
			
		||||
        -422,  -396,  -369,  -343,  -316,  -289,  -263,  -236,  -210,  -183,
 | 
			
		||||
        -157,  -130,  -103,   -77,   -50,   -24,     3,    30,    56,    83,
 | 
			
		||||
        109,   136,   162,   189,   216,   242,   269,   295,   322,   348,
 | 
			
		||||
        375,   402,   428,   455,   481,   508,   534,   561,   588,   614,
 | 
			
		||||
        641,   667,   694,   720,   747,   774,   800,   827,   853,   880,
 | 
			
		||||
        907,   933,   960,   986,  1013,  1039,  1066
 | 
			
		||||
    };
 | 
			
		||||
    RAPIDJSON_ASSERT(index < 87);
 | 
			
		||||
    return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline DiyFp GetCachedPower(int e, int* K) {
 | 
			
		||||
 | 
			
		||||
    //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
 | 
			
		||||
    double dk = (-61 - e) * 0.30102999566398114 + 347;  // dk must be positive, so can do ceiling in positive
 | 
			
		||||
    int k = static_cast<int>(dk);
 | 
			
		||||
    if (dk - k > 0.0)
 | 
			
		||||
        k++;
 | 
			
		||||
 | 
			
		||||
    unsigned index = static_cast<unsigned>((k >> 3) + 1);
 | 
			
		||||
    *K = -(-348 + static_cast<int>(index << 3));    // decimal exponent no need lookup table
 | 
			
		||||
 | 
			
		||||
    return GetCachedPowerByIndex(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline DiyFp GetCachedPower10(int exp, int *outExp) {
 | 
			
		||||
    RAPIDJSON_ASSERT(exp >= -348);
 | 
			
		||||
    unsigned index = static_cast<unsigned>(exp + 348) / 8u;
 | 
			
		||||
    *outExp = -348 + static_cast<int>(index) * 8;
 | 
			
		||||
    return GetCachedPowerByIndex(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_DIYFP_H_
 | 
			
		||||
							
								
								
									
										249
									
								
								library/include/rapidjson/internal/dtoa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								library/include/rapidjson/internal/dtoa.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,249 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
 | 
			
		||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
 | 
			
		||||
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_DTOA_
 | 
			
		||||
#define RAPIDJSON_DTOA_
 | 
			
		||||
 | 
			
		||||
#include "itoa.h" // GetDigitsLut()
 | 
			
		||||
#include "diyfp.h"
 | 
			
		||||
#include "ieee754.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
 | 
			
		||||
    while (rest < wp_w && delta - rest >= ten_kappa &&
 | 
			
		||||
           (rest + ten_kappa < wp_w ||  /// closer
 | 
			
		||||
            wp_w - rest > rest + ten_kappa - wp_w)) {
 | 
			
		||||
        buffer[len - 1]--;
 | 
			
		||||
        rest += ten_kappa;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline int CountDecimalDigit32(uint32_t n) {
 | 
			
		||||
    // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
 | 
			
		||||
    if (n < 10) return 1;
 | 
			
		||||
    if (n < 100) return 2;
 | 
			
		||||
    if (n < 1000) return 3;
 | 
			
		||||
    if (n < 10000) return 4;
 | 
			
		||||
    if (n < 100000) return 5;
 | 
			
		||||
    if (n < 1000000) return 6;
 | 
			
		||||
    if (n < 10000000) return 7;
 | 
			
		||||
    if (n < 100000000) return 8;
 | 
			
		||||
    // Will not reach 10 digits in DigitGen()
 | 
			
		||||
    //if (n < 1000000000) return 9;
 | 
			
		||||
    //return 10;
 | 
			
		||||
    return 9;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
 | 
			
		||||
    static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL,
 | 
			
		||||
                                       1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL,
 | 
			
		||||
                                       10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
 | 
			
		||||
                                       10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL,
 | 
			
		||||
                                       10000000000000000000ULL };
 | 
			
		||||
    const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
 | 
			
		||||
    const DiyFp wp_w = Mp - W;
 | 
			
		||||
    uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
 | 
			
		||||
    uint64_t p2 = Mp.f & (one.f - 1);
 | 
			
		||||
    int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
 | 
			
		||||
    *len = 0;
 | 
			
		||||
 | 
			
		||||
    while (kappa > 0) {
 | 
			
		||||
        uint32_t d = 0;
 | 
			
		||||
        switch (kappa) {
 | 
			
		||||
            case  9: d = p1 /  100000000; p1 %=  100000000; break;
 | 
			
		||||
            case  8: d = p1 /   10000000; p1 %=   10000000; break;
 | 
			
		||||
            case  7: d = p1 /    1000000; p1 %=    1000000; break;
 | 
			
		||||
            case  6: d = p1 /     100000; p1 %=     100000; break;
 | 
			
		||||
            case  5: d = p1 /      10000; p1 %=      10000; break;
 | 
			
		||||
            case  4: d = p1 /       1000; p1 %=       1000; break;
 | 
			
		||||
            case  3: d = p1 /        100; p1 %=        100; break;
 | 
			
		||||
            case  2: d = p1 /         10; p1 %=         10; break;
 | 
			
		||||
            case  1: d = p1;              p1 =           0; break;
 | 
			
		||||
            default:;
 | 
			
		||||
        }
 | 
			
		||||
        if (d || *len)
 | 
			
		||||
            buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
 | 
			
		||||
        kappa--;
 | 
			
		||||
        uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
 | 
			
		||||
        if (tmp <= delta) {
 | 
			
		||||
            *K += kappa;
 | 
			
		||||
            GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // kappa = 0
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        p2 *= 10;
 | 
			
		||||
        delta *= 10;
 | 
			
		||||
        char d = static_cast<char>(p2 >> -one.e);
 | 
			
		||||
        if (d || *len)
 | 
			
		||||
            buffer[(*len)++] = static_cast<char>('0' + d);
 | 
			
		||||
        p2 &= one.f - 1;
 | 
			
		||||
        kappa--;
 | 
			
		||||
        if (p2 < delta) {
 | 
			
		||||
            *K += kappa;
 | 
			
		||||
            int index = -kappa;
 | 
			
		||||
            GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void Grisu2(double value, char* buffer, int* length, int* K) {
 | 
			
		||||
    const DiyFp v(value);
 | 
			
		||||
    DiyFp w_m, w_p;
 | 
			
		||||
    v.NormalizedBoundaries(&w_m, &w_p);
 | 
			
		||||
 | 
			
		||||
    const DiyFp c_mk = GetCachedPower(w_p.e, K);
 | 
			
		||||
    const DiyFp W = v.Normalize() * c_mk;
 | 
			
		||||
    DiyFp Wp = w_p * c_mk;
 | 
			
		||||
    DiyFp Wm = w_m * c_mk;
 | 
			
		||||
    Wm.f++;
 | 
			
		||||
    Wp.f--;
 | 
			
		||||
    DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* WriteExponent(int K, char* buffer) {
 | 
			
		||||
    if (K < 0) {
 | 
			
		||||
        *buffer++ = '-';
 | 
			
		||||
        K = -K;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (K >= 100) {
 | 
			
		||||
        *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
 | 
			
		||||
        K %= 100;
 | 
			
		||||
        const char* d = GetDigitsLut() + K * 2;
 | 
			
		||||
        *buffer++ = d[0];
 | 
			
		||||
        *buffer++ = d[1];
 | 
			
		||||
    }
 | 
			
		||||
    else if (K >= 10) {
 | 
			
		||||
        const char* d = GetDigitsLut() + K * 2;
 | 
			
		||||
        *buffer++ = d[0];
 | 
			
		||||
        *buffer++ = d[1];
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        *buffer++ = static_cast<char>('0' + static_cast<char>(K));
 | 
			
		||||
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
 | 
			
		||||
    const int kk = length + k;  // 10^(kk-1) <= v < 10^kk
 | 
			
		||||
 | 
			
		||||
    if (0 <= k && kk <= 21) {
 | 
			
		||||
        // 1234e7 -> 12340000000
 | 
			
		||||
        for (int i = length; i < kk; i++)
 | 
			
		||||
            buffer[i] = '0';
 | 
			
		||||
        buffer[kk] = '.';
 | 
			
		||||
        buffer[kk + 1] = '0';
 | 
			
		||||
        return &buffer[kk + 2];
 | 
			
		||||
    }
 | 
			
		||||
    else if (0 < kk && kk <= 21) {
 | 
			
		||||
        // 1234e-2 -> 12.34
 | 
			
		||||
        std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
 | 
			
		||||
        buffer[kk] = '.';
 | 
			
		||||
        if (0 > k + maxDecimalPlaces) {
 | 
			
		||||
            // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
 | 
			
		||||
            // Remove extra trailing zeros (at least one) after truncation.
 | 
			
		||||
            for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
 | 
			
		||||
                if (buffer[i] != '0')
 | 
			
		||||
                    return &buffer[i + 1];
 | 
			
		||||
            return &buffer[kk + 2]; // Reserve one zero
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            return &buffer[length + 1];
 | 
			
		||||
    }
 | 
			
		||||
    else if (-6 < kk && kk <= 0) {
 | 
			
		||||
        // 1234e-6 -> 0.001234
 | 
			
		||||
        const int offset = 2 - kk;
 | 
			
		||||
        std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
 | 
			
		||||
        buffer[0] = '0';
 | 
			
		||||
        buffer[1] = '.';
 | 
			
		||||
        for (int i = 2; i < offset; i++)
 | 
			
		||||
            buffer[i] = '0';
 | 
			
		||||
        if (length - kk > maxDecimalPlaces) {
 | 
			
		||||
            // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
 | 
			
		||||
            // Remove extra trailing zeros (at least one) after truncation.
 | 
			
		||||
            for (int i = maxDecimalPlaces + 1; i > 2; i--)
 | 
			
		||||
                if (buffer[i] != '0')
 | 
			
		||||
                    return &buffer[i + 1];
 | 
			
		||||
            return &buffer[3]; // Reserve one zero
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            return &buffer[length + offset];
 | 
			
		||||
    }
 | 
			
		||||
    else if (kk < -maxDecimalPlaces) {
 | 
			
		||||
        // Truncate to zero
 | 
			
		||||
        buffer[0] = '0';
 | 
			
		||||
        buffer[1] = '.';
 | 
			
		||||
        buffer[2] = '0';
 | 
			
		||||
        return &buffer[3];
 | 
			
		||||
    }
 | 
			
		||||
    else if (length == 1) {
 | 
			
		||||
        // 1e30
 | 
			
		||||
        buffer[1] = 'e';
 | 
			
		||||
        return WriteExponent(kk - 1, &buffer[2]);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // 1234e30 -> 1.234e33
 | 
			
		||||
        std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
 | 
			
		||||
        buffer[1] = '.';
 | 
			
		||||
        buffer[length + 1] = 'e';
 | 
			
		||||
        return WriteExponent(kk - 1, &buffer[0 + length + 2]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
 | 
			
		||||
    RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
 | 
			
		||||
    Double d(value);
 | 
			
		||||
    if (d.IsZero()) {
 | 
			
		||||
        if (d.Sign())
 | 
			
		||||
            *buffer++ = '-';     // -0.0, Issue #289
 | 
			
		||||
        buffer[0] = '0';
 | 
			
		||||
        buffer[1] = '.';
 | 
			
		||||
        buffer[2] = '0';
 | 
			
		||||
        return &buffer[3];
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (value < 0) {
 | 
			
		||||
            *buffer++ = '-';
 | 
			
		||||
            value = -value;
 | 
			
		||||
        }
 | 
			
		||||
        int length, K;
 | 
			
		||||
        Grisu2(value, buffer, &length, &K);
 | 
			
		||||
        return Prettify(buffer, length, K, maxDecimalPlaces);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_DTOA_
 | 
			
		||||
							
								
								
									
										78
									
								
								library/include/rapidjson/internal/ieee754.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								library/include/rapidjson/internal/ieee754.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_IEEE754_
 | 
			
		||||
#define RAPIDJSON_IEEE754_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
class Double {
 | 
			
		||||
public:
 | 
			
		||||
    Double() {}
 | 
			
		||||
    Double(double d) : d_(d) {}
 | 
			
		||||
    Double(uint64_t u) : u_(u) {}
 | 
			
		||||
 | 
			
		||||
    double Value() const { return d_; }
 | 
			
		||||
    uint64_t Uint64Value() const { return u_; }
 | 
			
		||||
 | 
			
		||||
    double NextPositiveDouble() const {
 | 
			
		||||
        RAPIDJSON_ASSERT(!Sign());
 | 
			
		||||
        return Double(u_ + 1).Value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Sign() const { return (u_ & kSignMask) != 0; }
 | 
			
		||||
    uint64_t Significand() const { return u_ & kSignificandMask; }
 | 
			
		||||
    int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
 | 
			
		||||
 | 
			
		||||
    bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
 | 
			
		||||
    bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
 | 
			
		||||
    bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
 | 
			
		||||
    bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
 | 
			
		||||
    bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
 | 
			
		||||
 | 
			
		||||
    uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
 | 
			
		||||
    int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
 | 
			
		||||
    uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
 | 
			
		||||
 | 
			
		||||
    static int EffectiveSignificandSize(int order) {
 | 
			
		||||
        if (order >= -1021)
 | 
			
		||||
            return 53;
 | 
			
		||||
        else if (order <= -1074)
 | 
			
		||||
            return 0;
 | 
			
		||||
        else
 | 
			
		||||
            return order + 1074;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static const int kSignificandSize = 52;
 | 
			
		||||
    static const int kExponentBias = 0x3FF;
 | 
			
		||||
    static const int kDenormalExponent = 1 - kExponentBias;
 | 
			
		||||
    static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
 | 
			
		||||
    static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
 | 
			
		||||
    static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
 | 
			
		||||
    static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
        double d_;
 | 
			
		||||
        uint64_t u_;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_IEEE754_
 | 
			
		||||
							
								
								
									
										308
									
								
								library/include/rapidjson/internal/itoa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								library/include/rapidjson/internal/itoa.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,308 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ITOA_
 | 
			
		||||
#define RAPIDJSON_ITOA_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
inline const char* GetDigitsLut() {
 | 
			
		||||
    static const char cDigitsLut[200] = {
 | 
			
		||||
        '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
 | 
			
		||||
        '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
 | 
			
		||||
        '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
 | 
			
		||||
        '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
 | 
			
		||||
        '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
 | 
			
		||||
        '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
 | 
			
		||||
        '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
 | 
			
		||||
        '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
 | 
			
		||||
        '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
 | 
			
		||||
        '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
 | 
			
		||||
    };
 | 
			
		||||
    return cDigitsLut;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* u32toa(uint32_t value, char* buffer) {
 | 
			
		||||
    RAPIDJSON_ASSERT(buffer != 0);
 | 
			
		||||
 | 
			
		||||
    const char* cDigitsLut = GetDigitsLut();
 | 
			
		||||
 | 
			
		||||
    if (value < 10000) {
 | 
			
		||||
        const uint32_t d1 = (value / 100) << 1;
 | 
			
		||||
        const uint32_t d2 = (value % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        if (value >= 1000)
 | 
			
		||||
            *buffer++ = cDigitsLut[d1];
 | 
			
		||||
        if (value >= 100)
 | 
			
		||||
            *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
        if (value >= 10)
 | 
			
		||||
            *buffer++ = cDigitsLut[d2];
 | 
			
		||||
        *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
    }
 | 
			
		||||
    else if (value < 100000000) {
 | 
			
		||||
        // value = bbbbcccc
 | 
			
		||||
        const uint32_t b = value / 10000;
 | 
			
		||||
        const uint32_t c = value % 10000;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d1 = (b / 100) << 1;
 | 
			
		||||
        const uint32_t d2 = (b % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d3 = (c / 100) << 1;
 | 
			
		||||
        const uint32_t d4 = (c % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        if (value >= 10000000)
 | 
			
		||||
            *buffer++ = cDigitsLut[d1];
 | 
			
		||||
        if (value >= 1000000)
 | 
			
		||||
            *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
        if (value >= 100000)
 | 
			
		||||
            *buffer++ = cDigitsLut[d2];
 | 
			
		||||
        *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
 | 
			
		||||
        *buffer++ = cDigitsLut[d3];
 | 
			
		||||
        *buffer++ = cDigitsLut[d3 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d4];
 | 
			
		||||
        *buffer++ = cDigitsLut[d4 + 1];
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // value = aabbbbcccc in decimal
 | 
			
		||||
 | 
			
		||||
        const uint32_t a = value / 100000000; // 1 to 42
 | 
			
		||||
        value %= 100000000;
 | 
			
		||||
 | 
			
		||||
        if (a >= 10) {
 | 
			
		||||
            const unsigned i = a << 1;
 | 
			
		||||
            *buffer++ = cDigitsLut[i];
 | 
			
		||||
            *buffer++ = cDigitsLut[i + 1];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            *buffer++ = static_cast<char>('0' + static_cast<char>(a));
 | 
			
		||||
 | 
			
		||||
        const uint32_t b = value / 10000; // 0 to 9999
 | 
			
		||||
        const uint32_t c = value % 10000; // 0 to 9999
 | 
			
		||||
 | 
			
		||||
        const uint32_t d1 = (b / 100) << 1;
 | 
			
		||||
        const uint32_t d2 = (b % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d3 = (c / 100) << 1;
 | 
			
		||||
        const uint32_t d4 = (c % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        *buffer++ = cDigitsLut[d1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d2];
 | 
			
		||||
        *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d3];
 | 
			
		||||
        *buffer++ = cDigitsLut[d3 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d4];
 | 
			
		||||
        *buffer++ = cDigitsLut[d4 + 1];
 | 
			
		||||
    }
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* i32toa(int32_t value, char* buffer) {
 | 
			
		||||
    RAPIDJSON_ASSERT(buffer != 0);
 | 
			
		||||
    uint32_t u = static_cast<uint32_t>(value);
 | 
			
		||||
    if (value < 0) {
 | 
			
		||||
        *buffer++ = '-';
 | 
			
		||||
        u = ~u + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return u32toa(u, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* u64toa(uint64_t value, char* buffer) {
 | 
			
		||||
    RAPIDJSON_ASSERT(buffer != 0);
 | 
			
		||||
    const char* cDigitsLut = GetDigitsLut();
 | 
			
		||||
    const uint64_t  kTen8 = 100000000;
 | 
			
		||||
    const uint64_t  kTen9 = kTen8 * 10;
 | 
			
		||||
    const uint64_t kTen10 = kTen8 * 100;
 | 
			
		||||
    const uint64_t kTen11 = kTen8 * 1000;
 | 
			
		||||
    const uint64_t kTen12 = kTen8 * 10000;
 | 
			
		||||
    const uint64_t kTen13 = kTen8 * 100000;
 | 
			
		||||
    const uint64_t kTen14 = kTen8 * 1000000;
 | 
			
		||||
    const uint64_t kTen15 = kTen8 * 10000000;
 | 
			
		||||
    const uint64_t kTen16 = kTen8 * kTen8;
 | 
			
		||||
 | 
			
		||||
    if (value < kTen8) {
 | 
			
		||||
        uint32_t v = static_cast<uint32_t>(value);
 | 
			
		||||
        if (v < 10000) {
 | 
			
		||||
            const uint32_t d1 = (v / 100) << 1;
 | 
			
		||||
            const uint32_t d2 = (v % 100) << 1;
 | 
			
		||||
 | 
			
		||||
            if (v >= 1000)
 | 
			
		||||
                *buffer++ = cDigitsLut[d1];
 | 
			
		||||
            if (v >= 100)
 | 
			
		||||
                *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
            if (v >= 10)
 | 
			
		||||
                *buffer++ = cDigitsLut[d2];
 | 
			
		||||
            *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            // value = bbbbcccc
 | 
			
		||||
            const uint32_t b = v / 10000;
 | 
			
		||||
            const uint32_t c = v % 10000;
 | 
			
		||||
 | 
			
		||||
            const uint32_t d1 = (b / 100) << 1;
 | 
			
		||||
            const uint32_t d2 = (b % 100) << 1;
 | 
			
		||||
 | 
			
		||||
            const uint32_t d3 = (c / 100) << 1;
 | 
			
		||||
            const uint32_t d4 = (c % 100) << 1;
 | 
			
		||||
 | 
			
		||||
            if (value >= 10000000)
 | 
			
		||||
                *buffer++ = cDigitsLut[d1];
 | 
			
		||||
            if (value >= 1000000)
 | 
			
		||||
                *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
            if (value >= 100000)
 | 
			
		||||
                *buffer++ = cDigitsLut[d2];
 | 
			
		||||
            *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
 | 
			
		||||
            *buffer++ = cDigitsLut[d3];
 | 
			
		||||
            *buffer++ = cDigitsLut[d3 + 1];
 | 
			
		||||
            *buffer++ = cDigitsLut[d4];
 | 
			
		||||
            *buffer++ = cDigitsLut[d4 + 1];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (value < kTen16) {
 | 
			
		||||
        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
 | 
			
		||||
        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
 | 
			
		||||
 | 
			
		||||
        const uint32_t b0 = v0 / 10000;
 | 
			
		||||
        const uint32_t c0 = v0 % 10000;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d1 = (b0 / 100) << 1;
 | 
			
		||||
        const uint32_t d2 = (b0 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d3 = (c0 / 100) << 1;
 | 
			
		||||
        const uint32_t d4 = (c0 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t b1 = v1 / 10000;
 | 
			
		||||
        const uint32_t c1 = v1 % 10000;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d5 = (b1 / 100) << 1;
 | 
			
		||||
        const uint32_t d6 = (b1 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d7 = (c1 / 100) << 1;
 | 
			
		||||
        const uint32_t d8 = (c1 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        if (value >= kTen15)
 | 
			
		||||
            *buffer++ = cDigitsLut[d1];
 | 
			
		||||
        if (value >= kTen14)
 | 
			
		||||
            *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
        if (value >= kTen13)
 | 
			
		||||
            *buffer++ = cDigitsLut[d2];
 | 
			
		||||
        if (value >= kTen12)
 | 
			
		||||
            *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
        if (value >= kTen11)
 | 
			
		||||
            *buffer++ = cDigitsLut[d3];
 | 
			
		||||
        if (value >= kTen10)
 | 
			
		||||
            *buffer++ = cDigitsLut[d3 + 1];
 | 
			
		||||
        if (value >= kTen9)
 | 
			
		||||
            *buffer++ = cDigitsLut[d4];
 | 
			
		||||
 | 
			
		||||
        *buffer++ = cDigitsLut[d4 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d5];
 | 
			
		||||
        *buffer++ = cDigitsLut[d5 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d6];
 | 
			
		||||
        *buffer++ = cDigitsLut[d6 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d7];
 | 
			
		||||
        *buffer++ = cDigitsLut[d7 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d8];
 | 
			
		||||
        *buffer++ = cDigitsLut[d8 + 1];
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
 | 
			
		||||
        value %= kTen16;
 | 
			
		||||
 | 
			
		||||
        if (a < 10)
 | 
			
		||||
            *buffer++ = static_cast<char>('0' + static_cast<char>(a));
 | 
			
		||||
        else if (a < 100) {
 | 
			
		||||
            const uint32_t i = a << 1;
 | 
			
		||||
            *buffer++ = cDigitsLut[i];
 | 
			
		||||
            *buffer++ = cDigitsLut[i + 1];
 | 
			
		||||
        }
 | 
			
		||||
        else if (a < 1000) {
 | 
			
		||||
            *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
 | 
			
		||||
 | 
			
		||||
            const uint32_t i = (a % 100) << 1;
 | 
			
		||||
            *buffer++ = cDigitsLut[i];
 | 
			
		||||
            *buffer++ = cDigitsLut[i + 1];
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            const uint32_t i = (a / 100) << 1;
 | 
			
		||||
            const uint32_t j = (a % 100) << 1;
 | 
			
		||||
            *buffer++ = cDigitsLut[i];
 | 
			
		||||
            *buffer++ = cDigitsLut[i + 1];
 | 
			
		||||
            *buffer++ = cDigitsLut[j];
 | 
			
		||||
            *buffer++ = cDigitsLut[j + 1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
 | 
			
		||||
        const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
 | 
			
		||||
 | 
			
		||||
        const uint32_t b0 = v0 / 10000;
 | 
			
		||||
        const uint32_t c0 = v0 % 10000;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d1 = (b0 / 100) << 1;
 | 
			
		||||
        const uint32_t d2 = (b0 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d3 = (c0 / 100) << 1;
 | 
			
		||||
        const uint32_t d4 = (c0 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t b1 = v1 / 10000;
 | 
			
		||||
        const uint32_t c1 = v1 % 10000;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d5 = (b1 / 100) << 1;
 | 
			
		||||
        const uint32_t d6 = (b1 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        const uint32_t d7 = (c1 / 100) << 1;
 | 
			
		||||
        const uint32_t d8 = (c1 % 100) << 1;
 | 
			
		||||
 | 
			
		||||
        *buffer++ = cDigitsLut[d1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d1 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d2];
 | 
			
		||||
        *buffer++ = cDigitsLut[d2 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d3];
 | 
			
		||||
        *buffer++ = cDigitsLut[d3 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d4];
 | 
			
		||||
        *buffer++ = cDigitsLut[d4 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d5];
 | 
			
		||||
        *buffer++ = cDigitsLut[d5 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d6];
 | 
			
		||||
        *buffer++ = cDigitsLut[d6 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d7];
 | 
			
		||||
        *buffer++ = cDigitsLut[d7 + 1];
 | 
			
		||||
        *buffer++ = cDigitsLut[d8];
 | 
			
		||||
        *buffer++ = cDigitsLut[d8 + 1];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline char* i64toa(int64_t value, char* buffer) {
 | 
			
		||||
    RAPIDJSON_ASSERT(buffer != 0);
 | 
			
		||||
    uint64_t u = static_cast<uint64_t>(value);
 | 
			
		||||
    if (value < 0) {
 | 
			
		||||
        *buffer++ = '-';
 | 
			
		||||
        u = ~u + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return u64toa(u, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_ITOA_
 | 
			
		||||
							
								
								
									
										186
									
								
								library/include/rapidjson/internal/meta.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								library/include/rapidjson/internal/meta.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,186 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_INTERNAL_META_H_
 | 
			
		||||
#define RAPIDJSON_INTERNAL_META_H_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(6334)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//@cond RAPIDJSON_INTERNAL
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
 | 
			
		||||
template <typename T> struct Void { typedef void Type; };
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// BoolType, TrueType, FalseType
 | 
			
		||||
//
 | 
			
		||||
template <bool Cond> struct BoolType {
 | 
			
		||||
    static const bool Value = Cond;
 | 
			
		||||
    typedef BoolType Type;
 | 
			
		||||
};
 | 
			
		||||
typedef BoolType<true> TrueType;
 | 
			
		||||
typedef BoolType<false> FalseType;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
 | 
			
		||||
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
 | 
			
		||||
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
 | 
			
		||||
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
 | 
			
		||||
 | 
			
		||||
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
 | 
			
		||||
template <> struct AndExprCond<true, true> : TrueType {};
 | 
			
		||||
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
 | 
			
		||||
template <> struct OrExprCond<false, false> : FalseType {};
 | 
			
		||||
 | 
			
		||||
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
 | 
			
		||||
template <typename C> struct NotExpr  : SelectIf<C,FalseType,TrueType>::Type {};
 | 
			
		||||
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
 | 
			
		||||
template <typename C1, typename C2> struct OrExpr  : OrExprCond<C1::Value, C2::Value>::Type {};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// AddConst, MaybeAddConst, RemoveConst
 | 
			
		||||
template <typename T> struct AddConst { typedef const T Type; };
 | 
			
		||||
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
 | 
			
		||||
template <typename T> struct RemoveConst { typedef T Type; };
 | 
			
		||||
template <typename T> struct RemoveConst<const T> { typedef T Type; };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// IsSame, IsConst, IsMoreConst, IsPointer
 | 
			
		||||
//
 | 
			
		||||
template <typename T, typename U> struct IsSame : FalseType {};
 | 
			
		||||
template <typename T> struct IsSame<T, T> : TrueType {};
 | 
			
		||||
 | 
			
		||||
template <typename T> struct IsConst : FalseType {};
 | 
			
		||||
template <typename T> struct IsConst<const T> : TrueType {};
 | 
			
		||||
 | 
			
		||||
template <typename CT, typename T>
 | 
			
		||||
struct IsMoreConst
 | 
			
		||||
    : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
 | 
			
		||||
              BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
 | 
			
		||||
 | 
			
		||||
template <typename T> struct IsPointer : FalseType {};
 | 
			
		||||
template <typename T> struct IsPointer<T*> : TrueType {};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// IsBaseOf
 | 
			
		||||
//
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
 | 
			
		||||
 | 
			
		||||
template <typename B, typename D> struct IsBaseOf
 | 
			
		||||
    : BoolType< ::std::is_base_of<B,D>::value> {};
 | 
			
		||||
 | 
			
		||||
#else // simplified version adopted from Boost
 | 
			
		||||
 | 
			
		||||
template<typename B, typename D> struct IsBaseOfImpl {
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
 | 
			
		||||
    RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
 | 
			
		||||
 | 
			
		||||
    typedef char (&Yes)[1];
 | 
			
		||||
    typedef char (&No) [2];
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    static Yes Check(const D*, T);
 | 
			
		||||
    static No  Check(const B*, int);
 | 
			
		||||
 | 
			
		||||
    struct Host {
 | 
			
		||||
        operator const B*() const;
 | 
			
		||||
        operator const D*();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename B, typename D> struct IsBaseOf
 | 
			
		||||
    : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// EnableIf / DisableIf
 | 
			
		||||
//
 | 
			
		||||
template <bool Condition, typename T = void> struct EnableIfCond  { typedef T Type; };
 | 
			
		||||
template <typename T> struct EnableIfCond<false, T> { /* empty */ };
 | 
			
		||||
 | 
			
		||||
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
 | 
			
		||||
template <typename T> struct DisableIfCond<true, T> { /* empty */ };
 | 
			
		||||
 | 
			
		||||
template <typename Condition, typename T = void>
 | 
			
		||||
struct EnableIf : EnableIfCond<Condition::Value, T> {};
 | 
			
		||||
 | 
			
		||||
template <typename Condition, typename T = void>
 | 
			
		||||
struct DisableIf : DisableIfCond<Condition::Value, T> {};
 | 
			
		||||
 | 
			
		||||
// SFINAE helpers
 | 
			
		||||
struct SfinaeTag {};
 | 
			
		||||
template <typename T> struct RemoveSfinaeTag;
 | 
			
		||||
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_REMOVEFPTR_(type) \
 | 
			
		||||
    typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
 | 
			
		||||
        < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_ENABLEIF(cond) \
 | 
			
		||||
    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
 | 
			
		||||
        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_DISABLEIF(cond) \
 | 
			
		||||
    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
 | 
			
		||||
        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
 | 
			
		||||
    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
 | 
			
		||||
        <RAPIDJSON_REMOVEFPTR_(cond), \
 | 
			
		||||
         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
 | 
			
		||||
    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
 | 
			
		||||
        <RAPIDJSON_REMOVEFPTR_(cond), \
 | 
			
		||||
         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
//@endcond
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && !defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_INTERNAL_META_H_
 | 
			
		||||
							
								
								
									
										55
									
								
								library/include/rapidjson/internal/pow10.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								library/include/rapidjson/internal/pow10.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_POW10_
 | 
			
		||||
#define RAPIDJSON_POW10_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
//! Computes integer powers of 10 in double (10.0^n).
 | 
			
		||||
/*! This function uses lookup table for fast and accurate results.
 | 
			
		||||
    \param n non-negative exponent. Must <= 308.
 | 
			
		||||
    \return 10.0^n
 | 
			
		||||
*/
 | 
			
		||||
inline double Pow10(int n) {
 | 
			
		||||
    static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
 | 
			
		||||
        1e+0,  
 | 
			
		||||
        1e+1,  1e+2,  1e+3,  1e+4,  1e+5,  1e+6,  1e+7,  1e+8,  1e+9,  1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 
 | 
			
		||||
        1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
 | 
			
		||||
        1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
 | 
			
		||||
        1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
 | 
			
		||||
        1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
 | 
			
		||||
        1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
 | 
			
		||||
        1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
 | 
			
		||||
        1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
 | 
			
		||||
        1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
 | 
			
		||||
        1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
 | 
			
		||||
        1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
 | 
			
		||||
        1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
 | 
			
		||||
        1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
 | 
			
		||||
        1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
 | 
			
		||||
        1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
 | 
			
		||||
        1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
 | 
			
		||||
    };
 | 
			
		||||
    RAPIDJSON_ASSERT(n >= 0 && n <= 308);
 | 
			
		||||
    return e[n];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_POW10_
 | 
			
		||||
							
								
								
									
										739
									
								
								library/include/rapidjson/internal/regex.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										739
									
								
								library/include/rapidjson/internal/regex.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,739 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_INTERNAL_REGEX_H_
 | 
			
		||||
#define RAPIDJSON_INTERNAL_REGEX_H_
 | 
			
		||||
 | 
			
		||||
#include "../allocators.h"
 | 
			
		||||
#include "../stream.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(switch-enum)
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_REGEX_VERBOSE
 | 
			
		||||
#define RAPIDJSON_REGEX_VERBOSE 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// DecodedStream
 | 
			
		||||
 | 
			
		||||
template <typename SourceStream, typename Encoding>
 | 
			
		||||
class DecodedStream {
 | 
			
		||||
public:
 | 
			
		||||
    DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
 | 
			
		||||
    unsigned Peek() { return codepoint_; }
 | 
			
		||||
    unsigned Take() {
 | 
			
		||||
        unsigned c = codepoint_;
 | 
			
		||||
        if (c) // No further decoding when '\0'
 | 
			
		||||
            Decode();
 | 
			
		||||
        return c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void Decode() {
 | 
			
		||||
        if (!Encoding::Decode(ss_, &codepoint_))
 | 
			
		||||
            codepoint_ = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SourceStream& ss_;
 | 
			
		||||
    unsigned codepoint_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// GenericRegex
 | 
			
		||||
 | 
			
		||||
static const SizeType kRegexInvalidState = ~SizeType(0);  //!< Represents an invalid index in GenericRegex::State::out, out1
 | 
			
		||||
static const SizeType kRegexInvalidRange = ~SizeType(0);
 | 
			
		||||
 | 
			
		||||
template <typename Encoding, typename Allocator>
 | 
			
		||||
class GenericRegexSearch;
 | 
			
		||||
 | 
			
		||||
//! Regular expression engine with subset of ECMAscript grammar.
 | 
			
		||||
/*!
 | 
			
		||||
    Supported regular expression syntax:
 | 
			
		||||
    - \c ab     Concatenation
 | 
			
		||||
    - \c a|b    Alternation
 | 
			
		||||
    - \c a?     Zero or one
 | 
			
		||||
    - \c a*     Zero or more
 | 
			
		||||
    - \c a+     One or more
 | 
			
		||||
    - \c a{3}   Exactly 3 times
 | 
			
		||||
    - \c a{3,}  At least 3 times
 | 
			
		||||
    - \c a{3,5} 3 to 5 times
 | 
			
		||||
    - \c (ab)   Grouping
 | 
			
		||||
    - \c ^a     At the beginning
 | 
			
		||||
    - \c a$     At the end
 | 
			
		||||
    - \c .      Any character
 | 
			
		||||
    - \c [abc]  Character classes
 | 
			
		||||
    - \c [a-c]  Character class range
 | 
			
		||||
    - \c [a-z0-9_] Character class combination
 | 
			
		||||
    - \c [^abc] Negated character classes
 | 
			
		||||
    - \c [^a-c] Negated character class range
 | 
			
		||||
    - \c [\b]   Backspace (U+0008)
 | 
			
		||||
    - \c \\| \\\\ ...  Escape characters
 | 
			
		||||
    - \c \\f Form feed (U+000C)
 | 
			
		||||
    - \c \\n Line feed (U+000A)
 | 
			
		||||
    - \c \\r Carriage return (U+000D)
 | 
			
		||||
    - \c \\t Tab (U+0009)
 | 
			
		||||
    - \c \\v Vertical tab (U+000B)
 | 
			
		||||
 | 
			
		||||
    \note This is a Thompson NFA engine, implemented with reference to 
 | 
			
		||||
        Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", 
 | 
			
		||||
        https://swtch.com/~rsc/regexp/regexp1.html 
 | 
			
		||||
*/
 | 
			
		||||
template <typename Encoding, typename Allocator = CrtAllocator>
 | 
			
		||||
class GenericRegex {
 | 
			
		||||
public:
 | 
			
		||||
    typedef Encoding EncodingType;
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
    template <typename, typename> friend class GenericRegexSearch;
 | 
			
		||||
 | 
			
		||||
    GenericRegex(const Ch* source, Allocator* allocator = 0) : 
 | 
			
		||||
        ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), 
 | 
			
		||||
        states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), 
 | 
			
		||||
        anchorBegin_(), anchorEnd_()
 | 
			
		||||
    {
 | 
			
		||||
        GenericStringStream<Encoding> ss(source);
 | 
			
		||||
        DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
 | 
			
		||||
        Parse(ds);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~GenericRegex()
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_DELETE(ownAllocator_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool IsValid() const {
 | 
			
		||||
        return root_ != kRegexInvalidState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    enum Operator {
 | 
			
		||||
        kZeroOrOne,
 | 
			
		||||
        kZeroOrMore,
 | 
			
		||||
        kOneOrMore,
 | 
			
		||||
        kConcatenation,
 | 
			
		||||
        kAlternation,
 | 
			
		||||
        kLeftParenthesis
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static const unsigned kAnyCharacterClass = 0xFFFFFFFF;   //!< For '.'
 | 
			
		||||
    static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
 | 
			
		||||
    static const unsigned kRangeNegationFlag = 0x80000000;
 | 
			
		||||
 | 
			
		||||
    struct Range {
 | 
			
		||||
        unsigned start; // 
 | 
			
		||||
        unsigned end;
 | 
			
		||||
        SizeType next;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct State {
 | 
			
		||||
        SizeType out;     //!< Equals to kInvalid for matching state
 | 
			
		||||
        SizeType out1;    //!< Equals to non-kInvalid for split
 | 
			
		||||
        SizeType rangeStart;
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct Frag {
 | 
			
		||||
        Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
 | 
			
		||||
        SizeType start;
 | 
			
		||||
        SizeType out; //!< link-list of all output states
 | 
			
		||||
        SizeType minIndex;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    State& GetState(SizeType index) {
 | 
			
		||||
        RAPIDJSON_ASSERT(index < stateCount_);
 | 
			
		||||
        return states_.template Bottom<State>()[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const State& GetState(SizeType index) const {
 | 
			
		||||
        RAPIDJSON_ASSERT(index < stateCount_);
 | 
			
		||||
        return states_.template Bottom<State>()[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Range& GetRange(SizeType index) {
 | 
			
		||||
        RAPIDJSON_ASSERT(index < rangeCount_);
 | 
			
		||||
        return ranges_.template Bottom<Range>()[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Range& GetRange(SizeType index) const {
 | 
			
		||||
        RAPIDJSON_ASSERT(index < rangeCount_);
 | 
			
		||||
        return ranges_.template Bottom<Range>()[index];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    void Parse(DecodedStream<InputStream, Encoding>& ds) {
 | 
			
		||||
        Stack<Allocator> operandStack(allocator_, 256);    // Frag
 | 
			
		||||
        Stack<Allocator> operatorStack(allocator_, 256);   // Operator
 | 
			
		||||
        Stack<Allocator> atomCountStack(allocator_, 256);  // unsigned (Atom per parenthesis)
 | 
			
		||||
 | 
			
		||||
        *atomCountStack.template Push<unsigned>() = 0;
 | 
			
		||||
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        while (ds.Peek() != 0) {
 | 
			
		||||
            switch (codepoint = ds.Take()) {
 | 
			
		||||
                case '^':
 | 
			
		||||
                    anchorBegin_ = true;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '$':
 | 
			
		||||
                    anchorEnd_ = true;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '|':
 | 
			
		||||
                    while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
 | 
			
		||||
                        if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
 | 
			
		||||
                            return;
 | 
			
		||||
                    *operatorStack.template Push<Operator>() = kAlternation;
 | 
			
		||||
                    *atomCountStack.template Top<unsigned>() = 0;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '(':
 | 
			
		||||
                    *operatorStack.template Push<Operator>() = kLeftParenthesis;
 | 
			
		||||
                    *atomCountStack.template Push<unsigned>() = 0;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case ')':
 | 
			
		||||
                    while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
 | 
			
		||||
                        if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
 | 
			
		||||
                            return;
 | 
			
		||||
                    if (operatorStack.Empty())
 | 
			
		||||
                        return;
 | 
			
		||||
                    operatorStack.template Pop<Operator>(1);
 | 
			
		||||
                    atomCountStack.template Pop<unsigned>(1);
 | 
			
		||||
                    ImplicitConcatenation(atomCountStack, operatorStack);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '?':
 | 
			
		||||
                    if (!Eval(operandStack, kZeroOrOne))
 | 
			
		||||
                        return;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '*':
 | 
			
		||||
                    if (!Eval(operandStack, kZeroOrMore))
 | 
			
		||||
                        return;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '+':
 | 
			
		||||
                    if (!Eval(operandStack, kOneOrMore))
 | 
			
		||||
                        return;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '{':
 | 
			
		||||
                    {
 | 
			
		||||
                        unsigned n, m;
 | 
			
		||||
                        if (!ParseUnsigned(ds, &n))
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                        if (ds.Peek() == ',') {
 | 
			
		||||
                            ds.Take();
 | 
			
		||||
                            if (ds.Peek() == '}')
 | 
			
		||||
                                m = kInfinityQuantifier;
 | 
			
		||||
                            else if (!ParseUnsigned(ds, &m) || m < n)
 | 
			
		||||
                                return;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                            m = n;
 | 
			
		||||
 | 
			
		||||
                        if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
 | 
			
		||||
                            return;
 | 
			
		||||
                        ds.Take();
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '.':
 | 
			
		||||
                    PushOperand(operandStack, kAnyCharacterClass);
 | 
			
		||||
                    ImplicitConcatenation(atomCountStack, operatorStack);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '[':
 | 
			
		||||
                    {
 | 
			
		||||
                        SizeType range;
 | 
			
		||||
                        if (!ParseRange(ds, &range))
 | 
			
		||||
                            return;
 | 
			
		||||
                        SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
 | 
			
		||||
                        GetState(s).rangeStart = range;
 | 
			
		||||
                        *operandStack.template Push<Frag>() = Frag(s, s, s);
 | 
			
		||||
                    }
 | 
			
		||||
                    ImplicitConcatenation(atomCountStack, operatorStack);
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                case '\\': // Escape character
 | 
			
		||||
                    if (!CharacterEscape(ds, &codepoint))
 | 
			
		||||
                        return; // Unsupported escape character
 | 
			
		||||
                    // fall through to default
 | 
			
		||||
                    RAPIDJSON_DELIBERATE_FALLTHROUGH;
 | 
			
		||||
 | 
			
		||||
                default: // Pattern character
 | 
			
		||||
                    PushOperand(operandStack, codepoint);
 | 
			
		||||
                    ImplicitConcatenation(atomCountStack, operatorStack);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        while (!operatorStack.Empty())
 | 
			
		||||
            if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
        // Link the operand to matching state.
 | 
			
		||||
        if (operandStack.GetSize() == sizeof(Frag)) {
 | 
			
		||||
            Frag* e = operandStack.template Pop<Frag>(1);
 | 
			
		||||
            Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
 | 
			
		||||
            root_ = e->start;
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_REGEX_VERBOSE
 | 
			
		||||
            printf("root: %d\n", root_);
 | 
			
		||||
            for (SizeType i = 0; i < stateCount_ ; i++) {
 | 
			
		||||
                State& s = GetState(i);
 | 
			
		||||
                printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
 | 
			
		||||
            }
 | 
			
		||||
            printf("\n");
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
 | 
			
		||||
        State* s = states_.template Push<State>();
 | 
			
		||||
        s->out = out;
 | 
			
		||||
        s->out1 = out1;
 | 
			
		||||
        s->codepoint = codepoint;
 | 
			
		||||
        s->rangeStart = kRegexInvalidRange;
 | 
			
		||||
        return stateCount_++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
 | 
			
		||||
        SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
 | 
			
		||||
        *operandStack.template Push<Frag>() = Frag(s, s, s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
 | 
			
		||||
        if (*atomCountStack.template Top<unsigned>())
 | 
			
		||||
            *operatorStack.template Push<Operator>() = kConcatenation;
 | 
			
		||||
        (*atomCountStack.template Top<unsigned>())++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SizeType Append(SizeType l1, SizeType l2) {
 | 
			
		||||
        SizeType old = l1;
 | 
			
		||||
        while (GetState(l1).out != kRegexInvalidState)
 | 
			
		||||
            l1 = GetState(l1).out;
 | 
			
		||||
        GetState(l1).out = l2;
 | 
			
		||||
        return old;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Patch(SizeType l, SizeType s) {
 | 
			
		||||
        for (SizeType next; l != kRegexInvalidState; l = next) {
 | 
			
		||||
            next = GetState(l).out;
 | 
			
		||||
            GetState(l).out = s;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Eval(Stack<Allocator>& operandStack, Operator op) {
 | 
			
		||||
        switch (op) {
 | 
			
		||||
            case kConcatenation:
 | 
			
		||||
                RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
 | 
			
		||||
                {
 | 
			
		||||
                    Frag e2 = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    Frag e1 = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    Patch(e1.out, e2.start);
 | 
			
		||||
                    *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            case kAlternation:
 | 
			
		||||
                if (operandStack.GetSize() >= sizeof(Frag) * 2) {
 | 
			
		||||
                    Frag e2 = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    Frag e1 = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    SizeType s = NewState(e1.start, e2.start, 0);
 | 
			
		||||
                    *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            case kZeroOrOne:
 | 
			
		||||
                if (operandStack.GetSize() >= sizeof(Frag)) {
 | 
			
		||||
                    Frag e = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    SizeType s = NewState(kRegexInvalidState, e.start, 0);
 | 
			
		||||
                    *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            case kZeroOrMore:
 | 
			
		||||
                if (operandStack.GetSize() >= sizeof(Frag)) {
 | 
			
		||||
                    Frag e = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    SizeType s = NewState(kRegexInvalidState, e.start, 0);
 | 
			
		||||
                    Patch(e.out, s);
 | 
			
		||||
                    *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            case kOneOrMore:
 | 
			
		||||
                if (operandStack.GetSize() >= sizeof(Frag)) {
 | 
			
		||||
                    Frag e = *operandStack.template Pop<Frag>(1);
 | 
			
		||||
                    SizeType s = NewState(kRegexInvalidState, e.start, 0);
 | 
			
		||||
                    Patch(e.out, s);
 | 
			
		||||
                    *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            default: 
 | 
			
		||||
                // syntax error (e.g. unclosed kLeftParenthesis)
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
 | 
			
		||||
        RAPIDJSON_ASSERT(n <= m);
 | 
			
		||||
        RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
 | 
			
		||||
 | 
			
		||||
        if (n == 0) {
 | 
			
		||||
            if (m == 0)                             // a{0} not support
 | 
			
		||||
                return false;
 | 
			
		||||
            else if (m == kInfinityQuantifier)
 | 
			
		||||
                Eval(operandStack, kZeroOrMore);    // a{0,} -> a*
 | 
			
		||||
            else {
 | 
			
		||||
                Eval(operandStack, kZeroOrOne);         // a{0,5} -> a?
 | 
			
		||||
                for (unsigned i = 0; i < m - 1; i++)
 | 
			
		||||
                    CloneTopOperand(operandStack);      // a{0,5} -> a? a? a? a? a?
 | 
			
		||||
                for (unsigned i = 0; i < m - 1; i++)
 | 
			
		||||
                    Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < n - 1; i++)        // a{3} -> a a a
 | 
			
		||||
            CloneTopOperand(operandStack);
 | 
			
		||||
 | 
			
		||||
        if (m == kInfinityQuantifier)
 | 
			
		||||
            Eval(operandStack, kOneOrMore);         // a{3,} -> a a a+
 | 
			
		||||
        else if (m > n) {
 | 
			
		||||
            CloneTopOperand(operandStack);          // a{3,5} -> a a a a
 | 
			
		||||
            Eval(operandStack, kZeroOrOne);         // a{3,5} -> a a a a?
 | 
			
		||||
            for (unsigned i = n; i < m - 1; i++)
 | 
			
		||||
                CloneTopOperand(operandStack);      // a{3,5} -> a a a a? a?
 | 
			
		||||
            for (unsigned i = n; i < m; i++)
 | 
			
		||||
                Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < n - 1; i++)
 | 
			
		||||
            Eval(operandStack, kConcatenation);     // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
 | 
			
		||||
 | 
			
		||||
    void CloneTopOperand(Stack<Allocator>& operandStack) {
 | 
			
		||||
        const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
 | 
			
		||||
        SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
 | 
			
		||||
        State* s = states_.template Push<State>(count);
 | 
			
		||||
        memcpy(s, &GetState(src.minIndex), count * sizeof(State));
 | 
			
		||||
        for (SizeType j = 0; j < count; j++) {
 | 
			
		||||
            if (s[j].out != kRegexInvalidState)
 | 
			
		||||
                s[j].out += count;
 | 
			
		||||
            if (s[j].out1 != kRegexInvalidState)
 | 
			
		||||
                s[j].out1 += count;
 | 
			
		||||
        }
 | 
			
		||||
        *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
 | 
			
		||||
        stateCount_ += count;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
 | 
			
		||||
        unsigned r = 0;
 | 
			
		||||
        if (ds.Peek() < '0' || ds.Peek() > '9')
 | 
			
		||||
            return false;
 | 
			
		||||
        while (ds.Peek() >= '0' && ds.Peek() <= '9') {
 | 
			
		||||
            if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
 | 
			
		||||
                return false; // overflow
 | 
			
		||||
            r = r * 10 + (ds.Take() - '0');
 | 
			
		||||
        }
 | 
			
		||||
        *u = r;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
 | 
			
		||||
        bool isBegin = true;
 | 
			
		||||
        bool negate = false;
 | 
			
		||||
        int step = 0;
 | 
			
		||||
        SizeType start = kRegexInvalidRange;
 | 
			
		||||
        SizeType current = kRegexInvalidRange;
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        while ((codepoint = ds.Take()) != 0) {
 | 
			
		||||
            if (isBegin) {
 | 
			
		||||
                isBegin = false;
 | 
			
		||||
                if (codepoint == '^') {
 | 
			
		||||
                    negate = true;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (codepoint) {
 | 
			
		||||
            case ']':
 | 
			
		||||
                if (start == kRegexInvalidRange)
 | 
			
		||||
                    return false;   // Error: nothing inside []
 | 
			
		||||
                if (step == 2) { // Add trailing '-'
 | 
			
		||||
                    SizeType r = NewRange('-');
 | 
			
		||||
                    RAPIDJSON_ASSERT(current != kRegexInvalidRange);
 | 
			
		||||
                    GetRange(current).next = r;
 | 
			
		||||
                }
 | 
			
		||||
                if (negate)
 | 
			
		||||
                    GetRange(start).start |= kRangeNegationFlag;
 | 
			
		||||
                *range = start;
 | 
			
		||||
                return true;
 | 
			
		||||
 | 
			
		||||
            case '\\':
 | 
			
		||||
                if (ds.Peek() == 'b') {
 | 
			
		||||
                    ds.Take();
 | 
			
		||||
                    codepoint = 0x0008; // Escape backspace character
 | 
			
		||||
                }
 | 
			
		||||
                else if (!CharacterEscape(ds, &codepoint))
 | 
			
		||||
                    return false;
 | 
			
		||||
                // fall through to default
 | 
			
		||||
                RAPIDJSON_DELIBERATE_FALLTHROUGH;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                switch (step) {
 | 
			
		||||
                case 1:
 | 
			
		||||
                    if (codepoint == '-') {
 | 
			
		||||
                        step++;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    // fall through to step 0 for other characters
 | 
			
		||||
                    RAPIDJSON_DELIBERATE_FALLTHROUGH;
 | 
			
		||||
 | 
			
		||||
                case 0:
 | 
			
		||||
                    {
 | 
			
		||||
                        SizeType r = NewRange(codepoint);
 | 
			
		||||
                        if (current != kRegexInvalidRange)
 | 
			
		||||
                            GetRange(current).next = r;
 | 
			
		||||
                        if (start == kRegexInvalidRange)
 | 
			
		||||
                            start = r;
 | 
			
		||||
                        current = r;
 | 
			
		||||
                    }
 | 
			
		||||
                    step = 1;
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                default:
 | 
			
		||||
                    RAPIDJSON_ASSERT(step == 2);
 | 
			
		||||
                    GetRange(current).end = codepoint;
 | 
			
		||||
                    step = 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    SizeType NewRange(unsigned codepoint) {
 | 
			
		||||
        Range* r = ranges_.template Push<Range>();
 | 
			
		||||
        r->start = r->end = codepoint;
 | 
			
		||||
        r->next = kRegexInvalidRange;
 | 
			
		||||
        return rangeCount_++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        switch (codepoint = ds.Take()) {
 | 
			
		||||
            case '^':
 | 
			
		||||
            case '$':
 | 
			
		||||
            case '|':
 | 
			
		||||
            case '(':
 | 
			
		||||
            case ')':
 | 
			
		||||
            case '?':
 | 
			
		||||
            case '*':
 | 
			
		||||
            case '+':
 | 
			
		||||
            case '.':
 | 
			
		||||
            case '[':
 | 
			
		||||
            case ']':
 | 
			
		||||
            case '{':
 | 
			
		||||
            case '}':
 | 
			
		||||
            case '\\':
 | 
			
		||||
                *escapedCodepoint = codepoint; return true;
 | 
			
		||||
            case 'f': *escapedCodepoint = 0x000C; return true;
 | 
			
		||||
            case 'n': *escapedCodepoint = 0x000A; return true;
 | 
			
		||||
            case 'r': *escapedCodepoint = 0x000D; return true;
 | 
			
		||||
            case 't': *escapedCodepoint = 0x0009; return true;
 | 
			
		||||
            case 'v': *escapedCodepoint = 0x000B; return true;
 | 
			
		||||
            default:
 | 
			
		||||
                return false; // Unsupported escape character
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Allocator* ownAllocator_;
 | 
			
		||||
    Allocator* allocator_;
 | 
			
		||||
    Stack<Allocator> states_;
 | 
			
		||||
    Stack<Allocator> ranges_;
 | 
			
		||||
    SizeType root_;
 | 
			
		||||
    SizeType stateCount_;
 | 
			
		||||
    SizeType rangeCount_;
 | 
			
		||||
 | 
			
		||||
    static const unsigned kInfinityQuantifier = ~0u;
 | 
			
		||||
 | 
			
		||||
    // For SearchWithAnchoring()
 | 
			
		||||
    bool anchorBegin_;
 | 
			
		||||
    bool anchorEnd_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename RegexType, typename Allocator = CrtAllocator>
 | 
			
		||||
class GenericRegexSearch {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename RegexType::EncodingType Encoding;
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : 
 | 
			
		||||
        regex_(regex), allocator_(allocator), ownAllocator_(0),
 | 
			
		||||
        state0_(allocator, 0), state1_(allocator, 0), stateSet_()
 | 
			
		||||
    {
 | 
			
		||||
        RAPIDJSON_ASSERT(regex_.IsValid());
 | 
			
		||||
        if (!allocator_)
 | 
			
		||||
            ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
			
		||||
        stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
 | 
			
		||||
        state0_.template Reserve<SizeType>(regex_.stateCount_);
 | 
			
		||||
        state1_.template Reserve<SizeType>(regex_.stateCount_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~GenericRegexSearch() {
 | 
			
		||||
        Allocator::Free(stateSet_);
 | 
			
		||||
        RAPIDJSON_DELETE(ownAllocator_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    bool Match(InputStream& is) {
 | 
			
		||||
        return SearchWithAnchoring(is, true, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Match(const Ch* s) {
 | 
			
		||||
        GenericStringStream<Encoding> is(s);
 | 
			
		||||
        return Match(is);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    bool Search(InputStream& is) {
 | 
			
		||||
        return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Search(const Ch* s) {
 | 
			
		||||
        GenericStringStream<Encoding> is(s);
 | 
			
		||||
        return Search(is);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    typedef typename RegexType::State State;
 | 
			
		||||
    typedef typename RegexType::Range Range;
 | 
			
		||||
 | 
			
		||||
    template <typename InputStream>
 | 
			
		||||
    bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
 | 
			
		||||
        DecodedStream<InputStream, Encoding> ds(is);
 | 
			
		||||
 | 
			
		||||
        state0_.Clear();
 | 
			
		||||
        Stack<Allocator> *current = &state0_, *next = &state1_;
 | 
			
		||||
        const size_t stateSetSize = GetStateSetSize();
 | 
			
		||||
        std::memset(stateSet_, 0, stateSetSize);
 | 
			
		||||
 | 
			
		||||
        bool matched = AddState(*current, regex_.root_);
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        while (!current->Empty() && (codepoint = ds.Take()) != 0) {
 | 
			
		||||
            std::memset(stateSet_, 0, stateSetSize);
 | 
			
		||||
            next->Clear();
 | 
			
		||||
            matched = false;
 | 
			
		||||
            for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
 | 
			
		||||
                const State& sr = regex_.GetState(*s);
 | 
			
		||||
                if (sr.codepoint == codepoint ||
 | 
			
		||||
                    sr.codepoint == RegexType::kAnyCharacterClass || 
 | 
			
		||||
                    (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
 | 
			
		||||
                {
 | 
			
		||||
                    matched = AddState(*next, sr.out) || matched;
 | 
			
		||||
                    if (!anchorEnd && matched)
 | 
			
		||||
                        return true;
 | 
			
		||||
                }
 | 
			
		||||
                if (!anchorBegin)
 | 
			
		||||
                    AddState(*next, regex_.root_);
 | 
			
		||||
            }
 | 
			
		||||
            internal::Swap(current, next);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return matched;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t GetStateSetSize() const {
 | 
			
		||||
        return (regex_.stateCount_ + 31) / 32 * 4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Return whether the added states is a match state
 | 
			
		||||
    bool AddState(Stack<Allocator>& l, SizeType index) {
 | 
			
		||||
        RAPIDJSON_ASSERT(index != kRegexInvalidState);
 | 
			
		||||
 | 
			
		||||
        const State& s = regex_.GetState(index);
 | 
			
		||||
        if (s.out1 != kRegexInvalidState) { // Split
 | 
			
		||||
            bool matched = AddState(l, s.out);
 | 
			
		||||
            return AddState(l, s.out1) || matched;
 | 
			
		||||
        }
 | 
			
		||||
        else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
 | 
			
		||||
            stateSet_[index >> 5] |= (1u << (index & 31));
 | 
			
		||||
            *l.template PushUnsafe<SizeType>() = index;
 | 
			
		||||
        }
 | 
			
		||||
        return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
 | 
			
		||||
        bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
 | 
			
		||||
        while (rangeIndex != kRegexInvalidRange) {
 | 
			
		||||
            const Range& r = regex_.GetRange(rangeIndex);
 | 
			
		||||
            if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
 | 
			
		||||
                return yes;
 | 
			
		||||
            rangeIndex = r.next;
 | 
			
		||||
        }
 | 
			
		||||
        return !yes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const RegexType& regex_;
 | 
			
		||||
    Allocator* allocator_;
 | 
			
		||||
    Allocator* ownAllocator_;
 | 
			
		||||
    Stack<Allocator> state0_;
 | 
			
		||||
    Stack<Allocator> state1_;
 | 
			
		||||
    uint32_t* stateSet_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef GenericRegex<UTF8<> > Regex;
 | 
			
		||||
typedef GenericRegexSearch<Regex> RegexSearch;
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__) || defined(_MSC_VER)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_INTERNAL_REGEX_H_
 | 
			
		||||
							
								
								
									
										232
									
								
								library/include/rapidjson/internal/stack.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								library/include/rapidjson/internal/stack.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,232 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_INTERNAL_STACK_H_
 | 
			
		||||
#define RAPIDJSON_INTERNAL_STACK_H_
 | 
			
		||||
 | 
			
		||||
#include "../allocators.h"
 | 
			
		||||
#include "swap.h"
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Stack
 | 
			
		||||
 | 
			
		||||
//! A type-unsafe stack for storing different types of data.
 | 
			
		||||
/*! \tparam Allocator Allocator for allocating stack memory.
 | 
			
		||||
*/
 | 
			
		||||
template <typename Allocator>
 | 
			
		||||
class Stack {
 | 
			
		||||
public:
 | 
			
		||||
    // Optimization note: Do not allocate memory for stack_ in constructor.
 | 
			
		||||
    // Do it lazily when first Push() -> Expand() -> Resize().
 | 
			
		||||
    Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    Stack(Stack&& rhs)
 | 
			
		||||
        : allocator_(rhs.allocator_),
 | 
			
		||||
          ownAllocator_(rhs.ownAllocator_),
 | 
			
		||||
          stack_(rhs.stack_),
 | 
			
		||||
          stackTop_(rhs.stackTop_),
 | 
			
		||||
          stackEnd_(rhs.stackEnd_),
 | 
			
		||||
          initialCapacity_(rhs.initialCapacity_)
 | 
			
		||||
    {
 | 
			
		||||
        rhs.allocator_ = 0;
 | 
			
		||||
        rhs.ownAllocator_ = 0;
 | 
			
		||||
        rhs.stack_ = 0;
 | 
			
		||||
        rhs.stackTop_ = 0;
 | 
			
		||||
        rhs.stackEnd_ = 0;
 | 
			
		||||
        rhs.initialCapacity_ = 0;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    ~Stack() {
 | 
			
		||||
        Destroy();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    Stack& operator=(Stack&& rhs) {
 | 
			
		||||
        if (&rhs != this)
 | 
			
		||||
        {
 | 
			
		||||
            Destroy();
 | 
			
		||||
 | 
			
		||||
            allocator_ = rhs.allocator_;
 | 
			
		||||
            ownAllocator_ = rhs.ownAllocator_;
 | 
			
		||||
            stack_ = rhs.stack_;
 | 
			
		||||
            stackTop_ = rhs.stackTop_;
 | 
			
		||||
            stackEnd_ = rhs.stackEnd_;
 | 
			
		||||
            initialCapacity_ = rhs.initialCapacity_;
 | 
			
		||||
 | 
			
		||||
            rhs.allocator_ = 0;
 | 
			
		||||
            rhs.ownAllocator_ = 0;
 | 
			
		||||
            rhs.stack_ = 0;
 | 
			
		||||
            rhs.stackTop_ = 0;
 | 
			
		||||
            rhs.stackEnd_ = 0;
 | 
			
		||||
            rhs.initialCapacity_ = 0;
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
 | 
			
		||||
        internal::Swap(allocator_, rhs.allocator_);
 | 
			
		||||
        internal::Swap(ownAllocator_, rhs.ownAllocator_);
 | 
			
		||||
        internal::Swap(stack_, rhs.stack_);
 | 
			
		||||
        internal::Swap(stackTop_, rhs.stackTop_);
 | 
			
		||||
        internal::Swap(stackEnd_, rhs.stackEnd_);
 | 
			
		||||
        internal::Swap(initialCapacity_, rhs.initialCapacity_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Clear() { stackTop_ = stack_; }
 | 
			
		||||
 | 
			
		||||
    void ShrinkToFit() { 
 | 
			
		||||
        if (Empty()) {
 | 
			
		||||
            // If the stack is empty, completely deallocate the memory.
 | 
			
		||||
            Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
 | 
			
		||||
            stack_ = 0;
 | 
			
		||||
            stackTop_ = 0;
 | 
			
		||||
            stackEnd_ = 0;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            Resize(GetSize());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Optimization note: try to minimize the size of this function for force inline.
 | 
			
		||||
    // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
 | 
			
		||||
         // Expand the stack if needed
 | 
			
		||||
        if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
 | 
			
		||||
            Expand<T>(count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
 | 
			
		||||
        Reserve<T>(count);
 | 
			
		||||
        return PushUnsafe<T>(count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
 | 
			
		||||
        RAPIDJSON_ASSERT(stackTop_);
 | 
			
		||||
        RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
 | 
			
		||||
        T* ret = reinterpret_cast<T*>(stackTop_);
 | 
			
		||||
        stackTop_ += sizeof(T) * count;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    T* Pop(size_t count) {
 | 
			
		||||
        RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
 | 
			
		||||
        stackTop_ -= count * sizeof(T);
 | 
			
		||||
        return reinterpret_cast<T*>(stackTop_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    T* Top() { 
 | 
			
		||||
        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
 | 
			
		||||
        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    const T* Top() const {
 | 
			
		||||
        RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
 | 
			
		||||
        return reinterpret_cast<T*>(stackTop_ - sizeof(T));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    T* End() { return reinterpret_cast<T*>(stackTop_); }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    const T* End() const { return reinterpret_cast<T*>(stackTop_); }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    T* Bottom() { return reinterpret_cast<T*>(stack_); }
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
 | 
			
		||||
 | 
			
		||||
    bool HasAllocator() const {
 | 
			
		||||
        return allocator_ != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Allocator& GetAllocator() {
 | 
			
		||||
        RAPIDJSON_ASSERT(allocator_);
 | 
			
		||||
        return *allocator_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Empty() const { return stackTop_ == stack_; }
 | 
			
		||||
    size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
 | 
			
		||||
    size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    void Expand(size_t count) {
 | 
			
		||||
        // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
 | 
			
		||||
        size_t newCapacity;
 | 
			
		||||
        if (stack_ == 0) {
 | 
			
		||||
            if (!allocator_)
 | 
			
		||||
                ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
			
		||||
            newCapacity = initialCapacity_;
 | 
			
		||||
        } else {
 | 
			
		||||
            newCapacity = GetCapacity();
 | 
			
		||||
            newCapacity += (newCapacity + 1) / 2;
 | 
			
		||||
        }
 | 
			
		||||
        size_t newSize = GetSize() + sizeof(T) * count;
 | 
			
		||||
        if (newCapacity < newSize)
 | 
			
		||||
            newCapacity = newSize;
 | 
			
		||||
 | 
			
		||||
        Resize(newCapacity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Resize(size_t newCapacity) {
 | 
			
		||||
        const size_t size = GetSize();  // Backup the current size
 | 
			
		||||
        stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
 | 
			
		||||
        stackTop_ = stack_ + size;
 | 
			
		||||
        stackEnd_ = stack_ + newCapacity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Destroy() {
 | 
			
		||||
        Allocator::Free(stack_);
 | 
			
		||||
        RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prohibit copy constructor & assignment operator.
 | 
			
		||||
    Stack(const Stack&);
 | 
			
		||||
    Stack& operator=(const Stack&);
 | 
			
		||||
 | 
			
		||||
    Allocator* allocator_;
 | 
			
		||||
    Allocator* ownAllocator_;
 | 
			
		||||
    char *stack_;
 | 
			
		||||
    char *stackTop_;
 | 
			
		||||
    char *stackEnd_;
 | 
			
		||||
    size_t initialCapacity_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_STACK_H_
 | 
			
		||||
							
								
								
									
										83
									
								
								library/include/rapidjson/internal/strfunc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								library/include/rapidjson/internal/strfunc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
 | 
			
		||||
#define RAPIDJSON_INTERNAL_STRFUNC_H_
 | 
			
		||||
 | 
			
		||||
#include "../stream.h"
 | 
			
		||||
#include <cwchar>
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
//! Custom strlen() which works on different character types.
 | 
			
		||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
 | 
			
		||||
    \param s Null-terminated input string.
 | 
			
		||||
    \return Number of characters in the string. 
 | 
			
		||||
    \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
 | 
			
		||||
*/
 | 
			
		||||
template <typename Ch>
 | 
			
		||||
inline SizeType StrLen(const Ch* s) {
 | 
			
		||||
    RAPIDJSON_ASSERT(s != 0);
 | 
			
		||||
    const Ch* p = s;
 | 
			
		||||
    while (*p) ++p;
 | 
			
		||||
    return SizeType(p - s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
inline SizeType StrLen(const char* s) {
 | 
			
		||||
    return SizeType(std::strlen(s));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
inline SizeType StrLen(const wchar_t* s) {
 | 
			
		||||
    return SizeType(std::wcslen(s));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Custom strcmpn() which works on different character types.
 | 
			
		||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
 | 
			
		||||
    \param s1 Null-terminated input string.
 | 
			
		||||
    \param s2 Null-terminated input string.
 | 
			
		||||
    \return 0 if equal
 | 
			
		||||
*/
 | 
			
		||||
template<typename Ch>
 | 
			
		||||
inline int StrCmp(const Ch* s1, const Ch* s2) {
 | 
			
		||||
    RAPIDJSON_ASSERT(s1 != 0);
 | 
			
		||||
    RAPIDJSON_ASSERT(s2 != 0);
 | 
			
		||||
    while(*s1 && (*s1 == *s2)) { s1++; s2++; }
 | 
			
		||||
    return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Returns number of code points in a encoded string.
 | 
			
		||||
template<typename Encoding>
 | 
			
		||||
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
 | 
			
		||||
    RAPIDJSON_ASSERT(s != 0);
 | 
			
		||||
    RAPIDJSON_ASSERT(outCount != 0);
 | 
			
		||||
    GenericStringStream<Encoding> is(s);
 | 
			
		||||
    const typename Encoding::Ch* end = s + length;
 | 
			
		||||
    SizeType count = 0;
 | 
			
		||||
    while (is.src_ < end) {
 | 
			
		||||
        unsigned codepoint;
 | 
			
		||||
        if (!Encoding::Decode(is, &codepoint))
 | 
			
		||||
            return false;
 | 
			
		||||
        count++;
 | 
			
		||||
    }
 | 
			
		||||
    *outCount = count;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
 | 
			
		||||
							
								
								
									
										293
									
								
								library/include/rapidjson/internal/strtod.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								library/include/rapidjson/internal/strtod.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,293 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_STRTOD_
 | 
			
		||||
#define RAPIDJSON_STRTOD_
 | 
			
		||||
 | 
			
		||||
#include "ieee754.h"
 | 
			
		||||
#include "biginteger.h"
 | 
			
		||||
#include "diyfp.h"
 | 
			
		||||
#include "pow10.h"
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <limits>
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
inline double FastPath(double significand, int exp) {
 | 
			
		||||
    if (exp < -308)
 | 
			
		||||
        return 0.0;
 | 
			
		||||
    else if (exp >= 0)
 | 
			
		||||
        return significand * internal::Pow10(exp);
 | 
			
		||||
    else
 | 
			
		||||
        return significand / internal::Pow10(-exp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline double StrtodNormalPrecision(double d, int p) {
 | 
			
		||||
    if (p < -308) {
 | 
			
		||||
        // Prevent expSum < -308, making Pow10(p) = 0
 | 
			
		||||
        d = FastPath(d, -308);
 | 
			
		||||
        d = FastPath(d, p + 308);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        d = FastPath(d, p);
 | 
			
		||||
    return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline T Min3(T a, T b, T c) {
 | 
			
		||||
    T m = a;
 | 
			
		||||
    if (m > b) m = b;
 | 
			
		||||
    if (m > c) m = c;
 | 
			
		||||
    return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
 | 
			
		||||
    const Double db(b);
 | 
			
		||||
    const uint64_t bInt = db.IntegerSignificand();
 | 
			
		||||
    const int bExp = db.IntegerExponent();
 | 
			
		||||
    const int hExp = bExp - 1;
 | 
			
		||||
 | 
			
		||||
    int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
 | 
			
		||||
 | 
			
		||||
    // Adjust for decimal exponent
 | 
			
		||||
    if (dExp >= 0) {
 | 
			
		||||
        dS_Exp2 += dExp;
 | 
			
		||||
        dS_Exp5 += dExp;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        bS_Exp2 -= dExp;
 | 
			
		||||
        bS_Exp5 -= dExp;
 | 
			
		||||
        hS_Exp2 -= dExp;
 | 
			
		||||
        hS_Exp5 -= dExp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Adjust for binary exponent
 | 
			
		||||
    if (bExp >= 0)
 | 
			
		||||
        bS_Exp2 += bExp;
 | 
			
		||||
    else {
 | 
			
		||||
        dS_Exp2 -= bExp;
 | 
			
		||||
        hS_Exp2 -= bExp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Adjust for half ulp exponent
 | 
			
		||||
    if (hExp >= 0)
 | 
			
		||||
        hS_Exp2 += hExp;
 | 
			
		||||
    else {
 | 
			
		||||
        dS_Exp2 -= hExp;
 | 
			
		||||
        bS_Exp2 -= hExp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Remove common power of two factor from all three scaled values
 | 
			
		||||
    int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
 | 
			
		||||
    dS_Exp2 -= common_Exp2;
 | 
			
		||||
    bS_Exp2 -= common_Exp2;
 | 
			
		||||
    hS_Exp2 -= common_Exp2;
 | 
			
		||||
 | 
			
		||||
    BigInteger dS = d;
 | 
			
		||||
    dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
 | 
			
		||||
 | 
			
		||||
    BigInteger bS(bInt);
 | 
			
		||||
    bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
 | 
			
		||||
 | 
			
		||||
    BigInteger hS(1);
 | 
			
		||||
    hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
 | 
			
		||||
 | 
			
		||||
    BigInteger delta(0);
 | 
			
		||||
    dS.Difference(bS, &delta);
 | 
			
		||||
 | 
			
		||||
    return delta.Compare(hS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool StrtodFast(double d, int p, double* result) {
 | 
			
		||||
    // Use fast path for string-to-double conversion if possible
 | 
			
		||||
    // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
 | 
			
		||||
    if (p > 22  && p < 22 + 16) {
 | 
			
		||||
        // Fast Path Cases In Disguise
 | 
			
		||||
        d *= internal::Pow10(p - 22);
 | 
			
		||||
        p = 22;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
 | 
			
		||||
        *result = FastPath(d, p);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compute an approximation and see if it is within 1/2 ULP
 | 
			
		||||
template<typename Ch>
 | 
			
		||||
inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) {
 | 
			
		||||
    uint64_t significand = 0;
 | 
			
		||||
    int i = 0;   // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999    
 | 
			
		||||
    for (; i < dLen; i++) {
 | 
			
		||||
        if (significand  >  RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
 | 
			
		||||
            (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5')))
 | 
			
		||||
            break;
 | 
			
		||||
        significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0'));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (i < dLen && decimals[i] >= Ch('5')) // Rounding
 | 
			
		||||
        significand++;
 | 
			
		||||
 | 
			
		||||
    int remaining = dLen - i;
 | 
			
		||||
    const int kUlpShift = 3;
 | 
			
		||||
    const int kUlp = 1 << kUlpShift;
 | 
			
		||||
    int64_t error = (remaining == 0) ? 0 : kUlp / 2;
 | 
			
		||||
 | 
			
		||||
    DiyFp v(significand, 0);
 | 
			
		||||
    v = v.Normalize();
 | 
			
		||||
    error <<= -v.e;
 | 
			
		||||
 | 
			
		||||
    dExp += remaining;
 | 
			
		||||
 | 
			
		||||
    int actualExp;
 | 
			
		||||
    DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
 | 
			
		||||
    if (actualExp != dExp) {
 | 
			
		||||
        static const DiyFp kPow10[] = {
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60),  // 10^1
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57),  // 10^2
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54),  // 10^3
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50),  // 10^4
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47),  // 10^5
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44),  // 10^6
 | 
			
		||||
            DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40)   // 10^7
 | 
			
		||||
        };
 | 
			
		||||
        int adjustment = dExp - actualExp;
 | 
			
		||||
        RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
 | 
			
		||||
        v = v * kPow10[adjustment - 1];
 | 
			
		||||
        if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
 | 
			
		||||
            error += kUlp / 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    v = v * cachedPower;
 | 
			
		||||
 | 
			
		||||
    error += kUlp + (error == 0 ? 0 : 1);
 | 
			
		||||
 | 
			
		||||
    const int oldExp = v.e;
 | 
			
		||||
    v = v.Normalize();
 | 
			
		||||
    error <<= oldExp - v.e;
 | 
			
		||||
 | 
			
		||||
    const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
 | 
			
		||||
    int precisionSize = 64 - effectiveSignificandSize;
 | 
			
		||||
    if (precisionSize + kUlpShift >= 64) {
 | 
			
		||||
        int scaleExp = (precisionSize + kUlpShift) - 63;
 | 
			
		||||
        v.f >>= scaleExp;
 | 
			
		||||
        v.e += scaleExp; 
 | 
			
		||||
        error = (error >> scaleExp) + 1 + kUlp;
 | 
			
		||||
        precisionSize -= scaleExp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
 | 
			
		||||
    const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
 | 
			
		||||
    const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
 | 
			
		||||
    if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
 | 
			
		||||
        rounded.f++;
 | 
			
		||||
        if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
 | 
			
		||||
            rounded.f >>= 1;
 | 
			
		||||
            rounded.e++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    *result = rounded.ToDouble();
 | 
			
		||||
 | 
			
		||||
    return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Ch>
 | 
			
		||||
inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) {
 | 
			
		||||
    RAPIDJSON_ASSERT(dLen >= 0);
 | 
			
		||||
    const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
 | 
			
		||||
    Double a(approx);
 | 
			
		||||
    int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
 | 
			
		||||
    if (cmp < 0)
 | 
			
		||||
        return a.Value();  // within half ULP
 | 
			
		||||
    else if (cmp == 0) {
 | 
			
		||||
        // Round towards even
 | 
			
		||||
        if (a.Significand() & 1)
 | 
			
		||||
            return a.NextPositiveDouble();
 | 
			
		||||
        else
 | 
			
		||||
            return a.Value();
 | 
			
		||||
    }
 | 
			
		||||
    else // adjustment
 | 
			
		||||
        return a.NextPositiveDouble();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Ch>
 | 
			
		||||
inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) {
 | 
			
		||||
    RAPIDJSON_ASSERT(d >= 0.0);
 | 
			
		||||
    RAPIDJSON_ASSERT(length >= 1);
 | 
			
		||||
 | 
			
		||||
    double result = 0.0;
 | 
			
		||||
    if (StrtodFast(d, p, &result))
 | 
			
		||||
        return result;
 | 
			
		||||
 | 
			
		||||
    RAPIDJSON_ASSERT(length <= INT_MAX);
 | 
			
		||||
    int dLen = static_cast<int>(length);
 | 
			
		||||
 | 
			
		||||
    RAPIDJSON_ASSERT(length >= decimalPosition);
 | 
			
		||||
    RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
 | 
			
		||||
    int dExpAdjust = static_cast<int>(length - decimalPosition);
 | 
			
		||||
 | 
			
		||||
    RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
 | 
			
		||||
    int dExp = exp - dExpAdjust;
 | 
			
		||||
 | 
			
		||||
    // Make sure length+dExp does not overflow
 | 
			
		||||
    RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
 | 
			
		||||
 | 
			
		||||
    // Trim leading zeros
 | 
			
		||||
    while (dLen > 0 && *decimals == '0') {
 | 
			
		||||
        dLen--;
 | 
			
		||||
        decimals++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Trim trailing zeros
 | 
			
		||||
    while (dLen > 0 && decimals[dLen - 1] == '0') {
 | 
			
		||||
        dLen--;
 | 
			
		||||
        dExp++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dLen == 0) { // Buffer only contains zeros.
 | 
			
		||||
        return 0.0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Trim right-most digits
 | 
			
		||||
    const int kMaxDecimalDigit = 767 + 1;
 | 
			
		||||
    if (dLen > kMaxDecimalDigit) {
 | 
			
		||||
        dExp += dLen - kMaxDecimalDigit;
 | 
			
		||||
        dLen = kMaxDecimalDigit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // If too small, underflow to zero.
 | 
			
		||||
    // Any x <= 10^-324 is interpreted as zero.
 | 
			
		||||
    if (dLen + dExp <= -324)
 | 
			
		||||
        return 0.0;
 | 
			
		||||
 | 
			
		||||
    // If too large, overflow to infinity.
 | 
			
		||||
    // Any x >= 10^309 is interpreted as +infinity.
 | 
			
		||||
    if (dLen + dExp > 309)
 | 
			
		||||
        return std::numeric_limits<double>::infinity();
 | 
			
		||||
 | 
			
		||||
    if (StrtodDiyFp(decimals, dLen, dExp, &result))
 | 
			
		||||
        return result;
 | 
			
		||||
 | 
			
		||||
    // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
 | 
			
		||||
    return StrtodBigInteger(result, decimals, dLen, dExp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_STRTOD_
 | 
			
		||||
							
								
								
									
										46
									
								
								library/include/rapidjson/internal/swap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								library/include/rapidjson/internal/swap.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_INTERNAL_SWAP_H_
 | 
			
		||||
#define RAPIDJSON_INTERNAL_SWAP_H_
 | 
			
		||||
 | 
			
		||||
#include "../rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
//! Custom swap() to avoid dependency on C++ <algorithm> header
 | 
			
		||||
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
 | 
			
		||||
    \note This has the same semantics as std::swap().
 | 
			
		||||
*/
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
 | 
			
		||||
    T tmp = a;
 | 
			
		||||
        a = b;
 | 
			
		||||
        b = tmp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace internal
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_INTERNAL_SWAP_H_
 | 
			
		||||
							
								
								
									
										128
									
								
								library/include/rapidjson/istreamwrapper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								library/include/rapidjson/istreamwrapper.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
 | 
			
		||||
#define RAPIDJSON_ISTREAMWRAPPER_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include <iosfwd>
 | 
			
		||||
#include <ios>
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
 | 
			
		||||
/*!
 | 
			
		||||
    The classes can be wrapped including but not limited to:
 | 
			
		||||
 | 
			
		||||
    - \c std::istringstream
 | 
			
		||||
    - \c std::stringstream
 | 
			
		||||
    - \c std::wistringstream
 | 
			
		||||
    - \c std::wstringstream
 | 
			
		||||
    - \c std::ifstream
 | 
			
		||||
    - \c std::fstream
 | 
			
		||||
    - \c std::wifstream
 | 
			
		||||
    - \c std::wfstream
 | 
			
		||||
 | 
			
		||||
    \tparam StreamType Class derived from \c std::basic_istream.
 | 
			
		||||
*/
 | 
			
		||||
   
 | 
			
		||||
template <typename StreamType>
 | 
			
		||||
class BasicIStreamWrapper {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename StreamType::char_type Ch;
 | 
			
		||||
 | 
			
		||||
    //! Constructor.
 | 
			
		||||
    /*!
 | 
			
		||||
        \param stream stream opened for read.
 | 
			
		||||
    */
 | 
			
		||||
    BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 
 | 
			
		||||
        Read();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Constructor.
 | 
			
		||||
    /*!
 | 
			
		||||
        \param stream stream opened for read.
 | 
			
		||||
        \param buffer user-supplied buffer.
 | 
			
		||||
        \param bufferSize size of buffer in bytes. Must >=4 bytes.
 | 
			
		||||
    */
 | 
			
		||||
    BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { 
 | 
			
		||||
        RAPIDJSON_ASSERT(bufferSize >= 4);
 | 
			
		||||
        Read();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return *current_; }
 | 
			
		||||
    Ch Take() { Ch c = *current_; Read(); return c; }
 | 
			
		||||
    size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    void Flush() { RAPIDJSON_ASSERT(false); } 
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
    // For encoding detection only.
 | 
			
		||||
    const Ch* Peek4() const {
 | 
			
		||||
        return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    BasicIStreamWrapper();
 | 
			
		||||
    BasicIStreamWrapper(const BasicIStreamWrapper&);
 | 
			
		||||
    BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
 | 
			
		||||
 | 
			
		||||
    void Read() {
 | 
			
		||||
        if (current_ < bufferLast_)
 | 
			
		||||
            ++current_;
 | 
			
		||||
        else if (!eof_) {
 | 
			
		||||
            count_ += readCount_;
 | 
			
		||||
            readCount_ = bufferSize_;
 | 
			
		||||
            bufferLast_ = buffer_ + readCount_ - 1;
 | 
			
		||||
            current_ = buffer_;
 | 
			
		||||
 | 
			
		||||
            if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) {
 | 
			
		||||
                readCount_ = static_cast<size_t>(stream_.gcount());
 | 
			
		||||
                *(bufferLast_ = buffer_ + readCount_) = '\0';
 | 
			
		||||
                eof_ = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    StreamType &stream_;
 | 
			
		||||
    Ch peekBuffer_[4], *buffer_;
 | 
			
		||||
    size_t bufferSize_;
 | 
			
		||||
    Ch *bufferLast_;
 | 
			
		||||
    Ch *current_;
 | 
			
		||||
    size_t readCount_;
 | 
			
		||||
    size_t count_;  //!< Number of characters read
 | 
			
		||||
    bool eof_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
 | 
			
		||||
typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__) || defined(_MSC_VER)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_ISTREAMWRAPPER_H_
 | 
			
		||||
							
								
								
									
										70
									
								
								library/include/rapidjson/memorybuffer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								library/include/rapidjson/memorybuffer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_MEMORYBUFFER_H_
 | 
			
		||||
#define RAPIDJSON_MEMORYBUFFER_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include "internal/stack.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Represents an in-memory output byte stream.
 | 
			
		||||
/*!
 | 
			
		||||
    This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
 | 
			
		||||
 | 
			
		||||
    It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
 | 
			
		||||
 | 
			
		||||
    Differences between MemoryBuffer and StringBuffer:
 | 
			
		||||
    1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. 
 | 
			
		||||
    2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
 | 
			
		||||
 | 
			
		||||
    \tparam Allocator type for allocating memory buffer.
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
template <typename Allocator = CrtAllocator>
 | 
			
		||||
struct GenericMemoryBuffer {
 | 
			
		||||
    typedef char Ch; // byte
 | 
			
		||||
 | 
			
		||||
    GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
 | 
			
		||||
 | 
			
		||||
    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
 | 
			
		||||
    void Flush() {}
 | 
			
		||||
 | 
			
		||||
    void Clear() { stack_.Clear(); }
 | 
			
		||||
    void ShrinkToFit() { stack_.ShrinkToFit(); }
 | 
			
		||||
    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
 | 
			
		||||
    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
 | 
			
		||||
 | 
			
		||||
    const Ch* GetBuffer() const {
 | 
			
		||||
        return stack_.template Bottom<Ch>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t GetSize() const { return stack_.GetSize(); }
 | 
			
		||||
 | 
			
		||||
    static const size_t kDefaultCapacity = 256;
 | 
			
		||||
    mutable internal::Stack<Allocator> stack_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef GenericMemoryBuffer<> MemoryBuffer;
 | 
			
		||||
 | 
			
		||||
//! Implement specialized version of PutN() with memset() for better performance.
 | 
			
		||||
template<>
 | 
			
		||||
inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
 | 
			
		||||
    std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
 | 
			
		||||
							
								
								
									
										71
									
								
								library/include/rapidjson/memorystream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								library/include/rapidjson/memorystream.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_MEMORYSTREAM_H_
 | 
			
		||||
#define RAPIDJSON_MEMORYSTREAM_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(unreachable-code)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(missing-noreturn)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Represents an in-memory input byte stream.
 | 
			
		||||
/*!
 | 
			
		||||
    This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
 | 
			
		||||
 | 
			
		||||
    It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
 | 
			
		||||
 | 
			
		||||
    Differences between MemoryStream and StringStream:
 | 
			
		||||
    1. StringStream has encoding but MemoryStream is a byte stream.
 | 
			
		||||
    2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
 | 
			
		||||
    3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
struct MemoryStream {
 | 
			
		||||
    typedef char Ch; // byte
 | 
			
		||||
 | 
			
		||||
    MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
 | 
			
		||||
    Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
 | 
			
		||||
    size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
 | 
			
		||||
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    void Flush() { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
    // For encoding detection only.
 | 
			
		||||
    const Ch* Peek4() const {
 | 
			
		||||
        return Tell() + 4 <= size_ ? src_ : 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Ch* src_;     //!< Current read position.
 | 
			
		||||
    const Ch* begin_;   //!< Original head of the string.
 | 
			
		||||
    const Ch* end_;     //!< End of stream.
 | 
			
		||||
    size_t size_;       //!< Size of the stream.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
 | 
			
		||||
							
								
								
									
										316
									
								
								library/include/rapidjson/msinttypes/inttypes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								library/include/rapidjson/msinttypes/inttypes.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,316 @@
 | 
			
		||||
// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
 | 
			
		||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
 | 
			
		||||
// 
 | 
			
		||||
//  Copyright (c) 2006-2013 Alexander Chemeris
 | 
			
		||||
// 
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are met:
 | 
			
		||||
// 
 | 
			
		||||
//   1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
//      this list of conditions and the following disclaimer.
 | 
			
		||||
// 
 | 
			
		||||
//   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
//      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
//      documentation and/or other materials provided with the distribution.
 | 
			
		||||
// 
 | 
			
		||||
//   3. Neither the name of the product nor the names of its contributors may
 | 
			
		||||
//      be used to endorse or promote products derived from this software
 | 
			
		||||
//      without specific prior written permission.
 | 
			
		||||
// 
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | 
			
		||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 | 
			
		||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 | 
			
		||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | 
			
		||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
// 
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
// The above software in this distribution may have been modified by 
 | 
			
		||||
// THL A29 Limited ("Tencent Modifications"). 
 | 
			
		||||
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
 | 
			
		||||
 | 
			
		||||
#ifndef _MSC_VER // [
 | 
			
		||||
#error "Use this header only with Microsoft Visual C++ compilers!"
 | 
			
		||||
#endif // _MSC_VER ]
 | 
			
		||||
 | 
			
		||||
#ifndef _MSC_INTTYPES_H_ // [
 | 
			
		||||
#define _MSC_INTTYPES_H_
 | 
			
		||||
 | 
			
		||||
#if _MSC_VER > 1000
 | 
			
		||||
#pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "stdint.h"
 | 
			
		||||
 | 
			
		||||
// miloyip: VC supports inttypes.h since VC2013
 | 
			
		||||
#if _MSC_VER >= 1800
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
// 7.8 Format conversion of integer types
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
   intmax_t quot;
 | 
			
		||||
   intmax_t rem;
 | 
			
		||||
} imaxdiv_t;
 | 
			
		||||
 | 
			
		||||
// 7.8.1 Macros for format specifiers
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [   See footnote 185 at page 198
 | 
			
		||||
 | 
			
		||||
// The fprintf macros for signed integers are:
 | 
			
		||||
#define PRId8       "d"
 | 
			
		||||
#define PRIi8       "i"
 | 
			
		||||
#define PRIdLEAST8  "d"
 | 
			
		||||
#define PRIiLEAST8  "i"
 | 
			
		||||
#define PRIdFAST8   "d"
 | 
			
		||||
#define PRIiFAST8   "i"
 | 
			
		||||
 | 
			
		||||
#define PRId16       "hd"
 | 
			
		||||
#define PRIi16       "hi"
 | 
			
		||||
#define PRIdLEAST16  "hd"
 | 
			
		||||
#define PRIiLEAST16  "hi"
 | 
			
		||||
#define PRIdFAST16   "hd"
 | 
			
		||||
#define PRIiFAST16   "hi"
 | 
			
		||||
 | 
			
		||||
#define PRId32       "I32d"
 | 
			
		||||
#define PRIi32       "I32i"
 | 
			
		||||
#define PRIdLEAST32  "I32d"
 | 
			
		||||
#define PRIiLEAST32  "I32i"
 | 
			
		||||
#define PRIdFAST32   "I32d"
 | 
			
		||||
#define PRIiFAST32   "I32i"
 | 
			
		||||
 | 
			
		||||
#define PRId64       "I64d"
 | 
			
		||||
#define PRIi64       "I64i"
 | 
			
		||||
#define PRIdLEAST64  "I64d"
 | 
			
		||||
#define PRIiLEAST64  "I64i"
 | 
			
		||||
#define PRIdFAST64   "I64d"
 | 
			
		||||
#define PRIiFAST64   "I64i"
 | 
			
		||||
 | 
			
		||||
#define PRIdMAX     "I64d"
 | 
			
		||||
#define PRIiMAX     "I64i"
 | 
			
		||||
 | 
			
		||||
#define PRIdPTR     "Id"
 | 
			
		||||
#define PRIiPTR     "Ii"
 | 
			
		||||
 | 
			
		||||
// The fprintf macros for unsigned integers are:
 | 
			
		||||
#define PRIo8       "o"
 | 
			
		||||
#define PRIu8       "u"
 | 
			
		||||
#define PRIx8       "x"
 | 
			
		||||
#define PRIX8       "X"
 | 
			
		||||
#define PRIoLEAST8  "o"
 | 
			
		||||
#define PRIuLEAST8  "u"
 | 
			
		||||
#define PRIxLEAST8  "x"
 | 
			
		||||
#define PRIXLEAST8  "X"
 | 
			
		||||
#define PRIoFAST8   "o"
 | 
			
		||||
#define PRIuFAST8   "u"
 | 
			
		||||
#define PRIxFAST8   "x"
 | 
			
		||||
#define PRIXFAST8   "X"
 | 
			
		||||
 | 
			
		||||
#define PRIo16       "ho"
 | 
			
		||||
#define PRIu16       "hu"
 | 
			
		||||
#define PRIx16       "hx"
 | 
			
		||||
#define PRIX16       "hX"
 | 
			
		||||
#define PRIoLEAST16  "ho"
 | 
			
		||||
#define PRIuLEAST16  "hu"
 | 
			
		||||
#define PRIxLEAST16  "hx"
 | 
			
		||||
#define PRIXLEAST16  "hX"
 | 
			
		||||
#define PRIoFAST16   "ho"
 | 
			
		||||
#define PRIuFAST16   "hu"
 | 
			
		||||
#define PRIxFAST16   "hx"
 | 
			
		||||
#define PRIXFAST16   "hX"
 | 
			
		||||
 | 
			
		||||
#define PRIo32       "I32o"
 | 
			
		||||
#define PRIu32       "I32u"
 | 
			
		||||
#define PRIx32       "I32x"
 | 
			
		||||
#define PRIX32       "I32X"
 | 
			
		||||
#define PRIoLEAST32  "I32o"
 | 
			
		||||
#define PRIuLEAST32  "I32u"
 | 
			
		||||
#define PRIxLEAST32  "I32x"
 | 
			
		||||
#define PRIXLEAST32  "I32X"
 | 
			
		||||
#define PRIoFAST32   "I32o"
 | 
			
		||||
#define PRIuFAST32   "I32u"
 | 
			
		||||
#define PRIxFAST32   "I32x"
 | 
			
		||||
#define PRIXFAST32   "I32X"
 | 
			
		||||
 | 
			
		||||
#define PRIo64       "I64o"
 | 
			
		||||
#define PRIu64       "I64u"
 | 
			
		||||
#define PRIx64       "I64x"
 | 
			
		||||
#define PRIX64       "I64X"
 | 
			
		||||
#define PRIoLEAST64  "I64o"
 | 
			
		||||
#define PRIuLEAST64  "I64u"
 | 
			
		||||
#define PRIxLEAST64  "I64x"
 | 
			
		||||
#define PRIXLEAST64  "I64X"
 | 
			
		||||
#define PRIoFAST64   "I64o"
 | 
			
		||||
#define PRIuFAST64   "I64u"
 | 
			
		||||
#define PRIxFAST64   "I64x"
 | 
			
		||||
#define PRIXFAST64   "I64X"
 | 
			
		||||
 | 
			
		||||
#define PRIoMAX     "I64o"
 | 
			
		||||
#define PRIuMAX     "I64u"
 | 
			
		||||
#define PRIxMAX     "I64x"
 | 
			
		||||
#define PRIXMAX     "I64X"
 | 
			
		||||
 | 
			
		||||
#define PRIoPTR     "Io"
 | 
			
		||||
#define PRIuPTR     "Iu"
 | 
			
		||||
#define PRIxPTR     "Ix"
 | 
			
		||||
#define PRIXPTR     "IX"
 | 
			
		||||
 | 
			
		||||
// The fscanf macros for signed integers are:
 | 
			
		||||
#define SCNd8       "d"
 | 
			
		||||
#define SCNi8       "i"
 | 
			
		||||
#define SCNdLEAST8  "d"
 | 
			
		||||
#define SCNiLEAST8  "i"
 | 
			
		||||
#define SCNdFAST8   "d"
 | 
			
		||||
#define SCNiFAST8   "i"
 | 
			
		||||
 | 
			
		||||
#define SCNd16       "hd"
 | 
			
		||||
#define SCNi16       "hi"
 | 
			
		||||
#define SCNdLEAST16  "hd"
 | 
			
		||||
#define SCNiLEAST16  "hi"
 | 
			
		||||
#define SCNdFAST16   "hd"
 | 
			
		||||
#define SCNiFAST16   "hi"
 | 
			
		||||
 | 
			
		||||
#define SCNd32       "ld"
 | 
			
		||||
#define SCNi32       "li"
 | 
			
		||||
#define SCNdLEAST32  "ld"
 | 
			
		||||
#define SCNiLEAST32  "li"
 | 
			
		||||
#define SCNdFAST32   "ld"
 | 
			
		||||
#define SCNiFAST32   "li"
 | 
			
		||||
 | 
			
		||||
#define SCNd64       "I64d"
 | 
			
		||||
#define SCNi64       "I64i"
 | 
			
		||||
#define SCNdLEAST64  "I64d"
 | 
			
		||||
#define SCNiLEAST64  "I64i"
 | 
			
		||||
#define SCNdFAST64   "I64d"
 | 
			
		||||
#define SCNiFAST64   "I64i"
 | 
			
		||||
 | 
			
		||||
#define SCNdMAX     "I64d"
 | 
			
		||||
#define SCNiMAX     "I64i"
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN64 // [
 | 
			
		||||
#  define SCNdPTR     "I64d"
 | 
			
		||||
#  define SCNiPTR     "I64i"
 | 
			
		||||
#else  // _WIN64 ][
 | 
			
		||||
#  define SCNdPTR     "ld"
 | 
			
		||||
#  define SCNiPTR     "li"
 | 
			
		||||
#endif  // _WIN64 ]
 | 
			
		||||
 | 
			
		||||
// The fscanf macros for unsigned integers are:
 | 
			
		||||
#define SCNo8       "o"
 | 
			
		||||
#define SCNu8       "u"
 | 
			
		||||
#define SCNx8       "x"
 | 
			
		||||
#define SCNX8       "X"
 | 
			
		||||
#define SCNoLEAST8  "o"
 | 
			
		||||
#define SCNuLEAST8  "u"
 | 
			
		||||
#define SCNxLEAST8  "x"
 | 
			
		||||
#define SCNXLEAST8  "X"
 | 
			
		||||
#define SCNoFAST8   "o"
 | 
			
		||||
#define SCNuFAST8   "u"
 | 
			
		||||
#define SCNxFAST8   "x"
 | 
			
		||||
#define SCNXFAST8   "X"
 | 
			
		||||
 | 
			
		||||
#define SCNo16       "ho"
 | 
			
		||||
#define SCNu16       "hu"
 | 
			
		||||
#define SCNx16       "hx"
 | 
			
		||||
#define SCNX16       "hX"
 | 
			
		||||
#define SCNoLEAST16  "ho"
 | 
			
		||||
#define SCNuLEAST16  "hu"
 | 
			
		||||
#define SCNxLEAST16  "hx"
 | 
			
		||||
#define SCNXLEAST16  "hX"
 | 
			
		||||
#define SCNoFAST16   "ho"
 | 
			
		||||
#define SCNuFAST16   "hu"
 | 
			
		||||
#define SCNxFAST16   "hx"
 | 
			
		||||
#define SCNXFAST16   "hX"
 | 
			
		||||
 | 
			
		||||
#define SCNo32       "lo"
 | 
			
		||||
#define SCNu32       "lu"
 | 
			
		||||
#define SCNx32       "lx"
 | 
			
		||||
#define SCNX32       "lX"
 | 
			
		||||
#define SCNoLEAST32  "lo"
 | 
			
		||||
#define SCNuLEAST32  "lu"
 | 
			
		||||
#define SCNxLEAST32  "lx"
 | 
			
		||||
#define SCNXLEAST32  "lX"
 | 
			
		||||
#define SCNoFAST32   "lo"
 | 
			
		||||
#define SCNuFAST32   "lu"
 | 
			
		||||
#define SCNxFAST32   "lx"
 | 
			
		||||
#define SCNXFAST32   "lX"
 | 
			
		||||
 | 
			
		||||
#define SCNo64       "I64o"
 | 
			
		||||
#define SCNu64       "I64u"
 | 
			
		||||
#define SCNx64       "I64x"
 | 
			
		||||
#define SCNX64       "I64X"
 | 
			
		||||
#define SCNoLEAST64  "I64o"
 | 
			
		||||
#define SCNuLEAST64  "I64u"
 | 
			
		||||
#define SCNxLEAST64  "I64x"
 | 
			
		||||
#define SCNXLEAST64  "I64X"
 | 
			
		||||
#define SCNoFAST64   "I64o"
 | 
			
		||||
#define SCNuFAST64   "I64u"
 | 
			
		||||
#define SCNxFAST64   "I64x"
 | 
			
		||||
#define SCNXFAST64   "I64X"
 | 
			
		||||
 | 
			
		||||
#define SCNoMAX     "I64o"
 | 
			
		||||
#define SCNuMAX     "I64u"
 | 
			
		||||
#define SCNxMAX     "I64x"
 | 
			
		||||
#define SCNXMAX     "I64X"
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN64 // [
 | 
			
		||||
#  define SCNoPTR     "I64o"
 | 
			
		||||
#  define SCNuPTR     "I64u"
 | 
			
		||||
#  define SCNxPTR     "I64x"
 | 
			
		||||
#  define SCNXPTR     "I64X"
 | 
			
		||||
#else  // _WIN64 ][
 | 
			
		||||
#  define SCNoPTR     "lo"
 | 
			
		||||
#  define SCNuPTR     "lu"
 | 
			
		||||
#  define SCNxPTR     "lx"
 | 
			
		||||
#  define SCNXPTR     "lX"
 | 
			
		||||
#endif  // _WIN64 ]
 | 
			
		||||
 | 
			
		||||
#endif // __STDC_FORMAT_MACROS ]
 | 
			
		||||
 | 
			
		||||
// 7.8.2 Functions for greatest-width integer types
 | 
			
		||||
 | 
			
		||||
// 7.8.2.1 The imaxabs function
 | 
			
		||||
#define imaxabs _abs64
 | 
			
		||||
 | 
			
		||||
// 7.8.2.2 The imaxdiv function
 | 
			
		||||
 | 
			
		||||
// This is modified version of div() function from Microsoft's div.c found
 | 
			
		||||
// in %MSVC.NET%\crt\src\div.c
 | 
			
		||||
#ifdef STATIC_IMAXDIV // [
 | 
			
		||||
static
 | 
			
		||||
#else // STATIC_IMAXDIV ][
 | 
			
		||||
_inline
 | 
			
		||||
#endif // STATIC_IMAXDIV ]
 | 
			
		||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
 | 
			
		||||
{
 | 
			
		||||
   imaxdiv_t result;
 | 
			
		||||
 | 
			
		||||
   result.quot = numer / denom;
 | 
			
		||||
   result.rem = numer % denom;
 | 
			
		||||
 | 
			
		||||
   if (numer < 0 && result.rem > 0) {
 | 
			
		||||
      // did division wrong; must fix up
 | 
			
		||||
      ++result.quot;
 | 
			
		||||
      result.rem -= denom;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 7.8.2.3 The strtoimax and strtoumax functions
 | 
			
		||||
#define strtoimax _strtoi64
 | 
			
		||||
#define strtoumax _strtoui64
 | 
			
		||||
 | 
			
		||||
// 7.8.2.4 The wcstoimax and wcstoumax functions
 | 
			
		||||
#define wcstoimax _wcstoi64
 | 
			
		||||
#define wcstoumax _wcstoui64
 | 
			
		||||
 | 
			
		||||
#endif // _MSC_VER >= 1800
 | 
			
		||||
 | 
			
		||||
#endif // _MSC_INTTYPES_H_ ]
 | 
			
		||||
							
								
								
									
										300
									
								
								library/include/rapidjson/msinttypes/stdint.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								library/include/rapidjson/msinttypes/stdint.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,300 @@
 | 
			
		||||
// ISO C9x  compliant stdint.h for Microsoft Visual Studio
 | 
			
		||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
 | 
			
		||||
// 
 | 
			
		||||
//  Copyright (c) 2006-2013 Alexander Chemeris
 | 
			
		||||
// 
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are met:
 | 
			
		||||
// 
 | 
			
		||||
//   1. Redistributions of source code must retain the above copyright notice,
 | 
			
		||||
//      this list of conditions and the following disclaimer.
 | 
			
		||||
// 
 | 
			
		||||
//   2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
//      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
//      documentation and/or other materials provided with the distribution.
 | 
			
		||||
// 
 | 
			
		||||
//   3. Neither the name of the product nor the names of its contributors may
 | 
			
		||||
//      be used to endorse or promote products derived from this software
 | 
			
		||||
//      without specific prior written permission.
 | 
			
		||||
// 
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | 
			
		||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 | 
			
		||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 | 
			
		||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | 
			
		||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
// 
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
// The above software in this distribution may have been modified by 
 | 
			
		||||
// THL A29 Limited ("Tencent Modifications"). 
 | 
			
		||||
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
 | 
			
		||||
 | 
			
		||||
#ifndef _MSC_VER // [
 | 
			
		||||
#error "Use this header only with Microsoft Visual C++ compilers!"
 | 
			
		||||
#endif // _MSC_VER ]
 | 
			
		||||
 | 
			
		||||
#ifndef _MSC_STDINT_H_ // [
 | 
			
		||||
#define _MSC_STDINT_H_
 | 
			
		||||
 | 
			
		||||
#if _MSC_VER > 1000
 | 
			
		||||
#pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
 | 
			
		||||
#if _MSC_VER >= 1600 // [
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
 | 
			
		||||
 | 
			
		||||
#undef INT8_C
 | 
			
		||||
#undef INT16_C
 | 
			
		||||
#undef INT32_C
 | 
			
		||||
#undef INT64_C
 | 
			
		||||
#undef UINT8_C
 | 
			
		||||
#undef UINT16_C
 | 
			
		||||
#undef UINT32_C
 | 
			
		||||
#undef UINT64_C
 | 
			
		||||
 | 
			
		||||
// 7.18.4.1 Macros for minimum-width integer constants
 | 
			
		||||
 | 
			
		||||
#define INT8_C(val)  val##i8
 | 
			
		||||
#define INT16_C(val) val##i16
 | 
			
		||||
#define INT32_C(val) val##i32
 | 
			
		||||
#define INT64_C(val) val##i64
 | 
			
		||||
 | 
			
		||||
#define UINT8_C(val)  val##ui8
 | 
			
		||||
#define UINT16_C(val) val##ui16
 | 
			
		||||
#define UINT32_C(val) val##ui32
 | 
			
		||||
#define UINT64_C(val) val##ui64
 | 
			
		||||
 | 
			
		||||
// 7.18.4.2 Macros for greatest-width integer constants
 | 
			
		||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
 | 
			
		||||
// Check out Issue 9 for the details.
 | 
			
		||||
#ifndef INTMAX_C //   [
 | 
			
		||||
#  define INTMAX_C   INT64_C
 | 
			
		||||
#endif // INTMAX_C    ]
 | 
			
		||||
#ifndef UINTMAX_C //  [
 | 
			
		||||
#  define UINTMAX_C  UINT64_C
 | 
			
		||||
#endif // UINTMAX_C   ]
 | 
			
		||||
 | 
			
		||||
#endif // __STDC_CONSTANT_MACROS ]
 | 
			
		||||
 | 
			
		||||
#else // ] _MSC_VER >= 1700 [
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
 | 
			
		||||
// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
 | 
			
		||||
// or compiler would give many errors like this:
 | 
			
		||||
//   error C2733: second C linkage of overloaded function 'wmemchr' not allowed
 | 
			
		||||
#if defined(__cplusplus) && !defined(_M_ARM)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
#  include <wchar.h>
 | 
			
		||||
#if defined(__cplusplus) && !defined(_M_ARM)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Define _W64 macros to mark types changing their size, like intptr_t.
 | 
			
		||||
#ifndef _W64
 | 
			
		||||
#  if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
 | 
			
		||||
#     define _W64 __w64
 | 
			
		||||
#  else
 | 
			
		||||
#     define _W64
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 7.18.1 Integer types
 | 
			
		||||
 | 
			
		||||
// 7.18.1.1 Exact-width integer types
 | 
			
		||||
 | 
			
		||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
 | 
			
		||||
// realize that, e.g. char has the same size as __int8
 | 
			
		||||
// so we give up on __intX for them.
 | 
			
		||||
#if (_MSC_VER < 1300)
 | 
			
		||||
   typedef signed char       int8_t;
 | 
			
		||||
   typedef signed short      int16_t;
 | 
			
		||||
   typedef signed int        int32_t;
 | 
			
		||||
   typedef unsigned char     uint8_t;
 | 
			
		||||
   typedef unsigned short    uint16_t;
 | 
			
		||||
   typedef unsigned int      uint32_t;
 | 
			
		||||
#else
 | 
			
		||||
   typedef signed __int8     int8_t;
 | 
			
		||||
   typedef signed __int16    int16_t;
 | 
			
		||||
   typedef signed __int32    int32_t;
 | 
			
		||||
   typedef unsigned __int8   uint8_t;
 | 
			
		||||
   typedef unsigned __int16  uint16_t;
 | 
			
		||||
   typedef unsigned __int32  uint32_t;
 | 
			
		||||
#endif
 | 
			
		||||
typedef signed __int64       int64_t;
 | 
			
		||||
typedef unsigned __int64     uint64_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 7.18.1.2 Minimum-width integer types
 | 
			
		||||
typedef int8_t    int_least8_t;
 | 
			
		||||
typedef int16_t   int_least16_t;
 | 
			
		||||
typedef int32_t   int_least32_t;
 | 
			
		||||
typedef int64_t   int_least64_t;
 | 
			
		||||
typedef uint8_t   uint_least8_t;
 | 
			
		||||
typedef uint16_t  uint_least16_t;
 | 
			
		||||
typedef uint32_t  uint_least32_t;
 | 
			
		||||
typedef uint64_t  uint_least64_t;
 | 
			
		||||
 | 
			
		||||
// 7.18.1.3 Fastest minimum-width integer types
 | 
			
		||||
typedef int8_t    int_fast8_t;
 | 
			
		||||
typedef int16_t   int_fast16_t;
 | 
			
		||||
typedef int32_t   int_fast32_t;
 | 
			
		||||
typedef int64_t   int_fast64_t;
 | 
			
		||||
typedef uint8_t   uint_fast8_t;
 | 
			
		||||
typedef uint16_t  uint_fast16_t;
 | 
			
		||||
typedef uint32_t  uint_fast32_t;
 | 
			
		||||
typedef uint64_t  uint_fast64_t;
 | 
			
		||||
 | 
			
		||||
// 7.18.1.4 Integer types capable of holding object pointers
 | 
			
		||||
#ifdef _WIN64 // [
 | 
			
		||||
   typedef signed __int64    intptr_t;
 | 
			
		||||
   typedef unsigned __int64  uintptr_t;
 | 
			
		||||
#else // _WIN64 ][
 | 
			
		||||
   typedef _W64 signed int   intptr_t;
 | 
			
		||||
   typedef _W64 unsigned int uintptr_t;
 | 
			
		||||
#endif // _WIN64 ]
 | 
			
		||||
 | 
			
		||||
// 7.18.1.5 Greatest-width integer types
 | 
			
		||||
typedef int64_t   intmax_t;
 | 
			
		||||
typedef uint64_t  uintmax_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 7.18.2 Limits of specified-width integer types
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See footnote 220 at page 257 and footnote 221 at page 259
 | 
			
		||||
 | 
			
		||||
// 7.18.2.1 Limits of exact-width integer types
 | 
			
		||||
#define INT8_MIN     ((int8_t)_I8_MIN)
 | 
			
		||||
#define INT8_MAX     _I8_MAX
 | 
			
		||||
#define INT16_MIN    ((int16_t)_I16_MIN)
 | 
			
		||||
#define INT16_MAX    _I16_MAX
 | 
			
		||||
#define INT32_MIN    ((int32_t)_I32_MIN)
 | 
			
		||||
#define INT32_MAX    _I32_MAX
 | 
			
		||||
#define INT64_MIN    ((int64_t)_I64_MIN)
 | 
			
		||||
#define INT64_MAX    _I64_MAX
 | 
			
		||||
#define UINT8_MAX    _UI8_MAX
 | 
			
		||||
#define UINT16_MAX   _UI16_MAX
 | 
			
		||||
#define UINT32_MAX   _UI32_MAX
 | 
			
		||||
#define UINT64_MAX   _UI64_MAX
 | 
			
		||||
 | 
			
		||||
// 7.18.2.2 Limits of minimum-width integer types
 | 
			
		||||
#define INT_LEAST8_MIN    INT8_MIN
 | 
			
		||||
#define INT_LEAST8_MAX    INT8_MAX
 | 
			
		||||
#define INT_LEAST16_MIN   INT16_MIN
 | 
			
		||||
#define INT_LEAST16_MAX   INT16_MAX
 | 
			
		||||
#define INT_LEAST32_MIN   INT32_MIN
 | 
			
		||||
#define INT_LEAST32_MAX   INT32_MAX
 | 
			
		||||
#define INT_LEAST64_MIN   INT64_MIN
 | 
			
		||||
#define INT_LEAST64_MAX   INT64_MAX
 | 
			
		||||
#define UINT_LEAST8_MAX   UINT8_MAX
 | 
			
		||||
#define UINT_LEAST16_MAX  UINT16_MAX
 | 
			
		||||
#define UINT_LEAST32_MAX  UINT32_MAX
 | 
			
		||||
#define UINT_LEAST64_MAX  UINT64_MAX
 | 
			
		||||
 | 
			
		||||
// 7.18.2.3 Limits of fastest minimum-width integer types
 | 
			
		||||
#define INT_FAST8_MIN    INT8_MIN
 | 
			
		||||
#define INT_FAST8_MAX    INT8_MAX
 | 
			
		||||
#define INT_FAST16_MIN   INT16_MIN
 | 
			
		||||
#define INT_FAST16_MAX   INT16_MAX
 | 
			
		||||
#define INT_FAST32_MIN   INT32_MIN
 | 
			
		||||
#define INT_FAST32_MAX   INT32_MAX
 | 
			
		||||
#define INT_FAST64_MIN   INT64_MIN
 | 
			
		||||
#define INT_FAST64_MAX   INT64_MAX
 | 
			
		||||
#define UINT_FAST8_MAX   UINT8_MAX
 | 
			
		||||
#define UINT_FAST16_MAX  UINT16_MAX
 | 
			
		||||
#define UINT_FAST32_MAX  UINT32_MAX
 | 
			
		||||
#define UINT_FAST64_MAX  UINT64_MAX
 | 
			
		||||
 | 
			
		||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
 | 
			
		||||
#ifdef _WIN64 // [
 | 
			
		||||
#  define INTPTR_MIN   INT64_MIN
 | 
			
		||||
#  define INTPTR_MAX   INT64_MAX
 | 
			
		||||
#  define UINTPTR_MAX  UINT64_MAX
 | 
			
		||||
#else // _WIN64 ][
 | 
			
		||||
#  define INTPTR_MIN   INT32_MIN
 | 
			
		||||
#  define INTPTR_MAX   INT32_MAX
 | 
			
		||||
#  define UINTPTR_MAX  UINT32_MAX
 | 
			
		||||
#endif // _WIN64 ]
 | 
			
		||||
 | 
			
		||||
// 7.18.2.5 Limits of greatest-width integer types
 | 
			
		||||
#define INTMAX_MIN   INT64_MIN
 | 
			
		||||
#define INTMAX_MAX   INT64_MAX
 | 
			
		||||
#define UINTMAX_MAX  UINT64_MAX
 | 
			
		||||
 | 
			
		||||
// 7.18.3 Limits of other integer types
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN64 // [
 | 
			
		||||
#  define PTRDIFF_MIN  _I64_MIN
 | 
			
		||||
#  define PTRDIFF_MAX  _I64_MAX
 | 
			
		||||
#else  // _WIN64 ][
 | 
			
		||||
#  define PTRDIFF_MIN  _I32_MIN
 | 
			
		||||
#  define PTRDIFF_MAX  _I32_MAX
 | 
			
		||||
#endif  // _WIN64 ]
 | 
			
		||||
 | 
			
		||||
#define SIG_ATOMIC_MIN  INT_MIN
 | 
			
		||||
#define SIG_ATOMIC_MAX  INT_MAX
 | 
			
		||||
 | 
			
		||||
#ifndef SIZE_MAX // [
 | 
			
		||||
#  ifdef _WIN64 // [
 | 
			
		||||
#     define SIZE_MAX  _UI64_MAX
 | 
			
		||||
#  else // _WIN64 ][
 | 
			
		||||
#     define SIZE_MAX  _UI32_MAX
 | 
			
		||||
#  endif // _WIN64 ]
 | 
			
		||||
#endif // SIZE_MAX ]
 | 
			
		||||
 | 
			
		||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
 | 
			
		||||
#ifndef WCHAR_MIN // [
 | 
			
		||||
#  define WCHAR_MIN  0
 | 
			
		||||
#endif  // WCHAR_MIN ]
 | 
			
		||||
#ifndef WCHAR_MAX // [
 | 
			
		||||
#  define WCHAR_MAX  _UI16_MAX
 | 
			
		||||
#endif  // WCHAR_MAX ]
 | 
			
		||||
 | 
			
		||||
#define WINT_MIN  0
 | 
			
		||||
#define WINT_MAX  _UI16_MAX
 | 
			
		||||
 | 
			
		||||
#endif // __STDC_LIMIT_MACROS ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 7.18.4 Limits of other integer types
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See footnote 224 at page 260
 | 
			
		||||
 | 
			
		||||
// 7.18.4.1 Macros for minimum-width integer constants
 | 
			
		||||
 | 
			
		||||
#define INT8_C(val)  val##i8
 | 
			
		||||
#define INT16_C(val) val##i16
 | 
			
		||||
#define INT32_C(val) val##i32
 | 
			
		||||
#define INT64_C(val) val##i64
 | 
			
		||||
 | 
			
		||||
#define UINT8_C(val)  val##ui8
 | 
			
		||||
#define UINT16_C(val) val##ui16
 | 
			
		||||
#define UINT32_C(val) val##ui32
 | 
			
		||||
#define UINT64_C(val) val##ui64
 | 
			
		||||
 | 
			
		||||
// 7.18.4.2 Macros for greatest-width integer constants
 | 
			
		||||
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
 | 
			
		||||
// Check out Issue 9 for the details.
 | 
			
		||||
#ifndef INTMAX_C //   [
 | 
			
		||||
#  define INTMAX_C   INT64_C
 | 
			
		||||
#endif // INTMAX_C    ]
 | 
			
		||||
#ifndef UINTMAX_C //  [
 | 
			
		||||
#  define UINTMAX_C  UINT64_C
 | 
			
		||||
#endif // UINTMAX_C   ]
 | 
			
		||||
 | 
			
		||||
#endif // __STDC_CONSTANT_MACROS ]
 | 
			
		||||
 | 
			
		||||
#endif // _MSC_VER >= 1600 ]
 | 
			
		||||
 | 
			
		||||
#endif // _MSC_STDINT_H_ ]
 | 
			
		||||
							
								
								
									
										81
									
								
								library/include/rapidjson/ostreamwrapper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								library/include/rapidjson/ostreamwrapper.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
 | 
			
		||||
#define RAPIDJSON_OSTREAMWRAPPER_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include <iosfwd>
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
 | 
			
		||||
/*!
 | 
			
		||||
    The classes can be wrapped including but not limited to:
 | 
			
		||||
 | 
			
		||||
    - \c std::ostringstream
 | 
			
		||||
    - \c std::stringstream
 | 
			
		||||
    - \c std::wpstringstream
 | 
			
		||||
    - \c std::wstringstream
 | 
			
		||||
    - \c std::ifstream
 | 
			
		||||
    - \c std::fstream
 | 
			
		||||
    - \c std::wofstream
 | 
			
		||||
    - \c std::wfstream
 | 
			
		||||
 | 
			
		||||
    \tparam StreamType Class derived from \c std::basic_ostream.
 | 
			
		||||
*/
 | 
			
		||||
   
 | 
			
		||||
template <typename StreamType>
 | 
			
		||||
class BasicOStreamWrapper {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename StreamType::char_type Ch;
 | 
			
		||||
    BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
 | 
			
		||||
 | 
			
		||||
    void Put(Ch c) {
 | 
			
		||||
        stream_.put(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Flush() {
 | 
			
		||||
        stream_.flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Not implemented
 | 
			
		||||
    char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    char Take() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    BasicOStreamWrapper(const BasicOStreamWrapper&);
 | 
			
		||||
    BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
 | 
			
		||||
 | 
			
		||||
    StreamType& stream_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
 | 
			
		||||
typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_OSTREAMWRAPPER_H_
 | 
			
		||||
							
								
								
									
										1470
									
								
								library/include/rapidjson/pointer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1470
									
								
								library/include/rapidjson/pointer.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										277
									
								
								library/include/rapidjson/prettywriter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								library/include/rapidjson/prettywriter.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,277 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_PRETTYWRITER_H_
 | 
			
		||||
#define RAPIDJSON_PRETTYWRITER_H_
 | 
			
		||||
 | 
			
		||||
#include "writer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(effc++)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Combination of PrettyWriter format flags.
 | 
			
		||||
/*! \see PrettyWriter::SetFormatOptions
 | 
			
		||||
 */
 | 
			
		||||
enum PrettyFormatOptions {
 | 
			
		||||
    kFormatDefault = 0,         //!< Default pretty formatting.
 | 
			
		||||
    kFormatSingleLineArray = 1  //!< Format arrays on a single line.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Writer with indentation and spacing.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam OutputStream Type of output os.
 | 
			
		||||
    \tparam SourceEncoding Encoding of source string.
 | 
			
		||||
    \tparam TargetEncoding Encoding of output stream.
 | 
			
		||||
    \tparam StackAllocator Type of allocator for allocating memory of stack.
 | 
			
		||||
*/
 | 
			
		||||
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
 | 
			
		||||
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
 | 
			
		||||
public:
 | 
			
		||||
    typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
 | 
			
		||||
    typedef typename Base::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    //! Constructor
 | 
			
		||||
    /*! \param os Output stream.
 | 
			
		||||
        \param allocator User supplied allocator. If it is null, it will create a private one.
 | 
			
		||||
        \param levelDepth Initial capacity of stack.
 | 
			
		||||
    */
 | 
			
		||||
    explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
 | 
			
		||||
        Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : 
 | 
			
		||||
        Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    PrettyWriter(PrettyWriter&& rhs) :
 | 
			
		||||
        Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //! Set custom indentation.
 | 
			
		||||
    /*! \param indentChar       Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
 | 
			
		||||
        \param indentCharCount  Number of indent characters for each indentation level.
 | 
			
		||||
        \note The default indentation is 4 spaces.
 | 
			
		||||
    */
 | 
			
		||||
    PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
 | 
			
		||||
        RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
 | 
			
		||||
        indentChar_ = indentChar;
 | 
			
		||||
        indentCharCount_ = indentCharCount;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Set pretty writer formatting options.
 | 
			
		||||
    /*! \param options Formatting options.
 | 
			
		||||
    */
 | 
			
		||||
    PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
 | 
			
		||||
        formatOptions_ = options;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*! @name Implementation of Handler
 | 
			
		||||
        \see Handler
 | 
			
		||||
    */
 | 
			
		||||
    //@{
 | 
			
		||||
 | 
			
		||||
    bool Null()                 { PrettyPrefix(kNullType);   return Base::EndValue(Base::WriteNull()); }
 | 
			
		||||
    bool Bool(bool b)           { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
 | 
			
		||||
    bool Int(int i)             { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
 | 
			
		||||
    bool Uint(unsigned u)       { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
 | 
			
		||||
    bool Int64(int64_t i64)     { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
 | 
			
		||||
    bool Uint64(uint64_t u64)   { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64));  }
 | 
			
		||||
    bool Double(double d)       { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
 | 
			
		||||
 | 
			
		||||
    bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
 | 
			
		||||
        RAPIDJSON_ASSERT(str != 0);
 | 
			
		||||
        (void)copy;
 | 
			
		||||
        PrettyPrefix(kNumberType);
 | 
			
		||||
        return Base::EndValue(Base::WriteString(str, length));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool String(const Ch* str, SizeType length, bool copy = false) {
 | 
			
		||||
        RAPIDJSON_ASSERT(str != 0);
 | 
			
		||||
        (void)copy;
 | 
			
		||||
        PrettyPrefix(kStringType);
 | 
			
		||||
        return Base::EndValue(Base::WriteString(str, length));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    bool String(const std::basic_string<Ch>& str) {
 | 
			
		||||
        return String(str.data(), SizeType(str.size()));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool StartObject() {
 | 
			
		||||
        PrettyPrefix(kObjectType);
 | 
			
		||||
        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
 | 
			
		||||
        return Base::WriteStartObject();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    bool Key(const std::basic_string<Ch>& str) {
 | 
			
		||||
        return Key(str.data(), SizeType(str.size()));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
	
 | 
			
		||||
    bool EndObject(SizeType memberCount = 0) {
 | 
			
		||||
        (void)memberCount;
 | 
			
		||||
        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
 | 
			
		||||
        RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
 | 
			
		||||
        RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
 | 
			
		||||
       
 | 
			
		||||
        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
 | 
			
		||||
 | 
			
		||||
        if (!empty) {
 | 
			
		||||
            Base::os_->Put('\n');
 | 
			
		||||
            WriteIndent();
 | 
			
		||||
        }
 | 
			
		||||
        bool ret = Base::EndValue(Base::WriteEndObject());
 | 
			
		||||
        (void)ret;
 | 
			
		||||
        RAPIDJSON_ASSERT(ret == true);
 | 
			
		||||
        if (Base::level_stack_.Empty()) // end of json text
 | 
			
		||||
            Base::Flush();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool StartArray() {
 | 
			
		||||
        PrettyPrefix(kArrayType);
 | 
			
		||||
        new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
 | 
			
		||||
        return Base::WriteStartArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool EndArray(SizeType memberCount = 0) {
 | 
			
		||||
        (void)memberCount;
 | 
			
		||||
        RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
 | 
			
		||||
        RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
 | 
			
		||||
        bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
 | 
			
		||||
 | 
			
		||||
        if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
 | 
			
		||||
            Base::os_->Put('\n');
 | 
			
		||||
            WriteIndent();
 | 
			
		||||
        }
 | 
			
		||||
        bool ret = Base::EndValue(Base::WriteEndArray());
 | 
			
		||||
        (void)ret;
 | 
			
		||||
        RAPIDJSON_ASSERT(ret == true);
 | 
			
		||||
        if (Base::level_stack_.Empty()) // end of json text
 | 
			
		||||
            Base::Flush();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //@}
 | 
			
		||||
 | 
			
		||||
    /*! @name Convenience extensions */
 | 
			
		||||
    //@{
 | 
			
		||||
 | 
			
		||||
    //! Simpler but slower overload.
 | 
			
		||||
    bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
 | 
			
		||||
    bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
 | 
			
		||||
 | 
			
		||||
    //@}
 | 
			
		||||
 | 
			
		||||
    //! Write a raw JSON value.
 | 
			
		||||
    /*!
 | 
			
		||||
        For user to write a stringified JSON as a value.
 | 
			
		||||
 | 
			
		||||
        \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
 | 
			
		||||
        \param length Length of the json.
 | 
			
		||||
        \param type Type of the root of json.
 | 
			
		||||
        \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
 | 
			
		||||
    */
 | 
			
		||||
    bool RawValue(const Ch* json, size_t length, Type type) {
 | 
			
		||||
        RAPIDJSON_ASSERT(json != 0);
 | 
			
		||||
        PrettyPrefix(type);
 | 
			
		||||
        return Base::EndValue(Base::WriteRawValue(json, length));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void PrettyPrefix(Type type) {
 | 
			
		||||
        (void)type;
 | 
			
		||||
        if (Base::level_stack_.GetSize() != 0) { // this value is not at root
 | 
			
		||||
            typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
 | 
			
		||||
 | 
			
		||||
            if (level->inArray) {
 | 
			
		||||
                if (level->valueCount > 0) {
 | 
			
		||||
                    Base::os_->Put(','); // add comma if it is not the first element in array
 | 
			
		||||
                    if (formatOptions_ & kFormatSingleLineArray)
 | 
			
		||||
                        Base::os_->Put(' ');
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!(formatOptions_ & kFormatSingleLineArray)) {
 | 
			
		||||
                    Base::os_->Put('\n');
 | 
			
		||||
                    WriteIndent();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else {  // in object
 | 
			
		||||
                if (level->valueCount > 0) {
 | 
			
		||||
                    if (level->valueCount % 2 == 0) {
 | 
			
		||||
                        Base::os_->Put(',');
 | 
			
		||||
                        Base::os_->Put('\n');
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        Base::os_->Put(':');
 | 
			
		||||
                        Base::os_->Put(' ');
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    Base::os_->Put('\n');
 | 
			
		||||
 | 
			
		||||
                if (level->valueCount % 2 == 0)
 | 
			
		||||
                    WriteIndent();
 | 
			
		||||
            }
 | 
			
		||||
            if (!level->inArray && level->valueCount % 2 == 0)
 | 
			
		||||
                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
 | 
			
		||||
            level->valueCount++;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            RAPIDJSON_ASSERT(!Base::hasRoot_);  // Should only has one and only one root.
 | 
			
		||||
            Base::hasRoot_ = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void WriteIndent()  {
 | 
			
		||||
        size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
 | 
			
		||||
        PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ch indentChar_;
 | 
			
		||||
    unsigned indentCharCount_;
 | 
			
		||||
    PrettyFormatOptions formatOptions_;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // Prohibit copy constructor & assignment operator.
 | 
			
		||||
    PrettyWriter(const PrettyWriter&);
 | 
			
		||||
    PrettyWriter& operator=(const PrettyWriter&);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_RAPIDJSON_H_
 | 
			
		||||
							
								
								
									
										741
									
								
								library/include/rapidjson/rapidjson.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										741
									
								
								library/include/rapidjson/rapidjson.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,741 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_RAPIDJSON_H_
 | 
			
		||||
#define RAPIDJSON_RAPIDJSON_H_
 | 
			
		||||
 | 
			
		||||
/*!\file rapidjson.h
 | 
			
		||||
    \brief common definitions and configuration
 | 
			
		||||
 | 
			
		||||
    \see RAPIDJSON_CONFIG
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
 | 
			
		||||
    \brief Configuration macros for library features
 | 
			
		||||
 | 
			
		||||
    Some RapidJSON features are configurable to adapt the library to a wide
 | 
			
		||||
    variety of platforms, environments and usage scenarios.  Most of the
 | 
			
		||||
    features can be configured in terms of overridden or predefined
 | 
			
		||||
    preprocessor macros at compile-time.
 | 
			
		||||
 | 
			
		||||
    Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
 | 
			
		||||
 | 
			
		||||
    \note These macros should be given on the compiler command-line
 | 
			
		||||
          (where applicable)  to avoid inconsistent values when compiling
 | 
			
		||||
          different translation units of a single application.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <cstdlib>  // malloc(), realloc(), free(), size_t
 | 
			
		||||
#include <cstring>  // memset(), memcpy(), memmove(), memcmp()
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_VERSION_STRING
 | 
			
		||||
//
 | 
			
		||||
// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
			
		||||
// token stringification
 | 
			
		||||
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
 | 
			
		||||
#define RAPIDJSON_DO_STRINGIFY(x) #x
 | 
			
		||||
 | 
			
		||||
// token concatenation
 | 
			
		||||
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
 | 
			
		||||
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
 | 
			
		||||
#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
 | 
			
		||||
//!@endcond
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_MAJOR_VERSION
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Major version of RapidJSON in integer.
 | 
			
		||||
*/
 | 
			
		||||
/*! \def RAPIDJSON_MINOR_VERSION
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Minor version of RapidJSON in integer.
 | 
			
		||||
*/
 | 
			
		||||
/*! \def RAPIDJSON_PATCH_VERSION
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Patch version of RapidJSON in integer.
 | 
			
		||||
*/
 | 
			
		||||
/*! \def RAPIDJSON_VERSION_STRING
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
 | 
			
		||||
*/
 | 
			
		||||
#define RAPIDJSON_MAJOR_VERSION 1
 | 
			
		||||
#define RAPIDJSON_MINOR_VERSION 1
 | 
			
		||||
#define RAPIDJSON_PATCH_VERSION 0
 | 
			
		||||
#define RAPIDJSON_VERSION_STRING \
 | 
			
		||||
    RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_NAMESPACE_(BEGIN|END)
 | 
			
		||||
/*! \def RAPIDJSON_NAMESPACE
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief   provide custom rapidjson namespace
 | 
			
		||||
 | 
			
		||||
    In order to avoid symbol clashes and/or "One Definition Rule" errors
 | 
			
		||||
    between multiple inclusions of (different versions of) RapidJSON in
 | 
			
		||||
    a single binary, users can customize the name of the main RapidJSON
 | 
			
		||||
    namespace.
 | 
			
		||||
 | 
			
		||||
    In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
 | 
			
		||||
    to a custom name (e.g. \c MyRapidJSON) is sufficient.  If multiple
 | 
			
		||||
    levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
 | 
			
		||||
    RAPIDJSON_NAMESPACE_END need to be defined as well:
 | 
			
		||||
 | 
			
		||||
    \code
 | 
			
		||||
    // in some .cpp file
 | 
			
		||||
    #define RAPIDJSON_NAMESPACE my::rapidjson
 | 
			
		||||
    #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
 | 
			
		||||
    #define RAPIDJSON_NAMESPACE_END   } }
 | 
			
		||||
    #include "rapidjson/..."
 | 
			
		||||
    \endcode
 | 
			
		||||
 | 
			
		||||
    \see rapidjson
 | 
			
		||||
 */
 | 
			
		||||
/*! \def RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief   provide custom rapidjson namespace (opening expression)
 | 
			
		||||
    \see RAPIDJSON_NAMESPACE
 | 
			
		||||
*/
 | 
			
		||||
/*! \def RAPIDJSON_NAMESPACE_END
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief   provide custom rapidjson namespace (closing expression)
 | 
			
		||||
    \see RAPIDJSON_NAMESPACE
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_NAMESPACE
 | 
			
		||||
#define RAPIDJSON_NAMESPACE rapidjson
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RAPIDJSON_NAMESPACE_END
 | 
			
		||||
#define RAPIDJSON_NAMESPACE_END }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// __cplusplus macro
 | 
			
		||||
 | 
			
		||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
#define RAPIDJSON_CPLUSPLUS _MSVC_LANG
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_CPLUSPLUS __cplusplus
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//!@endcond
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
 | 
			
		||||
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
 | 
			
		||||
#endif
 | 
			
		||||
/*! \def RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Enable RapidJSON support for \c std::string
 | 
			
		||||
 | 
			
		||||
    By defining this preprocessor symbol to \c 1, several convenience functions for using
 | 
			
		||||
    \ref rapidjson::GenericValue with \c std::string are enabled, especially
 | 
			
		||||
    for construction and comparison.
 | 
			
		||||
 | 
			
		||||
    \hideinitializer
 | 
			
		||||
*/
 | 
			
		||||
#endif // !defined(RAPIDJSON_HAS_STDSTRING)
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
#include <string>
 | 
			
		||||
#endif // RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_USE_MEMBERSMAP
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_USE_MEMBERSMAP
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Enable RapidJSON support for object members handling in a \c std::multimap
 | 
			
		||||
 | 
			
		||||
    By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object
 | 
			
		||||
    members are stored in a \c std::multimap for faster lookup and deletion times, a
 | 
			
		||||
    trade off with a slightly slower insertion time and a small object allocat(or)ed
 | 
			
		||||
    memory overhead.
 | 
			
		||||
 | 
			
		||||
    \hideinitializer
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_USE_MEMBERSMAP
 | 
			
		||||
#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_NO_INT64DEFINE
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_NO_INT64DEFINE
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Use external 64-bit integer types.
 | 
			
		||||
 | 
			
		||||
    RapidJSON requires the 64-bit integer types \c int64_t and  \c uint64_t types
 | 
			
		||||
    to be available at global scope.
 | 
			
		||||
 | 
			
		||||
    If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
 | 
			
		||||
    prevent RapidJSON from defining its own types.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_NO_INT64DEFINE
 | 
			
		||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
 | 
			
		||||
#include "msinttypes/stdint.h"
 | 
			
		||||
#include "msinttypes/inttypes.h"
 | 
			
		||||
#else
 | 
			
		||||
// Other compilers should have this.
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#endif
 | 
			
		||||
//!@endcond
 | 
			
		||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
 | 
			
		||||
#define RAPIDJSON_NO_INT64DEFINE
 | 
			
		||||
#endif
 | 
			
		||||
#endif // RAPIDJSON_NO_INT64TYPEDEF
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_FORCEINLINE
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_FORCEINLINE
 | 
			
		||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
			
		||||
#if defined(_MSC_VER) && defined(NDEBUG)
 | 
			
		||||
#define RAPIDJSON_FORCEINLINE __forceinline
 | 
			
		||||
#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
 | 
			
		||||
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_FORCEINLINE
 | 
			
		||||
#endif
 | 
			
		||||
//!@endcond
 | 
			
		||||
#endif // RAPIDJSON_FORCEINLINE
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_ENDIAN
 | 
			
		||||
#define RAPIDJSON_LITTLEENDIAN  0   //!< Little endian machine
 | 
			
		||||
#define RAPIDJSON_BIGENDIAN     1   //!< Big endian machine
 | 
			
		||||
 | 
			
		||||
//! Endianness of the machine.
 | 
			
		||||
/*!
 | 
			
		||||
    \def RAPIDJSON_ENDIAN
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
 | 
			
		||||
    GCC 4.6 provided macro for detecting endianness of the target machine. But other
 | 
			
		||||
    compilers may not have this. User can define RAPIDJSON_ENDIAN to either
 | 
			
		||||
    \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
 | 
			
		||||
 | 
			
		||||
    Default detection implemented with reference to
 | 
			
		||||
    \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
 | 
			
		||||
    \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_ENDIAN
 | 
			
		||||
// Detect with GCC 4.6's macro
 | 
			
		||||
#  ifdef __BYTE_ORDER__
 | 
			
		||||
#    if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 | 
			
		||||
#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
			
		||||
#    elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 | 
			
		||||
#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
 | 
			
		||||
#    else
 | 
			
		||||
#      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
 | 
			
		||||
#    endif // __BYTE_ORDER__
 | 
			
		||||
// Detect with GLIBC's endian.h
 | 
			
		||||
#  elif defined(__GLIBC__)
 | 
			
		||||
#    include <endian.h>
 | 
			
		||||
#    if (__BYTE_ORDER == __LITTLE_ENDIAN)
 | 
			
		||||
#      define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
			
		||||
#    elif (__BYTE_ORDER == __BIG_ENDIAN)
 | 
			
		||||
#      define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
 | 
			
		||||
#    else
 | 
			
		||||
#      error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
 | 
			
		||||
#   endif // __GLIBC__
 | 
			
		||||
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
 | 
			
		||||
#  elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
 | 
			
		||||
#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
			
		||||
#  elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
 | 
			
		||||
#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
 | 
			
		||||
// Detect with architecture macros
 | 
			
		||||
#  elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
 | 
			
		||||
#    define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
 | 
			
		||||
#  elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
 | 
			
		||||
#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
			
		||||
#  elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
 | 
			
		||||
#    define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
 | 
			
		||||
#  elif defined(RAPIDJSON_DOXYGEN_RUNNING)
 | 
			
		||||
#    define RAPIDJSON_ENDIAN
 | 
			
		||||
#  else
 | 
			
		||||
#    error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
 | 
			
		||||
#  endif
 | 
			
		||||
#endif // RAPIDJSON_ENDIAN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_64BIT
 | 
			
		||||
 | 
			
		||||
//! Whether using 64-bit architecture
 | 
			
		||||
#ifndef RAPIDJSON_64BIT
 | 
			
		||||
#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
 | 
			
		||||
#define RAPIDJSON_64BIT 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_64BIT 0
 | 
			
		||||
#endif
 | 
			
		||||
#endif // RAPIDJSON_64BIT
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_ALIGN
 | 
			
		||||
 | 
			
		||||
//! Data alignment of the machine.
 | 
			
		||||
/*! \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \param x pointer to align
 | 
			
		||||
 | 
			
		||||
    Some machines require strict data alignment. The default is 8 bytes.
 | 
			
		||||
    User can customize by defining the RAPIDJSON_ALIGN function macro.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_ALIGN
 | 
			
		||||
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_UINT64_C2
 | 
			
		||||
 | 
			
		||||
//! Construct a 64-bit literal by a pair of 32-bit integer.
 | 
			
		||||
/*!
 | 
			
		||||
    64-bit literal with or without ULL suffix is prone to compiler warnings.
 | 
			
		||||
    UINT64_C() is C macro which cause compilation problems.
 | 
			
		||||
    Use this macro to define 64-bit constants by a pair of 32-bit integer.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_UINT64_C2
 | 
			
		||||
#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_48BITPOINTER_OPTIMIZATION
 | 
			
		||||
 | 
			
		||||
//! Use only lower 48-bit address for some pointers.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
 | 
			
		||||
    This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
 | 
			
		||||
    The higher 16-bit can be used for storing other data.
 | 
			
		||||
    \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
 | 
			
		||||
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
 | 
			
		||||
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
 | 
			
		||||
#endif
 | 
			
		||||
#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
 | 
			
		||||
#if RAPIDJSON_64BIT != 1
 | 
			
		||||
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
 | 
			
		||||
#endif
 | 
			
		||||
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
 | 
			
		||||
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
 | 
			
		||||
#define RAPIDJSON_GETPOINTER(type, p) (p)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_SIMD
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief Enable SSE2/SSE4.2/Neon optimization.
 | 
			
		||||
 | 
			
		||||
    RapidJSON supports optimized implementations for some parsing operations
 | 
			
		||||
    based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
 | 
			
		||||
    or ARM compatible processors.
 | 
			
		||||
 | 
			
		||||
    To enable these optimizations, three different symbols can be defined;
 | 
			
		||||
    \code
 | 
			
		||||
    // Enable SSE2 optimization.
 | 
			
		||||
    #define RAPIDJSON_SSE2
 | 
			
		||||
 | 
			
		||||
    // Enable SSE4.2 optimization.
 | 
			
		||||
    #define RAPIDJSON_SSE42
 | 
			
		||||
    \endcode
 | 
			
		||||
 | 
			
		||||
    // Enable ARM Neon optimization.
 | 
			
		||||
    #define RAPIDJSON_NEON
 | 
			
		||||
    \endcode
 | 
			
		||||
 | 
			
		||||
    \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.
 | 
			
		||||
 | 
			
		||||
    If any of these symbols is defined, RapidJSON defines the macro
 | 
			
		||||
    \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
 | 
			
		||||
*/
 | 
			
		||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
 | 
			
		||||
    || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
 | 
			
		||||
#define RAPIDJSON_SIMD
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_NO_SIZETYPEDEFINE
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
 | 
			
		||||
/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief User-provided \c SizeType definition.
 | 
			
		||||
 | 
			
		||||
    In order to avoid using 32-bit size types for indexing strings and arrays,
 | 
			
		||||
    define this preprocessor symbol and provide the type rapidjson::SizeType
 | 
			
		||||
    before including RapidJSON:
 | 
			
		||||
    \code
 | 
			
		||||
    #define RAPIDJSON_NO_SIZETYPEDEFINE
 | 
			
		||||
    namespace rapidjson { typedef ::std::size_t SizeType; }
 | 
			
		||||
    #include "rapidjson/..."
 | 
			
		||||
    \endcode
 | 
			
		||||
 | 
			
		||||
    \see rapidjson::SizeType
 | 
			
		||||
*/
 | 
			
		||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
 | 
			
		||||
#define RAPIDJSON_NO_SIZETYPEDEFINE
 | 
			
		||||
#endif
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
//! Size type (for string lengths, array sizes, etc.)
 | 
			
		||||
/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
 | 
			
		||||
    instead of using \c size_t. Users may override the SizeType by defining
 | 
			
		||||
    \ref RAPIDJSON_NO_SIZETYPEDEFINE.
 | 
			
		||||
*/
 | 
			
		||||
typedef unsigned SizeType;
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// always import std::size_t to rapidjson namespace
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
using std::size_t;
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_ASSERT
 | 
			
		||||
 | 
			
		||||
//! Assertion.
 | 
			
		||||
/*! \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    By default, rapidjson uses C \c assert() for internal assertions.
 | 
			
		||||
    User can override it by defining RAPIDJSON_ASSERT(x) macro.
 | 
			
		||||
 | 
			
		||||
    \note Parsing errors are handled and can be customized by the
 | 
			
		||||
          \ref RAPIDJSON_ERRORS APIs.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_ASSERT
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#define RAPIDJSON_ASSERT(x) assert(x)
 | 
			
		||||
#endif // RAPIDJSON_ASSERT
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_STATIC_ASSERT
 | 
			
		||||
 | 
			
		||||
// Prefer C++11 static_assert, if available
 | 
			
		||||
#ifndef RAPIDJSON_STATIC_ASSERT
 | 
			
		||||
#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
 | 
			
		||||
#define RAPIDJSON_STATIC_ASSERT(x) \
 | 
			
		||||
   static_assert(x, RAPIDJSON_STRINGIFY(x))
 | 
			
		||||
#endif // C++11
 | 
			
		||||
#endif // RAPIDJSON_STATIC_ASSERT
 | 
			
		||||
 | 
			
		||||
// Adopt C++03 implementation from boost
 | 
			
		||||
#ifndef RAPIDJSON_STATIC_ASSERT
 | 
			
		||||
#ifndef __clang__
 | 
			
		||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
			
		||||
#endif
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
 | 
			
		||||
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
 | 
			
		||||
template <size_t x> struct StaticAssertTest {};
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE 
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef __clang__
 | 
			
		||||
//!@endcond
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_STATIC_ASSERT
 | 
			
		||||
    \brief (Internal) macro to check for conditions at compile-time
 | 
			
		||||
    \param x compile-time condition
 | 
			
		||||
    \hideinitializer
 | 
			
		||||
 */
 | 
			
		||||
#define RAPIDJSON_STATIC_ASSERT(x) \
 | 
			
		||||
    typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
 | 
			
		||||
      sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
 | 
			
		||||
    RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
 | 
			
		||||
#endif // RAPIDJSON_STATIC_ASSERT
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
 | 
			
		||||
 | 
			
		||||
//! Compiler branching hint for expression with high probability to be true.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \param x Boolean expression likely to be true.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_LIKELY
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_LIKELY(x) (x)
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//! Compiler branching hint for expression with low probability to be true.
 | 
			
		||||
/*!
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \param x Boolean expression unlikely to be true.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_UNLIKELY
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_UNLIKELY(x) (x)
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Helpers
 | 
			
		||||
 | 
			
		||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
 | 
			
		||||
#define RAPIDJSON_MULTILINEMACRO_END \
 | 
			
		||||
} while((void)0, 0)
 | 
			
		||||
 | 
			
		||||
// adopted from Boost
 | 
			
		||||
#define RAPIDJSON_VERSION_CODE(x,y,z) \
 | 
			
		||||
  (((x)*100000) + ((y)*100) + (z))
 | 
			
		||||
 | 
			
		||||
#if defined(__has_builtin)
 | 
			
		||||
#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x)
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_BUILTIN(x) 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
#define RAPIDJSON_GNUC \
 | 
			
		||||
    RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
 | 
			
		||||
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
 | 
			
		||||
#define RAPIDJSON_DIAG_OFF(x) \
 | 
			
		||||
    RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
 | 
			
		||||
 | 
			
		||||
// push/pop support in Clang and GCC>=4.6
 | 
			
		||||
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
 | 
			
		||||
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
 | 
			
		||||
#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)
 | 
			
		||||
#else // GCC >= 4.2, < 4.6
 | 
			
		||||
#define RAPIDJSON_DIAG_PUSH /* ignored */
 | 
			
		||||
#define RAPIDJSON_DIAG_POP /* ignored */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
 | 
			
		||||
// pragma (MSVC specific)
 | 
			
		||||
#define RAPIDJSON_PRAGMA(x) __pragma(x)
 | 
			
		||||
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
 | 
			
		||||
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
 | 
			
		||||
#define RAPIDJSON_DIAG_POP  RAPIDJSON_DIAG_PRAGMA(pop)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_DIAG_OFF(x) /* ignored */
 | 
			
		||||
#define RAPIDJSON_DIAG_PUSH   /* ignored */
 | 
			
		||||
#define RAPIDJSON_DIAG_POP    /* ignored */
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_DIAG_*
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// C++11 features
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_HAS_CXX11
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
 | 
			
		||||
#elif defined(__clang__)
 | 
			
		||||
#if __has_feature(cxx_rvalue_references) && \
 | 
			
		||||
    (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
 | 
			
		||||
#endif
 | 
			
		||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
 | 
			
		||||
      (defined(_MSC_VER) && _MSC_VER >= 1600) || \
 | 
			
		||||
      (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
 | 
			
		||||
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
 | 
			
		||||
#endif
 | 
			
		||||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
#include <utility> // std::move
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
 | 
			
		||||
#elif defined(__clang__)
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
 | 
			
		||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
 | 
			
		||||
    (defined(_MSC_VER) && _MSC_VER >= 1900) || \
 | 
			
		||||
    (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RAPIDJSON_NOEXCEPT
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_NOEXCEPT
 | 
			
		||||
#define RAPIDJSON_NOEXCEPT noexcept
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_NOEXCEPT throw()
 | 
			
		||||
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// no automatic detection, yet
 | 
			
		||||
#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
 | 
			
		||||
#if (defined(_MSC_VER) && _MSC_VER >= 1700)
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
 | 
			
		||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
 | 
			
		||||
      (defined(_MSC_VER) && _MSC_VER >= 1700) || \
 | 
			
		||||
      (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
 | 
			
		||||
#endif
 | 
			
		||||
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// C++17 features
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_HAS_CXX17
 | 
			
		||||
#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX17
 | 
			
		||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
 | 
			
		||||
#elif defined(__has_cpp_attribute)
 | 
			
		||||
# if __has_cpp_attribute(clang::fallthrough)
 | 
			
		||||
#  define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
 | 
			
		||||
# elif __has_cpp_attribute(fallthrough)
 | 
			
		||||
#  define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
 | 
			
		||||
# else
 | 
			
		||||
#  define RAPIDJSON_DELIBERATE_FALLTHROUGH
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//!@endcond
 | 
			
		||||
 | 
			
		||||
//! Assertion (in non-throwing contexts).
 | 
			
		||||
 /*! \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    Some functions provide a \c noexcept guarantee, if the compiler supports it.
 | 
			
		||||
    In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
 | 
			
		||||
    throw an exception.  This macro adds a separate customization point for
 | 
			
		||||
    such cases.
 | 
			
		||||
 | 
			
		||||
    Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is
 | 
			
		||||
    supported, and to \ref RAPIDJSON_ASSERT otherwise.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// RAPIDJSON_NOEXCEPT_ASSERT
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_NOEXCEPT_ASSERT
 | 
			
		||||
#ifdef RAPIDJSON_ASSERT_THROWS
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x)
 | 
			
		||||
#else
 | 
			
		||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
 | 
			
		||||
#endif // RAPIDJSON_ASSERT_THROWS
 | 
			
		||||
#endif // RAPIDJSON_NOEXCEPT_ASSERT
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// malloc/realloc/free
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_MALLOC
 | 
			
		||||
///! customization point for global \c malloc
 | 
			
		||||
#define RAPIDJSON_MALLOC(size) std::malloc(size)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RAPIDJSON_REALLOC
 | 
			
		||||
///! customization point for global \c realloc
 | 
			
		||||
#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RAPIDJSON_FREE
 | 
			
		||||
///! customization point for global \c free
 | 
			
		||||
#define RAPIDJSON_FREE(ptr) std::free(ptr)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// new/delete
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_NEW
 | 
			
		||||
///! customization point for global \c new
 | 
			
		||||
#define RAPIDJSON_NEW(TypeName) new TypeName
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef RAPIDJSON_DELETE
 | 
			
		||||
///! customization point for global \c delete
 | 
			
		||||
#define RAPIDJSON_DELETE(x) delete x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Type
 | 
			
		||||
 | 
			
		||||
/*! \namespace rapidjson
 | 
			
		||||
    \brief main RapidJSON namespace
 | 
			
		||||
    \see RAPIDJSON_NAMESPACE
 | 
			
		||||
*/
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Type of JSON value
 | 
			
		||||
enum Type {
 | 
			
		||||
    kNullType = 0,      //!< null
 | 
			
		||||
    kFalseType = 1,     //!< false
 | 
			
		||||
    kTrueType = 2,      //!< true
 | 
			
		||||
    kObjectType = 3,    //!< object
 | 
			
		||||
    kArrayType = 4,     //!< array
 | 
			
		||||
    kStringType = 5,    //!< string
 | 
			
		||||
    kNumberType = 6     //!< number
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_RAPIDJSON_H_
 | 
			
		||||
							
								
								
									
										2246
									
								
								library/include/rapidjson/reader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2246
									
								
								library/include/rapidjson/reader.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2953
									
								
								library/include/rapidjson/schema.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2953
									
								
								library/include/rapidjson/schema.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										223
									
								
								library/include/rapidjson/stream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								library/include/rapidjson/stream.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#include "rapidjson.h"
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_STREAM_H_
 | 
			
		||||
#define RAPIDJSON_STREAM_H_
 | 
			
		||||
 | 
			
		||||
#include "encodings.h"
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//  Stream
 | 
			
		||||
 | 
			
		||||
/*! \class rapidjson::Stream
 | 
			
		||||
    \brief Concept for reading and writing characters.
 | 
			
		||||
 | 
			
		||||
    For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
 | 
			
		||||
 | 
			
		||||
    For write-only stream, only need to implement Put() and Flush().
 | 
			
		||||
 | 
			
		||||
\code
 | 
			
		||||
concept Stream {
 | 
			
		||||
    typename Ch;    //!< Character type of the stream.
 | 
			
		||||
 | 
			
		||||
    //! Read the current character from stream without moving the read cursor.
 | 
			
		||||
    Ch Peek() const;
 | 
			
		||||
 | 
			
		||||
    //! Read the current character from stream and moving the read cursor to next character.
 | 
			
		||||
    Ch Take();
 | 
			
		||||
 | 
			
		||||
    //! Get the current read cursor.
 | 
			
		||||
    //! \return Number of characters read from start.
 | 
			
		||||
    size_t Tell();
 | 
			
		||||
 | 
			
		||||
    //! Begin writing operation at the current read pointer.
 | 
			
		||||
    //! \return The begin writer pointer.
 | 
			
		||||
    Ch* PutBegin();
 | 
			
		||||
 | 
			
		||||
    //! Write a character.
 | 
			
		||||
    void Put(Ch c);
 | 
			
		||||
 | 
			
		||||
    //! Flush the buffer.
 | 
			
		||||
    void Flush();
 | 
			
		||||
 | 
			
		||||
    //! End the writing operation.
 | 
			
		||||
    //! \param begin The begin write pointer returned by PutBegin().
 | 
			
		||||
    //! \return Number of characters written.
 | 
			
		||||
    size_t PutEnd(Ch* begin);
 | 
			
		||||
}
 | 
			
		||||
\endcode
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//! Provides additional information for stream.
 | 
			
		||||
/*!
 | 
			
		||||
    By using traits pattern, this type provides a default configuration for stream.
 | 
			
		||||
    For custom stream, this type can be specialized for other configuration.
 | 
			
		||||
    See TEST(Reader, CustomStringStream) in readertest.cpp for example.
 | 
			
		||||
*/
 | 
			
		||||
template<typename Stream>
 | 
			
		||||
struct StreamTraits {
 | 
			
		||||
    //! Whether to make local copy of stream for optimization during parsing.
 | 
			
		||||
    /*!
 | 
			
		||||
        By default, for safety, streams do not use local copy optimization.
 | 
			
		||||
        Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
 | 
			
		||||
    */
 | 
			
		||||
    enum { copyOptimization = 0 };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Reserve n characters for writing to a stream.
 | 
			
		||||
template<typename Stream>
 | 
			
		||||
inline void PutReserve(Stream& stream, size_t count) {
 | 
			
		||||
    (void)stream;
 | 
			
		||||
    (void)count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Write character to a stream, presuming buffer is reserved.
 | 
			
		||||
template<typename Stream>
 | 
			
		||||
inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
 | 
			
		||||
    stream.Put(c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Put N copies of a character to a stream.
 | 
			
		||||
template<typename Stream, typename Ch>
 | 
			
		||||
inline void PutN(Stream& stream, Ch c, size_t n) {
 | 
			
		||||
    PutReserve(stream, n);
 | 
			
		||||
    for (size_t i = 0; i < n; i++)
 | 
			
		||||
        PutUnsafe(stream, c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// GenericStreamWrapper
 | 
			
		||||
 | 
			
		||||
//! A Stream Wrapper
 | 
			
		||||
/*! \tThis string stream is a wrapper for any stream by just forwarding any
 | 
			
		||||
    \treceived message to the origin stream.
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4702)  // unreachable code
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename InputStream, typename Encoding = UTF8<> >
 | 
			
		||||
class GenericStreamWrapper {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
    GenericStreamWrapper(InputStream& is): is_(is) {}
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return is_.Peek(); }
 | 
			
		||||
    Ch Take() { return is_.Take(); }
 | 
			
		||||
    size_t Tell() { return is_.Tell(); }
 | 
			
		||||
    Ch* PutBegin() { return is_.PutBegin(); }
 | 
			
		||||
    void Put(Ch ch) { is_.Put(ch); }
 | 
			
		||||
    void Flush() { is_.Flush(); }
 | 
			
		||||
    size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); }
 | 
			
		||||
 | 
			
		||||
    // wrapper for MemoryStream
 | 
			
		||||
    const Ch* Peek4() const { return is_.Peek4(); }
 | 
			
		||||
 | 
			
		||||
    // wrapper for AutoUTFInputStream
 | 
			
		||||
    UTFType GetType() const { return is_.GetType(); }
 | 
			
		||||
    bool HasBOM() const { return is_.HasBOM(); }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    InputStream& is_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// StringStream
 | 
			
		||||
 | 
			
		||||
//! Read-only string stream.
 | 
			
		||||
/*! \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
template <typename Encoding>
 | 
			
		||||
struct GenericStringStream {
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    GenericStringStream(const Ch *src) : src_(src), head_(src) {}
 | 
			
		||||
 | 
			
		||||
    Ch Peek() const { return *src_; }
 | 
			
		||||
    Ch Take() { return *src_++; }
 | 
			
		||||
    size_t Tell() const { return static_cast<size_t>(src_ - head_); }
 | 
			
		||||
 | 
			
		||||
    Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
    void Put(Ch) { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    void Flush() { RAPIDJSON_ASSERT(false); }
 | 
			
		||||
    size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
 | 
			
		||||
 | 
			
		||||
    const Ch* src_;     //!< Current read position.
 | 
			
		||||
    const Ch* head_;    //!< Original head of the string.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Encoding>
 | 
			
		||||
struct StreamTraits<GenericStringStream<Encoding> > {
 | 
			
		||||
    enum { copyOptimization = 1 };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! String stream with UTF8 encoding.
 | 
			
		||||
typedef GenericStringStream<UTF8<> > StringStream;
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// InsituStringStream
 | 
			
		||||
 | 
			
		||||
//! A read-write string stream.
 | 
			
		||||
/*! This string stream is particularly designed for in-situ parsing.
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
template <typename Encoding>
 | 
			
		||||
struct GenericInsituStringStream {
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
 | 
			
		||||
 | 
			
		||||
    // Read
 | 
			
		||||
    Ch Peek() { return *src_; }
 | 
			
		||||
    Ch Take() { return *src_++; }
 | 
			
		||||
    size_t Tell() { return static_cast<size_t>(src_ - head_); }
 | 
			
		||||
 | 
			
		||||
    // Write
 | 
			
		||||
    void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
 | 
			
		||||
 | 
			
		||||
    Ch* PutBegin() { return dst_ = src_; }
 | 
			
		||||
    size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
 | 
			
		||||
    void Flush() {}
 | 
			
		||||
 | 
			
		||||
    Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
 | 
			
		||||
    void Pop(size_t count) { dst_ -= count; }
 | 
			
		||||
 | 
			
		||||
    Ch* src_;
 | 
			
		||||
    Ch* dst_;
 | 
			
		||||
    Ch* head_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Encoding>
 | 
			
		||||
struct StreamTraits<GenericInsituStringStream<Encoding> > {
 | 
			
		||||
    enum { copyOptimization = 1 };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! Insitu string stream with UTF8 encoding.
 | 
			
		||||
typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_STREAM_H_
 | 
			
		||||
							
								
								
									
										121
									
								
								library/include/rapidjson/stringbuffer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								library/include/rapidjson/stringbuffer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_STRINGBUFFER_H_
 | 
			
		||||
#define RAPIDJSON_STRINGBUFFER_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include "internal/stack.h"
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
#include <utility> // std::move
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "internal/stack.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
//! Represents an in-memory output stream.
 | 
			
		||||
/*!
 | 
			
		||||
    \tparam Encoding Encoding of the stream.
 | 
			
		||||
    \tparam Allocator type for allocating memory buffer.
 | 
			
		||||
    \note implements Stream concept
 | 
			
		||||
*/
 | 
			
		||||
template <typename Encoding, typename Allocator = CrtAllocator>
 | 
			
		||||
class GenericStringBuffer {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename Encoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
 | 
			
		||||
    GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
 | 
			
		||||
        if (&rhs != this)
 | 
			
		||||
            stack_ = std::move(rhs.stack_);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    void Put(Ch c) { *stack_.template Push<Ch>() = c; }
 | 
			
		||||
    void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
 | 
			
		||||
    void Flush() {}
 | 
			
		||||
 | 
			
		||||
    void Clear() { stack_.Clear(); }
 | 
			
		||||
    void ShrinkToFit() {
 | 
			
		||||
        // Push and pop a null terminator. This is safe.
 | 
			
		||||
        *stack_.template Push<Ch>() = '\0';
 | 
			
		||||
        stack_.ShrinkToFit();
 | 
			
		||||
        stack_.template Pop<Ch>(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
 | 
			
		||||
    Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
 | 
			
		||||
    Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
 | 
			
		||||
    void Pop(size_t count) { stack_.template Pop<Ch>(count); }
 | 
			
		||||
 | 
			
		||||
    const Ch* GetString() const {
 | 
			
		||||
        // Push and pop a null terminator. This is safe.
 | 
			
		||||
        *stack_.template Push<Ch>() = '\0';
 | 
			
		||||
        stack_.template Pop<Ch>(1);
 | 
			
		||||
 | 
			
		||||
        return stack_.template Bottom<Ch>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Get the size of string in bytes in the string buffer.
 | 
			
		||||
    size_t GetSize() const { return stack_.GetSize(); }
 | 
			
		||||
 | 
			
		||||
    //! Get the length of string in Ch in the string buffer.
 | 
			
		||||
    size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }
 | 
			
		||||
 | 
			
		||||
    static const size_t kDefaultCapacity = 256;
 | 
			
		||||
    mutable internal::Stack<Allocator> stack_;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // Prohibit copy constructor & assignment operator.
 | 
			
		||||
    GenericStringBuffer(const GenericStringBuffer&);
 | 
			
		||||
    GenericStringBuffer& operator=(const GenericStringBuffer&);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! String buffer with UTF8 encoding
 | 
			
		||||
typedef GenericStringBuffer<UTF8<> > StringBuffer;
 | 
			
		||||
 | 
			
		||||
template<typename Encoding, typename Allocator>
 | 
			
		||||
inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
 | 
			
		||||
    stream.Reserve(count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Encoding, typename Allocator>
 | 
			
		||||
inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
 | 
			
		||||
    stream.PutUnsafe(c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Implement specialized version of PutN() with memset() for better performance.
 | 
			
		||||
template<>
 | 
			
		||||
inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
 | 
			
		||||
    std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_STRINGBUFFER_H_
 | 
			
		||||
							
								
								
									
										481
									
								
								library/include/rapidjson/uri.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								library/include/rapidjson/uri.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,481 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
//
 | 
			
		||||
// (C) Copyright IBM Corporation 2021
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_URI_H_
 | 
			
		||||
#define RAPIDJSON_URI_H_
 | 
			
		||||
 | 
			
		||||
#include "internal/strfunc.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// GenericUri
 | 
			
		||||
 | 
			
		||||
template <typename ValueType, typename Allocator=CrtAllocator>
 | 
			
		||||
class GenericUri {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename ValueType::Ch Ch;
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    typedef std::basic_string<Ch> String;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //! Constructors
 | 
			
		||||
    GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
			
		||||
        Parse(uri, len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
			
		||||
        Parse(uri, internal::StrLen<Ch>(uri));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Use with specializations of GenericValue
 | 
			
		||||
    template<typename T> GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
			
		||||
        const Ch* u = uri.template Get<const Ch*>(); // TypeHelper from document.h
 | 
			
		||||
        Parse(u, internal::StrLen<Ch>(u));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
			
		||||
        Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //! Copy constructor
 | 
			
		||||
    GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() {
 | 
			
		||||
        *this = rhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Copy constructor
 | 
			
		||||
    GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
 | 
			
		||||
        *this = rhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Destructor.
 | 
			
		||||
    ~GenericUri() {
 | 
			
		||||
        Free();
 | 
			
		||||
        RAPIDJSON_DELETE(ownAllocator_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Assignment operator
 | 
			
		||||
    GenericUri& operator=(const GenericUri& rhs) {
 | 
			
		||||
        if (this != &rhs) {
 | 
			
		||||
            // Do not delete ownAllocator
 | 
			
		||||
            Free();
 | 
			
		||||
            Allocate(rhs.GetStringLength());
 | 
			
		||||
            auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength());
 | 
			
		||||
            path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength());
 | 
			
		||||
            query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength());
 | 
			
		||||
            frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength());
 | 
			
		||||
            base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength());
 | 
			
		||||
            uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength());
 | 
			
		||||
            CopyPart(uri_, rhs.uri_, rhs.GetStringLength());
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Getters
 | 
			
		||||
    // Use with specializations of GenericValue
 | 
			
		||||
    template<typename T> void Get(T& uri, Allocator& allocator) {
 | 
			
		||||
        uri.template Set<const Ch*>(this->GetString(), allocator); // TypeHelper from document.h
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const Ch* GetString() const { return uri_; }
 | 
			
		||||
    SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); }
 | 
			
		||||
    const Ch* GetBaseString() const { return base_; }
 | 
			
		||||
    SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); }
 | 
			
		||||
    const Ch* GetSchemeString() const { return scheme_; }
 | 
			
		||||
    SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_); }
 | 
			
		||||
    const Ch* GetAuthString() const { return auth_; }
 | 
			
		||||
    SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); }
 | 
			
		||||
    const Ch* GetPathString() const { return path_; }
 | 
			
		||||
    SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); }
 | 
			
		||||
    const Ch* GetQueryString() const { return query_; }
 | 
			
		||||
    SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); }
 | 
			
		||||
    const Ch* GetFragString() const { return frag_; }
 | 
			
		||||
    SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen<Ch>(frag_); }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); }
 | 
			
		||||
    static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); }
 | 
			
		||||
    static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); }
 | 
			
		||||
    static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); }
 | 
			
		||||
    static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); }
 | 
			
		||||
    static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); }
 | 
			
		||||
    static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //! Equality operators
 | 
			
		||||
    bool operator==(const GenericUri& rhs) const {
 | 
			
		||||
        return Match(rhs, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator!=(const GenericUri& rhs) const {
 | 
			
		||||
        return !Match(rhs, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Match(const GenericUri& uri, bool full = true) const {
 | 
			
		||||
        Ch* s1;
 | 
			
		||||
        Ch* s2;
 | 
			
		||||
        if (full) {
 | 
			
		||||
            s1 = uri_;
 | 
			
		||||
            s2 = uri.uri_;
 | 
			
		||||
        } else {
 | 
			
		||||
            s1 = base_;
 | 
			
		||||
            s2 = uri.base_;
 | 
			
		||||
        }
 | 
			
		||||
        if (s1 == s2) return true;
 | 
			
		||||
        if (s1 == 0 || s2 == 0) return false;
 | 
			
		||||
        return internal::StrCmp<Ch>(s1, s2) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Resolve this URI against another (base) URI in accordance with URI resolution rules.
 | 
			
		||||
    // See https://tools.ietf.org/html/rfc3986
 | 
			
		||||
    // Use for resolving an id or $ref with an in-scope id.
 | 
			
		||||
    // Returns a new GenericUri for the resolved URI.
 | 
			
		||||
    GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) {
 | 
			
		||||
        GenericUri resuri;
 | 
			
		||||
        resuri.allocator_ = allocator;
 | 
			
		||||
        // Ensure enough space for combining paths
 | 
			
		||||
        resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash
 | 
			
		||||
 | 
			
		||||
        if (!(GetSchemeStringLength() == 0)) {
 | 
			
		||||
            // Use all of this URI
 | 
			
		||||
            resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength());
 | 
			
		||||
            resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
 | 
			
		||||
            resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
 | 
			
		||||
            resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
			
		||||
            resuri.RemoveDotSegments();
 | 
			
		||||
        } else {
 | 
			
		||||
            // Use the base scheme
 | 
			
		||||
            resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength());
 | 
			
		||||
            if (!(GetAuthStringLength() == 0)) {
 | 
			
		||||
                // Use this auth, path, query
 | 
			
		||||
                resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
 | 
			
		||||
                resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
 | 
			
		||||
                resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
			
		||||
                resuri.RemoveDotSegments();
 | 
			
		||||
            } else {
 | 
			
		||||
                // Use the base auth
 | 
			
		||||
                resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength());
 | 
			
		||||
                if (GetPathStringLength() == 0) {
 | 
			
		||||
                    // Use the base path
 | 
			
		||||
                    resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength());
 | 
			
		||||
                    if (GetQueryStringLength() == 0) {
 | 
			
		||||
                        // Use the base query
 | 
			
		||||
                        resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength());
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // Use this query
 | 
			
		||||
                        resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (path_[0] == '/') {
 | 
			
		||||
                        // Absolute path - use all of this path
 | 
			
		||||
                        resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
 | 
			
		||||
                        resuri.RemoveDotSegments();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // Relative path - append this path to base path after base path's last slash
 | 
			
		||||
                        size_t pos = 0;
 | 
			
		||||
                        if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) {
 | 
			
		||||
                            resuri.path_[pos] = '/';
 | 
			
		||||
                            pos++;
 | 
			
		||||
                        }
 | 
			
		||||
                        size_t lastslashpos = baseuri.GetPathStringLength();
 | 
			
		||||
                        while (lastslashpos > 0) {
 | 
			
		||||
                            if (baseuri.path_[lastslashpos - 1] == '/') break;
 | 
			
		||||
                            lastslashpos--;
 | 
			
		||||
                        }
 | 
			
		||||
                        std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch));
 | 
			
		||||
                        pos += lastslashpos;
 | 
			
		||||
                        resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength());
 | 
			
		||||
                        resuri.RemoveDotSegments();
 | 
			
		||||
                    }
 | 
			
		||||
                    // Use this query
 | 
			
		||||
                    resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Always use this frag
 | 
			
		||||
        resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength());
 | 
			
		||||
 | 
			
		||||
        // Re-constitute base_ and uri_
 | 
			
		||||
        resuri.SetBase();
 | 
			
		||||
        resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1;
 | 
			
		||||
        resuri.SetUri();
 | 
			
		||||
        return resuri;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Get the allocator of this GenericUri.
 | 
			
		||||
    Allocator& GetAllocator() { return *allocator_; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // Allocate memory for a URI
 | 
			
		||||
    // Returns total amount allocated
 | 
			
		||||
    std::size_t Allocate(std::size_t len) {
 | 
			
		||||
        // Create own allocator if user did not supply.
 | 
			
		||||
        if (!allocator_)
 | 
			
		||||
            ownAllocator_ =  allocator_ = RAPIDJSON_NEW(Allocator)();
 | 
			
		||||
 | 
			
		||||
        // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated.
 | 
			
		||||
        // Order: scheme, auth, path, query, frag, base, uri
 | 
			
		||||
        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
			
		||||
        size_t total = (3 * len + 7) * sizeof(Ch);
 | 
			
		||||
        scheme_ = static_cast<Ch*>(allocator_->Malloc(total));
 | 
			
		||||
        *scheme_ = '\0';
 | 
			
		||||
        auth_ = scheme_;
 | 
			
		||||
        auth_++;
 | 
			
		||||
        *auth_ = '\0';
 | 
			
		||||
        path_ = auth_;
 | 
			
		||||
        path_++;
 | 
			
		||||
        *path_ = '\0';
 | 
			
		||||
        query_ = path_;
 | 
			
		||||
        query_++;
 | 
			
		||||
        *query_ = '\0';
 | 
			
		||||
        frag_ = query_;
 | 
			
		||||
        frag_++;
 | 
			
		||||
        *frag_ = '\0';
 | 
			
		||||
        base_ = frag_;
 | 
			
		||||
        base_++;
 | 
			
		||||
        *base_ = '\0';
 | 
			
		||||
        uri_ = base_;
 | 
			
		||||
        uri_++;
 | 
			
		||||
        *uri_ = '\0';
 | 
			
		||||
        return total;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Free memory for a URI
 | 
			
		||||
    void Free() {
 | 
			
		||||
        if (scheme_) {
 | 
			
		||||
            Allocator::Free(scheme_);
 | 
			
		||||
            scheme_ = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Parse a URI into constituent scheme, authority, path, query, & fragment parts
 | 
			
		||||
    // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per
 | 
			
		||||
    // https://tools.ietf.org/html/rfc3986
 | 
			
		||||
    void Parse(const Ch* uri, std::size_t len) {
 | 
			
		||||
        std::size_t start = 0, pos1 = 0, pos2 = 0;
 | 
			
		||||
        Allocate(len);
 | 
			
		||||
 | 
			
		||||
        // Look for scheme ([^:/?#]+):)?
 | 
			
		||||
        if (start < len) {
 | 
			
		||||
            while (pos1 < len) {
 | 
			
		||||
                if (uri[pos1] == ':') break;
 | 
			
		||||
                pos1++;
 | 
			
		||||
            }
 | 
			
		||||
            if (pos1 != len) {
 | 
			
		||||
                while (pos2 < len) {
 | 
			
		||||
                    if (uri[pos2] == '/') break;
 | 
			
		||||
                    if (uri[pos2] == '?') break;
 | 
			
		||||
                    if (uri[pos2] == '#') break;
 | 
			
		||||
                    pos2++;
 | 
			
		||||
                }
 | 
			
		||||
                if (pos1 < pos2) {
 | 
			
		||||
                    pos1++;
 | 
			
		||||
                    std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch));
 | 
			
		||||
                    scheme_[pos1] = '\0';
 | 
			
		||||
                    start = pos1;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Look for auth (//([^/?#]*))?
 | 
			
		||||
        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
			
		||||
        auth_ = scheme_ + GetSchemeStringLength();
 | 
			
		||||
        auth_++;
 | 
			
		||||
        *auth_ = '\0';
 | 
			
		||||
        if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') {
 | 
			
		||||
            pos2 = start + 2;
 | 
			
		||||
            while (pos2 < len) {
 | 
			
		||||
                if (uri[pos2] == '/') break;
 | 
			
		||||
                if (uri[pos2] == '?') break;
 | 
			
		||||
                if (uri[pos2] == '#') break;
 | 
			
		||||
                pos2++;
 | 
			
		||||
            }
 | 
			
		||||
            std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch));
 | 
			
		||||
            auth_[pos2 - start] = '\0';
 | 
			
		||||
            start = pos2;
 | 
			
		||||
        }
 | 
			
		||||
        // Look for path ([^?#]*)
 | 
			
		||||
        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
			
		||||
        path_ = auth_ + GetAuthStringLength();
 | 
			
		||||
        path_++;
 | 
			
		||||
        *path_ = '\0';
 | 
			
		||||
        if (start < len) {
 | 
			
		||||
            pos2 = start;
 | 
			
		||||
            while (pos2 < len) {
 | 
			
		||||
                if (uri[pos2] == '?') break;
 | 
			
		||||
                if (uri[pos2] == '#') break;
 | 
			
		||||
                pos2++;
 | 
			
		||||
            }
 | 
			
		||||
            if (start != pos2) {
 | 
			
		||||
                std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch));
 | 
			
		||||
                path_[pos2 - start] = '\0';
 | 
			
		||||
                if (path_[0] == '/')
 | 
			
		||||
                    RemoveDotSegments();   // absolute path - normalize
 | 
			
		||||
                start = pos2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Look for query (\?([^#]*))?
 | 
			
		||||
        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
			
		||||
        query_ = path_ + GetPathStringLength();
 | 
			
		||||
        query_++;
 | 
			
		||||
        *query_ = '\0';
 | 
			
		||||
        if (start < len && uri[start] == '?') {
 | 
			
		||||
            pos2 = start + 1;
 | 
			
		||||
            while (pos2 < len) {
 | 
			
		||||
                if (uri[pos2] == '#') break;
 | 
			
		||||
                pos2++;
 | 
			
		||||
            }
 | 
			
		||||
            if (start != pos2) {
 | 
			
		||||
                std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch));
 | 
			
		||||
                query_[pos2 - start] = '\0';
 | 
			
		||||
                start = pos2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Look for fragment (#(.*))?
 | 
			
		||||
        // Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
 | 
			
		||||
        frag_ = query_ + GetQueryStringLength();
 | 
			
		||||
        frag_++;
 | 
			
		||||
        *frag_ = '\0';
 | 
			
		||||
        if (start < len && uri[start] == '#') {
 | 
			
		||||
            std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch));
 | 
			
		||||
            frag_[len - start] = '\0';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Re-constitute base_ and uri_
 | 
			
		||||
        base_ = frag_ + GetFragStringLength() + 1;
 | 
			
		||||
        SetBase();
 | 
			
		||||
        uri_ = base_ + GetBaseStringLength() + 1;
 | 
			
		||||
        SetUri();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Reconstitute base
 | 
			
		||||
    void SetBase() {
 | 
			
		||||
        Ch* next = base_;
 | 
			
		||||
        std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch));
 | 
			
		||||
        next+= GetSchemeStringLength();
 | 
			
		||||
        std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch));
 | 
			
		||||
        next+= GetAuthStringLength();
 | 
			
		||||
        std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch));
 | 
			
		||||
        next+= GetPathStringLength();
 | 
			
		||||
        std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch));
 | 
			
		||||
        next+= GetQueryStringLength();
 | 
			
		||||
        *next = '\0';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Reconstitute uri
 | 
			
		||||
    void SetUri() {
 | 
			
		||||
        Ch* next = uri_;
 | 
			
		||||
        std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch));
 | 
			
		||||
        next+= GetBaseStringLength();
 | 
			
		||||
        std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch));
 | 
			
		||||
        next+= GetFragStringLength();
 | 
			
		||||
        *next = '\0';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Copy a part from one GenericUri to another
 | 
			
		||||
    // Return the pointer to the next part to be copied to
 | 
			
		||||
    Ch* CopyPart(Ch* to, Ch* from, std::size_t len) {
 | 
			
		||||
        RAPIDJSON_ASSERT(to != 0);
 | 
			
		||||
        RAPIDJSON_ASSERT(from != 0);
 | 
			
		||||
        std::memcpy(to, from, len * sizeof(Ch));
 | 
			
		||||
        to[len] = '\0';
 | 
			
		||||
        Ch* next = to + len + 1;
 | 
			
		||||
        return next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Remove . and .. segments from the path_ member.
 | 
			
		||||
    // https://tools.ietf.org/html/rfc3986
 | 
			
		||||
    // This is done in place as we are only removing segments.
 | 
			
		||||
    void RemoveDotSegments() {
 | 
			
		||||
        std::size_t pathlen = GetPathStringLength();
 | 
			
		||||
        std::size_t pathpos = 0;  // Position in path_
 | 
			
		||||
        std::size_t newpos = 0;   // Position in new path_
 | 
			
		||||
 | 
			
		||||
        // Loop through each segment in original path_
 | 
			
		||||
        while (pathpos < pathlen) {
 | 
			
		||||
            // Get next segment, bounded by '/' or end
 | 
			
		||||
            size_t slashpos = 0;
 | 
			
		||||
            while ((pathpos + slashpos) < pathlen) {
 | 
			
		||||
                if (path_[pathpos + slashpos] == '/') break;
 | 
			
		||||
                slashpos++;
 | 
			
		||||
            }
 | 
			
		||||
            // Check for .. and . segments
 | 
			
		||||
            if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') {
 | 
			
		||||
                // Backup a .. segment in the new path_
 | 
			
		||||
                // We expect to find a previously added slash at the end or nothing
 | 
			
		||||
                RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/');
 | 
			
		||||
                size_t lastslashpos = newpos;
 | 
			
		||||
                // Make sure we don't go beyond the start segment
 | 
			
		||||
                if (lastslashpos > 1) {
 | 
			
		||||
                    // Find the next to last slash and back up to it
 | 
			
		||||
                    lastslashpos--;
 | 
			
		||||
                    while (lastslashpos > 0) {
 | 
			
		||||
                        if (path_[lastslashpos - 1] == '/') break;
 | 
			
		||||
                        lastslashpos--;
 | 
			
		||||
                    }
 | 
			
		||||
                    // Set the new path_ position
 | 
			
		||||
                    newpos = lastslashpos;
 | 
			
		||||
                }
 | 
			
		||||
            } else if (slashpos == 1 && path_[pathpos] == '.') {
 | 
			
		||||
                // Discard . segment, leaves new path_ unchanged
 | 
			
		||||
            } else {
 | 
			
		||||
                // Move any other kind of segment to the new path_
 | 
			
		||||
                RAPIDJSON_ASSERT(newpos <= pathpos);
 | 
			
		||||
                std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch));
 | 
			
		||||
                newpos += slashpos;
 | 
			
		||||
                // Add slash if not at end
 | 
			
		||||
                if ((pathpos + slashpos) < pathlen) {
 | 
			
		||||
                    path_[newpos] = '/';
 | 
			
		||||
                    newpos++;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // Move to next segment
 | 
			
		||||
            pathpos += slashpos + 1;
 | 
			
		||||
        }
 | 
			
		||||
        path_[newpos] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ch* uri_;    // Everything
 | 
			
		||||
    Ch* base_;   // Everything except fragment
 | 
			
		||||
    Ch* scheme_; // Includes the :
 | 
			
		||||
    Ch* auth_;   // Includes the //
 | 
			
		||||
    Ch* path_;   // Absolute if starts with /
 | 
			
		||||
    Ch* query_;  // Includes the ?
 | 
			
		||||
    Ch* frag_;   // Includes the #
 | 
			
		||||
 | 
			
		||||
    Allocator* allocator_;      //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
 | 
			
		||||
    Allocator* ownAllocator_;   //!< Allocator owned by this Uri.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! GenericUri for Value (UTF-8, default allocator).
 | 
			
		||||
typedef GenericUri<Value> Uri;
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_URI_H_
 | 
			
		||||
							
								
								
									
										710
									
								
								library/include/rapidjson/writer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										710
									
								
								library/include/rapidjson/writer.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,710 @@
 | 
			
		||||
// Tencent is pleased to support the open source community by making RapidJSON available.
 | 
			
		||||
// 
 | 
			
		||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the MIT License (the "License"); you may not use this file except
 | 
			
		||||
// in compliance with the License. You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://opensource.org/licenses/MIT
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software distributed 
 | 
			
		||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 | 
			
		||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 | 
			
		||||
// specific language governing permissions and limitations under the License.
 | 
			
		||||
 | 
			
		||||
#ifndef RAPIDJSON_WRITER_H_
 | 
			
		||||
#define RAPIDJSON_WRITER_H_
 | 
			
		||||
 | 
			
		||||
#include "stream.h"
 | 
			
		||||
#include "internal/clzll.h"
 | 
			
		||||
#include "internal/meta.h"
 | 
			
		||||
#include "internal/stack.h"
 | 
			
		||||
#include "internal/strfunc.h"
 | 
			
		||||
#include "internal/dtoa.h"
 | 
			
		||||
#include "internal/itoa.h"
 | 
			
		||||
#include "stringbuffer.h"
 | 
			
		||||
#include <new>      // placement new
 | 
			
		||||
 | 
			
		||||
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
 | 
			
		||||
#include <intrin.h>
 | 
			
		||||
#pragma intrinsic(_BitScanForward)
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RAPIDJSON_SSE42
 | 
			
		||||
#include <nmmintrin.h>
 | 
			
		||||
#elif defined(RAPIDJSON_SSE2)
 | 
			
		||||
#include <emmintrin.h>
 | 
			
		||||
#elif defined(RAPIDJSON_NEON)
 | 
			
		||||
#include <arm_neon.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __clang__
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(padded)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(unreachable-code)
 | 
			
		||||
RAPIDJSON_DIAG_OFF(c++98-compat)
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
RAPIDJSON_DIAG_PUSH
 | 
			
		||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// WriteFlag
 | 
			
		||||
 | 
			
		||||
/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS 
 | 
			
		||||
    \ingroup RAPIDJSON_CONFIG
 | 
			
		||||
    \brief User-defined kWriteDefaultFlags definition.
 | 
			
		||||
 | 
			
		||||
    User can define this as any \c WriteFlag combinations.
 | 
			
		||||
*/
 | 
			
		||||
#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
 | 
			
		||||
#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//! Combination of writeFlags
 | 
			
		||||
enum WriteFlag {
 | 
			
		||||
    kWriteNoFlags = 0,              //!< No flags are set.
 | 
			
		||||
    kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
 | 
			
		||||
    kWriteNanAndInfFlag = 2,        //!< Allow writing of Infinity, -Infinity and NaN.
 | 
			
		||||
    kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS  //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//! JSON writer
 | 
			
		||||
/*! Writer implements the concept Handler.
 | 
			
		||||
    It generates JSON text by events to an output os.
 | 
			
		||||
 | 
			
		||||
    User may programmatically calls the functions of a writer to generate JSON text.
 | 
			
		||||
 | 
			
		||||
    On the other side, a writer can also be passed to objects that generates events, 
 | 
			
		||||
 | 
			
		||||
    for example Reader::Parse() and Document::Accept().
 | 
			
		||||
 | 
			
		||||
    \tparam OutputStream Type of output stream.
 | 
			
		||||
    \tparam SourceEncoding Encoding of source string.
 | 
			
		||||
    \tparam TargetEncoding Encoding of output stream.
 | 
			
		||||
    \tparam StackAllocator Type of allocator for allocating memory of stack.
 | 
			
		||||
    \note implements Handler concept
 | 
			
		||||
*/
 | 
			
		||||
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
 | 
			
		||||
class Writer {
 | 
			
		||||
public:
 | 
			
		||||
    typedef typename SourceEncoding::Ch Ch;
 | 
			
		||||
 | 
			
		||||
    static const int kDefaultMaxDecimalPlaces = 324;
 | 
			
		||||
 | 
			
		||||
    //! Constructor
 | 
			
		||||
    /*! \param os Output stream.
 | 
			
		||||
        \param stackAllocator User supplied allocator. If it is null, it will create a private one.
 | 
			
		||||
        \param levelDepth Initial capacity of stack.
 | 
			
		||||
    */
 | 
			
		||||
    explicit
 | 
			
		||||
    Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : 
 | 
			
		||||
        os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
 | 
			
		||||
 | 
			
		||||
    explicit
 | 
			
		||||
    Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
 | 
			
		||||
        os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
 | 
			
		||||
    Writer(Writer&& rhs) :
 | 
			
		||||
        os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
 | 
			
		||||
        rhs.os_ = 0;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    //! Reset the writer with a new stream.
 | 
			
		||||
    /*!
 | 
			
		||||
        This function reset the writer with a new stream and default settings,
 | 
			
		||||
        in order to make a Writer object reusable for output multiple JSONs.
 | 
			
		||||
 | 
			
		||||
        \param os New output stream.
 | 
			
		||||
        \code
 | 
			
		||||
        Writer<OutputStream> writer(os1);
 | 
			
		||||
        writer.StartObject();
 | 
			
		||||
        // ...
 | 
			
		||||
        writer.EndObject();
 | 
			
		||||
 | 
			
		||||
        writer.Reset(os2);
 | 
			
		||||
        writer.StartObject();
 | 
			
		||||
        // ...
 | 
			
		||||
        writer.EndObject();
 | 
			
		||||
        \endcode
 | 
			
		||||
    */
 | 
			
		||||
    void Reset(OutputStream& os) {
 | 
			
		||||
        os_ = &os;
 | 
			
		||||
        hasRoot_ = false;
 | 
			
		||||
        level_stack_.Clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Checks whether the output is a complete JSON.
 | 
			
		||||
    /*!
 | 
			
		||||
        A complete JSON has a complete root object or array.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsComplete() const {
 | 
			
		||||
        return hasRoot_ && level_stack_.Empty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int GetMaxDecimalPlaces() const {
 | 
			
		||||
        return maxDecimalPlaces_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Sets the maximum number of decimal places for double output.
 | 
			
		||||
    /*!
 | 
			
		||||
        This setting truncates the output with specified number of decimal places.
 | 
			
		||||
 | 
			
		||||
        For example, 
 | 
			
		||||
 | 
			
		||||
        \code
 | 
			
		||||
        writer.SetMaxDecimalPlaces(3);
 | 
			
		||||
        writer.StartArray();
 | 
			
		||||
        writer.Double(0.12345);                 // "0.123"
 | 
			
		||||
        writer.Double(0.0001);                  // "0.0"
 | 
			
		||||
        writer.Double(1.234567890123456e30);    // "1.234567890123456e30" (do not truncate significand for positive exponent)
 | 
			
		||||
        writer.Double(1.23e-4);                 // "0.0"                  (do truncate significand for negative exponent)
 | 
			
		||||
        writer.EndArray();
 | 
			
		||||
        \endcode
 | 
			
		||||
 | 
			
		||||
        The default setting does not truncate any decimal places. You can restore to this setting by calling
 | 
			
		||||
        \code
 | 
			
		||||
        writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
 | 
			
		||||
        \endcode
 | 
			
		||||
    */
 | 
			
		||||
    void SetMaxDecimalPlaces(int maxDecimalPlaces) {
 | 
			
		||||
        maxDecimalPlaces_ = maxDecimalPlaces;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!@name Implementation of Handler
 | 
			
		||||
        \see Handler
 | 
			
		||||
    */
 | 
			
		||||
    //@{
 | 
			
		||||
 | 
			
		||||
    bool Null()                 { Prefix(kNullType);   return EndValue(WriteNull()); }
 | 
			
		||||
    bool Bool(bool b)           { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
 | 
			
		||||
    bool Int(int i)             { Prefix(kNumberType); return EndValue(WriteInt(i)); }
 | 
			
		||||
    bool Uint(unsigned u)       { Prefix(kNumberType); return EndValue(WriteUint(u)); }
 | 
			
		||||
    bool Int64(int64_t i64)     { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
 | 
			
		||||
    bool Uint64(uint64_t u64)   { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
 | 
			
		||||
 | 
			
		||||
    //! Writes the given \c double value to the stream
 | 
			
		||||
    /*!
 | 
			
		||||
        \param d The value to be written.
 | 
			
		||||
        \return Whether it is succeed.
 | 
			
		||||
    */
 | 
			
		||||
    bool Double(double d)       { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
 | 
			
		||||
 | 
			
		||||
    bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
 | 
			
		||||
        RAPIDJSON_ASSERT(str != 0);
 | 
			
		||||
        (void)copy;
 | 
			
		||||
        Prefix(kNumberType);
 | 
			
		||||
        return EndValue(WriteString(str, length));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool String(const Ch* str, SizeType length, bool copy = false) {
 | 
			
		||||
        RAPIDJSON_ASSERT(str != 0);
 | 
			
		||||
        (void)copy;
 | 
			
		||||
        Prefix(kStringType);
 | 
			
		||||
        return EndValue(WriteString(str, length));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    bool String(const std::basic_string<Ch>& str) {
 | 
			
		||||
        return String(str.data(), SizeType(str.size()));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool StartObject() {
 | 
			
		||||
        Prefix(kObjectType);
 | 
			
		||||
        new (level_stack_.template Push<Level>()) Level(false);
 | 
			
		||||
        return WriteStartObject();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
 | 
			
		||||
 | 
			
		||||
#if RAPIDJSON_HAS_STDSTRING
 | 
			
		||||
    bool Key(const std::basic_string<Ch>& str)
 | 
			
		||||
    {
 | 
			
		||||
      return Key(str.data(), SizeType(str.size()));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool EndObject(SizeType memberCount = 0) {
 | 
			
		||||
        (void)memberCount;
 | 
			
		||||
        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
 | 
			
		||||
        RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
 | 
			
		||||
        RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
 | 
			
		||||
        level_stack_.template Pop<Level>(1);
 | 
			
		||||
        return EndValue(WriteEndObject());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool StartArray() {
 | 
			
		||||
        Prefix(kArrayType);
 | 
			
		||||
        new (level_stack_.template Push<Level>()) Level(true);
 | 
			
		||||
        return WriteStartArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool EndArray(SizeType elementCount = 0) {
 | 
			
		||||
        (void)elementCount;
 | 
			
		||||
        RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
 | 
			
		||||
        RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
 | 
			
		||||
        level_stack_.template Pop<Level>(1);
 | 
			
		||||
        return EndValue(WriteEndArray());
 | 
			
		||||
    }
 | 
			
		||||
    //@}
 | 
			
		||||
 | 
			
		||||
    /*! @name Convenience extensions */
 | 
			
		||||
    //@{
 | 
			
		||||
 | 
			
		||||
    //! Simpler but slower overload.
 | 
			
		||||
    bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
 | 
			
		||||
    bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
 | 
			
		||||
    
 | 
			
		||||
    //@}
 | 
			
		||||
 | 
			
		||||
    //! Write a raw JSON value.
 | 
			
		||||
    /*!
 | 
			
		||||
        For user to write a stringified JSON as a value.
 | 
			
		||||
 | 
			
		||||
        \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
 | 
			
		||||
        \param length Length of the json.
 | 
			
		||||
        \param type Type of the root of json.
 | 
			
		||||
    */
 | 
			
		||||
    bool RawValue(const Ch* json, size_t length, Type type) {
 | 
			
		||||
        RAPIDJSON_ASSERT(json != 0);
 | 
			
		||||
        Prefix(type);
 | 
			
		||||
        return EndValue(WriteRawValue(json, length));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Flush the output stream.
 | 
			
		||||
    /*!
 | 
			
		||||
        Allows the user to flush the output stream immediately.
 | 
			
		||||
     */
 | 
			
		||||
    void Flush() {
 | 
			
		||||
        os_->Flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static const size_t kDefaultLevelDepth = 32;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    //! Information for each nested level
 | 
			
		||||
    struct Level {
 | 
			
		||||
        Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
 | 
			
		||||
        size_t valueCount;  //!< number of values in this level
 | 
			
		||||
        bool inArray;       //!< true if in array, otherwise in object
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    bool WriteNull()  {
 | 
			
		||||
        PutReserve(*os_, 4);
 | 
			
		||||
        PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteBool(bool b)  {
 | 
			
		||||
        if (b) {
 | 
			
		||||
            PutReserve(*os_, 4);
 | 
			
		||||
            PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            PutReserve(*os_, 5);
 | 
			
		||||
            PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteInt(int i) {
 | 
			
		||||
        char buffer[11];
 | 
			
		||||
        const char* end = internal::i32toa(i, buffer);
 | 
			
		||||
        PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
			
		||||
        for (const char* p = buffer; p != end; ++p)
 | 
			
		||||
            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteUint(unsigned u) {
 | 
			
		||||
        char buffer[10];
 | 
			
		||||
        const char* end = internal::u32toa(u, buffer);
 | 
			
		||||
        PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
			
		||||
        for (const char* p = buffer; p != end; ++p)
 | 
			
		||||
            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteInt64(int64_t i64) {
 | 
			
		||||
        char buffer[21];
 | 
			
		||||
        const char* end = internal::i64toa(i64, buffer);
 | 
			
		||||
        PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
			
		||||
        for (const char* p = buffer; p != end; ++p)
 | 
			
		||||
            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteUint64(uint64_t u64) {
 | 
			
		||||
        char buffer[20];
 | 
			
		||||
        char* end = internal::u64toa(u64, buffer);
 | 
			
		||||
        PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
			
		||||
        for (char* p = buffer; p != end; ++p)
 | 
			
		||||
            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteDouble(double d) {
 | 
			
		||||
        if (internal::Double(d).IsNanOrInf()) {
 | 
			
		||||
            if (!(writeFlags & kWriteNanAndInfFlag))
 | 
			
		||||
                return false;
 | 
			
		||||
            if (internal::Double(d).IsNan()) {
 | 
			
		||||
                PutReserve(*os_, 3);
 | 
			
		||||
                PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if (internal::Double(d).Sign()) {
 | 
			
		||||
                PutReserve(*os_, 9);
 | 
			
		||||
                PutUnsafe(*os_, '-');
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                PutReserve(*os_, 8);
 | 
			
		||||
            PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
 | 
			
		||||
            PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        char buffer[25];
 | 
			
		||||
        char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
 | 
			
		||||
        PutReserve(*os_, static_cast<size_t>(end - buffer));
 | 
			
		||||
        for (char* p = buffer; p != end; ++p)
 | 
			
		||||
            PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteString(const Ch* str, SizeType length)  {
 | 
			
		||||
        static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
 | 
			
		||||
        static const char escape[256] = {
 | 
			
		||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 | 
			
		||||
            //0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
 | 
			
		||||
            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
 | 
			
		||||
            'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
 | 
			
		||||
              0,   0, '"',   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, // 20
 | 
			
		||||
            Z16, Z16,                                                                       // 30~4F
 | 
			
		||||
              0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,   0,   0, // 50
 | 
			
		||||
            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16                                // 60~FF
 | 
			
		||||
#undef Z16
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if (TargetEncoding::supportUnicode)
 | 
			
		||||
            PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
 | 
			
		||||
        else
 | 
			
		||||
            PutReserve(*os_, 2 + length * 12);  // "\uxxxx\uyyyy..."
 | 
			
		||||
 | 
			
		||||
        PutUnsafe(*os_, '\"');
 | 
			
		||||
        GenericStringStream<SourceEncoding> is(str);
 | 
			
		||||
        while (ScanWriteUnescapedString(is, length)) {
 | 
			
		||||
            const Ch c = is.Peek();
 | 
			
		||||
            if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
 | 
			
		||||
                // Unicode escaping
 | 
			
		||||
                unsigned codepoint;
 | 
			
		||||
                if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
 | 
			
		||||
                    return false;
 | 
			
		||||
                PutUnsafe(*os_, '\\');
 | 
			
		||||
                PutUnsafe(*os_, 'u');
 | 
			
		||||
                if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(codepoint >>  8) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(codepoint >>  4) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(codepoint      ) & 15]);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
 | 
			
		||||
                    // Surrogate pair
 | 
			
		||||
                    unsigned s = codepoint - 0x010000;
 | 
			
		||||
                    unsigned lead = (s >> 10) + 0xD800;
 | 
			
		||||
                    unsigned trail = (s & 0x3FF) + 0xDC00;
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(lead >>  8) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(lead >>  4) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(lead      ) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, '\\');
 | 
			
		||||
                    PutUnsafe(*os_, 'u');
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(trail >>  8) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(trail >>  4) & 15]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[(trail      ) & 15]);                    
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)]))  {
 | 
			
		||||
                is.Take();
 | 
			
		||||
                PutUnsafe(*os_, '\\');
 | 
			
		||||
                PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
 | 
			
		||||
                if (escape[static_cast<unsigned char>(c)] == 'u') {
 | 
			
		||||
                    PutUnsafe(*os_, '0');
 | 
			
		||||
                    PutUnsafe(*os_, '0');
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
 | 
			
		||||
                    PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
 | 
			
		||||
                Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
 | 
			
		||||
                Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
        PutUnsafe(*os_, '\"');
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
 | 
			
		||||
        return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool WriteStartObject() { os_->Put('{'); return true; }
 | 
			
		||||
    bool WriteEndObject()   { os_->Put('}'); return true; }
 | 
			
		||||
    bool WriteStartArray()  { os_->Put('['); return true; }
 | 
			
		||||
    bool WriteEndArray()    { os_->Put(']'); return true; }
 | 
			
		||||
 | 
			
		||||
    bool WriteRawValue(const Ch* json, size_t length) {
 | 
			
		||||
        PutReserve(*os_, length);
 | 
			
		||||
        GenericStringStream<SourceEncoding> is(json);
 | 
			
		||||
        while (RAPIDJSON_LIKELY(is.Tell() < length)) {
 | 
			
		||||
            RAPIDJSON_ASSERT(is.Peek() != '\0');
 | 
			
		||||
            if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? 
 | 
			
		||||
                Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
 | 
			
		||||
                Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Prefix(Type type) {
 | 
			
		||||
        (void)type;
 | 
			
		||||
        if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
 | 
			
		||||
            Level* level = level_stack_.template Top<Level>();
 | 
			
		||||
            if (level->valueCount > 0) {
 | 
			
		||||
                if (level->inArray) 
 | 
			
		||||
                    os_->Put(','); // add comma if it is not the first element in array
 | 
			
		||||
                else  // in object
 | 
			
		||||
                    os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
 | 
			
		||||
            }
 | 
			
		||||
            if (!level->inArray && level->valueCount % 2 == 0)
 | 
			
		||||
                RAPIDJSON_ASSERT(type == kStringType);  // if it's in object, then even number should be a name
 | 
			
		||||
            level->valueCount++;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            RAPIDJSON_ASSERT(!hasRoot_);    // Should only has one and only one root.
 | 
			
		||||
            hasRoot_ = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Flush the value if it is the top level one.
 | 
			
		||||
    bool EndValue(bool ret) {
 | 
			
		||||
        if (RAPIDJSON_UNLIKELY(level_stack_.Empty()))   // end of json text
 | 
			
		||||
            Flush();
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    OutputStream* os_;
 | 
			
		||||
    internal::Stack<StackAllocator> level_stack_;
 | 
			
		||||
    int maxDecimalPlaces_;
 | 
			
		||||
    bool hasRoot_;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    // Prohibit copy constructor & assignment operator.
 | 
			
		||||
    Writer(const Writer&);
 | 
			
		||||
    Writer& operator=(const Writer&);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Full specialization for StringStream to prevent memory copying
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::WriteInt(int i) {
 | 
			
		||||
    char *buffer = os_->Push(11);
 | 
			
		||||
    const char* end = internal::i32toa(i, buffer);
 | 
			
		||||
    os_->Pop(static_cast<size_t>(11 - (end - buffer)));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
 | 
			
		||||
    char *buffer = os_->Push(10);
 | 
			
		||||
    const char* end = internal::u32toa(u, buffer);
 | 
			
		||||
    os_->Pop(static_cast<size_t>(10 - (end - buffer)));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
 | 
			
		||||
    char *buffer = os_->Push(21);
 | 
			
		||||
    const char* end = internal::i64toa(i64, buffer);
 | 
			
		||||
    os_->Pop(static_cast<size_t>(21 - (end - buffer)));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
 | 
			
		||||
    char *buffer = os_->Push(20);
 | 
			
		||||
    const char* end = internal::u64toa(u, buffer);
 | 
			
		||||
    os_->Pop(static_cast<size_t>(20 - (end - buffer)));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::WriteDouble(double d) {
 | 
			
		||||
    if (internal::Double(d).IsNanOrInf()) {
 | 
			
		||||
        // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
 | 
			
		||||
        if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
 | 
			
		||||
            return false;
 | 
			
		||||
        if (internal::Double(d).IsNan()) {
 | 
			
		||||
            PutReserve(*os_, 3);
 | 
			
		||||
            PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (internal::Double(d).Sign()) {
 | 
			
		||||
            PutReserve(*os_, 9);
 | 
			
		||||
            PutUnsafe(*os_, '-');
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            PutReserve(*os_, 8);
 | 
			
		||||
        PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
 | 
			
		||||
        PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    char *buffer = os_->Push(25);
 | 
			
		||||
    char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
 | 
			
		||||
    os_->Pop(static_cast<size_t>(25 - (end - buffer)));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
 | 
			
		||||
    if (length < 16)
 | 
			
		||||
        return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
 | 
			
		||||
    if (!RAPIDJSON_LIKELY(is.Tell() < length))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    const char* p = is.src_;
 | 
			
		||||
    const char* end = is.head_ + length;
 | 
			
		||||
    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
 | 
			
		||||
    const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
 | 
			
		||||
    if (nextAligned > end)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    while (p != nextAligned)
 | 
			
		||||
        if (*p < 0x20 || *p == '\"' || *p == '\\') {
 | 
			
		||||
            is.src_ = p;
 | 
			
		||||
            return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            os_->PutUnsafe(*p++);
 | 
			
		||||
 | 
			
		||||
    // The rest of string using SIMD
 | 
			
		||||
    static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
 | 
			
		||||
    static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
 | 
			
		||||
    static const char space[16]  = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
 | 
			
		||||
    const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
 | 
			
		||||
    const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
 | 
			
		||||
    const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
 | 
			
		||||
 | 
			
		||||
    for (; p != endAligned; p += 16) {
 | 
			
		||||
        const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
 | 
			
		||||
        const __m128i t1 = _mm_cmpeq_epi8(s, dq);
 | 
			
		||||
        const __m128i t2 = _mm_cmpeq_epi8(s, bs);
 | 
			
		||||
        const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
 | 
			
		||||
        const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
 | 
			
		||||
        unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
 | 
			
		||||
        if (RAPIDJSON_UNLIKELY(r != 0)) {   // some of characters is escaped
 | 
			
		||||
            SizeType len;
 | 
			
		||||
#ifdef _MSC_VER         // Find the index of first escaped
 | 
			
		||||
            unsigned long offset;
 | 
			
		||||
            _BitScanForward(&offset, r);
 | 
			
		||||
            len = offset;
 | 
			
		||||
#else
 | 
			
		||||
            len = static_cast<SizeType>(__builtin_ffs(r) - 1);
 | 
			
		||||
#endif
 | 
			
		||||
            char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
 | 
			
		||||
            for (size_t i = 0; i < len; i++)
 | 
			
		||||
                q[i] = p[i];
 | 
			
		||||
 | 
			
		||||
            p += len;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    is.src_ = p;
 | 
			
		||||
    return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
}
 | 
			
		||||
#elif defined(RAPIDJSON_NEON)
 | 
			
		||||
template<>
 | 
			
		||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
 | 
			
		||||
    if (length < 16)
 | 
			
		||||
        return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
 | 
			
		||||
    if (!RAPIDJSON_LIKELY(is.Tell() < length))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    const char* p = is.src_;
 | 
			
		||||
    const char* end = is.head_ + length;
 | 
			
		||||
    const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
 | 
			
		||||
    const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
 | 
			
		||||
    if (nextAligned > end)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
    while (p != nextAligned)
 | 
			
		||||
        if (*p < 0x20 || *p == '\"' || *p == '\\') {
 | 
			
		||||
            is.src_ = p;
 | 
			
		||||
            return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            os_->PutUnsafe(*p++);
 | 
			
		||||
 | 
			
		||||
    // The rest of string using SIMD
 | 
			
		||||
    const uint8x16_t s0 = vmovq_n_u8('"');
 | 
			
		||||
    const uint8x16_t s1 = vmovq_n_u8('\\');
 | 
			
		||||
    const uint8x16_t s2 = vmovq_n_u8('\b');
 | 
			
		||||
    const uint8x16_t s3 = vmovq_n_u8(32);
 | 
			
		||||
 | 
			
		||||
    for (; p != endAligned; p += 16) {
 | 
			
		||||
        const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
 | 
			
		||||
        uint8x16_t x = vceqq_u8(s, s0);
 | 
			
		||||
        x = vorrq_u8(x, vceqq_u8(s, s1));
 | 
			
		||||
        x = vorrq_u8(x, vceqq_u8(s, s2));
 | 
			
		||||
        x = vorrq_u8(x, vcltq_u8(s, s3));
 | 
			
		||||
 | 
			
		||||
        x = vrev64q_u8(x);                     // Rev in 64
 | 
			
		||||
        uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0);   // extract
 | 
			
		||||
        uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1);  // extract
 | 
			
		||||
 | 
			
		||||
        SizeType len = 0;
 | 
			
		||||
        bool escaped = false;
 | 
			
		||||
        if (low == 0) {
 | 
			
		||||
            if (high != 0) {
 | 
			
		||||
                uint32_t lz = internal::clzll(high);
 | 
			
		||||
                len = 8 + (lz >> 3);
 | 
			
		||||
                escaped = true;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            uint32_t lz = internal::clzll(low);
 | 
			
		||||
            len = lz >> 3;
 | 
			
		||||
            escaped = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (RAPIDJSON_UNLIKELY(escaped)) {   // some of characters is escaped
 | 
			
		||||
            char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
 | 
			
		||||
            for (size_t i = 0; i < len; i++)
 | 
			
		||||
                q[i] = p[i];
 | 
			
		||||
 | 
			
		||||
            p += len;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    is.src_ = p;
 | 
			
		||||
    return RAPIDJSON_LIKELY(is.Tell() < length);
 | 
			
		||||
}
 | 
			
		||||
#endif // RAPIDJSON_NEON
 | 
			
		||||
 | 
			
		||||
RAPIDJSON_NAMESPACE_END
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) || defined(__clang__)
 | 
			
		||||
RAPIDJSON_DIAG_POP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // RAPIDJSON_RAPIDJSON_H_
 | 
			
		||||
		Reference in New Issue
	
	Block a user