00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef CSBUILD_DEBIAN_CHANGES_H
00020 #define CSBUILD_DEBIAN_CHANGES_H
00021
00022 #include <sbuild/sbuild-i18n.h>
00023 #include <sbuild/sbuild-log.h>
00024 #include <sbuild/sbuild-parse-error.h>
00025 #include <sbuild/sbuild-parse-value.h>
00026 #include <sbuild/sbuild-types.h>
00027 #include <sbuild/sbuild-tr1types.h>
00028 #include <sbuild/sbuild-util.h>
00029
00030 #include <cassert>
00031 #include <map>
00032 #include <string>
00033 #include <sstream>
00034
00035 #include <boost/format.hpp>
00036
00037 namespace csbuild
00038 {
00039
00045 class debian_changes
00046 {
00047 private:
00048 typedef std::string key_type;
00049 typedef std::vector<std::string> value_type;
00050 typedef unsigned int size_type;
00051
00053 typedef std::tr1::tuple<key_type,value_type,size_type>
00054 item_type;
00055
00057 typedef std::map<key_type,item_type> item_map_type;
00058
00059 public:
00061 enum priority
00062 {
00063 PRIORITY_OPTIONAL,
00064 PRIORITY_REQUIRED,
00065 PRIORITY_DISALLOWED,
00066 PRIORITY_DEPRECATED,
00067 PRIORITY_OBSOLETE
00068 };
00069
00071 enum error_code
00072 {
00073 BAD_FILE,
00074 DEPRECATED_KEY,
00075 DEPRECATED_KEY_NL,
00076 DISALLOWED_KEY,
00077 DISALLOWED_KEY_NL,
00078 DUPLICATE_KEY,
00079 INVALID_LINE,
00080 MISSING_KEY,
00081 MISSING_KEY_NL,
00082 NO_KEY,
00083 OBSOLETE_KEY,
00084 OBSOLETE_KEY_NL,
00085 PASSTHROUGH_K,
00086 PASSTHROUGH_LK
00087 };
00088
00090 typedef sbuild::parse_error<error_code> error;
00091
00093 debian_changes ();
00094
00100 debian_changes (std::string const& file);
00101
00107 debian_changes (std::istream& stream);
00108
00110 virtual ~debian_changes ();
00111
00116 sbuild::string_list
00117 get_keys () const;
00118
00125 bool
00126 has_key (key_type const& key) const;
00127
00134 size_type
00135 get_line (key_type const& key) const;
00136
00146 template <typename T>
00147 bool
00148 get_value (key_type const& key,
00149 T& value) const
00150 {
00151 sbuild::log_debug(sbuild::DEBUG_INFO)
00152 << "Getting debian_changes key=" << key << std::endl;
00153 const item_type *found_item = find_item(key);
00154 if (found_item)
00155 {
00156 value_type const& strval(std::tr1::get<1>(*found_item));
00157 try
00158 {
00159 sbuild::parse_value(strval, value);
00160 return true;
00161 }
00162 catch (sbuild::parse_value_error const& e)
00163 {
00164 size_type line = get_line(key);
00165 if (line)
00166 {
00167 error ep(line, key, PASSTHROUGH_LK, e);
00168 log_exception_warning(ep);
00169 }
00170 else
00171 {
00172 error ep(key, PASSTHROUGH_K, e);
00173 log_exception_warning(ep);
00174 }
00175 return false;
00176 }
00177 }
00178 sbuild::log_debug(sbuild::DEBUG_NOTICE)
00179 << "key not found" << std::endl;
00180 return false;
00181 }
00182
00194 template <typename T>
00195 bool
00196 get_value (key_type const& key,
00197 priority priority,
00198 T& value) const
00199 {
00200 bool status = get_value(key, value);
00201 check_priority(key, priority, status);
00202 return status;
00203 }
00204
00213 bool
00214 get_value (key_type const& key,
00215 value_type& value) const;
00216
00227 bool
00228 get_value (key_type const& key,
00229 priority priority,
00230 value_type& value) const;
00231
00245 template <typename C>
00246 bool
00247 get_list_value (key_type const& key,
00248 C& container,
00249 std::string const& separator) const
00250 {
00251 value_type item_value;
00252 if (get_value(key, item_value))
00253 {
00254 for (value_type::const_iterator vpos = item_value.begin();
00255 vpos != item_value.end();
00256 ++vpos)
00257 {
00258 sbuild::string_list items =
00259 sbuild::split_string(*vpos, std::string(1, separator));
00260 for (sbuild::string_list::const_iterator pos = items.begin();
00261 pos != items.end();
00262 ++pos
00263 )
00264 {
00265 typename C::value_type tmp;
00266
00267 try
00268 {
00269 sbuild::parse_value(*pos, tmp);
00270 }
00271 catch (sbuild::parse_value_error const& e)
00272 {
00273 size_type line = get_line(key);
00274 if (line)
00275 {
00276 error ep(line, key, PASSTHROUGH_LK, e);
00277 log_exception_warning(ep);
00278 }
00279 else
00280 {
00281 error ep(key, PASSTHROUGH_K, e);
00282 log_exception_warning(ep);
00283 }
00284 return false;
00285 }
00286
00287 container.push_back(tmp);
00288 }
00289 }
00290 return true;
00291 }
00292 return false;
00293 }
00294
00308 template <typename C>
00309 bool
00310 get_list_value (key_type const& key,
00311 priority priority,
00312 C& container) const
00313 {
00314 bool status = get_list_value(key, container);
00315 check_priority(key, priority, status);
00316 return status;
00317 }
00318
00326 template <typename T>
00327 void
00328 set_value (key_type const& key,
00329 T const& value)
00330 {
00331 set_value(key, value, 0);
00332 }
00333
00342 template <typename T>
00343 void
00344 set_value (key_type const& key,
00345 T const& value,
00346 size_type line)
00347 {
00348 std::ostringstream os;
00349 os.imbue(std::locale::classic());
00350 os << std::boolalpha << value;
00351 value_type val;
00352 val.push_back(os.str());
00353
00354 item_map_type::iterator pos = items.find(key);
00355 if (pos != items.end())
00356 items.erase(pos);
00357 items.insert
00358 (item_map_type::value_type(key,
00359 item_type(key, val, line)));
00360 }
00361
00368 void
00369 set_value (key_type const& key,
00370 value_type const& value)
00371 {
00372 set_value(key, value, 0);
00373 }
00374
00382 void
00383 set_value (key_type const& key,
00384 value_type const& value,
00385 size_type line);
00386
00395 template <typename I>
00396 void
00397 set_list_value (key_type const& key,
00398 I begin,
00399 I end)
00400 {
00401 set_list_value (key, begin, end, 0);
00402 }
00403
00414 template <typename I>
00415 void
00416 set_list_value (key_type const& key,
00417 I begin,
00418 I end,
00419 std::string const& separator,
00420 size_type line)
00421 {
00422 std::string strval;
00423
00424 for (I pos = begin; pos != end; ++ pos)
00425 {
00426 std::ostringstream os;
00427 os.imbue(std::locale::classic());
00428 os << std::boolalpha << *pos;
00429 if (os)
00430 {
00431 strval += os.str();
00432 if (pos + 1 != end)
00433 strval += separator;
00434 }
00435 }
00436
00437 set_value (key, strval, line);
00438 }
00439
00445 void
00446 remove_key (key_type const& key);
00447
00454 debian_changes&
00455 operator += (debian_changes const& rhs);
00456
00464 friend debian_changes
00465 operator + (debian_changes const& lhs,
00466 debian_changes const& rhs);
00467
00475 template <class charT, class traits>
00476 friend
00477 std::basic_istream<charT,traits>&
00478 operator >> (std::basic_istream<charT,traits>& stream,
00479 debian_changes& dc)
00480 {
00481 debian_changes tmp;
00482 size_t linecount = 0;
00483 std::string line;
00484 std::string key;
00485 std::string value;
00486
00487 while (std::getline(stream, line))
00488 {
00489 linecount++;
00490
00491 if (line.length() == 0)
00492 {
00493
00494 }
00495 else
00496 {
00497 std::string::size_type pos = line.find_first_of('=');
00498 if (pos == std::string::npos)
00499 throw error(linecount, INVALID_LINE, line);
00500 if (pos == 0)
00501 throw error(linecount, NO_KEY, line);
00502 key = line.substr(0, pos);
00503 if (pos == line.length() - 1)
00504 value = "";
00505 else
00506 value = line.substr(pos + 1);
00507
00508
00509 if (tmp.has_key(key))
00510 throw error(linecount, DUPLICATE_KEY, key);
00511 else
00512 tmp.set_value(key, value, linecount);
00513 }
00514 }
00515
00516 dc += tmp;
00517
00518 return stream;
00519 }
00520
00528 template <class charT, class traits>
00529 friend
00530 std::basic_ostream<charT,traits>&
00531 operator << (std::basic_ostream<charT,traits>& stream,
00532 debian_changes const& dc)
00533 {
00534 size_type group_count = 0;
00535
00536 for (item_map_type::const_iterator it = dc.items.begin();
00537 it != dc.items.end();
00538 ++it)
00539 {
00540 item_type const& item = it->second;
00541 key_type const& key(std::tr1::get<0>(item));
00542 value_type const& value(std::tr1::get<1>(item));
00543
00544 stream << key << '=' << value << '\n';
00545 }
00546
00547 return stream;
00548 }
00549
00550 private:
00557 const item_type *
00558 find_item (key_type const& key) const;
00559
00566 item_type *
00567 find_item (key_type const& key);
00568
00576 void
00577 check_priority (key_type const& key,
00578 priority priority,
00579 bool valid) const;
00580
00582 item_map_type items;
00583
00584 public:
00596 template<class C, typename T>
00597 static void
00598 set_object_value (C const& object,
00599 T (C::* method)() const,
00600 debian_changes& debian_changes,
00601 debian_changes::key_type const& key)
00602 {
00603 try
00604 {
00605 debian_changes.set_value(key, (object.*method)());
00606 }
00607 catch (std::runtime_error const& e)
00608 {
00609 throw error(key, PASSTHROUGH_K, e);
00610 }
00611 }
00612
00624 template<class C, typename T>
00625 static void
00626 set_object_value (C const& object,
00627 T const& (C::* method)() const,
00628 debian_changes& debian_changes,
00629 debian_changes::key_type const& key)
00630 {
00631 try
00632 {
00633 debian_changes.set_value(key, (object.*method)());
00634 }
00635 catch (std::runtime_error const& e)
00636 {
00637 throw error(key, PASSTHROUGH_K, e);
00638 }
00639 }
00640
00653 template<class C, typename T>
00654 static void
00655 set_object_list_value (C const& object,
00656 T (C::* method)() const,
00657 debian_changes& debian_changes,
00658 debian_changes::key_type const& key)
00659 {
00660 try
00661 {
00662 debian_changes.set_list_value(key,
00663 (object.*method)().begin(),
00664 (object.*method)().end());
00665 }
00666 catch (std::runtime_error const& e)
00667 {
00668 throw error(key, PASSTHROUGH_K, e);
00669 }
00670 }
00671
00685 template<class C, typename T>
00686 static void
00687 set_object_list_value (C const& object,
00688 T const& (C::* method)() const,
00689 debian_changes& debian_changes,
00690 debian_changes::key_type const& key)
00691 {
00692 try
00693 {
00694 debian_changes.set_list_value(key,
00695 (object.*method)().begin(),
00696 (object.*method)().end());
00697 }
00698 catch (std::runtime_error const& e)
00699 {
00700 throw error(key, PASSTHROUGH_K, e);
00701 }
00702 }
00703
00717 template<class C, typename T>
00718 static void
00719 get_object_value (C& object,
00720 void (C::* method)(T param),
00721 debian_changes const& debian_changes,
00722 debian_changes::key_type const& key,
00723 debian_changes::priority priority)
00724 {
00725 try
00726 {
00727 T value;
00728 if (debian_changes.get_value(key, priority, value))
00729 (object.*method)(value);
00730 }
00731 catch (std::runtime_error const& e)
00732 {
00733 size_type line = debian_changes.get_line(key);
00734 if (line)
00735 throw error(line, key, PASSTHROUGH_LK, e);
00736 else
00737 throw error(key, PASSTHROUGH_K, e);
00738 }
00739 }
00740
00754 template<class C, typename T>
00755 static void
00756 get_object_value (C& object,
00757 void (C::* method)(T const& param),
00758 debian_changes const& debian_changes,
00759 debian_changes::key_type const& key,
00760 debian_changes::priority priority)
00761 {
00762 try
00763 {
00764 T value;
00765 if (debian_changes.get_value(key, priority, value))
00766 (object.*method)(value);
00767 }
00768 catch (std::runtime_error const& e)
00769 {
00770 size_type line = debian_changes.get_line(key);
00771 if (line)
00772 throw error(line, key, PASSTHROUGH_LK, e);
00773 else
00774 throw error(key, PASSTHROUGH_K, e);
00775 }
00776 }
00777
00791 template<class C, typename T>
00792 static void
00793 get_object_list_value (C& object,
00794 void (C::* method)(T param),
00795 debian_changes const& debian_changes,
00796 debian_changes::key_type const& key,
00797 debian_changes::priority priority)
00798 {
00799 try
00800 {
00801 T value;
00802 if (debian_changes.get_list_value(key, priority, value))
00803 (object.*method)(value);
00804 }
00805 catch (std::runtime_error const& e)
00806 {
00807 size_type line = debian_changes.get_line(key);
00808 if (line)
00809 throw error(line, key, PASSTHROUGH_LK, e);
00810 else
00811 throw error(key, PASSTHROUGH_K, e);
00812 throw error(debian_changes.get_line(key),
00813 key, e);
00814 }
00815 }
00816
00831 template<class C, typename T>
00832 static void
00833 get_object_list_value (C& object,
00834 void (C::* method)(T const& param),
00835 debian_changes const& debian_changes,
00836 debian_changes::key_type const& key,
00837 debian_changes::priority priority)
00838 {
00839 try
00840 {
00841 T value;
00842 if (debian_changes.get_list_value(key, priority, value))
00843 (object.*method)(value);
00844 }
00845 catch (std::runtime_error const& e)
00846 {
00847 size_type line = debian_changes.get_line(key);
00848 if (line)
00849 throw error(line, key, PASSTHROUGH_LK, e);
00850 else
00851 throw error(key, PASSTHROUGH_K, e);
00852 throw error(debian_changes.get_line(key),
00853 key, e);
00854 }
00855 }
00856 };
00857
00858 }
00859
00860 #endif
00861
00862
00863
00864
00865
00866