00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef SBUILD_SOURCEDEPS_H
00021 #define SBUILD_SOURCEDEPS_H
00022
00023 #include <cassert>
00024 #include <iostream>
00025 #include <map>
00026 #include <string>
00027 #include <sstream>
00028 #include <tr1/tuple>
00029
00030 #include <boost/format.hpp>
00031
00032 #include "sbuild-error.h"
00033 #include "sbuild-i18n.h"
00034 #include "sbuild-log.h"
00035 #include "sbuild-parse-value.h"
00036 #include "sbuild-types.h"
00037 #include "sbuild-util.h"
00038
00039 namespace sbuild
00040 {
00041
00045 class sourcedeps
00046 {
00047 private:
00049 typedef std::map<std::string, string_list> dependency_map;
00050
00051 class special
00052 {
00053 enum type
00054 {
00055 COND,
00056 CONDITION,
00057 GLOBAL,
00058 PATCH,
00059 PATCHCOND,
00060 POST,
00061 PRE,
00062 PREPRE,
00063 UNPACK
00064 }
00065 }
00066
00067 public:
00069 enum priority
00070 {
00071 PRIORITY_OPTIONAL,
00072 PRIORITY_REQUIRED,
00073 PRIORITY_DISALLOWED,
00074 PRIORITY_DEPRECATED,
00075 PRIORITY_OBSOLETE
00076 };
00077
00079 typedef runtime_error_custom<sourcedeps> error;
00080
00082 sourcedeps ();
00083
00089 sourcedeps (std::string const& file);
00090
00096 sourcedeps (std::istream& stream);
00097
00099 virtual ~sourcedeps ();
00100
00107 string_list
00108 get_groups () const;
00109
00117 string_list
00118 get_keys (std::string const& group) const;
00119
00126 bool
00127 has_group (std::string const& group) const;
00128
00136 bool
00137 has_key (std::string const& group,
00138 std::string const& key) const;
00139
00147 void
00148 set_group (std::string const& group,
00149 std::string const& comment);
00150
00157 std::string
00158 get_comment (std::string const& group) const;
00159
00167 std::string
00168 get_comment (std::string const& group,
00169 std::string const& key) const;
00170
00181 template <typename T>
00182 bool
00183 get_value (std::string const& group,
00184 std::string const& key,
00185 T& value) const
00186 {
00187 log_debug(DEBUG_INFO) << "Getting sourcedeps group=" << group
00188 << ", key=" << key << std::endl;
00189 const item_type *found_item = find_item(group, key);
00190 if (found_item)
00191 {
00192 std::string const& strval(std::tr1::get<1>(*found_item));
00193 return parse_value(strval, value);
00194 }
00195 log_debug(DEBUG_NOTICE) << "key not found" << std::endl;
00196 return false;
00197 }
00198
00211 template <typename T>
00212 bool
00213 get_value (std::string const& group,
00214 std::string const& key,
00215 priority priority,
00216 T& value) const
00217 {
00218 bool status = get_value(group, key, value);
00219 check_priority(group, key, priority, status);
00220 return status;
00221 }
00222
00232 bool
00233 get_locale_string (std::string const& group,
00234 std::string const& key,
00235 std::string& value) const;
00236
00248 bool
00249 get_locale_string (std::string const& group,
00250 std::string const& key,
00251 priority priority,
00252 std::string& value) const;
00253
00264 bool
00265 get_locale_string (std::string const& group,
00266 std::string const& key,
00267 std::string const& locale,
00268 std::string& value) const;
00269
00283 bool
00284 get_locale_string (std::string const& group,
00285 std::string const& key,
00286 std::string const& locale,
00287 priority priority,
00288 std::string& value) const;
00289
00301 template <typename T, template <typename T> class C>
00302 bool
00303 get_list_value (std::string const& group,
00304 std::string const& key,
00305 C<T>& value) const
00306 {
00307 std::string item_value;
00308 if (get_value(group, key, item_value))
00309 {
00310 C<T> tmplist;
00311 string_list items = split_string(item_value, this->separator);
00312 for (string_list::const_iterator pos = items.begin();
00313 pos != items.end();
00314 ++pos
00315 )
00316 {
00317 T tmpval;
00318 if (parse_value(*pos, tmpval) == false)
00319 return false;
00320 tmplist.push_back(tmpval);
00321 }
00322 value = tmplist;
00323 return true;
00324 }
00325 return false;
00326 }
00327
00341 template <typename T, template <typename T> class C>
00342 bool
00343 get_list_value (std::string const& group,
00344 std::string const& key,
00345 priority priority,
00346 C<T>& value) const
00347 {
00348 bool status = get_list_value(group, key, value);
00349 check_priority(group, key, priority, status);
00350 return status;
00351 }
00352
00361 template <typename T>
00362 void
00363 set_value (std::string const& group,
00364 std::string const& key,
00365 T const& value)
00366 {
00367 set_value(group, key, value, std::string());
00368 }
00369
00379 template <typename T>
00380 void
00381 set_value (std::string const& group,
00382 std::string const& key,
00383 T const& value,
00384 std::string const& comment)
00385 {
00386 std::ostringstream os;
00387 os.imbue(std::locale("C"));
00388 os << std::boolalpha << value;
00389
00390 set_group(group, "");
00391 group_type *found_group = find_group(group);
00392 assert (found_group != 0);
00393
00394 item_map_type& items = std::tr1::get<1>(*found_group);
00395
00396 item_map_type::iterator pos = items.find(key);
00397 if (pos != items.end())
00398 items.erase(pos);
00399
00400 items.insert
00401 (item_map_type::value_type(key,
00402 item_type(key, os.str(), comment)));
00403 }
00404
00414 template <typename T, template <typename T> class C>
00415 void
00416 set_list_value (std::string const& group,
00417 std::string const& key,
00418 C<T> const& value)
00419 {
00420 set_list_value(group, key, value, std::string());
00421 }
00422
00433 template <typename T, template <typename T> class C>
00434 void
00435 set_list_value (std::string const& group,
00436 std::string const& key,
00437 C<T> const& value,
00438 std::string const& comment)
00439 {
00440 std::string strval;
00441
00442 for (typename C<T>::const_iterator pos = value.begin();
00443 pos != value.end();
00444 ++ pos)
00445 {
00446 std::ostringstream os;
00447 os.imbue(std::locale("C"));
00448 os << std::boolalpha << *pos;
00449 if (os)
00450 {
00451 strval += os.str();
00452 if (pos + 1 != value.end())
00453 strval += this->separator;
00454 }
00455 }
00456
00457 set_value (group, key, strval, comment);
00458 }
00459
00465 void
00466 remove_group (std::string const& group);
00467
00474 void
00475 remove_key (std::string const& group,
00476 std::string const& key);
00477
00484 sourcedeps&
00485 operator += (sourcedeps const& rhs);
00486
00494 friend sourcedeps
00495 operator + (sourcedeps const& lhs,
00496 sourcedeps const& rhs);
00497
00501 template <class charT, class traits>
00502 friend
00503 std::basic_istream<charT,traits>&
00504 operator >> (std::basic_istream<charT,traits>& stream,
00505 sourcedeps& kf)
00506 {
00507 sourcedeps tmp;
00508 size_t linecount = 0;
00509 std::string line;
00510 std::string group;
00511 std::string comment;
00512 std::string key;
00513 std::string value;
00514
00515 while (std::getline(stream, line))
00516 {
00517 linecount++;
00518
00519 if (line[0] == '#')
00520 {
00521 if (!comment.empty())
00522 comment += '\n';
00523 comment += line.substr(1);
00524 }
00525 else if (line[0] == '[')
00526 {
00527 std::string::size_type fpos = line.find_first_of(']');
00528 std::string::size_type lpos = line.find_last_of(']');
00529 if (fpos == std::string::npos || fpos != lpos)
00530 {
00531 boost::format fmt(_("line %1%: invalid group entry: %2%"));
00532 fmt % linecount % line;
00533 throw error(fmt);
00534 }
00535 group = line.substr(1, fpos - 1);
00536
00537
00538 if (tmp.has_group(group))
00539 {
00540 log_warning()
00541 << boost::format(_("line %1%: duplicate group entry: %2%"))
00542 % linecount % group
00543 << std::endl;
00544 }
00545 else
00546 tmp.set_group(group, comment);
00547 comment.clear();
00548 }
00549 else if (line.length() == 0)
00550 {
00551
00552 }
00553 else
00554 {
00555 std::string::size_type pos = line.find_first_of('=');
00556 if (pos == std::string::npos)
00557 {
00558 boost::format fmt(_("line %1%: invalid line: %2%"));
00559 fmt % linecount % line;
00560 throw error(fmt);
00561 }
00562 if (pos == 0)
00563 {
00564 boost::format fmt(_("line %1%: no key specified: %2%"));
00565 fmt % linecount % line;
00566 throw error(fmt);
00567 }
00568 key = line.substr(0, pos);
00569 if (pos == line.length() - 1)
00570 value = "";
00571 else
00572 value = line.substr(pos + 1);
00573
00574
00575 if (tmp.has_key(group, key))
00576 {
00577 log_warning()
00578 << boost::format(_("line %1%: group %2%: duplicate key entry: %3%"))
00579 % linecount % group % key
00580 << std::endl;
00581 }
00582 else
00583 tmp.set_value(group, key, value, comment);
00584 comment.clear();
00585 }
00586 }
00587
00588 kf += tmp;
00589
00590 return stream;
00591 }
00592
00596 template <class charT, class traits>
00597 friend
00598 std::basic_ostream<charT,traits>&
00599 operator << (std::basic_ostream<charT,traits>& stream,
00600 sourcedeps const& kf)
00601 {
00602 unsigned int group_count = 0;
00603
00604 for (group_map_type::const_iterator gp = kf.groups.begin();
00605 gp != kf.groups.end();
00606 ++gp, ++group_count)
00607 {
00608 if (group_count > 0)
00609 stream << '\n';
00610
00611 group_type const& group = gp->second;
00612 std::string const& groupname = std::tr1::get<0>(group);
00613 std::string const& comment = std::tr1::get<2>(group);
00614
00615 if (comment.length() > 0)
00616 print_comment(comment, stream);
00617
00618 stream << '[' << groupname << ']' << '\n';
00619
00620 item_map_type const& items(std::tr1::get<1>(group));
00621 for (item_map_type::const_iterator it = items.begin();
00622 it != items.end();
00623 ++it)
00624 {
00625 item_type const& item = it->second;
00626 std::string const& key(std::tr1::get<0>(item));
00627 std::string const& value(std::tr1::get<1>(item));
00628 std::string const& comment(std::tr1::get<2>(item));
00629
00630 if (comment.length() > 0)
00631 print_comment(comment, stream);
00632
00633 stream << key << '=' << value << '\n';
00634 }
00635 }
00636
00637 return stream;
00638 }
00639
00640 private:
00647 const group_type *
00648 find_group (std::string const& group) const;
00649
00656 group_type *
00657 find_group (std::string const& group);
00658
00666 const item_type *
00667 find_item (std::string const& group,
00668 std::string const& key) const;
00669
00677 item_type *
00678 find_item (std::string const& group,
00679 std::string const& key);
00680
00689 void
00690 check_priority (std::string const& group,
00691 std::string const& key,
00692 priority priority,
00693 bool valid) const;
00694
00702 static void
00703 print_comment (std::string const& comment,
00704 std::ostream& stream);
00705
00707 group_map_type groups;
00709 char separator;
00710 };
00711
00712 }
00713
00714 #endif
00715
00716
00717
00718
00719
00720