正在编写配置文件读取
							parent
							
								
									149db74b2e
								
							
						
					
					
						commit
						ecc00b6fd2
					
				| 
						 | 
					@ -11,6 +11,7 @@ include_directories(external/gli)
 | 
				
			||||||
include_directories(external/imgui)
 | 
					include_directories(external/imgui)
 | 
				
			||||||
include_directories(external/stb)
 | 
					include_directories(external/stb)
 | 
				
			||||||
include_directories(external/tinygltf)
 | 
					include_directories(external/tinygltf)
 | 
				
			||||||
 | 
					include_directories(external/toml)
 | 
				
			||||||
include_directories(external/ktx/include)
 | 
					include_directories(external/ktx/include)
 | 
				
			||||||
include_directories(external/ktx/other_include)
 | 
					include_directories(external/ktx/other_include)
 | 
				
			||||||
include_directories(base)
 | 
					include_directories(base)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,8 @@ const std::string getAssetPath()
 | 
				
			||||||
	return "";
 | 
						return "";
 | 
				
			||||||
#elif defined(VK_EXAMPLE_DATA_DIR)
 | 
					#elif defined(VK_EXAMPLE_DATA_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::filesystem::path dataFilePath;
 | 
				
			||||||
 | 
						std::string dataFile;
 | 
				
			||||||
	if (std::filesystem::exists("./../data/"))
 | 
						if (std::filesystem::exists("./../data/"))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -27,8 +29,12 @@ const std::string getAssetPath()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							std::filesystem::path currentPath = std::filesystem::current_path();
 | 
				
			||||||
 | 
							dataFilePath = VK_EXAMPLE_DATA_DIR;
 | 
				
			||||||
 | 
							dataFilePath = dataFilePath.lexically_relative(currentPath);
 | 
				
			||||||
 | 
							dataFile = dataFilePath.generic_string();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		return std::filesystem::path(VK_EXAMPLE_DATA_DIR);
 | 
							return dataFile;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GLM_FORCE_RADIANS
 | 
					#define GLM_FORCE_RADIANS
 | 
				
			||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
					#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
				
			||||||
 | 
					//#define GLM_FORCE_LEFT_HANDED
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <glm/glm.hpp>
 | 
					#include <glm/glm.hpp>
 | 
				
			||||||
#include <glm/gtc/quaternion.hpp>
 | 
					#include <glm/gtc/quaternion.hpp>
 | 
				
			||||||
#include <glm/gtc/matrix_transform.hpp>
 | 
					#include <glm/gtc/matrix_transform.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,40 +1,24 @@
 | 
				
			||||||
#include "renderConfig.h"
 | 
					#include "renderConfig.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void PlumageConfig::PlumageConfiguration::writrConfigurationToJson()
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void PlumageConfig::PlumageConfiguration::readConfigurationFromToml(std::string configFilePath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	nlohmann::json configJson = nlohmann::json
 | 
						auto config = toml::parse(configFilePath);
 | 
				
			||||||
	{ 
 | 
						
 | 
				
			||||||
		{"width",settings.width},
 | 
						auto& tomlSettings = toml::find(config, "settings");
 | 
				
			||||||
		{"height",settings.height},
 | 
						
 | 
				
			||||||
		{"validation",settings.validation},
 | 
						settings.width = toml::find<uint32_t>(tomlSettings, "width");
 | 
				
			||||||
		{"fullscreen",settings.fullscreen},
 | 
						settings.height = toml::find<uint32_t>(tomlSettings, "height");
 | 
				
			||||||
		{"vsync",settings.vsync},
 | 
						settings.multiSampling = toml::find<bool>(tomlSettings, "multiSampling");
 | 
				
			||||||
		{"multiSampling",settings.multiSampling},
 | 
						auto sampleCount = toml::find<uint32_t>(tomlSettings, "sampleCount");
 | 
				
			||||||
		{"rotateModel",settings.rotateModel},
 | 
						settings.rotateModel = toml::find<bool>(tomlSettings, "rotateModel");
 | 
				
			||||||
		//{"headless",settings.headless},
 | 
						settings.modelRotateSpeed = toml::find<float>(tomlSettings, "modelRotateSpeed");
 | 
				
			||||||
		//{"outputPNGimage",settings.outputPNGimage},
 | 
						settings.startFrameIndex = toml::find<uint32_t>(tomlSettings, "startFrameIndex");
 | 
				
			||||||
		//{"enableSaveToImageSequeue",settings.enableSaveToImageSequeue},
 | 
						settings.endFrameIndex = toml::find<uint32_t>(tomlSettings, "endFrameIndex");
 | 
				
			||||||
		{"outputFrameCount",settings.endFrameIndex},
 | 
						settings.videoFrameRate = toml::find<uint32_t>(tomlSettings, "videoFrameRate");
 | 
				
			||||||
		//{"takeScreenShot",settings.takeScreenShot},
 | 
					 | 
				
			||||||
		{"startFrameCount",settings.endFrameIndex},
 | 
					 | 
				
			||||||
		{"videoFrameRate",settings.videoFrameRate},
 | 
					 | 
				
			||||||
		{"sampleCount",settings.sampleCount},
 | 
					 | 
				
			||||||
		//{"",settings.},
 | 
					 | 
				
			||||||
		//{"",settings.}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	std::ofstream configJsonFile(filePath.configFilePath);
 | 
					 | 
				
			||||||
	std::setw(4);
 | 
					 | 
				
			||||||
	//configJson >> configJsonFile;
 | 
					 | 
				
			||||||
	configJsonFile << configJson;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PlumageConfig::PlumageConfiguration::readConfigurationToJson(std::string configFilePath)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	nlohmann::json configJsonFile;
 | 
					 | 
				
			||||||
	std::ifstream jfile("test.json");
 | 
					 | 
				
			||||||
	jfile >> configJsonFile;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PlumageConfig::PlumageConfiguration::PlumageConfiguration()
 | 
					PlumageConfig::PlumageConfiguration::PlumageConfiguration()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <glm/glm.hpp>
 | 
					#include <glm/glm.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <json.hpp>
 | 
					#include <toml/toml.hpp>
 | 
				
			||||||
#include <vulkan/vulkan.h>
 | 
					#include <vulkan/vulkan.h>
 | 
				
			||||||
#include <VulkanTools.h>
 | 
					#include <VulkanTools.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,38 +18,58 @@ namespace PlumageConfig
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct Settings {
 | 
							struct Settings {
 | 
				
			||||||
			uint32_t width = 1280;
 | 
								
 | 
				
			||||||
			uint32_t height = 720;
 | 
					 | 
				
			||||||
			bool validation = true; // 校验层开关
 | 
								bool validation = true; // 校验层开关
 | 
				
			||||||
			bool fullscreen = false; // 全屏开关
 | 
								//bool fullscreen = false; // 全屏开关
 | 
				
			||||||
			bool vsync = false; // 垂直同步开关
 | 
								bool vsync = false; // 垂直同步开关
 | 
				
			||||||
			bool headless = false; // 无头开关
 | 
								bool headless = false; // 无头开关
 | 
				
			||||||
			bool outputPNGimage = false;
 | 
								bool outputPNGimage = false;
 | 
				
			||||||
 | 
								bool debugMode = true;
 | 
				
			||||||
 | 
								bool cleanUpImageSequece = true; // 图片序列开关(暂时弃用)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								uint32_t width = 1280;
 | 
				
			||||||
 | 
								uint32_t height = 720;
 | 
				
			||||||
			bool multiSampling = false; // 多重采样
 | 
								bool multiSampling = false; // 多重采样
 | 
				
			||||||
			VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT; // 多重采样倍率
 | 
								VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT; // 多重采样倍率
 | 
				
			||||||
			bool rotateModel = true; // 模型自旋转
 | 
								bool rotateModel = true; // 模型自旋转
 | 
				
			||||||
			uint32_t modelRotateSpeed = 2; // 自旋转速度
 | 
								float modelRotateSpeed = 2.0f; // 自旋转速度
 | 
				
			||||||
			//bool enableSaveToImageSequeue = true; // 图片序列开关(暂时弃用)
 | 
								
 | 
				
			||||||
			uint32_t startFrameIndex = 1; // 图片序列开始帧
 | 
								uint32_t startFrameIndex = 1; // 图片序列开始帧
 | 
				
			||||||
			uint32_t endFrameIndex = 50; // 图片序列结束帧
 | 
								uint32_t endFrameIndex = 50; // 图片序列结束帧
 | 
				
			||||||
			uint32_t videoFrameRate = 25; // 视频帧率
 | 
								uint32_t videoFrameRate = 25; // 视频帧率
 | 
				
			||||||
			uint32_t selectedPhysicalDeviceIndex = 0;
 | 
								uint32_t selectedPhysicalDeviceIndex = 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			float fovX = 1.f;
 | 
								float fovX = 1.f;
 | 
				
			||||||
			float fovY = 1.f;
 | 
								float fovY = 1.f;
 | 
				
			||||||
			float cX = 2.f;
 | 
								float cX = 2.f;
 | 
				
			||||||
			float cY = 0.f;
 | 
								float cY = 0.f;
 | 
				
			||||||
			glm::vec3 bottomCenter = glm::vec3(0.f,0.f,-6.f);
 | 
								std::vector<float> bottomCenter = { 0.f,0.f,-6.f };
 | 
				
			||||||
			glm::vec3 bottomNormal = glm::vec3(0.f,1.0f,0.f);
 | 
								std::vector<float> bottomNormal = { 0.f,1.0f,0.f };
 | 
				
			||||||
 | 
								std::vector<std::vector<float>> cameraTracks = { {0.f,0.f,-6.f},{1.f,0.f,-3.f} };
 | 
				
			||||||
 | 
								std::vector<std::vector<float>> cameraAngle = { {0.f,0.f,0.f},{45.f,0.f,0.f} };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}settings;
 | 
							}settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct RenderSettings
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								uint32_t width = 1280;
 | 
				
			||||||
 | 
								uint32_t height = 720;
 | 
				
			||||||
 | 
								bool multiSampling = false; // 多重采样
 | 
				
			||||||
 | 
								uint32_t sampleCount = VK_SAMPLE_COUNT_4_BIT; // 多重采样倍率
 | 
				
			||||||
 | 
								bool rotateModel = true; // 模型自旋转
 | 
				
			||||||
 | 
								float modelRotateSpeed = 2.0f; // 自旋转速度
 | 
				
			||||||
 | 
								uint32_t startFrameIndex = 1; // 图片序列开始帧
 | 
				
			||||||
 | 
								uint32_t endFrameIndex = 50; // 图片序列结束帧
 | 
				
			||||||
 | 
								uint32_t videoFrameRate = 25; // 视频帧率
 | 
				
			||||||
 | 
								uint32_t selectedPhysicalDeviceIndex = 7;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct FilePath
 | 
							struct FilePath
 | 
				
			||||||
		{	//model path
 | 
							{	//model path
 | 
				
			||||||
			std::string glTFModelFilePath = getAssetPath() + "models/DamagedHelmet/kettle.glb";
 | 
								std::string glTFModelFilePath = getAssetPath() + "models/DamagedHelmet/DamagedHelmet.gltf";
 | 
				
			||||||
			std::string modelVertShaderPath = getAssetPath() + "buster_drone/shaders/glsl/mesh.vert.spv";
 | 
								std::string modelVertShaderPath = getAssetPath() + "buster_drone/shaders/glsl/mesh.vert.spv";
 | 
				
			||||||
			std::string modelFragShaderPath = getAssetPath() + "buster_drone/shaders/glsl/mesh.frag.spv";
 | 
								std::string modelFragShaderPath = getAssetPath() + "buster_drone/shaders/glsl/mesh.frag.spv";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,11 +78,11 @@ namespace PlumageConfig
 | 
				
			||||||
			std::string uiFragShaderPath = getAssetPath() + "shaders/ui.frag.spv";
 | 
								std::string uiFragShaderPath = getAssetPath() + "shaders/ui.frag.spv";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// skybox path
 | 
								// skybox path
 | 
				
			||||||
			std::string skyboxModleFilePath = getAssetPath() + "models/cube.gltf";
 | 
								std::string skyboxModelFilePath = getAssetPath() + "models/cube.gltf";
 | 
				
			||||||
			std::string skyboxVertShaderPath = getAssetPath() + "shaders/skybox.vert.spv";
 | 
								std::string skyboxVertShaderPath = getAssetPath() + "shaders/skybox.vert.spv";
 | 
				
			||||||
			std::string skyboxFragShaderPath = getAssetPath() + "shaders/skybox.frag.spv";
 | 
								std::string skyboxFragShaderPath = getAssetPath() + "shaders/skybox.frag.spv";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			std::string iblTexturesFilePath = getAssetPath() + "textures/hdr/gcanyon_cube.ktx";
 | 
								//std::string iblTexturesFilePath = getAssetPath() + "textures/hdr/gcanyon_cube.ktx";
 | 
				
			||||||
			//tonemapping
 | 
								//tonemapping
 | 
				
			||||||
			std::string tonemappingVertShaderPath = getAssetPath() + "shaders/genbrdflut.vert.spv";
 | 
								std::string tonemappingVertShaderPath = getAssetPath() + "shaders/genbrdflut.vert.spv";
 | 
				
			||||||
			std::string tonemappingEnableFragShaderPath = getAssetPath() + "shaders/tonemapping_enable.frag.spv";
 | 
								std::string tonemappingEnableFragShaderPath = getAssetPath() + "shaders/tonemapping_enable.frag.spv";
 | 
				
			||||||
| 
						 | 
					@ -79,7 +99,7 @@ namespace PlumageConfig
 | 
				
			||||||
			std::string brdfVertShaderPath = getAssetPath() + "shaders/genbrdflut.vert.spv";
 | 
								std::string brdfVertShaderPath = getAssetPath() + "shaders/genbrdflut.vert.spv";
 | 
				
			||||||
			std::string brdfFragShaderPath = getAssetPath() + "shaders/genbrdflut.frag.spv";
 | 
								std::string brdfFragShaderPath = getAssetPath() + "shaders/genbrdflut.frag.spv";
 | 
				
			||||||
			// environment map texture
 | 
								// environment map texture
 | 
				
			||||||
			std::string envMapFilePath = getAssetPath() + "environments/metro_noord_4k_hdr16f_cube.ktx";
 | 
								std::string envMapFilePath = getAssetPath() + "environments/brown_photostudio_02_4k_hdr16f_cube.ktx";
 | 
				
			||||||
			std::string emptyEnvmapFilePath = getAssetPath() + "textures/empty.ktx";
 | 
								std::string emptyEnvmapFilePath = getAssetPath() + "textures/empty.ktx";
 | 
				
			||||||
			// pbr shader
 | 
								// pbr shader
 | 
				
			||||||
			std::string pbrVertShaderPath = getAssetPath() + "shaders/pbr.vert.spv";
 | 
								std::string pbrVertShaderPath = getAssetPath() + "shaders/pbr.vert.spv";
 | 
				
			||||||
| 
						 | 
					@ -98,14 +118,19 @@ namespace PlumageConfig
 | 
				
			||||||
			// script file path
 | 
								// script file path
 | 
				
			||||||
			std::string image2videoBatFilePath = getAssetPath() + "script/image2video.bat";
 | 
								std::string image2videoBatFilePath = getAssetPath() + "script/image2video.bat";
 | 
				
			||||||
			std::string image2videoShFilePath = getAssetPath() + "script/image2video.sh";
 | 
								std::string image2videoShFilePath = getAssetPath() + "script/image2video.sh";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								std::string hdr2ktxBatFilePath = getAssetPath() + "script/hdr2ktxBatFilePath.bat";
 | 
				
			||||||
 | 
								std::string hdr2ktxShFilePath = getAssetPath() + "script/hdr2ktxShFilePath.sh";
 | 
				
			||||||
			// 配置文件路径,命令行传入后保存在这
 | 
								// 配置文件路径,命令行传入后保存在这
 | 
				
			||||||
			std::string configFilePath = getAssetPath() + "config/config.json";
 | 
								std::string configFilePath = getAssetPath() + "config/config.toml";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		} filePath;
 | 
							} filePath;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		void writrConfigurationToJson();
 | 
							void writrConfigurationToJson();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void readConfigurationToJson(std::string configFilePath);
 | 
							void readConfigurationFromToml(std::string configFilePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							void convertIntToVkSampleCount(uint32_t sampleCount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		PlumageConfiguration();
 | 
							PlumageConfiguration();
 | 
				
			||||||
		~PlumageConfiguration();
 | 
							~PlumageConfiguration();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,26 +342,44 @@ void VulkanExampleBase::renderLoop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VulkanExampleBase::VulkanExampleBase()
 | 
					VulkanExampleBase::VulkanExampleBase()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char* numConvPtr;
 | 
						//char* numConvPtr;
 | 
				
			||||||
	// Parse command line arguments
 | 
						// Parse command line arguments
 | 
				
			||||||
	for (size_t i = 0; i < args.size(); i++)
 | 
						for (size_t i = 0; i < args.size(); i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (args[i] == std::string("-validation")) {
 | 
							if ((args[i] == std::string("--config"))) 
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::string configFile = args[i + 1];
 | 
				
			||||||
 | 
								if (std::filesystem::exists(configFile))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout << "loading config file from:  " << configFile << std::endl;
 | 
				
			||||||
 | 
									filePath.configFilePath = configFile;
 | 
				
			||||||
 | 
									settings.debugMode = false;
 | 
				
			||||||
 | 
									settings.validation = false;
 | 
				
			||||||
 | 
									settings.cleanUpImageSequece = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout << "config file no exists, please check file path" << std::endl;
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (settings.debugMode)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::cout << "=====================================WARNNING=================================" << std::endl;
 | 
				
			||||||
 | 
									std::cout << "debug Mode enabled,config file with command line argument will be ignore " << std::endl;
 | 
				
			||||||
 | 
									std::cout << "validation layer force to be enabled" << std::endl;
 | 
				
			||||||
 | 
									std::cout << "image sequece will not to be cleaned up after viedo generated" << std::endl;
 | 
				
			||||||
				settings.validation = true;
 | 
									settings.validation = true;
 | 
				
			||||||
 | 
									settings.cleanUpImageSequece = false;
 | 
				
			||||||
 | 
									std::cout << "=====================================WARNNING=================================" << std::endl;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		if (args[i] == std::string("-vsync")) {
 | 
								else
 | 
				
			||||||
			settings.vsync = true;
 | 
								{
 | 
				
			||||||
 | 
									std::cout << " [error] no config file path input with command line arguments" << std::endl;
 | 
				
			||||||
 | 
									exit(-1);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		if ((args[i] == std::string("-f")) || (args[i] == std::string("--fullscreen"))) {
 | 
					 | 
				
			||||||
			settings.fullscreen = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if ((args[i] == std::string("-w")) || (args[i] == std::string("--width"))) {
 | 
					 | 
				
			||||||
			uint32_t w = strtol(args[i + 1], &numConvPtr, 10);
 | 
					 | 
				
			||||||
			if (numConvPtr != args[i + 1]) { settings.width = w; };
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if ((args[i] == std::string("-h")) || (args[i] == std::string("--height"))) {
 | 
					 | 
				
			||||||
			uint32_t h = strtol(args[i + 1], &numConvPtr, 10);
 | 
					 | 
				
			||||||
			if (numConvPtr != args[i + 1]) { settings.height = h; };
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,11 +17,15 @@
 | 
				
			||||||
#define GLM_FORCE_RADIANS
 | 
					#define GLM_FORCE_RADIANS
 | 
				
			||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
					#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
				
			||||||
#define GLM_ENABLE_EXPERIMENTAL
 | 
					#define GLM_ENABLE_EXPERIMENTAL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#define GLM_FORCE_LEFT_HANDED
 | 
				
			||||||
#include <glm/glm.hpp>
 | 
					#include <glm/glm.hpp>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <numeric>
 | 
					#include <numeric>
 | 
				
			||||||
 | 
					#include <filesystem>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "renderConfig.h"
 | 
					#include "renderConfig.h"
 | 
				
			||||||
#include "vulkan/vulkan.h"
 | 
					#include "vulkan/vulkan.h"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,11 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    "setting":{
 | 
					  "endFrameIndex": 50,
 | 
				
			||||||
        "width":1280,
 | 
					  "height": 720,
 | 
				
			||||||
        "height":720
 | 
					  "multiSampling": false,
 | 
				
			||||||
    },
 | 
					  "rotateModel": true,
 | 
				
			||||||
    "filePath":{
 | 
					  "sampleCount": 4,
 | 
				
			||||||
        "glTFModelFilePath":"models/DamagedHelmet/DamagedHelmet.gltf",
 | 
					  "selectedPhysicalDeviceIndex": 7,
 | 
				
			||||||
        "envMapFilePath":"environments/metro_noord_4k_hdr16f_cube.ktx",
 | 
					  "startFrameIndex": 1,
 | 
				
			||||||
        "imageOutputPath":"output/imageSequence",
 | 
					  "videoFrameRate": 25,
 | 
				
			||||||
        "videoOutputPath":"output/video"
 | 
					  "width": 1280
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,63 @@
 | 
				
			||||||
 | 
					[settings]
 | 
				
			||||||
 | 
					width =1280
 | 
				
			||||||
 | 
					height =720
 | 
				
			||||||
 | 
					multiSampling =false
 | 
				
			||||||
 | 
					sampleCount =4
 | 
				
			||||||
 | 
					rotateModel =true
 | 
				
			||||||
 | 
					modelRotateSpeed =2.0
 | 
				
			||||||
 | 
					startFrameIndex =1
 | 
				
			||||||
 | 
					endFrameIndex =50
 | 
				
			||||||
 | 
					videoFrameRate =25
 | 
				
			||||||
 | 
					selectedPhysicalDeviceIndex =7
 | 
				
			||||||
 | 
					[settings.camera]
 | 
				
			||||||
 | 
					fovX =1.0
 | 
				
			||||||
 | 
					fovY =1.0
 | 
				
			||||||
 | 
					cX =2.0
 | 
				
			||||||
 | 
					cY =0.0
 | 
				
			||||||
 | 
					bottomCenter =[0.0,0.0,-6.0]  
 | 
				
			||||||
 | 
					bottomNormal =[0.0,1.0,0.0]
 | 
				
			||||||
 | 
					cameraTracks =[[0.0,0.0,-6.0],[1.0,0.0,-3.0]]
 | 
				
			||||||
 | 
					cameraAngle =[[0.0,0.0,0.0],[45.0,0.0,0.0]]
 | 
				
			||||||
 | 
					[settings.debug]
 | 
				
			||||||
 | 
					validation = true
 | 
				
			||||||
 | 
					vsync = false
 | 
				
			||||||
 | 
					headless = false
 | 
				
			||||||
 | 
					outputPNGimage = false
 | 
				
			||||||
 | 
					debugMode = true
 | 
				
			||||||
 | 
					[FilePath]
 | 
				
			||||||
 | 
					glTFModelFilePath ="./data/models/DamagedHelmet/DamagedHelmet.gltf"
 | 
				
			||||||
 | 
					envMapFilePath ="./data/environments/metro_noord_4k_hdr16f_cube.ktx"
 | 
				
			||||||
 | 
					imageOutputPath ="./data/output/imageSequence"
 | 
				
			||||||
 | 
					videoOutputPath ="./data/output/video"
 | 
				
			||||||
 | 
					configFilePath ="./data/config/config.toml"
 | 
				
			||||||
 | 
					[FilePath.ui]
 | 
				
			||||||
 | 
					uiVertShaderPath ="./data/shaders/ui.vert.spv"
 | 
				
			||||||
 | 
					uiFragShaderPath ="./data/shaders/ui.frag.spv"
 | 
				
			||||||
 | 
					[FilePath.skybox]
 | 
				
			||||||
 | 
					skyboxModelFilePath ="./data/models/cube.gltf"
 | 
				
			||||||
 | 
					skyboxVertShaderPath ="./data/shaders/skybox.vert.spv"
 | 
				
			||||||
 | 
					skyboxFragShaderPath ="./data/shaders/skybox.frag.spv"
 | 
				
			||||||
 | 
					[FilePath.tonemapping]
 | 
				
			||||||
 | 
					[FilePath.ibl]
 | 
				
			||||||
 | 
					[FilePath.pbr]
 | 
				
			||||||
 | 
					[FilePath.image2video]
 | 
				
			||||||
 | 
					[FilePath.hdr2ktx]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,88 @@
 | 
				
			||||||
 | 
					version: 2.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  test_suite:
 | 
				
			||||||
 | 
					    docker:
 | 
				
			||||||
 | 
					      - image: cimg/go:1.16
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - checkout
 | 
				
			||||||
 | 
					      - run:
 | 
				
			||||||
 | 
					          command: |
 | 
				
			||||||
 | 
					              g++ --version
 | 
				
			||||||
 | 
					              cd tests/
 | 
				
			||||||
 | 
					              g++ -std=c++11 -O2 -Wall -Wextra -Werror -I../ check_toml_test.cpp -o check_toml_test
 | 
				
			||||||
 | 
					              export PATH=$(pwd):${PATH}
 | 
				
			||||||
 | 
					              git clone --depth 1 --branch v1.3.0 https://github.com/BurntSushi/toml-test.git
 | 
				
			||||||
 | 
					              cd toml-test/
 | 
				
			||||||
 | 
					              go install -v ./cmd/toml-test
 | 
				
			||||||
 | 
					              cd -
 | 
				
			||||||
 | 
					              toml-test check_toml_test
 | 
				
			||||||
 | 
					#               go clean -modcache
 | 
				
			||||||
 | 
					#               go get github.com/BurntSushi/toml-test/cmd/toml-test
 | 
				
			||||||
 | 
					#               $GOPATH/bin/toml-test ./check_toml_test
 | 
				
			||||||
 | 
					  test_serialization:
 | 
				
			||||||
 | 
					    docker:
 | 
				
			||||||
 | 
					      - image: circleci/buildpack-deps:bionic
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - checkout
 | 
				
			||||||
 | 
					      - run:
 | 
				
			||||||
 | 
					          command: |
 | 
				
			||||||
 | 
					              g++ --version
 | 
				
			||||||
 | 
					              cd tests/
 | 
				
			||||||
 | 
					              g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check_serialization.cpp -o check_serialization
 | 
				
			||||||
 | 
					              git clone https://github.com/BurntSushi/toml-test.git
 | 
				
			||||||
 | 
					              cp check_serialization toml-test/tests/valid
 | 
				
			||||||
 | 
					              cd toml-test/tests/valid
 | 
				
			||||||
 | 
					              for f in $(ls ./*.toml);
 | 
				
			||||||
 | 
					                do echo "==> ${f}";
 | 
				
			||||||
 | 
					                cat ${f};
 | 
				
			||||||
 | 
					                echo "---------------------------------------";
 | 
				
			||||||
 | 
					                ./check_serialization ${f};
 | 
				
			||||||
 | 
					                if [ $? -ne 0 ] ; then
 | 
				
			||||||
 | 
					                  exit 1
 | 
				
			||||||
 | 
					                fi
 | 
				
			||||||
 | 
					                echo "=======================================";
 | 
				
			||||||
 | 
					              done
 | 
				
			||||||
 | 
					  output_result:
 | 
				
			||||||
 | 
					    docker:
 | 
				
			||||||
 | 
					      - image: circleci/buildpack-deps:bionic
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - checkout
 | 
				
			||||||
 | 
					      - run:
 | 
				
			||||||
 | 
					          command: |
 | 
				
			||||||
 | 
					              g++ --version
 | 
				
			||||||
 | 
					              cd tests/
 | 
				
			||||||
 | 
					              g++ -std=c++11 -O2 -Wall -Wextra -Wpedantic -Werror -I../ check.cpp -o check
 | 
				
			||||||
 | 
					              git clone https://github.com/BurntSushi/toml-test.git
 | 
				
			||||||
 | 
					              cp check toml-test/tests/invalid
 | 
				
			||||||
 | 
					              cp check toml-test/tests/valid
 | 
				
			||||||
 | 
					              cd toml-test/tests/invalid
 | 
				
			||||||
 | 
					              for f in $(ls ./*.toml);
 | 
				
			||||||
 | 
					                do echo "==> ${f}";
 | 
				
			||||||
 | 
					                cat ${f};
 | 
				
			||||||
 | 
					                echo "---------------------------------------";
 | 
				
			||||||
 | 
					                ./check ${f} invalid;
 | 
				
			||||||
 | 
					                if [ $? -ne 0 ] ; then
 | 
				
			||||||
 | 
					                  exit 1
 | 
				
			||||||
 | 
					                fi
 | 
				
			||||||
 | 
					                echo "=======================================";
 | 
				
			||||||
 | 
					              done
 | 
				
			||||||
 | 
					              cd ../valid
 | 
				
			||||||
 | 
					              for f in $(ls ./*.toml);
 | 
				
			||||||
 | 
					                do echo "==> ${f}";
 | 
				
			||||||
 | 
					                cat ${f};
 | 
				
			||||||
 | 
					                echo "---------------------------------------";
 | 
				
			||||||
 | 
					                ./check ${f} valid;
 | 
				
			||||||
 | 
					                if [ $? -ne 0 ] ; then
 | 
				
			||||||
 | 
					                  exit 1
 | 
				
			||||||
 | 
					                fi
 | 
				
			||||||
 | 
					                echo "=======================================";
 | 
				
			||||||
 | 
					              done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					workflows:
 | 
				
			||||||
 | 
					  version: 2.1
 | 
				
			||||||
 | 
					  test:
 | 
				
			||||||
 | 
					    jobs:
 | 
				
			||||||
 | 
					      - test_suite
 | 
				
			||||||
 | 
					      - test_serialization
 | 
				
			||||||
 | 
					      - output_result
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					FROM gcr.io/oss-fuzz-base/base-builder
 | 
				
			||||||
 | 
					RUN apt-get update && apt-get install -y make autoconf automake libtool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY . $SRC/toml11
 | 
				
			||||||
 | 
					COPY .clusterfuzzlite/build.sh $SRC/build.sh
 | 
				
			||||||
 | 
					WORKDIR $SRC/toml11
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					# ClusterFuzzLite set up
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This folder contains a fuzzing set for [ClusterFuzzLite](https://google.github.io/clusterfuzzlite).
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					#!/bin/bash -eu
 | 
				
			||||||
 | 
					# Copy fuzzer executable to $OUT/
 | 
				
			||||||
 | 
					$CXX $CFLAGS $LIB_FUZZING_ENGINE \
 | 
				
			||||||
 | 
					  $SRC/toml11/.clusterfuzzlite/parse_fuzzer.cpp \
 | 
				
			||||||
 | 
					  -o $OUT/parse_fuzzer \
 | 
				
			||||||
 | 
					  -I$SRC/toml11/
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 | 
				
			||||||
 | 
					  std::string s(reinterpret_cast<const char *>(data), size);
 | 
				
			||||||
 | 
					  std::istringstream iss(s);
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const auto ref = toml::parse(iss);
 | 
				
			||||||
 | 
					  } catch (...) {
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					language: c++
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					root = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[*]
 | 
				
			||||||
 | 
					indent_style = space
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[CMakeLists.txt]
 | 
				
			||||||
 | 
					indent_size = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[*.{c,h}*]
 | 
				
			||||||
 | 
					indent_size = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[*.{md,yml}]
 | 
				
			||||||
 | 
					indent_size = 2
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					name: ClusterFuzzLite PR fuzzing
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  workflow_dispatch:
 | 
				
			||||||
 | 
					  pull_request:
 | 
				
			||||||
 | 
					    branches: [ master ]
 | 
				
			||||||
 | 
					permissions: read-all
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  PR:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      fail-fast: false
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        sanitizer: [address]
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - name: Build Fuzzers (${{ matrix.sanitizer }})
 | 
				
			||||||
 | 
					      id: build
 | 
				
			||||||
 | 
					      uses: google/clusterfuzzlite/actions/build_fuzzers@v1
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        sanitizer: ${{ matrix.sanitizer }}
 | 
				
			||||||
 | 
					        language: c++
 | 
				
			||||||
 | 
					        bad-build-check: false
 | 
				
			||||||
 | 
					    - name: Run Fuzzers (${{ matrix.sanitizer }})
 | 
				
			||||||
 | 
					      id: run
 | 
				
			||||||
 | 
					      uses: google/clusterfuzzlite/actions/run_fuzzers@v1
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					        fuzz-seconds: 240
 | 
				
			||||||
 | 
					        mode: 'code-change'
 | 
				
			||||||
 | 
					        report-unreproducible-crashes: false
 | 
				
			||||||
 | 
					        sanitizer: ${{ matrix.sanitizer }}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,280 @@
 | 
				
			||||||
 | 
					name: build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on: [push, pull_request]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  build-linux-gcc:
 | 
				
			||||||
 | 
					    runs-on: Ubuntu-22.04
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        compiler: ['g++-12', 'g++-11', 'g++-10', 'g++-9']
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            sudo apt-add-repository ppa:ubuntu-toolchain-r/test
 | 
				
			||||||
 | 
					            sudo apt-get update
 | 
				
			||||||
 | 
					            sudo apt-get install libboost-test-dev
 | 
				
			||||||
 | 
					            sudo apt-get install language-pack-fr # test serializer w/ locale
 | 
				
			||||||
 | 
					            sudo apt-get install ${{ matrix.compiler }}
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					  build-linux-clang:
 | 
				
			||||||
 | 
					    runs-on: Ubuntu-22.04
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        compiler: ['15', '14', '13', '12', '11']
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					        exclude:
 | 
				
			||||||
 | 
					            - {compiler: '14', standard: '20'} # to avoid using gcc-13 libstdc++
 | 
				
			||||||
 | 
					            - {compiler: '13', standard: '20'} # with older clang
 | 
				
			||||||
 | 
					            - {compiler: '12', standard: '20'}
 | 
				
			||||||
 | 
					            - {compiler: '11', standard: '20'}
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            sudo apt-add-repository ppa:ubuntu-toolchain-r/test
 | 
				
			||||||
 | 
					            sudo apt-get update
 | 
				
			||||||
 | 
					            sudo apt-get install libboost-test-dev
 | 
				
			||||||
 | 
					            sudo apt-get install language-pack-fr # test serializer w/ locale
 | 
				
			||||||
 | 
					            sudo apt-get install clang-${{ matrix.compiler }}
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_C_COMPILER=clang-${{ matrix.compiler }} -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-linux-old-gcc:
 | 
				
			||||||
 | 
					    runs-on: Ubuntu-20.04
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        compiler: ['g++-8', 'g++-7']
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					        exclude:
 | 
				
			||||||
 | 
					            - {compiler: 'g++-7', standard: '20'}
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            sudo apt-add-repository ppa:ubuntu-toolchain-r/test
 | 
				
			||||||
 | 
					            sudo apt-get update
 | 
				
			||||||
 | 
					            sudo apt-get install libboost-test-dev
 | 
				
			||||||
 | 
					            sudo apt-get install language-pack-fr # test serializer w/ locale
 | 
				
			||||||
 | 
					            sudo apt-get install ${{ matrix.compiler }}
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            if [[ "${{ matrix.compiler }}" == "g++-8" && ( "${{ matrix.standard }}" == "17" || "${{ matrix.standard }}" == "20" ) ]] ; then
 | 
				
			||||||
 | 
					                cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_REQUIRE_FILESYSTEM_LIBRARY=ON -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					            fi
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-linux-old-clang:
 | 
				
			||||||
 | 
					    runs-on: Ubuntu-20.04
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        compiler: ['10', '9', '8', '7', '6.0']
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					        exclude:
 | 
				
			||||||
 | 
					            - {compiler: '6.0', standard: '20'}
 | 
				
			||||||
 | 
					            - {compiler: '7',   standard: '20'}
 | 
				
			||||||
 | 
					            - {compiler: '8',   standard: '20'}
 | 
				
			||||||
 | 
					            - {compiler: '9',   standard: '20'}
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            sudo apt-add-repository ppa:ubuntu-toolchain-r/test
 | 
				
			||||||
 | 
					            sudo apt-get update
 | 
				
			||||||
 | 
					            sudo apt-get install libboost-test-dev
 | 
				
			||||||
 | 
					            sudo apt-get install language-pack-fr # test serializer w/ locale
 | 
				
			||||||
 | 
					            sudo apt-get install clang-${{ matrix.compiler }}
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_C_COMPILER=clang-${{ matrix.compiler }} -DCMAKE_CXX_COMPILER=clang++-${{ matrix.compiler }} -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#  build-osx-13-arm64:
 | 
				
			||||||
 | 
					#    runs-on: macos-13-arm64
 | 
				
			||||||
 | 
					#    strategy:
 | 
				
			||||||
 | 
					#      matrix:
 | 
				
			||||||
 | 
					#        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					#        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					#    steps:
 | 
				
			||||||
 | 
					#      - name: Checkout
 | 
				
			||||||
 | 
					#        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					#        with:
 | 
				
			||||||
 | 
					#          submodules: true
 | 
				
			||||||
 | 
					#      - name: Install
 | 
				
			||||||
 | 
					#        run: |
 | 
				
			||||||
 | 
					#            brew install boost
 | 
				
			||||||
 | 
					#      - name: Configure
 | 
				
			||||||
 | 
					#        run: |
 | 
				
			||||||
 | 
					#            mkdir build && cd build
 | 
				
			||||||
 | 
					#            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					#      - name: Build
 | 
				
			||||||
 | 
					#        run: |
 | 
				
			||||||
 | 
					#            cd build && cmake --build .
 | 
				
			||||||
 | 
					#      - name: Test
 | 
				
			||||||
 | 
					#        run: |
 | 
				
			||||||
 | 
					#            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-osx-13:
 | 
				
			||||||
 | 
					    runs-on: macos-13
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            brew install boost
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-osx-12:
 | 
				
			||||||
 | 
					    runs-on: macos-12
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            brew install boost
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-osx-11:
 | 
				
			||||||
 | 
					    runs-on: macos-11
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            brew install boost
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            mkdir build && cd build
 | 
				
			||||||
 | 
					            cmake .. -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && cmake --build .
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cd build && ctest --output-on-failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-windows-msvc:
 | 
				
			||||||
 | 
					    runs-on: windows-2022
 | 
				
			||||||
 | 
					    strategy:
 | 
				
			||||||
 | 
					      matrix:
 | 
				
			||||||
 | 
					        standard: ['11', '14', '17', '20']
 | 
				
			||||||
 | 
					        config: ['Release', 'Debug']
 | 
				
			||||||
 | 
					        unreleased: ['ON', 'OFF']
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout
 | 
				
			||||||
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: true
 | 
				
			||||||
 | 
					      - name: Install
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            (New-Object System.Net.WebClient).DownloadFile("https://github.com/actions/boost-versions/releases/download/1.72.0-20200608.4/boost-1.72.0-win32-msvc14.2-x86_64.tar.gz", "$env:TEMP\\boost.tar.gz")
 | 
				
			||||||
 | 
					            7z.exe x "$env:TEMP\\boost.tar.gz" -o"$env:TEMP\\boostArchive" -y | Out-Null
 | 
				
			||||||
 | 
					            7z.exe x "$env:TEMP\\boostArchive" -o"$env:TEMP\\boost" -y | Out-Null
 | 
				
			||||||
 | 
					            Push-Location -Path "$env:TEMP\\boost"
 | 
				
			||||||
 | 
					            Invoke-Expression .\\setup.ps1
 | 
				
			||||||
 | 
					      - uses: ilammy/msvc-dev-cmd@v1
 | 
				
			||||||
 | 
					      - name: Configure
 | 
				
			||||||
 | 
					        shell: cmd
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            file --mime-encoding tests/test_literals.cpp
 | 
				
			||||||
 | 
					            mkdir build
 | 
				
			||||||
 | 
					            cd build
 | 
				
			||||||
 | 
					            cmake ../ -G "NMake Makefiles" -Dtoml11_BUILD_TEST=ON -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DBoost_NO_BOOST_CMAKE=ON -DBOOST_ROOT="C:\\hostedtoolcache\\windows\\Boost\\1.72.0\\x86_64" -DTOML11_USE_UNRELEASED_TOML_FEATURES=${{ matrix.unreleased }}
 | 
				
			||||||
 | 
					      - name: Build
 | 
				
			||||||
 | 
					        working-directory: ./build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            cmake --build . --config "${{ matrix.config }}"
 | 
				
			||||||
 | 
					      - name: Test
 | 
				
			||||||
 | 
					        working-directory: ./build
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					            file --mime-encoding tests/toml/tests/example.toml
 | 
				
			||||||
 | 
					            file --mime-encoding tests/toml/tests/fruit.toml
 | 
				
			||||||
 | 
					            file --mime-encoding tests/toml/tests/hard_example.toml
 | 
				
			||||||
 | 
					            file --mime-encoding tests/toml/tests/hard_example_unicode.toml
 | 
				
			||||||
 | 
					            ctest --build-config "${{ matrix.config }}" --output-on-failure
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					build/*
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,121 @@
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.5)
 | 
				
			||||||
 | 
					enable_testing()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(toml11 VERSION 3.8.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(toml11_BUILD_TEST "Build toml tests" OFF)
 | 
				
			||||||
 | 
					option(toml11_INSTALL "Install CMake targets during install step." ON)
 | 
				
			||||||
 | 
					option(toml11_TEST_WITH_ASAN  "use LLVM address sanitizer" OFF)
 | 
				
			||||||
 | 
					option(toml11_TEST_WITH_UBSAN "use LLVM undefined behavior sanitizer" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					option(TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    "use features in toml-lang/toml master while testing" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(CheckCXXCompilerFlag)
 | 
				
			||||||
 | 
					if("${CMAKE_VERSION}" VERSION_GREATER 3.1)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Boolean specifying whether compiler specific extensions are requested.")
 | 
				
			||||||
 | 
					    if(NOT DEFINED CMAKE_CXX_STANDARD)
 | 
				
			||||||
 | 
					        message(FATAL_ERROR "CMAKE_CXX_STANDARD is not defined. \
 | 
				
			||||||
 | 
					The C++ standard whose features are requested to *build* all targets. \
 | 
				
			||||||
 | 
					Remember that toml11 is a header only library that does NOT require compilation to use.")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "Boolean describing whether the value of CXX_STANDARD is a requirement.")
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
					    # Manually check for C++11 compiler flag.
 | 
				
			||||||
 | 
					    CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
 | 
				
			||||||
 | 
					    CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
 | 
				
			||||||
 | 
					    CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_GNU11)
 | 
				
			||||||
 | 
					    CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_GNU0X)
 | 
				
			||||||
 | 
					    if(COMPILER_SUPPORTS_CXX11)
 | 
				
			||||||
 | 
					        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 | 
				
			||||||
 | 
					    elseif(COMPILER_SUPPORTS_CXXOX)
 | 
				
			||||||
 | 
					        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
 | 
				
			||||||
 | 
					    elseif(COMPILER_SUPPORTS_GNU11)
 | 
				
			||||||
 | 
					        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
 | 
				
			||||||
 | 
					    elseif(COMPILER_SUPPORTS_GNU0X)
 | 
				
			||||||
 | 
					        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
 | 
				
			||||||
 | 
					    else()
 | 
				
			||||||
 | 
					        if(MSVC)
 | 
				
			||||||
 | 
					            if(MSVC_VERSION LESS 1900)
 | 
				
			||||||
 | 
					                message(SEND_ERROR "MSVC < 14.0 is not supported. Please update your compiler or use mingw")
 | 
				
			||||||
 | 
					            endif()
 | 
				
			||||||
 | 
					        else()
 | 
				
			||||||
 | 
					            message(SEND_ERROR "The ${CMAKE_CXX_COMPILER} compiler lacks C++11 support. Use another compiler.")
 | 
				
			||||||
 | 
					        endif()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(MSVC)
 | 
				
			||||||
 | 
					#     add_definitions("/Zc:__cplusplus")  # define __cplusplus value correctly
 | 
				
			||||||
 | 
					    add_definitions("/utf-8")           # enable to use u8"" literal
 | 
				
			||||||
 | 
					    if(MSVC_VERSION LESS 1910)
 | 
				
			||||||
 | 
					        message(STATUS "MSVC < 1910. DEFINE_CONVERSION_NON_INTRUSIVE is disabled")
 | 
				
			||||||
 | 
					        add_definitions(-DTOML11_WITHOUT_DEFINE_NON_INTRUSIVE)
 | 
				
			||||||
 | 
					    elseif(MSVC_VERSION LESS 1920)
 | 
				
			||||||
 | 
					        add_definitions("/experimental:preprocessor") # MSVC 2017
 | 
				
			||||||
 | 
					    else()
 | 
				
			||||||
 | 
					        add_definitions("/Zc:preprocessor") # MSVC 2019
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set some common directories
 | 
				
			||||||
 | 
					include(GNUInstallDirs)
 | 
				
			||||||
 | 
					set(toml11_install_cmake_dir         ${CMAKE_INSTALL_LIBDIR}/cmake/toml11)
 | 
				
			||||||
 | 
					set(toml11_install_include_dir       ${CMAKE_INSTALL_INCLUDEDIR})
 | 
				
			||||||
 | 
					set(toml11_config_dir                ${CMAKE_CURRENT_BINARY_DIR}/cmake/)
 | 
				
			||||||
 | 
					set(toml11_config                    ${toml11_config_dir}/toml11Config.cmake)
 | 
				
			||||||
 | 
					set(toml11_config_version            ${toml11_config_dir}/toml11ConfigVersion.cmake)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(toml11 INTERFACE)
 | 
				
			||||||
 | 
					target_include_directories(toml11 INTERFACE
 | 
				
			||||||
 | 
					    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
 | 
				
			||||||
 | 
					    $<INSTALL_INTERFACE:${toml11_install_include_dir}>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					add_library(toml11::toml11 ALIAS toml11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Write config and version config files
 | 
				
			||||||
 | 
					include(CMakePackageConfigHelpers)
 | 
				
			||||||
 | 
					write_basic_package_version_file(
 | 
				
			||||||
 | 
					    ${toml11_config_version}
 | 
				
			||||||
 | 
					    VERSION ${toml11_VERSION}
 | 
				
			||||||
 | 
					    COMPATIBILITY SameMajorVersion
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (toml11_INSTALL)
 | 
				
			||||||
 | 
					    configure_package_config_file(
 | 
				
			||||||
 | 
					        cmake/toml11Config.cmake.in
 | 
				
			||||||
 | 
					        ${toml11_config}
 | 
				
			||||||
 | 
					        INSTALL_DESTINATION ${toml11_install_cmake_dir}
 | 
				
			||||||
 | 
					        PATH_VARS toml11_install_cmake_dir
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Install config files
 | 
				
			||||||
 | 
					    install(FILES ${toml11_config} ${toml11_config_version}
 | 
				
			||||||
 | 
					        DESTINATION ${toml11_install_cmake_dir}
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Install header files
 | 
				
			||||||
 | 
					    install(
 | 
				
			||||||
 | 
					        FILES toml.hpp
 | 
				
			||||||
 | 
					        DESTINATION "${toml11_install_include_dir}"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    install(
 | 
				
			||||||
 | 
					        DIRECTORY "toml"
 | 
				
			||||||
 | 
					        DESTINATION "${toml11_install_include_dir}"
 | 
				
			||||||
 | 
					        FILES_MATCHING PATTERN "*.hpp"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Export targets and install them
 | 
				
			||||||
 | 
					    install(TARGETS toml11
 | 
				
			||||||
 | 
					        EXPORT toml11Targets
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    install(EXPORT toml11Targets
 | 
				
			||||||
 | 
					        FILE toml11Targets.cmake
 | 
				
			||||||
 | 
					        DESTINATION ${toml11_install_cmake_dir}
 | 
				
			||||||
 | 
					        NAMESPACE toml11::
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (toml11_BUILD_TEST)
 | 
				
			||||||
 | 
					    add_subdirectory(tests)
 | 
				
			||||||
 | 
					endif ()
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					The MIT License (MIT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2017 Toru Niina
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					THE SOFTWARE.
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					version: "{build}"
 | 
				
			||||||
 | 
					os: Visual Studio 2015
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					environment:
 | 
				
			||||||
 | 
					  matrix:
 | 
				
			||||||
 | 
					    - generator: Visual Studio 14 2015 Win64
 | 
				
			||||||
 | 
					    - generator: Visual Studio 14 2015
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					configuration:
 | 
				
			||||||
 | 
					  - Release
 | 
				
			||||||
 | 
					  - Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clone_depth: 10
 | 
				
			||||||
 | 
					clone_folder: c:\toml11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build_script:
 | 
				
			||||||
 | 
					  - cd C:\toml11
 | 
				
			||||||
 | 
					  - mkdir build
 | 
				
			||||||
 | 
					  - cd build
 | 
				
			||||||
 | 
					  - cmake -G"%generator%" -DCMAKE_CXX_STANDARD=11 -DBOOST_ROOT=C:/Libraries/boost_1_69_0 -Dtoml11_BUILD_TEST=ON ..
 | 
				
			||||||
 | 
					  - cmake --build . --config "%configuration%"
 | 
				
			||||||
 | 
					  - file --mime-encoding tests/toml/tests/hard_example_unicode.toml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_script:
 | 
				
			||||||
 | 
					  - ctest --build-config "%configuration%" --timeout 300 --output-on-failure
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					@PACKAGE_INIT@
 | 
				
			||||||
 | 
					include("@PACKAGE_toml11_install_cmake_dir@/toml11Targets.cmake")
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,291 @@
 | 
				
			||||||
 | 
					include(ExternalProject)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(TOML11_LANGSPEC_GIT_REPOSITORY "https://github.com/toml-lang/toml" CACHE STRING
 | 
				
			||||||
 | 
					    "URL of the TOML language specification repository")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(TOML11_LANGSPEC_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/toml" CACHE FILEPATH
 | 
				
			||||||
 | 
					    "directory for the TOML language specification tree")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(NOT EXISTS "${TOML11_LANGSPEC_SOURCE_DIR}/toml.abnf")
 | 
				
			||||||
 | 
					    ExternalProject_Add(toml
 | 
				
			||||||
 | 
					        SOURCE_DIR "${TOML11_LANGSPEC_SOURCE_DIR}"
 | 
				
			||||||
 | 
					        GIT_REPOSITORY "${TOML11_LANGSPEC_GIT_REPOSITORY}"
 | 
				
			||||||
 | 
					        GIT_TAG "v0.5.0"
 | 
				
			||||||
 | 
					        CONFIGURE_COMMAND ""
 | 
				
			||||||
 | 
					        BUILD_COMMAND ""
 | 
				
			||||||
 | 
					        INSTALL_COMMAND "")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(TEST_NAMES
 | 
				
			||||||
 | 
					    test_datetime
 | 
				
			||||||
 | 
					    test_string
 | 
				
			||||||
 | 
					    test_utility
 | 
				
			||||||
 | 
					    test_result
 | 
				
			||||||
 | 
					    test_traits
 | 
				
			||||||
 | 
					    test_value
 | 
				
			||||||
 | 
					    test_lex_boolean
 | 
				
			||||||
 | 
					    test_lex_integer
 | 
				
			||||||
 | 
					    test_lex_floating
 | 
				
			||||||
 | 
					    test_lex_datetime
 | 
				
			||||||
 | 
					    test_lex_string
 | 
				
			||||||
 | 
					    test_lex_key_comment
 | 
				
			||||||
 | 
					    test_parse_boolean
 | 
				
			||||||
 | 
					    test_parse_integer
 | 
				
			||||||
 | 
					    test_parse_floating
 | 
				
			||||||
 | 
					    test_parse_string
 | 
				
			||||||
 | 
					    test_parse_datetime
 | 
				
			||||||
 | 
					    test_parse_array
 | 
				
			||||||
 | 
					    test_parse_table
 | 
				
			||||||
 | 
					    test_parse_inline_table
 | 
				
			||||||
 | 
					    test_parse_key
 | 
				
			||||||
 | 
					    test_parse_table_key
 | 
				
			||||||
 | 
					    test_literals
 | 
				
			||||||
 | 
					    test_comments
 | 
				
			||||||
 | 
					    test_get
 | 
				
			||||||
 | 
					    test_get_or
 | 
				
			||||||
 | 
					    test_find
 | 
				
			||||||
 | 
					    test_find_or
 | 
				
			||||||
 | 
					    test_find_or_recursive
 | 
				
			||||||
 | 
					    test_expect
 | 
				
			||||||
 | 
					    test_parse_file
 | 
				
			||||||
 | 
					    test_serialize_file
 | 
				
			||||||
 | 
					    test_parse_unicode
 | 
				
			||||||
 | 
					    test_error_detection
 | 
				
			||||||
 | 
					    test_format_error
 | 
				
			||||||
 | 
					    test_extended_conversions
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wall"      COMPILER_SUPPORTS_WALL)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wextra"    COMPILER_SUPPORTS_WEXTRA)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Werror"    COMPILER_SUPPORTS_WERROR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wsign-conversion"     COMPILER_SUPPORTS_WSIGN_CONVERSION)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wconversion"          COMPILER_SUPPORTS_WCONVERSION)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wduplicated-cond"     COMPILER_SUPPORTS_WDUPLICATED_COND)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wlogical-op"          COMPILER_SUPPORTS_WLOGICAL_OP)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wuseless-cast"        COMPILER_SUPPORTS_WUSELESS_CAST)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wdouble-promotion"    COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wrange-loop-analysis" COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wundef"               COMPILER_SUPPORTS_WUNDEF)
 | 
				
			||||||
 | 
					CHECK_CXX_COMPILER_FLAG("-Wshadow"              COMPILER_SUPPORTS_WSHADOW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include(CheckCXXSourceCompiles)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check which standard library implementation is used. If libstdc++ is used,
 | 
				
			||||||
 | 
					# it will fail to compile. It compiles if libc++ is used.
 | 
				
			||||||
 | 
					check_cxx_source_compiles("
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					#ifdef __GLIBCXX__
 | 
				
			||||||
 | 
					    static_assert(false);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					int main() {
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}" TOML11_WITH_LIBCXX_LIBRARY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LLVM 8 requires -lc++fs if compiled with libc++ to use <filesystem>.
 | 
				
			||||||
 | 
					# LLVM 9+ does not require any special library.
 | 
				
			||||||
 | 
					# GCC 8 requires -lstdc++fs. GCC 9+ does not require it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Yes, we can check the version of the compiler used in the current build
 | 
				
			||||||
 | 
					# directly in CMake. But, in most cases, clang build uses libstdc++ as the
 | 
				
			||||||
 | 
					# standard library implementation and it makes the condition complicated.
 | 
				
			||||||
 | 
					# In many environment, the default installed C++ compiler is GCC and libstdc++
 | 
				
			||||||
 | 
					# is installed along with it. In most build on such an environment, even if we
 | 
				
			||||||
 | 
					# chose clang as the C++ compiler, still libstdc++ is used. Checking default
 | 
				
			||||||
 | 
					# gcc version makes the condition complicated.
 | 
				
			||||||
 | 
					# The purpose of this file is to compile tests. We know the environment on which
 | 
				
			||||||
 | 
					# the tests run. We can set this option and, I think, it is easier and better.
 | 
				
			||||||
 | 
					option(TOML11_REQUIRE_FILESYSTEM_LIBRARY "need to link -lstdc++fs or -lc++fs" OFF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(Boost COMPONENTS unit_test_framework REQUIRED)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(PREVIOUSLY_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}")
 | 
				
			||||||
 | 
					set(PREVIOUSLY_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					list(APPEND CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIRS})
 | 
				
			||||||
 | 
					list(APPEND CMAKE_REQUIRED_LIBRARIES ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_cxx_source_compiles("
 | 
				
			||||||
 | 
					#define BOOST_TEST_MODULE \"dummy\"
 | 
				
			||||||
 | 
					#undef BOOST_TEST_DYN_LINK
 | 
				
			||||||
 | 
					#define BOOST_TEST_NO_LIB
 | 
				
			||||||
 | 
					#include <boost/test/included/unit_test.hpp>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(proforma) { BOOST_TEST(true); }
 | 
				
			||||||
 | 
					" TOML11_WITH_BOOST_TEST_HEADER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_cxx_source_compiles("
 | 
				
			||||||
 | 
					#define BOOST_TEST_MODULE \"dummy\"
 | 
				
			||||||
 | 
					#undef BOOST_TEST_DYN_LINK
 | 
				
			||||||
 | 
					#undef BOOST_TEST_NO_LIB
 | 
				
			||||||
 | 
					#include <boost/test/unit_test.hpp>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(proforma) { BOOST_TEST(true); }
 | 
				
			||||||
 | 
					" TOML11_WITH_BOOST_TEST_STATIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_cxx_source_compiles("
 | 
				
			||||||
 | 
					#define BOOST_TEST_MODULE \"dummy\"
 | 
				
			||||||
 | 
					#define BOOST_TEST_DYN_LINK
 | 
				
			||||||
 | 
					#undef BOOST_TEST_NO_LIB
 | 
				
			||||||
 | 
					#include <boost/test/unit_test.hpp>
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(proforma) { BOOST_TEST(true); }
 | 
				
			||||||
 | 
					" TOML11_WITH_BOOST_TEST_DYNAMIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_REQUIRED_INCLUDES "${PREVIOUSLY_REQUIRED_INCLUDES}")
 | 
				
			||||||
 | 
					set(CMAKE_REQUIRED_LIBRARIES "${PREVIOUSLY_REQUIRED_LIBRARIES}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unset(PREVIOUSLY_REQUIRED_INCLUDES)
 | 
				
			||||||
 | 
					unset(PREVIOUSLY_REQUIRED_LIBRARIES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(TOML11_WITH_BOOST_TEST_DYNAMIC)
 | 
				
			||||||
 | 
					    add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST -DBOOST_TEST_DYN_LINK)
 | 
				
			||||||
 | 
					elseif(TOML11_WITH_BOOST_TEST_STATIC)
 | 
				
			||||||
 | 
					    add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
 | 
				
			||||||
 | 
					elseif(TOML11_WITH_BOOST_TEST_HEADER)
 | 
				
			||||||
 | 
					    add_definitions(-DBOOST_TEST_NO_LIB)
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
					    message(FATAL_ERROR "Neither the Boost.Test static or shared library nor the header-only version seem to be usable.")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WALL)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WEXTRA)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WPEDANTIC)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WERROR)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WSHADOW)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WSIGN_CONVERSION)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WCONVERSION)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WDUPLICATED_COND)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-cond")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-branches")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WLOGICAL_OP)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WUSELESS_CAST)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuseless-cast")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wrange-loop-analysis")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					if(COMPILER_SUPPORTS_WUNDEF)
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wundef")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(TOML11_USE_UNRELEASED_TOML_FEATURES)
 | 
				
			||||||
 | 
					    message(STATUS "adding TOML11_USE_UNRELEASED_TOML_FEATURES flag")
 | 
				
			||||||
 | 
					    add_definitions("-DTOML11_USE_UNRELEASED_TOML_FEATURES")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Disable some MSVC warnings
 | 
				
			||||||
 | 
					if(MSVC)
 | 
				
			||||||
 | 
					    # conversion from 'double' to 'unsigned int', possible loss of data
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244")
 | 
				
			||||||
 | 
					    # conversion from 'int' to 'unsigned int', signed/unsigned mismatch
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4365")
 | 
				
			||||||
 | 
					    # layout of class may have changed from a previous version of the compiler
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4371")
 | 
				
			||||||
 | 
					    # enumerator in switch of enum is not explicitly handled by a case label
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4061")
 | 
				
			||||||
 | 
					    # unreferenced inline function has been removed
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4514")
 | 
				
			||||||
 | 
					    # constructor is not implicitly called
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4582")
 | 
				
			||||||
 | 
					    # destructor is not implicitly called
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4583")
 | 
				
			||||||
 | 
					    # pragma warning: there is no warning number <x>
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4619")
 | 
				
			||||||
 | 
					    # default constructor was implicitly defined as deleted
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4623")
 | 
				
			||||||
 | 
					    # copy constructor was implicitly defined as deleted
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4625")
 | 
				
			||||||
 | 
					    # assignment operator was implicitly defined as deleted
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4626")
 | 
				
			||||||
 | 
					    # move assignment operator was implicitly defined as deleted
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4627")
 | 
				
			||||||
 | 
					    # <X> is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4668")
 | 
				
			||||||
 | 
					    # function not inlined
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4710")
 | 
				
			||||||
 | 
					    # function selected for automatic inlining
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4711")
 | 
				
			||||||
 | 
					    # <x> bytes padding added after data member
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4820")
 | 
				
			||||||
 | 
					    # pragma warning(pop): likely mismatch, popping warning state pushed in different file
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd5031")
 | 
				
			||||||
 | 
						# pragma warning(pop): spectre warnings in tests
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd5045")
 | 
				
			||||||
 | 
						# pragma warning(pop): spectre warnings in tests
 | 
				
			||||||
 | 
					    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4265")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(TEST_ENVIRON "TOMLDIR=${TOML11_LANGSPEC_SOURCE_DIR}")
 | 
				
			||||||
 | 
					if(WIN32)
 | 
				
			||||||
 | 
					    # Set the PATH to be able to find Boost DLL
 | 
				
			||||||
 | 
					    STRING(REPLACE ";" "\\;" PATH_STRING "$ENV{PATH}")
 | 
				
			||||||
 | 
					    list(APPEND TEST_ENVIRON "PATH=${PATH_STRING}\;${Boost_LIBRARY_DIRS}")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach(TEST_NAME ${TEST_NAMES})
 | 
				
			||||||
 | 
					    add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
 | 
				
			||||||
 | 
					    target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
 | 
				
			||||||
 | 
					    target_include_directories(${TEST_NAME} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
 | 
				
			||||||
 | 
					    target_compile_definitions(${TEST_NAME} PRIVATE "BOOST_TEST_MODULE=\"${TEST_NAME}\"")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # to compile tests with <filesystem>...
 | 
				
			||||||
 | 
					    if(TOML11_REQUIRE_FILESYSTEM_LIBRARY)
 | 
				
			||||||
 | 
					        if(TOML11_WITH_LIBCXX_LIBRARY)
 | 
				
			||||||
 | 
					            target_link_libraries(${TEST_NAME} "c++fs")
 | 
				
			||||||
 | 
					        else()
 | 
				
			||||||
 | 
					            target_link_libraries(${TEST_NAME} "stdc++fs")
 | 
				
			||||||
 | 
					        endif()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 | 
				
			||||||
 | 
					        if(toml11_TEST_WITH_ASAN)
 | 
				
			||||||
 | 
					            set_target_properties(${TEST_NAME} PROPERTIES
 | 
				
			||||||
 | 
					                COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer"
 | 
				
			||||||
 | 
					                LINK_FLAGS    "-fsanitize=address -fno-omit-frame-pointer")
 | 
				
			||||||
 | 
					        elseif(toml11_TEST_WITH_UBSAN)
 | 
				
			||||||
 | 
					            set_target_properties(${TEST_NAME} PROPERTIES
 | 
				
			||||||
 | 
					                COMPILE_FLAGS "-fsanitize=undefined"
 | 
				
			||||||
 | 
					                LINK_FLAGS    "-fsanitize=undefined")
 | 
				
			||||||
 | 
					        endif()
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 | 
				
			||||||
 | 
					    set_tests_properties(${TEST_NAME} PROPERTIES ENVIRONMENT "${TEST_ENVIRON}")
 | 
				
			||||||
 | 
					endforeach(TEST_NAME)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# this test is to check it compiles. it will not run
 | 
				
			||||||
 | 
					add_executable(test_multiple_translation_unit
 | 
				
			||||||
 | 
					               test_multiple_translation_unit_1.cpp
 | 
				
			||||||
 | 
					               test_multiple_translation_unit_2.cpp)
 | 
				
			||||||
 | 
					target_link_libraries(test_multiple_translation_unit toml11::toml11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(WIN32)
 | 
				
			||||||
 | 
					    add_executable(test_windows test_windows.cpp)
 | 
				
			||||||
 | 
					    target_link_libraries(test_windows toml11::toml11)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(argc != 3)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cerr << "usage: ./check [filename] [valid|invalid]" << std::endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::string file_kind(argv[2]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data = toml::parse(argv[1]);
 | 
				
			||||||
 | 
					        std::cout << std::setprecision(16) << std::setw(80) << data;
 | 
				
			||||||
 | 
					        if(file_kind == "valid")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    catch(const toml::syntax_error& err)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "what(): " << err.what() << std::endl;
 | 
				
			||||||
 | 
					        if(file_kind == "invalid")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 127;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,114 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(argc != 2)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cerr << "usage: ./check [filename]" << std::endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::string filename(argv[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data = toml::parse(filename);
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::ofstream ofs("tmp.toml");
 | 
				
			||||||
 | 
					            ofs << std::setprecision(16) << std::setw(80) << data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const auto serialized = toml::parse("tmp.toml");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(data != serialized)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // this is really a ditry hack, but is the easiest way...
 | 
				
			||||||
 | 
					            // TODO: cleanup by adding comparison function to check if a value is NaN or not
 | 
				
			||||||
 | 
					            if(filename.substr(filename.size() - 22, 22) == "float-inf-and-nan.toml" &&
 | 
				
			||||||
 | 
					                std::isnan   (toml::find<double>(serialized, "nan"))           &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "nan"))           &&
 | 
				
			||||||
 | 
					                std::isnan   (toml::find<double>(serialized, "nan_plus"))      &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "nan_plus"))      &&
 | 
				
			||||||
 | 
					                std::isnan   (toml::find<double>(serialized, "nan_neg"))       &&
 | 
				
			||||||
 | 
					                std::signbit (toml::find<double>(serialized, "nan_neg"))       &&
 | 
				
			||||||
 | 
					               !std::isnan   (toml::find<double>(serialized, "infinity"))      &&
 | 
				
			||||||
 | 
					               !std::isfinite(toml::find<double>(serialized, "infinity"))      &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "infinity"))      &&
 | 
				
			||||||
 | 
					               !std::isnan   (toml::find<double>(serialized, "infinity_plus")) &&
 | 
				
			||||||
 | 
					               !std::isfinite(toml::find<double>(serialized, "infinity_plus")) &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "infinity_plus")) &&
 | 
				
			||||||
 | 
					               !std::isnan   (toml::find<double>(serialized, "infinity_neg"))  &&
 | 
				
			||||||
 | 
					               !std::isfinite(toml::find<double>(serialized, "infinity_neg"))  &&
 | 
				
			||||||
 | 
					                std::signbit (toml::find<double>(serialized, "infinity_neg")))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // then it is correctly serialized.
 | 
				
			||||||
 | 
					                // Note that, the result of (nan == nan) is false. so `data == serialized` is false.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::cerr << "============================================================\n";
 | 
				
			||||||
 | 
					                std::cerr << "result (w/o comment) different: " << filename << std::endl;
 | 
				
			||||||
 | 
					                std::cerr << "------------------------------------------------------------\n";
 | 
				
			||||||
 | 
					                std::cerr << "# serialized\n";
 | 
				
			||||||
 | 
					                std::cerr << serialized;
 | 
				
			||||||
 | 
					                std::cerr << "------------------------------------------------------------\n";
 | 
				
			||||||
 | 
					                std::cerr << "# data\n";
 | 
				
			||||||
 | 
					                std::cerr << data;
 | 
				
			||||||
 | 
					                return 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data = toml::parse<toml::preserve_comments>(filename);
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::ofstream ofs("tmp.toml");
 | 
				
			||||||
 | 
					            ofs << std::setprecision(16) << std::setw(80) << data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const auto serialized = toml::parse<toml::preserve_comments>("tmp.toml");
 | 
				
			||||||
 | 
					        if(data != serialized)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // this is really a ditry hack, but is the easiest way...
 | 
				
			||||||
 | 
					            // TODO: cleanup by adding comparison function to check if a value is NaN or not
 | 
				
			||||||
 | 
					            if(filename.substr(filename.size() - 22, 22) == "float-inf-and-nan.toml" &&
 | 
				
			||||||
 | 
					                std::isnan   (toml::find<double>(serialized, "nan"))           &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "nan"))           &&
 | 
				
			||||||
 | 
					                std::isnan   (toml::find<double>(serialized, "nan_plus"))      &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "nan_plus"))      &&
 | 
				
			||||||
 | 
					                std::isnan   (toml::find<double>(serialized, "nan_neg"))       &&
 | 
				
			||||||
 | 
					                std::signbit (toml::find<double>(serialized, "nan_neg"))       &&
 | 
				
			||||||
 | 
					               !std::isnan   (toml::find<double>(serialized, "infinity"))      &&
 | 
				
			||||||
 | 
					               !std::isfinite(toml::find<double>(serialized, "infinity"))      &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "infinity"))      &&
 | 
				
			||||||
 | 
					               !std::isnan   (toml::find<double>(serialized, "infinity_plus")) &&
 | 
				
			||||||
 | 
					               !std::isfinite(toml::find<double>(serialized, "infinity_plus")) &&
 | 
				
			||||||
 | 
					               !std::signbit (toml::find<double>(serialized, "infinity_plus")) &&
 | 
				
			||||||
 | 
					               !std::isnan   (toml::find<double>(serialized, "infinity_neg"))  &&
 | 
				
			||||||
 | 
					               !std::isfinite(toml::find<double>(serialized, "infinity_neg"))  &&
 | 
				
			||||||
 | 
					                std::signbit (toml::find<double>(serialized, "infinity_neg"))  &&
 | 
				
			||||||
 | 
					                toml::find(data, "nan").comments()           == toml::find(serialized, "nan").comments()           &&
 | 
				
			||||||
 | 
					                toml::find(data, "nan_plus").comments()      == toml::find(serialized, "nan_plus").comments()      &&
 | 
				
			||||||
 | 
					                toml::find(data, "nan_neg").comments()       == toml::find(serialized, "nan_neg").comments()       &&
 | 
				
			||||||
 | 
					                toml::find(data, "infinity").comments()      == toml::find(serialized, "infinity").comments()      &&
 | 
				
			||||||
 | 
					                toml::find(data, "infinity_plus").comments() == toml::find(serialized, "infinity_plus").comments() &&
 | 
				
			||||||
 | 
					                toml::find(data, "infinity_neg").comments()  == toml::find(serialized, "infinity_neg").comments()  )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // then it is correctly serialized.
 | 
				
			||||||
 | 
					                // Note that, the result of (nan == nan) is false. so `data == serialized` is false.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::cerr << "============================================================\n";
 | 
				
			||||||
 | 
					                std::cerr << "result (w/  comment) different: " << filename << std::endl;
 | 
				
			||||||
 | 
					                std::cerr << "------------------------------------------------------------\n";
 | 
				
			||||||
 | 
					                std::cerr << "# serialized\n";
 | 
				
			||||||
 | 
					                std::cerr << serialized;
 | 
				
			||||||
 | 
					                std::cerr << "------------------------------------------------------------\n";
 | 
				
			||||||
 | 
					                std::cerr << "# data\n";
 | 
				
			||||||
 | 
					                std::cerr << data;
 | 
				
			||||||
 | 
					                return 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,139 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct json_serializer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    void operator()(toml::boolean v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"bool\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(toml::integer v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"integer\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(toml::floating v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(std::isnan(v) && std::signbit(v))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // toml-test does not allow negative NaN represented in "-nan" because
 | 
				
			||||||
 | 
					            // there are languages that does not distinguish nan and -nan.
 | 
				
			||||||
 | 
					            // But toml11 keeps sign from input. To resolve this difference,
 | 
				
			||||||
 | 
					            // we convert -nan to nan here.
 | 
				
			||||||
 | 
					            v = std::numeric_limits<toml::floating>::quiet_NaN();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"float\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::string& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // since toml11 automatically convert string to multiline string that is
 | 
				
			||||||
 | 
					        // valid only in TOML, we need to format the string to make it valid in
 | 
				
			||||||
 | 
					        // JSON.
 | 
				
			||||||
 | 
					        toml::serializer<toml::value> ser(std::numeric_limits<std::size_t>::max());
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"string\",\"value\":"
 | 
				
			||||||
 | 
					                  << ser(v.str) << "}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::local_time& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"time-local\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::local_date& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"date-local\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::local_datetime& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"datetime-local\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::offset_datetime& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "{\"type\":\"datetime\",\"value\":\"" << toml::value(v) << "\"}";
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::array& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(!v.empty() && v.front().is_table())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::cout << '[';
 | 
				
			||||||
 | 
					            bool is_first = true;
 | 
				
			||||||
 | 
					            for(const auto& elem : v)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if(!is_first) {std::cout << ", ";}
 | 
				
			||||||
 | 
					                is_first = false;
 | 
				
			||||||
 | 
					                toml::visit(*this, elem);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            std::cout << ']';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					//             std::cout << "{\"type\":\"array\",\"value\":[";
 | 
				
			||||||
 | 
					            std::cout << "[";
 | 
				
			||||||
 | 
					            bool is_first = true;
 | 
				
			||||||
 | 
					            for(const auto& elem : v)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if(!is_first) {std::cout << ", ";}
 | 
				
			||||||
 | 
					                is_first = false;
 | 
				
			||||||
 | 
					                toml::visit(*this, elem);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            std::cout << "]";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void operator()(const toml::table& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << '{';
 | 
				
			||||||
 | 
					        bool is_first = true;
 | 
				
			||||||
 | 
					        for(const auto& elem : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(!is_first) {std::cout << ", ";}
 | 
				
			||||||
 | 
					            is_first = false;
 | 
				
			||||||
 | 
					            const auto k = toml::format_key(elem.first);
 | 
				
			||||||
 | 
					            if(k.at(0) == '"')
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::cout << k << ":";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else // bare key
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::cout << '\"' << k << "\":";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            toml::visit(*this, elem.second);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        std::cout << '}';
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    try
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<char> buf;
 | 
				
			||||||
 | 
					        std::cin.peek();
 | 
				
			||||||
 | 
					        while(!std::cin.eof())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            buf.push_back(std::cin.get());
 | 
				
			||||||
 | 
					            std::cin.peek();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        std::string bufstr(buf.begin(), buf.end());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::istringstream ss(bufstr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto data = toml::parse(ss);
 | 
				
			||||||
 | 
					        std::cout << std::setprecision(std::numeric_limits<double>::max_digits10);
 | 
				
			||||||
 | 
					        toml::visit(json_serializer(), data);
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    catch(const toml::syntax_error& err)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::cout << "what(): " << err.what() << std::endl;
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,545 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_comment_before)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            # comment for a.
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            # comment for b.
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto& a = toml::find(v, "a");
 | 
				
			||||||
 | 
					        const auto& b = toml::find(v, "b");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().size()  == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().front() == " comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().size()  == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().front() == " comment for b.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            # comment for a.
 | 
				
			||||||
 | 
					            # another comment for a.
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            # comment for b.
 | 
				
			||||||
 | 
					            # also comment for b.
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto& a = toml::find(v, "a");
 | 
				
			||||||
 | 
					        const auto& b = toml::find(v, "b");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().size()  == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().front() == " comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().back()  == " another comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().size()  == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().front() == " comment for b.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().back()  == " also comment for b.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_comment_inline)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            a = 42    # comment for a.
 | 
				
			||||||
 | 
					            b = "baz" # comment for b.
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto& a = toml::find(v, "a");
 | 
				
			||||||
 | 
					        const auto& b = toml::find(v, "b");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().size()  == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().front() == " comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().size()  == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().front() == " comment for b.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            a = [
 | 
				
			||||||
 | 
					                42,
 | 
				
			||||||
 | 
					            ] # comment for a.
 | 
				
			||||||
 | 
					            b = [
 | 
				
			||||||
 | 
					                "bar", # this is not a comment for b, but "bar"
 | 
				
			||||||
 | 
					            ] # this is a comment for b.
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto& a  = toml::find(v, "a");
 | 
				
			||||||
 | 
					        const auto& b  = toml::find(v, "b");
 | 
				
			||||||
 | 
					        const auto& b0 = b.as_array().at(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().size()   == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().front()  == " comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().size()   == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().front()  == " this is a comment for b.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b0.comments().size()  == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(b0.comments().front() == " this is not a comment for b, but \"bar\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_comment_both)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            # comment for a.
 | 
				
			||||||
 | 
					            a = 42 # inline comment for a.
 | 
				
			||||||
 | 
					            # comment for b.
 | 
				
			||||||
 | 
					            b = "baz" # inline comment for b.
 | 
				
			||||||
 | 
					            # comment for c.
 | 
				
			||||||
 | 
					            c = [ # this comment will be ignored
 | 
				
			||||||
 | 
					                # comment for the first element.
 | 
				
			||||||
 | 
					                10 # this also.
 | 
				
			||||||
 | 
					            ] # another comment for c.
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto& a  = toml::find(v, "a");
 | 
				
			||||||
 | 
					        const auto& b  = toml::find(v, "b");
 | 
				
			||||||
 | 
					        const auto& c  = toml::find(v, "c");
 | 
				
			||||||
 | 
					        const auto& c0 = c.as_array().at(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().size()  == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().front() == " comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(a.comments().back()  == " inline comment for a.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().size()  == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().front() == " comment for b.");
 | 
				
			||||||
 | 
					        BOOST_TEST(b.comments().back()  == " inline comment for b.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(c.comments().size()  == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(c.comments().front() == " comment for c.");
 | 
				
			||||||
 | 
					        BOOST_TEST(c.comments().back()  == " another comment for c.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(c0.comments().size()  == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(c0.comments().front() == " comment for the first element.");
 | 
				
			||||||
 | 
					        BOOST_TEST(c0.comments().back()  == " this also.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_comments_on_implicit_values)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            # comment for the first element of array-of-tables.
 | 
				
			||||||
 | 
					            [[array-of-tables]]
 | 
				
			||||||
 | 
					            foo = "bar"
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto aot = toml::find(v, "array-of-tables");
 | 
				
			||||||
 | 
					        const auto elm = aot.at(0);
 | 
				
			||||||
 | 
					        BOOST_TEST(aot.comments().empty());
 | 
				
			||||||
 | 
					        BOOST_TEST(elm.comments().size() == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(elm.comments().front() == " comment for the first element of array-of-tables.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string file = R"(
 | 
				
			||||||
 | 
					            # comment for the array itself
 | 
				
			||||||
 | 
					            array-of-tables = [
 | 
				
			||||||
 | 
					                # comment for the first element of array-of-tables.
 | 
				
			||||||
 | 
					                {foo = "bar"}
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        )";
 | 
				
			||||||
 | 
					        std::istringstream iss(file);
 | 
				
			||||||
 | 
					        const auto v = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto aot = toml::find(v, "array-of-tables");
 | 
				
			||||||
 | 
					        const auto elm = aot.at(0);
 | 
				
			||||||
 | 
					        BOOST_TEST(aot.comments().size() == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(aot.comments().front() == " comment for the array itself");
 | 
				
			||||||
 | 
					        BOOST_TEST(elm.comments().size() == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(elm.comments().front() == " comment for the first element of array-of-tables.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_discard_comment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const std::string file = R"(
 | 
				
			||||||
 | 
					        # comment for a.
 | 
				
			||||||
 | 
					        a = 42 # inline comment for a.
 | 
				
			||||||
 | 
					        # comment for b.
 | 
				
			||||||
 | 
					        b = "baz" # inline comment for b.
 | 
				
			||||||
 | 
					        # comment for c.
 | 
				
			||||||
 | 
					        c = [ # this comment will be ignored
 | 
				
			||||||
 | 
					            # comment for the first element.
 | 
				
			||||||
 | 
					            10 # this also.
 | 
				
			||||||
 | 
					        ] # another comment for c.
 | 
				
			||||||
 | 
					    )";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::istringstream iss(file);
 | 
				
			||||||
 | 
					    const auto v = toml::parse<toml::discard_comments>(iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto& a  = toml::find(v, "a");
 | 
				
			||||||
 | 
					    const auto& b  = toml::find(v, "b");
 | 
				
			||||||
 | 
					    const auto& c  = toml::find(v, "c");
 | 
				
			||||||
 | 
					    const auto& c0 = c.as_array().at(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(a.comments().empty());
 | 
				
			||||||
 | 
					    BOOST_TEST(b.comments().empty());
 | 
				
			||||||
 | 
					    BOOST_TEST(c.comments().empty());
 | 
				
			||||||
 | 
					    BOOST_TEST(c0.comments().empty());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_construct_value_with_comments)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = toml::basic_value<toml::preserve_comments>;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(true, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_boolean());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_boolean() == true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_integer() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(3.14, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_floating());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_floating() == 3.14);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(toml::string("str"), {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(std::string("str"), {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(std::string("str"), toml::string_t::literal,
 | 
				
			||||||
 | 
					                           {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v("str", {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v("str", toml::string_t::literal,
 | 
				
			||||||
 | 
					                           {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using namespace std::literals::string_view_literals;
 | 
				
			||||||
 | 
					        const value_type v("str"sv, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using namespace std::literals::string_view_literals;
 | 
				
			||||||
 | 
					        const value_type v("str"sv, toml::string_t::literal,
 | 
				
			||||||
 | 
					                           {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_string() == "str");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    const toml::local_date      ld{2019, toml::month_t::Apr, 1};
 | 
				
			||||||
 | 
					    const toml::local_time      lt{12, 30, 45};
 | 
				
			||||||
 | 
					    const toml::local_datetime  ldt{ld, lt};
 | 
				
			||||||
 | 
					    const toml::offset_datetime odt{ld, lt, toml::time_offset{9, 0}};
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(ld, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_local_date());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_local_date() == ld);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(lt, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_local_time());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_local_time() == lt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::local_time three_hours{3,0,0};
 | 
				
			||||||
 | 
					        const value_type v(std::chrono::hours(3), {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_local_time());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_local_time() == three_hours);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(ldt, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_local_datetime());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_local_datetime() == ldt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(odt, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_offset_datetime());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_offset_datetime() == odt);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto systp = static_cast<std::chrono::system_clock::time_point>(odt);
 | 
				
			||||||
 | 
					        const value_type v(systp, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_offset_datetime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // While the conversion, the information about time offset may change.
 | 
				
			||||||
 | 
					        const auto systp2 = static_cast<std::chrono::system_clock::time_point>(
 | 
				
			||||||
 | 
					                v.as_offset_datetime());
 | 
				
			||||||
 | 
					        const bool result = systp == systp2; // because there is no operator<<
 | 
				
			||||||
 | 
					        BOOST_TEST(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::array_type a{1,2,3,4,5};
 | 
				
			||||||
 | 
					        const value_type v(a, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_array());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(0).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(1).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(2).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(3).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(4).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(0).as_integer() == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(1).as_integer() == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(2).as_integer() == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(3).as_integer() == 4);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(4).as_integer() == 5);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::initializer_list<int> a = {1,2,3,4,5};
 | 
				
			||||||
 | 
					        const value_type v(a, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_array());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(0).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(1).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(2).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(3).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(4).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(0).as_integer() == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(1).as_integer() == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(2).as_integer() == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(3).as_integer() == 4);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(4).as_integer() == 5);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::vector<int> a = {1,2,3,4,5};
 | 
				
			||||||
 | 
					        const value_type v(a, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_array());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(0).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(1).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(2).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(3).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(4).is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(0).as_integer() == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(1).as_integer() == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(2).as_integer() == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(3).as_integer() == 4);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_array().at(4).as_integer() == 5);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::table_type t{
 | 
				
			||||||
 | 
					                {"key1", 42}, {"key2", "foobar"}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        const value_type v(t, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_table());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key1").is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key2").is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::initializer_list<std::pair<std::string, value_type>> t{
 | 
				
			||||||
 | 
					                {"key1", 42}, {"key2", "foobar"}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        const value_type v(t, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_table());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key1").is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key2").is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::map<std::string, value_type> t{
 | 
				
			||||||
 | 
					                {"key1", 42}, {"key2", "foobar"}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        const value_type v(t, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_table());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key1").is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key2").is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_overwrite_comments)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = toml::basic_value<toml::preserve_comments>;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_integer() == 42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const value_type u(v, {"comment3", "comment4"});
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().at(0)  == "comment3");
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().at(1)  == "comment4");
 | 
				
			||||||
 | 
					        BOOST_TEST(u.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(u.as_integer() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_integer() == 42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const value_type u(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(u.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(u.as_integer() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().size() == 2u);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(0)  == "comment1");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.comments().at(1)  == "comment2");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v.as_integer() == 42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const value_type u(v, {});
 | 
				
			||||||
 | 
					        BOOST_TEST(u.comments().size() == 0u);
 | 
				
			||||||
 | 
					        BOOST_TEST(u.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(u.as_integer() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_output_comments)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = toml::basic_value<toml::preserve_comments>;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << v.comments();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::ostringstream ref;
 | 
				
			||||||
 | 
					        ref << "#comment1\n";
 | 
				
			||||||
 | 
					        ref << "#comment2\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == ref.str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If v is not a table, toml11 assumes that user is writing something
 | 
				
			||||||
 | 
					        // like the following.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        oss << "answer = " << v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If v is not a table, toml11 assumes that user is writing something
 | 
				
			||||||
 | 
					        // like the following.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        oss << toml::nocomment << "answer = " << v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "answer = 42");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v(42, {"comment1", "comment2"});
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If v is not a table, toml11 assumes that user is writing something
 | 
				
			||||||
 | 
					        // like the following.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        oss << toml::nocomment << toml::showcomment << "answer = " << v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,117 @@
 | 
				
			||||||
 | 
					#include <toml/datetime.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_local_date)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::local_date date(2018, toml::month_t::Jan, 1);
 | 
				
			||||||
 | 
					    const toml::local_date date1(date);
 | 
				
			||||||
 | 
					    BOOST_TEST(date == date1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::chrono::system_clock::time_point tp(date);
 | 
				
			||||||
 | 
					    const toml::local_date date2(tp);
 | 
				
			||||||
 | 
					    BOOST_TEST(date == date2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const toml::local_date date3(2017, toml::month_t::Dec, 31);
 | 
				
			||||||
 | 
					    BOOST_TEST(date > date3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ostringstream oss;
 | 
				
			||||||
 | 
					    oss << date;
 | 
				
			||||||
 | 
					    BOOST_TEST(oss.str() == std::string("2018-01-01"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_local_time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::local_time time(12, 30, 45);
 | 
				
			||||||
 | 
					    const toml::local_time time1(time);
 | 
				
			||||||
 | 
					    BOOST_TEST(time == time1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::chrono::nanoseconds dur(time);
 | 
				
			||||||
 | 
					    std::chrono::nanoseconds ns(0);
 | 
				
			||||||
 | 
					    ns += std::chrono::hours  (12);
 | 
				
			||||||
 | 
					    ns += std::chrono::minutes(30);
 | 
				
			||||||
 | 
					    ns += std::chrono::seconds(45);
 | 
				
			||||||
 | 
					    BOOST_TEST(dur.count() == ns.count());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const toml::local_time time3(12, 15, 45);
 | 
				
			||||||
 | 
					    BOOST_TEST(time > time3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << time;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == std::string("12:30:45"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::local_time time4(12, 30, 45, 123, 456);
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << time4;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == std::string("12:30:45.123456"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_time_offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::time_offset time(9, 30);
 | 
				
			||||||
 | 
					    const toml::time_offset time1(time);
 | 
				
			||||||
 | 
					    BOOST_TEST(time == time1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::chrono::minutes dur(time);
 | 
				
			||||||
 | 
					    std::chrono::minutes m(0);
 | 
				
			||||||
 | 
					    m += std::chrono::hours  (9);
 | 
				
			||||||
 | 
					    m += std::chrono::minutes(30);
 | 
				
			||||||
 | 
					    BOOST_TEST(dur.count() == m.count());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const toml::time_offset time2(9, 0);
 | 
				
			||||||
 | 
					    BOOST_TEST(time2 < time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ostringstream oss;
 | 
				
			||||||
 | 
					    oss << time;
 | 
				
			||||||
 | 
					    BOOST_TEST(oss.str() == std::string("+09:30"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_local_datetime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
 | 
				
			||||||
 | 
					                                  toml::local_time(12, 30, 45));
 | 
				
			||||||
 | 
					    const toml::local_datetime dt1(dt);
 | 
				
			||||||
 | 
					    BOOST_TEST(dt == dt1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::chrono::system_clock::time_point tp(dt);
 | 
				
			||||||
 | 
					    const toml::local_datetime dt2(tp);
 | 
				
			||||||
 | 
					    BOOST_TEST(dt == dt2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ostringstream oss;
 | 
				
			||||||
 | 
					    oss << dt;
 | 
				
			||||||
 | 
					    BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_offset_datetime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::offset_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
 | 
				
			||||||
 | 
					                                   toml::local_time(12, 30, 45),
 | 
				
			||||||
 | 
					                                   toml::time_offset(9, 30));
 | 
				
			||||||
 | 
					    const toml::offset_datetime dt1(dt);
 | 
				
			||||||
 | 
					    BOOST_TEST(dt == dt1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::chrono::system_clock::time_point tp1(dt);
 | 
				
			||||||
 | 
					    const toml::offset_datetime dt2(tp1);
 | 
				
			||||||
 | 
					    const std::chrono::system_clock::time_point tp2(dt2);
 | 
				
			||||||
 | 
					    const bool tp_same = (tp1 == tp2);
 | 
				
			||||||
 | 
					    BOOST_TEST(tp_same);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << dt;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45+09:30"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::offset_datetime dt3(
 | 
				
			||||||
 | 
					                toml::local_date(2018, toml::month_t::Jan, 1),
 | 
				
			||||||
 | 
					                toml::local_time(12, 30, 45),
 | 
				
			||||||
 | 
					                toml::time_offset(0, 0));
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << dt3;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45Z"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,97 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_empty_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string("= \"value\""));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_missing_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string("a ="));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_too_many_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string("a = 1 = \"value\""));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "[table]\n"
 | 
				
			||||||
 | 
					            "a = 42\n"
 | 
				
			||||||
 | 
					            "[table]\n"
 | 
				
			||||||
 | 
					            "b = 42\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "[[table]]\n"
 | 
				
			||||||
 | 
					            "a = 42\n"
 | 
				
			||||||
 | 
					            "[table]\n"
 | 
				
			||||||
 | 
					            "b = 42\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "[table]\n"
 | 
				
			||||||
 | 
					            "a = 42\n"
 | 
				
			||||||
 | 
					            "[[table]]\n"
 | 
				
			||||||
 | 
					            "b = 42\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "a = 1\n"
 | 
				
			||||||
 | 
					            "a = 2\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "a.b   = 1\n"
 | 
				
			||||||
 | 
					            "a.b.c = 2\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "a = [1, 1.0]\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("After v1.0.0-rc.1, heterogeneous arrays are allowed");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					            "a = [{b = 1}]\n"
 | 
				
			||||||
 | 
					            "[[a]]\n"
 | 
				
			||||||
 | 
					            "b = 2\n"
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_expect)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1(42);
 | 
				
			||||||
 | 
					        toml::value v2(3.14);
 | 
				
			||||||
 | 
					        const auto v1_or_0 = toml::expect<int>(v1).unwrap_or(0);
 | 
				
			||||||
 | 
					        const auto v2_or_0 = toml::expect<int>(v2).unwrap_or(0);
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == v1_or_0);
 | 
				
			||||||
 | 
					        BOOST_TEST( 0 == v2_or_0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto v1_or_none = toml::expect<int>(v1).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
 | 
				
			||||||
 | 
					        const auto v2_or_none = toml::expect<int>(v2).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
 | 
				
			||||||
 | 
					        BOOST_TEST("42" ==   v1_or_none);
 | 
				
			||||||
 | 
					        BOOST_TEST("none" == v2_or_none);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,627 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace extlib
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct foo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct bar
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void from_toml(const toml::value& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->a = toml::find<int>(v, "a");
 | 
				
			||||||
 | 
					        this->b = toml::find<std::string>(v, "b");
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    toml::table into_toml() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return toml::table{{"a", this->a}, {"b", this->b}};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct baz
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct qux
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct foobar
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // via constructor
 | 
				
			||||||
 | 
					    explicit foobar(const toml::value& v)
 | 
				
			||||||
 | 
					        : a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					} // extlib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct from<extlib::foo>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static extlib::foo from_toml(const toml::value& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct into<extlib::foo>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static toml::value into_toml(const extlib::foo& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return toml::value{{"a", f.a}, {"b", f.b}};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct from<extlib::baz>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static extlib::baz from_toml(const toml::value& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return extlib::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct into<extlib::qux>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static toml::table into_toml(const extlib::qux& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return toml::table{{"a", f.a}, {"b", f.b}};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace extlib2
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct foo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct bar
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename C, template<typename ...> class M, template<typename ...> class A>
 | 
				
			||||||
 | 
					    void from_toml(const toml::basic_value<C, M, A>& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->a = toml::find<int>(v, "a");
 | 
				
			||||||
 | 
					        this->b = toml::find<std::string>(v, "b");
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    toml::table into_toml() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return toml::table{{"a", this->a}, {"b", this->b}};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct baz
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct qux
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct foobar
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename C, template<typename ...> class M, template<typename ...> class A>
 | 
				
			||||||
 | 
					    explicit foobar(const toml::basic_value<C, M, A>& v)
 | 
				
			||||||
 | 
					        : a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // extlib2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct from<extlib2::foo>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename C, template<typename ...> class M, template<typename ...> class A>
 | 
				
			||||||
 | 
					    static extlib2::foo from_toml(const toml::basic_value<C, M, A>& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct into<extlib2::foo>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static toml::table into_toml(const extlib2::foo& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return toml::table{{"a", f.a}, {"b", f.b}};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct from<extlib2::baz>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename C, template<typename ...> class M, template<typename ...> class A>
 | 
				
			||||||
 | 
					    static extlib2::baz from_toml(const toml::basic_value<C, M, A>& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return extlib2::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct into<extlib2::qux>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static toml::basic_value<toml::preserve_comments, std::map>
 | 
				
			||||||
 | 
					    into_toml(const extlib2::qux& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return toml::basic_value<toml::preserve_comments, std::map>{
 | 
				
			||||||
 | 
					            {"a", f.a}, {"b", f.b}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foo = toml::get<extlib::foo>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::value v2(foo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v == v2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foo = toml::get<extlib2::foo>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::value v2(foo);
 | 
				
			||||||
 | 
					        BOOST_TEST(v == v2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foo = toml::get<extlib2::foo>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v2(foo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v == v2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bar = toml::get<extlib::bar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::value v2(bar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v == v2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bar = toml::get<extlib2::bar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::value v2(bar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v == v2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bar = toml::get<extlib2::bar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v2(bar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v == v2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_conversion_one_way)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto baz = toml::get<extlib::baz>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(baz.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(baz.b == "baz");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const extlib::qux q{42, "qux"};
 | 
				
			||||||
 | 
					        const toml::value v(q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::find<int>(v, "a")         == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map> v{
 | 
				
			||||||
 | 
					            {"a", 42}, {"b", "baz"}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto baz = toml::get<extlib2::baz>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(baz.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(baz.b == "baz");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const extlib::qux q{42, "qux"};
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::preserve_comments, std::map> v(q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::find<int>(v, "a")         == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_conversion_via_constructor)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "foobar"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foobar = toml::get<extlib::foobar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobar.b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map> v{
 | 
				
			||||||
 | 
					            {"a", 42}, {"b", "foobar"}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foobar = toml::get<extlib2::foobar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobar.b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_recursive_conversion)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{
 | 
				
			||||||
 | 
					            toml::table{{"a", 42}, {"b", "baz"}},
 | 
				
			||||||
 | 
					            toml::table{{"a", 43}, {"b", "qux"}},
 | 
				
			||||||
 | 
					            toml::table{{"a", 44}, {"b", "quux"}},
 | 
				
			||||||
 | 
					            toml::table{{"a", 45}, {"b", "foobar"}},
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foos = toml::get<std::vector<extlib::foo>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(3).b == "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bars = toml::get<std::vector<extlib::bar>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(3).b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{
 | 
				
			||||||
 | 
					                toml::table{{"a", 42}, {"b", "baz"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 43}, {"b", "qux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 44}, {"b", "quux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 45}, {"b", "foobar"}},
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foos = toml::get<std::vector<extlib2::foo>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(3).b == "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bars = toml::get<std::vector<extlib2::bar>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(3).b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v{
 | 
				
			||||||
 | 
					                toml::table{{"a", 42}, {"b", "baz"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 43}, {"b", "qux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 44}, {"b", "quux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 45}, {"b", "foobar"}}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foos = toml::get<std::vector<extlib2::foo>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foos.at(3).b == "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bars = toml::get<std::vector<extlib2::bar>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(bars.at(3).b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // via constructor
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{
 | 
				
			||||||
 | 
					                toml::table{{"a", 42}, {"b", "baz"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 43}, {"b", "qux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 44}, {"b", "quux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 45}, {"b", "foobar"}}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const auto foobars = toml::get<std::vector<extlib::foobar>>(v);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.size()  == 4ul);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(0).a == 42);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(1).a == 43);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(2).a == 44);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(0).b == "baz");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(1).b == "qux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(2).b == "quux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(3).b == "foobar");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.size()  == 4ul);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(0).a == 42);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(1).a == 43);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(2).a == 44);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(0).b == "baz");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(1).b == "qux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(2).b == "quux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at(3).b == "foobar");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v{
 | 
				
			||||||
 | 
					                toml::table{{"a", 42}, {"b", "baz"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 43}, {"b", "qux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 44}, {"b", "quux"}},
 | 
				
			||||||
 | 
					                toml::table{{"a", 45}, {"b", "foobar"}}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(0).a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(1).a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(2).a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(3).a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(0).b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(1).b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(2).b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at(3).b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // via constructor
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{
 | 
				
			||||||
 | 
					                {"0", toml::table{{"a", 42}, {"b", "baz"}}},
 | 
				
			||||||
 | 
					                {"1", toml::table{{"a", 43}, {"b", "qux"}}},
 | 
				
			||||||
 | 
					                {"2", toml::table{{"a", 44}, {"b", "quux"}}},
 | 
				
			||||||
 | 
					                {"3", toml::table{{"a", 45}, {"b", "foobar"}}}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.size()  == 4ul);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("0").a == 42);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("1").a == 43);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("2").a == 44);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("3").a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("0").b == "baz");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("1").b == "qux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("2").b == "quux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("3").b == "foobar");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const auto foobars = toml::get<std::map<std::string, extlib2::foobar>>(v);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.size()  == 4ul);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("0").a == 42);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("1").a == 43);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("2").a == 44);
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("3").a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("0").b == "baz");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("1").b == "qux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("2").b == "quux");
 | 
				
			||||||
 | 
					            BOOST_TEST(foobars.at("3").b == "foobar");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					            v{
 | 
				
			||||||
 | 
					                {"0", toml::table{{"a", 42}, {"b", "baz"}}},
 | 
				
			||||||
 | 
					                {"1", toml::table{{"a", 43}, {"b", "qux"}}},
 | 
				
			||||||
 | 
					                {"2", toml::table{{"a", 44}, {"b", "quux"}}},
 | 
				
			||||||
 | 
					                {"3", toml::table{{"a", 45}, {"b", "foobar"}}}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.size()  == 4ul);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("0").a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("1").a == 43);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("2").a == 44);
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("3").a == 45);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("0").b == "baz");
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("1").b == "qux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("2").b == "quux");
 | 
				
			||||||
 | 
					        BOOST_TEST(foobars.at("3").b == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace extlib3
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct foo
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct bar
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int         a;
 | 
				
			||||||
 | 
					    std::string b;
 | 
				
			||||||
 | 
					    foo         f;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // extlib3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::foo, a, b)
 | 
				
			||||||
 | 
					TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::bar, a, b, f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_conversion_via_macro)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foo = toml::get<extlib3::foo>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::value v2(foo);
 | 
				
			||||||
 | 
					        BOOST_TEST(v2 == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque> v{
 | 
				
			||||||
 | 
					            {"a", 42}, {"b", "baz"}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto foo = toml::get<extlib3::foo>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(foo.b == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque> v2(foo);
 | 
				
			||||||
 | 
					        BOOST_TEST(v2 == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v{
 | 
				
			||||||
 | 
					            {"a", 42},
 | 
				
			||||||
 | 
					            {"b", "bar.b"},
 | 
				
			||||||
 | 
					            {"f", toml::table{{"a", 42}, {"b", "foo.b"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bar = toml::get<extlib3::bar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.b == "bar.b");
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.f.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.f.b == "foo.b");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::value v2(bar);
 | 
				
			||||||
 | 
					        BOOST_TEST(v2 == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque> v{
 | 
				
			||||||
 | 
					            {"a", 42},
 | 
				
			||||||
 | 
					            {"b", "bar.b"},
 | 
				
			||||||
 | 
					            {"f", toml::table{{"a", 42}, {"b", "foo.b"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto bar = toml::get<extlib3::bar>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.b == "bar.b");
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.f.a == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(bar.f.b == "foo.b");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const toml::basic_value<toml::discard_comments, std::map, std::deque> v2(bar);
 | 
				
			||||||
 | 
					        BOOST_TEST(v2 == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif // TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,827 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using test_value_types = std::tuple<
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments,  std::map, std::deque>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					    >;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_throws)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					    // const-reference version
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // value is not a table
 | 
				
			||||||
 | 
					        const toml::value v(true);
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not the expected type
 | 
				
			||||||
 | 
					        const toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not found
 | 
				
			||||||
 | 
					        const toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::integer>(v, "different_key"),
 | 
				
			||||||
 | 
					                          std::out_of_range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the positive control.
 | 
				
			||||||
 | 
					        const toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == toml::find<int>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					    // reference version
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // value is not a table
 | 
				
			||||||
 | 
					        toml::value v(true);
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not the expected type
 | 
				
			||||||
 | 
					        toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, "key"), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not found
 | 
				
			||||||
 | 
					        toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::integer>(v, "different_key"),
 | 
				
			||||||
 | 
					                          std::out_of_range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the positive control.
 | 
				
			||||||
 | 
					        toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == toml::find<int>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					    // move version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // value is not a table
 | 
				
			||||||
 | 
					        toml::value v(true);
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), "key"), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not the expected type
 | 
				
			||||||
 | 
					        toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), "key"), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not found
 | 
				
			||||||
 | 
					        toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), "different_key"),
 | 
				
			||||||
 | 
					                          std::out_of_range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the positive control.
 | 
				
			||||||
 | 
					        toml::value v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == toml::find<int>(std::move(v), "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_array_throws)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					    // const-reference version
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // value is not an array
 | 
				
			||||||
 | 
					        const toml::value v(true);
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not the expected type
 | 
				
			||||||
 | 
					        const toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not found
 | 
				
			||||||
 | 
					        const toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the positive control.
 | 
				
			||||||
 | 
					        const toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_TEST(3 == toml::find<int>(v, 2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					    // non-const reference version
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // value is not an array
 | 
				
			||||||
 | 
					        toml::value v(true);
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not the expected type
 | 
				
			||||||
 | 
					        toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(v, 0), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not found
 | 
				
			||||||
 | 
					        toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::integer>(v, 6), std::out_of_range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the positive control.
 | 
				
			||||||
 | 
					        toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_TEST(3 == toml::find<int>(v, 2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // -----------------------------------------------------------------------
 | 
				
			||||||
 | 
					    // move version
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // value is not an array
 | 
				
			||||||
 | 
					        toml::value v(true);
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not the expected type
 | 
				
			||||||
 | 
					        toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::boolean>(std::move(v), 0), toml::type_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the value corresponding to the key is not found
 | 
				
			||||||
 | 
					        toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::find<toml::integer>(std::move(v), 6), std::out_of_range);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // the positive control.
 | 
				
			||||||
 | 
					        toml::value v{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					        BOOST_TEST(3 == toml::find<int>(std::move(v), 2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_recursive)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // recursively search tables
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v{
 | 
				
			||||||
 | 
					            {"a", {
 | 
				
			||||||
 | 
					                {"b", {
 | 
				
			||||||
 | 
					                    {"c", {
 | 
				
			||||||
 | 
					                        {"d", 42}
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == toml::find<int>(v, "a", "b", "c", "d"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reference that can be used to modify the content
 | 
				
			||||||
 | 
					        auto& num = toml::find<toml::integer>(v, "a", "b", "c", "d");
 | 
				
			||||||
 | 
					        num = 54;
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == toml::find<int>(v, "a", "b", "c", "d"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const std::string a("a"), b("b"), c("c"), d("d");
 | 
				
			||||||
 | 
					        auto& num2 = toml::find<toml::integer>(v, a, b, c, d);
 | 
				
			||||||
 | 
					        num2 = 42;
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == toml::find<int>(v, a, b, c, d));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto num3 = toml::find<toml::integer>(v, a, "b", c, "d");
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == num3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto num4 = toml::find<toml::integer>(std::move(v), a, b, c, d);
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == num4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // recursively search arrays
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v{
 | 
				
			||||||
 | 
					            toml::array{"array", "of", "string"},
 | 
				
			||||||
 | 
					            toml::array{toml::array{1, 2, 3}, toml::array{3.14, 2.71}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        BOOST_TEST("array"  == toml::find<std::string>(v, 0, 0));
 | 
				
			||||||
 | 
					        BOOST_TEST("of"     == toml::find<std::string>(v, 0, 1));
 | 
				
			||||||
 | 
					        BOOST_TEST("string" == toml::find<std::string>(v, 0, 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(1 == toml::find<int>(v, 1, 0, 0));
 | 
				
			||||||
 | 
					        BOOST_TEST(2 == toml::find<int>(v, 1, 0, 1));
 | 
				
			||||||
 | 
					        BOOST_TEST(3 == toml::find<int>(v, 1, 0, 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, 1, 1, 0));
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71 == toml::find<double>(v, 1, 1, 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reference that can be used to modify the content
 | 
				
			||||||
 | 
					        auto& num = toml::find<toml::integer>(v, 1, 0, 2);
 | 
				
			||||||
 | 
					        num = 42;
 | 
				
			||||||
 | 
					        BOOST_TEST( 1 == toml::find<int>(v, 1, 0, 0));
 | 
				
			||||||
 | 
					        BOOST_TEST( 2 == toml::find<int>(v, 1, 0, 1));
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == toml::find<int>(v, 1, 0, 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // move value
 | 
				
			||||||
 | 
					        auto num2 = toml::find<toml::integer>(std::move(v), 1, 0, 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == num2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // recursively search mixtures
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v = toml::table{{"array", toml::array{
 | 
				
			||||||
 | 
					                toml::array{1,   2,   3},
 | 
				
			||||||
 | 
					                toml::array{
 | 
				
			||||||
 | 
					                    toml::table{{"foo", "bar"}, {"baz", "qux"}},
 | 
				
			||||||
 | 
					                    toml::table{{"pi",   3.14}, {"e",    2.71}}
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					            }};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(1 == toml::find<int>(v, "array", 0, 0));
 | 
				
			||||||
 | 
					        BOOST_TEST(2 == toml::find<int>(v, "array", 0, 1));
 | 
				
			||||||
 | 
					        BOOST_TEST(3 == toml::find<int>(v, "array", 0, 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("bar" == toml::find<std::string>(v, "array", 1, 0, "foo"));
 | 
				
			||||||
 | 
					        BOOST_TEST("qux" == toml::find<std::string>(v, "array", 1, 0, "baz"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, "pi"));
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71 == toml::find<double>(v, "array", 1, 1, "e"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const std::string ar("array");
 | 
				
			||||||
 | 
					        const auto ar_c = "array";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const std::string pi("pi");
 | 
				
			||||||
 | 
					        const auto pi_c = "pi";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, "pi"));
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, pi));
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, ar, 1, 1, pi_c));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, "pi"));
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, pi));
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, ar_c, 1, 1, pi_c));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, pi));
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == toml::find<double>(v, "array", 1, 1, pi_c));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_exact, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", true}};
 | 
				
			||||||
 | 
					        BOOST_TEST(true == toml::find<toml::boolean>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::boolean>(v, "key") = false;
 | 
				
			||||||
 | 
					        BOOST_TEST(false == toml::find<toml::boolean>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::boolean>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(false == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::integer(42) == toml::find<toml::integer>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::integer>(v, "key") = 54;
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::integer(54) == toml::find<toml::integer>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::integer>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::integer(54) == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", 3.14}};
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::floating(3.14) == toml::find<toml::floating>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::floating>(v, "key") = 2.71;
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::floating(2.71) == toml::find<toml::floating>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::floating>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::floating(2.71) == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", "foo"}};
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
 | 
				
			||||||
 | 
					                          toml::find<toml::string>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::string>(v, "key").str += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
 | 
				
			||||||
 | 
					                          toml::find<toml::string>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::string>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::basic) == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", value_type("foo", toml::string_t::literal)}};
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
 | 
				
			||||||
 | 
					                          toml::find<toml::string>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::string>(v, "key").str += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
 | 
				
			||||||
 | 
					                          toml::find<toml::string>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::string>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::literal) == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::local_date d(2018, toml::month_t::Apr, 22);
 | 
				
			||||||
 | 
					        value_type v{{"key", d}};
 | 
				
			||||||
 | 
					        BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::local_date>(v, "key").year = 2017;
 | 
				
			||||||
 | 
					        d.year = 2017;
 | 
				
			||||||
 | 
					        BOOST_CHECK(d == toml::find<toml::local_date>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::local_date>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(d == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::local_time t(12, 30, 45);
 | 
				
			||||||
 | 
					        value_type v{{"key", t}};
 | 
				
			||||||
 | 
					        BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::local_time>(v, "key").hour = 9;
 | 
				
			||||||
 | 
					        t.hour = 9;
 | 
				
			||||||
 | 
					        BOOST_CHECK(t == toml::find<toml::local_time>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::local_time>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(t == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
 | 
				
			||||||
 | 
					                                toml::local_time(12, 30, 45));
 | 
				
			||||||
 | 
					        value_type v{{"key", dt}};
 | 
				
			||||||
 | 
					        BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::local_datetime>(v, "key").date.year = 2017;
 | 
				
			||||||
 | 
					        dt.date.year = 2017;
 | 
				
			||||||
 | 
					        BOOST_CHECK(dt == toml::find<toml::local_datetime>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::local_datetime>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(dt == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::offset_datetime dt(toml::local_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date(2018, toml::month_t::Apr, 22),
 | 
				
			||||||
 | 
					                    toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
 | 
				
			||||||
 | 
					        value_type v{{"key", dt}};
 | 
				
			||||||
 | 
					        BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<toml::offset_datetime>(v, "key").date.year = 2017;
 | 
				
			||||||
 | 
					        dt.date.year = 2017;
 | 
				
			||||||
 | 
					        BOOST_CHECK(dt == toml::find<toml::offset_datetime>(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<toml::offset_datetime>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(dt == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::array_type vec;
 | 
				
			||||||
 | 
					        vec.push_back(value_type(42));
 | 
				
			||||||
 | 
					        vec.push_back(value_type(54));
 | 
				
			||||||
 | 
					        value_type v{{"key", vec}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const bool result1 = (vec == toml::find<typename value_type::array_type>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_CHECK(result1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<typename value_type::array_type>(v, "key").push_back(value_type(123));
 | 
				
			||||||
 | 
					        vec.push_back(value_type(123));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const bool result2 = (vec == toml::find<typename value_type::array_type>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_CHECK(result2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<typename value_type::array_type>(std::move(v), "key");
 | 
				
			||||||
 | 
					        const bool result3 = (vec == moved);
 | 
				
			||||||
 | 
					        BOOST_CHECK(result3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::table_type tab;
 | 
				
			||||||
 | 
					        tab["key1"] = value_type(42);
 | 
				
			||||||
 | 
					        tab["key2"] = value_type(3.14);
 | 
				
			||||||
 | 
					        value_type v{{"key", tab}};
 | 
				
			||||||
 | 
					        const bool result1 = (tab == toml::find<typename value_type::table_type>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_CHECK(result1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::find<typename value_type::table_type>(v, "key")["key3"] = value_type(123);
 | 
				
			||||||
 | 
					        tab["key3"] = value_type(123);
 | 
				
			||||||
 | 
					        const bool result2 = (tab == toml::find<typename value_type::table_type>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_CHECK(result2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find<typename value_type::table_type>(std::move(v), "key");
 | 
				
			||||||
 | 
					        const bool result3 = (tab == moved);
 | 
				
			||||||
 | 
					        BOOST_CHECK(result3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1(42);
 | 
				
			||||||
 | 
					        value_type v{{"key", v1}};
 | 
				
			||||||
 | 
					        BOOST_CHECK(v1 == toml::find(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        value_type v2(54);
 | 
				
			||||||
 | 
					        toml::find(v, "key") = v2;
 | 
				
			||||||
 | 
					        BOOST_CHECK(v2 == toml::find(v, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved = toml::find(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(v2 == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_integer_type, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(int(42)           == toml::find<int          >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(short(42)         == toml::find<short        >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(char(42)          == toml::find<char         >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(unsigned(42)      == toml::find<unsigned     >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(long(42)          == toml::find<long         >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::int64_t(42)  == toml::find<std::int64_t >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::uint64_t(42) == toml::find<std::uint64_t>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::int16_t(42)  == toml::find<std::int16_t >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::uint16_t(42) == toml::find<std::uint16_t>(std::move(v), "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_floating_type, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", 3.14}};
 | 
				
			||||||
 | 
					        const double ref(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float      >(ref) == toml::find<float      >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(                         ref  == toml::find<double     >(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<long double>(ref) == toml::find<long double>(v, "key"));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float      >(ref) == toml::find<float      >(std::move(v), "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_string_type, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", toml::string("foo", toml::string_t::basic)}};
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::find<std::string>(v, "key"));
 | 
				
			||||||
 | 
					        toml::find<std::string>(v, "key") += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::find<std::string>(v, "key"));
 | 
				
			||||||
 | 
					        toml::find<std::string>(v, "key") += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find<std::string>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
 | 
				
			||||||
 | 
					        const auto moved = toml::find<std::string>(std::move(v), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", toml::string("foo", toml::string_t::basic)}};
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::find<std::string_view>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{{"key", toml::string("foo", toml::string_t::literal)}};
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::find<std::string_view>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type v{{"key", {42, 54, 69, 72}}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::vector<int>         vec = toml::find<std::vector<int>>(v, "key");
 | 
				
			||||||
 | 
					    const std::list<short>         lst = toml::find<std::list<short>>(v, "key");
 | 
				
			||||||
 | 
					    const std::deque<std::int64_t> deq = toml::find<std::deque<std::int64_t>>(v, "key");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(42 == vec.at(0));
 | 
				
			||||||
 | 
					    BOOST_TEST(54 == vec.at(1));
 | 
				
			||||||
 | 
					    BOOST_TEST(69 == vec.at(2));
 | 
				
			||||||
 | 
					    BOOST_TEST(72 == vec.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::list<short>::const_iterator iter = lst.begin();
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(42) == *(iter++));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(54) == *(iter++));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(69) == *(iter++));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(72) == *(iter++));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::array<int, 4> ary = toml::find<std::array<int, 4>>(v, "key");
 | 
				
			||||||
 | 
					    BOOST_TEST(42 == ary.at(0));
 | 
				
			||||||
 | 
					    BOOST_TEST(54 == ary.at(1));
 | 
				
			||||||
 | 
					    BOOST_TEST(69 == ary.at(2));
 | 
				
			||||||
 | 
					    BOOST_TEST(72 == ary.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::tuple<int, short, unsigned, long> tpl =
 | 
				
			||||||
 | 
					        toml::find<std::tuple<int, short, unsigned, long>>(v, "key");
 | 
				
			||||||
 | 
					    BOOST_TEST(                      42  == std::get<0>(tpl));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short   >(54) == std::get<1>(tpl));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<long    >(72) == std::get<3>(tpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_type p{{"key", {3.14, 2.71}}};
 | 
				
			||||||
 | 
					    std::pair<double, double> pr = toml::find<std::pair<double, double> >(p, "key");
 | 
				
			||||||
 | 
					    BOOST_TEST(3.14 == pr.first);
 | 
				
			||||||
 | 
					    BOOST_TEST(2.71 == pr.second);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type v1{{"key", {42, 54, 69, 72}}};
 | 
				
			||||||
 | 
					    value_type v2{{"key", {42, 54, 69, 72}}};
 | 
				
			||||||
 | 
					    value_type v3{{"key", {42, 54, 69, 72}}};
 | 
				
			||||||
 | 
					    value_type v4{{"key", {42, 54, 69, 72}}};
 | 
				
			||||||
 | 
					    value_type v5{{"key", {42, 54, 69, 72}}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::vector<int>         vec = toml::find<std::vector<int>>(std::move(v1), "key");
 | 
				
			||||||
 | 
					    const std::list<short>         lst = toml::find<std::list<short>>(std::move(v2), "key");
 | 
				
			||||||
 | 
					    const std::deque<std::int64_t> deq = toml::find<std::deque<std::int64_t>>(std::move(v3), "key");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(42 == vec.at(0));
 | 
				
			||||||
 | 
					    BOOST_TEST(54 == vec.at(1));
 | 
				
			||||||
 | 
					    BOOST_TEST(69 == vec.at(2));
 | 
				
			||||||
 | 
					    BOOST_TEST(72 == vec.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::list<short>::const_iterator iter = lst.begin();
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(42) == *(iter++));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(54) == *(iter++));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(69) == *(iter++));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short>(72) == *(iter++));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::array<int, 4> ary = toml::find<std::array<int, 4>>(std::move(v4), "key");
 | 
				
			||||||
 | 
					    BOOST_TEST(42 == ary.at(0));
 | 
				
			||||||
 | 
					    BOOST_TEST(54 == ary.at(1));
 | 
				
			||||||
 | 
					    BOOST_TEST(69 == ary.at(2));
 | 
				
			||||||
 | 
					    BOOST_TEST(72 == ary.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::tuple<int, short, unsigned, long> tpl =
 | 
				
			||||||
 | 
					        toml::find<std::tuple<int, short, unsigned, long>>(std::move(v5), "key");
 | 
				
			||||||
 | 
					    BOOST_TEST(                      42  == std::get<0>(tpl));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<short   >(54) == std::get<1>(tpl));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
 | 
				
			||||||
 | 
					    BOOST_TEST(static_cast<long    >(72) == std::get<3>(tpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_type p{{"key", {3.14, 2.71}}};
 | 
				
			||||||
 | 
					    std::pair<double, double> pr = toml::find<std::pair<double, double> >(std::move(p), "key");
 | 
				
			||||||
 | 
					    BOOST_TEST(3.14 == pr.first);
 | 
				
			||||||
 | 
					    BOOST_TEST(2.71 == pr.second);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_array_of_array, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type v1{42, 54, 69, 72};
 | 
				
			||||||
 | 
					    value_type v2{"foo", "bar", "baz"};
 | 
				
			||||||
 | 
					    value_type v{{"key", {v1, v2}}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::pair<std::vector<int>, std::vector<std::string>> p =
 | 
				
			||||||
 | 
					        toml::find<std::pair<std::vector<int>, std::vector<std::string>>>(v, "key");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(0) == 42);
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(1) == 54);
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(2) == 69);
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(p.second.at(0) == "foo");
 | 
				
			||||||
 | 
					    BOOST_TEST(p.second.at(1) == "bar");
 | 
				
			||||||
 | 
					    BOOST_TEST(p.second.at(2) == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::tuple<std::vector<int>, std::vector<std::string>> t =
 | 
				
			||||||
 | 
					        toml::find<std::tuple<std::vector<int>, std::vector<std::string>>>(v, "key");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(0) == 42);
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(1) == 54);
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(2) == 69);
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<1>(t).at(0) == "foo");
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<1>(t).at(1) == "bar");
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<1>(t).at(2) == "baz");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_move_toml_array_of_array, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type a1{42, 54, 69, 72};
 | 
				
			||||||
 | 
					    value_type a2{"foo", "bar", "baz"};
 | 
				
			||||||
 | 
					    value_type v1{{"key", {a1, a2}}};
 | 
				
			||||||
 | 
					    value_type v2{{"key", {a1, a2}}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::pair<std::vector<int>, std::vector<std::string>> p =
 | 
				
			||||||
 | 
					        toml::find<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v1), "key");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(0) == 42);
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(1) == 54);
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(2) == 69);
 | 
				
			||||||
 | 
					    BOOST_TEST(p.first.at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(p.second.at(0) == "foo");
 | 
				
			||||||
 | 
					    BOOST_TEST(p.second.at(1) == "bar");
 | 
				
			||||||
 | 
					    BOOST_TEST(p.second.at(2) == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::tuple<std::vector<int>, std::vector<std::string>> t =
 | 
				
			||||||
 | 
					        toml::find<std::tuple<std::vector<int>, std::vector<std::string>>>(std::move(v2), "key");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(0) == 42);
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(1) == 54);
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(2) == 69);
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<0>(t).at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<1>(t).at(0) == "foo");
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<1>(t).at(1) == "bar");
 | 
				
			||||||
 | 
					    BOOST_TEST(std::get<1>(t).at(2) == "baz");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_table, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", {
 | 
				
			||||||
 | 
					                {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
 | 
				
			||||||
 | 
					            }}};
 | 
				
			||||||
 | 
					        const auto v = toml::find<std::map<std::string, int>>(v1, "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key1") == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key2") == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key3") == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key4") == 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", {
 | 
				
			||||||
 | 
					                {"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}
 | 
				
			||||||
 | 
					            }}};
 | 
				
			||||||
 | 
					        const auto v = toml::find<std::map<std::string, int>>(std::move(v1), "key");
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key1") == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key2") == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key3") == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key4") == 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_date, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
 | 
				
			||||||
 | 
					        const auto date = std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                toml::find<std::chrono::system_clock::time_point>(v1, "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_year = 2018 - 1900;
 | 
				
			||||||
 | 
					        t.tm_mon  = 4    - 1;
 | 
				
			||||||
 | 
					        t.tm_mday = 1;
 | 
				
			||||||
 | 
					        t.tm_hour = 0;
 | 
				
			||||||
 | 
					        t.tm_min  = 0;
 | 
				
			||||||
 | 
					        t.tm_sec  = 0;
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					        const auto c = std::mktime(&t);
 | 
				
			||||||
 | 
					        BOOST_TEST(c == date);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::local_date{2018, toml::month_t::Apr, 1}}};
 | 
				
			||||||
 | 
					        const auto date = std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_year = 2018 - 1900;
 | 
				
			||||||
 | 
					        t.tm_mon  = 4    - 1;
 | 
				
			||||||
 | 
					        t.tm_mday = 1;
 | 
				
			||||||
 | 
					        t.tm_hour = 0;
 | 
				
			||||||
 | 
					        t.tm_min  = 0;
 | 
				
			||||||
 | 
					        t.tm_sec  = 0;
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					        const auto c = std::mktime(&t);
 | 
				
			||||||
 | 
					        BOOST_TEST(c == date);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_time, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::local_time{12, 30, 45}}};
 | 
				
			||||||
 | 
					        const auto time = toml::find<std::chrono::seconds>(v1, "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(time == std::chrono::hours(12) +
 | 
				
			||||||
 | 
					                            std::chrono::minutes(30) + std::chrono::seconds(45));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::local_time{12, 30, 45}}};
 | 
				
			||||||
 | 
					        const auto time = toml::find<std::chrono::seconds>(std::move(v1), "key");
 | 
				
			||||||
 | 
					        BOOST_CHECK(time == std::chrono::hours(12) +
 | 
				
			||||||
 | 
					                            std::chrono::minutes(30) + std::chrono::seconds(45));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_toml_local_datetime, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::local_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                    toml::local_time{12, 30, 45})}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto date = std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                toml::find<std::chrono::system_clock::time_point>(v1, "key"));
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_year = 2018 - 1900;
 | 
				
			||||||
 | 
					        t.tm_mon  = 4    - 1;
 | 
				
			||||||
 | 
					        t.tm_mday = 1;
 | 
				
			||||||
 | 
					        t.tm_hour = 12;
 | 
				
			||||||
 | 
					        t.tm_min  = 30;
 | 
				
			||||||
 | 
					        t.tm_sec  = 45;
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					        const auto c = std::mktime(&t);
 | 
				
			||||||
 | 
					        BOOST_TEST(c == date);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::local_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                    toml::local_time{12, 30, 45})}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto date = std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key"));
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_year = 2018 - 1900;
 | 
				
			||||||
 | 
					        t.tm_mon  = 4    - 1;
 | 
				
			||||||
 | 
					        t.tm_mday = 1;
 | 
				
			||||||
 | 
					        t.tm_hour = 12;
 | 
				
			||||||
 | 
					        t.tm_min  = 30;
 | 
				
			||||||
 | 
					        t.tm_sec  = 45;
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					        const auto c = std::mktime(&t);
 | 
				
			||||||
 | 
					        BOOST_TEST(c == date);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::offset_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                    toml::local_time{12, 30, 0},
 | 
				
			||||||
 | 
					                    toml::time_offset{9, 0})}};
 | 
				
			||||||
 | 
					        //    2018-04-01T12:30:00+09:00
 | 
				
			||||||
 | 
					        // == 2018-04-01T03:30:00Z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto date = toml::find<std::chrono::system_clock::time_point>(v1, "key");
 | 
				
			||||||
 | 
					        const auto timet = std::chrono::system_clock::to_time_t(date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // get time_t as gmtime (2018-04-01T03:30:00Z)
 | 
				
			||||||
 | 
					        const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
 | 
				
			||||||
 | 
					        BOOST_CHECK(tmp);
 | 
				
			||||||
 | 
					        const auto tm = *tmp;
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_year + 1900 == 2018);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_mon  + 1 ==       4);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_mday ==           1);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_hour ==           3);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_min ==           30);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_sec ==            0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::offset_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                    toml::local_time{12, 30, 0},
 | 
				
			||||||
 | 
					                    toml::time_offset{-8, 0})}};
 | 
				
			||||||
 | 
					        //    2018-04-01T12:30:00-08:00
 | 
				
			||||||
 | 
					        // == 2018-04-01T20:30:00Z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto date = toml::find<std::chrono::system_clock::time_point>(v1, "key");
 | 
				
			||||||
 | 
					        const auto timet = std::chrono::system_clock::to_time_t(date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // get time_t as gmtime (2018-04-01T03:30:00Z)
 | 
				
			||||||
 | 
					        const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
 | 
				
			||||||
 | 
					        BOOST_CHECK(tmp);
 | 
				
			||||||
 | 
					        const auto tm = *tmp;
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_year + 1900 == 2018);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_mon  + 1 ==       4);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_mday ==           1);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_hour ==          20);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_min ==           30);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_sec ==            0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{{"key", toml::offset_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                    toml::local_time{12, 30, 0},
 | 
				
			||||||
 | 
					                    toml::time_offset{-8, 0})}};
 | 
				
			||||||
 | 
					        //    2018-04-01T12:30:00-08:00
 | 
				
			||||||
 | 
					        // == 2018-04-01T20:30:00Z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto date = toml::find<std::chrono::system_clock::time_point>(std::move(v1), "key");
 | 
				
			||||||
 | 
					        const auto timet = std::chrono::system_clock::to_time_t(date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // get time_t as gmtime (2018-04-01T03:30:00Z)
 | 
				
			||||||
 | 
					        const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
 | 
				
			||||||
 | 
					        BOOST_CHECK(tmp);
 | 
				
			||||||
 | 
					        const auto tm = *tmp;
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_year + 1900 == 2018);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_mon  + 1 ==       4);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_mday ==           1);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_hour ==          20);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_min ==           30);
 | 
				
			||||||
 | 
					        BOOST_TEST(tm.tm_sec ==            0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,538 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using test_value_types = std::tuple<
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments,  std::map, std::deque>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace test
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits,
 | 
				
			||||||
 | 
					         typename Key, typename Value, typename Comp, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os,
 | 
				
			||||||
 | 
					           const std::map<Key, Value, Comp, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits,
 | 
				
			||||||
 | 
					         typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os,
 | 
				
			||||||
 | 
					           const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr)\
 | 
				
			||||||
 | 
					    {                                                           \
 | 
				
			||||||
 | 
					        using namespace test;                                   \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                  \
 | 
				
			||||||
 | 
					        const toml::toml_type opt  opt_expr ;                   \
 | 
				
			||||||
 | 
					        const value_type v{{"key", init}};                      \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);                                \
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::find_or(v, "key", opt));       \
 | 
				
			||||||
 | 
					    }                                                           \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        const typename value_type::array_type opt {6,7,8,9,10};
 | 
				
			||||||
 | 
					        const value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::find_or(v, "key", opt));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        const value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::find_or(v, "key", opt));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_EXACT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr)   \
 | 
				
			||||||
 | 
					    {                                                              \
 | 
				
			||||||
 | 
					        using namespace test;                                      \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                     \
 | 
				
			||||||
 | 
					        toml::toml_type opt  opt_expr ;                            \
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};                               \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);                                   \
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "key", std::move(opt));\
 | 
				
			||||||
 | 
					        BOOST_TEST(init == moved);                                 \
 | 
				
			||||||
 | 
					    }                                                              \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt {6,7,8,9,10};
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
 | 
				
			||||||
 | 
					        BOOST_TEST(init == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
 | 
				
			||||||
 | 
					        BOOST_TEST(init == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_MOVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
 | 
				
			||||||
 | 
					    {                                                             \
 | 
				
			||||||
 | 
					        using namespace test;                                     \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                    \
 | 
				
			||||||
 | 
					        toml::toml_type       opt1 opt_expr ;                     \
 | 
				
			||||||
 | 
					        toml::toml_type       opt2 opt_expr ;                     \
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};                              \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);                                 \
 | 
				
			||||||
 | 
					        toml::find_or(v, "key", opt2) = opt1;                     \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::find<toml::toml_type>(v, "key"));\
 | 
				
			||||||
 | 
					    }                                                             \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt1{6,7,8,9,10};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt2{6,7,8,9,10};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        toml::find_or(v, "key", opt2) = opt1;
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::find<typename value_type::array_type>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);
 | 
				
			||||||
 | 
					        toml::find_or(v, "key", opt2) = opt1;
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::find<typename value_type::table_type>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_MODIFY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type)         \
 | 
				
			||||||
 | 
					    {                                                             \
 | 
				
			||||||
 | 
					        using namespace test;                                     \
 | 
				
			||||||
 | 
					        value_type v(init_type);                                  \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt_type == toml::find_or(v, "key", opt_type));\
 | 
				
			||||||
 | 
					    }                                                             \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::boolean         boolean        (true);
 | 
				
			||||||
 | 
					    const toml::integer         integer        (42);
 | 
				
			||||||
 | 
					    const toml::floating        floating       (3.14);
 | 
				
			||||||
 | 
					    const toml::string          string         ("foo");
 | 
				
			||||||
 | 
					    const toml::local_time      local_time     (12, 30, 45);
 | 
				
			||||||
 | 
					    const toml::local_date      local_date     (2019, toml::month_t::Apr, 1);
 | 
				
			||||||
 | 
					    const toml::local_datetime  local_datetime (
 | 
				
			||||||
 | 
					            toml::local_date(2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					            toml::local_time(12, 30, 45));
 | 
				
			||||||
 | 
					    const toml::offset_datetime offset_datetime(
 | 
				
			||||||
 | 
					            toml::local_date(2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					            toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using array_type = typename value_type::array_type;
 | 
				
			||||||
 | 
					    using table_type = typename value_type::table_type;
 | 
				
			||||||
 | 
					    const array_type array{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					    const table_type table{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, array          );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_FALLBACK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_or_integer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v{{"num", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(42u == toml::find_or(v, "num", 0u));
 | 
				
			||||||
 | 
					        BOOST_TEST(0u ==  toml::find_or(v, "foo", 0u));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v{{"num", 42}};
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "num", 0u);
 | 
				
			||||||
 | 
					        BOOST_TEST(42u == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v{{"num", 42}};
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "foo", 0u);
 | 
				
			||||||
 | 
					        BOOST_TEST(0u ==  moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_or_floating)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1{{"key", 42}};
 | 
				
			||||||
 | 
					        toml::value v2{{"key", 3.14}};
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f));
 | 
				
			||||||
 | 
					        const double ref(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float>(ref) == toml::find_or(v2, "key", 2.71f));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1{{"key", 42}};
 | 
				
			||||||
 | 
					        toml::value v2{{"key", 3.14}};
 | 
				
			||||||
 | 
					        const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f);
 | 
				
			||||||
 | 
					        const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f);
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71f == moved1);
 | 
				
			||||||
 | 
					        const double ref(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float>(ref) == moved2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_or_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1 = toml::table{{"key", "foobar"}};
 | 
				
			||||||
 | 
					        toml::value v2 = toml::table{{"key", 42}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string       s1("bazqux");
 | 
				
			||||||
 | 
					        const std::string s2("bazqux");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find_or(v1, "key", s1));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::find_or(v2, "key", s1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string& v1r = toml::find_or(v1, "key", s1);
 | 
				
			||||||
 | 
					        std::string& s1r = toml::find_or(v2, "key", s1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == v1r);
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == s1r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find_or(v1, "key", s2));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::find_or(v2, "key", s2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find_or(std::move(v1), "key", std::move(s1)));
 | 
				
			||||||
 | 
					        s1 = "bazqux"; // restoring moved value
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::find_or(std::move(v2), "key", std::move(s1)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1 = toml::table{{"key", "foobar"}};
 | 
				
			||||||
 | 
					        toml::value v2 = toml::table{{"key", 42}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string s1("bazqux");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved1 = toml::find_or(std::move(v1), "key", s1);
 | 
				
			||||||
 | 
					        const auto moved2 = toml::find_or(std::move(v2), "key", s1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == moved1);
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == moved2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1 = toml::table{{"key", "foobar"}};
 | 
				
			||||||
 | 
					        toml::value v2 = toml::table{{"key", 42}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string s1("bazqux");
 | 
				
			||||||
 | 
					        std::string s2("bazqux");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved1 = toml::find_or(std::move(v1), "key", std::move(s1));
 | 
				
			||||||
 | 
					        const auto moved2 = toml::find_or(std::move(v2), "key", std::move(s2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == moved1);
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == moved2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // string literal
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1 = toml::table{{"key", "foobar"}};
 | 
				
			||||||
 | 
					        toml::value v2 = toml::table{{"key",42}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find_or(v1, "key", "bazqux"));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::find_or(v2, "key", "bazqux"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const char* lit = "bazqux";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::find_or(v1, "key", lit));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1 = toml::table{{"key", "foobar"}};
 | 
				
			||||||
 | 
					        toml::value v2 = toml::table{{"key",42}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto moved1 = toml::find_or(std::move(v1), "key", "bazqux");
 | 
				
			||||||
 | 
					        const auto moved2 = toml::find_or(std::move(v2), "key", "bazqux");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == moved1);
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == moved2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1 = toml::table{{"key", "foobar"}};
 | 
				
			||||||
 | 
					        toml::value v2 = toml::table{{"key",42}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const char* lit = "bazqux";
 | 
				
			||||||
 | 
					        const auto moved1 = toml::find_or(std::move(v1), "key", lit);
 | 
				
			||||||
 | 
					        const auto moved2 = toml::find_or(std::move(v2), "key", lit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == moved1);
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == moved2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_find_or_map)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using map_type = std::map<std::string, std::string>;
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1{
 | 
				
			||||||
 | 
					            {"key", {{"key", "value"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto key  = toml::find_or(v1, "key",  map_type{});
 | 
				
			||||||
 | 
					        const auto key2 = toml::find_or(v1, "key2", map_type{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!key.empty());
 | 
				
			||||||
 | 
					        BOOST_TEST(key2.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(key.size()    == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(key.at("key") == "value");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1{
 | 
				
			||||||
 | 
					            {"key", {{"key", "value"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto key  = toml::find_or<map_type>(v1, "key",  map_type{});
 | 
				
			||||||
 | 
					        const auto key2 = toml::find_or<map_type>(v1, "key2", map_type{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!key.empty());
 | 
				
			||||||
 | 
					        BOOST_TEST(key2.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(key.size()    == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(key.at("key") == "value");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1{
 | 
				
			||||||
 | 
					            {"key", {{"key", "value"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        toml::value v2(v1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto key  = toml::find_or(std::move(v1), "key",  map_type{});
 | 
				
			||||||
 | 
					        const auto key2 = toml::find_or(std::move(v2), "key2", map_type{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!key.empty());
 | 
				
			||||||
 | 
					        BOOST_TEST(key2.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(key.size()    == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(key.at("key") == "value");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1{
 | 
				
			||||||
 | 
					            {"key", {{"key", "value"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        toml::value v2(v1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto key  = toml::find_or<map_type>(std::move(v1), "key",  map_type{});
 | 
				
			||||||
 | 
					        const auto key2 = toml::find_or<map_type>(std::move(v2), "key2", map_type{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!key.empty());
 | 
				
			||||||
 | 
					        BOOST_TEST(key2.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(key.size()    == 1u);
 | 
				
			||||||
 | 
					        BOOST_TEST(key.at("key") == "value");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,393 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using test_value_types = std::tuple<
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments,  std::map, std::deque>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace test
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits,
 | 
				
			||||||
 | 
					         typename Key, typename Value, typename Comp, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os,
 | 
				
			||||||
 | 
					           const std::map<Key, Value, Comp, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits,
 | 
				
			||||||
 | 
					         typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os,
 | 
				
			||||||
 | 
					           const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr) \
 | 
				
			||||||
 | 
					    {                                                             \
 | 
				
			||||||
 | 
					        using namespace test;                                     \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                    \
 | 
				
			||||||
 | 
					        const toml::toml_type opt  opt_expr ;                     \
 | 
				
			||||||
 | 
					        const value_type v{{"key1", value_type{{"key2", init}} }};\
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);                                  \
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::find_or(v, "key1", "key2", opt));\
 | 
				
			||||||
 | 
					    }                                                             \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                               (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_EXACT(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        const typename value_type::array_type opt {6,7,8,9,10};
 | 
				
			||||||
 | 
					        const value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::find_or(v, "key", opt));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        const value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::find_or(v, "key", opt));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_EXACT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr)   \
 | 
				
			||||||
 | 
					    {                                                              \
 | 
				
			||||||
 | 
					        using namespace test;                                      \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                     \
 | 
				
			||||||
 | 
					        toml::toml_type opt  opt_expr ;                            \
 | 
				
			||||||
 | 
					        value_type v{{"key1", value_type{{"key2", init}} }};       \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);                                   \
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "key1", "key2", std::move(opt));\
 | 
				
			||||||
 | 
					        BOOST_TEST(init == moved);                                 \
 | 
				
			||||||
 | 
					    }                                                              \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MOVE(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt {6,7,8,9,10};
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
 | 
				
			||||||
 | 
					        BOOST_TEST(init == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
 | 
				
			||||||
 | 
					        BOOST_TEST(init == moved);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_MOVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
 | 
				
			||||||
 | 
					    {                                                             \
 | 
				
			||||||
 | 
					        using namespace test;                                     \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                    \
 | 
				
			||||||
 | 
					        toml::toml_type       opt1 opt_expr ;                     \
 | 
				
			||||||
 | 
					        toml::toml_type       opt2 opt_expr ;                     \
 | 
				
			||||||
 | 
					        value_type v{{"key1", value_type{{"key2", init}} }};      \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);                                 \
 | 
				
			||||||
 | 
					        toml::find_or(v, "key1", "key2", opt2) = opt1;            \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::find<toml::toml_type>(v, "key1", "key2"));\
 | 
				
			||||||
 | 
					    }                                                             \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_MODIFY(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt1{6,7,8,9,10};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt2{6,7,8,9,10};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        toml::find_or(v, "key", opt2) = opt1;
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::find<typename value_type::array_type>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        value_type v{{"key", init}};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);
 | 
				
			||||||
 | 
					        toml::find_or(v, "key", opt2) = opt1;
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::find<typename value_type::table_type>(v, "key"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_MODIFY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type)                   \
 | 
				
			||||||
 | 
					    {                                                                       \
 | 
				
			||||||
 | 
					        using namespace test;                                               \
 | 
				
			||||||
 | 
					        value_type v1{{"key1", value_type{{"key3", "foo"}}}};               \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt_type == toml::find_or(v1, "key1", "key2", opt_type));\
 | 
				
			||||||
 | 
					        value_type v2{{"key1", "foo"}};                                     \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt_type == toml::find_or(v2, "key1", "key3", opt_type));\
 | 
				
			||||||
 | 
					    }                                                                       \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::boolean         boolean        (true);
 | 
				
			||||||
 | 
					    const toml::integer         integer        (42);
 | 
				
			||||||
 | 
					    const toml::floating        floating       (3.14);
 | 
				
			||||||
 | 
					    const toml::string          string         ("foo");
 | 
				
			||||||
 | 
					    const toml::local_time      local_time     (12, 30, 45);
 | 
				
			||||||
 | 
					    const toml::local_date      local_date     (2019, toml::month_t::Apr, 1);
 | 
				
			||||||
 | 
					    const toml::local_datetime  local_datetime (
 | 
				
			||||||
 | 
					            toml::local_date(2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					            toml::local_time(12, 30, 45));
 | 
				
			||||||
 | 
					    const toml::offset_datetime offset_datetime(
 | 
				
			||||||
 | 
					            toml::local_date(2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					            toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using array_type = typename value_type::array_type;
 | 
				
			||||||
 | 
					    using table_type = typename value_type::table_type;
 | 
				
			||||||
 | 
					    const array_type array{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					    const table_type table{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(boolean, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(integer, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(floating, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(string, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_time, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_date, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(local_datetime, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(array, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_FIND_OR_FALLBACK(table, array          );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_FIND_OR_FALLBACK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct move_only_type
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    explicit move_only_type(const std::string& n): name_(n) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void from_toml(const toml::value& v)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->name_ = toml::find<std::string>(v, "name");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    move_only_type(): name_("default"){}
 | 
				
			||||||
 | 
					    ~move_only_type() = default;
 | 
				
			||||||
 | 
					    move_only_type(move_only_type&&)            = default;
 | 
				
			||||||
 | 
					    move_only_type& operator=(move_only_type&&) = default;
 | 
				
			||||||
 | 
					    move_only_type(const move_only_type&)            = delete;
 | 
				
			||||||
 | 
					    move_only_type& operator=(const move_only_type&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool operator==(const move_only_type& other) const noexcept {return this->name_ == other.name_;}
 | 
				
			||||||
 | 
					    bool operator!=(const move_only_type& other) const noexcept {return this->name_ != other.name_;}
 | 
				
			||||||
 | 
					    bool operator< (const move_only_type& other) const noexcept {return this->name_ <  other.name_;}
 | 
				
			||||||
 | 
					    bool operator<=(const move_only_type& other) const noexcept {return this->name_ <= other.name_;}
 | 
				
			||||||
 | 
					    bool operator> (const move_only_type& other) const noexcept {return this->name_ >  other.name_;}
 | 
				
			||||||
 | 
					    bool operator>=(const move_only_type& other) const noexcept {return this->name_ >= other.name_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string name_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::ostream& operator<<(std::ostream& os, const move_only_type& mot)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << mot.name_;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move_only, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const move_only_type ref("reference");
 | 
				
			||||||
 | 
					    move_only_type opt("optional");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v{{"key1", value_type{{"key2", value_type{{"name", "reference"}} }} }};
 | 
				
			||||||
 | 
					        BOOST_TEST(ref == toml::find_or(v, "key1", "key2", std::move(opt)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,72 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// to check it successfully compiles. it does not check the formatted string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_1_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    toml::value val(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string pretty_error =
 | 
				
			||||||
 | 
					            toml::format_error("[error] test error", val, "this is a value");
 | 
				
			||||||
 | 
					        std::cout << pretty_error << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string pretty_error =
 | 
				
			||||||
 | 
					            toml::format_error("[error] test error", val, "this is a value",
 | 
				
			||||||
 | 
					                               {"this is a hint"});
 | 
				
			||||||
 | 
					        std::cout << pretty_error << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_2_values)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    toml::value v1(42);
 | 
				
			||||||
 | 
					    toml::value v2(3.14);
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string pretty_error =
 | 
				
			||||||
 | 
					            toml::format_error("[error] test error with two values",
 | 
				
			||||||
 | 
					                               v1, "this is the answer",
 | 
				
			||||||
 | 
					                               v2, "this is the pi");
 | 
				
			||||||
 | 
					        std::cout << pretty_error << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string pretty_error =
 | 
				
			||||||
 | 
					            toml::format_error("[error] test error with two values",
 | 
				
			||||||
 | 
					                               v1, "this is the answer",
 | 
				
			||||||
 | 
					                               v2, "this is the pi",
 | 
				
			||||||
 | 
					                               {"hint"});
 | 
				
			||||||
 | 
					        std::cout << pretty_error << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_3_values)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    toml::value v1(42);
 | 
				
			||||||
 | 
					    toml::value v2(3.14);
 | 
				
			||||||
 | 
					    toml::value v3("foo");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string pretty_error =
 | 
				
			||||||
 | 
					            toml::format_error("[error] test error with two values",
 | 
				
			||||||
 | 
					                               v1, "this is the answer",
 | 
				
			||||||
 | 
					                               v2, "this is the pi",
 | 
				
			||||||
 | 
					                               v3, "this is a meta-syntactic variable");
 | 
				
			||||||
 | 
					        std::cout << pretty_error << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string pretty_error =
 | 
				
			||||||
 | 
					            toml::format_error("[error] test error with two values",
 | 
				
			||||||
 | 
					                               v1, "this is the answer",
 | 
				
			||||||
 | 
					                               v2, "this is the pi",
 | 
				
			||||||
 | 
					                               v3, "this is a meta-syntactic variable",
 | 
				
			||||||
 | 
					                               {"hint 1", "hint 2"});
 | 
				
			||||||
 | 
					        std::cout << pretty_error << std::endl;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,505 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using test_value_types = std::tuple<
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments,  std::map, std::deque>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v(true);
 | 
				
			||||||
 | 
					        BOOST_TEST(true == toml::get<toml::boolean>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::boolean>(v) = false;
 | 
				
			||||||
 | 
					        BOOST_TEST(false == toml::get<toml::boolean>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::boolean x = toml::get<toml::boolean>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(false == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v(42);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::integer(42) == toml::get<toml::integer>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::integer>(v) = 54;
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::integer x = toml::get<toml::integer>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::integer(54) == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::floating(3.14) == toml::get<toml::floating>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::floating>(v) = 2.71;
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::floating x = toml::get<toml::floating>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::floating(2.71) == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v("foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foo", toml::string_t::basic) ==
 | 
				
			||||||
 | 
					                          toml::get<toml::string>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::string>(v).str += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::basic) ==
 | 
				
			||||||
 | 
					                          toml::get<toml::string>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::string x = toml::get<toml::string>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar") == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v("foo", toml::string_t::literal);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
 | 
				
			||||||
 | 
					                          toml::get<toml::string>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::string>(v).str += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
 | 
				
			||||||
 | 
					                          toml::get<toml::string>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::string x = toml::get<toml::string>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::string("foobar", toml::string_t::literal) == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::local_date d(2018, toml::month_t::Apr, 22);
 | 
				
			||||||
 | 
					        value_type v(d);
 | 
				
			||||||
 | 
					        BOOST_TEST(d == toml::get<toml::local_date>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::local_date>(v).year = 2017;
 | 
				
			||||||
 | 
					        d.year = 2017;
 | 
				
			||||||
 | 
					        BOOST_TEST(d == toml::get<toml::local_date>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::local_date x = toml::get<toml::local_date>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(d == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::local_time t(12, 30, 45);
 | 
				
			||||||
 | 
					        value_type v(t);
 | 
				
			||||||
 | 
					        BOOST_TEST(t == toml::get<toml::local_time>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::local_time>(v).hour = 9;
 | 
				
			||||||
 | 
					        t.hour = 9;
 | 
				
			||||||
 | 
					        BOOST_TEST(t == toml::get<toml::local_time>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::local_time x = toml::get<toml::local_time>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(t == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22),
 | 
				
			||||||
 | 
					                                toml::local_time(12, 30, 45));
 | 
				
			||||||
 | 
					        value_type v(dt);
 | 
				
			||||||
 | 
					        BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::local_datetime>(v).date.year = 2017;
 | 
				
			||||||
 | 
					        dt.date.year = 2017;
 | 
				
			||||||
 | 
					        BOOST_TEST(dt == toml::get<toml::local_datetime>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::local_datetime x = toml::get<toml::local_datetime>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(dt == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::offset_datetime dt(toml::local_datetime(
 | 
				
			||||||
 | 
					                    toml::local_date(2018, toml::month_t::Apr, 22),
 | 
				
			||||||
 | 
					                    toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
 | 
				
			||||||
 | 
					        value_type v(dt);
 | 
				
			||||||
 | 
					        BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<toml::offset_datetime>(v).date.year = 2017;
 | 
				
			||||||
 | 
					        dt.date.year = 2017;
 | 
				
			||||||
 | 
					        BOOST_TEST(dt == toml::get<toml::offset_datetime>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::offset_datetime x = toml::get<toml::offset_datetime>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(dt == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using array_type = typename value_type::array_type;
 | 
				
			||||||
 | 
					        array_type vec;
 | 
				
			||||||
 | 
					        vec.push_back(value_type(42));
 | 
				
			||||||
 | 
					        vec.push_back(value_type(54));
 | 
				
			||||||
 | 
					        value_type v(vec);
 | 
				
			||||||
 | 
					        BOOST_TEST(vec == toml::get<array_type>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<array_type>(v).push_back(value_type(123));
 | 
				
			||||||
 | 
					        vec.push_back(value_type(123));
 | 
				
			||||||
 | 
					        BOOST_TEST(vec == toml::get<array_type>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        array_type x = toml::get<array_type>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(vec == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using table_type = typename value_type::table_type;
 | 
				
			||||||
 | 
					        table_type tab;
 | 
				
			||||||
 | 
					        tab["key1"] = value_type(42);
 | 
				
			||||||
 | 
					        tab["key2"] = value_type(3.14);
 | 
				
			||||||
 | 
					        value_type v(tab);
 | 
				
			||||||
 | 
					        BOOST_TEST(tab == toml::get<table_type>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        toml::get<table_type>(v)["key3"] = value_type(123);
 | 
				
			||||||
 | 
					        tab["key3"] = value_type(123);
 | 
				
			||||||
 | 
					        BOOST_TEST(tab == toml::get<table_type>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        table_type x = toml::get<table_type>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(tab == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1(42);
 | 
				
			||||||
 | 
					        BOOST_TEST(v1 == toml::get<value_type>(v1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        value_type v2(54);
 | 
				
			||||||
 | 
					        toml::get<value_type>(v1) = v2;
 | 
				
			||||||
 | 
					        BOOST_TEST(v2 == toml::get<value_type>(v1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        value_type x = toml::get<value_type>(std::move(v1));
 | 
				
			||||||
 | 
					        BOOST_TEST(v2 == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v(42);
 | 
				
			||||||
 | 
					        BOOST_TEST(int(42) ==           toml::get<int          >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(short(42) ==         toml::get<short        >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(char(42) ==          toml::get<char         >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(unsigned(42) ==      toml::get<unsigned     >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(long(42) ==          toml::get<long         >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::int64_t(42) ==  toml::get<std::int64_t >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::int16_t(42) ==  toml::get<std::int16_t >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(std::move(v)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v(3.14);
 | 
				
			||||||
 | 
					        const double ref(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float      >(ref) == toml::get<float      >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(                         ref  == toml::get<double     >(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<long double>(ref) == toml::get<long double>(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float      >(ref) == toml::get<float>(std::move(v)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v("foo", toml::string_t::basic);
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::get<std::string>(v));
 | 
				
			||||||
 | 
					        toml::get<std::string>(v) += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get<std::string>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto x = toml::get<std::string>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v("foo", toml::string_t::literal);
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::get<std::string>(v));
 | 
				
			||||||
 | 
					        toml::get<std::string>(v) += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get<std::string>(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto x = toml::get<std::string>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v("foo", toml::string_t::basic);
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::get<std::string_view>(v));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v("foo", toml::string_t::literal);
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == toml::get<std::string_view>(v));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v{42, 54, 69, 72};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const std::vector<int>         vec = toml::get<std::vector<int>>(v);
 | 
				
			||||||
 | 
					        const std::list<short>         lst = toml::get<std::list<short>>(v);
 | 
				
			||||||
 | 
					        const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == vec.at(0));
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == vec.at(1));
 | 
				
			||||||
 | 
					        BOOST_TEST(69 == vec.at(2));
 | 
				
			||||||
 | 
					        BOOST_TEST(72 == vec.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::list<short>::const_iterator iter = lst.begin();
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<short>(42) == *(iter++));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<short>(54) == *(iter++));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<short>(69) == *(iter++));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<short>(72) == *(iter++));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == ary.at(0));
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == ary.at(1));
 | 
				
			||||||
 | 
					        BOOST_TEST(69 == ary.at(2));
 | 
				
			||||||
 | 
					        BOOST_TEST(72 == ary.at(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::tuple<int, short, unsigned, long> tpl =
 | 
				
			||||||
 | 
					            toml::get<std::tuple<int, short, unsigned, long>>(v);
 | 
				
			||||||
 | 
					        BOOST_TEST(                      42  == std::get<0>(tpl));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<short   >(54) == std::get<1>(tpl));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<long    >(72) == std::get<3>(tpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const value_type p{3.14, 2.71};
 | 
				
			||||||
 | 
					        std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
 | 
				
			||||||
 | 
					        BOOST_TEST(3.14 == pr.first);
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71 == pr.second);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        const std::vector<int> vec = toml::get<std::vector<int>>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == vec.at(0));
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == vec.at(1));
 | 
				
			||||||
 | 
					        BOOST_TEST(69 == vec.at(2));
 | 
				
			||||||
 | 
					        BOOST_TEST(72 == vec.at(3));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        const std::deque<int> deq = toml::get<std::deque<int>>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == deq.at(0));
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == deq.at(1));
 | 
				
			||||||
 | 
					        BOOST_TEST(69 == deq.at(2));
 | 
				
			||||||
 | 
					        BOOST_TEST(72 == deq.at(3));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        const std::list<int> lst = toml::get<std::list<int>>(std::move(v));
 | 
				
			||||||
 | 
					        std::list<int>::const_iterator iter = lst.begin();
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == *(iter++));
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == *(iter++));
 | 
				
			||||||
 | 
					        BOOST_TEST(69 == *(iter++));
 | 
				
			||||||
 | 
					        BOOST_TEST(72 == *(iter++));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        std::array<int, 4> ary = toml::get<std::array<int, 4>>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(42 == ary.at(0));
 | 
				
			||||||
 | 
					        BOOST_TEST(54 == ary.at(1));
 | 
				
			||||||
 | 
					        BOOST_TEST(69 == ary.at(2));
 | 
				
			||||||
 | 
					        BOOST_TEST(72 == ary.at(3));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        std::tuple<int, short, unsigned, long> tpl =
 | 
				
			||||||
 | 
					            toml::get<std::tuple<int, short, unsigned, long>>(std::move(v));
 | 
				
			||||||
 | 
					        BOOST_TEST(                      42  == std::get<0>(tpl));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<short   >(54) == std::get<1>(tpl));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<long    >(72) == std::get<3>(tpl));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v1{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        const value_type v2{"foo", "bar", "baz"};
 | 
				
			||||||
 | 
					        const value_type v{v1, v2};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::pair<std::vector<int>, std::vector<std::string>> p =
 | 
				
			||||||
 | 
					            toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.size() == 4u);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(0) == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(1) == 54);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(2) == 69);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.size() == 3u);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.at(0) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.at(1) == "bar");
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.at(2) == "baz");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::tuple<std::vector<int>, std::vector<std::string>> t =
 | 
				
			||||||
 | 
					            toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<0>(t).at(0) == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<0>(t).at(1) == 54);
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<0>(t).at(2) == 69);
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<0>(t).at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<1>(t).at(0) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<1>(t).at(1) == "bar");
 | 
				
			||||||
 | 
					        BOOST_TEST(std::get<1>(t).at(2) == "baz");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v1{42, 54, 69, 72};
 | 
				
			||||||
 | 
					        const value_type v2{"foo", "bar", "baz"};
 | 
				
			||||||
 | 
					        value_type v{v1, v2};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::pair<std::vector<int>, std::vector<std::string>> p =
 | 
				
			||||||
 | 
					            toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.size() == 4u);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(0) == 42);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(1) == 54);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(2) == 69);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.first.at(3) == 72);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.size() == 3u);
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.at(0) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.at(1) == "bar");
 | 
				
			||||||
 | 
					        BOOST_TEST(p.second.at(2) == "baz");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const value_type v1{
 | 
				
			||||||
 | 
					                {"key1", 1},
 | 
				
			||||||
 | 
					                {"key2", 2},
 | 
				
			||||||
 | 
					                {"key3", 3},
 | 
				
			||||||
 | 
					                {"key4", 4}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto v = toml::get<std::map<std::string, int>>(v1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key1") == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key2") == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key3") == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key4") == 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        value_type v1{
 | 
				
			||||||
 | 
					                {"key1", 1},
 | 
				
			||||||
 | 
					                {"key2", 2},
 | 
				
			||||||
 | 
					                {"key3", 3},
 | 
				
			||||||
 | 
					                {"key4", 4}
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        const auto v = toml::get<std::map<std::string, int>>(std::move(v1));
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key1") == 1);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key2") == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key3") == 3);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.at("key4") == 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type v1(toml::local_date{2018, toml::month_t::Apr, 1});
 | 
				
			||||||
 | 
					    const auto date = std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					            toml::get<std::chrono::system_clock::time_point>(v1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::tm t;
 | 
				
			||||||
 | 
					    t.tm_year = 2018 - 1900;
 | 
				
			||||||
 | 
					    t.tm_mon  = 4    - 1;
 | 
				
			||||||
 | 
					    t.tm_mday = 1;
 | 
				
			||||||
 | 
					    t.tm_hour = 0;
 | 
				
			||||||
 | 
					    t.tm_min  = 0;
 | 
				
			||||||
 | 
					    t.tm_sec  = 0;
 | 
				
			||||||
 | 
					    t.tm_isdst = -1;
 | 
				
			||||||
 | 
					    const auto c = std::mktime(&t);
 | 
				
			||||||
 | 
					    BOOST_TEST(c == date);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_time, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type v1(toml::local_time{12, 30, 45});
 | 
				
			||||||
 | 
					    const auto time = toml::get<std::chrono::seconds>(v1);
 | 
				
			||||||
 | 
					    const bool result = time == std::chrono::hours(12)   +
 | 
				
			||||||
 | 
					                                std::chrono::minutes(30) +
 | 
				
			||||||
 | 
					                                std::chrono::seconds(45);
 | 
				
			||||||
 | 
					    BOOST_TEST(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_datetime, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    value_type v1(toml::local_datetime(
 | 
				
			||||||
 | 
					                toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                toml::local_time{12, 30, 45}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto date = std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					            toml::get<std::chrono::system_clock::time_point>(v1));
 | 
				
			||||||
 | 
					    std::tm t;
 | 
				
			||||||
 | 
					    t.tm_year = 2018 - 1900;
 | 
				
			||||||
 | 
					    t.tm_mon  = 4    - 1;
 | 
				
			||||||
 | 
					    t.tm_mday = 1;
 | 
				
			||||||
 | 
					    t.tm_hour = 12;
 | 
				
			||||||
 | 
					    t.tm_min  = 30;
 | 
				
			||||||
 | 
					    t.tm_sec  = 45;
 | 
				
			||||||
 | 
					    t.tm_isdst = -1;
 | 
				
			||||||
 | 
					    const auto c = std::mktime(&t);
 | 
				
			||||||
 | 
					    BOOST_TEST(c == date);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    value_type v1(toml::offset_datetime(
 | 
				
			||||||
 | 
					                toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                toml::local_time{12, 30, 0},
 | 
				
			||||||
 | 
					                toml::time_offset{9, 0}));
 | 
				
			||||||
 | 
					    //    2018-04-01T12:30:00+09:00
 | 
				
			||||||
 | 
					    // == 2018-04-01T03:30:00Z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto date = toml::get<std::chrono::system_clock::time_point>(v1);
 | 
				
			||||||
 | 
					    const auto timet = std::chrono::system_clock::to_time_t(date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get time_t as gmtime (2018-04-01T03:30:00Z)
 | 
				
			||||||
 | 
					    const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
 | 
				
			||||||
 | 
					    BOOST_TEST(tmp);
 | 
				
			||||||
 | 
					    const auto tm = *tmp;
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_year + 1900 == 2018);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_mon  + 1 ==       4);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_mday ==           1);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_hour ==           3);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_min ==           30);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_sec ==            0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    value_type v1(toml::offset_datetime(
 | 
				
			||||||
 | 
					                toml::local_date{2018, toml::month_t::Apr, 1},
 | 
				
			||||||
 | 
					                toml::local_time{12, 30, 0},
 | 
				
			||||||
 | 
					                toml::time_offset{-8, 0}));
 | 
				
			||||||
 | 
					    //    2018-04-01T12:30:00-08:00
 | 
				
			||||||
 | 
					    // == 2018-04-01T20:30:00Z
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto date = toml::get<std::chrono::system_clock::time_point>(v1);
 | 
				
			||||||
 | 
					    const auto timet = std::chrono::system_clock::to_time_t(date);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get time_t as gmtime (2018-04-01T03:30:00Z)
 | 
				
			||||||
 | 
					    const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
 | 
				
			||||||
 | 
					    BOOST_TEST(tmp);
 | 
				
			||||||
 | 
					    const auto tm = *tmp;
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_year + 1900 == 2018);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_mon  + 1 ==       4);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_mday ==           1);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_hour ==          20);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_min ==           30);
 | 
				
			||||||
 | 
					    BOOST_TEST(tm.tm_sec ==            0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,449 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using test_value_types = std::tuple<
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::discard_comments,  std::map, std::deque>,
 | 
				
			||||||
 | 
					    toml::basic_value<toml::preserve_comments, std::map, std::deque>
 | 
				
			||||||
 | 
					>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace test
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					// to compare result values in BOOST_TEST().
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// BOOST_TEST outputs the expected and actual values. Thus it includes the
 | 
				
			||||||
 | 
					// output stream operator inside. To compile it, we need operator<<s for
 | 
				
			||||||
 | 
					// containers to compare.
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename T, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << i << ' ';}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits,
 | 
				
			||||||
 | 
					         typename Key, typename Value, typename Comp, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os,
 | 
				
			||||||
 | 
					           const std::map<Key, Value, Comp, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename charT, typename traits,
 | 
				
			||||||
 | 
					         typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os,
 | 
				
			||||||
 | 
					           const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "[ ";
 | 
				
			||||||
 | 
					    for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
 | 
				
			||||||
 | 
					    os << ']';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_GET_OR_EXACT(toml_type, init_expr, opt_expr)\
 | 
				
			||||||
 | 
					    {                                                           \
 | 
				
			||||||
 | 
					        using namespace test;                                   \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                  \
 | 
				
			||||||
 | 
					        const toml::toml_type opt  opt_expr ;                   \
 | 
				
			||||||
 | 
					        const value_type v(init);                               \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);                                \
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::get_or(v, opt));               \
 | 
				
			||||||
 | 
					    }                                                           \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_exact, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_EXACT(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        const typename value_type::array_type opt {6,7,8,9,10};
 | 
				
			||||||
 | 
					        const value_type v(init);
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::get_or(v, opt));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        const value_type v(init);
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        BOOST_TEST(init == toml::get_or(v, opt));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_GET_OR_EXACT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_GET_OR_MOVE_EXACT(toml_type, init_expr, opt_expr)\
 | 
				
			||||||
 | 
					    {                                                                \
 | 
				
			||||||
 | 
					        using namespace test;                                        \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                       \
 | 
				
			||||||
 | 
					        toml::toml_type       opt  opt_expr ;                        \
 | 
				
			||||||
 | 
					        value_type v(init);                                          \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);                                     \
 | 
				
			||||||
 | 
					        const auto opt_ = toml::get_or(std::move(v), std::move(opt));\
 | 
				
			||||||
 | 
					        BOOST_TEST(init == opt_);                                    \
 | 
				
			||||||
 | 
					    }                                                                \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_move, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                                   (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MOVE_EXACT(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt {6,7,8,9,10};
 | 
				
			||||||
 | 
					        value_type v(init);
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        const auto opt_ = toml::get_or(std::move(v), std::move(opt));
 | 
				
			||||||
 | 
					        BOOST_TEST(init == opt_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        value_type v(init);
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt);
 | 
				
			||||||
 | 
					        const auto opt_ = toml::get_or(std::move(v), std::move(opt));
 | 
				
			||||||
 | 
					        BOOST_TEST(init == opt_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_GET_OR_MOVE_EXACT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\
 | 
				
			||||||
 | 
					    {                                                            \
 | 
				
			||||||
 | 
					        using namespace test;                                    \
 | 
				
			||||||
 | 
					        const toml::toml_type init init_expr ;                   \
 | 
				
			||||||
 | 
					        toml::toml_type       opt1 opt_expr ;                    \
 | 
				
			||||||
 | 
					        toml::toml_type       opt2 opt_expr ;                    \
 | 
				
			||||||
 | 
					        value_type v(init);                                      \
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);                                \
 | 
				
			||||||
 | 
					        toml::get_or(v, opt2) = opt1;                            \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::get<toml::toml_type>(v));       \
 | 
				
			||||||
 | 
					    }                                                            \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_modify, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(boolean,         ( true), (false))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(integer,         (   42), (   54))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(floating,        ( 3.14), ( 2.71))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(string,          ("foo"), ("bar"))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(local_time,      (12, 30, 45), (6, 0, 30))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(local_date,      (2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					                                              (1999, toml::month_t::Jan, 2))
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(local_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_MODIFY(offset_datetime,
 | 
				
			||||||
 | 
					            (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
 | 
				
			||||||
 | 
					            (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6,  0, 30), toml::time_offset(-3, 0))
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::array_type init{1,2,3,4,5};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt1{6,7,8,9,10};
 | 
				
			||||||
 | 
					        typename value_type::array_type opt2{6,7,8,9,10};
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);
 | 
				
			||||||
 | 
					        value_type v(init);
 | 
				
			||||||
 | 
					        toml::get_or(v, opt2) = opt1;
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::get<typename value_type::array_type>(v));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
 | 
				
			||||||
 | 
					        value_type v(init);
 | 
				
			||||||
 | 
					        BOOST_TEST(init != opt1);
 | 
				
			||||||
 | 
					        toml::get_or(v, opt2) = opt1;
 | 
				
			||||||
 | 
					        BOOST_TEST(opt1 == toml::get<typename value_type::table_type>(v));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_GET_OR_MODIFY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_GET_OR_FALLBACK(init_type, opt_type)  \
 | 
				
			||||||
 | 
					    {                                                     \
 | 
				
			||||||
 | 
					        using namespace test;                             \
 | 
				
			||||||
 | 
					        value_type v(init_type);                          \
 | 
				
			||||||
 | 
					        BOOST_TEST(opt_type == toml::get_or(v, opt_type));\
 | 
				
			||||||
 | 
					    }                                                     \
 | 
				
			||||||
 | 
					    /**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_fallback, value_type, test_value_types)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const toml::boolean         boolean        (true);
 | 
				
			||||||
 | 
					    const toml::integer         integer        (42);
 | 
				
			||||||
 | 
					    const toml::floating        floating       (3.14);
 | 
				
			||||||
 | 
					    const toml::string          string         ("foo");
 | 
				
			||||||
 | 
					    const toml::local_time      local_time     (12, 30, 45);
 | 
				
			||||||
 | 
					    const toml::local_date      local_date     (2019, toml::month_t::Apr, 1);
 | 
				
			||||||
 | 
					    const toml::local_datetime  local_datetime (
 | 
				
			||||||
 | 
					            toml::local_date(2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					            toml::local_time(12, 30, 45));
 | 
				
			||||||
 | 
					    const toml::offset_datetime offset_datetime(
 | 
				
			||||||
 | 
					            toml::local_date(2019, toml::month_t::Apr, 1),
 | 
				
			||||||
 | 
					            toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using array_type = typename value_type::array_type;
 | 
				
			||||||
 | 
					    using table_type = typename value_type::table_type;
 | 
				
			||||||
 | 
					    const array_type array{1, 2, 3, 4, 5};
 | 
				
			||||||
 | 
					    const table_type table{{"key1", 42}, {"key2", "foo"}};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(boolean, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(integer, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(floating, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(string, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_time, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_date, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(local_datetime, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, array          );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(offset_datetime, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(array, table          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, boolean        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, integer        );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, floating       );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, string         );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, local_time     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, local_date     );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, local_datetime );
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, offset_datetime);
 | 
				
			||||||
 | 
					    TOML11_TEST_GET_OR_FALLBACK(table, array          );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#undef TOML11_TEST_GET_OR_FALLBACK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_get_or_integer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1(42);
 | 
				
			||||||
 | 
					        toml::value v2(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(42u == toml::get_or(v1, 0u));
 | 
				
			||||||
 | 
					        BOOST_TEST(0u ==  toml::get_or(v2, 0u));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1(42);
 | 
				
			||||||
 | 
					        toml::value v2(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(42u == toml::get_or(std::move(v1), 0u));
 | 
				
			||||||
 | 
					        BOOST_TEST(0u ==  toml::get_or(std::move(v2), 0u));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_get_or_floating)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1(42);
 | 
				
			||||||
 | 
					        toml::value v2(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71f == toml::get_or(v1, 2.71f));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float>(v2.as_floating()) == toml::get_or(v2, 2.71f));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1(42);
 | 
				
			||||||
 | 
					        toml::value v2(3.14);
 | 
				
			||||||
 | 
					        BOOST_TEST(2.71f                    == toml::get_or(std::move(v1), 2.71f));
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<float>(3.14) == toml::get_or(std::move(v2), 2.71f));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_get_or_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1("foobar");
 | 
				
			||||||
 | 
					        toml::value v2(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string       s1("bazqux");
 | 
				
			||||||
 | 
					        const std::string s2("bazqux");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(v1, s1));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(v2, s1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string& v1r = toml::get_or(v1, s1);
 | 
				
			||||||
 | 
					        std::string& s1r = toml::get_or(v2, s1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == v1r);
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == s1r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(v1, s2));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(v2, s2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1)));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1("foobar");
 | 
				
			||||||
 | 
					        toml::value v2(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string       s1("bazqux");
 | 
				
			||||||
 | 
					        const std::string s2("bazqux");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(std::move(v1), s1));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(std::move(v2), s1));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1("foobar");
 | 
				
			||||||
 | 
					        toml::value v2(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(v1, "bazqux"));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(v2, "bazqux"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const char* lit = "bazqux";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(v1, lit));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(v2, lit));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1("foobar");
 | 
				
			||||||
 | 
					        toml::value v2(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(std::move(v1), "bazqux"));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(std::move(v2), "bazqux"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::value v1("foobar");
 | 
				
			||||||
 | 
					        toml::value v2(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const char* lit = "bazqux";
 | 
				
			||||||
 | 
					        BOOST_TEST("foobar" == toml::get_or(v1, lit));
 | 
				
			||||||
 | 
					        BOOST_TEST("bazqux" == toml::get_or(v2, lit));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <toml/region.hpp>
 | 
				
			||||||
 | 
					#include <toml/result.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_LEX_ACCEPT(lxr, tkn, expct)                                \
 | 
				
			||||||
 | 
					do {                                                                           \
 | 
				
			||||||
 | 
					    const std::string token   (tkn);                                           \
 | 
				
			||||||
 | 
					    const std::string expected(expct);                                         \
 | 
				
			||||||
 | 
					    toml::detail::location loc("test", token);                                 \
 | 
				
			||||||
 | 
					    const auto result = lxr::invoke(loc);                                      \
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_ok());                                                \
 | 
				
			||||||
 | 
					    if(result.is_ok()){                                                        \
 | 
				
			||||||
 | 
					        const auto region = result.unwrap();                                   \
 | 
				
			||||||
 | 
					        BOOST_TEST(region.str() == expected);                                  \
 | 
				
			||||||
 | 
					        BOOST_TEST(region.str().size() == expected.size());                    \
 | 
				
			||||||
 | 
					        BOOST_TEST(static_cast<std::size_t>(std::distance(                     \
 | 
				
			||||||
 | 
					                        loc.begin(), loc.iter())) == region.size());           \
 | 
				
			||||||
 | 
					    } else {                                                                   \
 | 
				
			||||||
 | 
					        std::cerr << "lexer failed with input `";                              \
 | 
				
			||||||
 | 
					        std::cerr << token << "`. expected `" << expected << "`\n";            \
 | 
				
			||||||
 | 
					        std::cerr << "reason: " << result.unwrap_err() << '\n';                \
 | 
				
			||||||
 | 
					    }                                                                          \
 | 
				
			||||||
 | 
					} while(false);                                                                \
 | 
				
			||||||
 | 
					/**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_LEX_REJECT(lxr, tkn)                                       \
 | 
				
			||||||
 | 
					do {                                                                           \
 | 
				
			||||||
 | 
					    const std::string token   (tkn);                                           \
 | 
				
			||||||
 | 
					    toml::detail::location loc("test", token);                                 \
 | 
				
			||||||
 | 
					    const auto result = lxr::invoke(loc);                                      \
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_err());                                               \
 | 
				
			||||||
 | 
					    const bool loc_same = (loc.begin() == loc.iter());                         \
 | 
				
			||||||
 | 
					    BOOST_TEST(loc_same);                                                      \
 | 
				
			||||||
 | 
					} while(false); /**/
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					#include <toml/lexer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_lex_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_correct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_boolean, "true", "true");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_boolean, "false", "false");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_boolean, "true  # trailing", "true");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_boolean, "false # trailing", "false");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_boolean, "TRUE");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_boolean, "FALSE");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_boolean, "True");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_boolean, "False");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					#include <toml/lexer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_lex_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_offset_datetime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00Z",
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00Z");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00-07:00",
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00-07:00");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00.999999-07:00",
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00.999999-07:00");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00Z",
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00Z");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00-07:00",
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00-07:00");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00.999999-07:00",
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00.999999-07:00");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_local_datetime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00",
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00.999999",
 | 
				
			||||||
 | 
					            "1979-05-27T07:32:00.999999");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00",
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00.999999",
 | 
				
			||||||
 | 
					            "1979-05-27 07:32:00.999999");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_local_date)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_date, "1979-05-27", "1979-05-27");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_local_time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00", "07:32:00");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00.999999", "07:32:00.999999");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,107 @@
 | 
				
			||||||
 | 
					#include <toml/lexer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_lex_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fractional_valid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1.0",               "1.0"              );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "0.1",               "0.1"              );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "0.001",             "0.001"            );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "0.100",             "0.100"            );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+3.14",             "+3.14"            );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-3.14",             "-3.14"            );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "3.1415_9265_3589",  "3.1415_9265_3589" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+3.1415_9265_3589", "+3.1415_9265_3589");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-3.1415_9265_3589", "-3.1415_9265_3589");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "123_456.789",       "123_456.789"      );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+123_456.789",      "+123_456.789"     );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-123_456.789",      "-123_456.789"     );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fractional_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, "0.");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, ".0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, "01.0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, "3,14");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, "+-1.0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, "1._0");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_exponential_valid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1e10",       "1e10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1e+10",      "1e+10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1e-10",      "1e-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+1e10",      "+1e10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+1e+10",     "+1e+10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+1e-10",     "+1e-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-1e10",      "-1e10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-1e+10",     "-1e+10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-1e-10",     "-1e-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "123e-10",    "123e-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1E10",       "1E10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1E+10",      "1E+10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1E-10",      "1E-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10",    "123E-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10",  "1_2_3E-10");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
 | 
				
			||||||
 | 
					    // toml-lang/toml master permits leading 0s in exp part (unreleased)
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-01",  "1_2_3E-01");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-0_1", "1_2_3E-0_1");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_exponential_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // accept partially
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_both_valid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23",          "6.02e23");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23",         "6.02e+23");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
 | 
				
			||||||
 | 
					    // toml-lang/toml master permits leading 0s in exp part (unreleased)
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e-07",          "1.0e-07");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_both_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_float, "01e1.0");
 | 
				
			||||||
 | 
					    // accept partially
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0",  "1e1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
 | 
				
			||||||
 | 
					    // toml-lang/toml master permits leading 0s in exp part (unreleased)
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e_01",  "1.0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e0__1", "1.0e0");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_special_floating_point)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float,  "inf",  "inf");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+inf", "+inf");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-inf", "-inf");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float,  "nan",  "nan");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "+nan", "+nan");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_float, "-nan", "-nan");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,101 @@
 | 
				
			||||||
 | 
					#include <toml/lexer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_lex_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_decimal_correct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "1234",        "1234"       );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "+1234",       "+1234"      );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "-1234",       "-1234"      );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0",           "0"          );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "1_2_3_4",     "1_2_3_4"    );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "+1_2_3_4",    "+1_2_3_4"   );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "-1_2_3_4",    "-1_2_3_4"   );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "123_456_789", "123_456_789");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_decimal_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "123+45",  "123");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "123-45",  "123");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "01234",   "0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "123__45", "123");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_integer, "_1234");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hex_correct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADBEEF",  "0xDEADBEEF" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdeadbeef",  "0xdeadbeef" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADbeef",  "0xDEADbeef" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD_BEEF", "0xDEAD_BEEF");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_beef", "0xdead_beef");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_BEEF", "0xdead_BEEF");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xFF",     "0xFF"    );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0x00FF",   "0x00FF"  );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0x0000FF", "0x0000FF");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hex_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xAPPLE",     "0xA");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD+BEEF", "0xDEAD");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD__BEEF", "0xDEAD");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_hex_int, "0x_DEADBEEF");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_hex_int, "0x+DEADBEEF");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_hex_int, "-0xFF"      );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_hex_int, "-0x00FF"    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0x_DEADBEEF", "0" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0x+DEADBEEF", "0" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "-0xFF"      , "-0" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "-0x00FF"    , "-0" );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_oct_correct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o777",    "0o777"  );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o7_7_7",  "0o7_7_7");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o007",    "0o007"  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_oct_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o77+7", "0o77");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o1__0", "0o1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_oct_int, "0o800" );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_oct_int, "-0o777");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_oct_int, "0o+777");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_oct_int, "0o_10" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o800",  "0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "-0o777", "-0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o+777", "0");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0o_10",  "0");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_bin_correct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0b10000",    "0b10000"   );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0b010000",   "0b010000"  );
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0b01_00_00", "0b01_00_00");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_integer, "0b111111",   "0b111111"  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_bin_invalid)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11__11", "0b11");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11+11" , "0b11");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_bin_int, "-0b10000");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_REJECT(lex_bin_int, "0b_1111" );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,52 @@
 | 
				
			||||||
 | 
					#include <toml/lexer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_lex_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_bare_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "barekey",  "barekey");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "bare-key", "bare-key");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "bare_key", "bare_key");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "1234",     "1234");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_quoted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "\"127.0.0.1\"", "\"127.0.0.1\"");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "\"character encoding\"", "\"character encoding\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // UTF-8 codepoint of characters that looks like "key" written upside down
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"",
 | 
				
			||||||
 | 
					                                    "\"\xCA\x8E\xC7\x9D\xCA\x9E\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "'key2'", "'key2'");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "'quoted \"value\"'", "'quoted \"value\"'");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_dotted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "physical.color", "physical.color");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "physical.shape", "physical.shape");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x.y", "x.y");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x . y", "x . y");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z", "x.y.z");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z", "x. y .z");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x .y. z", "x .y. z");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z", "x . y . z");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z.w", "x.y.z.w");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z. w", "x. y .z. w");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z . w", "x . y . z . w");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_key, "site.\"google.com\"", "site.\"google.com\"");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_comment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_comment, "#   hoge", "#   hoge");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_comment, "#   \n",   "#   ");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_comment, "#   \r\n", "#   ");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_comment, "# # \n",   "# # ");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,108 @@
 | 
				
			||||||
 | 
					#include <toml/lexer.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_lex_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\"The quick brown fox jumps over the lazy dog\"",
 | 
				
			||||||
 | 
					            "\"The quick brown fox jumps over the lazy dog\"");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\'The quick brown fox jumps over the lazy dog\'",
 | 
				
			||||||
 | 
					            "\'The quick brown fox jumps over the lazy dog\'");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_ml_basic_string,
 | 
				
			||||||
 | 
					            "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
 | 
				
			||||||
 | 
					            "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_ml_literal_string,
 | 
				
			||||||
 | 
					            "'''The quick brown fox \njumps over the lazy dog'''",
 | 
				
			||||||
 | 
					            "'''The quick brown fox \njumps over the lazy dog'''");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_basic_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
 | 
				
			||||||
 | 
					            "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\"192.168.1.1\"",
 | 
				
			||||||
 | 
					            "\"192.168.1.1\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",  // UTF-8 string (means "China" in
 | 
				
			||||||
 | 
					            "\"\xE4\xB8\xAD\xE5\x9B\xBD\""); // Chinese characters)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\"You'll hate me after this - #\"",
 | 
				
			||||||
 | 
					            "\"You'll hate me after this - #\"");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					            "\" And when \\\"'s are in the string, along with # \\\"\"",
 | 
				
			||||||
 | 
					            "\" And when \\\"'s are in the string, along with # \\\"\"");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_ml_basic_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "\"\"\"\nThe quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\"\"\"",
 | 
				
			||||||
 | 
					        "\"\"\"\nThe quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\"\"\"");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "\"\"\"\\\n  The quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\\\n  \"\"\"",
 | 
				
			||||||
 | 
					        "\"\"\"\\\n  The quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\\\n  \"\"\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
 | 
				
			||||||
 | 
					        "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
 | 
				
			||||||
 | 
					        "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
 | 
				
			||||||
 | 
					        "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
 | 
				
			||||||
 | 
					        "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_literal_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'C:\\Users\\nodejs\\templates'",
 | 
				
			||||||
 | 
					        "'C:\\Users\\nodejs\\templates'");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'\\\\ServerX\\admin$\\system32\\'",
 | 
				
			||||||
 | 
					        "'\\\\ServerX\\admin$\\system32\\'");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'Tom \"Dubs\" Preston-Werner'",
 | 
				
			||||||
 | 
					        "'Tom \"Dubs\" Preston-Werner'");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'<\\i\\c*\\s*>'",
 | 
				
			||||||
 | 
					        "'<\\i\\c*\\s*>'");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_ml_literal_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'''I [dw]on't need \\d{2} apples'''",
 | 
				
			||||||
 | 
					        "'''I [dw]on't need \\d{2} apples'''");
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'''\nThe first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n'''",
 | 
				
			||||||
 | 
					        "'''\nThe first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n'''");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "''''That's still pointless', she said.'''",
 | 
				
			||||||
 | 
					        "''''That's still pointless', she said.'''");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
 | 
				
			||||||
 | 
					        "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_LEX_ACCEPT(lex_string,
 | 
				
			||||||
 | 
					        "''''This,' she said, 'is just a pointless statement.''''",
 | 
				
			||||||
 | 
					        "''''This,' she said, 'is just a pointless statement.''''");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,336 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_file_as_literal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace toml::literals::toml_literals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					        const toml::value v = R"(
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{
 | 
				
			||||||
 | 
					            {"c", 3.14},
 | 
				
			||||||
 | 
					            {"table", toml::table{{"a", 42}, {"b", "baz"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const toml::value v = R"(
 | 
				
			||||||
 | 
					            c = 3.14
 | 
				
			||||||
 | 
					            [table]
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{
 | 
				
			||||||
 | 
					            {"table", toml::table{{"a", 42}, {"b", "baz"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const toml::value v = R"(
 | 
				
			||||||
 | 
					            [table]
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{
 | 
				
			||||||
 | 
					            {"array_of_tables", toml::array{toml::table{}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const toml::value v = R"(
 | 
				
			||||||
 | 
					            [[array_of_tables]]
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_value_as_literal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace toml::literals::toml_literals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "true"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = "false"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_boolean());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_boolean());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<bool>(v1));
 | 
				
			||||||
 | 
					        BOOST_TEST(!toml::get<bool>(v2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "123_456"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = "0b0010"_toml;
 | 
				
			||||||
 | 
					        const toml::value v3 = "0xDEADBEEF"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v3.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::integer>(v2) == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "3.1415"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = "6.02e+23"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_floating());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_floating());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<double>(v1) == 3.1415,  boost::test_tools::tolerance(0.00001));
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = R"("foo")"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = R"('foo')"_toml;
 | 
				
			||||||
 | 
					        const toml::value v3 = R"("""foo""")"_toml;
 | 
				
			||||||
 | 
					        const toml::value v4 = R"('''foo''')"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v3.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v4.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v1) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v2) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v3) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v4) == "foo");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v1 = R"([1,2,3])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v1.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v2 = R"([1,])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v2.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v3 = R"([[1,]])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v3.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v4 = R"([[1],])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v4.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = R"({a = 42})"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_table());
 | 
				
			||||||
 | 
					        const bool result = toml::get<std::map<std::string,int>>(v1) ==
 | 
				
			||||||
 | 
					                               std::map<std::string,int>{{"a", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "1979-05-27"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_local_date());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::local_date>(v1) ==
 | 
				
			||||||
 | 
					                   toml::local_date(1979, toml::month_t::May, 27));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "12:00:00"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_local_time());
 | 
				
			||||||
 | 
					        const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
 | 
				
			||||||
 | 
					        BOOST_TEST(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "1979-05-27T07:32:00"_toml;
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_local_datetime());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
 | 
				
			||||||
 | 
					            toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                                 toml::local_time(7, 32, 0)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_offset_datetime());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
 | 
				
			||||||
 | 
					            toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                                  toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_file_as_u8_literal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace toml::literals::toml_literals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{{"a", 42}, {"b", "baz"}};
 | 
				
			||||||
 | 
					        const toml::value v = u8R"(
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{
 | 
				
			||||||
 | 
					            {"c", 3.14},
 | 
				
			||||||
 | 
					            {"table", toml::table{{"a", 42}, {"b", "baz"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const toml::value v = u8R"(
 | 
				
			||||||
 | 
					            c = 3.14
 | 
				
			||||||
 | 
					            [table]
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{
 | 
				
			||||||
 | 
					            {"table", toml::table{{"a", 42}, {"b", "baz"}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const toml::value v = u8R"(
 | 
				
			||||||
 | 
					            [table]
 | 
				
			||||||
 | 
					            a = 42
 | 
				
			||||||
 | 
					            b = "baz"
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value r{
 | 
				
			||||||
 | 
					            {"array_of_tables", toml::array{toml::table{}}}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const toml::value v = u8R"(
 | 
				
			||||||
 | 
					            [[array_of_tables]]
 | 
				
			||||||
 | 
					        )"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r == v);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_value_as_u8_literal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace toml::literals::toml_literals;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"true"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = u8"false"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_boolean());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_boolean());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<bool>(v1));
 | 
				
			||||||
 | 
					        BOOST_TEST(!toml::get<bool>(v2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"123_456"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = u8"0b0010"_toml;
 | 
				
			||||||
 | 
					        const toml::value v3 = u8"0xDEADBEEF"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(v3.is_integer());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::integer>(v2) == 2);
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"3.1415"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = u8"6.02e+23"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_floating());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_floating());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<double>(v1) == 3.1415,  boost::test_tools::tolerance(0.00001));
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8R"("foo")"_toml;
 | 
				
			||||||
 | 
					        const toml::value v2 = u8R"('foo')"_toml;
 | 
				
			||||||
 | 
					        const toml::value v3 = u8R"("""foo""")"_toml;
 | 
				
			||||||
 | 
					        const toml::value v4 = u8R"('''foo''')"_toml;
 | 
				
			||||||
 | 
					        const toml::value v5 = u8R"("ひらがな")"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v2.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v3.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v4.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(v5.is_string());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v1) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v2) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v3) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v4) == "foo");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<std::string>(v5) == "\xE3\x81\xB2\xE3\x82\x89\xE3\x81\x8C\xE3\x81\xAA");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v1 = u8R"([1,2,3])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v1.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v2 = u8R"([1,])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v2.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v3 = u8R"([[1,]])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v3.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const toml::value v4 = u8R"([[1],])"_toml;
 | 
				
			||||||
 | 
					            BOOST_TEST(v4.is_array());
 | 
				
			||||||
 | 
					            const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
 | 
				
			||||||
 | 
					            BOOST_TEST(result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8R"({a = 42})"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_table());
 | 
				
			||||||
 | 
					        const bool result = toml::get<std::map<std::string,int>>(v1) ==
 | 
				
			||||||
 | 
					                               std::map<std::string,int>{{"a", 42}};
 | 
				
			||||||
 | 
					        BOOST_TEST(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"1979-05-27"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_local_date());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::local_date>(v1) ==
 | 
				
			||||||
 | 
					                   toml::local_date(1979, toml::month_t::May, 27));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"12:00:00"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_local_time());
 | 
				
			||||||
 | 
					        const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
 | 
				
			||||||
 | 
					        BOOST_TEST(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"1979-05-27T07:32:00"_toml;
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_local_datetime());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
 | 
				
			||||||
 | 
					            toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                                 toml::local_time(7, 32, 0)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::value v1 = u8"1979-05-27T07:32:00Z"_toml;
 | 
				
			||||||
 | 
					        BOOST_TEST(v1.is_offset_datetime());
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
 | 
				
			||||||
 | 
					            toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                                  toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int read_a(const toml::table&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const std::string content("a = 0");
 | 
				
			||||||
 | 
					    std::istringstream iss(content);
 | 
				
			||||||
 | 
					    const auto data = toml::parse(iss, "test_multiple_translation_unit.toml");
 | 
				
			||||||
 | 
					    return read_a(toml::get<toml::table>(data));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int read_a(const toml::table& t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return toml::get<int>(t.at("a"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,288 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_oneline_array)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[]", array());
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
 | 
				
			||||||
 | 
					        a[3] = toml::value(1); a[4] = toml::value(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[3,1,4,1,5]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(3);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo"); a[1] = toml::value("bar");
 | 
				
			||||||
 | 
					        a[2] = toml::value("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[\"foo\", \"bar\",  \"baz\"]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
 | 
				
			||||||
 | 
					        a[3] = toml::value(1); a[4] = toml::value(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[3,1,4,1,5,]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(3);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo"); a[1] = toml::value("bar");
 | 
				
			||||||
 | 
					        a[2] = toml::value("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[\"foo\", \"bar\",  \"baz\",]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_oneline_array_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[]", toml::value(array()));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
 | 
				
			||||||
 | 
					        a[3] = toml::value(1); a[4] = toml::value(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(3);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo"); a[1] = toml::value("bar");
 | 
				
			||||||
 | 
					        a[2] = toml::value("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\",  \"baz\"]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4);
 | 
				
			||||||
 | 
					        a[3] = toml::value(1); a[4] = toml::value(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5,]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(3);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo"); a[1] = toml::value("bar");
 | 
				
			||||||
 | 
					        a[2] = toml::value("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\",  \"baz\",]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_multiline_array)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value< discard_comments>>, "[\n#comment\n]", typename basic_value< discard_comments>::array_type());
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[\n#comment\n]", typename basic_value<preserve_comments>::array_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>(3);
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>(4);
 | 
				
			||||||
 | 
					        a[3] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[4] = basic_value<discard_comments>(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[3,\n1,\n4,\n1,\n5]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>(3);
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>(1);
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>(4);
 | 
				
			||||||
 | 
					        a[3] = basic_value<preserve_comments>(1);
 | 
				
			||||||
 | 
					        a[4] = basic_value<preserve_comments>(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[3,\n1,\n4,\n1,\n5]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>(3);
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>(4);
 | 
				
			||||||
 | 
					        a[3] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[4] = basic_value<discard_comments>(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>(3, {"comment"});
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>(1, {"comment"});
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>(4, {"comment"});
 | 
				
			||||||
 | 
					        a[3] = basic_value<preserve_comments>(1, {"comment"});
 | 
				
			||||||
 | 
					        a[4] = basic_value<preserve_comments>(5, {"comment"});
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>("bar");
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>("bar");
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>("b#r");
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>("b#z");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>("foo", {"comment"});
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>("b#r", {"comment"});
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>("b#z", {"comment"});
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_multiline_array_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value< discard_comments>>, "[\n#comment\n]", basic_value< discard_comments>(typename basic_value< discard_comments>::array_type()));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[\n#comment\n]", basic_value<preserve_comments>(typename basic_value<preserve_comments>::array_type()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>(3);
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>(4);
 | 
				
			||||||
 | 
					        a[3] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[4] = basic_value<discard_comments>(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[3,\n1,\n4,\n1,\n5]", basic_value<discard_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>(3);
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>(1);
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>(4);
 | 
				
			||||||
 | 
					        a[3] = basic_value<preserve_comments>(1);
 | 
				
			||||||
 | 
					        a[4] = basic_value<preserve_comments>(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[3,\n1,\n4,\n1,\n5]", basic_value<preserve_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>(3);
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>(4);
 | 
				
			||||||
 | 
					        a[3] = basic_value<discard_comments>(1);
 | 
				
			||||||
 | 
					        a[4] = basic_value<discard_comments>(5);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value<discard_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(5);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>(3, {"comment"});
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>(1, {"comment"});
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>(4, {"comment"});
 | 
				
			||||||
 | 
					        a[3] = basic_value<preserve_comments>(1, {"comment"});
 | 
				
			||||||
 | 
					        a[4] = basic_value<preserve_comments>(5, {"comment"});
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value<preserve_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>("bar");
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value<discard_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>("bar");
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value<preserve_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>("b#r");
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>("b#z");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value<discard_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>("foo", {"comment"});
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>("b#r", {"comment"});
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>("b#z", {"comment"});
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value<preserve_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_heterogeneous_array)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifndef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("In strict TOML v0.5.0, heterogeneous arrays are not allowed.");
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo");
 | 
				
			||||||
 | 
					        a[1] = toml::value(3.14);
 | 
				
			||||||
 | 
					        a[2] = toml::value(42);
 | 
				
			||||||
 | 
					        a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
 | 
				
			||||||
 | 
					        a[4] = toml::value{{"key", "value"}};
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", 3.14, 42, [\"array\", \"of\", \"hetero-array\", 1], {key = \"value\"}]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo");
 | 
				
			||||||
 | 
					        a[1] = toml::value(3.14);
 | 
				
			||||||
 | 
					        a[2] = toml::value(42);
 | 
				
			||||||
 | 
					        a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
 | 
				
			||||||
 | 
					        a[4] = toml::value{{"key", "value"}};
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n 3.14,\n 42,\n [\"array\", \"of\", \"hetero-array\", 1],\n {key = \"value\"},\n]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo");
 | 
				
			||||||
 | 
					        a[1] = toml::value(3.14);
 | 
				
			||||||
 | 
					        a[2] = toml::value(42);
 | 
				
			||||||
 | 
					        a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
 | 
				
			||||||
 | 
					        a[4] = toml::value{{"key", "value"}};
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n 3.14,#comment\n 42,#comment\n [\"array\", \"of\", \"hetero-array\", 1],#comment\n {key = \"value\"},#comment\n]#comment", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        array a(5);
 | 
				
			||||||
 | 
					        a[0] = toml::value("foo");
 | 
				
			||||||
 | 
					        a[1] = toml::value(3.14);
 | 
				
			||||||
 | 
					        a[2] = toml::value(42);
 | 
				
			||||||
 | 
					        a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
 | 
				
			||||||
 | 
					        a[4] = toml::value{{"key", "value"}};
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n 3.14,\n 42,\n [\"array\",\n \"of\",\n \"hetero-array\",\n 1],\n {key = \"value\"},\n]", toml::value(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_comments_after_comma)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<discard_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<discard_comments>("foo");
 | 
				
			||||||
 | 
					        a[1] = basic_value<discard_comments>("bar");
 | 
				
			||||||
 | 
					        a[2] = basic_value<discard_comments>("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>,
 | 
				
			||||||
 | 
					            "[ \"foo\" # comment\n"
 | 
				
			||||||
 | 
					            ", \"bar\" # comment\n"
 | 
				
			||||||
 | 
					            ", \"baz\" # comment\n"
 | 
				
			||||||
 | 
					            "]", basic_value<discard_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        typename basic_value<preserve_comments>::array_type a(3);
 | 
				
			||||||
 | 
					        a[0] = basic_value<preserve_comments>("foo", {" comment"});
 | 
				
			||||||
 | 
					        a[1] = basic_value<preserve_comments>("bar", {" comment"});
 | 
				
			||||||
 | 
					        a[2] = basic_value<preserve_comments>("baz", {" comment"});
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>,
 | 
				
			||||||
 | 
					            "[ \"foo\" # comment\n"
 | 
				
			||||||
 | 
					            ", \"bar\" # comment\n"
 | 
				
			||||||
 | 
					            ", \"baz\" # comment\n"
 | 
				
			||||||
 | 
					            "]", basic_value<preserve_comments>(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,54 @@
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// some of the parsers returns not only a value but also a region.
 | 
				
			||||||
 | 
					#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct)                               \
 | 
				
			||||||
 | 
					do {                                                                           \
 | 
				
			||||||
 | 
					    const std::string token(tkn);                                              \
 | 
				
			||||||
 | 
					    toml::detail::location loc("test", token);                                 \
 | 
				
			||||||
 | 
					    const auto result = psr(loc);                                              \
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_ok());                                                \
 | 
				
			||||||
 | 
					    if(result.is_ok()){                                                        \
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap().first == expct);                            \
 | 
				
			||||||
 | 
					    } else {                                                                   \
 | 
				
			||||||
 | 
					        std::cerr << "parser " << #psr << " failed with input `";              \
 | 
				
			||||||
 | 
					        std::cerr << token << "`.\n";                                          \
 | 
				
			||||||
 | 
					        std::cerr << "reason: " << result.unwrap_err() << '\n';                \
 | 
				
			||||||
 | 
					    }                                                                          \
 | 
				
			||||||
 | 
					} while(false);                                                                \
 | 
				
			||||||
 | 
					/**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_PARSE_EQUAL_VAT(psr, tkn, expct)                           \
 | 
				
			||||||
 | 
					do {                                                                           \
 | 
				
			||||||
 | 
					    const std::string token(tkn);                                              \
 | 
				
			||||||
 | 
					    toml::detail::location loc("test", token);                                 \
 | 
				
			||||||
 | 
					    const auto result = psr(loc, 0);                                           \
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_ok());                                                \
 | 
				
			||||||
 | 
					    if(result.is_ok()){                                                        \
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap().first == expct);                            \
 | 
				
			||||||
 | 
					    } else {                                                                   \
 | 
				
			||||||
 | 
					        std::cerr << "parser " << #psr << " failed with input `";              \
 | 
				
			||||||
 | 
					        std::cerr << token << "`.\n";                                          \
 | 
				
			||||||
 | 
					        std::cerr << "reason: " << result.unwrap_err() << '\n';                \
 | 
				
			||||||
 | 
					    }                                                                          \
 | 
				
			||||||
 | 
					} while(false);                                                                \
 | 
				
			||||||
 | 
					/**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_TEST_PARSE_EQUAL_VALUE(psr, tkn, expct)                         \
 | 
				
			||||||
 | 
					do {                                                                           \
 | 
				
			||||||
 | 
					    const std::string token(tkn);                                              \
 | 
				
			||||||
 | 
					    toml::detail::location loc("test", token);                                 \
 | 
				
			||||||
 | 
					    const auto result = psr(loc, 0);                                           \
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_ok());                                                \
 | 
				
			||||||
 | 
					    if(result.is_ok()){                                                        \
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == expct);                                  \
 | 
				
			||||||
 | 
					    } else {                                                                   \
 | 
				
			||||||
 | 
					        std::cerr << "parse_value failed with input `";                        \
 | 
				
			||||||
 | 
					        std::cerr << token << "`.\n";                                          \
 | 
				
			||||||
 | 
					        std::cerr << "reason: " << result.unwrap_err() << '\n';                \
 | 
				
			||||||
 | 
					    }                                                                          \
 | 
				
			||||||
 | 
					} while(false);                                                                \
 | 
				
			||||||
 | 
					/**/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_boolean)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_boolean,  "true",  true);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_boolean, "false", false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_boolean_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,  "true", toml::value( true));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "false", toml::value(false));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,246 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00",        toml::local_time(7, 32, 0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.99",     toml::local_time(7, 32, 0, 990, 0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999",    toml::local_time(7, 32, 0, 999, 0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999999", toml::local_time(7, 32, 0, 999, 999));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "00:00:00.000000", toml::local_time( 0,  0,  0,   0,   0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "23:59:59.999999", toml::local_time(23, 59, 59, 999, 999));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_time, "23:59:60.999999", toml::local_time(23, 59, 60, 999, 999)); // leap second
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_time_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00",        toml::value(toml::local_time(7, 32, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.99",     toml::value(toml::local_time(7, 32, 0, 990, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.999",    toml::value(toml::local_time(7, 32, 0, 999, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "00:00:00.000000", toml::value(toml::local_time( 0,  0,  0,   0,   0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "23:59:59.999999", toml::value(toml::local_time(23, 59, 59, 999, 999)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::istringstream stream1(std::string("invalid-datetime = 24:00:00"));
 | 
				
			||||||
 | 
					    std::istringstream stream2(std::string("invalid-datetime = 00:60:00"));
 | 
				
			||||||
 | 
					    std::istringstream stream3(std::string("invalid-datetime = 00:00:61"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream3), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_date)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "1979-05-27", toml::local_date(1979, toml::month_t::May, 27));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-01-01", toml::local_date(2000, toml::month_t::Jan,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-01-31", toml::local_date(2000, toml::month_t::Jan, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream1_1(std::string("invalid-datetime = 2000-01-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream1_2(std::string("invalid-datetime = 2000-01-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream1_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream1_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-02-01", toml::local_date(2000, toml::month_t::Feb,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-02-29", toml::local_date(2000, toml::month_t::Feb, 29));
 | 
				
			||||||
 | 
					    std::istringstream stream2_1(std::string("invalid-datetime = 2000-02-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream2_2(std::string("invalid-datetime = 2000-02-30"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2001-02-28", toml::local_date(2001, toml::month_t::Feb, 28));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2004-02-29", toml::local_date(2004, toml::month_t::Feb, 29));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2100-02-28", toml::local_date(2100, toml::month_t::Feb, 28));
 | 
				
			||||||
 | 
					    std::istringstream stream2_3(std::string("invalid-datetime = 2001-02-29"));
 | 
				
			||||||
 | 
					    std::istringstream stream2_4(std::string("invalid-datetime = 2004-02-30"));
 | 
				
			||||||
 | 
					    std::istringstream stream2_5(std::string("invalid-datetime = 2100-02-29"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2_3), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2_4), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2_5), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-03-01", toml::local_date(2000, toml::month_t::Mar,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-03-31", toml::local_date(2000, toml::month_t::Mar, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream3_1(std::string("invalid-datetime = 2000-03-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream3_2(std::string("invalid-datetime = 2000-03-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream3_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream3_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-04-01", toml::local_date(2000, toml::month_t::Apr,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-04-30", toml::local_date(2000, toml::month_t::Apr, 30));
 | 
				
			||||||
 | 
					    std::istringstream stream4_1(std::string("invalid-datetime = 2000-04-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream4_2(std::string("invalid-datetime = 2000-04-31"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream4_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream4_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-05-01", toml::local_date(2000, toml::month_t::May,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-05-31", toml::local_date(2000, toml::month_t::May, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream5_1(std::string("invalid-datetime = 2000-05-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream5_2(std::string("invalid-datetime = 2000-05-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream5_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream5_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-06-01", toml::local_date(2000, toml::month_t::Jun,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-06-30", toml::local_date(2000, toml::month_t::Jun, 30));
 | 
				
			||||||
 | 
					    std::istringstream stream6_1(std::string("invalid-datetime = 2000-06-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream6_2(std::string("invalid-datetime = 2000-06-31"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream6_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream6_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-07-01", toml::local_date(2000, toml::month_t::Jul,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-07-31", toml::local_date(2000, toml::month_t::Jul, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream7_1(std::string("invalid-datetime = 2000-07-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream7_2(std::string("invalid-datetime = 2000-07-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream7_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream7_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-08-01", toml::local_date(2000, toml::month_t::Aug,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-08-31", toml::local_date(2000, toml::month_t::Aug, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream8_1(std::string("invalid-datetime = 2000-08-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream8_2(std::string("invalid-datetime = 2000-08-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream8_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream8_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-09-01", toml::local_date(2000, toml::month_t::Sep,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-09-30", toml::local_date(2000, toml::month_t::Sep, 30));
 | 
				
			||||||
 | 
					    std::istringstream stream9_1(std::string("invalid-datetime = 2000-09-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream9_2(std::string("invalid-datetime = 2000-09-31"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream9_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream9_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-10-01", toml::local_date(2000, toml::month_t::Oct,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-10-31", toml::local_date(2000, toml::month_t::Oct, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream10_1(std::string("invalid-datetime = 2000-10-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream10_2(std::string("invalid-datetime = 2000-10-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream10_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream10_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-11-01", toml::local_date(2000, toml::month_t::Nov,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-11-30", toml::local_date(2000, toml::month_t::Nov, 30));
 | 
				
			||||||
 | 
					    std::istringstream stream11_1(std::string("invalid-datetime = 2000-11-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream11_2(std::string("invalid-datetime = 2000-11-31"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream11_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream11_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-12-01", toml::local_date(2000, toml::month_t::Dec,  1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_date,  "2000-12-31", toml::local_date(2000, toml::month_t::Dec, 31));
 | 
				
			||||||
 | 
					    std::istringstream stream12_1(std::string("invalid-datetime = 2000-12-00"));
 | 
				
			||||||
 | 
					    std::istringstream stream12_2(std::string("invalid-datetime = 2000-12-32"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream12_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream12_2), toml::syntax_error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::istringstream stream13_1(std::string("invalid-datetime = 2000-13-01"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream13_1), toml::syntax_error);
 | 
				
			||||||
 | 
					    std::istringstream stream0_1(std::string("invalid-datetime = 2000-00-01"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream0_1), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_date_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27", value(toml::local_date(1979, toml::month_t::May, 27)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_datetime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.99",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.999999",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.99",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.999999",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.99",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.999999",
 | 
				
			||||||
 | 
					        toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_datetime_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27t07:32:00",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27t07:32:00.99",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27t07:32:00.999999",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27 07:32:00",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27 07:32:00.99",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27 07:32:00.999999",
 | 
				
			||||||
 | 
					        toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_offset_datetime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00Z",
 | 
				
			||||||
 | 
					        toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99Z",
 | 
				
			||||||
 | 
					        toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999Z",
 | 
				
			||||||
 | 
					        toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00+09:00",
 | 
				
			||||||
 | 
					        toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0), toml::time_offset(9, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99+09:00",
 | 
				
			||||||
 | 
					        toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0)));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999+09:00",
 | 
				
			||||||
 | 
					        toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::istringstream stream1(std::string("invalid-datetime = 2000-01-01T00:00:00+24:00"));
 | 
				
			||||||
 | 
					    std::istringstream stream2(std::string("invalid-datetime = 2000-01-01T00:00:00+00:60"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream1), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(stream2), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_offset_datetime_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00Z",
 | 
				
			||||||
 | 
					        toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0), toml::time_offset(0, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99Z",
 | 
				
			||||||
 | 
					        toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999Z",
 | 
				
			||||||
 | 
					        toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00+09:00",
 | 
				
			||||||
 | 
					        toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0), toml::time_offset(9, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99+09:00",
 | 
				
			||||||
 | 
					        toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0))));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999+09:00",
 | 
				
			||||||
 | 
					        toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
 | 
				
			||||||
 | 
					                              toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,181 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fractional)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1.0",                1.0);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "0.1",                0.1);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "0.001",              0.001);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "0.100",              0.1);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.14",              3.14);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.14",             -3.14);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "3.1415_9265_3589",   3.141592653589);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.1415_9265_3589",  3.141592653589);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.1415_9265_3589", -3.141592653589);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "123_456.789",        123456.789);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+123_456.789",       123456.789);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-123_456.789",      -123456.789);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+0.0",               0.0);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-0.0",              -0.0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fractional_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.0",               value( 1.0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.1",               value( 0.1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.001",             value( 0.001));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.100",             value( 0.1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+3.14",             value( 3.14));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-3.14",             value(-3.14));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "3.1415_9265_3589",  value( 3.141592653589));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+3.1415_9265_3589", value( 3.141592653589));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-3.1415_9265_3589", value(-3.141592653589));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456.789",       value( 123456.789));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+123_456.789",      value( 123456.789));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-123_456.789",      value(-123456.789));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0.0",              value( 0.0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0.0",              value(-0.0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_exponential)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1e10",       1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1e+10",      1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1e-10",      1e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e10",      1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e+10",     1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e-10",     1e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e10",      -1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e+10",     -1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e-10",     -1e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "123e-10",    123e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1E10",       1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1E+10",      1e10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1E-10",      1e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "123E-10",    123e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-10",  123e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0",        0.0);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0",       -0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
 | 
				
			||||||
 | 
					    // toml-lang/toml master permits leading 0s in exp part (unreleased)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-01",  123e-1);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-0_1", 123e-1);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_exponential_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e10",       value(1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e+10",      value(1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e-10",      value(1e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e10",      value(1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e+10",     value(1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e-10",     value(1e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e10",      value(-1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e+10",     value(-1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e-10",     value(-1e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123e-10",    value(123e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E10",       value(1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E+10",      value(1e10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E-10",      value(1e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123E-10",    value(123e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-10",  value(123e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-1_0", value(123e-10));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0e0",       value( 0.0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0",       value(-0.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
 | 
				
			||||||
 | 
					    // toml-lang/toml master permits leading 0s in exp part (unreleased)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-01",  value(123e-1));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-0_1", value(123e-1));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fe)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e23",          6.02e23);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e+23",         6.02e23);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_floating, "1.112_650_06e-17", 1.11265006e-17);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fe_vaule)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e23",          value(6.02e23));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e+23",         value(6.02e23));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
 | 
				
			||||||
 | 
					    // toml-lang/toml master permits leading 0s in exp part (unreleased)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "3.141_5e-01",      value(3.1415e-1));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_inf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string token("inf");
 | 
				
			||||||
 | 
					        toml::detail::location loc("test", token);
 | 
				
			||||||
 | 
					        const auto r = parse_floating(loc);
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.is_ok());
 | 
				
			||||||
 | 
					        BOOST_CHECK(std::isinf(r.unwrap().first));
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.unwrap().first > 0.0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string token("+inf");
 | 
				
			||||||
 | 
					        toml::detail::location loc("test", token);
 | 
				
			||||||
 | 
					        const auto r = parse_floating(loc);
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.is_ok());
 | 
				
			||||||
 | 
					        BOOST_CHECK(std::isinf(r.unwrap().first));
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.unwrap().first > 0.0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string token("-inf");
 | 
				
			||||||
 | 
					        toml::detail::location loc("test", token);
 | 
				
			||||||
 | 
					        const auto r = parse_floating(loc);
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.is_ok());
 | 
				
			||||||
 | 
					        BOOST_CHECK(std::isinf(r.unwrap().first));
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.unwrap().first < 0.0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_nan)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string token("nan");
 | 
				
			||||||
 | 
					        toml::detail::location loc("test", token);
 | 
				
			||||||
 | 
					        const auto r = parse_floating(loc);
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.is_ok());
 | 
				
			||||||
 | 
					        BOOST_CHECK(std::isnan(r.unwrap().first));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string token("+nan");
 | 
				
			||||||
 | 
					        toml::detail::location loc("test", token);
 | 
				
			||||||
 | 
					        const auto r = parse_floating(loc);
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.is_ok());
 | 
				
			||||||
 | 
					        BOOST_CHECK(std::isnan(r.unwrap().first));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string token("-nan");
 | 
				
			||||||
 | 
					        toml::detail::location loc("test", token);
 | 
				
			||||||
 | 
					        const auto r = parse_floating(loc);
 | 
				
			||||||
 | 
					        BOOST_CHECK(r.is_ok());
 | 
				
			||||||
 | 
					        BOOST_CHECK(std::isnan(r.unwrap().first));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_overflow)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream float_overflow (std::string("float-overflow  = 1.0e+1024"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(float_overflow ), toml::syntax_error);
 | 
				
			||||||
 | 
					    // istringstream >> float does not set failbit in case of underflow.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,59 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_inline_table)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VAT(parse_inline_table<toml::value>, "{}", table());
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        table t;
 | 
				
			||||||
 | 
					        t["foo"] = toml::value(42);
 | 
				
			||||||
 | 
					        t["bar"] = toml::value("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_inline_table<toml::value>, "{foo = 42, bar = \"baz\"}", t);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        table t;
 | 
				
			||||||
 | 
					        table t_sub;
 | 
				
			||||||
 | 
					        t_sub["name"] = toml::value("pug");
 | 
				
			||||||
 | 
					        t["type"] = toml::value(t_sub);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VAT(parse_inline_table<toml::value>, "{type.name = \"pug\"}", t);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_inline_table_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{}", value(table()));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        table t;
 | 
				
			||||||
 | 
					        t["foo"] = toml::value(42);
 | 
				
			||||||
 | 
					        t["bar"] = toml::value("baz");
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{foo = 42, bar = \"baz\"}", value(t));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        table t;
 | 
				
			||||||
 | 
					        table t_sub;
 | 
				
			||||||
 | 
					        t_sub["name"] = toml::value("pug");
 | 
				
			||||||
 | 
					        t["type"] = toml::value(t_sub);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{type.name = \"pug\"}", value(t));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_inline_table_immutability)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					                "a = {b = 1}\n"
 | 
				
			||||||
 | 
					                "a.c = 2\n"));
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::istringstream stream(std::string(
 | 
				
			||||||
 | 
					                "a = {b = {c = 1}}\n"
 | 
				
			||||||
 | 
					                "a.b.d = 2\n"));
 | 
				
			||||||
 | 
					        BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,116 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_decimal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,        "1234",       1234);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,       "+1234",       1234);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,       "-1234",      -1234);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,           "0",          0);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,     "1_2_3_4",       1234);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,    "+1_2_3_4",      +1234);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer,    "-1_2_3_4",      -1234);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "123_456_789",  123456789);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_decimal_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,        "1234", toml::value(     1234));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,       "+1234", toml::value(     1234));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,       "-1234", toml::value(    -1234));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,           "0", toml::value(        0));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,     "1_2_3_4", toml::value(     1234));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,    "+1_2_3_4", toml::value(    +1234));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,    "-1_2_3_4", toml::value(    -1234));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456_789", toml::value(123456789));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hex)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADBEEF",  0xDEADBEEF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdeadbeef",  0xDEADBEEF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADbeef",  0xDEADBEEF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEAD_BEEF", 0xDEADBEEF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_beef", 0xDEADBEEF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_BEEF", 0xDEADBEEF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0xFF",        0xFF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0x00FF",      0xFF);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0x0000FF",    0xFF);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hex_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADBEEF",  value(0xDEADBEEF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdeadbeef",  value(0xDEADBEEF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADbeef",  value(0xDEADBEEF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEAD_BEEF", value(0xDEADBEEF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_beef", value(0xDEADBEEF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_BEEF", value(0xDEADBEEF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xFF",        value(0xFF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x00FF",      value(0xFF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x0000FF",    value(0xFF));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_oct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0o777",   64*7+8*7+7);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0o7_7_7", 64*7+8*7+7);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0o007",   7);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_oct_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o777",   value(64*7+8*7+7));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o7_7_7", value(64*7+8*7+7));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o007",   value(7));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_bin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0b10000",    16);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0b010000",   16);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0b01_00_00", 16);
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_integer, "0b111111",   63);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_bin_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b10000",    value(16));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b010000",   value(16));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b01_00_00", value(16));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b111111",   value(63));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "0b1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000",
 | 
				
			||||||
 | 
					        //      1   0   0   0
 | 
				
			||||||
 | 
					        //      0   C   8   4
 | 
				
			||||||
 | 
					        value(0x0888888888888888));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "0b01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111",
 | 
				
			||||||
 | 
					        //      1   0   0   0
 | 
				
			||||||
 | 
					        //      0   C   8   4
 | 
				
			||||||
 | 
					        value(0x7FFFFFFFFFFFFFFF));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "0b00000000_01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111",
 | 
				
			||||||
 | 
					        //      1   0   0   0
 | 
				
			||||||
 | 
					        //      0   C   8   4
 | 
				
			||||||
 | 
					        value(0x7FFFFFFFFFFFFFFF));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_integer_overflow)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::istringstream dec_overflow(std::string("dec-overflow = 9223372036854775808"));
 | 
				
			||||||
 | 
					    std::istringstream hex_overflow(std::string("hex-overflow = 0x1_00000000_00000000"));
 | 
				
			||||||
 | 
					    std::istringstream oct_overflow(std::string("oct-overflow = 0o1_000_000_000_000_000_000_000"));
 | 
				
			||||||
 | 
					    //                                                           64       56       48       40       32       24       16        8
 | 
				
			||||||
 | 
					    std::istringstream bin_overflow(std::string("bin-overflow = 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000"));
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(dec_overflow), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(hex_overflow), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(oct_overflow), toml::syntax_error);
 | 
				
			||||||
 | 
					    BOOST_CHECK_THROW(toml::parse(bin_overflow), toml::syntax_error);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_bare_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "barekey",  std::vector<key>(1, "barekey"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "bare-key", std::vector<key>(1, "bare-key"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "bare_key", std::vector<key>(1, "bare_key"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "1234",     std::vector<key>(1, "1234"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_quoted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "\"127.0.0.1\"",          std::vector<key>(1, "127.0.0.1"         ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "\"character encoding\"", std::vector<key>(1, "character encoding"));
 | 
				
			||||||
 | 
					#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", std::vector<key>(1, "\xCA\x8E\xC7\x9D\xCA\x9E"));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "\"ʎǝʞ\"",                std::vector<key>(1, "ʎǝʞ"               ));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "'key2'",                 std::vector<key>(1, "key2"              ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_key, "'quoted \"value\"'",     std::vector<key>(1, "quoted \"value\""  ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_dotted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "physical";
 | 
				
			||||||
 | 
					        keys[1] = "color";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_key, "physical.color", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "physical";
 | 
				
			||||||
 | 
					        keys[1] = "shape";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_key, "physical.shape", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(4);
 | 
				
			||||||
 | 
					        keys[0] = "x";
 | 
				
			||||||
 | 
					        keys[1] = "y";
 | 
				
			||||||
 | 
					        keys[2] = "z";
 | 
				
			||||||
 | 
					        keys[3] = "w";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_key, "x.y.z.w", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "site";
 | 
				
			||||||
 | 
					        keys[1] = "google.com";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_key, "site.\"google.com\"", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,245 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"The quick brown fox jumps over the lazy dog\"",
 | 
				
			||||||
 | 
					        string("The quick brown fox jumps over the lazy dog", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\'The quick brown fox jumps over the lazy dog\'",
 | 
				
			||||||
 | 
					        string("The quick brown fox jumps over the lazy dog", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
 | 
				
			||||||
 | 
					        string("The quick brown fox jumps over the lazy dog", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'''The quick brown fox \njumps over the lazy dog'''",
 | 
				
			||||||
 | 
					        string("The quick brown fox \njumps over the lazy dog", string_t::literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_string_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"The quick brown fox jumps over the lazy dog\"",
 | 
				
			||||||
 | 
					        toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\'The quick brown fox jumps over the lazy dog\'",
 | 
				
			||||||
 | 
					        toml::value("The quick brown fox jumps over the lazy dog", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
 | 
				
			||||||
 | 
					        toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'''The quick brown fox \njumps over the lazy dog'''",
 | 
				
			||||||
 | 
					        toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_basic_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
 | 
				
			||||||
 | 
					        string("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"192.168.1.1\"",
 | 
				
			||||||
 | 
					        string("192.168.1.1", string_t::basic));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
 | 
				
			||||||
 | 
					        string("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"中国\"",
 | 
				
			||||||
 | 
					        string("中国", string_t::basic));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"You'll hate me after this - #\"",
 | 
				
			||||||
 | 
					        string("You'll hate me after this - #", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\" And when \\\"'s are in the along with # \\\"\"",
 | 
				
			||||||
 | 
					        string(" And when \"'s are in the along with # \"", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"Here are fifteen apostrophes: '''''''''''''''\"",
 | 
				
			||||||
 | 
					        string("Here are fifteen apostrophes: '''''''''''''''", string_t::basic));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_basic_string_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
 | 
				
			||||||
 | 
					        value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"192.168.1.1\"",
 | 
				
			||||||
 | 
					        value("192.168.1.1", string_t::basic));
 | 
				
			||||||
 | 
					#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
 | 
				
			||||||
 | 
					        value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"中国\"",
 | 
				
			||||||
 | 
					        value("中国", string_t::basic));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"You'll hate me after this - #\"",
 | 
				
			||||||
 | 
					        value("You'll hate me after this - #", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\" And when \\\"'s are in the along with # \\\"\"",
 | 
				
			||||||
 | 
					        value(" And when \"'s are in the along with # \"", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"Here are fifteen apostrophes: '''''''''''''''\"",
 | 
				
			||||||
 | 
					        value("Here are fifteen apostrophes: '''''''''''''''", string_t::basic));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_ml_basic_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"\nThe quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\"\"\"",
 | 
				
			||||||
 | 
					        string("The quick brown fox jumps over the lazy dog.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"\\\n  The quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\\\n  \"\"\"",
 | 
				
			||||||
 | 
					        string("The quick brown fox jumps over the lazy dog.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
 | 
				
			||||||
 | 
					        string("Here are two quotation marks: \"\". Simple enough.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
 | 
				
			||||||
 | 
					        string("Here are three quotation marks: \"\"\".", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
 | 
				
			||||||
 | 
					        string("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
 | 
				
			||||||
 | 
					        string("\"This,\" she said, \"is just a pointless statement.\"", string_t::basic));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_ml_basic_string_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"\nThe quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\"\"\"",
 | 
				
			||||||
 | 
					        value("The quick brown fox jumps over the lazy dog.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"\\\n  The quick brown \\\n\n  fox jumps over \\\n  the lazy dog.\\\n  \"\"\"",
 | 
				
			||||||
 | 
					        value("The quick brown fox jumps over the lazy dog.", string_t::basic));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
 | 
				
			||||||
 | 
					        value("Here are two quotation marks: \"\". Simple enough.", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
 | 
				
			||||||
 | 
					        value("Here are three quotation marks: \"\"\".", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
 | 
				
			||||||
 | 
					        value("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
 | 
				
			||||||
 | 
					        value("\"This,\" she said, \"is just a pointless statement.\"", string_t::basic));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_literal_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'C:\\Users\\nodejs\\templates'",
 | 
				
			||||||
 | 
					        string("C:\\Users\\nodejs\\templates", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'\\\\ServerX\\admin$\\system32\\'",
 | 
				
			||||||
 | 
					        string("\\\\ServerX\\admin$\\system32\\", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'Tom \"Dubs\" Preston-Werner'",
 | 
				
			||||||
 | 
					        string("Tom \"Dubs\" Preston-Werner", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'<\\i\\c*\\s*>'",
 | 
				
			||||||
 | 
					        string("<\\i\\c*\\s*>", string_t::literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_literal_string_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'C:\\Users\\nodejs\\templates'",
 | 
				
			||||||
 | 
					        value("C:\\Users\\nodejs\\templates", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'\\\\ServerX\\admin$\\system32\\'",
 | 
				
			||||||
 | 
					        value("\\\\ServerX\\admin$\\system32\\", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'Tom \"Dubs\" Preston-Werner'",
 | 
				
			||||||
 | 
					        value("Tom \"Dubs\" Preston-Werner", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'<\\i\\c*\\s*>'",
 | 
				
			||||||
 | 
					        value("<\\i\\c*\\s*>", string_t::literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_ml_literal_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'''I [dw]on't need \\d{2} apples'''",
 | 
				
			||||||
 | 
					        string("I [dw]on't need \\d{2} apples", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'''\nThe first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n'''",
 | 
				
			||||||
 | 
					        string("The first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "''''That's still pointless', she said.'''",
 | 
				
			||||||
 | 
					        string("'That's still pointless', she said.", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
 | 
				
			||||||
 | 
					        string("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					        "''''This,' she said, 'is just a pointless statement.''''",
 | 
				
			||||||
 | 
					        string("'This,' she said, 'is just a pointless statement.'", string_t::literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_ml_literal_string_value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'''I [dw]on't need \\d{2} apples'''",
 | 
				
			||||||
 | 
					        value("I [dw]on't need \\d{2} apples", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'''\nThe first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n'''",
 | 
				
			||||||
 | 
					        value("The first newline is\ntrimmed in raw strings.\n   All other whitespace\n   is preserved.\n", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "''''That's still pointless', she said.'''",
 | 
				
			||||||
 | 
					        value("'That's still pointless', she said.", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
 | 
				
			||||||
 | 
					        value("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::literal));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
 | 
				
			||||||
 | 
					        "''''This,' she said, 'is just a pointless statement.''''",
 | 
				
			||||||
 | 
					        value("'This,' she said, 'is just a pointless statement.'", string_t::literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_simple_excape_sequences)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					            R"("\"\\\b\f\n\r\t")",
 | 
				
			||||||
 | 
					            string("\"\\\b\f\n\r\t", string_t::basic));
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					            R"("\e")",
 | 
				
			||||||
 | 
					            string("\x1b", string_t::basic));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_unicode_escape_sequence)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					            "\"\\u03B1\\u03B2\\u03B3\"",
 | 
				
			||||||
 | 
					            string("\xCE\xB1\xCE\xB2\xCE\xB3", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					            "\"\\U0001D7AA\"",
 | 
				
			||||||
 | 
					            string("\xF0\x9D\x9E\xAA", string_t::basic));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					            "\"\\u03B1\\u03B2\\u03B3\"",
 | 
				
			||||||
 | 
					            string("αβγ", string_t::basic));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_string,
 | 
				
			||||||
 | 
					            "\"\\U0001D7AA\"",
 | 
				
			||||||
 | 
					            string("𝞪", string_t::basic));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					#include <toml/get.hpp>
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_normal_table)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::string table(
 | 
				
			||||||
 | 
					        "key1 = \"value\"\n"
 | 
				
			||||||
 | 
					        "key2 = 42\n"
 | 
				
			||||||
 | 
					        "key3 = 3.14\n"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    location loc("test", table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto result = toml::detail::parse_ml_table<toml::value>(loc);
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					    const auto data = result.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::string >(data.at("key1")) == "value");
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::int64_t>(data.at("key2")) == 42);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<double      >(data.at("key3")) == 3.14);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_nested_table)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::string table(
 | 
				
			||||||
 | 
					        "a.b   = \"value\"\n"
 | 
				
			||||||
 | 
					        "a.c.d = 42\n"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    location loc("test", table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto result = toml::detail::parse_ml_table<toml::value>(loc);
 | 
				
			||||||
 | 
					    BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					    const auto data = result.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto a = toml::get<toml::table>(data.at("a"));
 | 
				
			||||||
 | 
					    const auto c = toml::get<toml::table>(a.at("c"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::string >(a.at("b")) == "value");
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::int64_t>(c.at("d")) == 42);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					#include <toml/parser.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					#include "test_parse_aux.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace toml;
 | 
				
			||||||
 | 
					using namespace detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_table_bare_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[barekey]",  std::vector<key>(1, "barekey"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare-key]", std::vector<key>(1, "bare-key"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare_key]", std::vector<key>(1, "bare_key"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[1234]",     std::vector<key>(1, "1234"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_table_quoted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"127.0.0.1\"]",          std::vector<key>(1, "127.0.0.1"         ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"character encoding\"]", std::vector<key>(1, "character encoding"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"ʎǝʞ\"]",                std::vector<key>(1, "ʎǝʞ"               ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "['key2']",                 std::vector<key>(1, "key2"              ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_table_key, "['quoted \"value\"']",     std::vector<key>(1, "quoted \"value\""  ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_table_dotted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "physical";
 | 
				
			||||||
 | 
					        keys[1] = "color";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.color]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "physical";
 | 
				
			||||||
 | 
					        keys[1] = "shape";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.shape]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(4);
 | 
				
			||||||
 | 
					        keys[0] = "x";
 | 
				
			||||||
 | 
					        keys[1] = "y";
 | 
				
			||||||
 | 
					        keys[2] = "z";
 | 
				
			||||||
 | 
					        keys[3] = "w";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x.y.z.w]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x . y . z . w]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x. y .z. w]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x .y. z .w]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x. y .z . w ]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x . y . z . w ]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "site";
 | 
				
			||||||
 | 
					        keys[1] = "google.com";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_table_key, "[site.\"google.com\"]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_array_of_table_bare_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[barekey]]",  std::vector<key>(1, "barekey"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare-key]]", std::vector<key>(1, "bare-key"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare_key]]", std::vector<key>(1, "bare_key"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[1234]]",     std::vector<key>(1, "1234"));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_array_of_table_quoted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"127.0.0.1\"]]",          std::vector<key>(1, "127.0.0.1"         ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"character encoding\"]]", std::vector<key>(1, "character encoding"));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"ʎǝʞ\"]]",                std::vector<key>(1, "ʎǝʞ"               ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['key2']]",                 std::vector<key>(1, "key2"              ));
 | 
				
			||||||
 | 
					    TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['quoted \"value\"']]",     std::vector<key>(1, "quoted \"value\""  ));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_array_of_table_dotted_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "physical";
 | 
				
			||||||
 | 
					        keys[1] = "color";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.color]]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "physical";
 | 
				
			||||||
 | 
					        keys[1] = "shape";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.shape]]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(4);
 | 
				
			||||||
 | 
					        keys[0] = "x";
 | 
				
			||||||
 | 
					        keys[1] = "y";
 | 
				
			||||||
 | 
					        keys[2] = "z";
 | 
				
			||||||
 | 
					        keys[3] = "w";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x.y.z.w]]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x . y . z . w]]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x. y .z. w]]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x .y. z .w]]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x. y .z . w ]]", keys);
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x . y . z . w ]]", keys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<key> keys(2);
 | 
				
			||||||
 | 
					        keys[0] = "site";
 | 
				
			||||||
 | 
					        keys[1] = "google.com";
 | 
				
			||||||
 | 
					        TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[site.\"google.com\"]]", keys);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse(testinput("hard_example_unicode.toml"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto the = toml::find<toml::table>(data, "the");
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
 | 
				
			||||||
 | 
					                      std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x27\xE2\x84\x93\xE2\x84\x93\x20\xCE\xBB\xC3\xA1\xC6\xAD\xC3\xA8\x20\xE2\x82\xA5\xC3\xA8\x20\xC3\xA1\xC6\x92\xC6\xAD\xC3\xA8\xC5\x99\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC6\xA8\x20\x2D\x20\x23"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto hard = toml::get<toml::table>(the.at("hard"));
 | 
				
			||||||
 | 
					    const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
 | 
				
			||||||
 | 
					    BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
 | 
				
			||||||
 | 
					                expected_the_hard_test_array);
 | 
				
			||||||
 | 
					    const std::vector<std::string> expected_the_hard_test_array2{
 | 
				
			||||||
 | 
					        std::string("\x54\xC3\xA8\xC6\xA8\xC6\xAD\x20\x23\x31\x31\x20\x5D\xC6\xA5\xC5\x99\xC3\xB4\xC6\xB2\xC3\xA8\xCE\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD"),
 | 
				
			||||||
 | 
					        std::string("\xC3\x89\xD0\xB6\xC6\xA5\xC3\xA8\xC5\x99\xC3\xAF\xE2\x82\xA5\xC3\xA8\xC3\xB1\xC6\xAD\x20\x23\x39\x20\xCF\x89\xC3\xA1\xC6\xA8\x20\xC3\xA1\x20\xC6\xA8\xC3\xBA\xC3\xA7\xC3\xA7\xC3\xA8\xC6\xA8\xC6\xA8")
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
 | 
				
			||||||
 | 
					                expected_the_hard_test_array2);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::string>(hard.at("another_test_string")) ==
 | 
				
			||||||
 | 
					                      std::string("\xC2\xA7\xC3\xA1\xE2\x82\xA5\xC3\xA8\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xCE\xB2\xC3\xBA\xC6\xAD\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\xC3\xA1\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x20\x23"));
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::string>(hard.at("harder_test_string")) ==
 | 
				
			||||||
 | 
					                      std::string("\x20\xC3\x82\xC3\xB1\xCE\xB4\x20\xCF\x89\xCE\xBB\xC3\xA8\xC3\xB1\x20\x22\x27\xC6\xA8\x20\xC3\xA1\xC5\x99\xC3\xA8\x20\xC3\xAF\xC3\xB1\x20\xC6\xAD\xCE\xBB\xC3\xA8\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xC3\xA1\xE2\x84\x93\xC3\xB4\xC3\xB1\xCF\xB1\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\x23\x20\x22"));
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					    const auto bit = toml::get<toml::table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23")));
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::get<std::string>(bit.at(std::string("\xCF\x89\xCE\xBB\xC3\xA1\xC6\xAD\x3F"))) ==
 | 
				
			||||||
 | 
					        std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x20\xCE\xB4\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xC6\x99\x20\xC6\xA8\xC3\xB4\xE2\x82\xA5\xC3\xA8\x20\xC3\xBA\xC6\xA8\xC3\xA8\xC5\x99\x20\xCF\x89\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xCE\xB4\xC3\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD\x3F"));
 | 
				
			||||||
 | 
					    const std::vector<std::string> expected_multi_line_array{"]"};
 | 
				
			||||||
 | 
					    BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
 | 
				
			||||||
 | 
					                expected_multi_line_array);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,440 @@
 | 
				
			||||||
 | 
					#include <toml/result.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_construct)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto s = toml::ok(42);
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(s);
 | 
				
			||||||
 | 
					        BOOST_TEST(!!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto s = toml::ok(42);
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(s);
 | 
				
			||||||
 | 
					        BOOST_TEST(!!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        BOOST_TEST(!!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto f = toml::err<std::string>("foobar");
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(f);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap_err() == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto f = toml::err<std::string>("foobar");
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(f);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap_err() == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        BOOST_TEST(!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap_err() == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_assignment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        result = toml::ok(42);
 | 
				
			||||||
 | 
					        BOOST_TEST(!!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        auto s = toml::ok(42);
 | 
				
			||||||
 | 
					        result = s;
 | 
				
			||||||
 | 
					        BOOST_TEST(!!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        const auto s = toml::ok(42);
 | 
				
			||||||
 | 
					        result = s;
 | 
				
			||||||
 | 
					        BOOST_TEST(!!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        result = toml::err<std::string>("hoge");
 | 
				
			||||||
 | 
					        BOOST_TEST(!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        auto f = toml::err<std::string>("hoge");
 | 
				
			||||||
 | 
					        result = f;
 | 
				
			||||||
 | 
					        BOOST_TEST(!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::string> result(toml::err<std::string>("foobar"));
 | 
				
			||||||
 | 
					        const auto f = toml::err<std::string>("hoge");
 | 
				
			||||||
 | 
					        result = f;
 | 
				
			||||||
 | 
					        BOOST_TEST(!result);
 | 
				
			||||||
 | 
					        BOOST_TEST(!result.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(result.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_map)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        const auto mapped = result.map(
 | 
				
			||||||
 | 
					                [](const int i) -> int {
 | 
				
			||||||
 | 
					                    return i * 2;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap() == 42 * 2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::ok(std::unique_ptr<int>(new int(42))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<int> i) -> int {
 | 
				
			||||||
 | 
					                    return *i;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.map(
 | 
				
			||||||
 | 
					                [](const int i) -> int {
 | 
				
			||||||
 | 
					                    return i * 2;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<int> i) -> int {
 | 
				
			||||||
 | 
					                    return *i;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_map_err)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_err(
 | 
				
			||||||
 | 
					                [](const std::string s) -> std::string {
 | 
				
			||||||
 | 
					                    return s + s;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::ok(std::unique_ptr<int>(new int(42))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map_err(
 | 
				
			||||||
 | 
					                [](const std::string s) -> std::string {
 | 
				
			||||||
 | 
					                    return s + s;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(*(mapped.unwrap()) == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_err(
 | 
				
			||||||
 | 
					                [](const std::string s) -> std::string {
 | 
				
			||||||
 | 
					                    return s + s;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hogehoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<int, std::unique_ptr<std::string>>
 | 
				
			||||||
 | 
					            result(toml::err(std::unique_ptr<std::string>(new std::string("hoge"))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map_err(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<std::string> p) -> std::string {
 | 
				
			||||||
 | 
					                    return *p;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_map_or_else)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_or_else(
 | 
				
			||||||
 | 
					                [](const int i) -> int {
 | 
				
			||||||
 | 
					                    return i * 2;
 | 
				
			||||||
 | 
					                }, 54);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == 42 * 2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::ok(std::unique_ptr<int>(new int(42))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map_or_else(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<int> i) -> int {
 | 
				
			||||||
 | 
					                    return *i;
 | 
				
			||||||
 | 
					                }, 54);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_or_else(
 | 
				
			||||||
 | 
					                [](const int i) -> int {
 | 
				
			||||||
 | 
					                    return i * 2;
 | 
				
			||||||
 | 
					                }, 54);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == 54);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map_or_else(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<int> i) -> int {
 | 
				
			||||||
 | 
					                    return *i;
 | 
				
			||||||
 | 
					                }, 54);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == 54);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_map_err_or_else)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_err_or_else(
 | 
				
			||||||
 | 
					                [](const std::string i) -> std::string {
 | 
				
			||||||
 | 
					                    return i + i;
 | 
				
			||||||
 | 
					                }, "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::ok(std::unique_ptr<int>(new int(42))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).map_err_or_else(
 | 
				
			||||||
 | 
					                [](const std::string i) -> std::string {
 | 
				
			||||||
 | 
					                    return i + i;
 | 
				
			||||||
 | 
					                }, "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_err_or_else(
 | 
				
			||||||
 | 
					                [](const std::string i) -> std::string {
 | 
				
			||||||
 | 
					                    return i + i;
 | 
				
			||||||
 | 
					                }, "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == "hogehoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.map_err_or_else(
 | 
				
			||||||
 | 
					                [](const std::string i) -> std::string {
 | 
				
			||||||
 | 
					                    return i + i;
 | 
				
			||||||
 | 
					                }, "foobar");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped == "hogehoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_and_then)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        const auto mapped = result.and_then(
 | 
				
			||||||
 | 
					                [](const int i) -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					                    return toml::ok(i * 2);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap() == 42 * 2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::ok(std::unique_ptr<int>(new int(42))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).and_then(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<int> i) -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					                    return toml::ok(*i);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.and_then(
 | 
				
			||||||
 | 
					                [](const int i) -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					                    return toml::ok(i * 2);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).and_then(
 | 
				
			||||||
 | 
					                [](std::unique_ptr<int> i) -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					                    return toml::ok(*i);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_or_else)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::ok(42));
 | 
				
			||||||
 | 
					        const auto mapped = result.or_else(
 | 
				
			||||||
 | 
					                [](const std::string& s) -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					                    return toml::err(s + s);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::ok(std::unique_ptr<int>(new int(42))));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).or_else(
 | 
				
			||||||
 | 
					                [](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
 | 
				
			||||||
 | 
					                    return toml::err(s + s);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(*mapped.unwrap() == 42);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = result.or_else(
 | 
				
			||||||
 | 
					                [](const std::string& s) -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					                    return toml::err(s + s);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hogehoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::result<std::unique_ptr<int>, std::string>
 | 
				
			||||||
 | 
					            result(toml::err<std::string>("hoge"));
 | 
				
			||||||
 | 
					        const auto mapped = std::move(result).or_else(
 | 
				
			||||||
 | 
					                [](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
 | 
				
			||||||
 | 
					                    return toml::err(s + s);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped);
 | 
				
			||||||
 | 
					        BOOST_TEST(!mapped.is_ok());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.is_err());
 | 
				
			||||||
 | 
					        BOOST_TEST(mapped.unwrap_err() == "hogehoge");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_and_or_other)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> r1(toml::ok(42));
 | 
				
			||||||
 | 
					        const toml::result<int, std::string> r2(toml::err<std::string>("foo"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r1 ==    r1.or_other(r2));
 | 
				
			||||||
 | 
					        BOOST_TEST(r2 ==    r1.and_other(r2));
 | 
				
			||||||
 | 
					        BOOST_TEST(42 ==    r1.or_other(r2).unwrap());
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == r1.and_other(r2).unwrap_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto r1_gen = []() -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					            return toml::ok(42);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        auto r2_gen = []() -> toml::result<int, std::string> {
 | 
				
			||||||
 | 
					            return toml::err<std::string>("foo");
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const auto r3 = r1_gen();
 | 
				
			||||||
 | 
					        const auto r4 = r2_gen();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        BOOST_TEST(r3 == r1_gen().or_other (r2_gen()));
 | 
				
			||||||
 | 
					        BOOST_TEST(r4 == r1_gen().and_other(r2_gen()));
 | 
				
			||||||
 | 
					        BOOST_TEST(42 ==    r1_gen().or_other (r2_gen()).unwrap());
 | 
				
			||||||
 | 
					        BOOST_TEST("foo" == r1_gen().and_other(r2_gen()).unwrap_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,405 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <clocale>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Comment,
 | 
				
			||||||
 | 
					         template<typename ...> class Table,
 | 
				
			||||||
 | 
					         template<typename ...> class Array>
 | 
				
			||||||
 | 
					bool has_comment_inside(const toml::basic_value<Comment, Table, Array>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(!v.comments().empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // v itself does not have a comment.
 | 
				
			||||||
 | 
					    if(v.is_array())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for(const auto& x : v.as_array())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(has_comment_inside(x))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(v.is_table())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        for(const auto& x : v.as_table())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(has_comment_inside(x.second))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_example)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse(testinput("example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp1.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto serialized = toml::parse("tmp1.toml");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto& owner = toml::find(serialized, "owner");
 | 
				
			||||||
 | 
					        auto& bio   = toml::find<std::string>(owner, "bio");
 | 
				
			||||||
 | 
					        const auto CR = std::find(bio.begin(), bio.end(), '\r');
 | 
				
			||||||
 | 
					        if(CR != bio.end())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bio.erase(CR);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_example_map_dq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            testinput("example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp1_map_dq.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            "tmp1_map_dq.toml");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto& owner = toml::find(serialized, "owner");
 | 
				
			||||||
 | 
					        auto& bio   = toml::find<std::string>(owner, "bio");
 | 
				
			||||||
 | 
					        const auto CR = std::find(bio.begin(), bio.end(), '\r');
 | 
				
			||||||
 | 
					        if(CR != bio.end())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bio.erase(CR);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_example_with_comment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::preserve_comments>(testinput("example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp1_com.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto serialized = toml::parse<toml::preserve_comments>("tmp1_com.toml");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto& owner = toml::find(serialized, "owner");
 | 
				
			||||||
 | 
					        auto& bio   = toml::find<std::string>(owner, "bio");
 | 
				
			||||||
 | 
					        const auto CR = std::find(bio.begin(), bio.end(), '\r');
 | 
				
			||||||
 | 
					        if(CR != bio.end())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bio.erase(CR);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp1_com1.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << serialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_example_with_comment_nocomment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data = toml::parse<toml::preserve_comments>(testinput("example.toml"));
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::ofstream ofs("tmp1_com_nocomment.toml");
 | 
				
			||||||
 | 
					            ofs << std::setw(80) << toml::nocomment << data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const auto serialized = toml::parse<toml::preserve_comments>("tmp1_com_nocomment.toml");
 | 
				
			||||||
 | 
					        // check no comment exist
 | 
				
			||||||
 | 
					        BOOST_TEST(!has_comment_inside(serialized));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data_nocomment = toml::parse<toml::discard_comments>(testinput("example.toml"));
 | 
				
			||||||
 | 
					        auto serialized = toml::parse<toml::discard_comments>("tmp1_com_nocomment.toml");
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto& owner = toml::find(serialized, "owner");
 | 
				
			||||||
 | 
					            auto& bio   = toml::find<std::string>(owner, "bio");
 | 
				
			||||||
 | 
					            const auto CR = std::find(bio.begin(), bio.end(), '\r');
 | 
				
			||||||
 | 
					            if(CR != bio.end())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                bio.erase(CR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // check collectly serialized
 | 
				
			||||||
 | 
					        BOOST_TEST(data_nocomment == serialized);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            testinput("example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp1_com_map_dq.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            "tmp1_com_map_dq.toml");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto& owner = toml::find(serialized, "owner");
 | 
				
			||||||
 | 
					        auto& bio   = toml::find<std::string>(owner, "bio");
 | 
				
			||||||
 | 
					        const auto CR = std::find(bio.begin(), bio.end(), '\r');
 | 
				
			||||||
 | 
					        if(CR != bio.end())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bio.erase(CR);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp1_com1_map_dq.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << serialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq_nocomment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(testinput("example.toml"));
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::ofstream ofs("tmp1_com_map_dq_nocomment.toml");
 | 
				
			||||||
 | 
					            ofs << std::setw(80) << toml::nocomment << data;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp1_com_map_dq_nocomment.toml");
 | 
				
			||||||
 | 
					        BOOST_TEST(!has_comment_inside(serialized));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto data_nocomment = toml::parse<toml::discard_comments>(testinput("example.toml"));
 | 
				
			||||||
 | 
					        auto serialized = toml::parse<toml::discard_comments>("tmp1_com_map_dq_nocomment.toml");
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto& owner = toml::find(serialized, "owner");
 | 
				
			||||||
 | 
					            auto& bio   = toml::find<std::string>(owner, "bio");
 | 
				
			||||||
 | 
					            const auto CR = std::find(bio.begin(), bio.end(), '\r');
 | 
				
			||||||
 | 
					            if(CR != bio.end())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                bio.erase(CR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        BOOST_TEST(data_nocomment == serialized);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fruit)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse(testinput("fruit.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp2.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse("tmp2.toml");
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fruit_map_dq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            testinput("fruit.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp2.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            "tmp2.toml");
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fruit_with_comments)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::preserve_comments>(testinput("fruit.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp2_com.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse<toml::preserve_comments>("tmp2_com.toml");
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_fruit_with_comments_map_dq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            testinput("fruit.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp2_com.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp2_com.toml");
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hard_example)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse(testinput("hard_example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp3.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse("tmp3.toml");
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hard_example_map_dq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            testinput("hard_example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp3.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            "tmp3.toml");
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_hard_example_with_comment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            testinput("hard_example.toml"));
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp3_com.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << data;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
 | 
				
			||||||
 | 
					            "tmp3_com.toml");
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ofstream ofs("tmp3_com1.toml");
 | 
				
			||||||
 | 
					        ofs << std::setw(80) << serialized;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    BOOST_TEST(data == serialized);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_format_key)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::key key("normal_bare-key");
 | 
				
			||||||
 | 
					        BOOST_TEST("normal_bare-key" == toml::format_key(key));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::key key("key.include.dots");
 | 
				
			||||||
 | 
					        BOOST_TEST("\"key.include.dots\"" == toml::format_key(key));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::key key("key-include-unicode-\xE3\x81\x82");
 | 
				
			||||||
 | 
					        BOOST_TEST("\"key-include-unicode-\xE3\x81\x82\"" == toml::format_key(key));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::key key("special-chars-\\-\"-\b-\f-\r-\n-\t");
 | 
				
			||||||
 | 
					        BOOST_TEST("\"special-chars-\\\\-\\\"-\\b-\\f-\\r-\\n-\\t\"" == toml::format_key(key));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// In toml11, an implicitly-defined value does not have any comments.
 | 
				
			||||||
 | 
					// So, in the following file,
 | 
				
			||||||
 | 
					// ```toml
 | 
				
			||||||
 | 
					// # comment
 | 
				
			||||||
 | 
					// [[array-of-tables]]
 | 
				
			||||||
 | 
					// foo = "bar"
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// The array named "array-of-tables" does not have the comment, but the first
 | 
				
			||||||
 | 
					// element of the array has. That means that, the above file is equivalent to
 | 
				
			||||||
 | 
					// the following.
 | 
				
			||||||
 | 
					// ```toml
 | 
				
			||||||
 | 
					// array-of-tables = [
 | 
				
			||||||
 | 
					//     # comment
 | 
				
			||||||
 | 
					//     {foo = "bar"},
 | 
				
			||||||
 | 
					// ]
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// If the array itself has a comment (value_has_comment_ == true), we should try
 | 
				
			||||||
 | 
					// to make it inline.
 | 
				
			||||||
 | 
					// ```toml
 | 
				
			||||||
 | 
					// # comment about array
 | 
				
			||||||
 | 
					// array-of-tables = [
 | 
				
			||||||
 | 
					//   # comment about table element
 | 
				
			||||||
 | 
					//   {foo = "bar"}
 | 
				
			||||||
 | 
					// ]
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// If it is formatted as a multiline table, the two comments becomes
 | 
				
			||||||
 | 
					// indistinguishable.
 | 
				
			||||||
 | 
					// ```toml
 | 
				
			||||||
 | 
					// # comment about array
 | 
				
			||||||
 | 
					// # comment about table element
 | 
				
			||||||
 | 
					// [[array-of-tables]]
 | 
				
			||||||
 | 
					// foo = "bar"
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// So we need to try to make it inline, and it force-inlines regardless
 | 
				
			||||||
 | 
					// of the line width limit.
 | 
				
			||||||
 | 
					//     It may fail if the element of a table has comment. In that case,
 | 
				
			||||||
 | 
					// the array-of-tables will be formatted as a multiline table.
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_distinguish_comment)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const std::string str = R"(# comment about array itself
 | 
				
			||||||
 | 
					array_of_table = [
 | 
				
			||||||
 | 
					    # comment about the first element (table)
 | 
				
			||||||
 | 
					    {key = "value"},
 | 
				
			||||||
 | 
					])";
 | 
				
			||||||
 | 
					    std::istringstream iss(str);
 | 
				
			||||||
 | 
					    const auto data = toml::parse<toml::preserve_comments>(iss);
 | 
				
			||||||
 | 
					    const auto serialized = toml::format(data, /*width = */ 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::istringstream reparse(serialized);
 | 
				
			||||||
 | 
					    const auto parsed = toml::parse<toml::preserve_comments>(reparse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(parsed.at("array_of_table").comments().size()  == 1u);
 | 
				
			||||||
 | 
					    BOOST_TEST(parsed.at("array_of_table").comments().front() == " comment about array itself");
 | 
				
			||||||
 | 
					    BOOST_TEST(parsed.at("array_of_table").at(0).comments().size()  == 1u);
 | 
				
			||||||
 | 
					    BOOST_TEST(parsed.at("array_of_table").at(0).comments().front() == " comment about the first element (table)");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_serialize_under_locale)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // avoid null init (setlocale returns null when it failed)
 | 
				
			||||||
 | 
					    std::string setloc(std::setlocale(LC_ALL, nullptr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fr_FR is a one of locales that uses `,` as a decimal separator.
 | 
				
			||||||
 | 
					    if(const char* try_hyphen = std::setlocale(LC_ALL, "fr_FR.UTF-8"))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        setloc = std::string(try_hyphen);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if(const char* try_nohyphen = std::setlocale(LC_ALL, "fr_FR.utf8"))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        setloc = std::string(try_nohyphen);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // In some envs, fr_FR locale has not been installed. Tests must work even in such a case.
 | 
				
			||||||
 | 
					//     else
 | 
				
			||||||
 | 
					//     {
 | 
				
			||||||
 | 
					//         BOOST_TEST(false);
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("current locale at the beginning of the test = " << setloc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::string str = R"(
 | 
				
			||||||
 | 
					pi        = 3.14159
 | 
				
			||||||
 | 
					large_int = 1234567890
 | 
				
			||||||
 | 
					)";
 | 
				
			||||||
 | 
					    std::istringstream iss(str);
 | 
				
			||||||
 | 
					    const auto ref = toml::parse(iss);
 | 
				
			||||||
 | 
					    const auto serialized_str = toml::format(ref, /*width = */ 80);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("serialized = " << serialized_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::istringstream serialized_iss(serialized_str);
 | 
				
			||||||
 | 
					    const auto serialized_ref = toml::parse(serialized_iss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(serialized_ref.at("pi").as_floating() == ref.at("pi").as_floating());
 | 
				
			||||||
 | 
					    BOOST_TEST(serialized_ref.at("large_int").as_integer() == ref.at("large_int").as_integer());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const std::string endloc(std::setlocale(LC_ALL, nullptr));
 | 
				
			||||||
 | 
					    BOOST_TEST_MESSAGE("current locale at the end of the test = " << endloc);
 | 
				
			||||||
 | 
					    // check if serializer change global locale
 | 
				
			||||||
 | 
					    BOOST_TEST(setloc == endloc);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,153 @@
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_basic_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::string str("basic string");
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << str;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "\"basic string\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string  s1 ("basic string");
 | 
				
			||||||
 | 
					        const toml::string str(s1);
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << str;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "\"basic string\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::string str("basic string", toml::string_t::basic);
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << str;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "\"basic string\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string  s1 ("basic string");
 | 
				
			||||||
 | 
					        const toml::string str(s1, toml::string_t::basic);
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << str;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "\"basic string\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_basic_ml_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::string str("basic\nstring");
 | 
				
			||||||
 | 
					        std::ostringstream oss1;
 | 
				
			||||||
 | 
					        oss1 << str;
 | 
				
			||||||
 | 
					        std::ostringstream oss2;
 | 
				
			||||||
 | 
					        oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
 | 
				
			||||||
 | 
					        BOOST_TEST(oss1.str() == oss2.str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string  s1 ("basic\nstring");
 | 
				
			||||||
 | 
					        const toml::string str(s1);
 | 
				
			||||||
 | 
					        std::ostringstream oss1;
 | 
				
			||||||
 | 
					        oss1 << str;
 | 
				
			||||||
 | 
					        std::ostringstream oss2;
 | 
				
			||||||
 | 
					        oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
 | 
				
			||||||
 | 
					        BOOST_TEST(oss1.str() == oss2.str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::string str("basic\nstring", toml::string_t::basic);
 | 
				
			||||||
 | 
					        std::ostringstream oss1;
 | 
				
			||||||
 | 
					        oss1 << str;
 | 
				
			||||||
 | 
					        std::ostringstream oss2;
 | 
				
			||||||
 | 
					        oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
 | 
				
			||||||
 | 
					        BOOST_TEST(oss1.str() == oss2.str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string  s1 ("basic\nstring");
 | 
				
			||||||
 | 
					        const toml::string str(s1, toml::string_t::basic);
 | 
				
			||||||
 | 
					        std::ostringstream oss1;
 | 
				
			||||||
 | 
					        oss1 << str;
 | 
				
			||||||
 | 
					        std::ostringstream oss2;
 | 
				
			||||||
 | 
					        oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
 | 
				
			||||||
 | 
					        BOOST_TEST(oss1.str() == oss2.str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_literal_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::string str("literal string", toml::string_t::literal);
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << str;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "'literal string'");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string  s1 ("literal string");
 | 
				
			||||||
 | 
					        const toml::string str(s1, toml::string_t::literal);
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << str;
 | 
				
			||||||
 | 
					        BOOST_TEST(oss.str() == "'literal string'");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_literal_ml_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const toml::string str("literal\nstring", toml::string_t::literal);
 | 
				
			||||||
 | 
					        std::ostringstream oss1;
 | 
				
			||||||
 | 
					        oss1 << str;
 | 
				
			||||||
 | 
					        std::ostringstream oss2;
 | 
				
			||||||
 | 
					        oss2 << "'''\nliteral\nstring'''";
 | 
				
			||||||
 | 
					        BOOST_TEST(oss1.str() == oss2.str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string  s1 ("literal\nstring");
 | 
				
			||||||
 | 
					        const toml::string str(s1, toml::string_t::literal);
 | 
				
			||||||
 | 
					        std::ostringstream oss1;
 | 
				
			||||||
 | 
					        oss1 << str;
 | 
				
			||||||
 | 
					        std::ostringstream oss2;
 | 
				
			||||||
 | 
					        oss2 << "'''\nliteral\nstring'''";
 | 
				
			||||||
 | 
					        BOOST_TEST(oss1.str() == oss2.str());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_string_add_assign)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // string literal
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::string str("foo");
 | 
				
			||||||
 | 
					        str += "bar";
 | 
				
			||||||
 | 
					        BOOST_TEST(str.str == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // std::string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::string str("foo");
 | 
				
			||||||
 | 
					        std::string str2("bar");
 | 
				
			||||||
 | 
					        str += str2;
 | 
				
			||||||
 | 
					        BOOST_TEST(str.str == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // toml::string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::string str("foo");
 | 
				
			||||||
 | 
					        toml::string str2("bar");
 | 
				
			||||||
 | 
					        str += str2;
 | 
				
			||||||
 | 
					        BOOST_TEST(str.str == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					    // std::string_view
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        toml::string str("foo");
 | 
				
			||||||
 | 
					        str += std::string_view("bar");
 | 
				
			||||||
 | 
					        BOOST_TEST(str == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    // std::string += toml::string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string  str("foo");
 | 
				
			||||||
 | 
					        toml::string str2("bar");
 | 
				
			||||||
 | 
					        str += str2;
 | 
				
			||||||
 | 
					        BOOST_TEST(str == "foobar");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,79 @@
 | 
				
			||||||
 | 
					#include <toml/types.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <deque>
 | 
				
			||||||
 | 
					#include <forward_list>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					#include <set>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					#include <unordered_set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct dummy_type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct dummy_container
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    typedef T value_type;
 | 
				
			||||||
 | 
					    typedef value_type* pointer;
 | 
				
			||||||
 | 
					    typedef value_type& reference;
 | 
				
			||||||
 | 
					    typedef value_type const* const_pointer;
 | 
				
			||||||
 | 
					    typedef value_type const& const_reference;
 | 
				
			||||||
 | 
					    typedef pointer       iterator;
 | 
				
			||||||
 | 
					    typedef const_pointer const_iterator;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef std::array<dummy_type, 10> std_array_type;
 | 
				
			||||||
 | 
					typedef std::map<std::string, dummy_type> std_map_type;
 | 
				
			||||||
 | 
					typedef std::unordered_map<std::string, dummy_type> std_unordered_map_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_has_xxx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std::list<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std::forward_list<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std::deque<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std::vector<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std::set<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std::unordered_set<std::string>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std_array_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<std_unordered_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_iterator<dummy_container<dummy_type>>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std::list<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std::forward_list<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std::deque<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std::vector<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std_array_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std::set<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std::unordered_set<std::string>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<std_unordered_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_value_type<dummy_container<dummy_type>>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_key_type<std_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_key_type<std_unordered_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_mapped_type<std_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::has_mapped_type<std_unordered_map_type>::value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_is_xxx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std::list<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std::forward_list<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std::deque<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std::vector<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std_array_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std::set<dummy_type>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<std::unordered_set<std::string>>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_container<dummy_container<dummy_type>>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(!toml::detail::is_container<std_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(!toml::detail::is_container<std_unordered_map_type>::value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_map<std_map_type>::value);
 | 
				
			||||||
 | 
					    BOOST_TEST(toml::detail::is_map<std_unordered_map_type>::value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					#include <toml/utility.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "unit_test.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_try_reserve)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // since BOOST_TEST is a macro, it cannot handle commas correctly.
 | 
				
			||||||
 | 
					        // When toml::detail::has_reserve_method<std::array<int, 1>>::value
 | 
				
			||||||
 | 
					        // is passed to a macro, C preprocessor considers
 | 
				
			||||||
 | 
					        // toml::detail::has_reserve_method<std::array<int as the first argument
 | 
				
			||||||
 | 
					        // and 1>>::value as the second argument. We need an alias to avoid
 | 
				
			||||||
 | 
					        // this problem.
 | 
				
			||||||
 | 
					        using reservable_type    = std::vector<int>  ;
 | 
				
			||||||
 | 
					        using nonreservable_type = std::array<int, 1>;
 | 
				
			||||||
 | 
					        BOOST_TEST( toml::detail::has_reserve_method<reservable_type   >::value);
 | 
				
			||||||
 | 
					        BOOST_TEST(!toml::detail::has_reserve_method<nonreservable_type>::value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::vector<int> v;
 | 
				
			||||||
 | 
					        toml::try_reserve(v, 100);
 | 
				
			||||||
 | 
					        BOOST_TEST(v.capacity() == 100u);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_concat_to_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const std::string cat = toml::concat_to_string("foo", "bar", 42);
 | 
				
			||||||
 | 
					    BOOST_TEST(cat == "foobar42");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOST_AUTO_TEST_CASE(test_from_string)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string str("123");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::from_string<int>(str, 0) == 123);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string str("01");
 | 
				
			||||||
 | 
					        BOOST_TEST(toml::from_string<int>(str, 0) == 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,12 @@
 | 
				
			||||||
 | 
					#include <windows.h>
 | 
				
			||||||
 | 
					#include <toml.hpp>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using namespace toml::literals::toml_literals;
 | 
				
			||||||
 | 
					    const auto data = R"(windows = "defines min and max as a macro")"_toml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::cout << toml::find<std::string>(data, "windows") << std::endl;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					#ifndef BOOST_TEST_MODULE
 | 
				
			||||||
 | 
					#    error "Please #define BOOST_TEST_MODULE before you #include <unit_test.hpp>"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
 | 
				
			||||||
 | 
					#    include <boost/test/unit_test.hpp>
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#    include <boost/test/included/unit_test.hpp>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdlib>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline auto testinput(const std::string& basename) -> std::string
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto this_or_that = [](const char *const s, const char *const t) { return s ? s : t; };
 | 
				
			||||||
 | 
					    std::string directory = this_or_that(std::getenv("TOMLDIR"), "toml");
 | 
				
			||||||
 | 
					    if (!directory.empty() && directory.back() != '/')
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        directory.push_back('/');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return directory.append("tests/").append(basename);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The MIT License (MIT)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2017 Toru Niina
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef TOML_FOR_MODERN_CPP
 | 
				
			||||||
 | 
					#define TOML_FOR_MODERN_CPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_VERSION_MAJOR 3
 | 
				
			||||||
 | 
					#define TOML11_VERSION_MINOR 8
 | 
				
			||||||
 | 
					#define TOML11_VERSION_PATCH 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "toml/parser.hpp"
 | 
				
			||||||
 | 
					#include "toml/literal.hpp"
 | 
				
			||||||
 | 
					#include "toml/serializer.hpp"
 | 
				
			||||||
 | 
					#include "toml/get.hpp"
 | 
				
			||||||
 | 
					#include "toml/macros.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif// TOML_FOR_MODERN_CPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,109 @@
 | 
				
			||||||
 | 
					#ifndef TOML11_COLOR_HPP
 | 
				
			||||||
 | 
					#define TOML11_COLOR_HPP
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <ostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_COLORIZE_ERROR_MESSAGE
 | 
				
			||||||
 | 
					#define TOML11_ERROR_MESSAGE_COLORIZED true
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define TOML11_ERROR_MESSAGE_COLORIZED false
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// put ANSI escape sequence to ostream
 | 
				
			||||||
 | 
					namespace color_ansi
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline int colorize_index()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const int index = std::ios_base::xalloc();
 | 
				
			||||||
 | 
					    return index;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Control color mode globally
 | 
				
			||||||
 | 
					class color_mode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    inline void enable()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        should_color_ = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    inline void disable()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        should_color_ = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline bool should_color() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return should_color_;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static color_mode& status()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        static color_mode status_;
 | 
				
			||||||
 | 
					        return status_;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    bool should_color_ = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline std::ostream& colorize(std::ostream& os)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // by default, it is zero.
 | 
				
			||||||
 | 
					    os.iword(detail::colorize_index()) = 1;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline std::ostream& nocolorize(std::ostream& os)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os.iword(detail::colorize_index()) = 0;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline std::ostream& reset  (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[00m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& bold   (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[01m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& grey   (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[30m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& red    (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[31m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& green  (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[32m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& yellow (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[33m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& blue   (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[34m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& magenta(std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[35m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& cyan   (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[36m";} return os;}
 | 
				
			||||||
 | 
					inline std::ostream& white  (std::ostream& os)
 | 
				
			||||||
 | 
					{if(os.iword(detail::colorize_index()) == 1) {os << "\033[37m";} return os;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void enable()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return detail::color_mode::status().enable();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline void disable()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return detail::color_mode::status().disable();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool should_color()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return detail::color_mode::status().should_color();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // color_ansi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ANSI escape sequence is the only and default colorization method currently
 | 
				
			||||||
 | 
					namespace color = color_ansi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_COLOR_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,306 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_COMBINATOR_HPP
 | 
				
			||||||
 | 
					#define TOML11_COMBINATOR_HPP
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <cctype>
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "region.hpp"
 | 
				
			||||||
 | 
					#include "result.hpp"
 | 
				
			||||||
 | 
					#include "traits.hpp"
 | 
				
			||||||
 | 
					#include "utility.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// they scans characters and returns region if it matches to the condition.
 | 
				
			||||||
 | 
					// when they fail, it does not change the location.
 | 
				
			||||||
 | 
					// in lexer.hpp, these are used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// to output character as an error message.
 | 
				
			||||||
 | 
					inline std::string show_char(const char c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // It suppresses an error that occurs only in Debug mode of MSVC++ on Windows.
 | 
				
			||||||
 | 
					    // I'm not completely sure but they check the value of char to be in the
 | 
				
			||||||
 | 
					    // range [0, 256) and some of the COMPLETELY VALID utf-8 character sometimes
 | 
				
			||||||
 | 
					    // has negative value (if char has sign). So here it re-interprets c as
 | 
				
			||||||
 | 
					    // unsigned char through pointer. In general, converting pointer to a
 | 
				
			||||||
 | 
					    // pointer that has different type cause UB, but `(signed|unsigned)?char`
 | 
				
			||||||
 | 
					    // are one of the exceptions. Converting pointer only to char and std::byte
 | 
				
			||||||
 | 
					    // (c++17) are valid.
 | 
				
			||||||
 | 
					    if(std::isgraph(*reinterpret_cast<unsigned char const*>(std::addressof(c))))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::string(1, c);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::array<char, 5> buf;
 | 
				
			||||||
 | 
					        buf.fill('\0');
 | 
				
			||||||
 | 
					        const auto r = std::snprintf(
 | 
				
			||||||
 | 
					                buf.data(), buf.size(), "0x%02x", static_cast<int>(c) & 0xFF);
 | 
				
			||||||
 | 
					        (void) r; // Unused variable warning
 | 
				
			||||||
 | 
					        assert(r == static_cast<int>(buf.size()) - 1);
 | 
				
			||||||
 | 
					        return std::string(buf.data());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<char C>
 | 
				
			||||||
 | 
					struct character
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static constexpr char target = C;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(loc.iter() == loc.end()) {return none();}
 | 
				
			||||||
 | 
					        const auto first = loc.iter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const char c = *(loc.iter());
 | 
				
			||||||
 | 
					        if(c != target)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return none();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        loc.advance(); // update location
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ok(region(loc, first, loc.iter()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<char C>
 | 
				
			||||||
 | 
					constexpr char character<C>::target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// closed interval [Low, Up]. both Low and Up are included.
 | 
				
			||||||
 | 
					template<char Low, char Up>
 | 
				
			||||||
 | 
					struct in_range
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // assuming ascii part of UTF-8...
 | 
				
			||||||
 | 
					    static_assert(Low <= Up, "lower bound should be less than upper bound.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static constexpr char upper = Up;
 | 
				
			||||||
 | 
					    static constexpr char lower = Low;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(loc.iter() == loc.end()) {return none();}
 | 
				
			||||||
 | 
					        const auto first = loc.iter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const char c = *(loc.iter());
 | 
				
			||||||
 | 
					        if(c < lower || upper < c)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return none();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loc.advance();
 | 
				
			||||||
 | 
					        return ok(region(loc, first, loc.iter()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<char L, char U> constexpr char in_range<L, U>::upper;
 | 
				
			||||||
 | 
					template<char L, char U> constexpr char in_range<L, U>::lower;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// keep iterator if `Combinator` matches. otherwise, increment `iter` by 1 char.
 | 
				
			||||||
 | 
					// for detecting invalid characters, like control sequences in toml string.
 | 
				
			||||||
 | 
					template<typename Combinator>
 | 
				
			||||||
 | 
					struct exclude
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(loc.iter() == loc.end()) {return none();}
 | 
				
			||||||
 | 
					        auto first = loc.iter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto rslt = Combinator::invoke(loc);
 | 
				
			||||||
 | 
					        if(rslt.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            loc.reset(first);
 | 
				
			||||||
 | 
					            return none();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        loc.reset(std::next(first)); // XXX maybe loc.advance() is okay but...
 | 
				
			||||||
 | 
					        return ok(region(loc, first, loc.iter()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// increment `iter`, if matches. otherwise, just return empty string.
 | 
				
			||||||
 | 
					template<typename Combinator>
 | 
				
			||||||
 | 
					struct maybe
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto rslt = Combinator::invoke(loc);
 | 
				
			||||||
 | 
					        if(rslt.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return rslt;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ok(region(loc));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ... Ts>
 | 
				
			||||||
 | 
					struct sequence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Head, typename ... Tail>
 | 
				
			||||||
 | 
					struct sequence<Head, Tail...>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto first = loc.iter();
 | 
				
			||||||
 | 
					        auto rslt = Head::invoke(loc);
 | 
				
			||||||
 | 
					        if(rslt.is_err())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            loc.reset(first);
 | 
				
			||||||
 | 
					            return none();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return sequence<Tail...>::invoke(loc, std::move(rslt.unwrap()), first);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // called from the above function only, recursively.
 | 
				
			||||||
 | 
					    template<typename Iterator>
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc, region reg, Iterator first)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto rslt = Head::invoke(loc);
 | 
				
			||||||
 | 
					        if(rslt.is_err())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            loc.reset(first);
 | 
				
			||||||
 | 
					            return none();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        reg += rslt.unwrap(); // concat regions
 | 
				
			||||||
 | 
					        return sequence<Tail...>::invoke(loc, std::move(reg), first);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Head>
 | 
				
			||||||
 | 
					struct sequence<Head>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // would be called from sequence<T ...>::invoke only.
 | 
				
			||||||
 | 
					    template<typename Iterator>
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc, region reg, Iterator first)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto rslt = Head::invoke(loc);
 | 
				
			||||||
 | 
					        if(rslt.is_err())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            loc.reset(first);
 | 
				
			||||||
 | 
					            return none();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        reg += rslt.unwrap(); // concat regions
 | 
				
			||||||
 | 
					        return ok(reg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ... Ts>
 | 
				
			||||||
 | 
					struct either;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Head, typename ... Tail>
 | 
				
			||||||
 | 
					struct either<Head, Tail...>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto rslt = Head::invoke(loc);
 | 
				
			||||||
 | 
					        if(rslt.is_ok()) {return rslt;}
 | 
				
			||||||
 | 
					        return either<Tail...>::invoke(loc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<typename Head>
 | 
				
			||||||
 | 
					struct either<Head>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Head::invoke(loc);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename N>
 | 
				
			||||||
 | 
					struct repeat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<std::size_t N> struct exactly{};
 | 
				
			||||||
 | 
					template<std::size_t N> struct at_least{};
 | 
				
			||||||
 | 
					struct unlimited{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, std::size_t N>
 | 
				
			||||||
 | 
					struct repeat<T, exactly<N>>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        region retval(loc);
 | 
				
			||||||
 | 
					        const auto first = loc.iter();
 | 
				
			||||||
 | 
					        for(std::size_t i=0; i<N; ++i)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto rslt = T::invoke(loc);
 | 
				
			||||||
 | 
					            if(rslt.is_err())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                loc.reset(first);
 | 
				
			||||||
 | 
					                return none();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            retval += rslt.unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ok(std::move(retval));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, std::size_t N>
 | 
				
			||||||
 | 
					struct repeat<T, at_least<N>>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        region retval(loc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto first = loc.iter();
 | 
				
			||||||
 | 
					        for(std::size_t i=0; i<N; ++i)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto rslt = T::invoke(loc);
 | 
				
			||||||
 | 
					            if(rslt.is_err())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                loc.reset(first);
 | 
				
			||||||
 | 
					                return none();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            retval += rslt.unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        while(true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto rslt = T::invoke(loc);
 | 
				
			||||||
 | 
					            if(rslt.is_err())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return ok(std::move(retval));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            retval += rslt.unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct repeat<T, unlimited>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static result<region, none_t>
 | 
				
			||||||
 | 
					    invoke(location& loc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        region retval(loc);
 | 
				
			||||||
 | 
					        while(true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto rslt = T::invoke(loc);
 | 
				
			||||||
 | 
					            if(rslt.is_err())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return ok(std::move(retval));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            retval += rslt.unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_COMBINATOR_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,484 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2019.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_COMMENTS_HPP
 | 
				
			||||||
 | 
					#define TOML11_COMMENTS_HPP
 | 
				
			||||||
 | 
					#include <initializer_list>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_PRESERVE_COMMENTS_BY_DEFAULT
 | 
				
			||||||
 | 
					#  define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::preserve_comments
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define TOML11_DEFAULT_COMMENT_STRATEGY ::toml::discard_comments
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This file provides mainly two classes, `preserve_comments` and `discard_comments`.
 | 
				
			||||||
 | 
					// Those two are a container that have the same interface as `std::vector<std::string>`
 | 
				
			||||||
 | 
					// but bahaves in the opposite way. `preserve_comments` is just the same as
 | 
				
			||||||
 | 
					// `std::vector<std::string>` and each `std::string` corresponds to a comment line.
 | 
				
			||||||
 | 
					// Conversely, `discard_comments` discards all the strings and ignores everything
 | 
				
			||||||
 | 
					// assigned in it. `discard_comments` is always empty and you will encounter an
 | 
				
			||||||
 | 
					// error whenever you access to the element.
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct discard_comments; // forward decl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// use it in the following way
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// const toml::basic_value<toml::preserve_comments> data =
 | 
				
			||||||
 | 
					//     toml::parse<toml::preserve_comments>("example.toml");
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// the interface is almost the same as std::vector<std::string>.
 | 
				
			||||||
 | 
					struct preserve_comments
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // `container_type` is not provided in discard_comments.
 | 
				
			||||||
 | 
					    // do not use this inner-type in a generic code.
 | 
				
			||||||
 | 
					    using container_type         = std::vector<std::string>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using size_type              = container_type::size_type;
 | 
				
			||||||
 | 
					    using difference_type        = container_type::difference_type;
 | 
				
			||||||
 | 
					    using value_type             = container_type::value_type;
 | 
				
			||||||
 | 
					    using reference              = container_type::reference;
 | 
				
			||||||
 | 
					    using const_reference        = container_type::const_reference;
 | 
				
			||||||
 | 
					    using pointer                = container_type::pointer;
 | 
				
			||||||
 | 
					    using const_pointer          = container_type::const_pointer;
 | 
				
			||||||
 | 
					    using iterator               = container_type::iterator;
 | 
				
			||||||
 | 
					    using const_iterator         = container_type::const_iterator;
 | 
				
			||||||
 | 
					    using reverse_iterator       = container_type::reverse_iterator;
 | 
				
			||||||
 | 
					    using const_reverse_iterator = container_type::const_reverse_iterator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    preserve_comments()  = default;
 | 
				
			||||||
 | 
					    ~preserve_comments() = default;
 | 
				
			||||||
 | 
					    preserve_comments(preserve_comments const&) = default;
 | 
				
			||||||
 | 
					    preserve_comments(preserve_comments &&)     = default;
 | 
				
			||||||
 | 
					    preserve_comments& operator=(preserve_comments const&) = default;
 | 
				
			||||||
 | 
					    preserve_comments& operator=(preserve_comments &&)     = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit preserve_comments(const std::vector<std::string>& c): comments(c){}
 | 
				
			||||||
 | 
					    explicit preserve_comments(std::vector<std::string>&& c)
 | 
				
			||||||
 | 
					        : comments(std::move(c))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    preserve_comments& operator=(const std::vector<std::string>& c)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        comments = c;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    preserve_comments& operator=(std::vector<std::string>&& c)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        comments = std::move(c);
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit preserve_comments(const discard_comments&) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit preserve_comments(size_type n): comments(n) {}
 | 
				
			||||||
 | 
					    preserve_comments(size_type n, const std::string& x): comments(n, x) {}
 | 
				
			||||||
 | 
					    preserve_comments(std::initializer_list<std::string> x): comments(x) {}
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    preserve_comments(InputIterator first, InputIterator last)
 | 
				
			||||||
 | 
					        : comments(first, last)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    void assign(InputIterator first, InputIterator last) {comments.assign(first, last);}
 | 
				
			||||||
 | 
					    void assign(std::initializer_list<std::string> ini)  {comments.assign(ini);}
 | 
				
			||||||
 | 
					    void assign(size_type n, const std::string& val)     {comments.assign(n, val);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Related to the issue #97.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // It is known that `std::vector::insert` and `std::vector::erase` in
 | 
				
			||||||
 | 
					    // the standard library implementation included in GCC 4.8.5 takes
 | 
				
			||||||
 | 
					    // `std::vector::iterator` instead of `std::vector::const_iterator`.
 | 
				
			||||||
 | 
					    // Because of the const-correctness, we cannot convert a `const_iterator` to
 | 
				
			||||||
 | 
					    // an `iterator`. It causes compilation error in GCC 4.8.5.
 | 
				
			||||||
 | 
					#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && !defined(__clang__)
 | 
				
			||||||
 | 
					#  if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) <= 40805
 | 
				
			||||||
 | 
					#    define TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef TOML11_WORKAROUND_GCC_4_8_X_STANDARD_LIBRARY_IMPLEMENTATION
 | 
				
			||||||
 | 
					    iterator insert(iterator p, const std::string& x)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    iterator insert(iterator p, std::string&&      x)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, std::move(x));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void insert(iterator p, size_type n, const std::string& x)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, n, x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    void insert(iterator p, InputIterator first, InputIterator last)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, first, last);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void insert(iterator p, std::initializer_list<std::string> ini)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, ini);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ... Ts>
 | 
				
			||||||
 | 
					    iterator emplace(iterator p, Ts&& ... args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.emplace(p, std::forward<Ts>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iterator erase(iterator pos) {return comments.erase(pos);}
 | 
				
			||||||
 | 
					    iterator erase(iterator first, iterator last)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.erase(first, last);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    iterator insert(const_iterator p, const std::string& x)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    iterator insert(const_iterator p, std::string&&      x)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, std::move(x));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    iterator insert(const_iterator p, size_type n, const std::string& x)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, n, x);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    iterator insert(const_iterator p, InputIterator first, InputIterator last)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, first, last);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    iterator insert(const_iterator p, std::initializer_list<std::string> ini)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.insert(p, ini);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ... Ts>
 | 
				
			||||||
 | 
					    iterator emplace(const_iterator p, Ts&& ... args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.emplace(p, std::forward<Ts>(args)...);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iterator erase(const_iterator pos) {return comments.erase(pos);}
 | 
				
			||||||
 | 
					    iterator erase(const_iterator first, const_iterator last)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return comments.erase(first, last);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void swap(preserve_comments& other) {comments.swap(other.comments);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void push_back(const std::string& v) {comments.push_back(v);}
 | 
				
			||||||
 | 
					    void push_back(std::string&&      v) {comments.push_back(std::move(v));}
 | 
				
			||||||
 | 
					    void pop_back()                      {comments.pop_back();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ... Ts>
 | 
				
			||||||
 | 
					    void emplace_back(Ts&& ... args) {comments.emplace_back(std::forward<Ts>(args)...);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void clear() {comments.clear();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_type size()     const noexcept {return comments.size();}
 | 
				
			||||||
 | 
					    size_type max_size() const noexcept {return comments.max_size();}
 | 
				
			||||||
 | 
					    size_type capacity() const noexcept {return comments.capacity();}
 | 
				
			||||||
 | 
					    bool      empty()    const noexcept {return comments.empty();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void reserve(size_type n)                      {comments.reserve(n);}
 | 
				
			||||||
 | 
					    void resize(size_type n)                       {comments.resize(n);}
 | 
				
			||||||
 | 
					    void resize(size_type n, const std::string& c) {comments.resize(n, c);}
 | 
				
			||||||
 | 
					    void shrink_to_fit()                           {comments.shrink_to_fit();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reference       operator[](const size_type n)       noexcept {return comments[n];}
 | 
				
			||||||
 | 
					    const_reference operator[](const size_type n) const noexcept {return comments[n];}
 | 
				
			||||||
 | 
					    reference       at(const size_type n)       {return comments.at(n);}
 | 
				
			||||||
 | 
					    const_reference at(const size_type n) const {return comments.at(n);}
 | 
				
			||||||
 | 
					    reference       front()       noexcept {return comments.front();}
 | 
				
			||||||
 | 
					    const_reference front() const noexcept {return comments.front();}
 | 
				
			||||||
 | 
					    reference       back()        noexcept {return comments.back();}
 | 
				
			||||||
 | 
					    const_reference back()  const noexcept {return comments.back();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pointer         data()        noexcept {return comments.data();}
 | 
				
			||||||
 | 
					    const_pointer   data()  const noexcept {return comments.data();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iterator       begin()        noexcept {return comments.begin();}
 | 
				
			||||||
 | 
					    iterator       end()          noexcept {return comments.end();}
 | 
				
			||||||
 | 
					    const_iterator begin()  const noexcept {return comments.begin();}
 | 
				
			||||||
 | 
					    const_iterator end()    const noexcept {return comments.end();}
 | 
				
			||||||
 | 
					    const_iterator cbegin() const noexcept {return comments.cbegin();}
 | 
				
			||||||
 | 
					    const_iterator cend()   const noexcept {return comments.cend();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reverse_iterator       rbegin()        noexcept {return comments.rbegin();}
 | 
				
			||||||
 | 
					    reverse_iterator       rend()          noexcept {return comments.rend();}
 | 
				
			||||||
 | 
					    const_reverse_iterator rbegin()  const noexcept {return comments.rbegin();}
 | 
				
			||||||
 | 
					    const_reverse_iterator rend()    const noexcept {return comments.rend();}
 | 
				
			||||||
 | 
					    const_reverse_iterator crbegin() const noexcept {return comments.crbegin();}
 | 
				
			||||||
 | 
					    const_reverse_iterator crend()   const noexcept {return comments.crend();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    friend bool operator==(const preserve_comments&, const preserve_comments&);
 | 
				
			||||||
 | 
					    friend bool operator!=(const preserve_comments&, const preserve_comments&);
 | 
				
			||||||
 | 
					    friend bool operator< (const preserve_comments&, const preserve_comments&);
 | 
				
			||||||
 | 
					    friend bool operator<=(const preserve_comments&, const preserve_comments&);
 | 
				
			||||||
 | 
					    friend bool operator> (const preserve_comments&, const preserve_comments&);
 | 
				
			||||||
 | 
					    friend bool operator>=(const preserve_comments&, const preserve_comments&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    friend void swap(preserve_comments&, std::vector<std::string>&);
 | 
				
			||||||
 | 
					    friend void swap(std::vector<std::string>&, preserve_comments&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    container_type comments;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments == rhs.comments;}
 | 
				
			||||||
 | 
					inline bool operator!=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments != rhs.comments;}
 | 
				
			||||||
 | 
					inline bool operator< (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <  rhs.comments;}
 | 
				
			||||||
 | 
					inline bool operator<=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments <= rhs.comments;}
 | 
				
			||||||
 | 
					inline bool operator> (const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >  rhs.comments;}
 | 
				
			||||||
 | 
					inline bool operator>=(const preserve_comments& lhs, const preserve_comments& rhs) {return lhs.comments >= rhs.comments;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void swap(preserve_comments& lhs, preserve_comments& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lhs.swap(rhs);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline void swap(preserve_comments& lhs, std::vector<std::string>& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lhs.comments.swap(rhs);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline void swap(std::vector<std::string>& lhs, preserve_comments& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lhs.swap(rhs.comments);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const preserve_comments& com)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    for(const auto& c : com)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        os << '#' << c << '\n';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// To provide the same interface with `preserve_comments`, `discard_comments`
 | 
				
			||||||
 | 
					// should have an iterator. But it does not contain anything, so we need to
 | 
				
			||||||
 | 
					// add an iterator that points nothing.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It always points null, so DO NOT unwrap this iterator. It always crashes
 | 
				
			||||||
 | 
					// your program.
 | 
				
			||||||
 | 
					template<typename T, bool is_const>
 | 
				
			||||||
 | 
					struct empty_iterator
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type        = T;
 | 
				
			||||||
 | 
					    using reference_type    = typename std::conditional<is_const, T const&, T&>::type;
 | 
				
			||||||
 | 
					    using pointer_type      = typename std::conditional<is_const, T const*, T*>::type;
 | 
				
			||||||
 | 
					    using difference_type   = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using iterator_category = std::random_access_iterator_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    empty_iterator()  = default;
 | 
				
			||||||
 | 
					    ~empty_iterator() = default;
 | 
				
			||||||
 | 
					    empty_iterator(empty_iterator const&) = default;
 | 
				
			||||||
 | 
					    empty_iterator(empty_iterator &&)     = default;
 | 
				
			||||||
 | 
					    empty_iterator& operator=(empty_iterator const&) = default;
 | 
				
			||||||
 | 
					    empty_iterator& operator=(empty_iterator &&)     = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // DO NOT call these operators.
 | 
				
			||||||
 | 
					    reference_type operator*()  const noexcept {std::terminate();}
 | 
				
			||||||
 | 
					    pointer_type   operator->() const noexcept {return nullptr;}
 | 
				
			||||||
 | 
					    reference_type operator[](difference_type) const noexcept {return this->operator*();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // These operators do nothing.
 | 
				
			||||||
 | 
					    empty_iterator& operator++()    noexcept {return *this;}
 | 
				
			||||||
 | 
					    empty_iterator  operator++(int) noexcept {return *this;}
 | 
				
			||||||
 | 
					    empty_iterator& operator--()    noexcept {return *this;}
 | 
				
			||||||
 | 
					    empty_iterator  operator--(int) noexcept {return *this;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    empty_iterator& operator+=(difference_type) noexcept {return *this;}
 | 
				
			||||||
 | 
					    empty_iterator& operator-=(difference_type) noexcept {return *this;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    empty_iterator  operator+(difference_type) const noexcept {return *this;}
 | 
				
			||||||
 | 
					    empty_iterator  operator-(difference_type) const noexcept {return *this;}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					bool operator==(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					bool operator!=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					bool operator< (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					bool operator<=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					bool operator> (const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return false;}
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					bool operator>=(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return true;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					typename empty_iterator<T, C>::difference_type
 | 
				
			||||||
 | 
					operator-(const empty_iterator<T, C>&, const empty_iterator<T, C>&) noexcept {return 0;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					empty_iterator<T, C>
 | 
				
			||||||
 | 
					operator+(typename empty_iterator<T, C>::difference_type, const empty_iterator<T, C>& rhs) noexcept {return rhs;}
 | 
				
			||||||
 | 
					template<typename T, bool C>
 | 
				
			||||||
 | 
					empty_iterator<T, C>
 | 
				
			||||||
 | 
					operator+(const empty_iterator<T, C>& lhs, typename empty_iterator<T, C>::difference_type) noexcept {return lhs;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The default comment type. It discards all the comments. It requires only one
 | 
				
			||||||
 | 
					// byte to contain, so the memory footprint is smaller than preserve_comments.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It just ignores `push_back`, `insert`, `erase`, and any other modifications.
 | 
				
			||||||
 | 
					// IT always returns size() == 0, the iterator taken by `begin()` is always the
 | 
				
			||||||
 | 
					// same as that of `end()`, and accessing through `operator[]` or iterators
 | 
				
			||||||
 | 
					// always causes a segmentation fault. DO NOT access to the element of this.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Why this is chose as the default type is because the last version (2.x.y)
 | 
				
			||||||
 | 
					// does not contain any comments in a value. To minimize the impact on the
 | 
				
			||||||
 | 
					// efficiency, this is chosen as a default.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// To reduce the memory footprint, later we can try empty base optimization (EBO).
 | 
				
			||||||
 | 
					struct discard_comments
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using size_type              = std::size_t;
 | 
				
			||||||
 | 
					    using difference_type        = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using value_type             = std::string;
 | 
				
			||||||
 | 
					    using reference              = std::string&;
 | 
				
			||||||
 | 
					    using const_reference        = std::string const&;
 | 
				
			||||||
 | 
					    using pointer                = std::string*;
 | 
				
			||||||
 | 
					    using const_pointer          = std::string const*;
 | 
				
			||||||
 | 
					    using iterator               = detail::empty_iterator<std::string, false>;
 | 
				
			||||||
 | 
					    using const_iterator         = detail::empty_iterator<std::string, true>;
 | 
				
			||||||
 | 
					    using reverse_iterator       = detail::empty_iterator<std::string, false>;
 | 
				
			||||||
 | 
					    using const_reverse_iterator = detail::empty_iterator<std::string, true>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    discard_comments() = default;
 | 
				
			||||||
 | 
					    ~discard_comments() = default;
 | 
				
			||||||
 | 
					    discard_comments(discard_comments const&) = default;
 | 
				
			||||||
 | 
					    discard_comments(discard_comments &&)     = default;
 | 
				
			||||||
 | 
					    discard_comments& operator=(discard_comments const&) = default;
 | 
				
			||||||
 | 
					    discard_comments& operator=(discard_comments &&)     = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit discard_comments(const std::vector<std::string>&) noexcept {}
 | 
				
			||||||
 | 
					    explicit discard_comments(std::vector<std::string>&&)      noexcept {}
 | 
				
			||||||
 | 
					    discard_comments& operator=(const std::vector<std::string>&) noexcept {return *this;}
 | 
				
			||||||
 | 
					    discard_comments& operator=(std::vector<std::string>&&)      noexcept {return *this;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit discard_comments(const preserve_comments&)        noexcept {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit discard_comments(size_type) noexcept {}
 | 
				
			||||||
 | 
					    discard_comments(size_type, const std::string&) noexcept {}
 | 
				
			||||||
 | 
					    discard_comments(std::initializer_list<std::string>) noexcept {}
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    discard_comments(InputIterator, InputIterator) noexcept {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    void assign(InputIterator, InputIterator)       noexcept {}
 | 
				
			||||||
 | 
					    void assign(std::initializer_list<std::string>) noexcept {}
 | 
				
			||||||
 | 
					    void assign(size_type, const std::string&)      noexcept {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iterator insert(const_iterator, const std::string&)                 {return iterator{};}
 | 
				
			||||||
 | 
					    iterator insert(const_iterator, std::string&&)                      {return iterator{};}
 | 
				
			||||||
 | 
					    iterator insert(const_iterator, size_type, const std::string&)      {return iterator{};}
 | 
				
			||||||
 | 
					    template<typename InputIterator>
 | 
				
			||||||
 | 
					    iterator insert(const_iterator, InputIterator, InputIterator)       {return iterator{};}
 | 
				
			||||||
 | 
					    iterator insert(const_iterator, std::initializer_list<std::string>) {return iterator{};}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ... Ts>
 | 
				
			||||||
 | 
					    iterator emplace(const_iterator, Ts&& ...)     {return iterator{};}
 | 
				
			||||||
 | 
					    iterator erase(const_iterator)                 {return iterator{};}
 | 
				
			||||||
 | 
					    iterator erase(const_iterator, const_iterator) {return iterator{};}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void swap(discard_comments&) {return;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void push_back(const std::string&) {return;}
 | 
				
			||||||
 | 
					    void push_back(std::string&&     ) {return;}
 | 
				
			||||||
 | 
					    void pop_back()                    {return;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename ... Ts>
 | 
				
			||||||
 | 
					    void emplace_back(Ts&& ...) {return;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void clear() {return;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    size_type size()     const noexcept {return 0;}
 | 
				
			||||||
 | 
					    size_type max_size() const noexcept {return 0;}
 | 
				
			||||||
 | 
					    size_type capacity() const noexcept {return 0;}
 | 
				
			||||||
 | 
					    bool      empty()    const noexcept {return true;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void reserve(size_type)                    {return;}
 | 
				
			||||||
 | 
					    void resize(size_type)                     {return;}
 | 
				
			||||||
 | 
					    void resize(size_type, const std::string&) {return;}
 | 
				
			||||||
 | 
					    void shrink_to_fit()                       {return;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // DO NOT access to the element of this container. This container is always
 | 
				
			||||||
 | 
					    // empty, so accessing through operator[], front/back, data causes address
 | 
				
			||||||
 | 
					    // error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reference       operator[](const size_type)       noexcept {never_call("toml::discard_comment::operator[]");}
 | 
				
			||||||
 | 
					    const_reference operator[](const size_type) const noexcept {never_call("toml::discard_comment::operator[]");}
 | 
				
			||||||
 | 
					    reference       at(const size_type)       {throw std::out_of_range("toml::discard_comment is always empty.");}
 | 
				
			||||||
 | 
					    const_reference at(const size_type) const {throw std::out_of_range("toml::discard_comment is always empty.");}
 | 
				
			||||||
 | 
					    reference       front()       noexcept {never_call("toml::discard_comment::front");}
 | 
				
			||||||
 | 
					    const_reference front() const noexcept {never_call("toml::discard_comment::front");}
 | 
				
			||||||
 | 
					    reference       back()        noexcept {never_call("toml::discard_comment::back");}
 | 
				
			||||||
 | 
					    const_reference back()  const noexcept {never_call("toml::discard_comment::back");}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pointer         data()        noexcept {return nullptr;}
 | 
				
			||||||
 | 
					    const_pointer   data()  const noexcept {return nullptr;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    iterator       begin()        noexcept {return iterator{};}
 | 
				
			||||||
 | 
					    iterator       end()          noexcept {return iterator{};}
 | 
				
			||||||
 | 
					    const_iterator begin()  const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					    const_iterator end()    const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					    const_iterator cbegin() const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					    const_iterator cend()   const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reverse_iterator       rbegin()        noexcept {return iterator{};}
 | 
				
			||||||
 | 
					    reverse_iterator       rend()          noexcept {return iterator{};}
 | 
				
			||||||
 | 
					    const_reverse_iterator rbegin()  const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					    const_reverse_iterator rend()    const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					    const_reverse_iterator crbegin() const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					    const_reverse_iterator crend()   const noexcept {return const_iterator{};}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [[noreturn]] static void never_call(const char *const this_function)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					#ifdef __has_builtin
 | 
				
			||||||
 | 
					#  if __has_builtin(__builtin_unreachable)
 | 
				
			||||||
 | 
					        __builtin_unreachable();
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        throw std::logic_error{this_function};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const discard_comments&, const discard_comments&) noexcept {return true;}
 | 
				
			||||||
 | 
					inline bool operator!=(const discard_comments&, const discard_comments&) noexcept {return false;}
 | 
				
			||||||
 | 
					inline bool operator< (const discard_comments&, const discard_comments&) noexcept {return false;}
 | 
				
			||||||
 | 
					inline bool operator<=(const discard_comments&, const discard_comments&) noexcept {return true;}
 | 
				
			||||||
 | 
					inline bool operator> (const discard_comments&, const discard_comments&) noexcept {return false;}
 | 
				
			||||||
 | 
					inline bool operator>=(const discard_comments&, const discard_comments&) noexcept {return true;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void swap(const discard_comments&, const discard_comments&) noexcept {return;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const discard_comments&)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml11
 | 
				
			||||||
 | 
					#endif// TOML11_COMMENTS_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,631 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_DATETIME_HPP
 | 
				
			||||||
 | 
					#define TOML11_DATETIME_HPP
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <cstdlib>
 | 
				
			||||||
 | 
					#include <ctime>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <ostream>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// To avoid non-threadsafe std::localtime. In C11 (not C++11!), localtime_s is
 | 
				
			||||||
 | 
					// provided in the absolutely same purpose, but C++11 is actually not compatible
 | 
				
			||||||
 | 
					// with C11. We need to dispatch the function depending on the OS.
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					// TODO: find more sophisticated way to handle this
 | 
				
			||||||
 | 
					#if defined(_MSC_VER)
 | 
				
			||||||
 | 
					inline std::tm localtime_s(const std::time_t* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::tm dst;
 | 
				
			||||||
 | 
					    const auto result = ::localtime_s(&dst, src);
 | 
				
			||||||
 | 
					    if (result) { throw std::runtime_error("localtime_s failed."); }
 | 
				
			||||||
 | 
					    return dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline std::tm gmtime_s(const std::time_t* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::tm dst;
 | 
				
			||||||
 | 
					    const auto result = ::gmtime_s(&dst, src);
 | 
				
			||||||
 | 
					    if (result) { throw std::runtime_error("gmtime_s failed."); }
 | 
				
			||||||
 | 
					    return dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 1) || defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || defined(_POSIX_SOURCE)
 | 
				
			||||||
 | 
					inline std::tm localtime_s(const std::time_t* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::tm dst;
 | 
				
			||||||
 | 
					    const auto result = ::localtime_r(src, &dst);
 | 
				
			||||||
 | 
					    if (!result) { throw std::runtime_error("localtime_r failed."); }
 | 
				
			||||||
 | 
					    return dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline std::tm gmtime_s(const std::time_t* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::tm dst;
 | 
				
			||||||
 | 
					    const auto result = ::gmtime_r(src, &dst);
 | 
				
			||||||
 | 
					    if (!result) { throw std::runtime_error("gmtime_r failed."); }
 | 
				
			||||||
 | 
					    return dst;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else // fallback. not threadsafe
 | 
				
			||||||
 | 
					inline std::tm localtime_s(const std::time_t* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto result = std::localtime(src);
 | 
				
			||||||
 | 
					    if (!result) { throw std::runtime_error("localtime failed."); }
 | 
				
			||||||
 | 
					    return *result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline std::tm gmtime_s(const std::time_t* src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const auto result = std::gmtime(src);
 | 
				
			||||||
 | 
					    if (!result) { throw std::runtime_error("gmtime failed."); }
 | 
				
			||||||
 | 
					    return *result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class month_t : std::uint8_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Jan =  0,
 | 
				
			||||||
 | 
					    Feb =  1,
 | 
				
			||||||
 | 
					    Mar =  2,
 | 
				
			||||||
 | 
					    Apr =  3,
 | 
				
			||||||
 | 
					    May =  4,
 | 
				
			||||||
 | 
					    Jun =  5,
 | 
				
			||||||
 | 
					    Jul =  6,
 | 
				
			||||||
 | 
					    Aug =  7,
 | 
				
			||||||
 | 
					    Sep =  8,
 | 
				
			||||||
 | 
					    Oct =  9,
 | 
				
			||||||
 | 
					    Nov = 10,
 | 
				
			||||||
 | 
					    Dec = 11
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct local_date
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::int16_t year{};   // A.D. (like, 2018)
 | 
				
			||||||
 | 
					    std::uint8_t month{};  // [0, 11]
 | 
				
			||||||
 | 
					    std::uint8_t day{};    // [1, 31]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_date(int y, month_t m, int d)
 | 
				
			||||||
 | 
					        : year (static_cast<std::int16_t>(y)),
 | 
				
			||||||
 | 
					          month(static_cast<std::uint8_t>(m)),
 | 
				
			||||||
 | 
					          day  (static_cast<std::uint8_t>(d))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_date(const std::tm& t)
 | 
				
			||||||
 | 
					        : year (static_cast<std::int16_t>(t.tm_year + 1900)),
 | 
				
			||||||
 | 
					          month(static_cast<std::uint8_t>(t.tm_mon)),
 | 
				
			||||||
 | 
					          day  (static_cast<std::uint8_t>(t.tm_mday))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_date(const std::chrono::system_clock::time_point& tp)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto t    = std::chrono::system_clock::to_time_t(tp);
 | 
				
			||||||
 | 
					        const auto time = detail::localtime_s(&t);
 | 
				
			||||||
 | 
					        *this = local_date(time);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_date(const std::time_t t)
 | 
				
			||||||
 | 
					        : local_date(std::chrono::system_clock::from_time_t(t))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::chrono::system_clock::time_point() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // std::mktime returns date as local time zone. no conversion needed
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_sec   = 0;
 | 
				
			||||||
 | 
					        t.tm_min   = 0;
 | 
				
			||||||
 | 
					        t.tm_hour  = 0;
 | 
				
			||||||
 | 
					        t.tm_mday  = static_cast<int>(this->day);
 | 
				
			||||||
 | 
					        t.tm_mon   = static_cast<int>(this->month);
 | 
				
			||||||
 | 
					        t.tm_year  = static_cast<int>(this->year) - 1900;
 | 
				
			||||||
 | 
					        t.tm_wday  = 0; // the value will be ignored
 | 
				
			||||||
 | 
					        t.tm_yday  = 0; // the value will be ignored
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					        return std::chrono::system_clock::from_time_t(std::mktime(&t));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::time_t() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                std::chrono::system_clock::time_point(*this));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_date() = default;
 | 
				
			||||||
 | 
					    ~local_date() = default;
 | 
				
			||||||
 | 
					    local_date(local_date const&) = default;
 | 
				
			||||||
 | 
					    local_date(local_date&&)      = default;
 | 
				
			||||||
 | 
					    local_date& operator=(local_date const&) = default;
 | 
				
			||||||
 | 
					    local_date& operator=(local_date&&)      = default;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const local_date& lhs, const local_date& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.year, lhs.month, lhs.day) ==
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.year, rhs.month, rhs.day);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator!=(const local_date& lhs, const local_date& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator< (const local_date& lhs, const local_date& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.year, lhs.month, lhs.day) <
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.year, rhs.month, rhs.day);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<=(const local_date& lhs, const local_date& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (lhs < rhs) || (lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator> (const local_date& lhs, const local_date& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs <= rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>=(const local_date& lhs, const local_date& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const local_date& date)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(4) << static_cast<int>(date.year )     << '-';
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << static_cast<int>(date.month) + 1 << '-';
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << static_cast<int>(date.day  )    ;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct local_time
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::uint8_t  hour{};        // [0, 23]
 | 
				
			||||||
 | 
					    std::uint8_t  minute{};      // [0, 59]
 | 
				
			||||||
 | 
					    std::uint8_t  second{};      // [0, 60]
 | 
				
			||||||
 | 
					    std::uint16_t millisecond{}; // [0, 999]
 | 
				
			||||||
 | 
					    std::uint16_t microsecond{}; // [0, 999]
 | 
				
			||||||
 | 
					    std::uint16_t nanosecond{};  // [0, 999]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_time(int h, int m, int s,
 | 
				
			||||||
 | 
					               int ms = 0, int us = 0, int ns = 0)
 | 
				
			||||||
 | 
					        : hour  (static_cast<std::uint8_t>(h)),
 | 
				
			||||||
 | 
					          minute(static_cast<std::uint8_t>(m)),
 | 
				
			||||||
 | 
					          second(static_cast<std::uint8_t>(s)),
 | 
				
			||||||
 | 
					          millisecond(static_cast<std::uint16_t>(ms)),
 | 
				
			||||||
 | 
					          microsecond(static_cast<std::uint16_t>(us)),
 | 
				
			||||||
 | 
					          nanosecond (static_cast<std::uint16_t>(ns))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_time(const std::tm& t)
 | 
				
			||||||
 | 
					        : hour  (static_cast<std::uint8_t>(t.tm_hour)),
 | 
				
			||||||
 | 
					          minute(static_cast<std::uint8_t>(t.tm_min)),
 | 
				
			||||||
 | 
					          second(static_cast<std::uint8_t>(t.tm_sec)),
 | 
				
			||||||
 | 
					          millisecond(0), microsecond(0), nanosecond(0)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename Rep, typename Period>
 | 
				
			||||||
 | 
					    explicit local_time(const std::chrono::duration<Rep, Period>& t)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto h = std::chrono::duration_cast<std::chrono::hours>(t);
 | 
				
			||||||
 | 
					        this->hour = static_cast<std::uint8_t>(h.count());
 | 
				
			||||||
 | 
					        const auto t2 = t - h;
 | 
				
			||||||
 | 
					        const auto m = std::chrono::duration_cast<std::chrono::minutes>(t2);
 | 
				
			||||||
 | 
					        this->minute = static_cast<std::uint8_t>(m.count());
 | 
				
			||||||
 | 
					        const auto t3 = t2 - m;
 | 
				
			||||||
 | 
					        const auto s = std::chrono::duration_cast<std::chrono::seconds>(t3);
 | 
				
			||||||
 | 
					        this->second = static_cast<std::uint8_t>(s.count());
 | 
				
			||||||
 | 
					        const auto t4 = t3 - s;
 | 
				
			||||||
 | 
					        const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t4);
 | 
				
			||||||
 | 
					        this->millisecond = static_cast<std::uint16_t>(ms.count());
 | 
				
			||||||
 | 
					        const auto t5 = t4 - ms;
 | 
				
			||||||
 | 
					        const auto us = std::chrono::duration_cast<std::chrono::microseconds>(t5);
 | 
				
			||||||
 | 
					        this->microsecond = static_cast<std::uint16_t>(us.count());
 | 
				
			||||||
 | 
					        const auto t6 = t5 - us;
 | 
				
			||||||
 | 
					        const auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(t6);
 | 
				
			||||||
 | 
					        this->nanosecond = static_cast<std::uint16_t>(ns.count());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::chrono::nanoseconds() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::chrono::nanoseconds (this->nanosecond)  +
 | 
				
			||||||
 | 
					               std::chrono::microseconds(this->microsecond) +
 | 
				
			||||||
 | 
					               std::chrono::milliseconds(this->millisecond) +
 | 
				
			||||||
 | 
					               std::chrono::seconds(this->second) +
 | 
				
			||||||
 | 
					               std::chrono::minutes(this->minute) +
 | 
				
			||||||
 | 
					               std::chrono::hours(this->hour);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_time() = default;
 | 
				
			||||||
 | 
					    ~local_time() = default;
 | 
				
			||||||
 | 
					    local_time(local_time const&) = default;
 | 
				
			||||||
 | 
					    local_time(local_time&&)      = default;
 | 
				
			||||||
 | 
					    local_time& operator=(local_time const&) = default;
 | 
				
			||||||
 | 
					    local_time& operator=(local_time&&)      = default;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const local_time& lhs, const local_time& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) ==
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator!=(const local_time& lhs, const local_time& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator< (const local_time& lhs, const local_time& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.hour, lhs.minute, lhs.second, lhs.millisecond, lhs.microsecond, lhs.nanosecond) <
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.hour, rhs.minute, rhs.second, rhs.millisecond, rhs.microsecond, rhs.nanosecond);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<=(const local_time& lhs, const local_time& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (lhs < rhs) || (lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator> (const local_time& lhs, const local_time& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs <= rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>=(const local_time& lhs, const local_time& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const local_time& time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << static_cast<int>(time.hour  ) << ':';
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << static_cast<int>(time.minute) << ':';
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << static_cast<int>(time.second);
 | 
				
			||||||
 | 
					    if(time.millisecond != 0 || time.microsecond != 0 || time.nanosecond != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        os << '.';
 | 
				
			||||||
 | 
					        os << std::setfill('0') << std::setw(3) << static_cast<int>(time.millisecond);
 | 
				
			||||||
 | 
					        if(time.microsecond != 0 || time.nanosecond != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            os << std::setfill('0') << std::setw(3) << static_cast<int>(time.microsecond);
 | 
				
			||||||
 | 
					            if(time.nanosecond != 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                os << std::setfill('0') << std::setw(3) << static_cast<int>(time.nanosecond);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct time_offset
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::int8_t hour{};   // [-12, 12]
 | 
				
			||||||
 | 
					    std::int8_t minute{}; // [-59, 59]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    time_offset(int h, int m)
 | 
				
			||||||
 | 
					        : hour  (static_cast<std::int8_t>(h)),
 | 
				
			||||||
 | 
					          minute(static_cast<std::int8_t>(m))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::chrono::minutes() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::chrono::minutes(this->minute) +
 | 
				
			||||||
 | 
					               std::chrono::hours(this->hour);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    time_offset() = default;
 | 
				
			||||||
 | 
					    ~time_offset() = default;
 | 
				
			||||||
 | 
					    time_offset(time_offset const&) = default;
 | 
				
			||||||
 | 
					    time_offset(time_offset&&)      = default;
 | 
				
			||||||
 | 
					    time_offset& operator=(time_offset const&) = default;
 | 
				
			||||||
 | 
					    time_offset& operator=(time_offset&&)      = default;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const time_offset& lhs, const time_offset& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.hour, lhs.minute) ==
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.hour, rhs.minute);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator!=(const time_offset& lhs, const time_offset& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator< (const time_offset& lhs, const time_offset& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.hour, lhs.minute) <
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.hour, rhs.minute);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<=(const time_offset& lhs, const time_offset& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (lhs < rhs) || (lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator> (const time_offset& lhs, const time_offset& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs <= rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>=(const time_offset& lhs, const time_offset& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const time_offset& offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(offset.hour == 0 && offset.minute == 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        os << 'Z';
 | 
				
			||||||
 | 
					        return os;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    int minute = static_cast<int>(offset.hour) * 60 + offset.minute;
 | 
				
			||||||
 | 
					    if(minute < 0){os << '-'; minute = std::abs(minute);} else {os << '+';}
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << minute / 60 << ':';
 | 
				
			||||||
 | 
					    os << std::setfill('0') << std::setw(2) << minute % 60;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct local_datetime
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    local_date date{};
 | 
				
			||||||
 | 
					    local_time time{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_datetime(local_date d, local_time t): date(d), time(t) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_datetime(const std::tm& t): date(t), time(t){}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_datetime(const std::chrono::system_clock::time_point& tp)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto t = std::chrono::system_clock::to_time_t(tp);
 | 
				
			||||||
 | 
					        std::tm ltime = detail::localtime_s(&t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this->date = local_date(ltime);
 | 
				
			||||||
 | 
					        this->time = local_time(ltime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // std::tm lacks subsecond information, so diff between tp and tm
 | 
				
			||||||
 | 
					        // can be used to get millisecond & microsecond information.
 | 
				
			||||||
 | 
					        const auto t_diff = tp -
 | 
				
			||||||
 | 
					            std::chrono::system_clock::from_time_t(std::mktime(<ime));
 | 
				
			||||||
 | 
					        this->time.millisecond = static_cast<std::uint16_t>(
 | 
				
			||||||
 | 
					          std::chrono::duration_cast<std::chrono::milliseconds>(t_diff).count());
 | 
				
			||||||
 | 
					        this->time.microsecond = static_cast<std::uint16_t>(
 | 
				
			||||||
 | 
					          std::chrono::duration_cast<std::chrono::microseconds>(t_diff).count());
 | 
				
			||||||
 | 
					        this->time.nanosecond = static_cast<std::uint16_t>(
 | 
				
			||||||
 | 
					          std::chrono::duration_cast<std::chrono::nanoseconds >(t_diff).count());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit local_datetime(const std::time_t t)
 | 
				
			||||||
 | 
					        : local_datetime(std::chrono::system_clock::from_time_t(t))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::chrono::system_clock::time_point() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using internal_duration =
 | 
				
			||||||
 | 
					            typename std::chrono::system_clock::time_point::duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Normally DST begins at A.M. 3 or 4. If we re-use conversion operator
 | 
				
			||||||
 | 
					        // of local_date and local_time independently, the conversion fails if
 | 
				
			||||||
 | 
					        // it is the day when DST begins or ends. Since local_date considers the
 | 
				
			||||||
 | 
					        // time is 00:00 A.M. and local_time does not consider DST because it
 | 
				
			||||||
 | 
					        // does not have any date information. We need to consider both date and
 | 
				
			||||||
 | 
					        // time information at the same time to convert it correctly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_sec   = static_cast<int>(this->time.second);
 | 
				
			||||||
 | 
					        t.tm_min   = static_cast<int>(this->time.minute);
 | 
				
			||||||
 | 
					        t.tm_hour  = static_cast<int>(this->time.hour);
 | 
				
			||||||
 | 
					        t.tm_mday  = static_cast<int>(this->date.day);
 | 
				
			||||||
 | 
					        t.tm_mon   = static_cast<int>(this->date.month);
 | 
				
			||||||
 | 
					        t.tm_year  = static_cast<int>(this->date.year) - 1900;
 | 
				
			||||||
 | 
					        t.tm_wday  = 0; // the value will be ignored
 | 
				
			||||||
 | 
					        t.tm_yday  = 0; // the value will be ignored
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // std::mktime returns date as local time zone. no conversion needed
 | 
				
			||||||
 | 
					        auto dt = std::chrono::system_clock::from_time_t(std::mktime(&t));
 | 
				
			||||||
 | 
					        dt += std::chrono::duration_cast<internal_duration>(
 | 
				
			||||||
 | 
					                std::chrono::milliseconds(this->time.millisecond) +
 | 
				
			||||||
 | 
					                std::chrono::microseconds(this->time.microsecond) +
 | 
				
			||||||
 | 
					                std::chrono::nanoseconds (this->time.nanosecond));
 | 
				
			||||||
 | 
					        return dt;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::time_t() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                std::chrono::system_clock::time_point(*this));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_datetime() = default;
 | 
				
			||||||
 | 
					    ~local_datetime() = default;
 | 
				
			||||||
 | 
					    local_datetime(local_datetime const&) = default;
 | 
				
			||||||
 | 
					    local_datetime(local_datetime&&)      = default;
 | 
				
			||||||
 | 
					    local_datetime& operator=(local_datetime const&) = default;
 | 
				
			||||||
 | 
					    local_datetime& operator=(local_datetime&&)      = default;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const local_datetime& lhs, const local_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.date, lhs.time) ==
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.date, rhs.time);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator!=(const local_datetime& lhs, const local_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator< (const local_datetime& lhs, const local_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.date, lhs.time) <
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.date, rhs.time);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<=(const local_datetime& lhs, const local_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (lhs < rhs) || (lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator> (const local_datetime& lhs, const local_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs <= rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>=(const local_datetime& lhs, const local_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const local_datetime& dt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << dt.date << 'T' << dt.time;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct offset_datetime
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    local_date  date{};
 | 
				
			||||||
 | 
					    local_time  time{};
 | 
				
			||||||
 | 
					    time_offset offset{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    offset_datetime(local_date d, local_time t, time_offset o)
 | 
				
			||||||
 | 
					        : date(d), time(t), offset(o)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    offset_datetime(const local_datetime& dt, time_offset o)
 | 
				
			||||||
 | 
					        : date(dt.date), time(dt.time), offset(o)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    explicit offset_datetime(const local_datetime& ld)
 | 
				
			||||||
 | 
					        : date(ld.date), time(ld.time), offset(get_local_offset(nullptr))
 | 
				
			||||||
 | 
					          // use the current local timezone offset
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
 | 
				
			||||||
 | 
					        : offset(0, 0) // use gmtime
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto timet = std::chrono::system_clock::to_time_t(tp);
 | 
				
			||||||
 | 
					        const auto tm    = detail::gmtime_s(&timet);
 | 
				
			||||||
 | 
					        this->date = local_date(tm);
 | 
				
			||||||
 | 
					        this->time = local_time(tm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    explicit offset_datetime(const std::time_t& t)
 | 
				
			||||||
 | 
					        : offset(0, 0) // use gmtime
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto tm    = detail::gmtime_s(&t);
 | 
				
			||||||
 | 
					        this->date = local_date(tm);
 | 
				
			||||||
 | 
					        this->time = local_time(tm);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    explicit offset_datetime(const std::tm& t)
 | 
				
			||||||
 | 
					        : offset(0, 0) // assume gmtime
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->date = local_date(t);
 | 
				
			||||||
 | 
					        this->time = local_time(t);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::chrono::system_clock::time_point() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // get date-time
 | 
				
			||||||
 | 
					        using internal_duration =
 | 
				
			||||||
 | 
					            typename std::chrono::system_clock::time_point::duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // first, convert it to local date-time information in the same way as
 | 
				
			||||||
 | 
					        // local_datetime does. later we will use time_t to adjust time offset.
 | 
				
			||||||
 | 
					        std::tm t;
 | 
				
			||||||
 | 
					        t.tm_sec   = static_cast<int>(this->time.second);
 | 
				
			||||||
 | 
					        t.tm_min   = static_cast<int>(this->time.minute);
 | 
				
			||||||
 | 
					        t.tm_hour  = static_cast<int>(this->time.hour);
 | 
				
			||||||
 | 
					        t.tm_mday  = static_cast<int>(this->date.day);
 | 
				
			||||||
 | 
					        t.tm_mon   = static_cast<int>(this->date.month);
 | 
				
			||||||
 | 
					        t.tm_year  = static_cast<int>(this->date.year) - 1900;
 | 
				
			||||||
 | 
					        t.tm_wday  = 0; // the value will be ignored
 | 
				
			||||||
 | 
					        t.tm_yday  = 0; // the value will be ignored
 | 
				
			||||||
 | 
					        t.tm_isdst = -1;
 | 
				
			||||||
 | 
					        const std::time_t tp_loc = std::mktime(std::addressof(t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto tp = std::chrono::system_clock::from_time_t(tp_loc);
 | 
				
			||||||
 | 
					        tp += std::chrono::duration_cast<internal_duration>(
 | 
				
			||||||
 | 
					                std::chrono::milliseconds(this->time.millisecond) +
 | 
				
			||||||
 | 
					                std::chrono::microseconds(this->time.microsecond) +
 | 
				
			||||||
 | 
					                std::chrono::nanoseconds (this->time.nanosecond));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Since mktime uses local time zone, it should be corrected.
 | 
				
			||||||
 | 
					        // `12:00:00+09:00` means `03:00:00Z`. So mktime returns `03:00:00Z` if
 | 
				
			||||||
 | 
					        // we are in `+09:00` timezone. To represent `12:00:00Z` there, we need
 | 
				
			||||||
 | 
					        // to add `+09:00` to `03:00:00Z`.
 | 
				
			||||||
 | 
					        //    Here, it uses the time_t converted from date-time info to handle
 | 
				
			||||||
 | 
					        // daylight saving time.
 | 
				
			||||||
 | 
					        const auto ofs = get_local_offset(std::addressof(tp_loc));
 | 
				
			||||||
 | 
					        tp += std::chrono::hours  (ofs.hour);
 | 
				
			||||||
 | 
					        tp += std::chrono::minutes(ofs.minute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We got `12:00:00Z` by correcting local timezone applied by mktime.
 | 
				
			||||||
 | 
					        // Then we will apply the offset. Let's say `12:00:00-08:00` is given.
 | 
				
			||||||
 | 
					        // And now, we have `12:00:00Z`. `12:00:00-08:00` means `20:00:00Z`.
 | 
				
			||||||
 | 
					        // So we need to subtract the offset.
 | 
				
			||||||
 | 
					        tp -= std::chrono::minutes(this->offset);
 | 
				
			||||||
 | 
					        return tp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::time_t() const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::chrono::system_clock::to_time_t(
 | 
				
			||||||
 | 
					                std::chrono::system_clock::time_point(*this));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    offset_datetime() = default;
 | 
				
			||||||
 | 
					    ~offset_datetime() = default;
 | 
				
			||||||
 | 
					    offset_datetime(offset_datetime const&) = default;
 | 
				
			||||||
 | 
					    offset_datetime(offset_datetime&&)      = default;
 | 
				
			||||||
 | 
					    offset_datetime& operator=(offset_datetime const&) = default;
 | 
				
			||||||
 | 
					    offset_datetime& operator=(offset_datetime&&)      = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static time_offset get_local_offset(const std::time_t* tp)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // get local timezone with the same date-time information as mktime
 | 
				
			||||||
 | 
					        const auto t = detail::localtime_s(tp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::array<char, 6> buf;
 | 
				
			||||||
 | 
					        const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
 | 
				
			||||||
 | 
					        if(result != 5)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw std::runtime_error("toml::offset_datetime: cannot obtain "
 | 
				
			||||||
 | 
					                                     "timezone information of current env");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const int ofs = std::atoi(buf.data());
 | 
				
			||||||
 | 
					        const int ofs_h = ofs / 100;
 | 
				
			||||||
 | 
					        const int ofs_m = ofs - (ofs_h * 100);
 | 
				
			||||||
 | 
					        return time_offset(ofs_h, ofs_m);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const offset_datetime& lhs, const offset_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.date, lhs.time, lhs.offset) ==
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.date, rhs.time, rhs.offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator!=(const offset_datetime& lhs, const offset_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator< (const offset_datetime& lhs, const offset_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::make_tuple(lhs.date, lhs.time, lhs.offset) <
 | 
				
			||||||
 | 
					           std::make_tuple(rhs.date, rhs.time, rhs.offset);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<=(const offset_datetime& lhs, const offset_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (lhs < rhs) || (lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator> (const offset_datetime& lhs, const offset_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs <= rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>=(const offset_datetime& lhs, const offset_datetime& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const offset_datetime& dt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << dt.date << 'T' << dt.time << dt.offset;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}//toml
 | 
				
			||||||
 | 
					#endif// TOML11_DATETIME
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,83 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_EXCEPTION_HPP
 | 
				
			||||||
 | 
					#define TOML11_EXCEPTION_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "source_location.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct file_io_error : public std::runtime_error
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    file_io_error(int errnum, const std::string& msg, const std::string& fname)
 | 
				
			||||||
 | 
					        : std::runtime_error(msg + " \"" + fname + "\": errno = " + std::to_string(errnum)),
 | 
				
			||||||
 | 
					          errno_(errnum)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int get_errno() const noexcept {return errno_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    int errno_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct exception : public std::exception
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    explicit exception(const source_location& loc): loc_(loc) {}
 | 
				
			||||||
 | 
					    virtual ~exception() noexcept override = default;
 | 
				
			||||||
 | 
					    virtual const char* what() const noexcept override {return "";}
 | 
				
			||||||
 | 
					    virtual source_location const& location() const noexcept {return loc_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected:
 | 
				
			||||||
 | 
					    source_location loc_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct syntax_error : public toml::exception
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    explicit syntax_error(const std::string& what_arg, const source_location& loc)
 | 
				
			||||||
 | 
					        : exception(loc), what_(what_arg)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    virtual ~syntax_error() noexcept override = default;
 | 
				
			||||||
 | 
					    virtual const char* what() const noexcept override {return what_.c_str();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected:
 | 
				
			||||||
 | 
					    std::string what_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct type_error : public toml::exception
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    explicit type_error(const std::string& what_arg, const source_location& loc)
 | 
				
			||||||
 | 
					        : exception(loc), what_(what_arg)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    virtual ~type_error() noexcept override = default;
 | 
				
			||||||
 | 
					    virtual const char* what() const noexcept override {return what_.c_str();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected:
 | 
				
			||||||
 | 
					    std::string what_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct internal_error : public toml::exception
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					    explicit internal_error(const std::string& what_arg, const source_location& loc)
 | 
				
			||||||
 | 
					        : exception(loc), what_(what_arg)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    virtual ~internal_error() noexcept override = default;
 | 
				
			||||||
 | 
					    virtual const char* what() const noexcept override {return what_.c_str();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected:
 | 
				
			||||||
 | 
					    std::string what_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif // TOML_EXCEPTION
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2019.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_FROM_HPP
 | 
				
			||||||
 | 
					#define TOML11_FROM_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct from;
 | 
				
			||||||
 | 
					// {
 | 
				
			||||||
 | 
					//     static T from_toml(const toml::value& v)
 | 
				
			||||||
 | 
					//     {
 | 
				
			||||||
 | 
					//         // User-defined conversions ...
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif // TOML11_FROM_HPP
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2019.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_INTO_HPP
 | 
				
			||||||
 | 
					#define TOML11_INTO_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct into;
 | 
				
			||||||
 | 
					// {
 | 
				
			||||||
 | 
					//     static toml::value into_toml(const T& user_defined_type)
 | 
				
			||||||
 | 
					//     {
 | 
				
			||||||
 | 
					//         // User-defined conversions ...
 | 
				
			||||||
 | 
					//     }
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif // TOML11_INTO_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,294 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_LEXER_HPP
 | 
				
			||||||
 | 
					#define TOML11_LEXER_HPP
 | 
				
			||||||
 | 
					#include <istream>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "combinator.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// these scans contents from current location in a container of char
 | 
				
			||||||
 | 
					// and extract a region that matches their own pattern.
 | 
				
			||||||
 | 
					// to see the implementation of each component, see combinator.hpp.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_wschar  = either<character<' '>, character<'\t'>>;
 | 
				
			||||||
 | 
					using lex_ws      = repeat<lex_wschar, at_least<1>>;
 | 
				
			||||||
 | 
					using lex_newline = either<character<'\n'>,
 | 
				
			||||||
 | 
					                           sequence<character<'\r'>, character<'\n'>>>;
 | 
				
			||||||
 | 
					using lex_lower   = in_range<'a', 'z'>;
 | 
				
			||||||
 | 
					using lex_upper   = in_range<'A', 'Z'>;
 | 
				
			||||||
 | 
					using lex_alpha   = either<lex_lower, lex_upper>;
 | 
				
			||||||
 | 
					using lex_digit   = in_range<'0', '9'>;
 | 
				
			||||||
 | 
					using lex_nonzero = in_range<'1', '9'>;
 | 
				
			||||||
 | 
					using lex_oct_dig = in_range<'0', '7'>;
 | 
				
			||||||
 | 
					using lex_bin_dig = in_range<'0', '1'>;
 | 
				
			||||||
 | 
					using lex_hex_dig = either<lex_digit, in_range<'A', 'F'>, in_range<'a', 'f'>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_hex_prefix = sequence<character<'0'>, character<'x'>>;
 | 
				
			||||||
 | 
					using lex_oct_prefix = sequence<character<'0'>, character<'o'>>;
 | 
				
			||||||
 | 
					using lex_bin_prefix = sequence<character<'0'>, character<'b'>>;
 | 
				
			||||||
 | 
					using lex_underscore = character<'_'>;
 | 
				
			||||||
 | 
					using lex_plus       = character<'+'>;
 | 
				
			||||||
 | 
					using lex_minus      = character<'-'>;
 | 
				
			||||||
 | 
					using lex_sign       = either<lex_plus, lex_minus>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// digit | nonzero 1*(digit | _ digit)
 | 
				
			||||||
 | 
					using lex_unsigned_dec_int = either<sequence<lex_nonzero, repeat<
 | 
				
			||||||
 | 
					    either<lex_digit, sequence<lex_underscore, lex_digit>>, at_least<1>>>,
 | 
				
			||||||
 | 
					    lex_digit>;
 | 
				
			||||||
 | 
					// (+|-)? unsigned_dec_int
 | 
				
			||||||
 | 
					using lex_dec_int = sequence<maybe<lex_sign>, lex_unsigned_dec_int>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// hex_prefix hex_dig *(hex_dig | _ hex_dig)
 | 
				
			||||||
 | 
					using lex_hex_int = sequence<lex_hex_prefix, sequence<lex_hex_dig, repeat<
 | 
				
			||||||
 | 
					    either<lex_hex_dig, sequence<lex_underscore, lex_hex_dig>>, unlimited>>>;
 | 
				
			||||||
 | 
					// oct_prefix oct_dig *(oct_dig | _ oct_dig)
 | 
				
			||||||
 | 
					using lex_oct_int = sequence<lex_oct_prefix, sequence<lex_oct_dig, repeat<
 | 
				
			||||||
 | 
					    either<lex_oct_dig, sequence<lex_underscore, lex_oct_dig>>, unlimited>>>;
 | 
				
			||||||
 | 
					// bin_prefix bin_dig *(bin_dig | _ bin_dig)
 | 
				
			||||||
 | 
					using lex_bin_int = sequence<lex_bin_prefix, sequence<lex_bin_dig, repeat<
 | 
				
			||||||
 | 
					    either<lex_bin_dig, sequence<lex_underscore, lex_bin_dig>>, unlimited>>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// (dec_int | hex_int | oct_int | bin_int)
 | 
				
			||||||
 | 
					using lex_integer = either<lex_bin_int, lex_oct_int, lex_hex_int, lex_dec_int>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_inf = sequence<character<'i'>, character<'n'>, character<'f'>>;
 | 
				
			||||||
 | 
					using lex_nan = sequence<character<'n'>, character<'a'>, character<'n'>>;
 | 
				
			||||||
 | 
					using lex_special_float = sequence<maybe<lex_sign>, either<lex_inf, lex_nan>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_zero_prefixable_int = sequence<lex_digit, repeat<either<lex_digit,
 | 
				
			||||||
 | 
					    sequence<lex_underscore, lex_digit>>, unlimited>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_fractional_part = sequence<character<'.'>, lex_zero_prefixable_int>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_exponent_part   = sequence<either<character<'e'>, character<'E'>>,
 | 
				
			||||||
 | 
					        maybe<lex_sign>, lex_zero_prefixable_int>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_float = either<lex_special_float,
 | 
				
			||||||
 | 
					      sequence<lex_dec_int, either<lex_exponent_part,
 | 
				
			||||||
 | 
					      sequence<lex_fractional_part, maybe<lex_exponent_part>>>>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_true = sequence<character<'t'>, character<'r'>,
 | 
				
			||||||
 | 
					                          character<'u'>, character<'e'>>;
 | 
				
			||||||
 | 
					using lex_false = sequence<character<'f'>, character<'a'>, character<'l'>,
 | 
				
			||||||
 | 
					                           character<'s'>, character<'e'>>;
 | 
				
			||||||
 | 
					using lex_boolean = either<lex_true, lex_false>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_date_fullyear = repeat<lex_digit, exactly<4>>;
 | 
				
			||||||
 | 
					using lex_date_month    = repeat<lex_digit, exactly<2>>;
 | 
				
			||||||
 | 
					using lex_date_mday     = repeat<lex_digit, exactly<2>>;
 | 
				
			||||||
 | 
					using lex_time_delim    = either<character<'T'>, character<'t'>, character<' '>>;
 | 
				
			||||||
 | 
					using lex_time_hour     = repeat<lex_digit, exactly<2>>;
 | 
				
			||||||
 | 
					using lex_time_minute   = repeat<lex_digit, exactly<2>>;
 | 
				
			||||||
 | 
					using lex_time_second   = repeat<lex_digit, exactly<2>>;
 | 
				
			||||||
 | 
					using lex_time_secfrac  = sequence<character<'.'>,
 | 
				
			||||||
 | 
					                                   repeat<lex_digit, at_least<1>>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_time_numoffset = sequence<either<character<'+'>, character<'-'>>,
 | 
				
			||||||
 | 
					                                    sequence<lex_time_hour, character<':'>,
 | 
				
			||||||
 | 
					                                             lex_time_minute>>;
 | 
				
			||||||
 | 
					using lex_time_offset = either<character<'Z'>, character<'z'>,
 | 
				
			||||||
 | 
					                               lex_time_numoffset>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_partial_time = sequence<lex_time_hour,   character<':'>,
 | 
				
			||||||
 | 
					                                  lex_time_minute, character<':'>,
 | 
				
			||||||
 | 
					                                  lex_time_second, maybe<lex_time_secfrac>>;
 | 
				
			||||||
 | 
					using lex_full_date    = sequence<lex_date_fullyear, character<'-'>,
 | 
				
			||||||
 | 
					                                  lex_date_month,    character<'-'>,
 | 
				
			||||||
 | 
					                                  lex_date_mday>;
 | 
				
			||||||
 | 
					using lex_full_time    = sequence<lex_partial_time, lex_time_offset>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_offset_date_time = sequence<lex_full_date, lex_time_delim, lex_full_time>;
 | 
				
			||||||
 | 
					using lex_local_date_time  = sequence<lex_full_date, lex_time_delim, lex_partial_time>;
 | 
				
			||||||
 | 
					using lex_local_date       = lex_full_date;
 | 
				
			||||||
 | 
					using lex_local_time       = lex_partial_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===========================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_quotation_mark  = character<'"'>;
 | 
				
			||||||
 | 
					using lex_basic_unescaped = exclude<either<in_range<0x00, 0x08>, // 0x09 (tab) is allowed
 | 
				
			||||||
 | 
					                                           in_range<0x0A, 0x1F>,
 | 
				
			||||||
 | 
					                                           character<0x22>, character<0x5C>,
 | 
				
			||||||
 | 
					                                           character<0x7F>>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_escape          = character<'\\'>;
 | 
				
			||||||
 | 
					using lex_escape_unicode_short = sequence<character<'u'>,
 | 
				
			||||||
 | 
					                                          repeat<lex_hex_dig, exactly<4>>>;
 | 
				
			||||||
 | 
					using lex_escape_unicode_long  = sequence<character<'U'>,
 | 
				
			||||||
 | 
					                                          repeat<lex_hex_dig, exactly<8>>>;
 | 
				
			||||||
 | 
					using lex_escape_seq_char = either<character<'"'>, character<'\\'>,
 | 
				
			||||||
 | 
					                                   character<'b'>, character<'f'>,
 | 
				
			||||||
 | 
					                                   character<'n'>, character<'r'>,
 | 
				
			||||||
 | 
					                                   character<'t'>,
 | 
				
			||||||
 | 
					#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
 | 
				
			||||||
 | 
					                                   character<'e'>, // ESC (0x1B)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                                   lex_escape_unicode_short,
 | 
				
			||||||
 | 
					                                   lex_escape_unicode_long
 | 
				
			||||||
 | 
					                                   >;
 | 
				
			||||||
 | 
					using lex_escaped      = sequence<lex_escape, lex_escape_seq_char>;
 | 
				
			||||||
 | 
					using lex_basic_char   = either<lex_basic_unescaped, lex_escaped>;
 | 
				
			||||||
 | 
					using lex_basic_string = sequence<lex_quotation_mark,
 | 
				
			||||||
 | 
					                                  repeat<lex_basic_char, unlimited>,
 | 
				
			||||||
 | 
					                                  lex_quotation_mark>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// After toml post-v0.5.0, it is explicitly clarified how quotes in ml-strings
 | 
				
			||||||
 | 
					// are allowed to be used.
 | 
				
			||||||
 | 
					// After this, the following strings are *explicitly* allowed.
 | 
				
			||||||
 | 
					// - One or two `"`s in a multi-line basic string is allowed wherever it is.
 | 
				
			||||||
 | 
					// - Three consecutive `"`s in a multi-line basic string is considered as a delimiter.
 | 
				
			||||||
 | 
					// - One or two `"`s can appear just before or after the delimiter.
 | 
				
			||||||
 | 
					// ```toml
 | 
				
			||||||
 | 
					// str4 = """Here are two quotation marks: "". Simple enough."""
 | 
				
			||||||
 | 
					// str5 = """Here are three quotation marks: ""\"."""
 | 
				
			||||||
 | 
					// str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
 | 
				
			||||||
 | 
					// str7 = """"This," she said, "is just a pointless statement.""""
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// In the current implementation (v3.3.0), it is difficult to parse `str7` in
 | 
				
			||||||
 | 
					// the above example. It is difficult to recognize `"` at the end of string body
 | 
				
			||||||
 | 
					// collectly. It will be misunderstood as a `"""` delimiter and an additional,
 | 
				
			||||||
 | 
					// invalid `"`. Like this:
 | 
				
			||||||
 | 
					// ```console
 | 
				
			||||||
 | 
					//   what():  [error] toml::parse_table: invalid line format
 | 
				
			||||||
 | 
					//  --> hoge.toml
 | 
				
			||||||
 | 
					//     |
 | 
				
			||||||
 | 
					//  13 | str7 = """"This," she said, "is just a pointless statement.""""
 | 
				
			||||||
 | 
					//     |                                                               ^- expected newline, but got '"'.
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// As a quick workaround for this problem, `lex_ml_basic_string_delim` was
 | 
				
			||||||
 | 
					// split into two, `lex_ml_basic_string_open` and `lex_ml_basic_string_close`.
 | 
				
			||||||
 | 
					// `lex_ml_basic_string_open` allows only `"""`. `_close` allows 3-5 `"`s.
 | 
				
			||||||
 | 
					// In parse_ml_basic_string() function, the trailing `"`s will be attached to
 | 
				
			||||||
 | 
					// the string body.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					using lex_ml_basic_string_delim = repeat<lex_quotation_mark, exactly<3>>;
 | 
				
			||||||
 | 
					using lex_ml_basic_string_open  = lex_ml_basic_string_delim;
 | 
				
			||||||
 | 
					using lex_ml_basic_string_close = sequence<
 | 
				
			||||||
 | 
					        repeat<lex_quotation_mark, exactly<3>>,
 | 
				
			||||||
 | 
					        maybe<lex_quotation_mark>, maybe<lex_quotation_mark>
 | 
				
			||||||
 | 
					    >;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_ml_basic_unescaped    = exclude<either<in_range<0x00, 0x08>, // 0x09 is tab
 | 
				
			||||||
 | 
					                                                 in_range<0x0A, 0x1F>,
 | 
				
			||||||
 | 
					                                                 character<0x5C>, // backslash
 | 
				
			||||||
 | 
					                                                 character<0x7F>, // DEL
 | 
				
			||||||
 | 
					                                                 lex_ml_basic_string_delim>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_ml_basic_escaped_newline = sequence<
 | 
				
			||||||
 | 
					        lex_escape, maybe<lex_ws>, lex_newline,
 | 
				
			||||||
 | 
					        repeat<either<lex_ws, lex_newline>, unlimited>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_ml_basic_char = either<lex_ml_basic_unescaped, lex_escaped>;
 | 
				
			||||||
 | 
					using lex_ml_basic_body = repeat<either<lex_ml_basic_char, lex_newline,
 | 
				
			||||||
 | 
					                                        lex_ml_basic_escaped_newline>,
 | 
				
			||||||
 | 
					                                 unlimited>;
 | 
				
			||||||
 | 
					using lex_ml_basic_string = sequence<lex_ml_basic_string_open,
 | 
				
			||||||
 | 
					                                     lex_ml_basic_body,
 | 
				
			||||||
 | 
					                                     lex_ml_basic_string_close>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_literal_char = exclude<either<in_range<0x00, 0x08>, in_range<0x0A, 0x1F>,
 | 
				
			||||||
 | 
					                                        character<0x7F>, character<0x27>>>;
 | 
				
			||||||
 | 
					using lex_apostrophe = character<'\''>;
 | 
				
			||||||
 | 
					using lex_literal_string = sequence<lex_apostrophe,
 | 
				
			||||||
 | 
					                                    repeat<lex_literal_char, unlimited>,
 | 
				
			||||||
 | 
					                                    lex_apostrophe>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// the same reason as above.
 | 
				
			||||||
 | 
					using lex_ml_literal_string_delim = repeat<lex_apostrophe, exactly<3>>;
 | 
				
			||||||
 | 
					using lex_ml_literal_string_open  = lex_ml_literal_string_delim;
 | 
				
			||||||
 | 
					using lex_ml_literal_string_close = sequence<
 | 
				
			||||||
 | 
					        repeat<lex_apostrophe, exactly<3>>,
 | 
				
			||||||
 | 
					        maybe<lex_apostrophe>, maybe<lex_apostrophe>
 | 
				
			||||||
 | 
					    >;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_ml_literal_char = exclude<either<in_range<0x00, 0x08>,
 | 
				
			||||||
 | 
					                                           in_range<0x0A, 0x1F>,
 | 
				
			||||||
 | 
					                                           character<0x7F>,
 | 
				
			||||||
 | 
					                                           lex_ml_literal_string_delim>>;
 | 
				
			||||||
 | 
					using lex_ml_literal_body = repeat<either<lex_ml_literal_char, lex_newline>,
 | 
				
			||||||
 | 
					                                   unlimited>;
 | 
				
			||||||
 | 
					using lex_ml_literal_string = sequence<lex_ml_literal_string_open,
 | 
				
			||||||
 | 
					                                       lex_ml_literal_body,
 | 
				
			||||||
 | 
					                                       lex_ml_literal_string_close>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_string = either<lex_ml_basic_string,   lex_basic_string,
 | 
				
			||||||
 | 
					                          lex_ml_literal_string, lex_literal_string>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ===========================================================================
 | 
				
			||||||
 | 
					using lex_dot_sep = sequence<maybe<lex_ws>, character<'.'>, maybe<lex_ws>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_unquoted_key = repeat<either<lex_alpha, lex_digit,
 | 
				
			||||||
 | 
					                                       character<'-'>, character<'_'>>,
 | 
				
			||||||
 | 
					                                at_least<1>>;
 | 
				
			||||||
 | 
					using lex_quoted_key = either<lex_basic_string, lex_literal_string>;
 | 
				
			||||||
 | 
					using lex_simple_key = either<lex_unquoted_key, lex_quoted_key>;
 | 
				
			||||||
 | 
					using lex_dotted_key = sequence<lex_simple_key,
 | 
				
			||||||
 | 
					                                repeat<sequence<lex_dot_sep, lex_simple_key>,
 | 
				
			||||||
 | 
					                                       at_least<1>
 | 
				
			||||||
 | 
					                                       >
 | 
				
			||||||
 | 
					                                >;
 | 
				
			||||||
 | 
					using lex_key = either<lex_dotted_key, lex_simple_key>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_keyval_sep = sequence<maybe<lex_ws>,
 | 
				
			||||||
 | 
					                                character<'='>,
 | 
				
			||||||
 | 
					                                maybe<lex_ws>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_std_table_open  = character<'['>;
 | 
				
			||||||
 | 
					using lex_std_table_close = character<']'>;
 | 
				
			||||||
 | 
					using lex_std_table       = sequence<lex_std_table_open,
 | 
				
			||||||
 | 
					                                     maybe<lex_ws>,
 | 
				
			||||||
 | 
					                                     lex_key,
 | 
				
			||||||
 | 
					                                     maybe<lex_ws>,
 | 
				
			||||||
 | 
					                                     lex_std_table_close>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_array_table_open  = sequence<lex_std_table_open,  lex_std_table_open>;
 | 
				
			||||||
 | 
					using lex_array_table_close = sequence<lex_std_table_close, lex_std_table_close>;
 | 
				
			||||||
 | 
					using lex_array_table       = sequence<lex_array_table_open,
 | 
				
			||||||
 | 
					                                       maybe<lex_ws>,
 | 
				
			||||||
 | 
					                                       lex_key,
 | 
				
			||||||
 | 
					                                       maybe<lex_ws>,
 | 
				
			||||||
 | 
					                                       lex_array_table_close>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_utf8_1byte = in_range<0x00, 0x7F>;
 | 
				
			||||||
 | 
					using lex_utf8_2byte = sequence<
 | 
				
			||||||
 | 
					        in_range<'\xC2', '\xDF'>,
 | 
				
			||||||
 | 
					        in_range<'\x80', '\xBF'>
 | 
				
			||||||
 | 
					    >;
 | 
				
			||||||
 | 
					using lex_utf8_3byte = sequence<either<
 | 
				
			||||||
 | 
					        sequence<character<'\xE0'>, in_range<'\xA0', '\xBF'>>,
 | 
				
			||||||
 | 
					        sequence<in_range<'\xE1', '\xEC'>, in_range<'\x80', '\xBF'>>,
 | 
				
			||||||
 | 
					        sequence<character<'\xED'>, in_range<'\x80', '\x9F'>>,
 | 
				
			||||||
 | 
					        sequence<in_range<'\xEE', '\xEF'>, in_range<'\x80', '\xBF'>>
 | 
				
			||||||
 | 
					    >, in_range<'\x80', '\xBF'>>;
 | 
				
			||||||
 | 
					using lex_utf8_4byte = sequence<either<
 | 
				
			||||||
 | 
					        sequence<character<'\xF0'>, in_range<'\x90', '\xBF'>>,
 | 
				
			||||||
 | 
					        sequence<in_range<'\xF1', '\xF3'>, in_range<'\x80', '\xBF'>>,
 | 
				
			||||||
 | 
					        sequence<character<'\xF4'>, in_range<'\x80', '\x8F'>>
 | 
				
			||||||
 | 
					    >, in_range<'\x80', '\xBF'>, in_range<'\x80', '\xBF'>>;
 | 
				
			||||||
 | 
					using lex_utf8_code = either<
 | 
				
			||||||
 | 
					        lex_utf8_1byte,
 | 
				
			||||||
 | 
					        lex_utf8_2byte,
 | 
				
			||||||
 | 
					        lex_utf8_3byte,
 | 
				
			||||||
 | 
					        lex_utf8_4byte
 | 
				
			||||||
 | 
					    >;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using lex_comment_start_symbol = character<'#'>;
 | 
				
			||||||
 | 
					using lex_non_eol_ascii = either<character<0x09>, in_range<0x20, 0x7E>>;
 | 
				
			||||||
 | 
					using lex_comment = sequence<lex_comment_start_symbol, repeat<either<
 | 
				
			||||||
 | 
					    lex_non_eol_ascii, lex_utf8_2byte, lex_utf8_3byte, lex_utf8_4byte>, unlimited>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif // TOML_LEXER_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,113 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2019.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_LITERAL_HPP
 | 
				
			||||||
 | 
					#define TOML11_LITERAL_HPP
 | 
				
			||||||
 | 
					#include "parser.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					inline namespace literals
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					inline namespace toml_literals
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// implementation
 | 
				
			||||||
 | 
					inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
 | 
				
			||||||
 | 
					literal_internal_impl(::toml::detail::location loc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = ::toml::basic_value<
 | 
				
			||||||
 | 
					        TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>;
 | 
				
			||||||
 | 
					    // if there are some comments or empty lines, skip them.
 | 
				
			||||||
 | 
					    using skip_line = ::toml::detail::repeat<toml::detail::sequence<
 | 
				
			||||||
 | 
					            ::toml::detail::maybe<::toml::detail::lex_ws>,
 | 
				
			||||||
 | 
					            ::toml::detail::maybe<::toml::detail::lex_comment>,
 | 
				
			||||||
 | 
					            ::toml::detail::lex_newline
 | 
				
			||||||
 | 
					        >, ::toml::detail::at_least<1>>;
 | 
				
			||||||
 | 
					    skip_line::invoke(loc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // if there are some whitespaces before a value, skip them.
 | 
				
			||||||
 | 
					    using skip_ws = ::toml::detail::repeat<
 | 
				
			||||||
 | 
					        ::toml::detail::lex_ws, ::toml::detail::at_least<1>>;
 | 
				
			||||||
 | 
					    skip_ws::invoke(loc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // to distinguish arrays and tables, first check it is a table or not.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // "[1,2,3]"_toml;   // this is an array
 | 
				
			||||||
 | 
					    // "[table]"_toml;   // a table that has an empty table named "table" inside.
 | 
				
			||||||
 | 
					    // "[[1,2,3]]"_toml; // this is an array of arrays
 | 
				
			||||||
 | 
					    // "[[table]]"_toml; // this is a table that has an array of tables inside.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // "[[1]]"_toml;     // this can be both... (currently it becomes a table)
 | 
				
			||||||
 | 
					    // "1 = [{}]"_toml;  // this is a table that has an array of table named 1.
 | 
				
			||||||
 | 
					    // "[[1,]]"_toml;    // this is an array of arrays.
 | 
				
			||||||
 | 
					    // "[[1],]"_toml;    // this also.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto the_front = loc.iter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const bool is_table_key = ::toml::detail::lex_std_table::invoke(loc);
 | 
				
			||||||
 | 
					    loc.reset(the_front);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const bool is_aots_key  = ::toml::detail::lex_array_table::invoke(loc);
 | 
				
			||||||
 | 
					    loc.reset(the_front);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If it is neither a table-key or a array-of-table-key, it may be a value.
 | 
				
			||||||
 | 
					    if(!is_table_key && !is_aots_key)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(auto data = ::toml::detail::parse_value<value_type>(loc, 0))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return data.unwrap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Note that still it can be a table, because the literal might be something
 | 
				
			||||||
 | 
					    // like the following.
 | 
				
			||||||
 | 
					    // ```cpp
 | 
				
			||||||
 | 
					    // R"( // c++11 raw string literals
 | 
				
			||||||
 | 
					    //   key = "value"
 | 
				
			||||||
 | 
					    //   int = 42
 | 
				
			||||||
 | 
					    // )"_toml;
 | 
				
			||||||
 | 
					    // ```
 | 
				
			||||||
 | 
					    // It is a valid toml file.
 | 
				
			||||||
 | 
					    // It should be parsed as if we parse a file with this content.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(auto data = ::toml::detail::parse_toml_file<value_type>(loc))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return data.unwrap();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else // none of them.
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        throw ::toml::syntax_error(data.unwrap_err(), source_location(loc));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
 | 
				
			||||||
 | 
					operator"" _toml(const char* str, std::size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ::toml::detail::location loc(
 | 
				
			||||||
 | 
					            std::string("TOML literal encoded in a C++ code"),
 | 
				
			||||||
 | 
					            std::vector<char>(str, str + len));
 | 
				
			||||||
 | 
					    // literal length does not include the null character at the end.
 | 
				
			||||||
 | 
					    return literal_internal_impl(std::move(loc));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// value of __cplusplus in C++2a/20 mode is not fixed yet along compilers.
 | 
				
			||||||
 | 
					// So here we use the feature test macro for `char8_t` itself.
 | 
				
			||||||
 | 
					#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
 | 
				
			||||||
 | 
					// value of u8"" literal has been changed from char to char8_t and char8_t is
 | 
				
			||||||
 | 
					// NOT compatible to char
 | 
				
			||||||
 | 
					inline ::toml::basic_value<TOML11_DEFAULT_COMMENT_STRATEGY, std::unordered_map, std::vector>
 | 
				
			||||||
 | 
					operator"" _toml(const char8_t* str, std::size_t len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ::toml::detail::location loc(
 | 
				
			||||||
 | 
					            std::string("TOML literal encoded in a C++ code"),
 | 
				
			||||||
 | 
					            std::vector<char>(reinterpret_cast<const char*>(str),
 | 
				
			||||||
 | 
					                              reinterpret_cast<const char*>(str) + len));
 | 
				
			||||||
 | 
					    return literal_internal_impl(std::move(loc));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml_literals
 | 
				
			||||||
 | 
					} // literals
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif//TOML11_LITERAL_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,121 @@
 | 
				
			||||||
 | 
					#ifndef TOML11_MACROS_HPP
 | 
				
			||||||
 | 
					#define TOML11_MACROS_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_STRINGIZE_AUX(x) #x
 | 
				
			||||||
 | 
					#define TOML11_STRINGIZE(x)     TOML11_STRINGIZE_AUX(x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_CONCATENATE_AUX(x, y) x##y
 | 
				
			||||||
 | 
					#define TOML11_CONCATENATE(x, y)     TOML11_CONCATENATE_AUX(x, y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// TOML11_ARGS_SIZE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_INDEX_RSEQ() \
 | 
				
			||||||
 | 
					    32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, \
 | 
				
			||||||
 | 
					    16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1, 0
 | 
				
			||||||
 | 
					#define TOML11_ARGS_SIZE_IMPL(\
 | 
				
			||||||
 | 
					    ARG1,  ARG2,  ARG3,  ARG4,  ARG5,  ARG6,  ARG7,  ARG8,  ARG9,  ARG10, \
 | 
				
			||||||
 | 
					    ARG11, ARG12, ARG13, ARG14, ARG15, ARG16, ARG17, ARG18, ARG19, ARG20, \
 | 
				
			||||||
 | 
					    ARG21, ARG22, ARG23, ARG24, ARG25, ARG26, ARG27, ARG28, ARG29, ARG30, \
 | 
				
			||||||
 | 
					    ARG31, ARG32, N, ...) N
 | 
				
			||||||
 | 
					#define TOML11_ARGS_SIZE_AUX(...) TOML11_ARGS_SIZE_IMPL(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_ARGS_SIZE(...) TOML11_ARGS_SIZE_AUX(__VA_ARGS__, TOML11_INDEX_RSEQ())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// TOML11_FOR_EACH_VA_ARGS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_1( FUNCTOR, ARG1     ) FUNCTOR(ARG1)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_2( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_1( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_3( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_2( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_4( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_3( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_5( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_4( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_6( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_5( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_7( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_6( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_8( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_7( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_9( FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_8( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_10(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_9( FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_11(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_10(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_12(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_11(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_13(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_12(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_14(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_13(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_15(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_14(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_16(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_15(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_17(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_16(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_18(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_17(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_19(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_18(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_20(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_19(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_21(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_20(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_22(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_21(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_23(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_22(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_24(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_23(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_25(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_24(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_26(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_25(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_27(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_26(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_28(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_27(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_29(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_28(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_30(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_29(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_31(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_30(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS_AUX_32(FUNCTOR, ARG1, ...) FUNCTOR(ARG1) TOML11_FOR_EACH_VA_ARGS_AUX_31(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_FOR_EACH_VA_ARGS(FUNCTOR, ...)\
 | 
				
			||||||
 | 
					    TOML11_CONCATENATE(TOML11_FOR_EACH_VA_ARGS_AUX_, TOML11_ARGS_SIZE(__VA_ARGS__))(FUNCTOR, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// use it in the following way.
 | 
				
			||||||
 | 
					// ```cpp
 | 
				
			||||||
 | 
					// namespace foo
 | 
				
			||||||
 | 
					// {
 | 
				
			||||||
 | 
					// struct Foo
 | 
				
			||||||
 | 
					// {
 | 
				
			||||||
 | 
					//     std::string s;
 | 
				
			||||||
 | 
					//     double      d;
 | 
				
			||||||
 | 
					//     int         i;
 | 
				
			||||||
 | 
					// };
 | 
				
			||||||
 | 
					// } // foo
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(foo::Foo, s, d, i)
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// And then you can use `toml::find<foo::Foo>(file, "foo");`
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					#define TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE(VAR_NAME)\
 | 
				
			||||||
 | 
					    obj.VAR_NAME = toml::find<decltype(obj.VAR_NAME)>(v, TOML11_STRINGIZE(VAR_NAME));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_ASSIGN_MEMBER_VARIABLE_TO_VALUE(VAR_NAME)\
 | 
				
			||||||
 | 
					    v[TOML11_STRINGIZE(VAR_NAME)] = obj.VAR_NAME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(NAME, ...)\
 | 
				
			||||||
 | 
					    namespace toml {                                                                     \
 | 
				
			||||||
 | 
					    template<>                                                                           \
 | 
				
			||||||
 | 
					    struct from<NAME>                                                                    \
 | 
				
			||||||
 | 
					    {                                                                                    \
 | 
				
			||||||
 | 
					        template<typename C, template<typename ...> class T,                             \
 | 
				
			||||||
 | 
					                 template<typename ...> class A>                                         \
 | 
				
			||||||
 | 
					        static NAME from_toml(const basic_value<C, T, A>& v)                             \
 | 
				
			||||||
 | 
					        {                                                                                \
 | 
				
			||||||
 | 
					            NAME obj;                                                                    \
 | 
				
			||||||
 | 
					            TOML11_FOR_EACH_VA_ARGS(TOML11_FIND_MEMBER_VARIABLE_FROM_VALUE, __VA_ARGS__) \
 | 
				
			||||||
 | 
					            return obj;                                                                  \
 | 
				
			||||||
 | 
					        }                                                                                \
 | 
				
			||||||
 | 
					    };                                                                                   \
 | 
				
			||||||
 | 
					    template<>                                                                           \
 | 
				
			||||||
 | 
					    struct into<NAME>                                                                    \
 | 
				
			||||||
 | 
					    {                                                                                    \
 | 
				
			||||||
 | 
					        static value into_toml(const NAME& obj)                                          \
 | 
				
			||||||
 | 
					        {                                                                                \
 | 
				
			||||||
 | 
					            ::toml::value v = ::toml::table{};                                           \
 | 
				
			||||||
 | 
					            TOML11_FOR_EACH_VA_ARGS(TOML11_ASSIGN_MEMBER_VARIABLE_TO_VALUE, __VA_ARGS__) \
 | 
				
			||||||
 | 
					            return v;                                                                    \
 | 
				
			||||||
 | 
					        }                                                                                \
 | 
				
			||||||
 | 
					    };                                                                                   \
 | 
				
			||||||
 | 
					    } /* toml */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif// TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif// TOML11_MACROS_HPP
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,416 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_REGION_HPP
 | 
				
			||||||
 | 
					#define TOML11_REGION_HPP
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <initializer_list>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <iomanip>
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include "color.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// helper function to avoid std::string(0, 'c') or std::string(iter, iter)
 | 
				
			||||||
 | 
					template<typename Iterator>
 | 
				
			||||||
 | 
					std::string make_string(Iterator first, Iterator last)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(first == last) {return "";}
 | 
				
			||||||
 | 
					    return std::string(first, last);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline std::string make_string(std::size_t len, char c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(len == 0) {return "";}
 | 
				
			||||||
 | 
					    return std::string(len, c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// region_base is a base class of location and region that are defined below.
 | 
				
			||||||
 | 
					// it will be used to generate better error messages.
 | 
				
			||||||
 | 
					struct region_base
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    region_base() = default;
 | 
				
			||||||
 | 
					    virtual ~region_base() = default;
 | 
				
			||||||
 | 
					    region_base(const region_base&) = default;
 | 
				
			||||||
 | 
					    region_base(region_base&&     ) = default;
 | 
				
			||||||
 | 
					    region_base& operator=(const region_base&) = default;
 | 
				
			||||||
 | 
					    region_base& operator=(region_base&&     ) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual bool is_ok()           const noexcept {return false;}
 | 
				
			||||||
 | 
					    virtual char front()           const noexcept {return '\0';}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual std::string str()      const {return std::string("unknown region");}
 | 
				
			||||||
 | 
					    virtual std::string name()     const {return std::string("unknown file");}
 | 
				
			||||||
 | 
					    virtual std::string line()     const {return std::string("unknown line");}
 | 
				
			||||||
 | 
					    virtual std::string line_num() const {return std::string("?");}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // length of the region
 | 
				
			||||||
 | 
					    virtual std::size_t size()     const noexcept {return 0;}
 | 
				
			||||||
 | 
					    // number of characters in the line before the region
 | 
				
			||||||
 | 
					    virtual std::size_t before()   const noexcept {return 0;}
 | 
				
			||||||
 | 
					    // number of characters in the line after the region
 | 
				
			||||||
 | 
					    virtual std::size_t after()    const noexcept {return 0;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual std::vector<std::string> comments() const {return {};}
 | 
				
			||||||
 | 
					    // ```toml
 | 
				
			||||||
 | 
					    // # comment_before
 | 
				
			||||||
 | 
					    // key = "value" # comment_inline
 | 
				
			||||||
 | 
					    // ```
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// location represents a position in a container, which contains a file content.
 | 
				
			||||||
 | 
					// it can be considered as a region that contains only one character.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// it contains pointer to the file content and iterator that points the current
 | 
				
			||||||
 | 
					// location.
 | 
				
			||||||
 | 
					struct location final : public region_base
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using const_iterator  = typename std::vector<char>::const_iterator;
 | 
				
			||||||
 | 
					    using difference_type = typename std::iterator_traits<const_iterator>::difference_type;
 | 
				
			||||||
 | 
					    using source_ptr      = std::shared_ptr<const std::vector<char>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    location(std::string source_name, std::vector<char> cont)
 | 
				
			||||||
 | 
					      : source_(std::make_shared<std::vector<char>>(std::move(cont))),
 | 
				
			||||||
 | 
					        line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin())
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    location(std::string source_name, const std::string& cont)
 | 
				
			||||||
 | 
					      : source_(std::make_shared<std::vector<char>>(cont.begin(), cont.end())),
 | 
				
			||||||
 | 
					        line_number_(1), source_name_(std::move(source_name)), iter_(source_->cbegin())
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    location(const location&) = default;
 | 
				
			||||||
 | 
					    location(location&&)      = default;
 | 
				
			||||||
 | 
					    location& operator=(const location&) = default;
 | 
				
			||||||
 | 
					    location& operator=(location&&)      = default;
 | 
				
			||||||
 | 
					    ~location() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_ok() const noexcept override {return static_cast<bool>(source_);}
 | 
				
			||||||
 | 
					    char front() const noexcept override {return *iter_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // this const prohibits codes like `++(loc.iter())`.
 | 
				
			||||||
 | 
					    std::add_const<const_iterator>::type iter()  const noexcept {return iter_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const_iterator begin() const noexcept {return source_->cbegin();}
 | 
				
			||||||
 | 
					    const_iterator end()   const noexcept {return source_->cend();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // XXX `location::line_num()` used to be implemented using `std::count` to
 | 
				
			||||||
 | 
					    // count a number of '\n'. But with a long toml file (typically, 10k lines),
 | 
				
			||||||
 | 
					    // it becomes intolerably slow because each time it generates error messages,
 | 
				
			||||||
 | 
					    // it counts '\n' from thousands of characters. To workaround it, I decided
 | 
				
			||||||
 | 
					    // to introduce `location::line_number_` member variable and synchronize it
 | 
				
			||||||
 | 
					    // to the location changes the point to look. So an overload of `iter()`
 | 
				
			||||||
 | 
					    // which returns mutable reference is removed and `advance()`, `retrace()`
 | 
				
			||||||
 | 
					    // and `reset()` is added.
 | 
				
			||||||
 | 
					    void advance(difference_type n = 1) noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->line_number_ += static_cast<std::size_t>(
 | 
				
			||||||
 | 
					                std::count(this->iter_, std::next(this->iter_, n), '\n'));
 | 
				
			||||||
 | 
					        this->iter_ += n;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void retrace(difference_type n = 1) noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->line_number_ -= static_cast<std::size_t>(
 | 
				
			||||||
 | 
					                std::count(std::prev(this->iter_, n), this->iter_, '\n'));
 | 
				
			||||||
 | 
					        this->iter_ -= n;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    void reset(const_iterator rollback) noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // since c++11, std::distance works in both ways for random-access
 | 
				
			||||||
 | 
					        // iterators and returns a negative value if `first > last`.
 | 
				
			||||||
 | 
					        if(0 <= std::distance(rollback, this->iter_)) // rollback < iter
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this->line_number_ -= static_cast<std::size_t>(
 | 
				
			||||||
 | 
					                    std::count(rollback, this->iter_, '\n'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else // iter < rollback [[unlikely]]
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this->line_number_ += static_cast<std::size_t>(
 | 
				
			||||||
 | 
					                    std::count(this->iter_, rollback, '\n'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this->iter_ = rollback;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string str()  const override {return make_string(1, *this->iter());}
 | 
				
			||||||
 | 
					    std::string name() const override {return source_name_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string line_num() const override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::to_string(this->line_number_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string line() const override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return make_string(this->line_begin(), this->line_end());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const_iterator line_begin() const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using reverse_iterator = std::reverse_iterator<const_iterator>;
 | 
				
			||||||
 | 
					        return std::find(reverse_iterator(this->iter()),
 | 
				
			||||||
 | 
					                         reverse_iterator(this->begin()), '\n').base();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const_iterator line_end() const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::find(this->iter(), this->end(), '\n');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // location is always points a character. so the size is 1.
 | 
				
			||||||
 | 
					    std::size_t size() const noexcept override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return 1u;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::size_t before() const noexcept override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto sz = std::distance(this->line_begin(), this->iter());
 | 
				
			||||||
 | 
					        assert(sz >= 0);
 | 
				
			||||||
 | 
					        return static_cast<std::size_t>(sz);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::size_t after() const noexcept override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto sz = std::distance(this->iter(), this->line_end());
 | 
				
			||||||
 | 
					        assert(sz >= 0);
 | 
				
			||||||
 | 
					        return static_cast<std::size_t>(sz);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source_ptr const& source() const& noexcept {return source_;}
 | 
				
			||||||
 | 
					    source_ptr&&      source() &&     noexcept {return std::move(source_);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source_ptr     source_;
 | 
				
			||||||
 | 
					    std::size_t    line_number_;
 | 
				
			||||||
 | 
					    std::string    source_name_;
 | 
				
			||||||
 | 
					    const_iterator iter_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// region represents a range in a container, which contains a file content.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// it contains pointer to the file content and iterator that points the first
 | 
				
			||||||
 | 
					// and last location.
 | 
				
			||||||
 | 
					struct region final : public region_base
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using const_iterator = typename std::vector<char>::const_iterator;
 | 
				
			||||||
 | 
					    using source_ptr     = std::shared_ptr<const std::vector<char>>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // delete default constructor. source_ never be null.
 | 
				
			||||||
 | 
					    region() = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit region(const location& loc)
 | 
				
			||||||
 | 
					      : source_(loc.source()), source_name_(loc.name()),
 | 
				
			||||||
 | 
					        first_(loc.iter()), last_(loc.iter())
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    explicit region(location&& loc)
 | 
				
			||||||
 | 
					      : source_(loc.source()), source_name_(loc.name()),
 | 
				
			||||||
 | 
					        first_(loc.iter()), last_(loc.iter())
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    region(const location& loc, const_iterator f, const_iterator l)
 | 
				
			||||||
 | 
					      : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    region(location&& loc, const_iterator f, const_iterator l)
 | 
				
			||||||
 | 
					      : source_(loc.source()), source_name_(loc.name()), first_(f), last_(l)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    region(const region&) = default;
 | 
				
			||||||
 | 
					    region(region&&)      = default;
 | 
				
			||||||
 | 
					    region& operator=(const region&) = default;
 | 
				
			||||||
 | 
					    region& operator=(region&&)      = default;
 | 
				
			||||||
 | 
					    ~region() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    region& operator+=(const region& other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // different regions cannot be concatenated
 | 
				
			||||||
 | 
					        assert(this->source_ == other.source_ && this->last_ == other.first_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this->last_ = other.last_;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_ok() const noexcept override {return static_cast<bool>(source_);}
 | 
				
			||||||
 | 
					    char front() const noexcept override {return *first_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string str()  const override {return make_string(first_, last_);}
 | 
				
			||||||
 | 
					    std::string line() const override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->contain_newline())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return make_string(this->line_begin(),
 | 
				
			||||||
 | 
					                    std::find(this->line_begin(), this->last(), '\n'));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return make_string(this->line_begin(), this->line_end());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string line_num() const override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::to_string(1 + std::count(this->begin(), this->first(), '\n'));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::size_t size() const noexcept override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto sz = std::distance(first_, last_);
 | 
				
			||||||
 | 
					        assert(sz >= 0);
 | 
				
			||||||
 | 
					        return static_cast<std::size_t>(sz);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::size_t before() const noexcept override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto sz = std::distance(this->line_begin(), this->first());
 | 
				
			||||||
 | 
					        assert(sz >= 0);
 | 
				
			||||||
 | 
					        return static_cast<std::size_t>(sz);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::size_t after() const noexcept override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto sz = std::distance(this->last(), this->line_end());
 | 
				
			||||||
 | 
					        assert(sz >= 0);
 | 
				
			||||||
 | 
					        return static_cast<std::size_t>(sz);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool contain_newline() const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::find(this->first(), this->last(), '\n') != this->last();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const_iterator line_begin() const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        using reverse_iterator = std::reverse_iterator<const_iterator>;
 | 
				
			||||||
 | 
					        return std::find(reverse_iterator(this->first()),
 | 
				
			||||||
 | 
					                         reverse_iterator(this->begin()), '\n').base();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const_iterator line_end() const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::find(this->last(), this->end(), '\n');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const_iterator begin() const noexcept {return source_->cbegin();}
 | 
				
			||||||
 | 
					    const_iterator end()   const noexcept {return source_->cend();}
 | 
				
			||||||
 | 
					    const_iterator first() const noexcept {return first_;}
 | 
				
			||||||
 | 
					    const_iterator last()  const noexcept {return last_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source_ptr const& source() const& noexcept {return source_;}
 | 
				
			||||||
 | 
					    source_ptr&&      source() &&     noexcept {return std::move(source_);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string name() const override {return source_name_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<std::string> comments() const override
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // assuming the current region (`*this`) points a value.
 | 
				
			||||||
 | 
					        // ```toml
 | 
				
			||||||
 | 
					        // a = "value"
 | 
				
			||||||
 | 
					        //     ^^^^^^^- this region
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        using rev_iter = std::reverse_iterator<const_iterator>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::vector<std::string> com{};
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // find comments just before the current region.
 | 
				
			||||||
 | 
					            // ```toml
 | 
				
			||||||
 | 
					            // # this should be collected.
 | 
				
			||||||
 | 
					            // # this also.
 | 
				
			||||||
 | 
					            // a = value # not this.
 | 
				
			||||||
 | 
					            // ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // # this is a comment for `a`, not array elements.
 | 
				
			||||||
 | 
					            // a = [1, 2, 3, 4, 5]
 | 
				
			||||||
 | 
					            if(this->first() == std::find_if(this->line_begin(), this->first(),
 | 
				
			||||||
 | 
					                [](const char c) noexcept -> bool {return c == '[' || c == '{';}))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                auto iter = this->line_begin(); // points the first character
 | 
				
			||||||
 | 
					                while(iter != this->begin())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    iter = std::prev(iter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // range [line_start, iter) represents the previous line
 | 
				
			||||||
 | 
					                    const auto line_start   = std::find(
 | 
				
			||||||
 | 
					                            rev_iter(iter), rev_iter(this->begin()), '\n').base();
 | 
				
			||||||
 | 
					                    const auto comment_found = std::find(line_start, iter, '#');
 | 
				
			||||||
 | 
					                    if(comment_found == iter)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        break; // comment not found.
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // exclude the following case.
 | 
				
			||||||
 | 
					                    // > a = "foo" # comment // <-- this is not a comment for b but a.
 | 
				
			||||||
 | 
					                    // > b = "current value"
 | 
				
			||||||
 | 
					                    if(std::all_of(line_start, comment_found,
 | 
				
			||||||
 | 
					                            [](const char c) noexcept -> bool {
 | 
				
			||||||
 | 
					                                return c == ' ' || c == '\t';
 | 
				
			||||||
 | 
					                            }))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        // unwrap the first '#' by std::next.
 | 
				
			||||||
 | 
					                        auto s = make_string(std::next(comment_found), iter);
 | 
				
			||||||
 | 
					                        if(!s.empty() && s.back() == '\r') {s.pop_back();}
 | 
				
			||||||
 | 
					                        com.push_back(std::move(s));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    iter = line_start;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(com.size() > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::reverse(com.begin(), com.end());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // find comments just after the current region.
 | 
				
			||||||
 | 
					            // ```toml
 | 
				
			||||||
 | 
					            // # not this.
 | 
				
			||||||
 | 
					            // a = value # this one.
 | 
				
			||||||
 | 
					            // a = [ # not this (technically difficult)
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            // ] # and this.
 | 
				
			||||||
 | 
					            // ```
 | 
				
			||||||
 | 
					            // The reason why it's difficult is that it requires parsing in the
 | 
				
			||||||
 | 
					            // following case.
 | 
				
			||||||
 | 
					            // ```toml
 | 
				
			||||||
 | 
					            // a = [ 10 # this comment is for `10`. not for `a` but `a[0]`.
 | 
				
			||||||
 | 
					            // # ...
 | 
				
			||||||
 | 
					            // ] # this is apparently a comment for a.
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            // b = [
 | 
				
			||||||
 | 
					            // 3.14 ] # there is no way to add a comment to `3.14` currently.
 | 
				
			||||||
 | 
					            //
 | 
				
			||||||
 | 
					            // c = [
 | 
				
			||||||
 | 
					            //   3.14 # do this if you need a comment here.
 | 
				
			||||||
 | 
					            // ]
 | 
				
			||||||
 | 
					            // ```
 | 
				
			||||||
 | 
					            const auto comment_found =
 | 
				
			||||||
 | 
					                std::find(this->last(), this->line_end(), '#');
 | 
				
			||||||
 | 
					            if(comment_found != this->line_end()) // '#' found
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // table = {key = "value"} # what is this for?
 | 
				
			||||||
 | 
					                // the above comment is not for "value", but {key="value"}.
 | 
				
			||||||
 | 
					                if(comment_found == std::find_if(this->last(), comment_found,
 | 
				
			||||||
 | 
					                    [](const char c) noexcept -> bool {
 | 
				
			||||||
 | 
					                        return !(c == ' ' || c == '\t' || c == ',');
 | 
				
			||||||
 | 
					                    }))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // unwrap the first '#' by std::next.
 | 
				
			||||||
 | 
					                    auto s = make_string(std::next(comment_found), this->line_end());
 | 
				
			||||||
 | 
					                    if(!s.empty() && s.back() == '\r') {s.pop_back();}
 | 
				
			||||||
 | 
					                    com.push_back(std::move(s));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return com;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source_ptr     source_;
 | 
				
			||||||
 | 
					    std::string    source_name_;
 | 
				
			||||||
 | 
					    const_iterator first_, last_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_REGION_H
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,717 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_RESULT_HPP
 | 
				
			||||||
 | 
					#define TOML11_RESULT_HPP
 | 
				
			||||||
 | 
					#include "traits.hpp"
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <new>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct success
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = T;
 | 
				
			||||||
 | 
					    value_type value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit success(const value_type& v)
 | 
				
			||||||
 | 
					        noexcept(std::is_nothrow_copy_constructible<value_type>::value)
 | 
				
			||||||
 | 
					        : value(v)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    explicit success(value_type&& v)
 | 
				
			||||||
 | 
					        noexcept(std::is_nothrow_move_constructible<value_type>::value)
 | 
				
			||||||
 | 
					        : value(std::move(v))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    explicit success(U&& v): value(std::forward<U>(v)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    explicit success(const success<U>& v): value(v.value) {}
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    explicit success(success<U>&& v): value(std::move(v.value)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~success() = default;
 | 
				
			||||||
 | 
					    success(const success&) = default;
 | 
				
			||||||
 | 
					    success(success&&)      = default;
 | 
				
			||||||
 | 
					    success& operator=(const success&) = default;
 | 
				
			||||||
 | 
					    success& operator=(success&&)      = default;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct failure
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = T;
 | 
				
			||||||
 | 
					    value_type value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit failure(const value_type& v)
 | 
				
			||||||
 | 
					        noexcept(std::is_nothrow_copy_constructible<value_type>::value)
 | 
				
			||||||
 | 
					        : value(v)
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    explicit failure(value_type&& v)
 | 
				
			||||||
 | 
					        noexcept(std::is_nothrow_move_constructible<value_type>::value)
 | 
				
			||||||
 | 
					        : value(std::move(v))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    explicit failure(U&& v): value(std::forward<U>(v)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    explicit failure(const failure<U>& v): value(v.value) {}
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    explicit failure(failure<U>&& v): value(std::move(v.value)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~failure() = default;
 | 
				
			||||||
 | 
					    failure(const failure&) = default;
 | 
				
			||||||
 | 
					    failure(failure&&)      = default;
 | 
				
			||||||
 | 
					    failure& operator=(const failure&) = default;
 | 
				
			||||||
 | 
					    failure& operator=(failure&&)      = default;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					success<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
 | 
				
			||||||
 | 
					ok(T&& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return success<
 | 
				
			||||||
 | 
					        typename std::remove_cv<typename std::remove_reference<T>::type>::type
 | 
				
			||||||
 | 
					        >(std::forward<T>(v));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					failure<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
 | 
				
			||||||
 | 
					err(T&& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return failure<
 | 
				
			||||||
 | 
					        typename std::remove_cv<typename std::remove_reference<T>::type>::type
 | 
				
			||||||
 | 
					        >(std::forward<T>(v));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline success<std::string> ok(const char* literal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return success<std::string>(std::string(literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline failure<std::string> err(const char* literal)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return failure<std::string>(std::string(literal));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename E>
 | 
				
			||||||
 | 
					struct result
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = T;
 | 
				
			||||||
 | 
					    using error_type = E;
 | 
				
			||||||
 | 
					    using success_type = success<value_type>;
 | 
				
			||||||
 | 
					    using failure_type = failure<error_type>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result(const success_type& s): is_ok_(true)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(s);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result(const failure_type& f): is_ok_(false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result(success_type&& s): is_ok_(true)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result(failure_type&& f): is_ok_(false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result(const success<U>& s): is_ok_(true)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result(const failure<U>& f): is_ok_(false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result(success<U>&& s): is_ok_(true)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result(failure<U>&& f): is_ok_(false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result& operator=(const success_type& s)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = true;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(s);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result& operator=(const failure_type& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = false;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(f);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result& operator=(success_type&& s)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = true;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result& operator=(failure_type&& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = false;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result& operator=(const success<U>& s)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = true;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(s.value);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result& operator=(const failure<U>& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = false;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value);
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result& operator=(success<U>&& s)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = true;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U>
 | 
				
			||||||
 | 
					    result& operator=(failure<U>&& f)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        this->is_ok_ = false;
 | 
				
			||||||
 | 
					        auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value));
 | 
				
			||||||
 | 
					        assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					        (void)tmp;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~result() noexcept {this->cleanup();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result(const result& other): is_ok_(other.is_ok())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result(result&& other): is_ok_(other.is_ok())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U, typename F>
 | 
				
			||||||
 | 
					    result(const result<U, F>& other): is_ok_(other.is_ok())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U, typename F>
 | 
				
			||||||
 | 
					    result(result<U, F>&& other): is_ok_(other.is_ok())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result& operator=(const result& other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        is_ok_ = other.is_ok();
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result& operator=(result&& other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        is_ok_ = other.is_ok();
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename U, typename F>
 | 
				
			||||||
 | 
					    result& operator=(const result<U, F>& other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err());
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        is_ok_ = other.is_ok();
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U, typename F>
 | 
				
			||||||
 | 
					    result& operator=(result<U, F>&& other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->cleanup();
 | 
				
			||||||
 | 
					        if(other.is_ok())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->succ));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err()));
 | 
				
			||||||
 | 
					            assert(tmp == std::addressof(this->fail));
 | 
				
			||||||
 | 
					            (void)tmp;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        is_ok_ = other.is_ok();
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_ok()  const noexcept {return is_ok_;}
 | 
				
			||||||
 | 
					    bool is_err() const noexcept {return !is_ok_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator bool() const noexcept {return is_ok_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_type&       unwrap() &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_err())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw std::runtime_error("toml::result: bad unwrap: " +
 | 
				
			||||||
 | 
					                                     format_error(this->as_err()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this->succ.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    value_type const& unwrap() const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_err())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw std::runtime_error("toml::result: bad unwrap: " +
 | 
				
			||||||
 | 
					                                     format_error(this->as_err()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this->succ.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    value_type&&      unwrap() &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_err())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            throw std::runtime_error("toml::result: bad unwrap: " +
 | 
				
			||||||
 | 
					                                     format_error(this->as_err()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return std::move(this->succ.value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_type&       unwrap_or(value_type& opt) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_err()) {return opt;}
 | 
				
			||||||
 | 
					        return this->succ.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    value_type const& unwrap_or(value_type const& opt) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_err()) {return opt;}
 | 
				
			||||||
 | 
					        return this->succ.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    value_type        unwrap_or(value_type opt) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_err()) {return opt;}
 | 
				
			||||||
 | 
					        return this->succ.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    error_type&       unwrap_err() &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
 | 
				
			||||||
 | 
					        return this->fail.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    error_type const& unwrap_err() const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
 | 
				
			||||||
 | 
					        return this->fail.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    error_type&&      unwrap_err() &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");}
 | 
				
			||||||
 | 
					        return std::move(this->fail.value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_type&       as_ok() &      noexcept {return this->succ.value;}
 | 
				
			||||||
 | 
					    value_type const& as_ok() const& noexcept {return this->succ.value;}
 | 
				
			||||||
 | 
					    value_type&&      as_ok() &&     noexcept {return std::move(this->succ.value);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    error_type&       as_err() &      noexcept {return this->fail.value;}
 | 
				
			||||||
 | 
					    error_type const& as_err() const& noexcept {return this->fail.value;}
 | 
				
			||||||
 | 
					    error_type&&      as_err() &&     noexcept {return std::move(this->fail.value);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prerequisities
 | 
				
			||||||
 | 
					    // F: T -> U
 | 
				
			||||||
 | 
					    // retval: result<U, E>
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    result<detail::return_type_of_t<F, value_type&>, error_type>
 | 
				
			||||||
 | 
					    map(F&& f) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return ok(f(this->as_ok()));}
 | 
				
			||||||
 | 
					        return err(this->as_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    result<detail::return_type_of_t<F, value_type const&>, error_type>
 | 
				
			||||||
 | 
					    map(F&& f) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return ok(f(this->as_ok()));}
 | 
				
			||||||
 | 
					        return err(this->as_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    result<detail::return_type_of_t<F, value_type &&>, error_type>
 | 
				
			||||||
 | 
					    map(F&& f) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return ok(f(std::move(this->as_ok())));}
 | 
				
			||||||
 | 
					        return err(std::move(this->as_err()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prerequisities
 | 
				
			||||||
 | 
					    // F: E -> F
 | 
				
			||||||
 | 
					    // retval: result<T, F>
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    result<value_type, detail::return_type_of_t<F, error_type&>>
 | 
				
			||||||
 | 
					    map_err(F&& f) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return err(f(this->as_err()));}
 | 
				
			||||||
 | 
					        return ok(this->as_ok());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    result<value_type, detail::return_type_of_t<F, error_type const&>>
 | 
				
			||||||
 | 
					    map_err(F&& f) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return err(f(this->as_err()));}
 | 
				
			||||||
 | 
					        return ok(this->as_ok());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    result<value_type, detail::return_type_of_t<F, error_type&&>>
 | 
				
			||||||
 | 
					    map_err(F&& f) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return err(f(std::move(this->as_err())));}
 | 
				
			||||||
 | 
					        return ok(std::move(this->as_ok()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prerequisities
 | 
				
			||||||
 | 
					    // F: T -> U
 | 
				
			||||||
 | 
					    // retval: U
 | 
				
			||||||
 | 
					    template<typename F, typename U>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, value_type&>
 | 
				
			||||||
 | 
					    map_or_else(F&& f, U&& opt) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return std::forward<U>(opt);}
 | 
				
			||||||
 | 
					        return f(this->as_ok());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F, typename U>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, value_type const&>
 | 
				
			||||||
 | 
					    map_or_else(F&& f, U&& opt) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return std::forward<U>(opt);}
 | 
				
			||||||
 | 
					        return f(this->as_ok());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F, typename U>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, value_type&&>
 | 
				
			||||||
 | 
					    map_or_else(F&& f, U&& opt) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return std::forward<U>(opt);}
 | 
				
			||||||
 | 
					        return f(std::move(this->as_ok()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prerequisities
 | 
				
			||||||
 | 
					    // F: E -> U
 | 
				
			||||||
 | 
					    // retval: U
 | 
				
			||||||
 | 
					    template<typename F, typename U>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, error_type&>
 | 
				
			||||||
 | 
					    map_err_or_else(F&& f, U&& opt) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return std::forward<U>(opt);}
 | 
				
			||||||
 | 
					        return f(this->as_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F, typename U>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, error_type const&>
 | 
				
			||||||
 | 
					    map_err_or_else(F&& f, U&& opt) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return std::forward<U>(opt);}
 | 
				
			||||||
 | 
					        return f(this->as_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F, typename U>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, error_type&&>
 | 
				
			||||||
 | 
					    map_err_or_else(F&& f, U&& opt) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return std::forward<U>(opt);}
 | 
				
			||||||
 | 
					        return f(std::move(this->as_err()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prerequisities:
 | 
				
			||||||
 | 
					    // F: func T -> U
 | 
				
			||||||
 | 
					    // toml::err(error_type) should be convertible to U.
 | 
				
			||||||
 | 
					    // normally, type U is another result<S, F> and E is convertible to F
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, value_type&>
 | 
				
			||||||
 | 
					    and_then(F&& f) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return f(this->as_ok());}
 | 
				
			||||||
 | 
					        return err(this->as_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, value_type const&>
 | 
				
			||||||
 | 
					    and_then(F&& f) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return f(this->as_ok());}
 | 
				
			||||||
 | 
					        return err(this->as_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, value_type&&>
 | 
				
			||||||
 | 
					    and_then(F&& f) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok()){return f(std::move(this->as_ok()));}
 | 
				
			||||||
 | 
					        return err(std::move(this->as_err()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // prerequisities:
 | 
				
			||||||
 | 
					    // F: func E -> U
 | 
				
			||||||
 | 
					    // toml::ok(value_type) should be convertible to U.
 | 
				
			||||||
 | 
					    // normally, type U is another result<S, F> and T is convertible to S
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, error_type&>
 | 
				
			||||||
 | 
					    or_else(F&& f) &
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return f(this->as_err());}
 | 
				
			||||||
 | 
					        return ok(this->as_ok());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, error_type const&>
 | 
				
			||||||
 | 
					    or_else(F&& f) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return f(this->as_err());}
 | 
				
			||||||
 | 
					        return ok(this->as_ok());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename F>
 | 
				
			||||||
 | 
					    detail::return_type_of_t<F, error_type&&>
 | 
				
			||||||
 | 
					    or_else(F&& f) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_err()){return f(std::move(this->as_err()));}
 | 
				
			||||||
 | 
					        return ok(std::move(this->as_ok()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // if *this is error, returns *this. otherwise, returns other.
 | 
				
			||||||
 | 
					    result and_other(const result& other) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return this->is_err() ? *this : other;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result and_other(result&& other) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return this->is_err() ? std::move(*this) : std::move(other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // if *this is okay, returns *this. otherwise, returns other.
 | 
				
			||||||
 | 
					    result or_other(const result& other) const&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return this->is_ok() ? *this : other;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    result or_other(result&& other) &&
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return this->is_ok() ? std::move(*this) : std::move(other);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void swap(result<T, E>& other)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        result<T, E> tmp(std::move(*this));
 | 
				
			||||||
 | 
					        *this = std::move(other);
 | 
				
			||||||
 | 
					        other = std::move(tmp);
 | 
				
			||||||
 | 
					        return ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static std::string format_error(std::exception const& excpt)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::string(excpt.what());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    template<typename U, typename std::enable_if<!std::is_base_of<
 | 
				
			||||||
 | 
					        std::exception, U>::value, std::nullptr_t>::type = nullptr>
 | 
				
			||||||
 | 
					    static std::string format_error(U const& others)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss; oss << others;
 | 
				
			||||||
 | 
					        return oss.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void cleanup() noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(this->is_ok_) {this->succ.~success_type();}
 | 
				
			||||||
 | 
					        else             {this->fail.~failure_type();}
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool      is_ok_;
 | 
				
			||||||
 | 
					    union
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        success_type succ;
 | 
				
			||||||
 | 
					        failure_type fail;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename E>
 | 
				
			||||||
 | 
					void swap(result<T, E>& lhs, result<T, E>& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    lhs.swap(rhs);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// this might be confusing because it eagerly evaluated, while in the other
 | 
				
			||||||
 | 
					// cases operator && and || are short-circuited.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// template<typename T, typename E>
 | 
				
			||||||
 | 
					// inline result<T, E>
 | 
				
			||||||
 | 
					// operator&&(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
 | 
				
			||||||
 | 
					// {
 | 
				
			||||||
 | 
					//     return lhs.is_ok() ? rhs : lhs;
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// template<typename T, typename E>
 | 
				
			||||||
 | 
					// inline result<T, E>
 | 
				
			||||||
 | 
					// operator||(const result<T, E>& lhs, const result<T, E>& rhs) noexcept
 | 
				
			||||||
 | 
					// {
 | 
				
			||||||
 | 
					//     return lhs.is_ok() ? lhs : rhs;
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// re-use result<T, E> as a optional<T> with none_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					struct none_t {};
 | 
				
			||||||
 | 
					inline bool operator==(const none_t&, const none_t&) noexcept {return true;}
 | 
				
			||||||
 | 
					inline bool operator!=(const none_t&, const none_t&) noexcept {return false;}
 | 
				
			||||||
 | 
					inline bool operator< (const none_t&, const none_t&) noexcept {return false;}
 | 
				
			||||||
 | 
					inline bool operator<=(const none_t&, const none_t&) noexcept {return true;}
 | 
				
			||||||
 | 
					inline bool operator> (const none_t&, const none_t&) noexcept {return false;}
 | 
				
			||||||
 | 
					inline bool operator>=(const none_t&, const none_t&) noexcept {return true;}
 | 
				
			||||||
 | 
					template<typename charT, typename traitsT>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traitsT>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    os << "none";
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};}
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml11
 | 
				
			||||||
 | 
					#endif// TOML11_RESULT_H
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,994 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2019.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_SERIALIZER_HPP
 | 
				
			||||||
 | 
					#define TOML11_SERIALIZER_HPP
 | 
				
			||||||
 | 
					#include <cmath>
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					#include <locale.h>
 | 
				
			||||||
 | 
					#elif defined(__APPLE__) || defined(__FreeBSD__)
 | 
				
			||||||
 | 
					#include <xlocale.h>
 | 
				
			||||||
 | 
					#elif defined(__linux__)
 | 
				
			||||||
 | 
					#include <locale.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lexer.hpp"
 | 
				
			||||||
 | 
					#include "value.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This function serialize a key. It checks a string is a bare key and
 | 
				
			||||||
 | 
					// escapes special characters if the string is not compatible to a bare key.
 | 
				
			||||||
 | 
					// ```cpp
 | 
				
			||||||
 | 
					// std::string k("non.bare.key"); // the key itself includes `.`s.
 | 
				
			||||||
 | 
					// std::string formatted = toml::format_key(k);
 | 
				
			||||||
 | 
					// assert(formatted == "\"non.bare.key\"");
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This function is exposed to make it easy to write a user-defined serializer.
 | 
				
			||||||
 | 
					// Since toml restricts characters available in a bare key, generally a string
 | 
				
			||||||
 | 
					// should be escaped. But checking whether a string needs to be surrounded by
 | 
				
			||||||
 | 
					// a `"` and escaping some special character is boring.
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_string<charT, traits, Alloc>
 | 
				
			||||||
 | 
					format_key(const std::basic_string<charT, traits, Alloc>& k)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(k.empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::string("\"\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check the key can be a bare (unquoted) key
 | 
				
			||||||
 | 
					    detail::location loc(k, std::vector<char>(k.begin(), k.end()));
 | 
				
			||||||
 | 
					    detail::lex_unquoted_key::invoke(loc);
 | 
				
			||||||
 | 
					    if(loc.iter() == loc.end())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return k; // all the tokens are consumed. the key is unquoted-key.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //if it includes special characters, then format it in a "quoted" key.
 | 
				
			||||||
 | 
					    std::basic_string<charT, traits, Alloc> serialized("\"");
 | 
				
			||||||
 | 
					    for(const char c : k)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        switch(c)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            case '\\': {serialized += "\\\\"; break;}
 | 
				
			||||||
 | 
					            case '\"': {serialized += "\\\""; break;}
 | 
				
			||||||
 | 
					            case '\b': {serialized += "\\b";  break;}
 | 
				
			||||||
 | 
					            case '\t': {serialized += "\\t";  break;}
 | 
				
			||||||
 | 
					            case '\f': {serialized += "\\f";  break;}
 | 
				
			||||||
 | 
					            case '\n': {serialized += "\\n";  break;}
 | 
				
			||||||
 | 
					            case '\r': {serialized += "\\r";  break;}
 | 
				
			||||||
 | 
					            default: {
 | 
				
			||||||
 | 
					                if (c >= 0x00 && c < 0x20)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    std::array<char, 7> buf;
 | 
				
			||||||
 | 
					                    std::snprintf(buf.data(), buf.size(), "\\u00%02x", static_cast<int>(c));
 | 
				
			||||||
 | 
					                    serialized += buf.data();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    serialized += c;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    serialized += "\"";
 | 
				
			||||||
 | 
					    return serialized;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename Alloc>
 | 
				
			||||||
 | 
					std::basic_string<charT, traits, Alloc>
 | 
				
			||||||
 | 
					format_keys(const std::vector<std::basic_string<charT, traits, Alloc>>& keys)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(keys.empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return std::string("\"\"");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::basic_string<charT, traits, Alloc> serialized;
 | 
				
			||||||
 | 
					    for(const auto& ky : keys)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        serialized += format_key(ky);
 | 
				
			||||||
 | 
					        serialized += charT('.');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    serialized.pop_back(); // remove the last dot '.'
 | 
				
			||||||
 | 
					    return serialized;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Value>
 | 
				
			||||||
 | 
					struct serializer
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static_assert(detail::is_basic_value<Value>::value,
 | 
				
			||||||
 | 
					                  "toml::serializer is for toml::value and its variants, "
 | 
				
			||||||
 | 
					                  "toml::basic_value<...>.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using value_type           = Value;
 | 
				
			||||||
 | 
					    using key_type             = typename value_type::key_type            ;
 | 
				
			||||||
 | 
					    using comment_type         = typename value_type::comment_type        ;
 | 
				
			||||||
 | 
					    using boolean_type         = typename value_type::boolean_type        ;
 | 
				
			||||||
 | 
					    using integer_type         = typename value_type::integer_type        ;
 | 
				
			||||||
 | 
					    using floating_type        = typename value_type::floating_type       ;
 | 
				
			||||||
 | 
					    using string_type          = typename value_type::string_type         ;
 | 
				
			||||||
 | 
					    using local_time_type      = typename value_type::local_time_type     ;
 | 
				
			||||||
 | 
					    using local_date_type      = typename value_type::local_date_type     ;
 | 
				
			||||||
 | 
					    using local_datetime_type  = typename value_type::local_datetime_type ;
 | 
				
			||||||
 | 
					    using offset_datetime_type = typename value_type::offset_datetime_type;
 | 
				
			||||||
 | 
					    using array_type           = typename value_type::array_type          ;
 | 
				
			||||||
 | 
					    using table_type           = typename value_type::table_type          ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    serializer(const std::size_t w              = 80u,
 | 
				
			||||||
 | 
					               const int         float_prec     = std::numeric_limits<toml::floating>::max_digits10,
 | 
				
			||||||
 | 
					               const bool        can_be_inlined = false,
 | 
				
			||||||
 | 
					               const bool        no_comment     = false,
 | 
				
			||||||
 | 
					               std::vector<toml::key> ks        = {},
 | 
				
			||||||
 | 
					               const bool     value_has_comment = false)
 | 
				
			||||||
 | 
					        : can_be_inlined_(can_be_inlined), no_comment_(no_comment),
 | 
				
			||||||
 | 
					          value_has_comment_(value_has_comment && !no_comment),
 | 
				
			||||||
 | 
					          float_prec_(float_prec), width_(w), keys_(std::move(ks))
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    ~serializer() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string operator()(const boolean_type& b) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return b ? "true" : "false";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string operator()(const integer_type i) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					        _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
 | 
				
			||||||
 | 
					        const std::string original_locale(setlocale(LC_NUMERIC, nullptr));
 | 
				
			||||||
 | 
					        setlocale(LC_NUMERIC, "C");
 | 
				
			||||||
 | 
					#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 | 
				
			||||||
 | 
					        const auto c_locale = newlocale(LC_NUMERIC_MASK, "C", locale_t(0));
 | 
				
			||||||
 | 
					        locale_t original_locale(0);
 | 
				
			||||||
 | 
					        if(c_locale != locale_t(0))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            original_locale = uselocale(c_locale);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto str = std::to_string(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					        setlocale(LC_NUMERIC, original_locale.c_str());
 | 
				
			||||||
 | 
					        _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
 | 
				
			||||||
 | 
					#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 | 
				
			||||||
 | 
					        if(original_locale != locale_t(0))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            uselocale(original_locale);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        return str;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string operator()(const floating_type f) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(std::isnan(f))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(std::signbit(f))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return std::string("-nan");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return std::string("nan");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if(!std::isfinite(f))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(std::signbit(f))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return std::string("-inf");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return std::string("inf");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // set locale to "C".
 | 
				
			||||||
 | 
					        // To make it thread-local, we use OS-specific features.
 | 
				
			||||||
 | 
					        // If we set process-global locale, it can break other thread that also
 | 
				
			||||||
 | 
					        // outputs something simultaneously.
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					        _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
 | 
				
			||||||
 | 
					        const std::string original_locale(setlocale(LC_NUMERIC, nullptr));
 | 
				
			||||||
 | 
					        setlocale(LC_NUMERIC, "C");
 | 
				
			||||||
 | 
					#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 | 
				
			||||||
 | 
					        const auto c_locale = newlocale(LC_NUMERIC_MASK, "C", locale_t(0));
 | 
				
			||||||
 | 
					        locale_t original_locale(0);
 | 
				
			||||||
 | 
					        if(c_locale != locale_t(0))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            original_locale = uselocale(c_locale);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto fmt = "%.*g";
 | 
				
			||||||
 | 
					        const auto bsz = std::snprintf(nullptr, 0, fmt, this->float_prec_, f);
 | 
				
			||||||
 | 
					        // +1 for null character(\0)
 | 
				
			||||||
 | 
					        std::vector<char> buf(static_cast<std::size_t>(bsz + 1), '\0');
 | 
				
			||||||
 | 
					        std::snprintf(buf.data(), buf.size(), fmt, this->float_prec_, f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // restore the original locale
 | 
				
			||||||
 | 
					#if defined(_WIN32)
 | 
				
			||||||
 | 
					        setlocale(LC_NUMERIC, original_locale.c_str());
 | 
				
			||||||
 | 
					        _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
 | 
				
			||||||
 | 
					#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 | 
				
			||||||
 | 
					        if(original_locale != locale_t(0))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            uselocale(original_locale);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string token(buf.begin(), std::prev(buf.end()));
 | 
				
			||||||
 | 
					        if(!token.empty() && token.back() == '.') // 1. => 1.0
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            token += '0';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto e = std::find_if(
 | 
				
			||||||
 | 
					            token.cbegin(), token.cend(), [](const char c) noexcept -> bool {
 | 
				
			||||||
 | 
					                return c == 'e' || c == 'E';
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        const auto has_exponent = (token.cend() != e);
 | 
				
			||||||
 | 
					        const auto has_fraction = (token.cend() != std::find(
 | 
				
			||||||
 | 
					            token.cbegin(), token.cend(), '.'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!has_exponent && !has_fraction)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // the resulting value does not have any float specific part!
 | 
				
			||||||
 | 
					            token += ".0";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string operator()(const string_type& s) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(s.kind == string_t::basic)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if((std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
 | 
				
			||||||
 | 
					                std::find(s.str.cbegin(), s.str.cend(), '\"') != s.str.cend()) &&
 | 
				
			||||||
 | 
					               this->width_ != (std::numeric_limits<std::size_t>::max)())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // if linefeed or double-quote is contained,
 | 
				
			||||||
 | 
					                // make it multiline basic string.
 | 
				
			||||||
 | 
					                const auto escaped = this->escape_ml_basic_string(s.str);
 | 
				
			||||||
 | 
					                std::string open("\"\"\"");
 | 
				
			||||||
 | 
					                std::string close("\"\"\"");
 | 
				
			||||||
 | 
					                if(escaped.find('\n') != std::string::npos ||
 | 
				
			||||||
 | 
					                   this->width_ < escaped.size() + 6)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // if the string body contains newline or is enough long,
 | 
				
			||||||
 | 
					                    // add newlines after and before delimiters.
 | 
				
			||||||
 | 
					                    open += "\n";
 | 
				
			||||||
 | 
					                    close = std::string("\\\n") + close;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return open + escaped + close;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // no linefeed. try to make it oneline-string.
 | 
				
			||||||
 | 
					            std::string oneline = this->escape_basic_string(s.str);
 | 
				
			||||||
 | 
					            if(oneline.size() + 2 < width_ || width_ < 2)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const std::string quote("\"");
 | 
				
			||||||
 | 
					                return quote + oneline + quote;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // the line is too long compared to the specified width.
 | 
				
			||||||
 | 
					            // split it into multiple lines.
 | 
				
			||||||
 | 
					            std::string token("\"\"\"\n");
 | 
				
			||||||
 | 
					            while(!oneline.empty())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if(oneline.size() < width_)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    token += oneline;
 | 
				
			||||||
 | 
					                    oneline.clear();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else if(oneline.at(width_-2) == '\\')
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    token += oneline.substr(0, width_-2);
 | 
				
			||||||
 | 
					                    token += "\\\n";
 | 
				
			||||||
 | 
					                    oneline.erase(0, width_-2);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    token += oneline.substr(0, width_-1);
 | 
				
			||||||
 | 
					                    token += "\\\n";
 | 
				
			||||||
 | 
					                    oneline.erase(0, width_-1);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return token + std::string("\\\n\"\"\"");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else // the string `s` is literal-string.
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
 | 
				
			||||||
 | 
					               std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::string open("'''");
 | 
				
			||||||
 | 
					                if(this->width_ + 6 < s.str.size())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    open += '\n'; // the first newline is ignored by TOML spec
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                const std::string close("'''");
 | 
				
			||||||
 | 
					                return open + s.str + close;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                const std::string quote("'");
 | 
				
			||||||
 | 
					                return quote + s.str + quote;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string operator()(const local_date_type& d) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << d;
 | 
				
			||||||
 | 
					        return oss.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string operator()(const local_time_type& t) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << t;
 | 
				
			||||||
 | 
					        return oss.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string operator()(const local_datetime_type& dt) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << dt;
 | 
				
			||||||
 | 
					        return oss.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    std::string operator()(const offset_datetime_type& odt) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        oss << odt;
 | 
				
			||||||
 | 
					        return oss.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string operator()(const array_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(v.empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return std::string("[]");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(this->is_array_of_tables(v))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return make_array_of_tables(v);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // not an array of tables. normal array.
 | 
				
			||||||
 | 
					        // first, try to make it inline if none of the elements have a comment.
 | 
				
			||||||
 | 
					        if( ! this->has_comment_inside(v))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            const auto inl = this->make_inline_array(v);
 | 
				
			||||||
 | 
					            if(inl.size() < this->width_ &&
 | 
				
			||||||
 | 
					               std::find(inl.cbegin(), inl.cend(), '\n') == inl.cend())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return inl;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if the length exceeds this->width_, print multiline array.
 | 
				
			||||||
 | 
					        // key = [
 | 
				
			||||||
 | 
					        //   # ...
 | 
				
			||||||
 | 
					        //   42,
 | 
				
			||||||
 | 
					        //   ...
 | 
				
			||||||
 | 
					        // ]
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        std::string current_line;
 | 
				
			||||||
 | 
					        token += "[\n";
 | 
				
			||||||
 | 
					        for(const auto& item : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if( ! item.comments().empty() && !no_comment_)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // if comment exists, the element must be the only element in the line.
 | 
				
			||||||
 | 
					                // e.g. the following is not allowed.
 | 
				
			||||||
 | 
					                // ```toml
 | 
				
			||||||
 | 
					                // array = [
 | 
				
			||||||
 | 
					                // # comment for what?
 | 
				
			||||||
 | 
					                // 1, 2, 3, 4, 5
 | 
				
			||||||
 | 
					                // ]
 | 
				
			||||||
 | 
					                // ```
 | 
				
			||||||
 | 
					                if(!current_line.empty())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if(current_line.back() != '\n')
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        current_line += '\n';
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    token += current_line;
 | 
				
			||||||
 | 
					                    current_line.clear();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                for(const auto& c : item.comments())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    token += '#';
 | 
				
			||||||
 | 
					                    token += c;
 | 
				
			||||||
 | 
					                    token += '\n';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                token += toml::visit(*this, item);
 | 
				
			||||||
 | 
					                if(!token.empty() && token.back() == '\n') {token.pop_back();}
 | 
				
			||||||
 | 
					                token += ",\n";
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            std::string next_elem;
 | 
				
			||||||
 | 
					            if(item.is_table())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                serializer ser(*this);
 | 
				
			||||||
 | 
					                ser.can_be_inlined_ = true;
 | 
				
			||||||
 | 
					                ser.width_ = (std::numeric_limits<std::size_t>::max)();
 | 
				
			||||||
 | 
					                next_elem += toml::visit(ser, item);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                next_elem += toml::visit(*this, item);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // comma before newline.
 | 
				
			||||||
 | 
					            if(!next_elem.empty() && next_elem.back() == '\n') {next_elem.pop_back();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // if current line does not exceeds the width limit, continue.
 | 
				
			||||||
 | 
					            if(current_line.size() + next_elem.size() + 1 < this->width_)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                current_line += next_elem;
 | 
				
			||||||
 | 
					                current_line += ',';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if(current_line.empty())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // if current line was empty, force put the next_elem because
 | 
				
			||||||
 | 
					                // next_elem is not splittable
 | 
				
			||||||
 | 
					                token += next_elem;
 | 
				
			||||||
 | 
					                token += ",\n";
 | 
				
			||||||
 | 
					                // current_line is kept empty
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else // reset current_line
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                assert(current_line.back() == ',');
 | 
				
			||||||
 | 
					                token += current_line;
 | 
				
			||||||
 | 
					                token += '\n';
 | 
				
			||||||
 | 
					                current_line = next_elem;
 | 
				
			||||||
 | 
					                current_line += ',';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(!current_line.empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(!current_line.empty() && current_line.back() != '\n')
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                current_line += '\n';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            token += current_line;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        token += "]\n";
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // templatize for any table-like container
 | 
				
			||||||
 | 
					    std::string operator()(const table_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // if an element has a comment, then it can't be inlined.
 | 
				
			||||||
 | 
					        // table = {# how can we write a comment for this? key = "value"}
 | 
				
			||||||
 | 
					        if(this->can_be_inlined_ && !(this->has_comment_inside(v)))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::string token;
 | 
				
			||||||
 | 
					            if(!this->keys_.empty())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                token += format_key(this->keys_.back());
 | 
				
			||||||
 | 
					                token += " = ";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            token += this->make_inline_table(v);
 | 
				
			||||||
 | 
					            if(token.size() < this->width_ &&
 | 
				
			||||||
 | 
					               token.end() == std::find(token.begin(), token.end(), '\n'))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return token;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        if(!keys_.empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            token += '[';
 | 
				
			||||||
 | 
					            token += format_keys(keys_);
 | 
				
			||||||
 | 
					            token += "]\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        token += this->make_multiline_table(v);
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string escape_basic_string(const std::string& s) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //XXX assuming `s` is a valid utf-8 sequence.
 | 
				
			||||||
 | 
					        std::string retval;
 | 
				
			||||||
 | 
					        for(const char c : s)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch(c)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case '\\': {retval += "\\\\"; break;}
 | 
				
			||||||
 | 
					                case '\"': {retval += "\\\""; break;}
 | 
				
			||||||
 | 
					                case '\b': {retval += "\\b";  break;}
 | 
				
			||||||
 | 
					                case '\t': {retval += "\\t";  break;}
 | 
				
			||||||
 | 
					                case '\f': {retval += "\\f";  break;}
 | 
				
			||||||
 | 
					                case '\n': {retval += "\\n";  break;}
 | 
				
			||||||
 | 
					                case '\r': {retval += "\\r";  break;}
 | 
				
			||||||
 | 
					                default  :
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retval += "\\u00";
 | 
				
			||||||
 | 
					                        retval += char(48 + (c / 16));
 | 
				
			||||||
 | 
					                        retval += char((c % 16 < 10 ? 48 : 55) + (c % 16));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retval += c;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return retval;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string escape_ml_basic_string(const std::string& s) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string retval;
 | 
				
			||||||
 | 
					        for(auto i=s.cbegin(), e=s.cend(); i!=e; ++i)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch(*i)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case '\\': {retval += "\\\\"; break;}
 | 
				
			||||||
 | 
					                // One or two consecutive "s are allowed.
 | 
				
			||||||
 | 
					                // Later we will check there are no three consecutive "s.
 | 
				
			||||||
 | 
					                //   case '\"': {retval += "\\\""; break;}
 | 
				
			||||||
 | 
					                case '\b': {retval += "\\b";  break;}
 | 
				
			||||||
 | 
					                case '\t': {retval += "\\t";  break;}
 | 
				
			||||||
 | 
					                case '\f': {retval += "\\f";  break;}
 | 
				
			||||||
 | 
					                case '\n': {retval += "\n";   break;}
 | 
				
			||||||
 | 
					                case '\r':
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if(std::next(i) != e && *std::next(i) == '\n')
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retval += "\r\n";
 | 
				
			||||||
 | 
					                        ++i;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retval += "\\r";
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                default  :
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    const auto c = *i;
 | 
				
			||||||
 | 
					                    if((0x00 <= c && c <= 0x08) || (0x0A <= c && c <= 0x1F) || c == 0x7F)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retval += "\\u00";
 | 
				
			||||||
 | 
					                        retval += char(48 + (c / 16));
 | 
				
			||||||
 | 
					                        retval += char((c % 16 < 10 ? 48 : 55) + (c % 16));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        retval += c;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Only 1 or 2 consecutive `"`s are allowed in multiline basic string.
 | 
				
			||||||
 | 
					        // 3 consecutive `"`s are considered as a closing delimiter.
 | 
				
			||||||
 | 
					        // We need to check if there are 3 or more consecutive `"`s and insert
 | 
				
			||||||
 | 
					        // backslash to break them down into several short `"`s like the `str6`
 | 
				
			||||||
 | 
					        // in the following example.
 | 
				
			||||||
 | 
					        // ```toml
 | 
				
			||||||
 | 
					        // str4 = """Here are two quotation marks: "". Simple enough."""
 | 
				
			||||||
 | 
					        // # str5 = """Here are three quotation marks: """."""  # INVALID
 | 
				
			||||||
 | 
					        // str5 = """Here are three quotation marks: ""\"."""
 | 
				
			||||||
 | 
					        // str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        auto found_3_quotes = retval.find("\"\"\"");
 | 
				
			||||||
 | 
					        while(found_3_quotes != std::string::npos)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            retval.replace(found_3_quotes, 3, "\"\"\\\"");
 | 
				
			||||||
 | 
					            found_3_quotes = retval.find("\"\"\"");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return retval;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // if an element of a table or an array has a comment, it cannot be inlined.
 | 
				
			||||||
 | 
					    bool has_comment_inside(const array_type& a) const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // if no_comment is set, comments would not be written.
 | 
				
			||||||
 | 
					        if(this->no_comment_) {return false;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(const auto& v : a)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(!v.comments().empty()) {return true;}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bool has_comment_inside(const table_type& t) const noexcept
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // if no_comment is set, comments would not be written.
 | 
				
			||||||
 | 
					        if(this->no_comment_) {return false;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(const auto& kv : t)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(!kv.second.comments().empty()) {return true;}
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string make_inline_array(const array_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        assert(!has_comment_inside(v));
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        token += '[';
 | 
				
			||||||
 | 
					        bool is_first = true;
 | 
				
			||||||
 | 
					        for(const auto& item : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(is_first) {is_first = false;} else {token += ',';}
 | 
				
			||||||
 | 
					            token += visit(serializer(
 | 
				
			||||||
 | 
					                (std::numeric_limits<std::size_t>::max)(), this->float_prec_,
 | 
				
			||||||
 | 
					                /* inlined */ true, /*no comment*/ false, /*keys*/ {},
 | 
				
			||||||
 | 
					                /*has_comment*/ !item.comments().empty()), item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        token += ']';
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string make_inline_table(const table_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        assert(!has_comment_inside(v));
 | 
				
			||||||
 | 
					        assert(this->can_be_inlined_);
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        token += '{';
 | 
				
			||||||
 | 
					        bool is_first = true;
 | 
				
			||||||
 | 
					        for(const auto& kv : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // in inline tables, trailing comma is not allowed (toml-lang #569).
 | 
				
			||||||
 | 
					            if(is_first) {is_first = false;} else {token += ',';}
 | 
				
			||||||
 | 
					            token += format_key(kv.first);
 | 
				
			||||||
 | 
					            token += '=';
 | 
				
			||||||
 | 
					            token += visit(serializer(
 | 
				
			||||||
 | 
					                (std::numeric_limits<std::size_t>::max)(), this->float_prec_,
 | 
				
			||||||
 | 
					                /* inlined */ true, /*no comment*/ false, /*keys*/ {},
 | 
				
			||||||
 | 
					                /*has_comment*/ !kv.second.comments().empty()), kv.second);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        token += '}';
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string make_multiline_table(const table_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // print non-table elements first.
 | 
				
			||||||
 | 
					        // ```toml
 | 
				
			||||||
 | 
					        // [foo]         # a table we're writing now here
 | 
				
			||||||
 | 
					        // key = "value" # <- non-table element, "key"
 | 
				
			||||||
 | 
					        // # ...
 | 
				
			||||||
 | 
					        // [foo.bar] # <- table element, "bar"
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        // because after printing [foo.bar], the remaining non-table values will
 | 
				
			||||||
 | 
					        // be assigned into [foo.bar], not [foo]. Those values should be printed
 | 
				
			||||||
 | 
					        // earlier.
 | 
				
			||||||
 | 
					        for(const auto& kv : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(kv.second.is_table() || is_array_of_tables(kv.second))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            token += write_comments(kv.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const auto key_and_sep    = format_key(kv.first) + " = ";
 | 
				
			||||||
 | 
					            const auto residual_width = (this->width_ > key_and_sep.size()) ?
 | 
				
			||||||
 | 
					                                        this->width_ - key_and_sep.size() : 0;
 | 
				
			||||||
 | 
					            token += key_and_sep;
 | 
				
			||||||
 | 
					            token += visit(serializer(residual_width, this->float_prec_,
 | 
				
			||||||
 | 
					                /*can be inlined*/ true, /*no comment*/ false, /*keys*/ {},
 | 
				
			||||||
 | 
					                /*has_comment*/ !kv.second.comments().empty()), kv.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(token.back() != '\n')
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                token += '\n';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // normal tables / array of tables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // after multiline table appeared, the other tables cannot be inline
 | 
				
			||||||
 | 
					        // because the table would be assigned into the table.
 | 
				
			||||||
 | 
					        // [foo]
 | 
				
			||||||
 | 
					        // ...
 | 
				
			||||||
 | 
					        // bar = {...} # <- bar will be a member of [foo].
 | 
				
			||||||
 | 
					        bool multiline_table_printed = false;
 | 
				
			||||||
 | 
					        for(const auto& kv : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(!kv.second.is_table() && !is_array_of_tables(kv.second))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                continue; // other stuff are already serialized. skip them.
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::vector<toml::key> ks(this->keys_);
 | 
				
			||||||
 | 
					            ks.push_back(kv.first);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            auto tmp = visit(serializer(this->width_, this->float_prec_,
 | 
				
			||||||
 | 
					                !multiline_table_printed, this->no_comment_, ks,
 | 
				
			||||||
 | 
					                /*has_comment*/ !kv.second.comments().empty()), kv.second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // If it is the first time to print a multi-line table, it would be
 | 
				
			||||||
 | 
					            // helpful to separate normal key-value pair and subtables by a
 | 
				
			||||||
 | 
					            // newline.
 | 
				
			||||||
 | 
					            // (this checks if the current key-value pair contains newlines.
 | 
				
			||||||
 | 
					            //  but it is not perfect because multi-line string can also contain
 | 
				
			||||||
 | 
					            //  a newline. in such a case, an empty line will be written) TODO
 | 
				
			||||||
 | 
					            if((!multiline_table_printed) &&
 | 
				
			||||||
 | 
					               std::find(tmp.cbegin(), tmp.cend(), '\n') != tmp.cend())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                multiline_table_printed = true;
 | 
				
			||||||
 | 
					                token += '\n'; // separate key-value pairs and subtables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                token += write_comments(kv.second);
 | 
				
			||||||
 | 
					                token += tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // care about recursive tables (all tables in each level prints
 | 
				
			||||||
 | 
					                // newline and there will be a full of newlines)
 | 
				
			||||||
 | 
					                if(tmp.substr(tmp.size() - 2, 2) != "\n\n" &&
 | 
				
			||||||
 | 
					                   tmp.substr(tmp.size() - 4, 4) != "\r\n\r\n" )
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    token += '\n';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                token += write_comments(kv.second);
 | 
				
			||||||
 | 
					                token += tmp;
 | 
				
			||||||
 | 
					                token += '\n';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string make_array_of_tables(const array_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // if it's not inlined, we need to add `[[table.key]]`.
 | 
				
			||||||
 | 
					        // but if it can be inlined, we can format it as the following.
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        // table.key = [
 | 
				
			||||||
 | 
					        //   {...},
 | 
				
			||||||
 | 
					        //   # comment
 | 
				
			||||||
 | 
					        //   {...},
 | 
				
			||||||
 | 
					        // ]
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        // This function checks if inlinization is possible or not, and then
 | 
				
			||||||
 | 
					        // format the array-of-tables in a proper way.
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // Note about comments:
 | 
				
			||||||
 | 
					        //
 | 
				
			||||||
 | 
					        // If the array itself has a comment (value_has_comment_ == true), we
 | 
				
			||||||
 | 
					        // should try to make it inline.
 | 
				
			||||||
 | 
					        // ```toml
 | 
				
			||||||
 | 
					        // # comment about array
 | 
				
			||||||
 | 
					        // array = [
 | 
				
			||||||
 | 
					        //   # comment about table element
 | 
				
			||||||
 | 
					        //   {of = "table"}
 | 
				
			||||||
 | 
					        // ]
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        // If it is formatted as a multiline table, the two comments becomes
 | 
				
			||||||
 | 
					        // indistinguishable.
 | 
				
			||||||
 | 
					        // ```toml
 | 
				
			||||||
 | 
					        // # comment about array
 | 
				
			||||||
 | 
					        // # comment about table element
 | 
				
			||||||
 | 
					        // [[array]]
 | 
				
			||||||
 | 
					        // of = "table"
 | 
				
			||||||
 | 
					        // ```
 | 
				
			||||||
 | 
					        // So we need to try to make it inline, and it force-inlines regardless
 | 
				
			||||||
 | 
					        // of the line width limit.
 | 
				
			||||||
 | 
					        //     It may fail if the element of a table has comment. In that case,
 | 
				
			||||||
 | 
					        // the array-of-tables will be formatted as a multiline table.
 | 
				
			||||||
 | 
					        if(this->can_be_inlined_ || this->value_has_comment_)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::string token;
 | 
				
			||||||
 | 
					            if(!keys_.empty())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                token += format_key(keys_.back());
 | 
				
			||||||
 | 
					                token += " = ";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool failed = false;
 | 
				
			||||||
 | 
					            token += "[\n";
 | 
				
			||||||
 | 
					            for(const auto& item : v)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // if an element of the table has a comment, the table
 | 
				
			||||||
 | 
					                // cannot be inlined.
 | 
				
			||||||
 | 
					                if(this->has_comment_inside(item.as_table()))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    failed = true;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // write comments for the table itself
 | 
				
			||||||
 | 
					                token += write_comments(item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const auto t = this->make_inline_table(item.as_table());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(t.size() + 1 > width_ || // +1 for the last comma {...},
 | 
				
			||||||
 | 
					                   std::find(t.cbegin(), t.cend(), '\n') != t.cend())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // if the value itself has a comment, ignore the line width limit
 | 
				
			||||||
 | 
					                    if( ! this->value_has_comment_)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        failed = true;
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                token += t;
 | 
				
			||||||
 | 
					                token += ",\n";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if( ! failed)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                token += "]\n";
 | 
				
			||||||
 | 
					                return token;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // if failed, serialize them as [[array.of.tables]].
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        for(const auto& item : v)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            token += write_comments(item);
 | 
				
			||||||
 | 
					            token += "[[";
 | 
				
			||||||
 | 
					            token += format_keys(keys_);
 | 
				
			||||||
 | 
					            token += "]]\n";
 | 
				
			||||||
 | 
					            token += this->make_multiline_table(item.as_table());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return token;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string write_comments(const value_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::string retval;
 | 
				
			||||||
 | 
					        if(this->no_comment_) {return retval;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for(const auto& c : v.comments())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            retval += '#';
 | 
				
			||||||
 | 
					            retval += c;
 | 
				
			||||||
 | 
					            retval += '\n';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return retval;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_array_of_tables(const value_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(!v.is_array() || v.as_array().empty()) {return false;}
 | 
				
			||||||
 | 
					        return is_array_of_tables(v.as_array());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bool is_array_of_tables(const array_type& v) const
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Since TOML v0.5.0, heterogeneous arrays are allowed. So we need to
 | 
				
			||||||
 | 
					        // check all the element in an array to check if the array is an array
 | 
				
			||||||
 | 
					        // of tables.
 | 
				
			||||||
 | 
					        return std::all_of(v.begin(), v.end(), [](const value_type& elem) {
 | 
				
			||||||
 | 
					                return elem.is_table();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool        can_be_inlined_;
 | 
				
			||||||
 | 
					    bool        no_comment_;
 | 
				
			||||||
 | 
					    bool        value_has_comment_;
 | 
				
			||||||
 | 
					    int         float_prec_;
 | 
				
			||||||
 | 
					    std::size_t width_;
 | 
				
			||||||
 | 
					    std::vector<toml::key> keys_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename C,
 | 
				
			||||||
 | 
					         template<typename ...> class M, template<typename ...> class V>
 | 
				
			||||||
 | 
					std::string
 | 
				
			||||||
 | 
					format(const basic_value<C, M, V>& v, std::size_t w = 80u,
 | 
				
			||||||
 | 
					       int fprec = std::numeric_limits<toml::floating>::max_digits10,
 | 
				
			||||||
 | 
					       bool no_comment = false, bool force_inline = false)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = basic_value<C, M, V>;
 | 
				
			||||||
 | 
					    // if value is a table, it is considered to be a root object.
 | 
				
			||||||
 | 
					    // the root object can't be an inline table.
 | 
				
			||||||
 | 
					    if(v.is_table())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::ostringstream oss;
 | 
				
			||||||
 | 
					        if(!v.comments().empty())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            oss << v.comments();
 | 
				
			||||||
 | 
					            oss << '\n'; // to split the file comment from the first element
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const auto serialized = visit(serializer<value_type>(w, fprec, false, no_comment), v);
 | 
				
			||||||
 | 
					        oss << serialized;
 | 
				
			||||||
 | 
					        return oss.str();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return visit(serializer<value_type>(w, fprec, force_inline), v);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					int comment_index(std::basic_ostream<charT, traits>&)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const int index = std::ios_base::xalloc();
 | 
				
			||||||
 | 
					    return index;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					nocomment(std::basic_ostream<charT, traits>& os)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // by default, it is zero. and by default, it shows comments.
 | 
				
			||||||
 | 
					    os.iword(detail::comment_index(os)) = 1;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					showcomment(std::basic_ostream<charT, traits>& os)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // by default, it is zero. and by default, it shows comments.
 | 
				
			||||||
 | 
					    os.iword(detail::comment_index(os)) = 0;
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits, typename C,
 | 
				
			||||||
 | 
					         template<typename ...> class M, template<typename ...> class V>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const basic_value<C, M, V>& v)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = basic_value<C, M, V>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get status of std::setw().
 | 
				
			||||||
 | 
					    const auto w     = static_cast<std::size_t>(os.width());
 | 
				
			||||||
 | 
					    const int  fprec = static_cast<int>(os.precision());
 | 
				
			||||||
 | 
					    os.width(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // by default, iword is initialized by 0. And by default, toml11 outputs
 | 
				
			||||||
 | 
					    // comments. So `0` means showcomment. 1 means nocommnet.
 | 
				
			||||||
 | 
					    const bool no_comment = (1 == os.iword(detail::comment_index(os)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!no_comment && v.is_table() && !v.comments().empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        os << v.comments();
 | 
				
			||||||
 | 
					        os << '\n'; // to split the file comment from the first element
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // the root object can't be an inline table. so pass `false`.
 | 
				
			||||||
 | 
					    const auto serialized = visit(serializer<value_type>(w, fprec, no_comment, false), v);
 | 
				
			||||||
 | 
					    os << serialized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // if v is a non-table value, and has only one comment, then
 | 
				
			||||||
 | 
					    // put a comment just after a value. in the following way.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // ```toml
 | 
				
			||||||
 | 
					    // key = "value" # comment.
 | 
				
			||||||
 | 
					    // ```
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // Since the top-level toml object is a table, one who want to put a
 | 
				
			||||||
 | 
					    // non-table toml value must use this in a following way.
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // ```cpp
 | 
				
			||||||
 | 
					    // toml::value v;
 | 
				
			||||||
 | 
					    // std::cout << "user-defined-key = " << v << std::endl;
 | 
				
			||||||
 | 
					    // ```
 | 
				
			||||||
 | 
					    //
 | 
				
			||||||
 | 
					    // In this case, it is impossible to put comments before key-value pair.
 | 
				
			||||||
 | 
					    // The only way to preserve comments is to put all of them after a value.
 | 
				
			||||||
 | 
					    if(!no_comment && !v.is_table() && !v.comments().empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        os << " #";
 | 
				
			||||||
 | 
					        for(const auto& c : v.comments()) {os << c;}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_SERIALIZER_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,239 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2019.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_SOURCE_LOCATION_HPP
 | 
				
			||||||
 | 
					#define TOML11_SOURCE_LOCATION_HPP
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "region.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A struct to contain location in a toml file.
 | 
				
			||||||
 | 
					// The interface imitates std::experimental::source_location,
 | 
				
			||||||
 | 
					// but not completely the same.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It would be constructed by toml::value. It can be used to generate
 | 
				
			||||||
 | 
					// user-defined error messages.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// - std::uint_least32_t line() const noexcept
 | 
				
			||||||
 | 
					//   - returns the line number where the region is on.
 | 
				
			||||||
 | 
					// - std::uint_least32_t column() const noexcept
 | 
				
			||||||
 | 
					//   - returns the column number where the region starts.
 | 
				
			||||||
 | 
					// - std::uint_least32_t region() const noexcept
 | 
				
			||||||
 | 
					//   - returns the size of the region.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// +-- line()       +-- region of interest (region() == 9)
 | 
				
			||||||
 | 
					// v            .---+---.
 | 
				
			||||||
 | 
					// 12 | value = "foo bar"
 | 
				
			||||||
 | 
					//              ^
 | 
				
			||||||
 | 
					//              +-- column()
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// - std::string const& file_name() const noexcept;
 | 
				
			||||||
 | 
					//   - name of the file.
 | 
				
			||||||
 | 
					// - std::string const& line_str() const noexcept;
 | 
				
			||||||
 | 
					//   - the whole line that contains the region of interest.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					struct source_location
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source_location()
 | 
				
			||||||
 | 
					        : line_num_(1), column_num_(1), region_size_(1),
 | 
				
			||||||
 | 
					          file_name_("unknown file"), line_str_("")
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit source_location(const detail::region_base* reg)
 | 
				
			||||||
 | 
					        : line_num_(1), column_num_(1), region_size_(1),
 | 
				
			||||||
 | 
					          file_name_("unknown file"), line_str_("")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(reg)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(reg->line_num() != detail::region_base().line_num())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                line_num_ = static_cast<std::uint_least32_t>(
 | 
				
			||||||
 | 
					                        std::stoul(reg->line_num()));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            column_num_  = static_cast<std::uint_least32_t>(reg->before() + 1);
 | 
				
			||||||
 | 
					            region_size_ = static_cast<std::uint_least32_t>(reg->size());
 | 
				
			||||||
 | 
					            file_name_   = reg->name();
 | 
				
			||||||
 | 
					            line_str_    = reg->line();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit source_location(const detail::region& reg)
 | 
				
			||||||
 | 
					        : line_num_(static_cast<std::uint_least32_t>(std::stoul(reg.line_num()))),
 | 
				
			||||||
 | 
					          column_num_(static_cast<std::uint_least32_t>(reg.before() + 1)),
 | 
				
			||||||
 | 
					          region_size_(static_cast<std::uint_least32_t>(reg.size())),
 | 
				
			||||||
 | 
					          file_name_(reg.name()),
 | 
				
			||||||
 | 
					          line_str_ (reg.line())
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					    explicit source_location(const detail::location& loc)
 | 
				
			||||||
 | 
					        : line_num_(static_cast<std::uint_least32_t>(std::stoul(loc.line_num()))),
 | 
				
			||||||
 | 
					          column_num_(static_cast<std::uint_least32_t>(loc.before() + 1)),
 | 
				
			||||||
 | 
					          region_size_(static_cast<std::uint_least32_t>(loc.size())),
 | 
				
			||||||
 | 
					          file_name_(loc.name()),
 | 
				
			||||||
 | 
					          line_str_ (loc.line())
 | 
				
			||||||
 | 
					    {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ~source_location() = default;
 | 
				
			||||||
 | 
					    source_location(source_location const&) = default;
 | 
				
			||||||
 | 
					    source_location(source_location &&)     = default;
 | 
				
			||||||
 | 
					    source_location& operator=(source_location const&) = default;
 | 
				
			||||||
 | 
					    source_location& operator=(source_location &&)     = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::uint_least32_t line()      const noexcept {return line_num_;}
 | 
				
			||||||
 | 
					    std::uint_least32_t column()    const noexcept {return column_num_;}
 | 
				
			||||||
 | 
					    std::uint_least32_t region()    const noexcept {return region_size_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string const&  file_name() const noexcept {return file_name_;}
 | 
				
			||||||
 | 
					    std::string const&  line_str()  const noexcept {return line_str_;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::uint_least32_t line_num_;
 | 
				
			||||||
 | 
					    std::uint_least32_t column_num_;
 | 
				
			||||||
 | 
					    std::uint_least32_t region_size_;
 | 
				
			||||||
 | 
					    std::string         file_name_;
 | 
				
			||||||
 | 
					    std::string         line_str_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// internal error message generation.
 | 
				
			||||||
 | 
					inline std::string format_underline(const std::string& message,
 | 
				
			||||||
 | 
					        const std::vector<std::pair<source_location, std::string>>& loc_com,
 | 
				
			||||||
 | 
					        const std::vector<std::string>& helps = {},
 | 
				
			||||||
 | 
					        const bool colorize = TOML11_ERROR_MESSAGE_COLORIZED)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::size_t line_num_width = 0;
 | 
				
			||||||
 | 
					    for(const auto& lc : loc_com)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::uint_least32_t line = lc.first.line();
 | 
				
			||||||
 | 
					        std::size_t        digit = 0;
 | 
				
			||||||
 | 
					        while(line != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            line  /= 10;
 | 
				
			||||||
 | 
					            digit +=  1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        line_num_width = (std::max)(line_num_width, digit);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 1 is the minimum width
 | 
				
			||||||
 | 
					    line_num_width = std::max<std::size_t>(line_num_width, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ostringstream retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(color::should_color() || colorize)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        retval << color::colorize; // turn on ANSI color
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // XXX
 | 
				
			||||||
 | 
					    // Here, before `colorize` support, it does not output `[error]` prefix
 | 
				
			||||||
 | 
					    // automatically. So some user may output it manually and this change may
 | 
				
			||||||
 | 
					    // duplicate the prefix. To avoid it, check the first 7 characters and
 | 
				
			||||||
 | 
					    // if it is "[error]", it removes that part from the message shown.
 | 
				
			||||||
 | 
					    if(message.size() > 7 && message.substr(0, 7) == "[error]")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        retval
 | 
				
			||||||
 | 
					#ifndef TOML11_NO_ERROR_PREFIX
 | 
				
			||||||
 | 
					               << color::bold << color::red << "[error]" << color::reset
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					               << color::bold << message.substr(7) << color::reset << '\n';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        retval
 | 
				
			||||||
 | 
					#ifndef TOML11_NO_ERROR_PREFIX
 | 
				
			||||||
 | 
					               << color::bold << color::red << "[error] " << color::reset
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					               << color::bold << message << color::reset << '\n';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto format_one_location = [line_num_width]
 | 
				
			||||||
 | 
					        (std::ostringstream& oss,
 | 
				
			||||||
 | 
					         const source_location& loc, const std::string& comment) -> void
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            oss << ' ' << color::bold << color::blue
 | 
				
			||||||
 | 
					                << std::setw(static_cast<int>(line_num_width))
 | 
				
			||||||
 | 
					                << std::right << loc.line() << " | "  << color::reset
 | 
				
			||||||
 | 
					                << loc.line_str() << '\n';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            oss << make_string(line_num_width + 1, ' ')
 | 
				
			||||||
 | 
					                << color::bold << color::blue << " | " << color::reset
 | 
				
			||||||
 | 
					                << make_string(loc.column()-1 /*1-origin*/, ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(loc.region() == 1)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // invalid
 | 
				
			||||||
 | 
					                // ^------
 | 
				
			||||||
 | 
					                oss << color::bold << color::red << "^---" << color::reset;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // invalid
 | 
				
			||||||
 | 
					                // ~~~~~~~
 | 
				
			||||||
 | 
					                const auto underline_len = (std::min)(
 | 
				
			||||||
 | 
					                    static_cast<std::size_t>(loc.region()), loc.line_str().size());
 | 
				
			||||||
 | 
					                oss << color::bold << color::red
 | 
				
			||||||
 | 
					                    << make_string(underline_len, '~') << color::reset;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            oss << ' ';
 | 
				
			||||||
 | 
					            oss << comment;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert(!loc_com.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // --> example.toml
 | 
				
			||||||
 | 
					    //   |
 | 
				
			||||||
 | 
					    retval << color::bold << color::blue << " --> " << color::reset
 | 
				
			||||||
 | 
					           << loc_com.front().first.file_name() << '\n';
 | 
				
			||||||
 | 
					    retval << make_string(line_num_width + 1, ' ')
 | 
				
			||||||
 | 
					           << color::bold << color::blue << " |\n"  << color::reset;
 | 
				
			||||||
 | 
					    // 1 | key value
 | 
				
			||||||
 | 
					    //   |    ^--- missing =
 | 
				
			||||||
 | 
					    format_one_location(retval, loc_com.front().first, loc_com.front().second);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // process the rest of the locations
 | 
				
			||||||
 | 
					    for(std::size_t i=1; i<loc_com.size(); ++i)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const auto& prev = loc_com.at(i-1);
 | 
				
			||||||
 | 
					        const auto& curr = loc_com.at(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        retval << '\n';
 | 
				
			||||||
 | 
					        // if the filenames are the same, print "..."
 | 
				
			||||||
 | 
					        if(prev.first.file_name() == curr.first.file_name())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            retval << color::bold << color::blue << " ...\n" << color::reset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else // if filename differs, print " --> filename.toml" again
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            retval << color::bold << color::blue << " --> " << color::reset
 | 
				
			||||||
 | 
					                   << curr.first.file_name() << '\n';
 | 
				
			||||||
 | 
					            retval << make_string(line_num_width + 1, ' ')
 | 
				
			||||||
 | 
					                   << color::bold << color::blue << " |\n"  << color::reset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        format_one_location(retval, curr.first, curr.second);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!helps.empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        retval << '\n';
 | 
				
			||||||
 | 
					        retval << make_string(line_num_width + 1, ' ');
 | 
				
			||||||
 | 
					        retval << color::bold << color::blue << " |" << color::reset;
 | 
				
			||||||
 | 
					        for(const auto& help : helps)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            retval << color::bold << "\nHint: " << color::reset;
 | 
				
			||||||
 | 
					            retval << help;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return retval.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_SOURCE_LOCATION_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_STORAGE_HPP
 | 
				
			||||||
 | 
					#define TOML11_STORAGE_HPP
 | 
				
			||||||
 | 
					#include "utility.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// this contains pointer and deep-copy the content if copied.
 | 
				
			||||||
 | 
					// to avoid recursive pointer.
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct storage
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using value_type = T;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit storage(value_type const& v): ptr(toml::make_unique<T>(v)) {}
 | 
				
			||||||
 | 
					    explicit storage(value_type&&      v): ptr(toml::make_unique<T>(std::move(v))) {}
 | 
				
			||||||
 | 
					    ~storage() = default;
 | 
				
			||||||
 | 
					    storage(const storage& rhs): ptr(toml::make_unique<T>(*rhs.ptr)) {}
 | 
				
			||||||
 | 
					    storage& operator=(const storage& rhs)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        this->ptr = toml::make_unique<T>(*rhs.ptr);
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    storage(storage&&) = default;
 | 
				
			||||||
 | 
					    storage& operator=(storage&&) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool is_ok() const noexcept {return static_cast<bool>(ptr);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value_type&       value() &      noexcept {return *ptr;}
 | 
				
			||||||
 | 
					    value_type const& value() const& noexcept {return *ptr;}
 | 
				
			||||||
 | 
					    value_type&&      value() &&     noexcept {return std::move(*ptr);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
					    std::unique_ptr<value_type> ptr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_STORAGE_HPP
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,228 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_STRING_HPP
 | 
				
			||||||
 | 
					#define TOML11_STRING_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "version.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#if __has_include(<string_view>)
 | 
				
			||||||
 | 
					#define TOML11_USING_STRING_VIEW 1
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class string_t : std::uint8_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    basic   = 0,
 | 
				
			||||||
 | 
					    literal = 1,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct string
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    string()  = default;
 | 
				
			||||||
 | 
					    ~string() = default;
 | 
				
			||||||
 | 
					    string(const string& s) = default;
 | 
				
			||||||
 | 
					    string(string&& s)      = default;
 | 
				
			||||||
 | 
					    string& operator=(const string& s) = default;
 | 
				
			||||||
 | 
					    string& operator=(string&& s)      = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string(const std::string& s): kind(string_t::basic), str(s){}
 | 
				
			||||||
 | 
					    string(const std::string& s, string_t k):   kind(k), str(s){}
 | 
				
			||||||
 | 
					    string(const char* s):        kind(string_t::basic), str(s){}
 | 
				
			||||||
 | 
					    string(const char* s,        string_t k):   kind(k), str(s){}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string(std::string&& s): kind(string_t::basic), str(std::move(s)){}
 | 
				
			||||||
 | 
					    string(std::string&& s, string_t k):   kind(k), str(std::move(s)){}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string& operator=(const std::string& s)
 | 
				
			||||||
 | 
					    {kind = string_t::basic; str = s; return *this;}
 | 
				
			||||||
 | 
					    string& operator=(std::string&& s)
 | 
				
			||||||
 | 
					    {kind = string_t::basic; str = std::move(s); return *this;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operator std::string&       () &      noexcept {return str;}
 | 
				
			||||||
 | 
					    operator std::string const& () const& noexcept {return str;}
 | 
				
			||||||
 | 
					    operator std::string&&      () &&     noexcept {return std::move(str);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string& operator+=(const char*        rhs) {str += rhs; return *this;}
 | 
				
			||||||
 | 
					    string& operator+=(const char         rhs) {str += rhs; return *this;}
 | 
				
			||||||
 | 
					    string& operator+=(const std::string& rhs) {str += rhs; return *this;}
 | 
				
			||||||
 | 
					    string& operator+=(const string&      rhs) {str += rhs.str; return *this;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(TOML11_USING_STRING_VIEW) && TOML11_USING_STRING_VIEW>0
 | 
				
			||||||
 | 
					    explicit string(std::string_view s): kind(string_t::basic), str(s){}
 | 
				
			||||||
 | 
					    string(std::string_view s, string_t k): kind(k), str(s){}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string& operator=(std::string_view s)
 | 
				
			||||||
 | 
					    {kind = string_t::basic; str = s; return *this;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    explicit operator std::string_view() const noexcept
 | 
				
			||||||
 | 
					    {return std::string_view(str);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string& operator+=(const std::string_view& rhs) {str += rhs; return *this;}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    string_t    kind;
 | 
				
			||||||
 | 
					    std::string str;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool operator==(const string& lhs, const string& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return lhs.kind == rhs.kind && lhs.str == rhs.str;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator!=(const string& lhs, const string& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs == rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<(const string& lhs, const string& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (lhs.kind == rhs.kind) ? (lhs.str < rhs.str) : (lhs.kind < rhs.kind);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>(const string& lhs, const string& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return rhs < lhs;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator<=(const string& lhs, const string& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(rhs < lhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					inline bool operator>=(const string& lhs, const string& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return !(lhs < rhs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator==(const string& lhs, const std::string& rhs) {return lhs.str == rhs;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator!=(const string& lhs, const std::string& rhs) {return lhs.str != rhs;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator< (const string& lhs, const std::string& rhs) {return lhs.str <  rhs;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator> (const string& lhs, const std::string& rhs) {return lhs.str >  rhs;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator<=(const string& lhs, const std::string& rhs) {return lhs.str <= rhs;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator>=(const string& lhs, const std::string& rhs) {return lhs.str >= rhs;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator==(const std::string& lhs, const string& rhs) {return lhs == rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator!=(const std::string& lhs, const string& rhs) {return lhs != rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator< (const std::string& lhs, const string& rhs) {return lhs <  rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator> (const std::string& lhs, const string& rhs) {return lhs >  rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator<=(const std::string& lhs, const string& rhs) {return lhs <= rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator>=(const std::string& lhs, const string& rhs) {return lhs >= rhs.str;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator==(const string& lhs, const char* rhs) {return lhs.str == std::string(rhs);}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator!=(const string& lhs, const char* rhs) {return lhs.str != std::string(rhs);}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator< (const string& lhs, const char* rhs) {return lhs.str <  std::string(rhs);}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator> (const string& lhs, const char* rhs) {return lhs.str >  std::string(rhs);}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator<=(const string& lhs, const char* rhs) {return lhs.str <= std::string(rhs);}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator>=(const string& lhs, const char* rhs) {return lhs.str >= std::string(rhs);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator==(const char* lhs, const string& rhs) {return std::string(lhs) == rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator!=(const char* lhs, const string& rhs) {return std::string(lhs) != rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator< (const char* lhs, const string& rhs) {return std::string(lhs) <  rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator> (const char* lhs, const string& rhs) {return std::string(lhs) >  rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator<=(const char* lhs, const string& rhs) {return std::string(lhs) <= rhs.str;}
 | 
				
			||||||
 | 
					inline bool
 | 
				
			||||||
 | 
					operator>=(const char* lhs, const string& rhs) {return std::string(lhs) >= rhs.str;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, const string& s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(s.kind == string_t::basic)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // it contains newline. make it multiline string.
 | 
				
			||||||
 | 
					            os << "\"\"\"\n";
 | 
				
			||||||
 | 
					            for(auto i=s.str.cbegin(), e=s.str.cend(); i!=e; ++i)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                switch(*i)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    case '\\': {os << "\\\\"; break;}
 | 
				
			||||||
 | 
					                    case '\"': {os << "\\\""; break;}
 | 
				
			||||||
 | 
					                    case '\b': {os << "\\b";  break;}
 | 
				
			||||||
 | 
					                    case '\t': {os << "\\t";  break;}
 | 
				
			||||||
 | 
					                    case '\f': {os << "\\f";  break;}
 | 
				
			||||||
 | 
					                    case '\n': {os << '\n';   break;}
 | 
				
			||||||
 | 
					                    case '\r':
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        // since it is a multiline string,
 | 
				
			||||||
 | 
					                        // CRLF is not needed to be escaped.
 | 
				
			||||||
 | 
					                        if(std::next(i) != e && *std::next(i) == '\n')
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            os << "\r\n";
 | 
				
			||||||
 | 
					                            ++i;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            os << "\\r";
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    default: {os << *i; break;}
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            os << "\\\n\"\"\"";
 | 
				
			||||||
 | 
					            return os;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // no newline. make it inline.
 | 
				
			||||||
 | 
					        os << "\"";
 | 
				
			||||||
 | 
					        for(const auto c : s.str)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch(c)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case '\\': {os << "\\\\"; break;}
 | 
				
			||||||
 | 
					                case '\"': {os << "\\\""; break;}
 | 
				
			||||||
 | 
					                case '\b': {os << "\\b";  break;}
 | 
				
			||||||
 | 
					                case '\t': {os << "\\t";  break;}
 | 
				
			||||||
 | 
					                case '\f': {os << "\\f";  break;}
 | 
				
			||||||
 | 
					                case '\n': {os << "\\n";  break;}
 | 
				
			||||||
 | 
					                case '\r': {os << "\\r";  break;}
 | 
				
			||||||
 | 
					                default  : {os << c;      break;}
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        os << "\"";
 | 
				
			||||||
 | 
					        return os;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // the string `s` is literal-string.
 | 
				
			||||||
 | 
					    if(std::find(s.str.cbegin(), s.str.cend(), '\n') != s.str.cend() ||
 | 
				
			||||||
 | 
					       std::find(s.str.cbegin(), s.str.cend(), '\'') != s.str.cend() )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // contains newline or single quote. make it multiline.
 | 
				
			||||||
 | 
					        os << "'''\n" << s.str << "'''";
 | 
				
			||||||
 | 
					        return os;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // normal literal string
 | 
				
			||||||
 | 
					    os << '\'' << s.str << '\'';
 | 
				
			||||||
 | 
					    return os;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					#endif// TOML11_STRING_H
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,328 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_TRAITS_HPP
 | 
				
			||||||
 | 
					#define TOML11_TRAITS_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "from.hpp"
 | 
				
			||||||
 | 
					#include "into.hpp"
 | 
				
			||||||
 | 
					#include "version.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					#include <forward_list>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <tuple>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#if __has_include(<string_view>)
 | 
				
			||||||
 | 
					#include <string_view>
 | 
				
			||||||
 | 
					#endif // has_include(<string_view>)
 | 
				
			||||||
 | 
					#endif // cplusplus   >= C++17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<typename C, template<typename ...> class T, template<typename ...> class A>
 | 
				
			||||||
 | 
					class basic_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// check whether type T is a kind of container/map class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct has_iterator_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(typename T::iterator*);
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_value_type_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(typename T::value_type*);
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_key_type_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(typename T::key_type*);
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_mapped_type_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(typename T::mapped_type*);
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_reserve_method_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(
 | 
				
			||||||
 | 
					        decltype(std::declval<T>().reserve(std::declval<std::size_t>()))*);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_push_back_method_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(
 | 
				
			||||||
 | 
					        decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))*);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct is_comparable_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T> static std::false_type check(...);
 | 
				
			||||||
 | 
					    template<typename T> static std::true_type  check(
 | 
				
			||||||
 | 
					        decltype(std::declval<T>() < std::declval<T>())*);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct has_from_toml_method_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T, typename C,
 | 
				
			||||||
 | 
					             template<typename ...> class Tb, template<typename ...> class A>
 | 
				
			||||||
 | 
					    static std::true_type  check(
 | 
				
			||||||
 | 
					        decltype(std::declval<T>().from_toml(
 | 
				
			||||||
 | 
					                std::declval<::toml::basic_value<C, Tb, A>>()))*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<typename T, typename C,
 | 
				
			||||||
 | 
					             template<typename ...> class Tb, template<typename ...> class A>
 | 
				
			||||||
 | 
					    static std::false_type check(...);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_into_toml_method_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T>
 | 
				
			||||||
 | 
					    static std::true_type  check(decltype(std::declval<T>().into_toml())*);
 | 
				
			||||||
 | 
					    template<typename T>
 | 
				
			||||||
 | 
					    static std::false_type check(...);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct has_specialized_from_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T>
 | 
				
			||||||
 | 
					    static std::false_type check(...);
 | 
				
			||||||
 | 
					    template<typename T, std::size_t S = sizeof(::toml::from<T>)>
 | 
				
			||||||
 | 
					    static std::true_type check(::toml::from<T>*);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct has_specialized_into_impl
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    template<typename T>
 | 
				
			||||||
 | 
					    static std::false_type check(...);
 | 
				
			||||||
 | 
					    template<typename T, std::size_t S = sizeof(::toml::into<T>)>
 | 
				
			||||||
 | 
					    static std::true_type check(::toml::from<T>*);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Intel C++ compiler can not use decltype in parent class declaration, here
 | 
				
			||||||
 | 
					/// is a hack to work around it. https://stackoverflow.com/a/23953090/4692076
 | 
				
			||||||
 | 
					#ifdef __INTEL_COMPILER
 | 
				
			||||||
 | 
					#define decltype(...) std::enable_if<true, decltype(__VA_ARGS__)>::type
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_iterator    : decltype(has_iterator_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_value_type  : decltype(has_value_type_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_key_type    : decltype(has_key_type_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_mapped_type : decltype(has_mapped_type_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_reserve_method : decltype(has_reserve_method_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_push_back_method : decltype(has_push_back_method_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct is_comparable : decltype(is_comparable_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename C,
 | 
				
			||||||
 | 
					         template<typename ...> class Tb, template<typename ...> class A>
 | 
				
			||||||
 | 
					struct has_from_toml_method
 | 
				
			||||||
 | 
					: decltype(has_from_toml_method_impl::check<T, C, Tb, A>(nullptr)){};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_into_toml_method
 | 
				
			||||||
 | 
					: decltype(has_into_toml_method_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_specialized_from : decltype(has_specialized_from_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct has_specialized_into : decltype(has_specialized_into_impl::check<T>(nullptr)){};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __INTEL_COMPILER
 | 
				
			||||||
 | 
					#undef decltype
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// C++17 and/or/not
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using std::conjunction;
 | 
				
			||||||
 | 
					using std::disjunction;
 | 
				
			||||||
 | 
					using std::negation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ...> struct conjunction : std::true_type{};
 | 
				
			||||||
 | 
					template<typename T>   struct conjunction<T> : T{};
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					struct conjunction<T, Ts...> :
 | 
				
			||||||
 | 
					    std::conditional<static_cast<bool>(T::value), conjunction<Ts...>, T>::type
 | 
				
			||||||
 | 
					{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ...> struct disjunction : std::false_type{};
 | 
				
			||||||
 | 
					template<typename T>   struct disjunction<T> : T {};
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					struct disjunction<T, Ts...> :
 | 
				
			||||||
 | 
					    std::conditional<static_cast<bool>(T::value), T, disjunction<Ts...>>::type
 | 
				
			||||||
 | 
					{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct negation : std::integral_constant<bool, !static_cast<bool>(T::value)>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// type checkers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> struct is_std_pair : std::false_type{};
 | 
				
			||||||
 | 
					template<typename T1, typename T2>
 | 
				
			||||||
 | 
					struct is_std_pair<std::pair<T1, T2>> : std::true_type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> struct is_std_tuple : std::false_type{};
 | 
				
			||||||
 | 
					template<typename ... Ts>
 | 
				
			||||||
 | 
					struct is_std_tuple<std::tuple<Ts...>> : std::true_type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> struct is_std_forward_list : std::false_type{};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct is_std_forward_list<std::forward_list<T>> : std::true_type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T> struct is_chrono_duration: std::false_type{};
 | 
				
			||||||
 | 
					template<typename Rep, typename Period>
 | 
				
			||||||
 | 
					struct is_chrono_duration<std::chrono::duration<Rep, Period>>: std::true_type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct is_map : conjunction< // map satisfies all the following conditions
 | 
				
			||||||
 | 
					    has_iterator<T>,         // has T::iterator
 | 
				
			||||||
 | 
					    has_value_type<T>,       // has T::value_type
 | 
				
			||||||
 | 
					    has_key_type<T>,         // has T::key_type
 | 
				
			||||||
 | 
					    has_mapped_type<T>       // has T::mapped_type
 | 
				
			||||||
 | 
					    >{};
 | 
				
			||||||
 | 
					template<typename T> struct is_map<T&>                : is_map<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_map<T const&>          : is_map<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_map<T volatile&>       : is_map<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_map<T const volatile&> : is_map<T>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct is_container : conjunction<
 | 
				
			||||||
 | 
					    negation<is_map<T>>,                         // not a map
 | 
				
			||||||
 | 
					    negation<std::is_same<T, std::string>>,      // not a std::string
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
 | 
				
			||||||
 | 
					#if __has_include(<string_view>)
 | 
				
			||||||
 | 
					    negation<std::is_same<T, std::string_view>>, // not a std::string_view
 | 
				
			||||||
 | 
					#endif // has_include(<string_view>)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    has_iterator<T>,                             // has T::iterator
 | 
				
			||||||
 | 
					    has_value_type<T>                            // has T::value_type
 | 
				
			||||||
 | 
					    >{};
 | 
				
			||||||
 | 
					template<typename T> struct is_container<T&>                : is_container<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_container<T const&>          : is_container<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_container<T volatile&>       : is_container<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_container<T const volatile&> : is_container<T>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct is_basic_value: std::false_type{};
 | 
				
			||||||
 | 
					template<typename T> struct is_basic_value<T&>                : is_basic_value<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_basic_value<T const&>          : is_basic_value<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_basic_value<T volatile&>       : is_basic_value<T>{};
 | 
				
			||||||
 | 
					template<typename T> struct is_basic_value<T const volatile&> : is_basic_value<T>{};
 | 
				
			||||||
 | 
					template<typename C, template<typename ...> class M, template<typename ...> class V>
 | 
				
			||||||
 | 
					struct is_basic_value<::toml::basic_value<C, M, V>>: std::true_type{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// C++14 index_sequence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using std::index_sequence;
 | 
				
			||||||
 | 
					using std::make_index_sequence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<std::size_t ... Ns> struct index_sequence{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename IS, std::size_t N> struct push_back_index_sequence{};
 | 
				
			||||||
 | 
					template<std::size_t N, std::size_t ... Ns>
 | 
				
			||||||
 | 
					struct push_back_index_sequence<index_sequence<Ns...>, N>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    typedef index_sequence<Ns..., N> type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<std::size_t N>
 | 
				
			||||||
 | 
					struct index_sequence_maker
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    typedef typename push_back_index_sequence<
 | 
				
			||||||
 | 
					        typename index_sequence_maker<N-1>::type, N>::type type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<>
 | 
				
			||||||
 | 
					struct index_sequence_maker<0>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    typedef index_sequence<0> type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<std::size_t N>
 | 
				
			||||||
 | 
					using make_index_sequence = typename index_sequence_maker<N-1>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // cplusplus >= 2014
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// C++14 enable_if_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using std::enable_if_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<bool B, typename T>
 | 
				
			||||||
 | 
					using enable_if_t = typename std::enable_if<B, T>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // cplusplus >= 2014
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// return_type_of_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L && defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable>=201703
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename F, typename ... Args>
 | 
				
			||||||
 | 
					using return_type_of_t = std::invoke_result_t<F, Args...>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					// result_of is deprecated after C++17
 | 
				
			||||||
 | 
					template<typename F, typename ... Args>
 | 
				
			||||||
 | 
					using return_type_of_t = typename std::result_of<F(Args...)>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// is_string_literal
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// to use this, pass `typename remove_reference<T>::type` to T.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct is_string_literal:
 | 
				
			||||||
 | 
					disjunction<
 | 
				
			||||||
 | 
					    std::is_same<const char*, T>,
 | 
				
			||||||
 | 
					    conjunction<
 | 
				
			||||||
 | 
					        std::is_array<T>,
 | 
				
			||||||
 | 
					        std::is_same<const char, typename std::remove_extent<T>::type>
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					    >{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ---------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// C++20 remove_cvref_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct remove_cvref
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using type = typename std::remove_cv<
 | 
				
			||||||
 | 
					        typename std::remove_reference<T>::type>::type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					using remove_cvref_t = typename remove_cvref<T>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}// detail
 | 
				
			||||||
 | 
					}//toml
 | 
				
			||||||
 | 
					#endif // TOML_TRAITS
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,173 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_TYPES_HPP
 | 
				
			||||||
 | 
					#define TOML11_TYPES_HPP
 | 
				
			||||||
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "comments.hpp"
 | 
				
			||||||
 | 
					#include "datetime.hpp"
 | 
				
			||||||
 | 
					#include "string.hpp"
 | 
				
			||||||
 | 
					#include "traits.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Comment, // discard/preserve_comment
 | 
				
			||||||
 | 
					         template<typename ...> class Table, // map-like class
 | 
				
			||||||
 | 
					         template<typename ...> class Array> // vector-like class
 | 
				
			||||||
 | 
					class basic_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using character = char;
 | 
				
			||||||
 | 
					using key = std::string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ <= 4
 | 
				
			||||||
 | 
					#  pragma GCC diagnostic push
 | 
				
			||||||
 | 
					#  pragma GCC diagnostic ignored "-Wshadow"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using boolean        = bool;
 | 
				
			||||||
 | 
					using integer        = std::int64_t;
 | 
				
			||||||
 | 
					using floating       = double; // "float" is a keyword, cannot use it here.
 | 
				
			||||||
 | 
					// the following stuffs are structs defined here, so aliases are not needed.
 | 
				
			||||||
 | 
					// - string
 | 
				
			||||||
 | 
					// - offset_datetime
 | 
				
			||||||
 | 
					// - offset_datetime
 | 
				
			||||||
 | 
					// - local_datetime
 | 
				
			||||||
 | 
					// - local_date
 | 
				
			||||||
 | 
					// - local_time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__GNUC__) && !defined(__clang__)
 | 
				
			||||||
 | 
					#  pragma GCC diagnostic pop
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// default toml::value and default array/table. these are defined after defining
 | 
				
			||||||
 | 
					// basic_value itself.
 | 
				
			||||||
 | 
					// using value = basic_value<discard_comments, std::unordered_map, std::vector>;
 | 
				
			||||||
 | 
					// using array = typename value::array_type;
 | 
				
			||||||
 | 
					// using table = typename value::table_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// to avoid warnings about `value_t::integer` is "shadowing" toml::integer in
 | 
				
			||||||
 | 
					// GCC -Wshadow=global.
 | 
				
			||||||
 | 
					#if defined(__GNUC__) && !defined(__clang__)
 | 
				
			||||||
 | 
					#  pragma GCC diagnostic push
 | 
				
			||||||
 | 
					#  if 7 <= __GNUC__
 | 
				
			||||||
 | 
					#    pragma GCC diagnostic ignored "-Wshadow=global"
 | 
				
			||||||
 | 
					#  else // gcc-6 or older
 | 
				
			||||||
 | 
					#    pragma GCC diagnostic ignored "-Wshadow"
 | 
				
			||||||
 | 
					#  endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					enum class value_t : std::uint8_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    empty           =  0,
 | 
				
			||||||
 | 
					    boolean         =  1,
 | 
				
			||||||
 | 
					    integer         =  2,
 | 
				
			||||||
 | 
					    floating        =  3,
 | 
				
			||||||
 | 
					    string          =  4,
 | 
				
			||||||
 | 
					    offset_datetime =  5,
 | 
				
			||||||
 | 
					    local_datetime  =  6,
 | 
				
			||||||
 | 
					    local_date      =  7,
 | 
				
			||||||
 | 
					    local_time      =  8,
 | 
				
			||||||
 | 
					    array           =  9,
 | 
				
			||||||
 | 
					    table           = 10,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#if defined(__GNUC__) && !defined(__clang__)
 | 
				
			||||||
 | 
					#  pragma GCC diagnostic pop
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT, typename traits>
 | 
				
			||||||
 | 
					inline std::basic_ostream<charT, traits>&
 | 
				
			||||||
 | 
					operator<<(std::basic_ostream<charT, traits>& os, value_t t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch(t)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case value_t::boolean         : os << "boolean";         return os;
 | 
				
			||||||
 | 
					        case value_t::integer         : os << "integer";         return os;
 | 
				
			||||||
 | 
					        case value_t::floating        : os << "floating";        return os;
 | 
				
			||||||
 | 
					        case value_t::string          : os << "string";          return os;
 | 
				
			||||||
 | 
					        case value_t::offset_datetime : os << "offset_datetime"; return os;
 | 
				
			||||||
 | 
					        case value_t::local_datetime  : os << "local_datetime";  return os;
 | 
				
			||||||
 | 
					        case value_t::local_date      : os << "local_date";      return os;
 | 
				
			||||||
 | 
					        case value_t::local_time      : os << "local_time";      return os;
 | 
				
			||||||
 | 
					        case value_t::array           : os << "array";           return os;
 | 
				
			||||||
 | 
					        case value_t::table           : os << "table";           return os;
 | 
				
			||||||
 | 
					        case value_t::empty           : os << "empty";           return os;
 | 
				
			||||||
 | 
					        default                       : os << "unknown";         return os;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename charT = char,
 | 
				
			||||||
 | 
					         typename traits = std::char_traits<charT>,
 | 
				
			||||||
 | 
					         typename alloc = std::allocator<charT>>
 | 
				
			||||||
 | 
					inline std::basic_string<charT, traits, alloc> stringize(value_t t)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::basic_ostringstream<charT, traits, alloc> oss;
 | 
				
			||||||
 | 
					    oss << t;
 | 
				
			||||||
 | 
					    return oss.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// helper to define a type that represents a value_t value.
 | 
				
			||||||
 | 
					template<value_t V>
 | 
				
			||||||
 | 
					using value_t_constant = std::integral_constant<value_t, V>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// meta-function that convertes from value_t to the exact toml type that corresponds to.
 | 
				
			||||||
 | 
					// It takes toml::basic_value type because array and table types depend on it.
 | 
				
			||||||
 | 
					template<value_t t, typename Value> struct enum_to_type                      {using type = void                      ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::empty          , Value>{using type = void                      ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::boolean        , Value>{using type = boolean                   ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::integer        , Value>{using type = integer                   ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::floating       , Value>{using type = floating                  ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::string         , Value>{using type = string                    ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::offset_datetime, Value>{using type = offset_datetime           ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::local_datetime , Value>{using type = local_datetime            ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::local_date     , Value>{using type = local_date                ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::local_time     , Value>{using type = local_time                ;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::array          , Value>{using type = typename Value::array_type;};
 | 
				
			||||||
 | 
					template<typename Value> struct enum_to_type<value_t::table          , Value>{using type = typename Value::table_type;};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// meta-function that converts from an exact toml type to the enum that corresponds to.
 | 
				
			||||||
 | 
					template<typename T, typename Value>
 | 
				
			||||||
 | 
					struct type_to_enum : std::conditional<
 | 
				
			||||||
 | 
					    std::is_same<T, typename Value::array_type>::value, // if T == array_type,
 | 
				
			||||||
 | 
					    value_t_constant<value_t::array>,                   // then value_t::array
 | 
				
			||||||
 | 
					    typename std::conditional<                          // else...
 | 
				
			||||||
 | 
					        std::is_same<T, typename Value::table_type>::value, // if T == table_type
 | 
				
			||||||
 | 
					        value_t_constant<value_t::table>,               // then value_t::table
 | 
				
			||||||
 | 
					        value_t_constant<value_t::empty>                // else value_t::empty
 | 
				
			||||||
 | 
					        >::type
 | 
				
			||||||
 | 
					    >::type {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<boolean        , Value>: value_t_constant<value_t::boolean        > {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<integer        , Value>: value_t_constant<value_t::integer        > {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<floating       , Value>: value_t_constant<value_t::floating       > {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<string         , Value>: value_t_constant<value_t::string         > {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<offset_datetime, Value>: value_t_constant<value_t::offset_datetime> {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<local_datetime , Value>: value_t_constant<value_t::local_datetime > {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<local_date     , Value>: value_t_constant<value_t::local_date     > {};
 | 
				
			||||||
 | 
					template<typename Value> struct type_to_enum<local_time     , Value>: value_t_constant<value_t::local_time     > {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// meta-function that checks the type T is the same as one of the toml::* types.
 | 
				
			||||||
 | 
					template<typename T, typename Value>
 | 
				
			||||||
 | 
					struct is_exact_toml_type : disjunction<
 | 
				
			||||||
 | 
					    std::is_same<T, boolean        >,
 | 
				
			||||||
 | 
					    std::is_same<T, integer        >,
 | 
				
			||||||
 | 
					    std::is_same<T, floating       >,
 | 
				
			||||||
 | 
					    std::is_same<T, string         >,
 | 
				
			||||||
 | 
					    std::is_same<T, offset_datetime>,
 | 
				
			||||||
 | 
					    std::is_same<T, local_datetime >,
 | 
				
			||||||
 | 
					    std::is_same<T, local_date     >,
 | 
				
			||||||
 | 
					    std::is_same<T, local_time     >,
 | 
				
			||||||
 | 
					    std::is_same<T, typename Value::array_type>,
 | 
				
			||||||
 | 
					    std::is_same<T, typename Value::table_type>
 | 
				
			||||||
 | 
					    >{};
 | 
				
			||||||
 | 
					template<typename T, typename V> struct is_exact_toml_type<T&, V>               : is_exact_toml_type<T, V>{};
 | 
				
			||||||
 | 
					template<typename T, typename V> struct is_exact_toml_type<T const&, V>         : is_exact_toml_type<T, V>{};
 | 
				
			||||||
 | 
					template<typename T, typename V> struct is_exact_toml_type<T volatile&, V>      : is_exact_toml_type<T, V>{};
 | 
				
			||||||
 | 
					template<typename T, typename V> struct is_exact_toml_type<T const volatile&, V>: is_exact_toml_type<T, V>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					} // toml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif// TOML11_TYPES_H
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,150 @@
 | 
				
			||||||
 | 
					//     Copyright Toru Niina 2017.
 | 
				
			||||||
 | 
					// Distributed under the MIT License.
 | 
				
			||||||
 | 
					#ifndef TOML11_UTILITY_HPP
 | 
				
			||||||
 | 
					#define TOML11_UTILITY_HPP
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "traits.hpp"
 | 
				
			||||||
 | 
					#include "version.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L
 | 
				
			||||||
 | 
					#  define TOML11_MARK_AS_DEPRECATED(msg) [[deprecated(msg)]]
 | 
				
			||||||
 | 
					#elif defined(__GNUC__)
 | 
				
			||||||
 | 
					#  define TOML11_MARK_AS_DEPRECATED(msg) __attribute__((deprecated(msg)))
 | 
				
			||||||
 | 
					#elif defined(_MSC_VER)
 | 
				
			||||||
 | 
					#  define TOML11_MARK_AS_DEPRECATED(msg) __declspec(deprecated(msg))
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define TOML11_MARK_AS_DEPRECATED
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace toml
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using std::make_unique;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					inline std::unique_ptr<T> make_unique(Ts&& ... args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::unique_ptr<T>(new T(std::forward<Ts>(args)...));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // TOML11_CPLUSPLUS_STANDARD_VERSION >= 2014
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					template<typename Container>
 | 
				
			||||||
 | 
					void try_reserve_impl(Container& container, std::size_t N, std::true_type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    container.reserve(N);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename Container>
 | 
				
			||||||
 | 
					void try_reserve_impl(Container&, std::size_t, std::false_type) noexcept
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename Container>
 | 
				
			||||||
 | 
					void try_reserve(Container& container, std::size_t N)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(N <= container.size()) {return;}
 | 
				
			||||||
 | 
					    detail::try_reserve_impl(container, N, detail::has_reserve_method<Container>{});
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					inline std::string concat_to_string_impl(std::ostringstream& oss)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return oss.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					std::string concat_to_string_impl(std::ostringstream& oss, T&& head, Ts&& ... tail)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    oss << std::forward<T>(head);
 | 
				
			||||||
 | 
					    return concat_to_string_impl(oss, std::forward<Ts>(tail) ... );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename ... Ts>
 | 
				
			||||||
 | 
					std::string concat_to_string(Ts&& ... args)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    std::ostringstream oss;
 | 
				
			||||||
 | 
					    oss << std::boolalpha << std::fixed;
 | 
				
			||||||
 | 
					    return detail::concat_to_string_impl(oss, std::forward<Ts>(args) ...);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T from_string(const std::string& str, T opt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    T v(opt);
 | 
				
			||||||
 | 
					    std::istringstream iss(str);
 | 
				
			||||||
 | 
					    iss >> v;
 | 
				
			||||||
 | 
					    return v;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace detail
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201402L
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					decltype(auto) last_one(T&& tail) noexcept
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::forward<T>(tail);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					decltype(auto) last_one(T&& /*head*/, Ts&& ... tail) noexcept
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return last_one(std::forward<Ts>(tail)...);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else // C++11
 | 
				
			||||||
 | 
					// The following code
 | 
				
			||||||
 | 
					// ```cpp
 | 
				
			||||||
 | 
					//  1 | template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					//  2 | auto last_one(T&& /*head*/, Ts&& ... tail)
 | 
				
			||||||
 | 
					//  3 |  -> decltype(last_one(std::forward<Ts>(tail)...))
 | 
				
			||||||
 | 
					//  4 | {
 | 
				
			||||||
 | 
					//  5 |     return last_one(std::forward<Ts>(tail)...);
 | 
				
			||||||
 | 
					//  6 | }
 | 
				
			||||||
 | 
					// ```
 | 
				
			||||||
 | 
					// does not work because the function `last_one(...)` is not yet defined at
 | 
				
			||||||
 | 
					// line #3, so `decltype()` cannot deduce the type returned from `last_one`.
 | 
				
			||||||
 | 
					// So we need to determine return type in a different way, like a meta func.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					struct last_one_in_pack
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using type = typename last_one_in_pack<Ts...>::type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					struct last_one_in_pack<T>
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    using type = T;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					template<typename ... Ts>
 | 
				
			||||||
 | 
					using last_one_in_pack_t = typename last_one_in_pack<Ts...>::type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<typename T>
 | 
				
			||||||
 | 
					T&& last_one(T&& tail) noexcept
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return std::forward<T>(tail);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					template<typename T, typename ... Ts>
 | 
				
			||||||
 | 
					enable_if_t<(sizeof...(Ts) > 0), last_one_in_pack_t<Ts&& ...>>
 | 
				
			||||||
 | 
					last_one(T&& /*head*/, Ts&& ... tail)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return last_one(std::forward<Ts>(tail)...);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} // detail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}// toml
 | 
				
			||||||
 | 
					#endif // TOML11_UTILITY
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					#ifndef TOML11_VERSION_HPP
 | 
				
			||||||
 | 
					#define TOML11_VERSION_HPP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This file checks C++ version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __cplusplus
 | 
				
			||||||
 | 
					#    error "__cplusplus is not defined"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Since MSVC does not define `__cplusplus` correctly unless you pass
 | 
				
			||||||
 | 
					// `/Zc:__cplusplus` when compiling, the workaround macros are added.
 | 
				
			||||||
 | 
					// Those enables you to define version manually or to use MSVC specific
 | 
				
			||||||
 | 
					// version macro automatically.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// The value of `__cplusplus` macro is defined in the C++ standard spec, but
 | 
				
			||||||
 | 
					// MSVC ignores the value, maybe because of backward compatibility. Instead,
 | 
				
			||||||
 | 
					// MSVC defines _MSVC_LANG that has the same value as __cplusplus defined in
 | 
				
			||||||
 | 
					// the C++ standard. First we check the manual version definition, and then
 | 
				
			||||||
 | 
					// we check if _MSVC_LANG is defined. If neither, use normal `__cplusplus`.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// FYI: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=msvc-170
 | 
				
			||||||
 | 
					//      https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					#if   defined(TOML11_ENFORCE_CXX11)
 | 
				
			||||||
 | 
					#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201103L
 | 
				
			||||||
 | 
					#elif defined(TOML11_ENFORCE_CXX14)
 | 
				
			||||||
 | 
					#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201402L
 | 
				
			||||||
 | 
					#elif defined(TOML11_ENFORCE_CXX17)
 | 
				
			||||||
 | 
					#  define TOML11_CPLUSPLUS_STANDARD_VERSION 201703L
 | 
				
			||||||
 | 
					#elif defined(TOML11_ENFORCE_CXX20)
 | 
				
			||||||
 | 
					#  define TOML11_CPLUSPLUS_STANDARD_VERSION 202002L
 | 
				
			||||||
 | 
					#elif defined(_MSVC_LANG) && defined(_MSC_VER) && 1910 <= _MSC_VER
 | 
				
			||||||
 | 
					#  define TOML11_CPLUSPLUS_STANDARD_VERSION _MSVC_LANG
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#  define TOML11_CPLUSPLUS_STANDARD_VERSION __cplusplus
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if TOML11_CPLUSPLUS_STANDARD_VERSION < 201103L && _MSC_VER < 1900
 | 
				
			||||||
 | 
					#    error "toml11 requires C++11 or later."
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif// TOML11_VERSION_HPP
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,9 @@
 | 
				
			||||||
#ifndef GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
					#ifndef GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
				
			||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
					#define GLM_FORCE_DEPTH_ZERO_TO_ONE
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <glm/glm.hpp>
 | 
					#include <glm/glm.hpp>
 | 
				
			||||||
#include <glm/gtc/matrix_transform.hpp>
 | 
					#include <glm/gtc/matrix_transform.hpp>
 | 
				
			||||||
#include <glm/gtc/type_ptr.hpp>
 | 
					#include <glm/gtc/type_ptr.hpp>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -262,7 +262,7 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		loadScene(sceneFile.c_str());
 | 
							loadScene(sceneFile.c_str());
 | 
				
			||||||
		models.skybox.loadFromFile(PlumageRender::filePath.skyboxModleFilePath, vulkanDevice, queue);
 | 
							models.skybox.loadFromFile(PlumageRender::filePath.skyboxModelFilePath, vulkanDevice, queue);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		loadEnvironment(envMapFile.c_str());
 | 
							loadEnvironment(envMapFile.c_str());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1923,7 +1923,10 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		std::cout << "vidoe codec complete,saved in:" << resultVideoPath << std::endl;
 | 
							std::cout << "vidoe codec complete,saved in:" << resultVideoPath << std::endl;
 | 
				
			||||||
		std::cout << "star to clean up image sequence" << std::endl;
 | 
							std::cout << "star to clean up image sequence" << std::endl;
 | 
				
			||||||
 | 
							if (settings.cleanUpImageSequece = true)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
			removeImageSequence();
 | 
								removeImageSequence();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		signal.imageSequenceToVideoComplete = true;
 | 
							signal.imageSequenceToVideoComplete = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2045,7 +2048,7 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
			if (settings.rotateModel) {
 | 
								if (settings.rotateModel) {
 | 
				
			||||||
				modelrot += frameTimer * 2.0f;
 | 
									modelrot += frameTimer * settings.modelRotateSpeed;
 | 
				
			||||||
				if (modelrot > 360.0f) {
 | 
									if (modelrot > 360.0f) {
 | 
				
			||||||
					modelrot -= 360.0f;
 | 
										modelrot -= 360.0f;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -2297,6 +2300,9 @@ PlumageRender::PlumageRender()
 | 
				
			||||||
	int main(int argc, char* argv[])
 | 
						int main(int argc, char* argv[])
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		for (int32_t i = 0; i < argc; i++) { PlumageRender::args.push_back(argv[i]); };
 | 
							for (int32_t i = 0; i < argc; i++) { PlumageRender::args.push_back(argv[i]); };
 | 
				
			||||||
 | 
							PlumageConfig::PlumageConfiguration config;
 | 
				
			||||||
 | 
							//config.writrConfigurationToJson();
 | 
				
			||||||
 | 
							//config.readConfigurationFromJson(config.filePath.configFilePath);
 | 
				
			||||||
		plumageRender = new PlumageRender();
 | 
							plumageRender = new PlumageRender();
 | 
				
			||||||
		std::cout << "start to init vulkan" << std::endl;
 | 
							std::cout << "start to init vulkan" << std::endl;
 | 
				
			||||||
		plumageRender->initVulkan();
 | 
							plumageRender->initVulkan();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue