Skip to content

Commit 5caeb32

Browse files
committed
test
1 parent fededad commit 5caeb32

File tree

1 file changed

+143
-8
lines changed

1 file changed

+143
-8
lines changed

include/cpptoml.h

Lines changed: 143 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,8 +2310,7 @@ class parser
23102310
}
23112311
}
23122312

2313-
parse_type determine_value_type(const std::string::iterator& it,
2314-
const std::string::iterator& end)
2313+
parse_type determine_value_type(const std::string::iterator& it, const std::string::iterator& end)
23152314
{
23162315
if (it == end)
23172316
{
@@ -2352,8 +2351,7 @@ class parser
23522351
throw_parse_exception("Failed to parse value type");
23532352
}
23542353

2355-
parse_type determine_number_type(const std::string::iterator& it,
2356-
const std::string::iterator& end)
2354+
parse_type determine_number_type(const std::string::iterator& it, const std::string::iterator& end)
23572355
{
23582356
// determine if we are an integer or a float
23592357
auto check_it = it;
@@ -2368,7 +2366,7 @@ class parser
23682366

23692367
while (check_it != end && is_number(*check_it))
23702368
++check_it;
2371-
if (check_it != end && *check_it == '.')
2369+
if (check_it != end && (*check_it == '.' || *check_it == 'e' || *check_it == 'E'))
23722370
{
23732371
++check_it;
23742372
while (check_it != end && is_number(*check_it))
@@ -2381,8 +2379,7 @@ class parser
23812379
}
23822380
}
23832381

2384-
std::shared_ptr<value<std::string>> parse_string(std::string::iterator& it,
2385-
std::string::iterator& end)
2382+
std::shared_ptr<value<std::string>> parse_string(std::string::iterator& it, std::string::iterator& end)
23862383
{
23872384
auto delim = *it;
23882385
assert(delim == '"' || delim == '\'');
@@ -2400,9 +2397,87 @@ class parser
24002397
return parse_multiline_string(it, end, delim);
24012398
}
24022399
}
2400+
// Check for raw string
2401+
else if (delim == '"' && check_it != end && *check_it == '#')
2402+
{
2403+
return parse_raw_string(it, end);
2404+
}
24032405
return make_value<std::string>(string_literal(it, end, delim));
24042406
}
24052407

2408+
std::shared_ptr<value<std::string>>
2409+
parse_raw_string(std::string::iterator& it, std::string::iterator& end)
2410+
{
2411+
// Skip the opening "
2412+
++it;
2413+
2414+
// Count the number of # characters
2415+
size_t hash_count = 0;
2416+
while (it != end && *it == '#')
2417+
{
2418+
++hash_count;
2419+
++it;
2420+
}
2421+
2422+
if (it == end)
2423+
throw_parse_exception("Unterminated raw string");
2424+
2425+
std::stringstream ss;
2426+
2427+
// Handle the remainder of the current line
2428+
auto handle_line = [&](std::string::iterator& local_it, std::string::iterator& local_end)
2429+
{
2430+
while (local_it != local_end)
2431+
{
2432+
// Check if we've reached the end of the raw string
2433+
if (std::distance(local_it, local_end) >= hash_count + 1)
2434+
{
2435+
bool found = true;
2436+
auto check = local_it;
2437+
for (size_t i = 0; i < hash_count; ++i)
2438+
{
2439+
if (*check++ != '#')
2440+
{
2441+
found = false;
2442+
break;
2443+
}
2444+
}
2445+
if (found && *check == '"')
2446+
{
2447+
local_it = check + 1;
2448+
return true; // End of raw string
2449+
}
2450+
}
2451+
2452+
ss << *local_it++;
2453+
}
2454+
return false; // Not end of raw string
2455+
};
2456+
2457+
// Handle the current line
2458+
bool done = handle_line(it, end);
2459+
if (done)
2460+
return make_value<std::string>(ss.str());
2461+
2462+
// Start eating lines
2463+
while (detail::getline(input_, line_))
2464+
{
2465+
++line_number_;
2466+
2467+
it = line_.begin();
2468+
end = line_.end();
2469+
2470+
done = handle_line(it, end);
2471+
if (done)
2472+
return make_value<std::string>(ss.str());
2473+
2474+
// Add the newline
2475+
ss << std::endl;
2476+
}
2477+
2478+
throw_parse_exception("Unterminated raw string");
2479+
}
2480+
24062481
std::shared_ptr<value<std::string>>
24072482
parse_multiline_string(std::string::iterator& it,
24082483
std::string::iterator& end, char delim)
@@ -3214,7 +3289,7 @@ class parser
32143289

32153290
/**
32163291
* Utility function to parse a file as a TOML file. Returns the root table.
3217-
* Throws a parse_exception if the file cannot be opened.
3292+
* Throws a parse_exception if the file cannot be opened or parsed.
32183293
*/
32193294
inline std::shared_ptr<table> parse_file(const std::string& filename)
32203295
{
@@ -3231,6 +3306,66 @@ inline std::shared_ptr<table> parse_file(const std::string& filename)
32313306
return p.parse();
32323307
}
32333308

3309+
/**
3310+
* Utility function to validate a TOML file. Returns true if the file is valid,
3311+
* false otherwise. If validate_only is true, the function will only validate
3312+
* the file without parsing it completely.
3313+
*/
3314+
inline bool validate_file(const std::string& filename, bool validate_only = false)
3315+
{
3316+
try
3317+
{
3318+
#if defined(BOOST_NOWIDE_FSTREAM_INCLUDED_HPP)
3319+
boost::nowide::ifstream file{filename.c_str()};
3320+
#elif defined(NOWIDE_FSTREAM_INCLUDED_HPP)
3321+
nowide::ifstream file{filename.c_str()};
3322+
#else
3323+
std::ifstream file{filename};
3324+
#endif
3325+
if (!file.is_open())
3326+
throw parse_exception{filename + " could not be opened for validation"};
3327+
3328+
parser p{file};
3329+
if (validate_only)
3330+
{
3331+
// Only validate the syntax, not the full parsing
3332+
std::string line;
3333+
while (std::getline(file, line))
3334+
{
3335+
// This is a simple validation, real validation would be more complex
3336+
// For now, just check for basic syntax errors
3337+
size_t comment_pos = line.find('#');
3338+
if (comment_pos != std::string::npos)
3339+
line = line.substr(0, comment_pos);
3340+
3341+
if (!line.empty())
3342+
{
3343+
// Check for valid key-value pairs or table headers
3344+
if (line.find('=') == std::string::npos &&
3345+
line.find('[') == std::string::npos)
3346+
{
3347+
return false;
3348+
}
3349+
}
3350+
}
3351+
}
3352+
else
3353+
{
3354+
// Parse the entire file to validate it
3355+
p.parse();
3356+
}
3357+
return true;
3358+
}
3359+
catch (const parse_exception&)
3360+
{
3361+
return false;
3362+
}
3363+
catch (const std::exception&)
3364+
{
3365+
return false;
3366+
}
3367+
}
3368+
32343369
template <class... Ts>
32353370
struct value_accept;
32363371

0 commit comments

Comments
 (0)