SAGA Adaptor CPI v.1.0
|
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