sbuild-sourcedeps.h

Go to the documentation of this file.
00001 /* Copyright © 2005-2006  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 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); // should not fail
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] == '#') // Comment line
00520           {
00521             if (!comment.empty())
00522               comment += '\n';
00523             comment += line.substr(1);
00524           }
00525         else if (line[0] == '[') // Group
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             // Insert group
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             // Empty line; do nothing.
00552           }
00553         else // Item
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             // Insert item
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 /* SBUILD_SOURCEDEPS_H */
00715 
00716 /*
00717  * Local Variables:
00718  * mode:C++
00719  * End:
00720  */

Generated on Sun Mar 19 12:07:48 2006 for schroot by  doxygen 1.4.6