SAGA Adaptor CPI v.1.0
utils.cpp
Go to the documentation of this file.
00001 //  Copyright (c) 2005-2006 Andre Merzky (andre@merzky.net)
00002 // 
00003 //  Use, modification and distribution is subject to the Boost Software
00004 //  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
00005 //  http://www.boost.org/LICENSE_1_0.txt)
00006 
00007 #include <boost/config.hpp>
00008 
00009 #include <set>
00010 #include <string>
00011 #include <vector>
00012 #include <algorithm>
00013 
00014 #include <boost/bind.hpp>
00015 #include <boost/algorithm/string/find.hpp>
00016 #include <boost/algorithm/string/split.hpp>
00017 #include <boost/algorithm/string/classification.hpp>
00018 
00019 #include <saga/saga/adaptors/utils/utils.hpp>
00020 
00021 namespace saga
00022 {
00023   namespace adaptors
00024   {
00025     namespace utils
00026     {
00028       std::vector <std::string> split (std::string line,
00029                                        char        delim, 
00030                                        int         number)
00031       {
00032         std::vector <std::string> list;
00033 
00034         if (number == 0)    // nothing to do (asking for 0 elements)
00035           return list;
00036 
00037         std::string split_at (1, delim);
00038         boost::split (list, line, boost::is_any_of (split_at)); 
00039 
00040 
00041         if (number < 0)    // number of elems does not matter
00042           return list;
00043 
00044         // concatenate the superfluous elements to the last element
00045         for (std::size_t i = number; i < list.size(); ++i)
00046         {
00047           list[number-1] += delim;
00048           list[number-1] += list[i];
00049         }
00050 
00051         // adjust the list size
00052         list.resize (number);
00053         return list;
00054       }
00055 
00056 
00058       // The command line splitting below is taken from the Boost.ProgramOptions
00059       // library.
00060 
00061       // Copyright Vladimir Prus 2002-2004.
00062       // Distributed under the Boost Software License, Version 1.0.
00063       // (See accompanying file LICENSE_1_0.txt
00064       // or copy at http://www.boost.org/LICENSE_1_0.txt)
00065 
00066       // Take a command line string and splits in into tokens, according
00067       // to the following rules
00068       //
00069       //  - Arguments are delimited by white space, which is either a space or 
00070       //    a tab.
00071       //  - A string surrounded by double quotation marks is interpreted as a 
00072       //    single argument, regardless of white space contained within. A 
00073       //    quoted string can be embedded in an argument. 
00074       //  - A double quotation mark preceded by a backslash, \", is interpreted 
00075       //    as a literal double quotation mark (").
00076       //  - Backslashes are interpreted literally, unless they immediately precede 
00077       //    a double quotation mark.
00078       //
00079       // These rules are a slight modification of the windows command line 
00080       // processor rules, as described here:
00081       //    http://article.gmane.org/gmane.comp.lib.boost.user/3005
00082       //    http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
00083       //
00084       std::vector <std::string> split_commandline (std::string const & line)
00085       {
00086         using namespace std;
00087         vector <string> result;
00088 
00089         string::const_iterator i = line.begin ();
00090         string::const_iterator e = line.end   ();
00091 
00092         for (  ; i != e; ++i )
00093           if ( ! isspace ((unsigned char)*i) )
00094             break;
00095 
00096         if ( i != e ) 
00097         {
00098           string current;
00099           bool   inside_quoted   = false;
00100           int    backslash_count = 0;
00101 
00102           for (; i != e; ++i) 
00103           {
00104             if (*i == '\\') 
00105             {
00106               // just count backslashes 
00107               ++backslash_count;
00108             }
00109             else if ( *i == '"' ) 
00110             {
00111               // '"' preceded by a backslash is a literal quote
00112               // the backslash which quoted is removed
00113               if ( backslash_count > 0 ) 
00114               {
00115                 current += '"';
00116                 --backslash_count;
00117               }
00118               // '"' not preceded by a backslash limits a quote
00119               else 
00120               {
00121                 inside_quoted = ! inside_quoted;
00122               }
00123             } 
00124             else 
00125             {
00126               // Not quote or backslash. All accumulated backslashes should be
00127               // added
00128               if ( backslash_count ) 
00129               {
00130                 current.append (backslash_count, '\\');
00131                 backslash_count = 0;
00132               }
00133 
00134               if ( isspace ((unsigned char) *i) && ! inside_quoted ) 
00135               {
00136                 // Space outside quoted section terminate the current argument
00137                 result.push_back (current);
00138                 current.resize   (0);
00139 
00140                 for (  ; i != e && isspace ((unsigned char) *i); ++i ) 
00141                   ;
00142 
00143                 --i;
00144               } 
00145               else 
00146               {                  
00147                 current += *i;
00148               }
00149             }
00150           }
00151 
00152           // If we have trailing backslashes, add them
00153           if ( backslash_count )
00154           {
00155             current.append (backslash_count, '\\');
00156           }
00157 
00158           // If we have non-empty 'current' or we're still in quoted
00159           // section (even if 'current' is empty), add the last token.
00160           if ( ! current.empty () || inside_quoted )
00161           {
00162             result.push_back (current);        
00163           }
00164           // FIXME: we SHOULD thrown an exception here, non-matching quotes
00165           // are a BadParameter -- AM
00166         }
00167 
00168         return result;
00169       }
00170 
00172       std::vector <std::string> head (std::size_t n, 
00173                                       std::vector <std::string> const& in)
00174       {
00175         std::vector <std::string> out;
00176         std::copy(in.begin(), (std::min)(in.end(), in.begin()+n), 
00177             std::back_inserter(out));
00178         return out;
00179       }
00180 
00182       std::vector <std::string> tail (std::size_t n, 
00183                                       std::vector <std::string> const& in)
00184       {
00185         std::vector <std::string> out;
00186         std::copy((std::min)(in.begin()+in.size()-n, in.end()), in.end(), 
00187             std::back_inserter(out));
00188         return out;
00189       }
00190 
00192       // lines should not include newlines
00193       std::vector <std::string> rev  (std::vector <std::string> const& in)
00194       {
00195         std::vector <std::string> out;
00196         std::vector <std::string>::const_iterator end = in.end();
00197         for (std::vector <std::string>::const_iterator it = in.begin(); 
00198             it != end; ++it)
00199         {
00200             std::string line;
00201             std::reverse_copy((*it).begin(), (*it).end(), 
00202                 std::back_inserter(line));
00203             out.push_back(line);
00204         }
00205         return out;
00206       }
00207 
00209       std::vector <std::string> tac  (std::vector <std::string> const& in)
00210       {
00211         std::vector <std::string> out;
00212         std::reverse_copy(in.begin(), in.end(), std::back_inserter(out));
00213         return out;
00214       }
00215 
00217       bool find(std::string const& s, std::string const& pattern)
00218       {
00219           return s.find(pattern) == std::string::npos;
00220       }
00221 
00222       std::vector <std::string> grep (std::string pattern, 
00223                                       std::vector <std::string> const& in)
00224       {
00225         std::vector <std::string> out;
00226         std::remove_copy_if(in.begin(), in.end(), std::back_inserter(out),
00227             TR1::bind(find, TR1::placeholders::_1, pattern));
00228         return out;
00229       }
00230 
00231     } // namespace utils
00232   } // namespace adaptors 
00233 } // namespace saga
00234 
00235 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines