ampsci
c++ program for high-precision atomic structure calculations of single-valence systems
Loading...
Searching...
No Matches
InputBlock.hpp
1#pragma once
2#include "fmt/color.hpp"
3#include "qip/String.hpp" //for case insensitive
4#include <algorithm>
5#include <array>
6#include <chrono>
7#include <fstream>
8#include <iostream>
9#include <istream>
10#include <optional>
11#include <sstream>
12#include <string>
13#include <string_view>
14#include <vector>
15
16namespace IO {
17//==============================================================================
19inline std::string removeSpaces(std::string str);
20
22inline std::string removeQuoteMarks(std::string str);
23
25inline void removeBlockComments(std::string &input);
26
28inline std::string removeComments(const std::string &input);
29
31inline std::string expandIncludes(std::string input);
32
34template <typename T>
35inline T parse_str_to_T(const std::string &value_as_str);
36
38inline std::string file_to_string(const std::istream &file);
39
41template <typename T>
42struct IsVector {
43 constexpr static bool v = false;
44 using t = T;
45};
46template <typename T>
47struct IsVector<std::vector<T>> {
48 constexpr static bool v = true;
49 // nb: returns conatined type of vector
50 using t = T;
51};
52// e.g.:
53// std::cout << std::boolalpha;
54// std::cout << IO::IsVector<int>::v << "\n";
55// std::cout << IO::IsVector<std::vector<int>>::v << "\n";
56// std::cout << IO::IsVector<std::vector<double>>::v << "\n";
57
58template <typename T>
59struct IsArray {
60 constexpr static bool v = false;
61 using t = T;
62 static constexpr std::size_t size = 0;
63};
64template <typename T, std::size_t N>
65struct IsArray<std::array<T, N>> {
66 constexpr static bool v = true;
67 // nb: returns conatined type of array
68 using t = T;
69 static constexpr std::size_t size = N;
70};
71
74inline void print_line(const char c = '*', const int num = 80) {
75 for (int i = 0; i < num; i++)
76 std::cout << c;
77 std::cout << "\n";
78}
79
80//==============================================================================
81inline std::string time_date() {
82 const auto now =
83 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
84 char buffer[30];
85 std::strftime(buffer, 30, "%F %T", localtime(&now));
86 return buffer;
87}
88inline std::string date() {
89 const auto now =
90 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
91 char buffer[30];
92 std::strftime(buffer, 30, "%F", localtime(&now));
93 return buffer;
94}
95inline std::string time() {
96 const auto now =
97 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
98 char buffer[30];
99 std::strftime(buffer, 30, "%T", localtime(&now));
100 return buffer;
101}
102
103//==============================================================================
105struct Option {
106 std::string key;
107 std::string value_str;
108
109 friend bool operator==(Option option, std::string_view tkey) {
110 // return option.key == tkey;
111 return qip::ci_wc_compare(tkey, option.key);
112 }
113 friend bool operator==(std::string_view tkey, Option option) {
114 return option == tkey;
115 }
116 friend bool operator!=(Option option, std::string_view tkey) {
117 return !(option == tkey);
118 }
119 friend bool operator!=(std::string_view tkey, Option option) {
120 return !(option == tkey);
121 }
122};
123
124//==============================================================================
128
139// nb: I sepparate the function implementations below (in the header file) and
140// mark them as inline. This is for readability only, and ensures this file
141// works as a single-file header-only
143private:
144 std::string m_name{};
145 std::vector<Option> m_options{};
146 std::vector<InputBlock> m_blocks{};
147
148public:
151
153 InputBlock(std::string_view name, std::initializer_list<Option> options = {})
154 : m_name(name), m_options(options) {}
155
157 InputBlock(std::string_view name, const std::string &string_input)
158 : m_name(name) {
159 add(string_input);
160 }
161
163 InputBlock(std::string_view name, const std::istream &file) : m_name(name) {
164 add(file_to_string(file));
165 }
166
169 inline void add(InputBlock block, bool merge = false);
170 inline void merge(InputBlock block) { add(block, true); }
172 inline void add(Option option);
173 inline void add(const std::vector<Option> &options);
175 inline void add(const std::string &string, bool merge = false);
176 inline void merge(const std::string &string) { add(string, true); }
177
178 std::string_view name() const { return m_name; }
180 const std::vector<Option> &options() const { return m_options; }
182 const std::vector<InputBlock> &blocks() const { return m_blocks; }
183
185 friend inline bool operator==(InputBlock block, std::string_view name);
186 friend inline bool operator==(std::string_view name, InputBlock block);
187 friend inline bool operator!=(InputBlock block, std::string_view name);
188 friend inline bool operator!=(std::string_view name, InputBlock block);
189
192 template <typename T>
193 T get(std::string_view key, T default_value) const;
194
197 template <typename T = std::string>
198 std::optional<T> get(std::string_view key) const;
199
201 bool has_option(std::string_view key) const {
202 const auto option = std::find(m_options.crbegin(), m_options.crend(), key);
203 return !(option == m_options.crend());
204 }
205
207 bool option_is_set(std::string_view key) const {
208 return !(get(key) == std::nullopt);
209 }
210
212 template <typename T>
213 T get(std::initializer_list<std::string> blocks, std::string_view key,
214 T default_value) const;
216 template <typename T>
217 std::optional<T> get(std::initializer_list<std::string> blocks,
218 std::string_view key) const;
219
222 inline std::optional<InputBlock> getBlock(std::string_view name) const;
223 inline std::optional<InputBlock>
224 getBlock(std::initializer_list<std::string> blocks,
225 std::string_view name) const;
226
228 inline InputBlock get_block(std::string_view name) const {
229 auto temp = getBlock(name);
230 if (temp)
231 return *temp;
232 return InputBlock{};
233 }
234
236 bool has_block(std::string_view name) const {
237 auto temp = getBlock(name);
238 return temp != std::nullopt;
239 }
241 bool has_block(std::initializer_list<std::string> blocks,
242 std::string_view name) const {
243 auto temp = getBlock(blocks, name);
244 return temp != std::nullopt;
245 }
246
248 inline std::optional<Option> getOption(std::string_view key) const;
249
252 inline void print(std::ostream &os = std::cout, int indent_depth = 0) const;
253
260 inline bool
261 check(std::initializer_list<std::string> blocks,
262 const std::vector<std::pair<std::string, std::string>> &list,
263 bool print = false) const;
264
266 inline bool
267 check(const std::vector<std::pair<std::string, std::string>> &list,
268 bool print = false) const {
269 return checkBlock(list, print);
270 }
271
272private:
273 inline bool
274 checkBlock(const std::vector<std::pair<std::string, std::string>> &list,
275 bool print = false) const;
276
278 inline InputBlock *getBlock_ptr(std::string_view name);
279 inline const InputBlock *getBlock_cptr(std::string_view name) const;
280
281 // Allows returning std::vector: comma-separated list input
282 template <typename T>
283 std::optional<std::vector<T>> get_vector(std::string_view key) const;
284
285 // Allows returning std::array: comma-separated list input
286 template <typename T, std::size_t N>
287 std::optional<std::array<T, N>> get_array(std::string_view key) const;
288
289 inline void add_option(std::string_view in_string);
290 inline void add_blocks_from_string(std::string_view string, bool merge);
291 inline void consolidate();
292};
293
294//==============================================================================
295//==============================================================================
296void InputBlock::add(InputBlock block, bool merge) {
297 auto existing_block = getBlock_ptr(block.m_name);
298 if (merge && existing_block) {
299 existing_block->m_options.insert(existing_block->m_options.end(),
300 block.m_options.cbegin(),
301 block.m_options.cend());
302 } else {
303 m_blocks.push_back(block);
304 }
305}
306
307//==============================================================================
308void InputBlock::add(Option option) { m_options.push_back(option); }
309void InputBlock::add(const std::vector<Option> &options) {
310 for (const auto &option : options)
311 m_options.push_back(option);
312}
313//==============================================================================
314void InputBlock::add(const std::string &string, bool merge) {
315
316 add_blocks_from_string(
318 merge);
319}
320
321//==============================================================================
322bool operator==(InputBlock block, std::string_view name) {
323 return qip::ci_wc_compare(name, block.m_name);
324}
325bool operator==(std::string_view name, InputBlock block) {
326 return block == name;
327}
328bool operator!=(InputBlock block, std::string_view name) {
329 return !(block == name);
330}
331bool operator!=(std::string_view name, InputBlock block) {
332 return !(block == name);
333}
334
335//==============================================================================
336template <typename T>
337std::optional<T> InputBlock::get(std::string_view key) const {
338 if constexpr (IsVector<T>::v) {
339 return get_vector<typename IsVector<T>::t>(key);
340 } else if constexpr (IsArray<T>::v) {
341 return get_array<typename IsArray<T>::t, IsArray<T>::size>(key);
342 } else if constexpr (std::is_same_v<T, bool>) {
343 const auto option = std::find(m_options.crbegin(), m_options.crend(), key);
344 if (option == m_options.crend())
345 return std::nullopt;
346 if (qip::ci_wc_compare("default", option->value_str) ||
347 option->value_str == "")
348 return std::nullopt;
349 const auto &str = option->value_str;
350 if (qip::ci_wc_compare("true", str) || qip::ci_wc_compare("yes", str) ||
351 qip::ci_wc_compare("y", str))
352 return true;
353 return false;
354 } else {
355 // Use reverse iterators so that we find _last_ option that matches key
356 // i.e., assume later options override earlier ones.
357 const auto option = std::find(m_options.crbegin(), m_options.crend(), key);
358 if (option == m_options.crend())
359 return std::nullopt;
360 if (qip::ci_wc_compare("default", option->value_str) ||
361 option->value_str == "")
362 return std::nullopt;
363 return parse_str_to_T<T>(option->value_str);
364 }
365}
366
367// special function; allows return of std::vector (for comma-separated list
368// input). Optional of vector is kind of redundant, but is this way so it
369// aligns with the other functions (checks if optional is empty when deciding
370// if should return the default value)
371template <typename T>
372std::optional<std::vector<T>>
373InputBlock::get_vector(std::string_view key) const {
374 // Use reverse iterators so that we find _last_ option that matches key
375 // i.e., assume later options override earlier ones.
376 std::vector<T> out;
377 const auto option = std::find(m_options.crbegin(), m_options.crend(), key);
378 if (option == m_options.crend())
379 return std::nullopt;
380 if (option->value_str == "")
381 return std::nullopt;
382 std::stringstream ss(option->value_str);
383 while (ss.good()) {
384 // note: *very* innefficient
385 std::string substr;
386 std::getline(ss, substr, ',');
387 out.push_back(parse_str_to_T<T>(substr));
388 }
389 return out;
390}
391
392template <typename T, std::size_t N>
393std::optional<std::array<T, N>>
394InputBlock::get_array(std::string_view key) const {
395 // Use reverse iterators so that we find _last_ option that matches key
396 // i.e., assume later options override earlier ones.
397 std::array<T, N> out;
398 const auto option = std::find(m_options.crbegin(), m_options.crend(), key);
399 if (option == m_options.crend())
400 return std::nullopt;
401 if (option->value_str == "")
402 return std::nullopt;
403 std::stringstream ss(option->value_str);
404 std::size_t index = 0;
405 while (ss.good()) {
406 // note: *very* innefficient
407 std::string substr;
408 std::getline(ss, substr, ',');
409 // out.push_back(parse_str_to_T<T>(substr));
410 out.at(index) = parse_str_to_T<T>(substr);
411 ++index;
412 }
413 return out;
414}
415
416template <typename T>
417T InputBlock::get(std::string_view key, T default_value) const {
418 static_assert(!std::is_same_v<T, const char *>,
419 "Cannot use get with const char* - use std::string");
420 return get<T>(key).value_or(default_value);
421}
422
423template <typename T>
424T InputBlock::get(std::initializer_list<std::string> blocks,
425 std::string_view key, T default_value) const {
426 return get<T>(blocks, key).value_or(default_value);
427}
428
429template <typename T>
430std::optional<T> InputBlock::get(std::initializer_list<std::string> blocks,
431 std::string_view key) const {
432 // Find key in nested blocks
433 const InputBlock *pB = this;
434 for (const auto &block : blocks) {
435 pB = pB->getBlock_cptr(block);
436 if (pB == nullptr)
437 return std::nullopt;
438 }
439 return pB->get<T>(key);
440}
441
442//==============================================================================
443std::optional<InputBlock> InputBlock::getBlock(std::string_view name) const {
444 // note: by copy!
445 const auto block = std::find(m_blocks.crbegin(), m_blocks.crend(), name);
446 if (block == m_blocks.crend())
447 return {};
448 return *block;
449}
450
451std::optional<InputBlock>
452InputBlock::getBlock(std::initializer_list<std::string> blocks,
453 std::string_view name) const {
454 // note: by copy!
455 const InputBlock *pB = this;
456 for (const auto &block : blocks) {
457 pB = pB->getBlock_cptr(block);
458 if (pB == nullptr)
459 return std::nullopt;
460 }
461 return pB->getBlock(name);
462}
463
464//==============================================================================
465std::optional<Option> InputBlock::getOption(std::string_view key) const {
466 // Use reverse iterators so that we find _last_ option that matches key
467 // i.e., assume later options override earlier ones.
468 const auto option = std::find(m_options.crbegin(), m_options.crend(), key);
469 if (option != m_options.crend())
470 return *option;
471 return {};
472}
473
474//==============================================================================
475void InputBlock::print(std::ostream &os, int depth) const {
476
477 std::string indent = "";
478 for (int i = 1; i < depth; ++i)
479 indent += " ";
480
481 // Don't print outer-most name
482 if (depth != 0)
483 os << indent << m_name << " { ";
484
485 const auto multi_entry = (!m_blocks.empty() || (m_options.size() > 1));
486
487 if (depth != 0 && multi_entry)
488 os << "\n";
489
490 for (const auto &[key, value] : m_options) {
491 os << (depth != 0 && multi_entry ? indent + " " : "");
492 if (value == "")
493 os << key << ';';
494 else
495 os << key << " = " << value << ';';
496 os << (multi_entry ? '\n' : ' ');
497 }
498
499 for (const auto &block : m_blocks)
500 block.print(os, depth + 1);
501
502 if (depth != 0 && multi_entry)
503 os << indent;
504
505 if (depth != 0)
506 os << "}\n";
507}
508
509//==============================================================================
510bool InputBlock::checkBlock(
511 const std::vector<std::pair<std::string, std::string>> &list,
512 bool print) const {
513 // Check each option NOT each sub block!
514 // For each input option stored, see if it is allowed
515 // "allowed" means appears in list
516 bool all_ok = true;
517 for (const auto &option : m_options) {
518 const auto is_optionQ = [&](const auto &l) {
519 // return option.key == l.first;
520 return qip::ci_wc_compare(l.first, option.key);
521 };
522 const auto bad_option =
523 !std::any_of(list.cbegin(), list.cend(), is_optionQ);
524 const auto help = qip::ci_wc_compare("help", option.key) ? true : false;
525 if (help)
526 print = true;
527 if (bad_option && !help) {
528 all_ok = false;
529 fmt2::styled_print(fg(fmt::color::orange), "\nWARNING\n");
530 std::cout << "Unclear input option in " << m_name << ": " << option.key
531 << " = " << option.value_str << ";\n"
532 << "Option may be ignored!\n"
533 << "Check spelling (or update list of options)\n";
534 // spell-check + nearest suggestion:
535 auto compare_sc = [&option](const auto &s1, const auto &s2) {
536 return qip::ci_Levenstein(s1.first, option.key) <
537 qip::ci_Levenstein(s2.first, option.key);
538 };
539 auto guess = std::min_element(list.cbegin(), list.cend(), compare_sc);
540 if (guess != list.cend()) {
541 std::cout << "\nDid you mean: " << guess->first << " ?\n";
542 }
543 }
544 }
545
546 using namespace std::string_literals;
547 for (const auto &block : m_blocks) {
548 const auto is_blockQ = [&](const auto &b) {
549 return qip::ci_wc_compare(std::string{block.name()} + "{}"s, b.first);
550 };
551 const auto bad_block = !std::any_of(list.cbegin(), list.cend(), is_blockQ);
552 if (bad_block) {
553 all_ok = false;
554 fmt2::styled_print(fg(fmt::color::orange), "\nWARNING\n");
555 std::cout << "Unclear input block within " << m_name << ": "
556 << block.name() << "{}\n"
557 << "Block and containing options may be ignored!\n"
558 << "Check spelling (or update list of options)\n";
559 // spell-check + nearest suggestion:
560 auto compare_sc = [&block](const auto &s1, const auto &s2) {
561 return qip::ci_Levenstein(s1.first, block.name()) <
562 qip::ci_Levenstein(s2.first, block.name());
563 };
564 auto guess = std::min_element(list.cbegin(), list.cend(), compare_sc);
565 if (guess != list.cend()) {
566 std::cout << "\nDid you mean: " << guess->first << " ?\n";
567 }
568 }
569 }
570
571 if (!all_ok || print) {
572 fmt2::styled_print(fg(fmt::color::light_blue),
573 "\n// Available {} options/blocks\n", m_name);
574 fmt2::styled_print(fmt::emphasis::bold, m_name);
575 std::cout << "{\n";
576 std::for_each(list.cbegin(), list.cend(), [](const auto &s) {
577 const auto option_is_block = s.first.back() == '}';
578 if (!s.second.empty()) {
579 fmt2::styled_print(fg(fmt::color::light_blue), "{}\n",
580 qip::wrap(s.second, 80, " // "));
581 }
582 if (!s.first.empty()) {
583 std::cout << " " << s.first << (option_is_block ? "\n" : ";\n");
584 } else {
585 std::cout << "\n";
586 }
587 });
588 std::cout << "}\n\n";
589 }
590 return all_ok;
591}
592
594bool InputBlock::check(
595 std::initializer_list<std::string> blocks,
596 const std::vector<std::pair<std::string, std::string>> &list,
597 bool print) const {
598 // Find key in nested blocks
599 const InputBlock *pB = this;
600 for (const auto &block : blocks) {
601 pB = pB->getBlock_cptr(block);
602 if (pB == nullptr) {
603 // Did not fund nested block... may be fine
604 // Return true, since a missing block is not an issue (or sepparate
605 // issue) We are checking to see if blocks exist that shouldn't
606 return true;
607 }
608 }
609 return pB->check(list, print);
610}
611
612//==============================================================================
613void InputBlock::add_blocks_from_string(std::string_view string, bool merge) {
614
615 // Expects that string has comments and spaces removed already
616
617 auto start = 0ul;
618 while (start < string.length()) {
619
620 // Find the first of either next ';' or open '{'
621 // This is the end of the next input option, or start of block
622 auto end = std::min(string.find(';', start), string.find('{', start));
623 if (end > string.length() || start >= end)
624 break;
625
626 if (string.at(end) == ';') {
627 // end of option:
628
629 this->add_option(string.substr(start, end - start));
630
631 } else {
632 // start of block
633
634 // 'name' directly preceeds "{"
635 const auto block_name = string.substr(start, end - start);
636 start = end + 1;
637
638 // Now, find *matching* close '}' - ensure balanced
639 int depth_count = 1;
640 auto next_start = start; // + 1;
641 while (depth_count != 0) {
642 if (next_start > string.length())
643 break;
644 const auto next_end = std::min(string.find('{', next_start),
645 string.find('}', next_start));
646 if (next_end > string.length())
647 break;
648
649 // count depth of bracket nesting:
650 if (string.at(next_end) == '{')
651 ++depth_count;
652 else
653 --depth_count;
654
655 if (depth_count == 0) {
656 end = next_end;
657 break;
658 }
659 if (depth_count > 100) {
660 std::cerr << "FAIL 271 in InputBlock::add_blocks_from_string: Depth "
661 "error. Check balanced {} in input\n";
662 end = next_end;
663 break;
664 }
665 next_start = next_end + 1;
666 }
667
668 // Add a new block, populate it with string. Recursive, since blocks may
669 // contain blocks
670 auto &block = m_blocks.emplace_back(block_name);
671
672 if (end > start)
673 block.add_blocks_from_string(string.substr(start, end - start), merge);
674 }
675
676 start = end + 1;
677 }
678
679 // Merge duplicated blocks.
680 if (merge)
681 consolidate();
682 // No - want ability to have multiple blocks of same name
683}
684
685//==============================================================================
686void InputBlock::add_option(std::string_view in_string) {
687 const auto pos = in_string.find('=');
688 const auto option = in_string.substr(0, pos);
689 const auto value = pos < in_string.length() ? in_string.substr(pos + 1) : "";
690 m_options.push_back({std::string(option), std::string(value)});
691}
692
693//==============================================================================
694InputBlock *InputBlock::getBlock_ptr(std::string_view name) {
695 auto block = std::find(m_blocks.rbegin(), m_blocks.rend(), name);
696 if (block == m_blocks.rend())
697 return nullptr;
698 return &(*block);
699}
700
701const InputBlock *InputBlock::getBlock_cptr(std::string_view name) const {
702 auto block = std::find(m_blocks.crbegin(), m_blocks.crend(), name);
703 if (block == m_blocks.rend())
704 return nullptr;
705 return &(*block);
706}
707
708//==============================================================================
709void InputBlock::consolidate() {
710 for (auto bl = m_blocks.end() - 1; bl != m_blocks.begin() - 1; --bl) {
711 bl->consolidate();
712 auto bl2 = std::find(m_blocks.begin(), bl, bl->name());
713 if (bl2 != bl) {
714 bl2->m_options.insert(bl2->m_options.end(), bl->m_options.cbegin(),
715 bl->m_options.cend());
716 m_blocks.erase(bl);
717 }
718 }
719}
720
721//==============================================================================
722//==============================================================================
723//==============================================================================
724inline std::string expandIncludes(std::string str) {
725 const std::string include_text = "#include";
726
727 for (auto ipos = str.find(include_text); ipos != std::string::npos;
728 ipos = str.find(include_text)) {
729 const auto start = std::min(str.find('"', ipos), str.find('<', ipos));
730 const auto end =
731 std::min(str.find('"', start + 1), str.find('>', start + 1));
732 const auto fname = str.substr(start + 1, end - start - 1);
733 str.erase(ipos, end - ipos + 1);
734 std::ifstream ifile(fname);
735 if (ifile.good()) {
736 str.insert(ipos, removeComments(file_to_string(ifile)));
737 }
738 }
739
740 return str;
741}
742
743//==============================================================================
744inline std::string removeSpaces(std::string str) {
745
746 bool inside = false;
747 auto lambda = [&inside](unsigned char x) {
748 if (x == '\"' || x == '\'')
749 inside = !inside;
750 return ((x == ' ' || x == '\t' || x == '\n') && !inside);
751 };
752
753 str.erase(std::remove_if(str.begin(), str.end(), lambda), str.end());
754
755 return str;
756}
757
758inline std::string removeQuoteMarks(std::string str) {
759
760 // remove ' and "
761 str.erase(std::remove_if(str.begin(), str.end(),
762 [](unsigned char x) { return x == '\''; }),
763 str.end());
764 str.erase(std::remove_if(str.begin(), str.end(),
765 [](unsigned char x) { return x == '\"'; }),
766 str.end());
767
768 return str;
769}
770
771//==============================================================================
772inline void removeBlockComments(std::string &input) {
773 for (auto posi = input.find("/*"); posi != std::string::npos;
774 posi = input.find("/*")) {
775 auto posf = input.find("*/");
776 if (posf != std::string::npos) {
777 input = input.substr(0, posi) + input.substr(posf + 2);
778 } else {
779 input = input.substr(0, posi);
780 }
781 }
782}
783
784//==============================================================================
785inline std::string removeComments(const std::string &input) {
786 std::string str = "";
787 {
788 std::string line;
789 std::stringstream stream1(input);
790 while (std::getline(stream1, line, '\n')) {
791 // const auto comm1 = line.find('!'); // nb: char, NOT string literal!
792 // auto comm2 = line.find('#');
793 const auto comm3 = line.find("//"); // str literal here
794 // const auto comm = std::min({comm1, comm3});
795 str += line.substr(0, comm3);
796 str += '\n';
797 }
798 }
799 removeBlockComments(str);
800
801 return str;
802}
803
804//==============================================================================
805template <typename T>
806T inline parse_str_to_T(const std::string &value_as_str) {
807 if constexpr (std::is_same_v<T, std::string>) {
808 // already a string, just return value
809 return value_as_str;
810 } else {
811 // T is not a string: convert using stringstream
812 T value_T;
813 std::stringstream ss(value_as_str);
814 ss >> value_T;
815 return value_T;
816 }
817}
818
819//==============================================================================
820inline std::string file_to_string(const std::istream &file) {
821 std::string out;
822 if (!file)
823 return "";
824 // Horribly inneficient...
825 std::ostringstream ss;
826 ss << file.rdbuf();
827 return ss.str();
828}
829
830} // namespace IO
Holds list of Options, and a list of other InputBlocks. Can be initialised with a list of options,...
Definition InputBlock.hpp:142
InputBlock(std::string_view name, const std::istream &file)
Construct from plain text file, in Block{option=value;} format.
Definition InputBlock.hpp:163
bool check(const std::vector< std::pair< std::string, std::string > > &list, bool print=false) const
Override for when condidering current block.
Definition InputBlock.hpp:267
bool has_block(std::string_view name) const
Checks if block 'name' is present in current block.
Definition InputBlock.hpp:236
std::optional< Option > getOption(std::string_view key) const
Get an 'Option' (kay, value) - rarely needed.
Definition InputBlock.hpp:465
InputBlock(std::string_view name, const std::string &string_input)
Construct from a string with the correct Block{option=value;} format.
Definition InputBlock.hpp:157
void add(InputBlock block, bool merge=false)
Add a new InputBlock (merge: will be merged with existing if names match)
Definition InputBlock.hpp:296
bool check(std::initializer_list< std::string > blocks, const std::vector< std::pair< std::string, std::string > > &list, bool print=false) const
Check all the options and blocks in this; if any of them are not present in 'list',...
Definition InputBlock.hpp:594
void print(std::ostream &os=std::cout, int indent_depth=0) const
Prints options to screen in user-friendly form. Same form as input string. By default prints to cout,...
Definition InputBlock.hpp:475
const std::vector< Option > & options() const
Return const reference to list of options.
Definition InputBlock.hpp:180
InputBlock(std::string_view name, std::initializer_list< Option > options={})
Construct from literal list of 'Options' (see Option struct)
Definition InputBlock.hpp:153
InputBlock get_block(std::string_view name) const
If block is present, returns a copy of it. If not, returns empty block.
Definition InputBlock.hpp:228
const std::vector< InputBlock > & blocks() const
Return const reference to list of blocks.
Definition InputBlock.hpp:182
std::optional< InputBlock > getBlock(std::string_view name) const
Returns optional InputBlock. Contains InputBlock if block of given name exists; empty otherwise.
Definition InputBlock.hpp:443
bool option_is_set(std::string_view key) const
Check if option is present AND has been set.
Definition InputBlock.hpp:207
bool has_option(std::string_view key) const
Check is option is present (even if not set) in current block.
Definition InputBlock.hpp:201
T get(std::string_view key, T default_value) const
If 'key' exists in the options, returns value. Else, returns default_value. Note: If two keys with sa...
Definition InputBlock.hpp:417
friend bool operator==(InputBlock block, std::string_view name)
Comparison of blocks compares the 'name'.
Definition InputBlock.hpp:322
bool has_block(std::initializer_list< std::string > blocks, std::string_view name) const
Checks if block 'name' is present in nesteded block.
Definition InputBlock.hpp:241
InputBlock()
Default constructor: name will be blank.
Definition InputBlock.hpp:150
In-out (timers, profilers, and read/write data)
Definition ChronoTimer.hpp:9
void removeBlockComments(std::string &input)
Removes all c++ style block comments from a string.
Definition InputBlock.hpp:772
std::string expandIncludes(std::string input)
Expands "#include" files.
Definition InputBlock.hpp:724
std::string removeSpaces(std::string str)
Removes all white space (space, tab, newline), except for those in quotes.
Definition InputBlock.hpp:744
void print_line(const char c=' *', const int num=80)
Prints a line of 'c' characters (dflt '*'), num chars long (dflt 80) to cout.
Definition InputBlock.hpp:74
std::string file_to_string(const std::istream &file)
Parses entire file into string. Note: v. inefficient.
Definition InputBlock.hpp:820
std::string removeComments(const std::string &input)
Removes all c++ style comments from a string (block and line)
Definition InputBlock.hpp:785
T parse_str_to_T(const std::string &value_as_str)
Parses a string to type T by stringstream.
Definition InputBlock.hpp:806
std::string removeQuoteMarks(std::string str)
Removes all quote marks.
Definition InputBlock.hpp:758
auto ci_Levenstein(std::string_view a, std::string_view b)
A simple non-optimised implementation of the Levenshtein distance (case insensitive)
Definition String.hpp:193
bool ci_wc_compare(std::string_view s1, std::string_view s2)
Compares two strings, s1 and s2. s2 may contain ONE wildcard ('*') which will match anything....
Definition String.hpp:139
Class to determine if a class template in vector.
Definition InputBlock.hpp:42
Simple struct; holds key-value pair, both strings. == compares key.
Definition InputBlock.hpp:105