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