Mercurial > hg > octave-nkf
annotate liboctave/oct-env.cc @ 8870:eea0e1b45ec0
optimize string manipulation in lookfor
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 25 Feb 2009 10:21:33 +0100 |
parents | 85184151822e |
children | eb63fbe60fab |
rev | line source |
---|---|
2926 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005, 2006, |
4 2007 John W. Eaton | |
2926 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
2926 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
2926 | 21 |
22 */ | |
23 | |
24 /* | |
25 | |
26 The functions listed below were adapted from a similar functions | |
27 from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991 | |
28 Free Software Foundation, Inc. | |
29 | |
30 octave_env::do_absolute_pathname | |
31 octave_env::do_base_pathname | |
32 octave_env::do_chdir | |
33 octave_env::do_getcwd | |
34 octave_env::do_make_absolute | |
35 octave_env::do_polite_directory_format | |
36 octave_env::pathname_backup | |
37 | |
38 */ | |
39 | |
40 #ifdef HAVE_CONFIG_H | |
41 #include <config.h> | |
42 #endif | |
43 | |
4093 | 44 #include <cctype> |
2926 | 45 #include <cstdlib> |
7048 | 46 #include <cstring> |
4093 | 47 |
3504 | 48 #include <string> |
2926 | 49 |
50 #ifdef HAVE_UNISTD_H | |
51 #ifdef HAVE_SYS_TYPES_H | |
52 #include <sys/types.h> | |
53 #endif | |
54 #include <unistd.h> | |
55 #endif | |
56 | |
4097 | 57 #include "file-ops.h" |
2926 | 58 #include "lo-error.h" |
59 #include "lo-sysdep.h" | |
60 #include "lo-utils.h" | |
61 #include "oct-env.h" | |
2934 | 62 #include "oct-passwd.h" |
2947 | 63 #include "oct-syscalls.h" |
2926 | 64 |
65 octave_env::octave_env (void) | |
66 : follow_symbolic_links (true), verbatim_pwd (true), | |
67 current_directory (), program_name (), program_invocation_name (), | |
68 user_name (), host_name () | |
69 { | |
70 // Get a real value for the current directory. | |
71 do_getcwd (); | |
72 | |
73 // Etc. | |
74 do_get_user_name (); | |
75 | |
76 do_get_host_name (); | |
77 } | |
78 | |
79 octave_env *octave_env::instance = 0; | |
80 | |
81 bool | |
82 octave_env::instance_ok (void) | |
83 { | |
84 bool retval = true; | |
85 | |
86 if (! instance) | |
87 instance = new octave_env (); | |
88 | |
89 if (! instance) | |
90 { | |
91 (*current_liboctave_error_handler) | |
8006
b0e7bbe7cd47
oct-env.cc (octave_env::instance_ok): fix type in error message
John W. Eaton <jwe@octave.org>
parents:
7609
diff
changeset
|
92 ("unable to create current working directory object!"); |
2926 | 93 |
94 retval = false; | |
95 } | |
96 | |
97 return retval; | |
98 } | |
99 | |
3504 | 100 std::string |
101 octave_env::polite_directory_format (const std::string& name) | |
2926 | 102 { |
103 return (instance_ok ()) | |
3504 | 104 ? instance->do_polite_directory_format (name) : std::string (); |
2926 | 105 } |
106 | |
107 bool | |
3504 | 108 octave_env::absolute_pathname (const std::string& s) |
2926 | 109 { |
110 return (instance_ok ()) | |
111 ? instance->do_absolute_pathname (s) : false; | |
112 } | |
113 | |
6838 | 114 bool |
115 octave_env::rooted_relative_pathname (const std::string& s) | |
116 { | |
117 return (instance_ok ()) | |
118 ? instance->do_rooted_relative_pathname (s) : false; | |
119 } | |
120 | |
3504 | 121 std::string |
122 octave_env::base_pathname (const std::string& s) | |
2926 | 123 { |
124 return (instance_ok ()) | |
3504 | 125 ? instance->do_base_pathname (s) : std::string (); |
2926 | 126 } |
127 | |
3504 | 128 std::string |
129 octave_env::make_absolute (const std::string& s, const std::string& dot_path) | |
2926 | 130 { |
131 return (instance_ok ()) | |
3504 | 132 ? instance->do_make_absolute (s, dot_path) : std::string (); |
2926 | 133 } |
134 | |
3504 | 135 std::string |
2926 | 136 octave_env::getcwd () |
137 { | |
138 return (instance_ok ()) | |
3504 | 139 ? instance->do_getcwd () : std::string (); |
2926 | 140 } |
141 | |
3504 | 142 std::string |
2926 | 143 octave_env::get_home_directory () |
144 { | |
145 return (instance_ok ()) | |
3504 | 146 ? instance->do_get_home_directory () : std::string (); |
2926 | 147 } |
148 | |
3504 | 149 std::string |
2926 | 150 octave_env::get_program_name (void) |
151 { | |
152 return (instance_ok ()) | |
3504 | 153 ? instance->program_name : std::string (); |
2926 | 154 } |
155 | |
3504 | 156 std::string |
2926 | 157 octave_env::get_program_invocation_name (void) |
158 { | |
159 return (instance_ok ()) | |
3504 | 160 ? instance->program_invocation_name : std::string (); |
2926 | 161 } |
162 | |
163 void | |
3504 | 164 octave_env::set_program_name (const std::string& s) |
2926 | 165 { |
166 if (instance_ok ()) | |
167 instance->do_set_program_name (s); | |
168 } | |
169 | |
3504 | 170 std::string |
2926 | 171 octave_env::get_user_name (void) |
172 { | |
173 return (instance_ok ()) | |
3504 | 174 ? instance->do_get_user_name () : std::string (); |
2926 | 175 } |
176 | |
3504 | 177 std::string |
2926 | 178 octave_env::get_host_name (void) |
179 { | |
180 return (instance_ok ()) | |
3504 | 181 ? instance->do_get_host_name () : std::string (); |
2926 | 182 } |
183 | |
5775 | 184 // FIXME -- this leaves no way to distinguish between a |
2926 | 185 // variable that is not set and one that is set to the empty string. |
186 // Is this a problem? | |
187 | |
3504 | 188 std::string |
189 octave_env::getenv (const std::string& name) | |
2926 | 190 { |
191 return (instance_ok ()) | |
3504 | 192 ? instance->do_getenv (name) : std::string (); |
2926 | 193 } |
194 | |
195 void | |
3504 | 196 octave_env::putenv (const std::string& name, const std::string& value) |
2926 | 197 { |
198 octave_putenv (name, value); | |
199 } | |
200 | |
201 bool | |
5489 | 202 octave_env::have_x11_display (void) |
203 { | |
204 std::string display = getenv ("DISPLAY"); | |
205 | |
206 return ! display.empty (); | |
207 } | |
208 | |
209 bool | |
3504 | 210 octave_env::chdir (const std::string& newdir) |
2926 | 211 { |
212 return (instance_ok ()) | |
213 ? instance->do_chdir (newdir) : false; | |
214 } | |
215 | |
216 void | |
3504 | 217 octave_env::do_set_program_name (const std::string& s) const |
2926 | 218 { |
219 program_invocation_name = s; | |
220 | |
8007
a2ab20ba78f7
make file_ops a proper singleton class
John W. Eaton <jwe@octave.org>
parents:
8006
diff
changeset
|
221 size_t pos |
a2ab20ba78f7
make file_ops a proper singleton class
John W. Eaton <jwe@octave.org>
parents:
8006
diff
changeset
|
222 = program_invocation_name.find_last_of (file_ops::dir_sep_chars ()); |
2926 | 223 |
8021 | 224 program_name = (pos == std::string::npos) |
2926 | 225 ? program_invocation_name : program_invocation_name.substr (pos+1); |
226 } | |
227 | |
228 // Return a pretty pathname. If the first part of the pathname is the | |
229 // same as $HOME, then replace that with `~'. | |
230 | |
3504 | 231 std::string |
232 octave_env::do_polite_directory_format (const std::string& name) const | |
2926 | 233 { |
3504 | 234 std::string retval; |
2926 | 235 |
3504 | 236 std::string home_dir = do_get_home_directory (); |
2926 | 237 |
238 size_t len = home_dir.length (); | |
239 | |
3516 | 240 if (len > 1 && home_dir == name.substr (0, len) |
4097 | 241 && (name.length () == len || file_ops::is_dir_sep (name[len]))) |
2926 | 242 { |
243 retval = "~"; | |
244 retval.append (name.substr (len)); | |
245 } | |
246 else | |
247 retval = name; | |
248 | |
249 return retval; | |
250 } | |
251 | |
252 bool | |
3504 | 253 octave_env::do_absolute_pathname (const std::string& s) const |
2926 | 254 { |
4087 | 255 size_t len = s.length (); |
256 | |
257 if (len == 0) | |
258 return false; | |
2926 | 259 |
4097 | 260 if (file_ops::is_dir_sep (s[0])) |
2926 | 261 return true; |
262 | |
4101 | 263 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) |
4088 | 264 if ((len == 2 && isalpha (s[0]) && s[1] == ':') |
4097 | 265 || (len > 2 && isalpha (s[0]) && s[1] == ':' |
266 && file_ops::is_dir_sep (s[2]))) | |
4087 | 267 return true; |
268 #endif | |
269 | |
2926 | 270 return false; |
271 } | |
272 | |
6838 | 273 bool |
274 octave_env::do_rooted_relative_pathname (const std::string& s) const | |
275 { | |
276 size_t len = s.length (); | |
277 | |
278 if (len == 0) | |
279 return false; | |
280 | |
281 if (len == 1 && s[0] == '.') | |
282 return true; | |
283 | |
284 if (len > 1 && s[0] == '.' && file_ops::is_dir_sep (s[1])) | |
285 return true; | |
286 | |
287 if (len == 2 && s[0] == '.' && s[1] == '.') | |
288 return true; | |
289 | |
290 if (len > 2 && s[0] == '.' && s[1] == '.' && file_ops::is_dir_sep (s[2])) | |
291 return true; | |
292 | |
293 return false; | |
294 } | |
295 | |
2926 | 296 // Return the `basename' of the pathname in STRING (the stuff after |
4097 | 297 // the last directory separator). If STRING is not a full pathname, |
298 // simply return it. | |
2926 | 299 |
3504 | 300 std::string |
301 octave_env::do_base_pathname (const std::string& s) const | |
2926 | 302 { |
7609
7e6002d15d4d
octave_env::do_base_pathname: handle rooted relativel names
John W. Eaton <jwe@octave.org>
parents:
7048
diff
changeset
|
303 if (! (do_absolute_pathname (s) || do_rooted_relative_pathname (s))) |
2926 | 304 return s; |
305 | |
8007
a2ab20ba78f7
make file_ops a proper singleton class
John W. Eaton <jwe@octave.org>
parents:
8006
diff
changeset
|
306 size_t pos = s.find_last_of (file_ops::dir_sep_chars ()); |
2926 | 307 |
8021 | 308 if (pos == std::string::npos) |
2926 | 309 return s; |
310 else | |
311 return s.substr (pos+1); | |
312 } | |
313 | |
314 // Turn STRING (a pathname) into an absolute pathname, assuming that | |
4097 | 315 // DOT_PATH contains the symbolic location of the current directory. |
2926 | 316 |
3504 | 317 std::string |
318 octave_env::do_make_absolute (const std::string& s, | |
319 const std::string& dot_path) const | |
2926 | 320 { |
321 #if defined (__EMX__) | |
322 if (s.length () > 1 && s[1] == ':') | |
323 return s; | |
324 #endif | |
325 | |
4087 | 326 if (dot_path.empty () || s.empty () || do_absolute_pathname (s)) |
2926 | 327 return s; |
328 | |
4097 | 329 std::string current_dir = dot_path; |
2926 | 330 |
4097 | 331 if (current_dir.empty ()) |
332 current_dir = do_getcwd (); | |
2926 | 333 |
4097 | 334 size_t pos = current_dir.length () - 1; |
2926 | 335 |
4097 | 336 if (! file_ops::is_dir_sep (current_dir[pos])) |
8007
a2ab20ba78f7
make file_ops a proper singleton class
John W. Eaton <jwe@octave.org>
parents:
8006
diff
changeset
|
337 current_dir.append (file_ops::dir_sep_str ()); |
4097 | 338 |
5775 | 339 // FIXME -- this is probably not correct for all systems. |
2926 | 340 |
341 size_t i = 0; | |
342 size_t slen = s.length (); | |
343 | |
344 while (i < slen) | |
345 { | |
346 if (s[i] == '.') | |
347 { | |
348 if (i + 1 == slen) | |
4097 | 349 return current_dir; |
2926 | 350 |
4097 | 351 if (file_ops::is_dir_sep (s[i+1])) |
2926 | 352 { |
353 i += 2; | |
354 continue; | |
355 } | |
356 | |
4097 | 357 if (s[i+1] == '.' |
358 && (i + 2 == slen || file_ops::is_dir_sep (s[i+2]))) | |
2926 | 359 { |
360 i += 2; | |
361 | |
362 if (i != slen) | |
363 i++; | |
364 | |
4097 | 365 pathname_backup (current_dir, 1); |
2926 | 366 |
367 continue; | |
368 } | |
369 } | |
370 | |
8007
a2ab20ba78f7
make file_ops a proper singleton class
John W. Eaton <jwe@octave.org>
parents:
8006
diff
changeset
|
371 size_t tmp = s.find_first_of (file_ops::dir_sep_chars (), i); |
2926 | 372 |
8021 | 373 if (tmp == std::string::npos) |
2926 | 374 { |
4097 | 375 current_dir.append (s, i, tmp-i); |
2926 | 376 break; |
377 } | |
378 else | |
379 { | |
4097 | 380 current_dir.append (s, i, tmp-i+1); |
2926 | 381 i = tmp + 1; |
382 } | |
383 } | |
384 | |
4097 | 385 return current_dir; |
2926 | 386 } |
387 | |
4097 | 388 // Return a string which is the current working directory. |
2926 | 389 |
3504 | 390 std::string |
4097 | 391 octave_env::do_getcwd () const |
2926 | 392 { |
393 if (! follow_symbolic_links) | |
394 current_directory = ""; | |
395 | |
396 if (verbatim_pwd || current_directory.empty ()) | |
397 current_directory = ::octave_getcwd (); | |
398 | |
399 return current_directory; | |
400 } | |
401 | |
402 // This value is not cached because it can change while Octave is | |
403 // running. | |
404 | |
3504 | 405 std::string |
2926 | 406 octave_env::do_get_home_directory (void) const |
407 { | |
3504 | 408 std::string hd = do_getenv ("HOME"); |
2926 | 409 |
6096 | 410 #if defined (__MINGW32__) || defined (_MSC_VER) |
411 // Maybe we are started directly from cmd.exe. | |
5451 | 412 if (hd.empty ()) |
5454 | 413 { |
414 std::string drv = do_getenv ("HOMEDRIVE"); | |
415 if (drv.empty ()) | |
416 hd = do_getenv ("HOMEPATH"); | |
417 else | |
418 hd = drv + do_getenv ("HOMEPATH"); | |
419 } | |
5451 | 420 #endif |
421 | |
2947 | 422 if (hd.empty ()) |
423 { | |
424 octave_passwd pw = octave_passwd::getpwuid (octave_syscalls::getuid ()); | |
425 | |
8007
a2ab20ba78f7
make file_ops a proper singleton class
John W. Eaton <jwe@octave.org>
parents:
8006
diff
changeset
|
426 hd = pw ? pw.dir () : std::string (file_ops::dir_sep_str ()); |
2947 | 427 } |
428 | |
429 return hd; | |
2926 | 430 } |
431 | |
3504 | 432 std::string |
2926 | 433 octave_env::do_get_user_name (void) const |
434 { | |
435 if (user_name.empty ()) | |
436 { | |
2947 | 437 octave_passwd pw = octave_passwd::getpwuid (octave_syscalls::getuid ()); |
2926 | 438 |
3504 | 439 user_name = pw ? pw.name () : std::string ("unknown"); |
2926 | 440 } |
441 | |
442 return user_name; | |
443 } | |
444 | |
3504 | 445 std::string |
2926 | 446 octave_env::do_get_host_name (void) const |
447 { | |
448 if (host_name.empty ()) | |
449 { | |
450 char hostname[256]; | |
451 | |
3803 | 452 int status = octave_gethostname (hostname, 255); |
2926 | 453 |
3185 | 454 host_name = (status < 0) ? "unknown" : hostname; |
2926 | 455 } |
456 | |
457 return host_name; | |
458 } | |
459 | |
3504 | 460 std::string |
461 octave_env::do_getenv (const std::string& name) const | |
2926 | 462 { |
463 char *value = ::getenv (name.c_str ()); | |
464 | |
465 return value ? value : ""; | |
466 } | |
467 | |
468 // Do the work of changing to the directory NEWDIR. Handle symbolic | |
469 // link following, etc. | |
470 | |
471 bool | |
3504 | 472 octave_env::do_chdir (const std::string& newdir) |
2926 | 473 { |
474 bool retval = false; | |
475 | |
3504 | 476 std::string tmp; |
2926 | 477 |
478 if (follow_symbolic_links) | |
479 { | |
480 if (current_directory.empty ()) | |
481 do_getcwd (); | |
482 | |
483 if (current_directory.empty ()) | |
484 tmp = newdir; | |
485 else | |
486 tmp = do_make_absolute (newdir, current_directory); | |
487 | |
4097 | 488 // Get rid of trailing directory separator. |
2926 | 489 |
490 size_t len = tmp.length (); | |
491 | |
492 if (len > 1) | |
493 { | |
4097 | 494 if (file_ops::is_dir_sep (tmp[--len])) |
2926 | 495 tmp.resize (len); |
496 } | |
497 | |
498 if (! ::octave_chdir (tmp)) | |
499 { | |
500 current_directory = tmp; | |
501 retval = true; | |
502 } | |
503 } | |
504 else | |
505 retval = (! ::octave_chdir (newdir)); | |
506 | |
507 return retval; | |
508 } | |
509 | |
510 // Remove the last N directories from PATH. | |
511 | |
512 void | |
3504 | 513 octave_env::pathname_backup (std::string& path, int n) const |
2926 | 514 { |
515 if (path.empty ()) | |
516 return; | |
517 | |
518 size_t i = path.length () - 1; | |
519 | |
520 while (n--) | |
521 { | |
4097 | 522 while (file_ops::is_dir_sep (path[i]) && i > 0) |
2926 | 523 i--; |
524 | |
4097 | 525 while (! file_ops::is_dir_sep (path[i]) && i > 0) |
2926 | 526 i--; |
527 | |
528 i++; | |
529 } | |
530 | |
531 path.resize (i); | |
532 } | |
533 | |
534 void | |
535 octave_env::error (int err_num) const | |
536 { | |
537 (*current_liboctave_error_handler) ("%s", strerror (err_num)); | |
538 } | |
539 | |
540 void | |
3504 | 541 octave_env::error (const std::string& s) const |
2926 | 542 { |
543 (*current_liboctave_error_handler) ("%s", s.c_str ()); | |
544 } | |
545 | |
546 /* | |
547 ;;; Local Variables: *** | |
548 ;;; mode: C++ *** | |
549 ;;; End: *** | |
550 */ |