aboutsummaryrefslogtreecommitdiffstats
path: root/lib/utils/read_cfg.cpp
blob: ad57a8b3eccf9dee6d6698aa84a5f3e8e2ba883c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
* Simple config/test file reader
* (C) 2013 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/parsing.h>
#include <boost/algorithm/string.hpp>

namespace Botan {

void lex_cfg(std::istream& is,
             std::function<void (std::string)> cb)
   {
   while(is.good())
      {
      std::string s;

      std::getline(is, s);

      while(is.good() && s.back() == '\\')
         {
         boost::trim_if(s, boost::is_any_of("\\\n"));
         std::string x;
         std::getline(is, x);
         boost::trim_left(x);
         s += x;
         }

      auto comment = s.find('#');
      if(comment)
         s = s.substr(0, comment);

      if(s.empty())
         continue;

      std::vector<std::string> parts;
      boost::split(parts, s, boost::is_any_of(" \t\n"), boost::token_compress_on);

      for(auto p : parts)
         {
         if(p.empty())
            continue;

         auto eq = p.find("=");

         if(eq == std::string::npos || p.size() < 2)
            {
            cb(p);
            }
         else if(eq == 0)
            {
            cb("=");
            cb(p.substr(1, std::string::npos));
            }
         else if(eq == p.size() - 1)
            {
            cb(p.substr(0, p.size() - 1));
            cb("=");
            }
         else if(eq != std::string::npos)
            {
            cb(p.substr(0, eq));
            cb("=");
            cb(p.substr(eq + 1, std::string::npos));
            }
         }
      }
   }

void lex_cfg_w_headers(std::istream& is,
                       std::function<void (std::string)> cb,
                       std::function<void (std::string)> hdr_cb)
   {
   auto intercept = [cb,hdr_cb](const std::string& s)
      {
      if(s[0] == '[' && s[s.length()-1] == ']')
         hdr_cb(s.substr(1, s.length()-2));
      else
         cb(s);
      };

   lex_cfg(is, intercept);
   }

std::map<std::string, std::map<std::string, std::string>>
   parse_cfg(std::istream& is)
   {
   std::string header = "default";
   std::map<std::string, std::map<std::string, std::string>> vals;
   std::string key;

   auto header_cb = [&header](const std::string i) { header = i; };
   auto cb = [&header,&key,&vals](const std::string s)
      {
      if(s == "=")
         {
         BOTAN_ASSERT(!key.empty(), "Valid assignment in config");
         }
      else if(key.empty())
         key = s;
      else
         {
         vals[header][key] = s;
         key = "";
         }
      };

   lex_cfg_w_headers(is, cb, header_cb);

   return vals;
   }

}