]> git.tdb.fi Git - builder.git/blob - source/config.cpp
Better encapsulation of config inside Package
[builder.git] / source / config.cpp
1 #include <fstream>
2 #include <msp/error.h>
3 #include <msp/path/utils.h>
4 #include <msp/time/utils.h>
5 #include "config.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 /**
11 Adds a configuration option.
12
13 @param   n  Option name
14 @param   v  Default value
15 @param   d  Description
16 */
17 void Config::add_option(const string &n, const string &v, const string &d)
18 {
19         options.insert(OptionMap::value_type(n, Option(n, v, d)));
20 }
21
22 /**
23 Gets the given option from the configuration.  If the option doesn't exist,
24 an Exception is thrown.
25 */
26 const Config::Option &Config::get_option(const string &name) const
27 {
28         OptionMap::const_iterator i=options.find(name);
29         if(i==options.end())
30                 throw Exception("Tried to access nonexistent option "+name);
31
32         return i->second;
33 }
34
35 /**
36 Checks whether an option with the given name exists.
37 */
38 bool Config::is_option(const string &name) const
39 {
40         return options.count(name);
41 }
42
43 /**
44 Selects the last profile used.  If the profile cache file is not present, the
45 default profile is assumed.
46 */
47 void Config::select_last_profile()
48 {
49         ifstream in((source/".profile.cache").str().c_str());
50         if(in)
51         {
52                 string profile;
53                 in>>profile;
54                 set_option("profile", profile);
55         }
56         else
57                 set_option("profile", "default");
58
59         load();
60 }
61
62 /**
63 Selects the given profile.  The profile cache file is updated as well.
64 */
65 void Config::select_profile(const string &profile)
66 {
67         set_option("profile", profile);
68
69         ofstream out((source/".profile.cache").str().c_str());
70         if(out)
71                 out<<profile<<'\n';
72
73         load();
74 }
75
76 /**
77 Processes options from the given raw option map.  Nonexistent options are
78 ignored.  If any options were changed, the mtime of the configuration is updated
79 to the current time.
80
81 @param   opts  A map to process options from
82
83 @return  Whether any option values were changed
84 */
85 bool Config::update(const RawOptionMap &opts)
86 {
87         bool changed=false;
88         for(RawOptionMap::const_iterator i=opts.begin(); i!=opts.end(); ++i)
89         {
90                 if(set_option(i->first, i->second) && i->first!="profile")
91                         changed=true;
92         }
93
94         if(changed)
95                 mtime=Time::now();
96
97         return changed;
98 }
99
100 void Config::save() const
101 {
102         Path::Path fn=source/".options.cache";
103
104         OptionMap::const_iterator i=options.find("profile");
105         if(i!=options.end())
106                 fn=source/(".options."+i->second.value+".cache");
107
108         ofstream out(fn.str().c_str());
109         if(!out) return;
110         
111         for(i=options.begin(); i!=options.end(); ++i)
112                 out<<"option \""<<i->second.name<<"\" \""<<i->second.value<<"\";\n";
113 }
114
115 bool Config::set_option(const string &opt, const string &val)
116 {
117         bool result=false;
118
119         OptionMap::iterator i=options.find(opt);
120         if(i!=options.end())
121         {
122                 if(i->second.value!=val)
123                         result=true;
124                 i->second.value=val;
125         }
126
127         return result;
128 }
129
130 void Config::load()
131 {
132         Path::Path fn=source/".options.cache";
133
134         OptionMap::iterator i=options.find("profile");
135         if(i!=options.end())
136                 fn=source/(".options."+i->second.value+".cache");
137
138         ifstream in(fn.str().c_str());
139         if(!in) return;
140
141         struct stat st;
142         Path::stat(fn, st);
143         mtime=Time::TimeStamp::from_unixtime(st.st_mtime);
144
145         Parser::Parser parser(in, fn.str());
146         Loader loader(*this);
147         loader.load(parser);
148 }
149
150 Config::Option::Option(const string &n, const string &v, const string &d):
151         name(n),
152         defv(v),
153         descr(d),
154         value(v)
155 { }
156
157 Config::Loader::Loader(Config &c):
158         conf(c)
159 {
160         add("option", &Loader::option);
161 }
162
163 void Config::Loader::option(const string &n, const string &v)
164 {
165         conf.set_option(n, v);
166 }