csbuild-debian-changes.h

Go to the documentation of this file.
00001 /* Copyright © 2005-2007  Roger Leigh <rleigh@debian.org>
00002  *
00003  * schroot is free software: you can redistribute it and/or modify it
00004  * under the terms of the GNU General Public License as published by
00005  * the Free Software Foundation, either version 3 of the License, or
00006  * (at your option) any later version.
00007  *
00008  * schroot is distributed in the hope that it will be useful, but
00009  * WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011  * General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program.  If not, see
00015  * <http://www.gnu.org/licenses/>.
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             // Empty line; do nothing.
00494           }
00495         else // Item
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             // Insert item
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 /* CSBUILD_DEBIAN_CHANGES_H */
00861 
00862 /*
00863  * Local Variables:
00864  * mode:C++
00865  * End:
00866  */

Generated on Mon May 5 09:26:51 2008 for schroot by  doxygen 1.5.5