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

Revision 24167, 12.8 KB checked in by broder, 15 years ago (diff)
Import schroot upstream into subversion.
Line 
1/* Copyright © 2005-2008  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#include <algorithm>
20#include <fstream>
21#include <set>
22
23template <typename K, typename P>
24sbuild::basic_keyfile<K, P>::basic_keyfile ():
25  groups(),
26  separator(",")
27{
28}
29
30template <typename K, typename P>
31sbuild::basic_keyfile<K, P>::basic_keyfile (std::string const& file):
32  groups(),
33  separator(",")
34{
35  std::ifstream fs(file.c_str());
36  if (fs)
37    {
38      fs.imbue(std::locale::classic());
39      fs >> *this;
40    }
41  else
42    {
43      throw error(file, BAD_FILE);
44    }
45}
46
47template <typename K, typename P>
48sbuild::basic_keyfile<K, P>::basic_keyfile (std::istream& stream):
49  groups(),
50  separator(",")
51{
52  stream >> *this;
53}
54
55template <typename K, typename P>
56sbuild::basic_keyfile<K, P>::~basic_keyfile()
57{
58}
59
60template <typename K, typename P>
61typename sbuild::basic_keyfile<K, P>::group_list
62sbuild::basic_keyfile<K, P>::get_groups () const
63{
64  group_list ret;
65
66  for (typename group_map_type::const_iterator pos = this->groups.begin();
67       pos != this->groups.end();
68       ++pos)
69    ret.push_back(pos->first);
70
71  return ret;
72}
73
74template <typename K, typename P>
75typename sbuild::basic_keyfile<K, P>::key_list
76sbuild::basic_keyfile<K, P>::get_keys (group_name_type const& group) const
77{
78  key_list ret;
79
80  const group_type *found_group = find_group(group);
81  if (found_group)
82    {
83      item_map_type const& items(std::tr1::get<1>(*found_group));
84      for (typename item_map_type::const_iterator pos = items.begin();
85           pos != items.end();
86           ++pos)
87        ret.push_back(pos->first);
88    }
89
90  return ret;
91}
92
93template <typename K, typename P>
94void
95sbuild::basic_keyfile<K, P>::check_keys (group_name_type const& group,
96                                         key_list const&        keys) const
97{
98  const string_list total(get_keys(group));
99
100  const string_set a(total.begin(), total.end());
101  const string_set b(keys.begin(), keys.end());
102
103  string_set unused;
104
105  set_difference(a.begin(), a.end(),
106                 b.begin(), b.end(),
107                 inserter(unused, unused.begin()));
108
109  for (string_set::const_iterator pos = unused.begin();
110       pos != unused.end();
111       ++pos)
112    {
113      size_type line = get_line(group, *pos);
114      error e(line, group, UNKNOWN_KEY, *pos);
115      e.set_reason(_("This option may be present in a newer version"));
116      log_exception_warning(e);
117    }
118}
119
120template <typename K, typename P>
121bool
122sbuild::basic_keyfile<K, P>::has_group (group_name_type const& group) const
123{
124  return (find_group(group) != 0);
125}
126
127template <typename K, typename P>
128bool
129sbuild::basic_keyfile<K, P>::has_key (group_name_type const& group,
130                                      key_type const&        key) const
131{
132  return (find_item(group, key) != 0);
133}
134
135template <typename K, typename P>
136void
137sbuild::basic_keyfile<K, P>::set_group (group_name_type const& group,
138                                        comment_type const&    comment)
139{
140  set_group(group, comment, 0);
141}
142
143template <typename K, typename P>
144void
145sbuild::basic_keyfile<K, P>::set_group (group_name_type const& group,
146                                        comment_type const&    comment,
147                                        size_type              line)
148{
149  if (!has_group(group))
150    this->groups.insert
151      (typename group_map_type::value_type(group,
152                                           group_type(group,
153                                                      item_map_type(),
154                                                      comment,
155                                                      line)));
156}
157
158template <typename K, typename P>
159typename sbuild::basic_keyfile<K, P>::comment_type
160sbuild::basic_keyfile<K, P>::get_comment (group_name_type const& group) const
161{
162  const group_type *found_group = find_group(group);
163  if (found_group)
164    return std::tr1::get<2>(*found_group);
165  else
166    return comment_type();
167}
168
169template <typename K, typename P>
170typename sbuild::basic_keyfile<K, P>::comment_type
171sbuild::basic_keyfile<K, P>::get_comment (group_name_type const& group,
172                                          key_type const&        key) const
173{
174  const item_type *found_item = find_item(group, key);
175  if (found_item)
176      return std::tr1::get<2>(*found_item);
177  else
178    return comment_type();
179}
180
181template <typename K, typename P>
182typename sbuild::basic_keyfile<K, P>::size_type
183sbuild::basic_keyfile<K, P>::get_line (group_name_type const& group) const
184{
185  const group_type *found_group = find_group(group);
186  if (found_group)
187    return std::tr1::get<3>(*found_group);
188  else
189    return 0;
190}
191
192template <typename K, typename P>
193typename sbuild::basic_keyfile<K, P>::size_type
194sbuild::basic_keyfile<K, P>::get_line (group_name_type const& group,
195                                       key_type const&        key) const
196{
197  const item_type *found_item = find_item(group, key);
198  if (found_item)
199      return std::tr1::get<3>(*found_item);
200  else
201    return 0;
202}
203
204template <typename K, typename P>
205bool
206sbuild::basic_keyfile<K, P>::get_locale_string (group_name_type const& group,
207                                                key_type const&        key,
208                                                value_type&            value) const
209{
210  std::string localename;
211  try
212    {
213      localename = std::locale("").name();
214    }
215  catch (std::runtime_error const& e) // Invalid locale
216    {
217      localename = std::locale::classic();
218    }
219  std::string::size_type pos;
220  bool status = false;
221
222  // Strip off any charset.
223  if ((pos = localename.find_first_of('.')) != std::string::npos)
224    localename = localename.substr(0, pos);
225  status = get_locale_string(group, key, localename, value);
226
227  // Strip off territory.
228  if (status == false &&
229      (pos = localename.find_first_of('_')) != std::string::npos)
230    {
231      localename = localename.substr(0, pos);
232      status = get_locale_string(group, key, localename, value);
233    }
234
235  // Fall back to non-localised version.
236  if (status == false)
237    status = get_value(group, key, value);
238
239  return status;
240}
241
242template <typename K, typename P>
243bool
244sbuild::basic_keyfile<K, P>::get_locale_string (group_name_type const& group,
245                                                key_type const&        key,
246                                                priority               priority,
247                                                value_type&            value) const
248{
249  bool status = get_locale_string(group, key, value);
250  check_priority(group, key, priority, status);
251  return status;
252}
253
254template <typename K, typename P>
255bool
256sbuild::basic_keyfile<K, P>::get_locale_string (group_name_type const& group,
257                                                key_type const&        key,
258                                                std::string const&     locale,
259                                                value_type&            value) const
260{
261  std::string lkey = key + '[' + locale + ']';
262  return get_value(group, lkey, value);
263}
264
265template <typename K, typename P>
266bool
267sbuild::basic_keyfile<K, P>::get_locale_string (group_name_type const& group,
268                                                key_type const&        key,
269                                                std::string const&     locale,
270                                                priority               priority,
271                                                value_type&            value) const
272{
273  bool status = get_locale_string(group, key, locale, value);
274  check_priority(group, key, priority, status);
275  return status;
276}
277
278template <typename K, typename P>
279void
280sbuild::basic_keyfile<K, P>::remove_group (group_name_type const& group)
281{
282  typename group_map_type::iterator pos = this->groups.find(group);
283  if (pos != this->groups.end())
284    this->groups.erase(pos);
285}
286
287template <typename K, typename P>
288void
289sbuild::basic_keyfile<K, P>::remove_key (group_name_type const& group,
290                                         key_type const&        key)
291{
292  group_type *found_group = find_group(group);
293  if (found_group)
294    {
295      item_map_type& items = std::tr1::get<1>(*found_group);
296      typename item_map_type::iterator pos = items.find(key);
297      if (pos != items.end())
298        items.erase(pos);
299    }
300}
301
302template <typename K, typename P>
303sbuild::basic_keyfile<K, P>&
304sbuild::basic_keyfile<K, P>::operator += (basic_keyfile const& rhs)
305{
306  for (typename group_map_type::const_iterator gp = rhs.groups.begin();
307       gp != rhs.groups.end();
308       ++gp)
309    {
310      group_type const& group = gp->second;
311      group_name_type const& groupname = std::tr1::get<0>(group);
312      comment_type const& comment = std::tr1::get<2>(group);
313      size_type const& line = std::tr1::get<3>(group);
314      set_group(groupname, comment, line);
315
316      item_map_type const& items(std::tr1::get<1>(group));
317      for (typename item_map_type::const_iterator it = items.begin();
318           it != items.end();
319           ++it)
320        {
321          item_type const& item = it->second;
322          key_type const& key(std::tr1::get<0>(item));
323          value_type const& value(std::tr1::get<1>(item));
324          comment_type const& comment(std::tr1::get<2>(item));
325          size_type const& line(std::tr1::get<3>(item));
326          set_value(groupname, key, value, comment, line);
327        }
328    }
329  return *this;
330}
331
332template <typename _K>
333sbuild::basic_keyfile<_K>
334operator + (sbuild::basic_keyfile<_K> const& lhs,
335            sbuild::basic_keyfile<_K> const& rhs)
336{
337  sbuild::basic_keyfile<_K> ret(lhs);
338  ret += rhs;
339  return ret;
340}
341
342template <typename K, typename P>
343const typename sbuild::basic_keyfile<K, P>::group_type *
344sbuild::basic_keyfile<K, P>::find_group (group_name_type const& group) const
345{
346  typename group_map_type::const_iterator pos = this->groups.find(group);
347  if (pos != this->groups.end())
348    return &pos->second;
349
350  return 0;
351}
352
353template <typename K, typename P>
354typename sbuild::basic_keyfile<K, P>::group_type *
355sbuild::basic_keyfile<K, P>::find_group (group_name_type const& group)
356{
357  typename group_map_type::iterator pos = this->groups.find(group);
358  if (pos != this->groups.end())
359    return &pos->second;
360
361  return 0;
362}
363
364template <typename K, typename P>
365const typename sbuild::basic_keyfile<K, P>::item_type *
366sbuild::basic_keyfile<K, P>::find_item (group_name_type const& group,
367                                        key_type const&        key) const
368{
369  const group_type *found_group = find_group(group);
370  if (found_group)
371    {
372      item_map_type const& items = std::tr1::get<1>(*found_group);
373      typename item_map_type::const_iterator pos = items.find(key);
374      if (pos != items.end())
375        return &pos->second;
376    }
377
378  return 0;
379}
380
381template <typename K, typename P>
382typename sbuild::basic_keyfile<K, P>::item_type *
383sbuild::basic_keyfile<K, P>::find_item (group_name_type const& group,
384                                        key_type const&        key)
385{
386  group_type *found_group = find_group(group);
387  if (found_group)
388    {
389      item_map_type& items = std::tr1::get<1>(*found_group);
390      typename item_map_type::iterator pos = items.find(key);
391      if (pos != items.end())
392        return &pos->second;
393    }
394
395  return 0;
396}
397
398template <typename K, typename P>
399void
400sbuild::basic_keyfile<K, P>::print_comment (comment_type const& comment,
401                                            std::ostream&       stream)
402{
403  std::string::size_type last_pos = 0;
404  std::string::size_type pos = comment.find_first_of('\n', last_pos);
405
406  while (1)
407    {
408      if (last_pos == pos)
409        stream << "#\n";
410      else
411        stream << '#' << comment.substr(last_pos, pos - last_pos) << '\n';
412
413      // Find next
414      if (pos < comment.length() - 1)
415        {
416          last_pos = pos + 1;
417          pos = comment.find_first_of('\n', last_pos);
418        }
419      else
420        break;
421    }
422}
423
424template <typename K, typename P>
425void
426sbuild::basic_keyfile<K, P>::check_priority (group_name_type const& group,
427                                             key_type const&        key,
428                                             priority               priority,
429                                             bool                   valid) const
430{
431  if (valid == false)
432    {
433      size_type gline = get_line(group);
434
435      switch (priority)
436        {
437        case PRIORITY_REQUIRED:
438          {
439            if (gline)
440              throw error(gline, group, MISSING_KEY, key);
441            else
442              throw error(group, MISSING_KEY_NL, key);
443          }
444          break;
445        default:
446          break;
447        }
448    }
449  else
450    {
451      size_type line = get_line(group, key);
452
453      switch (priority)
454        {
455        case PRIORITY_DEPRECATED:
456          {
457            if (line)
458              {
459                error e(line, group, DEPRECATED_KEY, key);
460                e.set_reason(_("This option will be removed in the future; please update your configuration"));
461                log_exception_warning(e);
462              }
463            else
464              {
465                error e(group, DEPRECATED_KEY_NL, key);
466                e.set_reason(_("This option will be removed in the future; please update your configuration"));
467                log_exception_warning(e);
468              }
469          }
470          break;
471        case PRIORITY_OBSOLETE:
472          {
473            if (line)
474              {
475                error e(line, group, OBSOLETE_KEY, key);
476                e.set_reason(_("This option has been removed, and no longer has any effect"));
477                log_exception_warning(e);
478              }
479            else
480              {
481                error e(group, OBSOLETE_KEY_NL, key);
482                e.set_reason(_("This option has been removed, and no longer has any effect"));
483                log_exception_warning(e);
484              }
485          }
486          break;
487        case PRIORITY_DISALLOWED:
488          {
489            if (line)
490              throw error(line, group, DISALLOWED_KEY, key);
491            else
492              throw error(group, DISALLOWED_KEY_NL, key);
493          }
494          break;
495        default:
496          break;
497        }
498    }
499}
500
501/*
502 * Local Variables:
503 * mode:C++
504 * End:
505 */
Note: See TracBrowser for help on using the repository browser.