1
/* Copyright © 2005-2006 Roger Leigh <rleigh@debian.org>
3
* schroot is free software; you can redistribute it and/or modify it
4
* under the terms of the GNU General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
8
* schroot is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18
*********************************************************************/
20
#ifndef SBUILD_KEYFILE_H
21
#define SBUILD_KEYFILE_H
23
#include <sbuild/sbuild-i18n.h>
24
#include <sbuild/sbuild-log.h>
25
#include <sbuild/sbuild-parse-error.h>
26
#include <sbuild/sbuild-parse-value.h>
27
#include <sbuild/sbuild-types.h>
28
#include <sbuild/sbuild-tr1types.h>
29
#include <sbuild/sbuild-util.h>
36
#include <boost/format.hpp>
42
* Configuration file parser. This class loads an INI-style
43
* configuration file from a file or stream. The format is
44
* documented in schroot.conf(5). It is based upon the Glib
45
* GKeyFile class, which it is intended to replace.
50
/// Key-value-comment-line tuple.
51
typedef std::tr1::tuple<std::string,std::string,std::string,unsigned int>
54
/// Map between key name and key-value-comment tuple.
55
typedef std::map<std::string,item_type> item_map_type;
57
/// Group-items-comment-line tuple.
58
typedef std::tr1::tuple<std::string,item_map_type,std::string,unsigned int> group_type;
60
/// Map between group name and group-items-comment tuple.
61
typedef std::map<std::string,group_type> group_map_type;
64
/// Configuration parameter priority.
67
PRIORITY_OPTIONAL, ///< The parameter is optional.
68
PRIORITY_REQUIRED, ///< The parameter is required.
69
PRIORITY_DISALLOWED, ///< The parameter is not allowed in this context.
70
PRIORITY_DEPRECATED, ///< The parameter is deprecated, but functional.
71
PRIORITY_OBSOLETE ///< The parameter is obsolete, and not functional.
75
typedef parse_error error;
83
* @param file the file to load the configuration from.
85
keyfile (std::string const& file);
90
* @param stream the stream to load the configuration from.
92
keyfile (std::istream& stream);
98
* Get a list of groups.
100
* @returns a list of groups in the keyfile. If no groups exist,
101
* the list will be empty.
107
* Get a list of keys in a group.
109
* @param group the group to use.
110
* @returns a list of keys in a group. If no keys exist in the
111
* group, or the group does not exist, the list will be empty.
114
get_keys (std::string const& group) const;
117
* Check if a group exists.
119
* @param group the group to check for.
120
* @returns true if the group exists, otherwise false.
123
has_group (std::string const& group) const;
126
* Check if a key exists.
128
* @param group the group the key is in.
129
* @param key the key to check for.
130
* @returns true if the key exists, otherwise false.
133
has_key (std::string const& group,
134
std::string const& key) const;
137
* Set a group. The group will be created (and the comment set)
138
* only if the group does not already exist.
140
* @param group the group to set.
141
* @param comment the comment to set.
144
set_group (std::string const& group,
145
std::string const& comment);
149
* Set a group. The group will be created (and the comment set)
150
* only if the group does not already exist.
152
* @param group the group to set.
153
* @param comment the comment to set.
154
* @param line the line number in the input file, or 0 otherwise.
157
set_group (std::string const& group,
158
std::string const& comment,
163
* Get a group comment.
165
* @param group the group to find.
166
* @returns the comment.
169
get_comment (std::string const& group) const;
174
* @param group the group to find.
175
* @param key the key to find.
176
* @returns the comment.
179
get_comment (std::string const& group,
180
std::string const& key) const;
183
* Get a group line number.
185
* @param group the group to find.
186
* @returns the line number, or 0 if not available.
189
get_line (std::string const& group) const;
192
* Get a key line number.
194
* @param group the group to find.
195
* @param key the key to find.
196
* @returns the line number, or 0 if not available.
199
get_line (std::string const& group,
200
std::string const& key) const;
205
* @param group the group the key is in.
206
* @param key the key to get.
207
* @param value the value to store the key's value in. This must
208
* be settable from an istream and be copyable.
209
* @returns true if the key was found, otherwise false (in which
210
* case value will be unchanged).
212
template <typename T>
214
get_value (std::string const& group,
215
std::string const& key,
218
log_debug(DEBUG_INFO) << "Getting keyfile group=" << group
219
<< ", key=" << key << std::endl;
220
const item_type *found_item = find_item(group, key);
223
std::string const& strval(std::tr1::get<1>(*found_item));
226
parse_value(strval, value);
229
catch (parse_error const& e)
231
error ep(group, key, parse_error::NONE, e.what());
232
log_warning() << ep.what() << std::endl;
236
log_debug(DEBUG_NOTICE) << "key not found" << std::endl;
241
* Get a key value. If the value does not exist, is deprecated or
242
* obsolete, warn appropriately.
244
* @param group the group the key is in.
245
* @param key the key to get.
246
* @param priority the priority of the option.
247
* @param value the value to store the key's value in. This must
248
* be settable from an istream and be copyable.
249
* @returns true if the key was found, otherwise false (in which
250
* case value will be unchanged).
252
template <typename T>
254
get_value (std::string const& group,
255
std::string const& key,
259
bool status = get_value(group, key, value);
260
check_priority(group, key, priority, status);
265
* Get a localised key string value.
267
* @param group the group the key is in.
268
* @param key the key to get.
269
* @param value the string to store the key's localised value in.
270
* @returns true if the key was found, otherwise false (in which
271
* case value will be unchanged).
274
get_locale_string (std::string const& group,
275
std::string const& key,
276
std::string& value) const;
279
* Get a localised key string value. If the value does not exist,
280
* is deprecated or obsolete, warn appropriately.
282
* @param group the group the key is in.
283
* @param key the key to get.
284
* @param priority the priority of the option.
285
* @param value the string to store the key's localised value in.
286
* @returns true if the key was found, otherwise false (in which
287
* case value will be unchanged).
290
get_locale_string (std::string const& group,
291
std::string const& key,
293
std::string& value) const;
296
* Get a localised key string value for a specific locale.
298
* @param group the group the key is in.
299
* @param key the key to get.
300
* @param locale the locale to use.
301
* @param value the string to store the key's localised value in.
302
* @returns true if the key was found, otherwise false (in which
303
* case value will be unchanged).
306
get_locale_string (std::string const& group,
307
std::string const& key,
308
std::string const& locale,
309
std::string& value) const;
312
* Get a localised key string value for a specific locale. If the
313
* value does not exist, is deprecated or obsolete, warn
316
* @param group the group the key is in.
317
* @param key the key to get.
318
* @param locale the locale to use.
319
* @param priority the priority of the option.
320
* @param value the string to store the key's localised value in.
321
* @returns true if the key was found, otherwise false (in which
322
* case value will be unchanged).
325
get_locale_string (std::string const& group,
326
std::string const& key,
327
std::string const& locale,
329
std::string& value) const;
332
* Get a key value as a list.
334
* @param group the group the key is in.
335
* @param key the key to get.
336
* @param container the container to store the key's value in.
337
* The value type must be settable from an istream and be
338
* copyable. The list must be a container with a standard insert
340
* @returns true if the key was found, otherwise false (in which
341
* case value will be undefined).
343
template <typename C>
345
get_list_value (std::string const& group,
346
std::string const& key,
349
std::string item_value;
350
if (get_value(group, key, item_value))
352
string_list items = split_string(item_value,
353
std::string(1, this->separator));
354
for (string_list::const_iterator pos = items.begin();
359
typename C::value_type tmp;
363
parse_value(*pos, tmp);
365
catch (parse_error const& e)
367
error ep(group, key, parse_error::NONE, e.what());
368
log_warning() << ep.what() << std::endl;
372
container.push_back(tmp);
380
* Get a key value as a list. If the value does not exist, is
381
* deprecated or obsolete, warn appropriately.
383
* @param group the group the key is in.
384
* @param key the key to get.
385
* @param priority the priority of the option.
386
* @param container the container to store the key's value in.
387
* The value type must be settable from an istream and be
388
* copyable. The list must be a container with a standard insert
390
* @returns true if the key was found, otherwise false (in which
391
* case value will be undefined).
393
template <typename C>
395
get_list_value (std::string const& group,
396
std::string const& key,
400
bool status = get_list_value(group, key, container);
401
check_priority(group, key, priority, status);
408
* @param group the group the key is in.
409
* @param key the key to set.
410
* @param value the value to get the key's value from. This must
411
* allow output to an ostream.
413
template <typename T>
415
set_value (std::string const& group,
416
std::string const& key,
419
set_value(group, key, value, std::string());
425
* @param group the group the key is in.
426
* @param key the key to set.
427
* @param value the value to get the key's value from. This must
428
* @param comment the comment for this key.
429
* allow output to an ostream.
431
template <typename T>
433
set_value (std::string const& group,
434
std::string const& key,
436
std::string const& comment)
438
std::ostringstream os;
439
os.imbue(std::locale("C"));
440
os << std::boolalpha << value;
442
set_value(group, key, os.str(), comment, 0);
449
* @param group the group the key is in.
450
* @param key the key to set.
451
* @param value the value to get the key's value from. This must
452
* @param comment the comment for this key.
453
* @param line the line number in the input file, or 0 otherwise.
454
* allow output to an ostream.
457
set_value (std::string const& group,
458
std::string const& key,
459
std::string const& value,
460
std::string const& comment,
463
set_group(group, "");
464
group_type *found_group = find_group(group);
465
assert (found_group != 0); // should not fail
467
item_map_type& items = std::tr1::get<1>(*found_group);
469
item_map_type::iterator pos = items.find(key);
470
if (pos != items.end())
473
(item_map_type::value_type(key,
474
item_type(key, value, comment, line)));
479
* Set a key value from a list.
481
* @param group the group the key is in.
482
* @param key the key to set.
483
* @param begin an iterator referring to the start of the
484
* list. The value type must allow output to an ostream.
485
* @param end an iterator referring to the end of the list.
487
template <typename I>
489
set_list_value (std::string const& group,
490
std::string const& key,
494
set_list_value(group, key, begin, end, std::string());
498
* Set a key value from a list.
500
* @param group the group the key is in.
501
* @param key the key to set.
502
* @param begin an iterator referring to the start of the
503
* list. The value type must allow output to an ostream.
504
* @param end an iterator referring to the end of the list.
505
* @param comment the comment for this key.
507
template <typename I>
509
set_list_value (std::string const& group,
510
std::string const& key,
513
std::string const& comment)
517
for (I pos = begin; pos != end; ++ pos)
519
std::ostringstream os;
520
os.imbue(std::locale("C"));
521
os << std::boolalpha << *pos;
526
strval += this->separator;
530
set_value (group, key, strval, comment);
536
* @param group the group to remove.
539
remove_group (std::string const& group);
544
* @param group the group the key is in.
545
* @param key the key to remove.
548
remove_key (std::string const& group,
549
std::string const& key);
552
* Add a keyfile to the keyfile.
554
* @param rhs the keyfile to add.
555
* @returns the modified keyfile.
558
operator += (keyfile const& rhs);
561
* Add a keyfile to the keyfile.
563
* @param lhs the keyfile to add to.
564
* @param rhs the values to add.
565
* @returns the new keyfile.
568
operator + (keyfile const& lhs,
572
* keyfile initialisation from an istream.
574
template <class charT, class traits>
576
std::basic_istream<charT,traits>&
577
operator >> (std::basic_istream<charT,traits>& stream,
581
size_t linecount = 0;
588
while (std::getline(stream, line))
592
if (line.length() == 0)
594
// Empty line; do nothing.
596
else if (line[0] == '#') // Comment line
598
if (!comment.empty())
600
comment += line.substr(1);
602
else if (line[0] == '[') // Group
604
std::string::size_type fpos = line.find_first_of(']');
605
std::string::size_type lpos = line.find_last_of(']');
606
if (fpos == std::string::npos || lpos == std::string::npos ||
609
throw error(linecount, parse_error::INVALID_GROUP, line);
611
group = line.substr(1, fpos - 1);
613
if (group.length() == 0)
615
throw error(linecount, parse_error::INVALID_GROUP, line);
619
if (tmp.has_group(group))
621
error e(linecount, parse_error::DUPLICATE_GROUP, group);
622
log_warning() << e.what() << std::endl;
625
tmp.set_group(group, comment, linecount);
630
std::string::size_type pos = line.find_first_of('=');
631
if (pos == std::string::npos)
633
throw error(linecount, parse_error::INVALID_LINE, line);
637
throw error(linecount, parse_error::NO_KEY, line);
639
key = line.substr(0, pos);
640
if (pos == line.length() - 1)
643
value = line.substr(pos + 1);
645
// No group specified
648
throw error(linecount, parse_error::NO_GROUP, line);
652
if (tmp.has_key(group, key))
654
error e(linecount, group, parse_error::DUPLICATE_KEY, key);
655
log_warning() << e.what() << std::endl;
658
tmp.set_value(group, key, value, comment, linecount);
669
* keyfile output to an ostream.
671
template <class charT, class traits>
673
std::basic_ostream<charT,traits>&
674
operator << (std::basic_ostream<charT,traits>& stream,
677
unsigned int group_count = 0;
679
for (group_map_type::const_iterator gp = kf.groups.begin();
680
gp != kf.groups.end();
686
group_type const& group = gp->second;
687
std::string const& groupname = std::tr1::get<0>(group);
688
std::string const& comment = std::tr1::get<2>(group);
690
if (comment.length() > 0)
691
print_comment(comment, stream);
693
stream << '[' << groupname << ']' << '\n';
695
item_map_type const& items(std::tr1::get<1>(group));
696
for (item_map_type::const_iterator it = items.begin();
700
item_type const& item = it->second;
701
std::string const& key(std::tr1::get<0>(item));
702
std::string const& value(std::tr1::get<1>(item));
703
std::string const& comment(std::tr1::get<2>(item));
705
if (comment.length() > 0)
706
print_comment(comment, stream);
708
stream << key << '=' << value << '\n';
717
* Find a group by it's name.
719
* @param group the group to find.
720
* @returns the group, or 0 if not found.
723
find_group (std::string const& group) const;
726
* Find a group by it's name.
728
* @param group the group to find.
729
* @returns the group, or 0 if not found.
732
find_group (std::string const& group);
735
* Find a key by it's group and name.
737
* @param group the group the key is in.
738
* @param key the key to find
739
* @returns the key, or 0 if not found.
742
find_item (std::string const& group,
743
std::string const& key) const;
746
* Find a key by it's group and name.
748
* @param group the group the key is in.
749
* @param key the key to find
750
* @returns the key, or 0 if not found.
753
find_item (std::string const& group,
754
std::string const& key);
757
* Check if a key is missing or present when not permitted.
759
* @param group the group the key is in.
760
* @param key the key to get.
761
* @param priority the key priority.
762
* @param valid true if key exists, false if not existing.
765
check_priority (std::string const& group,
766
std::string const& key,
771
* Print a comment to a stream. The comment will have hash ('#')
772
* marks printed at the start of each line.
774
* @param comment the comment to print.
775
* @param stream the stream to output to.
778
print_comment (std::string const& comment,
779
std::ostream& stream);
781
/// The top-level groups.
782
group_map_type groups;
783
/// The separator used as a list item delimiter.
788
* Set a key value from an object method return value. This is
789
* the same as calling set_value directly, but handles exceptions
790
* being thrown by the object method, which are turned into
791
* parse_error exceptions.
793
* @param object the object to use.
794
* @param method the object method to call.
795
* @param keyfile the keyfile to use.
796
* @param group the group the key is in.
797
* @param key the key to set.
799
template<class C, typename T>
801
set_object_value (C const& object,
802
T (C::* method)() const,
804
std::string const& group,
805
std::string const& key)
809
keyfile.set_value(group, key, (object.*method)());
811
catch (runtime_error const& e)
813
throw parse_error(group, key, parse_error::NONE, e.what());
818
* Set a key value from an object method return value reference.
819
* This is the same as calling set_value directly, but handles
820
* exceptions being thrown by the object method, which are turned
821
* into parse_error exceptions.
823
* @param object the object to use.
824
* @param method the object method to call.
825
* @param keyfile the keyfile to use.
826
* @param group the group the key is in.
827
* @param key the key to set.
829
template<class C, typename T>
831
set_object_value (C const& object,
832
T const& (C::* method)() const,
834
std::string const& group,
835
std::string const& key)
839
keyfile.set_value(group, key, (object.*method)());
841
catch (runtime_error const& e)
843
throw parse_error(group, key, parse_error::NONE, e.what());
848
* Set a key list value from an object method return value. The
849
* method must return a container with begin() and end() methods
850
* which return forward iterators. This is the same as calling
851
* set_list_value directly, but handles exceptions being thrown by
852
* the object method, which are turned into parse_error
855
* @param object the object to use.
856
* @param method the object method to call.
857
* @param keyfile the keyfile to use.
858
* @param group the group the key is in.
859
* @param key the key to set.
861
template<class C, typename T>
863
set_object_list_value (C const& object,
864
T (C::* method)() const,
866
std::string const& group,
867
std::string const& key)
871
keyfile.set_list_value(group, key,
872
(object.*method)().begin(),
873
(object.*method)().end());
875
catch (runtime_error const& e)
877
throw parse_error(group, key, parse_error::NONE, e.what());
882
* Set a key list value from an object method return value. The
883
* method must return a container reference with begin() and end()
884
* methods which return forward iterators. This is the same as
885
* calling set_list_value directly, but handles exceptions being
886
* thrown by the object method, which are turned into parse_error
889
* @param object the object to use.
890
* @param method the object method to call.
891
* @param keyfile the keyfile to use.
892
* @param group the group the key is in.
893
* @param key the key to set.
895
template<class C, typename T>
897
set_object_list_value (C const& object,
898
T const& (C::* method)() const,
900
std::string const& group,
901
std::string const& key)
905
keyfile.set_list_value(group, key,
906
(object.*method)().begin(),
907
(object.*method)().end());
909
catch (runtime_error const& e)
911
throw parse_error(group, key, parse_error::NONE, e.what());
916
* Get a key value and set it in an object using an object method.
917
* This is the same as calling get_value directly, but handles
918
* exceptions being thrown by the object method, and
919
* deserialisation errors, which are turned into parse_error
920
* exceptions pointing to the group, key and line number in the
923
* @param object the object to use.
924
* @param method the object method to call.
925
* @param keyfile the keyfile to use.
926
* @param group the group the key is in.
927
* @param key the key to set.
928
* @param priority the key priority.
930
template<class C, typename T>
932
get_object_value (C& object,
933
void (C::* method)(T param),
934
keyfile const& keyfile,
935
std::string const& group,
936
std::string const& key,
937
keyfile::priority priority)
940
if (keyfile.get_value(group, key, priority, value))
944
(object.*method)(value);
946
catch (runtime_error const& e)
948
throw parse_error(keyfile.get_line(group, key),
949
group, key, parse_error::NONE, e.what());
955
* Get a key value and set it by reference in an object using an
956
* object method. This is the same as calling get_value directly,
957
* but handles exceptions being thrown by the object method, and
958
* deserialisation errors, which are turned into parse_error
959
* exceptions pointing to the group, key and line number in the
962
* @param object the object to use.
963
* @param method the object method to call.
964
* @param keyfile the keyfile to use.
965
* @param group the group the key is in.
966
* @param key the key to set.
967
* @param priority the key priority.
969
template<class C, typename T>
971
get_object_value (C& object,
972
void (C::* method)(T const& param),
973
keyfile const& keyfile,
974
std::string const& group,
975
std::string const& key,
976
keyfile::priority priority)
979
if (keyfile.get_value(group, key, priority, value))
983
(object.*method)(value);
985
catch (runtime_error const& e)
987
throw parse_error(keyfile.get_line(group, key),
988
group, key, parse_error::NONE, e.what());
994
* Get a key list value and set it in an object using an object
995
* method. This is the same as calling get_list_value directly,
996
* but handles exceptions being thrown by the object method, and
997
* deserialisation errors, which are turned into parse_error
998
* exceptions pointing to the group, key and line number in the
1001
* @param object the object to use.
1002
* @param method the object method to call.
1003
* @param keyfile the keyfile to use.
1004
* @param group the group the key is in.
1005
* @param key the key to set.
1006
* @param priority the key priority.
1008
template<class C, typename T>
1010
get_object_list_value (C& object,
1011
void (C::* method)(T param),
1012
keyfile const& keyfile,
1013
std::string const& group,
1014
std::string const& key,
1015
keyfile::priority priority)
1018
if (keyfile.get_list_value(group, key, priority, value))
1022
(object.*method)(value);
1024
catch (runtime_error const& e)
1026
throw parse_error(keyfile.get_line(group, key),
1027
group, key, parse_error::NONE, e.what());
1033
* Get a key list value and set it by reference in an object using
1034
* an object method. This is the same as calling get_list_value
1035
* directly, but handles exceptions being thrown by the object
1036
* method, and deserialisation errors, which are turned into
1037
* parse_error exceptions pointing to the group, key and line
1038
* number in the input file.
1040
* @param object the object to use.
1041
* @param method the object method to call.
1042
* @param keyfile the keyfile to use.
1043
* @param group the group the key is in.
1044
* @param key the key to set.
1045
* @param priority the key priority.
1047
template<class C, typename T>
1049
get_object_list_value (C& object,
1050
void (C::* method)(T const& param),
1051
keyfile const& keyfile,
1052
std::string const& group,
1053
std::string const& key,
1054
keyfile::priority priority)
1057
if (keyfile.get_list_value(group, key, priority, value))
1061
(object.*method)(value);
1063
catch (runtime_error const& e)
1065
throw parse_error(keyfile.get_line(group, key),
1066
group, key, parse_error::NONE, e.what());
1074
#endif /* SBUILD_KEYFILE_H */