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 2 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, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00016  * MA  02111-1307  USA
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             // Empty line; do nothing.
00495           }
00496         else // Item
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             // Insert item
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 /* CSBUILD_DEBIAN_CHANGES_H */
00862 
00863 /*
00864  * Local Variables:
00865  * mode:C++
00866  * End:
00867  */

Generated on Sun Jul 8 21:23:54 2007 for schroot by  doxygen 1.5.2