MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
cpptoml::parser Class Reference

#include <cpptoml.h>

Collaboration diagram for cpptoml::parser:
[legend]

Public Member Functions

 parser (std::istream &stream)
 
parseroperator= (const parser &parser)=delete
 
std::shared_ptr< tableparse ()
 

Private Types

enum class  parse_type {
  STRING = 1 , LOCAL_TIME , LOCAL_DATE , LOCAL_DATETIME ,
  OFFSET_DATETIME , INT , FLOAT , BOOL ,
  ARRAY , INLINE_TABLE
}
 

Private Member Functions

 __declspec (noreturn) __attribute__((noreturn)) void throw_parse_exception(const std
 
void parse_table (std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
 
void parse_single_table (std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
 
void parse_table_array (std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
 
void parse_key_value (std::string::iterator &it, std::string::iterator &end, table *curr_table)
 
template<class KeyEndFinder , class KeyPartHandler >
std::string parse_key (std::string::iterator &it, const std::string::iterator &end, KeyEndFinder &&key_end, KeyPartHandler &&key_part_handler)
 
std::string parse_simple_key (std::string::iterator &it, const std::string::iterator &end)
 
std::string parse_bare_key (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< baseparse_value (std::string::iterator &it, std::string::iterator &end)
 
parse_type determine_value_type (const std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< value< std::string > > parse_string (std::string::iterator &it, std::string::iterator &end)
 
std::shared_ptr< value< std::string > > parse_multiline_string (std::string::iterator &it, std::string::iterator &end, char delim)
 
std::string string_literal (std::string::iterator &it, const std::string::iterator &end, char delim)
 
std::string parse_escape_code (std::string::iterator &it, const std::string::iterator &end)
 
std::string parse_unicode (std::string::iterator &it, const std::string::iterator &end)
 
uint32_t parse_hex (std::string::iterator &it, const std::string::iterator &end, uint32_t place)
 
std::shared_ptr< baseparse_number (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< value< int64_t > > parse_int (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< value< double > > parse_float (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< value< MBool > > parse_bool (std::string::iterator &it, const std::string::iterator &end)
 
local_time read_time (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< value< local_time > > parse_time (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< baseparse_date (std::string::iterator &it, const std::string::iterator &end)
 
std::shared_ptr< baseparse_array (std::string::iterator &it, std::string::iterator &end)
 
template<class Value >
std::shared_ptr< arrayparse_value_array (std::string::iterator &it, std::string::iterator &end)
 
template<class Object , class Function >
std::shared_ptr< Object > parse_object_array (Function &&fun, char delim, std::string::iterator &it, std::string::iterator &end)
 
std::shared_ptr< tableparse_inline_table (std::string::iterator &it, std::string::iterator &end)
 
void skip_whitespace_and_comments (std::string::iterator &start, std::string::iterator &end)
 
void eol_or_comment (const std::string::iterator &it, const std::string::iterator &end)
 

Static Private Member Functions

static parse_type determine_number_type (const std::string::iterator &it, const std::string::iterator &end)
 
static MBool is_hex (char c)
 
static uint32_t hex_to_digit (char c)
 
static std::string::iterator find_end_of_number (std::string::iterator it, std::string::iterator end)
 
static std::string::iterator find_end_of_date (std::string::iterator it, std::string::iterator end)
 
static std::string::iterator find_end_of_time (std::string::iterator it, std::string::iterator end)
 
static void consume_whitespace (std::string::iterator &it, const std::string::iterator &end)
 
static void consume_backwards_whitespace (std::string::iterator &back, const std::string::iterator &front)
 
static MBool is_time (const std::string::iterator &it, const std::string::iterator &end)
 
static option< parse_typedate_type (const std::string::iterator &it, const std::string::iterator &end)
 

Private Attributes

std::istream & input_
 
std::string line_
 
std::size_t line_number_ = 0
 

Detailed Description

The parser class.

Definition at line 1546 of file cpptoml.h.

Member Enumeration Documentation

◆ parse_type

enum class cpptoml::parser::parse_type
strongprivate
Enumerator
STRING 
LOCAL_TIME 
LOCAL_DATE 
LOCAL_DATETIME 
OFFSET_DATETIME 
INT 
FLOAT 
BOOL 
ARRAY 
INLINE_TABLE 

Definition at line 1835 of file cpptoml.h.

Constructor & Destructor Documentation

◆ parser()

cpptoml::parser::parser ( std::istream &  stream)
inlineexplicit

Parsers are constructed from streams.

Definition at line 1551 of file cpptoml.h.

1551 : input_(stream) {
1552 // nothing
1553 }
std::istream & input_
Definition: cpptoml.h:2493

Member Function Documentation

◆ __declspec()

cpptoml::parser::__declspec ( noreturn  ) const
inlineprivate

Definition at line 1586 of file cpptoml.h.

1590 {
1591 THROW2_(parse_exception, err, line_number_);
1592 }
std::size_t line_number_
Definition: cpptoml.h:2495

◆ consume_backwards_whitespace()

static void cpptoml::parser::consume_backwards_whitespace ( std::string::iterator &  back,
const std::string::iterator &  front 
)
inlinestaticprivate

Definition at line 2447 of file cpptoml.h.

2447 {
2448 while(back != front && (*back == ' ' || *back == '\t'))
2449 --back;
2450 }

◆ consume_whitespace()

static void cpptoml::parser::consume_whitespace ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlinestaticprivate

Definition at line 2442 of file cpptoml.h.

2442 {
2443 while(it != end && (*it == ' ' || *it == '\t'))
2444 ++it;
2445 }

◆ date_type()

static option< parse_type > cpptoml::parser::date_type ( const std::string::iterator &  it,
const std::string::iterator &  end 
)
inlinestaticprivate

Definition at line 2470 of file cpptoml.h.

2470 {
2471 auto date_end = find_end_of_date(it, end);
2472 auto len = std::distance(it, date_end);
2473
2474 if(len < 10) return {};
2475
2476 if(it[4] != '-' || it[7] != '-') return {};
2477
2478 if(len >= 19 && it[10] == 'T' && is_time(it + 11, date_end)) {
2479 // datetime type
2480 auto time_end = find_end_of_time(it + 11, date_end);
2481 if(time_end == date_end)
2483 else
2485 } else if(len == 10) {
2486 // just a regular date
2487 return {parse_type::LOCAL_DATE};
2488 }
2489
2490 return {};
2491 }
static std::string::iterator find_end_of_date(std::string::iterator it, std::string::iterator end)
Definition: cpptoml.h:2239
static std::string::iterator find_end_of_time(std::string::iterator it, std::string::iterator end)
Definition: cpptoml.h:2245
static MBool is_time(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2457

◆ determine_number_type()

static parse_type cpptoml::parser::determine_number_type ( const std::string::iterator &  it,
const std::string::iterator &  end 
)
inlinestaticprivate

Definition at line 1895 of file cpptoml.h.

1895 {
1896 // determine if we are an integer or a float
1897 auto check_it = it;
1898 if(*check_it == '-' || *check_it == '+') ++check_it;
1899 while(check_it != end && is_number(*check_it))
1900 ++check_it;
1901 if(check_it != end && *check_it == '.') {
1902 ++check_it;
1903 while(check_it != end && is_number(*check_it))
1904 ++check_it;
1905 return parse_type::FLOAT;
1906 } else {
1907 return parse_type::INT;
1908 }
1909 }
MBool is_number(char c)
Definition: cpptoml.h:1471

◆ determine_value_type()

parse_type cpptoml::parser::determine_value_type ( const std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 1873 of file cpptoml.h.

1873 {
1874 if(it == end) {
1875 throw_parse_exception("Failed to parse value type");
1876 }
1877 if(*it == '"' || *it == '\'') {
1878 return parse_type::STRING;
1879 } else if(is_time(it, end)) {
1881 } else if(auto dtype = date_type(it, end)) {
1882 return *dtype;
1883 } else if(is_number(*it) || *it == '-' || *it == '+') {
1884 return determine_number_type(it, end);
1885 } else if(*it == 't' || *it == 'f') {
1886 return parse_type::BOOL;
1887 } else if(*it == '[') {
1888 return parse_type::ARRAY;
1889 } else if(*it == '{') {
1891 }
1892 throw_parse_exception("Failed to parse value type");
1893 }
static option< parse_type > date_type(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2470
static parse_type determine_number_type(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:1895

◆ eol_or_comment()

void cpptoml::parser::eol_or_comment ( const std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2452 of file cpptoml.h.

2452 {
2453 if(it != end && *it != '#')
2454 throw_parse_exception("Unidentified trailing character '" + std::string{*it} + "'---did you forget a '#'?");
2455 }

◆ find_end_of_date()

static std::string::iterator cpptoml::parser::find_end_of_date ( std::string::iterator  it,
std::string::iterator  end 
)
inlinestaticprivate

Definition at line 2239 of file cpptoml.h.

2239 {
2240 return std::find_if(it, end, [](char c) {
2241 return !is_number(c) && c != 'T' && c != 'Z' && c != ':' && c != '-' && c != '+' && c != '.';
2242 });
2243 }

◆ find_end_of_number()

static std::string::iterator cpptoml::parser::find_end_of_number ( std::string::iterator  it,
std::string::iterator  end 
)
inlinestaticprivate

Definition at line 2233 of file cpptoml.h.

2233 {
2234 return std::find_if(it, end, [](char c) {
2235 return !is_number(c) && c != '_' && c != '.' && c != 'e' && c != 'E' && c != '-' && c != '+';
2236 });
2237 }

◆ find_end_of_time()

static std::string::iterator cpptoml::parser::find_end_of_time ( std::string::iterator  it,
std::string::iterator  end 
)
inlinestaticprivate

Definition at line 2245 of file cpptoml.h.

2245 {
2246 return std::find_if(it, end, [](char c) { return !is_number(c) && c != ':' && c != '.'; });
2247 }

◆ hex_to_digit()

static uint32_t cpptoml::parser::hex_to_digit ( char  c)
inlinestaticprivate

Definition at line 2113 of file cpptoml.h.

2113 {
2114 if(is_number(c)) return static_cast<uint32_t>(c - '0');
2115 return 10 + static_cast<uint32_t>(c - ((c >= 'a' && c <= 'f') ? 'a' : 'A'));
2116 }

◆ is_hex()

static MBool cpptoml::parser::is_hex ( char  c)
inlinestaticprivate

Definition at line 2111 of file cpptoml.h.

2111{ return is_number(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); }

◆ is_time()

static MBool cpptoml::parser::is_time ( const std::string::iterator &  it,
const std::string::iterator &  end 
)
inlinestaticprivate

Definition at line 2457 of file cpptoml.h.

2457 {
2458 auto time_end = find_end_of_time(it, end);
2459 auto len = std::distance(it, time_end);
2460
2461 if(len < 8) return false;
2462
2463 if(it[2] != ':' || it[5] != ':') return false;
2464
2465 if(len > 8) return it[8] == '.' && len > 9;
2466
2467 return true;
2468 }

◆ operator=()

parser & cpptoml::parser::operator= ( const parser parser)
delete

◆ parse()

std::shared_ptr< table > cpptoml::parser::parse ( )
inline

Parses the stream this parser was created on until EOF.

Exceptions
parse_exceptionif there are errors in parsing

Definition at line 1561 of file cpptoml.h.

1561 {
1562 std::shared_ptr<table> root = make_table();
1563
1564 table* curr_table = root.get();
1565
1566 while(detail::getline(input_, line_)) {
1567 line_number_++;
1568 auto it = line_.begin();
1569 auto end = line_.end();
1570 consume_whitespace(it, end);
1571 if(it == end || *it == '#') continue;
1572 if(*it == '[') {
1573 curr_table = root.get();
1574 parse_table(it, end, curr_table);
1575 } else {
1576 parse_key_value(it, end, curr_table);
1577 consume_whitespace(it, end);
1578 eol_or_comment(it, end);
1579 }
1580 }
1581 return root;
1582 }
void parse_key_value(std::string::iterator &it, std::string::iterator &end, table *curr_table)
Definition: cpptoml.h:1733
static void consume_whitespace(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2442
void parse_table(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
Definition: cpptoml.h:1594
void eol_or_comment(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2452
std::string line_
Definition: cpptoml.h:2494
std::istream & getline(std::istream &input, std::string &line)
Definition: cpptoml.h:1519
std::shared_ptr< table > make_table()
Definition: cpptoml.h:1417

◆ parse_array()

std::shared_ptr< base > cpptoml::parser::parse_array ( std::string::iterator &  it,
std::string::iterator &  end 
)
inlineprivate

Definition at line 2325 of file cpptoml.h.

2325 {
2326 // this gets ugly because of the "homogeneity" restriction:
2327 // arrays can either be of only one type, or contain arrays
2328 // (each of those arrays could be of different types, though)
2329 //
2330 // because of the latter portion, we don't really have a choice
2331 // but to represent them as arrays of base values...
2332 ++it;
2333
2334 // ugh---have to read the first value to determine array type...
2336
2337 // edge case---empty array
2338 if(*it == ']') {
2339 ++it;
2340 return make_array();
2341 }
2342
2343 auto val_end = std::find_if(it, end, [](char c) { return c == ',' || c == ']' || c == '#'; });
2344 parse_type type = determine_value_type(it, val_end);
2345 switch(type) {
2346 case parse_type::STRING:
2347 return parse_value_array<std::string>(it, end);
2349 return parse_value_array<local_time>(it, end);
2351 return parse_value_array<local_date>(it, end);
2353 return parse_value_array<local_datetime>(it, end);
2355 return parse_value_array<offset_datetime>(it, end);
2356 case parse_type::INT:
2357 return parse_value_array<int64_t>(it, end);
2358 case parse_type::FLOAT:
2359 return parse_value_array<double>(it, end);
2360 case parse_type::BOOL:
2361 return parse_value_array<MBool>(it, end);
2362 case parse_type::ARRAY:
2363 return parse_object_array<array>(&parser::parse_array, '[', it, end);
2365 return parse_object_array<table_array>(&parser::parse_inline_table, '{', it, end);
2366 default:
2367 throw_parse_exception("Unable to parse array");
2368 }
2369 }
std::shared_ptr< base > parse_array(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:2325
std::shared_ptr< table > parse_inline_table(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:2412
void skip_whitespace_and_comments(std::string::iterator &start, std::string::iterator &end)
Definition: cpptoml.h:2431
parse_type determine_value_type(const std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:1873
std::shared_ptr< array > make_array()
Definition: cpptoml.h:873

◆ parse_bare_key()

std::string cpptoml::parser::parse_bare_key ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 1808 of file cpptoml.h.

1808 {
1809 if(it == end) {
1810 throw_parse_exception("Bare key missing name");
1811 }
1812
1813 auto key_end = end;
1814 --key_end;
1815 consume_backwards_whitespace(key_end, it);
1816 ++key_end;
1817 std::string key{it, key_end};
1818
1819 if(std::find(it, key_end, '#') != key_end) {
1820 throw_parse_exception("Bare key " + key + " cannot contain #");
1821 }
1822
1823 if(std::find_if(it, key_end, [](char c) { return c == ' ' || c == '\t'; }) != key_end) {
1824 throw_parse_exception("Bare key " + key + " cannot contain whitespace");
1825 }
1826
1827 if(std::find_if(it, key_end, [](char c) { return c == '[' || c == ']'; }) != key_end) {
1828 throw_parse_exception("Bare key " + key + " cannot contain '[' or ']'");
1829 }
1830
1831 it = end;
1832 return key;
1833 }
static void consume_backwards_whitespace(std::string::iterator &back, const std::string::iterator &front)
Definition: cpptoml.h:2447

◆ parse_bool()

std::shared_ptr< value< MBool > > cpptoml::parser::parse_bool ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2218 of file cpptoml.h.

2218 {
2219 auto eat = make_consumer(it, end, [this]() { throw_parse_exception("Attempted to parse invalid boolean value"); });
2220
2221 if(*it == 't') {
2222 eat("true");
2223 return make_value<MBool>(true);
2224 } else if(*it == 'f') {
2225 eat("false");
2226 return make_value<MBool>(false);
2227 }
2228
2229 eat.error();
2230 return nullptr;
2231 }
consumer< OnError > make_consumer(std::string::iterator &it, const std::string::iterator &end, OnError &&on_error)
Definition: cpptoml.h:1512

◆ parse_date()

std::shared_ptr< base > cpptoml::parser::parse_date ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2280 of file cpptoml.h.

2280 {
2281 auto date_end = find_end_of_date(it, end);
2282
2283 auto eat = make_consumer(it, date_end, [&]() { throw_parse_exception("Malformed date"); });
2284
2285 local_date ldate;
2286 ldate.year = eat.eat_digits(4);
2287 eat('-');
2288 ldate.month = eat.eat_digits(2);
2289 eat('-');
2290 ldate.day = eat.eat_digits(2);
2291
2292 if(it == date_end) return make_value(ldate);
2293
2294 eat('T');
2295
2296 local_datetime ldt;
2297 static_cast<local_date&>(ldt) = ldate;
2298 static_cast<local_time&>(ldt) = read_time(it, date_end);
2299
2300 if(it == date_end) return make_value(ldt);
2301
2302 offset_datetime dt;
2303 static_cast<local_datetime&>(dt) = ldt;
2304
2305 int hoff = 0;
2306 int moff = 0;
2307 if(*it == '+' || *it == '-') {
2308 auto plus = *it == '+';
2309 ++it;
2310
2311 hoff = eat.eat_digits(2);
2312 dt.hour_offset = (plus) ? hoff : -hoff;
2313 eat(':');
2314 moff = eat.eat_digits(2);
2315 dt.minute_offset = (plus) ? moff : -moff;
2316 } else if(*it == 'Z') {
2317 ++it;
2318 }
2319
2320 if(it != date_end) throw_parse_exception("Malformed date");
2321
2322 return make_value(dt);
2323 }
local_time read_time(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2249
std::shared_ptr< typename value_traits< T >::type > make_value(T &&val)
Definition: cpptoml.h:588

◆ parse_escape_code()

std::string cpptoml::parser::parse_escape_code ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2019 of file cpptoml.h.

2019 {
2020 ++it;
2021 if(it == end) throw_parse_exception("Invalid escape sequence");
2022 char value;
2023 if(*it == 'b') {
2024 value = '\b';
2025 } else if(*it == 't') {
2026 value = '\t';
2027 } else if(*it == 'n') {
2028 value = '\n';
2029 } else if(*it == 'f') {
2030 value = '\f';
2031 } else if(*it == 'r') {
2032 value = '\r';
2033 } else if(*it == '"') {
2034 value = '"';
2035 } else if(*it == '\\') {
2036 value = '\\';
2037 } else if(*it == 'u' || *it == 'U') {
2038 return parse_unicode(it, end);
2039 } else {
2040 throw_parse_exception("Invalid escape sequence");
2041 }
2042 ++it;
2043 return std::string(1, value);
2044 }
std::string parse_unicode(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2046

◆ parse_float()

std::shared_ptr< value< double > > cpptoml::parser::parse_float ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2197 of file cpptoml.h.

2197 {
2198 std::string v{it, end};
2199 v.erase(std::remove(v.begin(), v.end(), '_'), v.end());
2200 it = end;
2201 char decimal_point = std::localeconv()->decimal_point[0];
2202 std::replace(v.begin(), v.end(), '.', decimal_point);
2203#ifndef CPPTOML_NO_EXCEPTIONS
2204 try
2205#endif
2206 {
2207 return make_value<double>(std::stod(v));
2208 }
2209#ifndef CPPTOML_NO_EXCEPTIONS
2210 catch(const std::invalid_argument& ex) {
2211 throw_parse_exception("Malformed number (invalid argument: " + std::string{ex.what()} + ")");
2212 } catch(const std::out_of_range& ex) {
2213 throw_parse_exception("Malformed number (out of range: " + std::string{ex.what()} + ")");
2214 }
2215#endif
2216 }

◆ parse_hex()

uint32_t cpptoml::parser::parse_hex ( std::string::iterator &  it,
const std::string::iterator &  end,
uint32_t  place 
)
inlineprivate

Definition at line 2098 of file cpptoml.h.

2098 {
2099 uint32_t value = 0;
2100 while(place > 0) {
2101 if(it == end) throw_parse_exception("Unexpected end of unicode sequence");
2102
2103 if(!is_hex(*it)) throw_parse_exception("Invalid unicode escape sequence");
2104
2105 value += place * hex_to_digit(*it++);
2106 place /= 16;
2107 }
2108 return value;
2109 }
static MBool is_hex(char c)
Definition: cpptoml.h:2111
static uint32_t hex_to_digit(char c)
Definition: cpptoml.h:2113

◆ parse_inline_table()

std::shared_ptr< table > cpptoml::parser::parse_inline_table ( std::string::iterator &  it,
std::string::iterator &  end 
)
inlineprivate

Definition at line 2412 of file cpptoml.h.

2412 {
2413 auto tbl = make_table();
2414 do {
2415 ++it;
2416 if(it == end) throw_parse_exception("Unterminated inline table");
2417
2418 consume_whitespace(it, end);
2419 parse_key_value(it, end, tbl.get());
2420 consume_whitespace(it, end);
2421 } while(*it == ',');
2422
2423 if(it == end || *it != '}') throw_parse_exception("Unterminated inline table");
2424
2425 ++it;
2426 consume_whitespace(it, end);
2427
2428 return tbl;
2429 }

◆ parse_int()

std::shared_ptr< value< int64_t > > cpptoml::parser::parse_int ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2178 of file cpptoml.h.

2178 {
2179 std::string v{it, end};
2180 v.erase(std::remove(v.begin(), v.end(), '_'), v.end());
2181 it = end;
2182#ifndef CPPTOML_NO_EXCEPTIONS
2183 try
2184#endif
2185 {
2186 return make_value<int64_t>(std::stoll(v));
2187 }
2188#ifndef CPPTOML_NO_EXCEPTIONS
2189 catch(const std::invalid_argument& ex) {
2190 throw_parse_exception("Malformed number (invalid argument: " + std::string{ex.what()} + ")");
2191 } catch(const std::out_of_range& ex) {
2192 throw_parse_exception("Malformed number (out of range: " + std::string{ex.what()} + ")");
2193 }
2194#endif
2195 }

◆ parse_key()

template<class KeyEndFinder , class KeyPartHandler >
std::string cpptoml::parser::parse_key ( std::string::iterator &  it,
const std::string::iterator &  end,
KeyEndFinder &&  key_end,
KeyPartHandler &&  key_part_handler 
)
inlineprivate

Definition at line 1765 of file cpptoml.h.

1766 {
1767 // parse the key as a series of one or more simple-keys joined with '.'
1768 while(it != end && !key_end(*it)) {
1769 auto part = parse_simple_key(it, end);
1770 consume_whitespace(it, end);
1771
1772 if(it == end || key_end(*it)) {
1773 return part;
1774 }
1775
1776 if(*it != '.') {
1777 std::string errmsg{"Unexpected character in key: "};
1778 errmsg += '"';
1779 errmsg += *it;
1780 errmsg += '"';
1781 throw_parse_exception(errmsg);
1782 }
1783
1784 key_part_handler(part);
1785
1786 // consume the dot
1787 ++it;
1788 }
1789
1790 throw_parse_exception("Unexpected end of key");
1791 }
std::string parse_simple_key(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:1793

◆ parse_key_value()

void cpptoml::parser::parse_key_value ( std::string::iterator &  it,
std::string::iterator &  end,
table curr_table 
)
inlineprivate

Definition at line 1733 of file cpptoml.h.

1733 {
1734 auto key_end = [](char c) { return c == '='; };
1735
1736 auto key_part_handler = [&](const std::string& part) {
1737 // two cases: this key part exists already, in which case it must
1738 // be a table, or it doesn't exist in which case we must create
1739 // an implicitly defined table
1740 if(curr_table->contains(part)) {
1741 auto val = curr_table->get(part);
1742 if(val->is_table()) {
1743 curr_table = static_cast<table*>(val.get());
1744 } else {
1745 throw_parse_exception("Key " + part + " already exists as a value");
1746 }
1747 } else {
1748 auto newtable = make_table();
1749 curr_table->insert(part, newtable);
1750 curr_table = newtable.get();
1751 }
1752 };
1753
1754 auto key = parse_key(it, end, key_end, key_part_handler);
1755
1756 if(curr_table->contains(key)) throw_parse_exception("Key " + key + " already present");
1757 if(it == end || *it != '=') throw_parse_exception("Value must follow after a '='");
1758 ++it;
1759 consume_whitespace(it, end);
1760 curr_table->insert(key, parse_value(it, end));
1761 consume_whitespace(it, end);
1762 }
std::shared_ptr< base > parse_value(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:1848
std::string parse_key(std::string::iterator &it, const std::string::iterator &end, KeyEndFinder &&key_end, KeyPartHandler &&key_part_handler)
Definition: cpptoml.h:1765

◆ parse_multiline_string()

std::shared_ptr< value< std::string > > cpptoml::parser::parse_multiline_string ( std::string::iterator &  it,
std::string::iterator &  end,
char  delim 
)
inlineprivate

Definition at line 1929 of file cpptoml.h.

1930 {
1931 std::stringstream ss;
1932
1933 auto is_ws = [](char c) { return c == ' ' || c == '\t'; };
1934
1935 MBool consuming = false;
1936 std::shared_ptr<value<std::string>> ret;
1937
1938 auto handle_line = [&](std::string::iterator& local_it, std::string::iterator& local_end) {
1939 if(consuming) {
1940 local_it = std::find_if_not(local_it, local_end, is_ws);
1941
1942 // whole line is whitespace
1943 if(local_it == local_end) return;
1944 }
1945
1946 consuming = false;
1947
1948 while(local_it != local_end) {
1949 // handle escaped characters
1950 if(delim == '"' && *local_it == '\\') {
1951 auto check = local_it;
1952 // check if this is an actual escape sequence or a
1953 // whitespace escaping backslash
1954 ++check;
1955 consume_whitespace(check, local_end);
1956 if(check == local_end) {
1957 consuming = true;
1958 break;
1959 }
1960
1961 ss << parse_escape_code(local_it, local_end);
1962 continue;
1963 }
1964
1965 // if we can end the string
1966 if(std::distance(local_it, local_end) >= 3) {
1967 auto check = local_it;
1968 // check for """
1969 if(*check++ == delim && *check++ == delim && *check++ == delim) {
1970 local_it = check;
1971 ret = make_value<std::string>(ss.str());
1972 break;
1973 }
1974 }
1975
1976 ss << *local_it++;
1977 }
1978 };
1979
1980 // handle the remainder of the current line
1981 handle_line(it, end);
1982 if(ret) return ret;
1983
1984 // start eating lines
1985 while(detail::getline(input_, line_)) {
1986 ++line_number_;
1987
1988 it = line_.begin();
1989 end = line_.end();
1990
1991 handle_line(it, end);
1992
1993 if(ret) return ret;
1994
1995 if(!consuming) ss << std::endl;
1996 }
1997
1998 throw_parse_exception("Unterminated multi-line basic string");
1999 }
std::string parse_escape_code(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2019
bool MBool
Definition: maiatypes.h:58

◆ parse_number()

std::shared_ptr< base > cpptoml::parser::parse_number ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2118 of file cpptoml.h.

2118 {
2119 auto check_it = it;
2120 auto check_end = find_end_of_number(it, end);
2121
2122 auto eat_sign = [&]() {
2123 if(check_it != end && (*check_it == '-' || *check_it == '+')) ++check_it;
2124 };
2125
2126 eat_sign();
2127
2128 auto eat_numbers = [&]() {
2129 auto beg = check_it;
2130 while(check_it != end && is_number(*check_it)) {
2131 ++check_it;
2132 if(check_it != end && *check_it == '_') {
2133 ++check_it;
2134 if(check_it == end || !is_number(*check_it)) throw_parse_exception("Malformed number");
2135 }
2136 }
2137
2138 if(check_it == beg) throw_parse_exception("Malformed number");
2139 };
2140
2141 auto check_no_leading_zero = [&]() {
2142 if(check_it != end && *check_it == '0' && check_it + 1 != check_end && check_it[1] != '.') {
2143 throw_parse_exception("Numbers may not have leading zeros");
2144 }
2145 };
2146
2147 check_no_leading_zero();
2148 eat_numbers();
2149
2150 if(check_it != end && (*check_it == '.' || *check_it == 'e' || *check_it == 'E')) {
2151 MBool is_exp = *check_it == 'e' || *check_it == 'E';
2152
2153 ++check_it;
2154 if(check_it == end) throw_parse_exception("Floats must have trailing digits");
2155
2156 auto eat_exp = [&]() {
2157 eat_sign();
2158 check_no_leading_zero();
2159 eat_numbers();
2160 };
2161
2162 if(is_exp)
2163 eat_exp();
2164 else
2165 eat_numbers();
2166
2167 if(!is_exp && check_it != end && (*check_it == 'e' || *check_it == 'E')) {
2168 ++check_it;
2169 eat_exp();
2170 }
2171
2172 return parse_float(it, check_it);
2173 } else {
2174 return parse_int(it, check_it);
2175 }
2176 }
std::shared_ptr< value< double > > parse_float(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2197
static std::string::iterator find_end_of_number(std::string::iterator it, std::string::iterator end)
Definition: cpptoml.h:2233
std::shared_ptr< value< int64_t > > parse_int(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2178

◆ parse_object_array()

template<class Object , class Function >
std::shared_ptr< Object > cpptoml::parser::parse_object_array ( Function &&  fun,
char  delim,
std::string::iterator &  it,
std::string::iterator &  end 
)
inlineprivate

Definition at line 2390 of file cpptoml.h.

2391 {
2392 auto arr = make_element<Object>();
2393
2394 while(it != end && *it != ']') {
2395 if(*it != delim) throw_parse_exception("Unexpected character in array");
2396
2397 arr->get().push_back(((*this).*fun)(it, end));
2399
2400 if(*it != ',') break;
2401
2402 ++it;
2404 }
2405
2406 if(it == end || *it != ']') throw_parse_exception("Unterminated array");
2407
2408 ++it;
2409 return arr;
2410 }

◆ parse_simple_key()

std::string cpptoml::parser::parse_simple_key ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 1793 of file cpptoml.h.

1793 {
1794 consume_whitespace(it, end);
1795
1796
1797 if(it == end) throw_parse_exception("Unexpected end of key (blank key?)");
1798
1799 if(*it == '"' || *it == '\'') {
1800 return string_literal(it, end, *it);
1801 } else {
1802 auto bke = std::find_if(it, end, [](char c) { return c == '.' || c == '=' || c == ']'; });
1803 return parse_bare_key(it, bke);
1804 }
1805 }
std::string parse_bare_key(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:1808
std::string string_literal(std::string::iterator &it, const std::string::iterator &end, char delim)
Definition: cpptoml.h:2001

◆ parse_single_table()

void cpptoml::parser::parse_single_table ( std::string::iterator &  it,
const std::string::iterator &  end,
table *&  curr_table 
)
inlineprivate

Definition at line 1604 of file cpptoml.h.

1604 {
1605 if(it == end || *it == ']') throw_parse_exception("Table name cannot be empty");
1606
1607 std::string full_table_name;
1608 MBool inserted = false;
1609
1610 auto key_end = [](char c) { return c == ']'; };
1611
1612 auto key_part_handler = [&](const std::string& part) {
1613 if(part.empty()) throw_parse_exception("Empty component of table name");
1614
1615 if(!full_table_name.empty()) full_table_name += '.';
1616 full_table_name += part;
1617
1618 if(curr_table->contains(part)) {
1619 // Necessary fix for PGI compiler
1620 // auto b = curr_table->get(part);
1621 std::shared_ptr<base> b = curr_table->get(part);
1622 if(b->is_table())
1623 curr_table = static_cast<table*>(b.get());
1624 else if(b->is_table_array())
1625 curr_table = std::static_pointer_cast<table_array>(b)->get().back().get();
1626 else
1627 throw_parse_exception("Key " + full_table_name + "already exists as a value");
1628 } else {
1629 inserted = true;
1630 curr_table->insert(part, make_table());
1631 curr_table = static_cast<table*>(curr_table->get(part).get());
1632 }
1633 };
1634
1635 key_part_handler(parse_key(it, end, key_end, key_part_handler));
1636
1637 if(it == end) throw_parse_exception("Unterminated table declaration; did you forget a ']'?");
1638
1639 if(*it != ']') {
1640 std::string errmsg{"Unexpected character in table definition: "};
1641 errmsg += '"';
1642 errmsg += *it;
1643 errmsg += '"';
1644 throw_parse_exception(errmsg);
1645 }
1646
1647 // table already existed
1648 if(!inserted) {
1649 auto is_value = [](const std::pair<const std::string&, const std::shared_ptr<base>&>& p) {
1650 return p.second->is_value();
1651 };
1652
1653 // if there are any values, we can't add values to this table
1654 // since it has already been defined. If there aren't any
1655 // values, then it was implicitly created by something like
1656 // [a.b]
1657 if(curr_table->empty() || std::any_of(curr_table->begin(), curr_table->end(), is_value)) {
1658 throw_parse_exception("Redefinition of table " + full_table_name);
1659 }
1660 }
1661
1662 ++it;
1663 consume_whitespace(it, end);
1664 eol_or_comment(it, end);
1665 }
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.

◆ parse_string()

std::shared_ptr< value< std::string > > cpptoml::parser::parse_string ( std::string::iterator &  it,
std::string::iterator &  end 
)
inlineprivate

Definition at line 1911 of file cpptoml.h.

1911 {
1912 auto delim = *it;
1913 assert(delim == '"' || delim == '\'');
1914
1915 // end is non-const here because we have to be able to potentially
1916 // parse multiple lines in a string, not just one
1917 auto check_it = it;
1918 ++check_it;
1919 if(check_it != end && *check_it == delim) {
1920 ++check_it;
1921 if(check_it != end && *check_it == delim) {
1922 it = ++check_it;
1923 return parse_multiline_string(it, end, delim);
1924 }
1925 }
1926 return make_value<std::string>(string_literal(it, end, delim));
1927 }
std::shared_ptr< value< std::string > > parse_multiline_string(std::string::iterator &it, std::string::iterator &end, char delim)
Definition: cpptoml.h:1929

◆ parse_table()

void cpptoml::parser::parse_table ( std::string::iterator &  it,
const std::string::iterator &  end,
table *&  curr_table 
)
inlineprivate

Definition at line 1594 of file cpptoml.h.

1594 {
1595 // remove the beginning keytable marker
1596 ++it;
1597 if(it == end) throw_parse_exception("Unexpected end of table");
1598 if(*it == '[')
1599 parse_table_array(it, end, curr_table);
1600 else
1601 parse_single_table(it, end, curr_table);
1602 }
void parse_single_table(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
Definition: cpptoml.h:1604
void parse_table_array(std::string::iterator &it, const std::string::iterator &end, table *&curr_table)
Definition: cpptoml.h:1667

◆ parse_table_array()

void cpptoml::parser::parse_table_array ( std::string::iterator &  it,
const std::string::iterator &  end,
table *&  curr_table 
)
inlineprivate

Definition at line 1667 of file cpptoml.h.

1667 {
1668 ++it;
1669 if(it == end || *it == ']') throw_parse_exception("Table array name cannot be empty");
1670
1671 auto key_end = [](char c) { return c == ']'; };
1672
1673
1674 std::string full_ta_name;
1675 auto key_part_handler = [&](const std::string& part) {
1676 if(part.empty()) throw_parse_exception("Empty component of table array name");
1677
1678 if(!full_ta_name.empty()) full_ta_name += '.';
1679 full_ta_name += part;
1680
1681 if(curr_table->contains(part)) {
1682 // Necessary fix for PGI compiler
1683 // auto b = curr_table->get(part);
1684 std::shared_ptr<base> b = curr_table->get(part);
1685
1686 // if this is the end of the table array name, add an
1687 // element to the table array that we just looked up
1688 if(it != end && *it == ']') {
1689 if(!b->is_table_array()) throw_parse_exception("Key " + full_ta_name + " is not a table array");
1690 auto v = b->as_table_array();
1691 v->get().push_back(make_table());
1692 curr_table = v->get().back().get();
1693 }
1694 // otherwise, just keep traversing down the key name
1695 else {
1696 if(b->is_table())
1697 curr_table = static_cast<table*>(b.get());
1698 else if(b->is_table_array())
1699 curr_table = std::static_pointer_cast<table_array>(b)->get().back().get();
1700 else
1701 throw_parse_exception("Key " + full_ta_name + " already exists as a value");
1702 }
1703 } else {
1704 // if this is the end of the table array name, add a new
1705 // table array and a new table inside that array for us to
1706 // add keys to next
1707 if(it != end && *it == ']') {
1708 curr_table->insert(part, make_table_array());
1709 auto arr = std::static_pointer_cast<table_array>(curr_table->get(part));
1710 arr->get().push_back(make_table());
1711 curr_table = arr->get().back().get();
1712 }
1713 // otherwise, create the implicitly defined table and move
1714 // down to it
1715 else {
1716 curr_table->insert(part, make_table());
1717 curr_table = static_cast<table*>(curr_table->get(part).get());
1718 }
1719 }
1720 };
1721
1722 key_part_handler(parse_key(it, end, key_end, key_part_handler));
1723
1724 // consume the last "]]"
1725 auto eat = make_consumer(it, end, [this]() { throw_parse_exception("Unterminated table array name"); });
1726 eat(']');
1727 eat(']');
1728
1729 consume_whitespace(it, end);
1730 eol_or_comment(it, end);
1731 }
std::shared_ptr< table_array > make_table_array()
Definition: cpptoml.h:999

◆ parse_time()

std::shared_ptr< value< local_time > > cpptoml::parser::parse_time ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2276 of file cpptoml.h.

2276 {
2277 return make_value(read_time(it, end));
2278 }

◆ parse_unicode()

std::string cpptoml::parser::parse_unicode ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2046 of file cpptoml.h.

2046 {
2047 MBool large = *it++ == 'U';
2048 auto codepoint = parse_hex(it, end, large ? 0x10000000 : 0x1000);
2049
2050 if((codepoint > 0xd7ff && codepoint < 0xe000) || codepoint > 0x10ffff) {
2051 throw_parse_exception("Unicode escape sequence is not a Unicode scalar value");
2052 }
2053
2054 std::string result;
2055 // See Table 3-6 of the Unicode standard
2056 if(codepoint <= 0x7f) {
2057 // 1-byte codepoints: 00000000 0xxxxxxx
2058 // repr: 0xxxxxxx
2059 result += static_cast<char>(codepoint & 0x7f);
2060 } else if(codepoint <= 0x7ff) {
2061 // 2-byte codepoints: 00000yyy yyxxxxxx
2062 // repr: 110yyyyy 10xxxxxx
2063 //
2064 // 0x1f = 00011111
2065 // 0xc0 = 11000000
2066 //
2067 result += static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f));
2068 //
2069 // 0x80 = 10000000
2070 // 0x3f = 00111111
2071 //
2072 result += static_cast<char>(0x80 | (codepoint & 0x3f));
2073 } else if(codepoint <= 0xffff) {
2074 // 3-byte codepoints: zzzzyyyy yyxxxxxx
2075 // repr: 1110zzzz 10yyyyyy 10xxxxxx
2076 //
2077 // 0xe0 = 11100000
2078 // 0x0f = 00001111
2079 //
2080 result += static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f));
2081 result += static_cast<char>(0x80 | ((codepoint >> 6) & 0x1f));
2082 result += static_cast<char>(0x80 | (codepoint & 0x3f));
2083 } else {
2084 // 4-byte codepoints: 000uuuuu zzzzyyyy yyxxxxxx
2085 // repr: 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
2086 //
2087 // 0xf0 = 11110000
2088 // 0x07 = 00000111
2089 //
2090 result += static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07));
2091 result += static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f));
2092 result += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f));
2093 result += static_cast<char>(0x80 | (codepoint & 0x3f));
2094 }
2095 return result;
2096 }
uint32_t parse_hex(std::string::iterator &it, const std::string::iterator &end, uint32_t place)
Definition: cpptoml.h:2098

◆ parse_value()

std::shared_ptr< base > cpptoml::parser::parse_value ( std::string::iterator &  it,
std::string::iterator &  end 
)
inlineprivate

Definition at line 1848 of file cpptoml.h.

1848 {
1849 parse_type type = determine_value_type(it, end);
1850 switch(type) {
1851 case parse_type::STRING:
1852 return parse_string(it, end);
1854 return parse_time(it, end);
1858 return parse_date(it, end);
1859 case parse_type::INT:
1860 case parse_type::FLOAT:
1861 return parse_number(it, end);
1862 case parse_type::BOOL:
1863 return parse_bool(it, end);
1864 case parse_type::ARRAY:
1865 return parse_array(it, end);
1867 return parse_inline_table(it, end);
1868 default:
1869 throw_parse_exception("Failed to parse value");
1870 }
1871 }
std::shared_ptr< value< local_time > > parse_time(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2276
std::shared_ptr< base > parse_date(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2280
std::shared_ptr< value< std::string > > parse_string(std::string::iterator &it, std::string::iterator &end)
Definition: cpptoml.h:1911
std::shared_ptr< base > parse_number(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2118
std::shared_ptr< value< MBool > > parse_bool(std::string::iterator &it, const std::string::iterator &end)
Definition: cpptoml.h:2218

◆ parse_value_array()

template<class Value >
std::shared_ptr< array > cpptoml::parser::parse_value_array ( std::string::iterator &  it,
std::string::iterator &  end 
)
inlineprivate

Definition at line 2372 of file cpptoml.h.

2372 {
2373 auto arr = make_array();
2374 while(it != end && *it != ']') {
2375 auto val = parse_value(it, end);
2376 if(auto v = val->as<Value>())
2377 arr->get().push_back(val);
2378 else
2379 throw_parse_exception("Arrays must be homogeneous");
2381 if(*it != ',') break;
2382 ++it;
2384 }
2385 if(it != end) ++it;
2386 return arr;
2387 }

◆ read_time()

local_time cpptoml::parser::read_time ( std::string::iterator &  it,
const std::string::iterator &  end 
)
inlineprivate

Definition at line 2249 of file cpptoml.h.

2249 {
2250 auto time_end = find_end_of_time(it, end);
2251
2252 auto eat = make_consumer(it, time_end, [&]() { throw_parse_exception("Malformed time"); });
2253
2254 local_time ltime;
2255
2256 ltime.hour = eat.eat_digits(2);
2257 eat(':');
2258 ltime.minute = eat.eat_digits(2);
2259 eat(':');
2260 ltime.second = eat.eat_digits(2);
2261
2262 int power = 100000;
2263 if(it != time_end && *it == '.') {
2264 ++it;
2265 while(it != time_end && is_number(*it)) {
2266 ltime.microsecond += power * (*it++ - '0');
2267 power /= 10;
2268 }
2269 }
2270
2271 if(it != time_end) throw_parse_exception("Malformed time");
2272
2273 return ltime;
2274 }

◆ skip_whitespace_and_comments()

void cpptoml::parser::skip_whitespace_and_comments ( std::string::iterator &  start,
std::string::iterator &  end 
)
inlineprivate

Definition at line 2431 of file cpptoml.h.

2431 {
2432 consume_whitespace(start, end);
2433 while(start == end || *start == '#') {
2434 if(!detail::getline(input_, line_)) throw_parse_exception("Unclosed array");
2435 line_number_++;
2436 start = line_.begin();
2437 end = line_.end();
2438 consume_whitespace(start, end);
2439 }
2440 }

◆ string_literal()

std::string cpptoml::parser::string_literal ( std::string::iterator &  it,
const std::string::iterator &  end,
char  delim 
)
inlineprivate

Definition at line 2001 of file cpptoml.h.

2001 {
2002 ++it;
2003 std::string val;
2004 while(it != end) {
2005 // handle escaped characters
2006 if(delim == '"' && *it == '\\') {
2007 val += parse_escape_code(it, end);
2008 } else if(*it == delim) {
2009 ++it;
2010 consume_whitespace(it, end);
2011 return val;
2012 } else {
2013 val += *it++;
2014 }
2015 }
2016 throw_parse_exception("Unterminated string literal");
2017 }

Member Data Documentation

◆ input_

std::istream& cpptoml::parser::input_
private

Definition at line 2493 of file cpptoml.h.

◆ line_

std::string cpptoml::parser::line_
private

Definition at line 2494 of file cpptoml.h.

◆ line_number_

std::size_t cpptoml::parser::line_number_ = 0
private

Definition at line 2495 of file cpptoml.h.


The documentation for this class was generated from the following file: