source: trunk/debathena/third/schroot/sbuild/sbuild-basic-keyfile.h @ 24167

Revision 24167, 34.0 KB checked in by broder, 15 years ago (diff)
Import schroot upstream into subversion.
Line 
1/* Copyright © 2005-2009  Roger Leigh <rleigh@debian.org>
2 *
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 3 of the License, or
6 * (at your option) any later version.
7 *
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.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 *********************************************************************/
18
19#ifndef SBUILD_BASIC_KEYFILE_H
20#define SBUILD_BASIC_KEYFILE_H
21
22#include <sbuild/sbuild-i18n.h>
23#include <sbuild/sbuild-log.h>
24#include <sbuild/sbuild-keyfile-base.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>
30
31#include <cassert>
32#include <map>
33#include <string>
34#include <sstream>
35
36#include <boost/format.hpp>
37
38namespace sbuild
39{
40  /**
41   *
42   */
43  template <typename K>
44  class basic_keyfile_parser
45  {
46  public:
47    /// Exception type.
48    typedef keyfile_base::error error;
49
50    /// The constructor.
51    basic_keyfile_parser ():
52      group(),
53      group_set(false),
54      key(),
55      key_set(false),
56      value(),
57      value_set(false),
58      comment(),
59      comment_set(false),
60      line_number(0)
61    {
62    }
63
64    /// The destructor.
65    virtual ~basic_keyfile_parser ()
66    {
67    }
68
69    /// Group name.
70    typename K::group_name_type group;
71
72    /// Group name is set.
73    bool                        group_set;
74
75    /// Key name.
76    typename K::key_type        key;
77
78    /// Key name is set.
79    bool                        key_set;
80
81    /// Value.
82    typename K::value_type      value;
83
84    /// Value is set.
85    bool                        value_set;
86
87    /// Comment.
88    typename K::comment_type    comment;
89
90    /// Comment is set.
91    bool                        comment_set;
92
93    /// Line number.
94    typename K::size_type       line_number;
95
96    /**
97     * Start processing input.
98     * Any setup may be done here.
99     */
100    virtual void
101    begin ()
102    {
103      line_number = 0;
104    }
105
106    /**
107     * Parse a line of input.  This function will be called for every
108     * line of input in the source file.  The input line, line, is
109     * parsed appropriately.  Any of the group, key, value, and
110     * comment members are set as required.  If any of these members
111     * are ready for insertion into the keyfile, then the
112     * corresponding _set member must be set to true to signal the
113     * fact to the caller.
114     * @param line the line to parse.
115     */
116    virtual void
117    parse_line (std::string const& line)
118    {
119      ++line_number;
120    }
121
122    /**
123     * Stop processing input.  Any cleanup may be done here.  For
124     * example, any cached group or item may be set here.
125     */
126    virtual void
127    end()
128    {
129    }
130  };
131
132  /**
133   * Configuration file parser.  This class loads an INI-style
134   * configuration file from a file or stream.  The format is
135   * documented in schroot.conf(5).
136   */
137  template <typename K, typename P = basic_keyfile_parser<K> >
138  class basic_keyfile : public keyfile_base
139  {
140  public:
141    /// Group name.
142    typedef typename K::group_name_type group_name_type;
143
144    /// Key name.
145    typedef typename K::key_type key_type;
146
147    /// Value.
148    typedef typename K::value_type value_type;
149
150    /// Comment.
151    typedef typename K::comment_type comment_type;
152
153    /// Line number.
154    typedef typename K::size_type size_type;
155
156    /// Vector of groups
157    typedef std::vector<group_name_type> group_list;
158
159    /// Vector of values
160    typedef std::vector<value_type> value_list;
161
162  private:
163    /// Parse type.
164    typedef P parse_type;
165
166    /// Key-value-comment-line tuple.
167    typedef std::tr1::tuple<key_type,value_type,comment_type,size_type>
168    item_type;
169
170    /// Map between key name and key-value-comment tuple.
171    typedef std::map<key_type,item_type> item_map_type;
172
173    /// Group-items-comment-line tuple.
174    typedef std::tr1::tuple<group_name_type,item_map_type,comment_type,size_type> group_type;
175
176    /// Map between group name and group-items-comment tuple.
177    typedef std::map<group_name_type,group_type> group_map_type;
178
179    /// Vector of keys
180    typedef std::vector<key_type> key_list;
181
182  public:
183    /// The constructor.
184    basic_keyfile ();
185
186    /**
187     * The constructor.
188     *
189     * @param file the file to load the configuration from.
190     */
191    basic_keyfile (std::string const& file);
192
193    /**
194     * The constructor.
195     *
196     * @param stream the stream to load the configuration from.
197     */
198    basic_keyfile (std::istream& stream);
199
200    /// The destructor.
201    virtual ~basic_keyfile ();
202
203    /**
204     * Get a list of groups.
205     *
206     * @returns a list of groups in the basic_keyfile.  If no groups exist,
207     * the list will be empty.
208     */
209    group_list
210    get_groups () const;
211
212    /**
213     * Get a list of keys in a group.
214     *
215     * @param group the group to use.
216     * @returns a list of keys in a group.  If no keys exist in the
217     * group, or the group does not exist, the list will be empty.
218     */
219    key_list
220    get_keys (group_name_type const& group) const;
221
222    /**
223     * Check for unused keys in a group.  If keys other than the
224     * specified keys exist in the specified group, print a warning
225     * about unknown keys having been used.
226     *
227     * @param group the group to use.
228     * @param keys the keys which have been used.
229     */
230    void
231    check_keys (group_name_type const& group,
232                key_list const&        keys) const;
233
234    /**
235     * Check if a group exists.
236     *
237     * @param group the group to check for.
238     * @returns true if the group exists, otherwise false.
239     */
240    bool
241    has_group (group_name_type const& group) const;
242
243    /**
244     * Check if a key exists.
245     *
246     * @param group the group the key is in.
247     * @param key the key to check for.
248     * @returns true if the key exists, otherwise false.
249     */
250    bool
251    has_key (group_name_type const& group,
252             key_type const&        key) const;
253
254    /**
255     * Set a group.  The group will be created (and the comment set)
256     * only if the group does not already exist.
257     *
258     * @param group the group to set.
259     * @param comment the comment to set.
260     */
261    void
262    set_group (group_name_type const& group,
263               comment_type const&    comment);
264
265    /**
266     * Set a group.  The group will be created (and the comment set)
267     * only if the group does not already exist.
268     *
269     * @param group the group to set.
270     * @param comment the comment to set.
271     * @param line the line number in the input file, or 0 otherwise.
272     */
273    void
274    set_group (group_name_type const& group,
275               comment_type const&    comment,
276               size_type              line);
277
278    /**
279     * Get a group comment.
280     *
281     * @param group the group to find.
282     * @returns the comment.
283     */
284    comment_type
285    get_comment (group_name_type const& group) const;
286
287    /**
288     * Get a key comment.
289     *
290     * @param group the group to find.
291     * @param key the key to find.
292     * @returns the comment.
293     */
294    comment_type
295    get_comment (group_name_type const& group,
296                 key_type const&        key) const;
297
298    /**
299     * Get a group line number.
300     *
301     * @param group the group to find.
302     * @returns the line number, or 0 if not available.
303     */
304    size_type
305    get_line (group_name_type const& group) const;
306
307    /**
308     * Get a key line number.
309     *
310     * @param group the group to find.
311     * @param key the key to find.
312     * @returns the line number, or 0 if not available.
313     */
314    size_type
315    get_line (group_name_type const& group,
316              key_type const&        key) const;
317
318    /**
319     * Get a key value.
320     *
321     * @param group the group the key is in.
322     * @param key the key to get.
323     * @param value the value to store the key's value in.  This must
324     * be settable from an istream and be copyable.
325     * @returns true if the key was found, otherwise false (in which
326     * case value will be unchanged).
327     */
328    template <typename T>
329    bool
330    get_value (group_name_type const& group,
331               key_type const&        key,
332               T&                     value) const
333    {
334      log_debug(DEBUG_INFO) << "Getting keyfile group=" << group
335                            << ", key=" << key << std::endl;
336      const item_type *found_item = find_item(group, key);
337      if (found_item)
338        {
339          value_type const& strval(std::tr1::get<1>(*found_item));
340          try
341            {
342              parse_value(strval, value);
343              return true;
344            }
345          catch (parse_value_error const& e)
346            {
347              size_type line = get_line(group, key);
348              if (line)
349                {
350                  error ep(line, group, key, PASSTHROUGH_LGK, e);
351                  log_exception_warning(ep);
352                }
353              else
354                {
355                  error ep(group, key, PASSTHROUGH_GK, e);
356                  log_exception_warning(ep);
357                }
358              return false;
359            }
360        }
361      log_debug(DEBUG_NOTICE) << "key not found" << std::endl;
362      return false;
363    }
364
365    /**
366     * Get a key value.  If the value does not exist, is deprecated or
367     * obsolete, warn appropriately.
368     *
369     * @param group the group the key is in.
370     * @param key the key to get.
371     * @param priority the priority of the option.
372     * @param value the value to store the key's value in.  This must
373     * be settable from an istream and be copyable.
374     * @returns true if the key was found, otherwise false (in which
375     * case value will be unchanged).
376     */
377    template <typename T>
378    bool
379    get_value (group_name_type const& group,
380               key_type const&        key,
381               priority               priority,
382               T&                     value) const
383    {
384      bool status = get_value(group, key, value);
385      check_priority(group, key, priority, status);
386      return status;
387    }
388
389    /**
390     * Get a localised key string value.
391     *
392     * @param group the group the key is in.
393     * @param key the key to get.
394     * @param value the string to store the key's localised value in.
395     * @returns true if the key was found, otherwise false (in which
396     * case value will be unchanged).
397     */
398    bool
399    get_locale_string (group_name_type const& group,
400                       key_type const&        key,
401                       value_type&            value) const;
402
403    /**
404     * Get a localised key string value.  If the value does not exist,
405     * is deprecated or obsolete, warn appropriately.
406     *
407     * @param group the group the key is in.
408     * @param key the key to get.
409     * @param priority the priority of the option.
410     * @param value the string to store the key's localised value in.
411     * @returns true if the key was found, otherwise false (in which
412     * case value will be unchanged).
413     */
414    bool
415    get_locale_string (group_name_type const& group,
416                       key_type const&        key,
417                       priority               priority,
418                       value_type&            value) const;
419
420    /**
421     * Get a localised key string value for a specific locale.
422     *
423     * @param group the group the key is in.
424     * @param key the key to get.
425     * @param locale the locale to use.
426     * @param value the string to store the key's localised value in.
427     * @returns true if the key was found, otherwise false (in which
428     * case value will be unchanged).
429     */
430    bool
431    get_locale_string (group_name_type const& group,
432                       key_type const&        key,
433                       std::string const&     locale,
434                       value_type&            value) const;
435
436    /**
437     * Get a localised key string value for a specific locale.  If the
438     * value does not exist, is deprecated or obsolete, warn
439     * appropriately.
440     *
441     * @param group the group the key is in.
442     * @param key the key to get.
443     * @param locale the locale to use.
444     * @param priority the priority of the option.
445     * @param value the string to store the key's localised value in.
446     * @returns true if the key was found, otherwise false (in which
447     * case value will be unchanged).
448     */
449    bool
450    get_locale_string (group_name_type const& group,
451                       key_type const&        key,
452                       std::string const&     locale,
453                       priority               priority,
454                       value_type&            value) const;
455
456    /**
457     * Get a key value as a list.
458     *
459     * @param group the group the key is in.
460     * @param key the key to get.
461     * @param container the container to store the key's value in.
462     * The value type must be settable from an istream and be
463     * copyable.  The list must be a container with a standard insert
464     * method.
465     * @returns true if the key was found, otherwise false (in which
466     * case value will be undefined).
467     */
468    template <typename C>
469    bool
470    get_list_value (group_name_type const& group,
471                    key_type const&        key,
472                    C&                     container) const
473    {
474      value_type item_value;
475      if (get_value(group, key, item_value))
476        {
477          value_list items = split_string(item_value,
478                                          this->separator);
479          for (typename value_list::const_iterator pos = items.begin();
480               pos != items.end();
481               ++pos
482               )
483            {
484              typename C::value_type tmp;
485
486              try
487                {
488                  parse_value(*pos, tmp);
489                }
490              catch (parse_value_error const& e)
491                {
492                  size_type line = get_line(group, key);
493                  if (line)
494                    {
495                      error ep(line, group, key, PASSTHROUGH_LGK, e);
496                      log_exception_warning(ep);
497                    }
498                  else
499                    {
500                      error ep(group, key, PASSTHROUGH_GK, e);
501                      log_exception_warning(ep);
502                    }
503                  return false;
504                }
505
506              container.push_back(tmp);
507            }
508          return true;
509        }
510      return false;
511    }
512
513    /**
514     * Get a key value as a list.  If the value does not exist, is
515     * deprecated or obsolete, warn appropriately.
516     *
517     * @param group the group the key is in.
518     * @param key the key to get.
519     * @param priority the priority of the option.
520     * @param container the container to store the key's value in.
521     * The value type must be settable from an istream and be
522     * copyable.  The list must be a container with a standard insert
523     * method.
524     * @returns true if the key was found, otherwise false (in which
525     * case value will be undefined).
526     */
527    template <typename C>
528    bool
529    get_list_value (group_name_type const& group,
530                    key_type const&        key,
531                    priority               priority,
532                    C&                     container) const
533    {
534      bool status = get_list_value(group, key, container);
535      check_priority(group, key, priority, status);
536      return status;
537    }
538
539    /**
540     * Set a key value.
541     *
542     * @param group the group the key is in.
543     * @param key the key to set.
544     * @param value the value to get the key's value from.  This must
545     * allow output to an ostream.
546     */
547    template <typename T>
548    void
549    set_value (group_name_type const& group,
550               key_type const&        key,
551               T const&               value)
552    {
553      set_value(group, key, value, comment_type());
554    }
555
556    /**
557     * Set a key value.
558     *
559     * @param group the group the key is in.
560     * @param key the key to set.
561     * @param value the value to get the key's value from.  This must
562     * allow output to an ostream.
563     * @param comment the comment for this key.
564     */
565    template <typename T>
566    void
567    set_value (group_name_type const& group,
568               key_type const&        key,
569               T const&               value,
570               comment_type const&    comment)
571    {
572      set_value(group, key, value, comment, 0);
573    }
574
575    /**
576     * Set a key value.
577     *
578     * @param group the group the key is in.
579     * @param key the key to set.
580     * @param value the value to get the key's value from.  This must
581     * allow output to an ostream.
582     * @param comment the comment for this key.
583     * @param line the line number in the input file, or 0 otherwise.
584     */
585    template <typename T>
586    void
587    set_value (group_name_type const& group,
588               key_type const&        key,
589               T const&               value,
590               comment_type const&    comment,
591               size_type              line)
592    {
593      std::ostringstream os;
594      os.imbue(std::locale::classic());
595      os << std::boolalpha << value;
596
597      set_group(group, "");
598      group_type *found_group = find_group(group);
599      assert (found_group != 0); // should not fail
600
601      item_map_type& items = std::tr1::get<1>(*found_group);
602
603      typename item_map_type::iterator pos = items.find(key);
604      if (pos != items.end())
605        items.erase(pos);
606      items.insert
607        (typename item_map_type::value_type(key,
608                                            item_type(key, os.str(),
609                                                      comment, line)));
610    }
611
612    /**
613     * Set a key value from a list.
614     *
615     * @param group the group the key is in.
616     * @param key the key to set.
617     * @param begin an iterator referring to the start of the
618     * list. The value type must allow output to an ostream.
619     * @param end an iterator referring to the end of the list.
620     */
621    template <typename I>
622    void
623    set_list_value (group_name_type const& group,
624                    key_type const&        key,
625                    I                      begin,
626                    I                      end)
627    {
628      set_list_value(group, key, begin, end, comment_type());
629    }
630
631    /**
632     * Set a key value from a list.
633     *
634     * @param group the group the key is in.
635     * @param key the key to set.
636     * @param begin an iterator referring to the start of the
637     * list. The value type must allow output to an ostream.
638     * @param end an iterator referring to the end of the list.
639     * @param comment the comment for this key.
640     */
641    template <typename I>
642    void
643    set_list_value (group_name_type const& group,
644                    key_type const&        key,
645                    I                      begin,
646                    I                      end,
647                    comment_type const&    comment)
648    {
649      set_list_value (group, key, begin, end, comment, 0);
650    }
651
652    /**
653     * Set a key value from a list.
654     *
655     * @param group the group the key is in.
656     * @param key the key to set.
657     * @param begin an iterator referring to the start of the
658     * list. The value type must allow output to an ostream.
659     * @param end an iterator referring to the end of the list.
660     * @param comment the comment for this key.
661     * @param line the line number in the input file, or 0 otherwise.
662     */
663    template <typename I>
664    void
665    set_list_value (group_name_type const& group,
666                    key_type const&        key,
667                    I                      begin,
668                    I                      end,
669                    comment_type const&    comment,
670                    size_type              line)
671    {
672      value_type strval;
673
674      for (I pos = begin; pos != end; ++ pos)
675        {
676          std::ostringstream os;
677          os.imbue(std::locale::classic());
678          os << std::boolalpha << *pos;
679          if (os)
680            {
681              strval += os.str();
682              if (pos + 1 != end)
683                strval += this->separator;
684            }
685        }
686
687      set_value (group, key, strval, comment, line);
688    }
689
690    /**
691     * Remove a group.
692     *
693     * @param group the group to remove.
694     */
695    void
696    remove_group (group_name_type const& group);
697
698    /**
699     * Remove a key.
700     *
701     * @param group the group the key is in.
702     * @param key the key to remove.
703     */
704    void
705    remove_key (group_name_type const& group,
706                key_type const&        key);
707
708    /**
709     * Add a basic_keyfile to the basic_keyfile.
710     *
711     * @param rhs the basic_keyfile to add.
712     * @returns the modified basic_keyfile.
713     */
714    basic_keyfile&
715    operator += (basic_keyfile const& rhs);
716
717    /**
718     * Add a basic_keyfile to the basic_keyfile.
719     *
720     * @param lhs the basic_keyfile to add to.
721     * @param rhs the values to add.
722     * @returns the new basic_keyfile.
723     */
724    template <typename _K, typename _P>
725    friend basic_keyfile<_K, _P>
726    operator + (basic_keyfile<_K, _P> const& lhs,
727                basic_keyfile<_K, _P> const& rhs);
728
729    /**
730     * basic_keyfile initialisation from an istream.
731     *
732     * @param stream the stream to input from.
733     * @param kf the basic_keyfile to set.
734     * @returns the stream.
735     */
736    template <class charT, class traits>
737    friend
738    std::basic_istream<charT,traits>&
739    operator >> (std::basic_istream<charT,traits>& stream,
740                 basic_keyfile&                    kf)
741    {
742      basic_keyfile tmp;
743      parse_type state;
744      std::string line;
745
746      state.begin();
747
748      while (std::getline(stream, line))
749      {
750        state.parse_line(line);
751
752        // Insert group
753        if (state.group_set)
754          {
755            if (tmp.has_group(state.group))
756              throw error(state.line_number, DUPLICATE_GROUP, state.group);
757            else
758              tmp.set_group(state.group, state.comment, state.line_number);
759          }
760
761        // Insert item
762        if (state.key_set && state.value_set)
763          {
764            if (tmp.has_key(state.group, state.key))
765              throw error(state.line_number, state.group, DUPLICATE_KEY, state.key);
766            else
767              tmp.set_value(state.group, state.key, state.value, state.comment, state.line_number);
768          }
769      }
770
771      state.end();
772      // TODO: do inserts here as well.
773
774      kf += tmp;
775
776      return stream;
777    }
778
779    /**
780     * basic_keyfile output to an ostream.
781     *
782     * @param stream the stream to output to.
783     * @param kf the basic_keyfile to output.
784     * @returns the stream.
785     */
786    template <class charT, class traits>
787    friend
788    std::basic_ostream<charT,traits>&
789    operator << (std::basic_ostream<charT,traits>& stream,
790                 basic_keyfile const&              kf)
791    {
792      size_type group_count = 0;
793
794      for (typename group_map_type::const_iterator gp = kf.groups.begin();
795           gp != kf.groups.end();
796           ++gp, ++group_count)
797        {
798          if (group_count > 0)
799            stream << '\n';
800
801          group_type const& group = gp->second;
802          group_name_type const& groupname = std::tr1::get<0>(group);
803          comment_type const& comment = std::tr1::get<2>(group);
804
805          if (comment.length() > 0)
806            print_comment(comment, stream);
807
808          stream << '[' << groupname << ']' << '\n';
809
810          item_map_type const& items(std::tr1::get<1>(group));
811          for (typename item_map_type::const_iterator it = items.begin();
812               it != items.end();
813               ++it)
814            {
815              item_type const& item = it->second;
816              key_type const& key(std::tr1::get<0>(item));
817              value_type const& value(std::tr1::get<1>(item));
818              comment_type const& comment(std::tr1::get<2>(item));
819
820              if (comment.length() > 0)
821                print_comment(comment, stream);
822
823              stream << key << '=' << value << '\n';
824            }
825        }
826
827      return stream;
828    }
829
830  private:
831    /**
832     * Find a group by it's name.
833     *
834     * @param group the group to find.
835     * @returns the group, or 0 if not found.
836     */
837    const group_type *
838    find_group (group_name_type const& group) const;
839
840    /**
841     * Find a group by it's name.
842     *
843     * @param group the group to find.
844     * @returns the group, or 0 if not found.
845     */
846    group_type *
847    find_group (group_name_type const& group);
848
849    /**
850     * Find a key by it's group and name.
851     *
852     * @param group the group the key is in.
853     * @param key the key to find
854     * @returns the key, or 0 if not found.
855     */
856    const item_type *
857    find_item (group_name_type const& group,
858               key_type const&        key) const;
859
860    /**
861     * Find a key by it's group and name.
862     *
863     * @param group the group the key is in.
864     * @param key the key to find
865     * @returns the key, or 0 if not found.
866     */
867    item_type *
868    find_item (group_name_type const& group,
869               key_type const&        key);
870
871    /**
872     * Check if a key is missing or present when not permitted.
873     *
874     * @param group the group the key is in.
875     * @param key the key to get.
876     * @param priority the key priority.
877     * @param valid true if key exists, false if not existing.
878     */
879    void
880    check_priority (group_name_type const& group,
881                    key_type const&        key,
882                    priority               priority,
883                    bool                   valid) const;
884
885    /**
886     * Print a comment to a stream.  The comment will have hash ('#')
887     * marks printed at the start of each line.
888     *
889     * @param comment the comment to print.
890     * @param stream the stream to output to.
891     *
892     * @todo Use split string or some general iterator/algorithm
893     * instead of custom string manipulation.  This could be reused by
894     * log_exception_* functions and split_string.
895     */
896    static void
897    print_comment (comment_type const& comment,
898                   std::ostream&       stream);
899
900    /// The top-level groups.
901    group_map_type groups;
902    /// The separator used as a list item delimiter.
903    value_type     separator;
904
905  public:
906    /**
907     * Set a key value from an object method return value.  This is
908     * the same as calling set_value directly, but handles exceptions
909     * being thrown by the object method, which are turned into error
910     * exceptions.
911     *
912     * @param object the object to use.
913     * @param method the object method to call.
914     * @param basic_keyfile the basic_keyfile to use.
915     * @param group the group the key is in.
916     * @param key the key to set.
917     */
918    template<class C, typename T>
919    static void
920    set_object_value (C const&               object,
921                      T                (C::* method)() const,
922                      basic_keyfile&         basic_keyfile,
923                      group_name_type const& group,
924                      key_type const&        key)
925    {
926      try
927        {
928          if (method)
929            basic_keyfile.set_value(group, key, (object.*method)());
930        }
931      catch (std::runtime_error const& e)
932        {
933          throw error(group, key, PASSTHROUGH_GK, e);
934        }
935    }
936
937    /**
938     * Set a key value from an object method return value reference.
939     * This is the same as calling set_value directly, but handles
940     * exceptions being thrown by the object method, which are turned
941     * into error exceptions.
942     *
943     * @param object the object to use.
944     * @param method the object method to call.
945     * @param basic_keyfile the basic_keyfile to use.
946     * @param group the group the key is in.
947     * @param key the key to set.
948     */
949    template<class C, typename T>
950    static void
951    set_object_value (C const&               object,
952                      T const&         (C::* method)() const,
953                      basic_keyfile&         basic_keyfile,
954                      group_name_type const& group,
955                      key_type const&        key)
956    {
957      try
958        {
959          if (method)
960            basic_keyfile.set_value(group, key, (object.*method)());
961        }
962      catch (std::runtime_error const& e)
963        {
964          throw error(group, key, PASSTHROUGH_GK, e);
965        }
966    }
967
968    /**
969     * Set a key list value from an object method return value.  The
970     * method must return a container with begin() and end() methods
971     * which return forward iterators.  This is the same as calling
972     * set_list_value directly, but handles exceptions being thrown by
973     * the object method, which are turned into error exceptions.
974     *
975     * @param object the object to use.
976     * @param method the object method to call.
977     * @param basic_keyfile the basic_keyfile to use.
978     * @param group the group the key is in.
979     * @param key the key to set.
980     */
981    template<class C, typename T>
982    static void
983    set_object_list_value (C const&               object,
984                           T                (C::* method)() const,
985                           basic_keyfile&         basic_keyfile,
986                           group_name_type const& group,
987                           key_type const&        key)
988    {
989      try
990        {
991          if (method)
992            basic_keyfile.set_list_value(group, key,
993                                         (object.*method)().begin(),
994                                         (object.*method)().end());
995        }
996      catch (std::runtime_error const& e)
997        {
998          throw error(group, key, PASSTHROUGH_GK, e);
999        }
1000    }
1001
1002    /**
1003     * Set a key list value from an object method return value.  The
1004     * method must return a container reference with begin() and end()
1005     * methods which return forward iterators.  This is the same as
1006     * calling set_list_value directly, but handles exceptions being
1007     * thrown by the object method, which are turned into error
1008     * exceptions.
1009     *
1010     * @param object the object to use.
1011     * @param method the object method to call.
1012     * @param basic_keyfile the basic_keyfile to use.
1013     * @param group the group the key is in.
1014     * @param key the key to set.
1015     */
1016    template<class C, typename T>
1017    static void
1018    set_object_list_value (C const&               object,
1019                           T const&         (C::* method)() const,
1020                           basic_keyfile&         basic_keyfile,
1021                           group_name_type const& group,
1022                           key_type const&        key)
1023    {
1024      try
1025        {
1026          if (method)
1027            basic_keyfile.set_list_value(group, key,
1028                                         (object.*method)().begin(),
1029                                         (object.*method)().end());
1030        }
1031      catch (std::runtime_error const& e)
1032        {
1033          throw error(group, key, PASSTHROUGH_GK, e);
1034        }
1035    }
1036
1037    /**
1038     * Get a key value and set it in an object using an object method.
1039     * This is the same as calling get_value directly, but handles
1040     * exceptions being thrown by the object method, and
1041     * deserialisation errors, which are turned into error exceptions
1042     * pointing to the group, key and line number in the input file.
1043     *
1044     * @param object the object to use.
1045     * @param method the object method to call.
1046     * @param basic_keyfile the basic_keyfile to use.
1047     * @param group the group the key is in.
1048     * @param key the key to set.
1049     * @param priority the key priority.
1050     */
1051    template<class C, typename T>
1052    static void
1053    get_object_value (C&                      object,
1054                      void              (C::* method)(T param),
1055                      basic_keyfile const&    basic_keyfile,
1056                      group_name_type const&  group,
1057                      key_type const&         key,
1058                      basic_keyfile::priority priority)
1059    {
1060      try
1061        {
1062          T value;
1063          if (basic_keyfile.get_value(group, key, priority, value)
1064              && method)
1065            (object.*method)(value);
1066        }
1067      catch (std::runtime_error const& e)
1068        {
1069          size_type line = basic_keyfile.get_line(group, key);
1070          if (line)
1071            throw error(line, group, key, PASSTHROUGH_LGK, e);
1072          else
1073            throw error(group, key, PASSTHROUGH_GK, e);
1074        }
1075    }
1076
1077    /**
1078     * Get a key value and set it by reference in an object using an
1079     * object method.  This is the same as calling get_value directly,
1080     * but handles exceptions being thrown by the object method, and
1081     * deserialisation errors, which are turned into error exceptions
1082     * pointing to the group, key and line number in the input file.
1083     *
1084     * @param object the object to use.
1085     * @param method the object method to call.
1086     * @param basic_keyfile the basic_keyfile to use.
1087     * @param group the group the key is in.
1088     * @param key the key to set.
1089     * @param priority the key priority.
1090     */
1091    template<class C, typename T>
1092    static void
1093    get_object_value (C&                      object,
1094                      void              (C::* method)(T const& param),
1095                      basic_keyfile const&    basic_keyfile,
1096                      group_name_type const&  group,
1097                      key_type const&         key,
1098                      basic_keyfile::priority priority)
1099    {
1100      try
1101        {
1102          T value;
1103          if (basic_keyfile.get_value(group, key, priority, value)
1104              && method)
1105            (object.*method)(value);
1106        }
1107      catch (std::runtime_error const& e)
1108        {
1109          size_type line = basic_keyfile.get_line(group, key);
1110          if (line)
1111            throw error(line, group, key, PASSTHROUGH_LGK, e);
1112          else
1113            throw error(group, key, PASSTHROUGH_GK, e);
1114        }
1115    }
1116
1117    /**
1118     * Get a key list value and set it in an object using an object
1119     * method.  This is the same as calling get_list_value directly,
1120     * but handles exceptions being thrown by the object method, and
1121     * deserialisation errors, which are turned into error exceptions
1122     * pointing to the group, key and line number in the input file.
1123     *
1124     * @param object the object to use.
1125     * @param method the object method to call.
1126     * @param basic_keyfile the basic_keyfile to use.
1127     * @param group the group the key is in.
1128     * @param key the key to set.
1129     * @param priority the key priority.
1130     */
1131    template<class C, typename T>
1132    static void
1133    get_object_list_value (C&                      object,
1134                           void              (C::* method)(T param),
1135                           basic_keyfile const&    basic_keyfile,
1136                           group_name_type const&  group,
1137                           key_type const&         key,
1138                           basic_keyfile::priority priority)
1139    {
1140      try
1141        {
1142          T value;
1143          if (basic_keyfile.get_list_value(group, key, priority, value)
1144              && method)
1145            (object.*method)(value);
1146        }
1147      catch (std::runtime_error const& e)
1148        {
1149          size_type line = basic_keyfile.get_line(group, key);
1150          if (line)
1151            throw error(line, group, key, PASSTHROUGH_LGK, e);
1152          else
1153            throw error(group, key, PASSTHROUGH_GK, e);
1154          throw error(basic_keyfile.get_line(group, key),
1155                      group, key, e);
1156        }
1157    }
1158
1159    /**
1160     * Get a key list value and set it by reference in an object using
1161     * an object method.  This is the same as calling get_list_value
1162     * directly, but handles exceptions being thrown by the object
1163     * method, and deserialisation errors, which are turned into error
1164     * exceptions pointing to the group, key and line number in the
1165     * input file.
1166     *
1167     * @param object the object to use.
1168     * @param method the object method to call.
1169     * @param basic_keyfile the basic_keyfile to use.
1170     * @param group the group the key is in.
1171     * @param key the key to set.
1172     * @param priority the key priority.
1173     */
1174    template<class C, typename T>
1175    static void
1176    get_object_list_value (C&                      object,
1177                           void              (C::* method)(T const& param),
1178                           basic_keyfile const&    basic_keyfile,
1179                           group_name_type const&  group,
1180                           key_type const&         key,
1181                           basic_keyfile::priority priority)
1182    {
1183      try
1184        {
1185          T value;
1186          if (basic_keyfile.get_list_value(group, key, priority, value)
1187              && method)
1188            (object.*method)(value);
1189        }
1190      catch (std::runtime_error const& e)
1191        {
1192          size_type line = basic_keyfile.get_line(group, key);
1193          if (line)
1194            throw error(line, group, key, PASSTHROUGH_LGK, e);
1195          else
1196            throw error(group, key, PASSTHROUGH_GK, e);
1197          throw error(basic_keyfile.get_line(group, key),
1198                      group, key, e);
1199        }
1200    }
1201  };
1202
1203}
1204
1205#include <sbuild/sbuild-basic-keyfile.tcc>
1206
1207#endif /* SBUILD_BASIC_KEYFILE_H */
1208
1209/*
1210 * Local Variables:
1211 * mode:C++
1212 * End:
1213 */
Note: See TracBrowser for help on using the repository browser.