00001 /* 00002 00003 Copyright (C) 1996-2012 John W. Eaton 00004 00005 This file is part of Octave. 00006 00007 Octave is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 Octave is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with Octave; see the file COPYING. If not, see 00019 <http://www.gnu.org/licenses/>. 00020 00021 */ 00022 00023 /* 00024 00025 The function string_vector::list_in_columns was adapted from a similar 00026 function distributed in the GNU file utilities, copyright (C) 85, 88, 00027 90, 91, 95, 1996 Free Software Foundation, Inc. 00028 00029 */ 00030 00031 #ifdef HAVE_CONFIG_H 00032 #include <config.h> 00033 #endif 00034 00035 #include <iostream> 00036 #include <string> 00037 00038 #include "cmd-edit.h" 00039 #include "lo-utils.h" 00040 #include "str-vec.h" 00041 00042 // FIXME -- isn't there some STL trick that could be used to make this 00043 // work for all STL containers of std::string objects? 00044 00045 string_vector::string_vector (const std::list<std::string>& lst) 00046 : Array<std::string> () 00047 { 00048 size_t n = lst.size (); 00049 00050 resize (n); 00051 00052 octave_idx_type i = 0; 00053 00054 for (std::list<std::string>::const_iterator p = lst.begin (); 00055 p != lst.end (); 00056 p++) 00057 elem(i++) = *p; 00058 } 00059 00060 string_vector::string_vector (const std::set<std::string>& lst) 00061 : Array<std::string> () 00062 { 00063 size_t n = lst.size (); 00064 00065 resize (n); 00066 00067 octave_idx_type i = 0; 00068 00069 for (std::set<std::string>::const_iterator p = lst.begin (); 00070 p != lst.end (); 00071 p++) 00072 elem(i++) = *p; 00073 } 00074 00075 // Create a string vector from a NULL terminated list of C strings. 00076 00077 string_vector::string_vector (const char * const *s) 00078 : Array<std::string> () 00079 { 00080 octave_idx_type n = 0; 00081 00082 if (s) 00083 { 00084 const char * const *t = s; 00085 00086 while (*t++) 00087 n++; 00088 } 00089 00090 resize (n); 00091 00092 for (octave_idx_type i = 0; i < n; i++) 00093 elem (i) = s[i]; 00094 } 00095 00096 // Create a string vector from up to N C strings. Assumes that N is 00097 // nonnegative. 00098 00099 string_vector::string_vector (const char * const *s, octave_idx_type n) 00100 : Array<std::string> (dim_vector (n, 1)) 00101 { 00102 for (octave_idx_type i = 0; i < n; i++) 00103 elem (i) = s[i]; 00104 } 00105 00106 string_vector& 00107 string_vector::sort (bool make_uniq) 00108 { 00109 // Don't use Array<std::string>::sort () to allow sorting in place. 00110 octave_sort<std::string> lsort; 00111 lsort.sort (Array<std::string>::fortran_vec (), length ()); 00112 00113 if (make_uniq) 00114 uniq (); 00115 00116 return *this; 00117 } 00118 string_vector& 00119 string_vector::uniq (void) 00120 { 00121 octave_idx_type len = length (); 00122 00123 if (len > 0) 00124 { 00125 octave_idx_type k = 0; 00126 00127 for (octave_idx_type i = 1; i < len; i++) 00128 if (elem(i) != elem(k)) 00129 if (++k != i) 00130 elem(k) = elem(i); 00131 00132 if (len != ++k) 00133 resize (k); 00134 } 00135 00136 return *this; 00137 } 00138 00139 string_vector& 00140 string_vector::append (const std::string& s) 00141 { 00142 octave_idx_type len = length (); 00143 00144 resize (len + 1); 00145 00146 elem(len) = s; 00147 00148 return *this; 00149 } 00150 00151 string_vector& 00152 string_vector::append (const string_vector& sv) 00153 { 00154 octave_idx_type len = length (); 00155 octave_idx_type sv_len = sv.length (); 00156 octave_idx_type new_len = len + sv_len; 00157 00158 resize (new_len); 00159 00160 for (octave_idx_type i = 0; i < sv_len; i++) 00161 elem(len + i) = sv[i]; 00162 00163 return *this; 00164 } 00165 00166 std::string 00167 string_vector::join (const std::string& sep) const 00168 { 00169 std::string retval; 00170 00171 octave_idx_type len = length (); 00172 00173 if (len > 0) 00174 { 00175 octave_idx_type i; 00176 00177 for (i = 0; i < len - 1; i++) 00178 retval += elem(i) + sep; 00179 00180 retval += elem(i); 00181 } 00182 00183 return retval; 00184 } 00185 00186 char ** 00187 string_vector::c_str_vec (void) const 00188 { 00189 octave_idx_type len = length (); 00190 00191 char **retval = new char * [len + 1]; 00192 00193 retval [len] = 0; 00194 00195 for (octave_idx_type i = 0; i < len; i++) 00196 retval[i] = strsave (elem(i).c_str ()); 00197 00198 return retval; 00199 } 00200 00201 void 00202 string_vector::delete_c_str_vec (const char * const *v) 00203 { 00204 const char * const *p = v; 00205 00206 while (*p) 00207 delete [] *p++; 00208 00209 delete [] v; 00210 } 00211 00212 // Format a list in neat columns. 00213 00214 std::ostream& 00215 string_vector::list_in_columns (std::ostream& os, int width) const 00216 { 00217 // Compute the maximum name length. 00218 00219 octave_idx_type max_name_length = 0; 00220 octave_idx_type total_names = length (); 00221 00222 if (total_names == 0) 00223 { 00224 // List empty, remember to end output with a newline. 00225 00226 os << "\n"; 00227 return os; 00228 } 00229 00230 for (octave_idx_type i = 0; i < total_names; i++) 00231 { 00232 octave_idx_type name_length = elem (i).length (); 00233 if (name_length > max_name_length) 00234 max_name_length = name_length; 00235 } 00236 00237 // Allow at least two spaces between names. 00238 00239 max_name_length += 2; 00240 00241 // Calculate the maximum number of columns that will fit. 00242 00243 octave_idx_type line_length 00244 = (width <= 0) ? command_editor::terminal_cols () : width; 00245 00246 octave_idx_type nc = line_length / max_name_length; 00247 if (nc == 0) 00248 nc = 1; 00249 00250 // Calculate the number of rows that will be in each column except 00251 // possibly for a short column on the right. 00252 00253 octave_idx_type nr = total_names / nc + (total_names % nc != 0); 00254 00255 // Recalculate columns based on rows. 00256 00257 nc = total_names / nr + (total_names % nr != 0); 00258 00259 octave_idx_type count; 00260 for (octave_idx_type row = 0; row < nr; row++) 00261 { 00262 count = row; 00263 octave_idx_type pos = 0; 00264 00265 // Print the next row. 00266 00267 while (1) 00268 { 00269 std::string nm = elem (count); 00270 00271 os << nm; 00272 octave_idx_type name_length = nm.length (); 00273 00274 count += nr; 00275 if (count >= total_names) 00276 break; 00277 00278 octave_idx_type spaces_to_pad = max_name_length - name_length; 00279 for (octave_idx_type i = 0; i < spaces_to_pad; i++) 00280 os << " "; 00281 pos += max_name_length; 00282 } 00283 os << "\n"; 00284 } 00285 00286 return os; 00287 }