Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <cctype>
00029 #include <cstdlib>
00030 #include <cstdio>
00031 #include <cstring>
00032 #include <cfloat>
00033
00034 #include <limits>
00035 #include <string>
00036
00037 #include <sys/types.h>
00038 #include <unistd.h>
00039
00040 #include "quit.h"
00041
00042 #include "lo-error.h"
00043 #include "lo-ieee.h"
00044 #include "lo-mappers.h"
00045 #include "lo-utils.h"
00046
00047 bool xis_int_or_inf_or_nan (double x)
00048 { return xisnan (x) || D_NINT (x) == x; }
00049
00050 bool xis_one_or_zero (double x)
00051 { return x == 0 || x == 1; }
00052
00053 bool xis_zero (double x)
00054 { return x == 0; }
00055
00056 bool xtoo_large_for_float (double x)
00057 { return (! (xisnan (x) || xisinf (x)) && fabs (x) > FLT_MAX); }
00058
00059 bool xis_int_or_inf_or_nan (float x)
00060 { return xisnan (x) || D_NINT (x) == x; }
00061
00062 bool xis_one_or_zero (float x)
00063 { return x == 0 || x == 1; }
00064
00065 bool xis_zero (float x)
00066 { return x == 0; }
00067
00068
00069
00070 char *
00071 strsave (const char *s)
00072 {
00073 if (! s)
00074 return 0;
00075
00076 int len = strlen (s);
00077 char *tmp = new char [len+1];
00078 tmp = strcpy (tmp, s);
00079 return tmp;
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 void
00089 octave_putenv (const std::string& name, const std::string& value)
00090 {
00091 int new_len = name.length () + value.length () + 2;
00092
00093 char *new_item = static_cast<char*> (gnulib::malloc (new_len));
00094
00095 sprintf (new_item, "%s=%s", name.c_str (), value.c_str ());
00096
00097
00098
00099
00100 if (putenv (new_item) < 0)
00101 (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
00102 }
00103
00104 std::string
00105 octave_fgets (FILE *f)
00106 {
00107 bool eof;
00108 return octave_fgets (f, eof);
00109 }
00110
00111 std::string
00112 octave_fgets (FILE *f, bool& eof)
00113 {
00114 eof = false;
00115
00116 std::string retval;
00117
00118 int grow_size = 1024;
00119 int max_size = grow_size;
00120
00121 char *buf = static_cast<char *> (gnulib::malloc (max_size));
00122 char *bufptr = buf;
00123 int len = 0;
00124
00125 do
00126 {
00127 if (gnulib::fgets (bufptr, grow_size, f))
00128 {
00129 len = strlen (bufptr);
00130
00131 if (len == grow_size - 1)
00132 {
00133 int tmp = bufptr - buf + grow_size - 1;
00134 grow_size *= 2;
00135 max_size += grow_size;
00136 buf = static_cast<char *> (gnulib::realloc (buf, max_size));
00137 bufptr = buf + tmp;
00138
00139 if (*(bufptr-1) == '\n')
00140 {
00141 *bufptr = '\0';
00142 retval = buf;
00143 }
00144 }
00145 else if (bufptr[len-1] != '\n')
00146 {
00147 bufptr[len++] = '\n';
00148 bufptr[len] = '\0';
00149 retval = buf;
00150 }
00151 else
00152 retval = buf;
00153 }
00154 else
00155 {
00156 if (len == 0)
00157 {
00158 eof = true;
00159
00160 free (buf);
00161
00162 buf = 0;
00163 }
00164
00165 break;
00166 }
00167 }
00168 while (retval.empty ());
00169
00170 if (buf)
00171 free (buf);
00172
00173 octave_quit ();
00174
00175 return retval;
00176 }
00177
00178 std::string
00179 octave_fgetl (FILE *f)
00180 {
00181 bool eof;
00182 return octave_fgetl (f, eof);
00183 }
00184
00185 std::string
00186 octave_fgetl (FILE *f, bool& eof)
00187 {
00188 std::string retval = octave_fgets (f, eof);
00189
00190 size_t len = retval.length ();
00191
00192 if (retval[len-1] == '\n')
00193 retval.resize (len-1);
00194
00195 return retval;
00196 }
00197
00198
00199
00200
00201 static inline double
00202 read_inf_nan_na (std::istream& is, char c0)
00203 {
00204 double d = 0.0;
00205
00206 switch (c0)
00207 {
00208 case 'i': case 'I':
00209 {
00210 char c1 = is.get ();
00211 if (c1 == 'n' || c1 == 'N')
00212 {
00213 char c2 = is.get ();
00214 if (c2 == 'f' || c2 == 'F')
00215 d = octave_Inf;
00216 else
00217 is.setstate (std::ios::failbit);
00218 }
00219 else
00220 is.setstate (std::ios::failbit);
00221 }
00222 break;
00223
00224 case 'n': case 'N':
00225 {
00226 char c1 = is.get ();
00227 if (c1 == 'a' || c1 == 'A')
00228 {
00229 char c2 = is.get ();
00230 if (c2 == 'n' || c2 == 'N')
00231 d = octave_NaN;
00232 else
00233 d = octave_NA;
00234 }
00235 else
00236 is.setstate (std::ios::failbit);
00237 }
00238 break;
00239
00240 default:
00241 abort ();
00242 }
00243
00244 return d;
00245 }
00246
00247
00248
00249 template <>
00250 double
00251 octave_read_value (std::istream& is)
00252 {
00253 double d = 0.0;
00254
00255
00256
00257 std::ios::streampos pos = is.tellg ();
00258
00259 char c1 = ' ';
00260
00261 while (isspace (c1))
00262 c1 = is.get ();
00263
00264 bool neg = false;
00265
00266 switch (c1)
00267 {
00268 case '-':
00269 neg = true;
00270
00271
00272 case '+':
00273 {
00274 char c2 = 0;
00275 c2 = is.get ();
00276 if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
00277 d = read_inf_nan_na (is, c2);
00278 else
00279 {
00280 is.putback (c2);
00281 is >> d;
00282 }
00283
00284 if (neg && ! is.fail ())
00285 d = -d;
00286 }
00287 break;
00288
00289 case 'i': case 'I':
00290 case 'n': case 'N':
00291 d = read_inf_nan_na (is, c1);
00292 break;
00293
00294 default:
00295 is.putback (c1);
00296 is >> d;
00297 break;
00298 }
00299
00300 std::ios::iostate status = is.rdstate ();
00301 if (status & std::ios::failbit)
00302 {
00303 is.clear ();
00304 is.seekg (pos);
00305 is.setstate (status);
00306 }
00307
00308 return d;
00309 }
00310
00311 template <>
00312 Complex
00313 octave_read_value (std::istream& is)
00314 {
00315 double re = 0.0, im = 0.0;
00316
00317 Complex cx = 0.0;
00318
00319 char ch = ' ';
00320
00321 while (isspace (ch))
00322 ch = is.get ();
00323
00324 if (ch == '(')
00325 {
00326 re = octave_read_value<double> (is);
00327 ch = is.get ();
00328
00329 if (ch == ',')
00330 {
00331 im = octave_read_value<double> (is);
00332 ch = is.get ();
00333
00334 if (ch == ')')
00335 cx = Complex (re, im);
00336 else
00337 is.setstate (std::ios::failbit);
00338 }
00339 else if (ch == ')')
00340 cx = re;
00341 else
00342 is.setstate (std::ios::failbit);
00343 }
00344 else
00345 {
00346 is.putback (ch);
00347 cx = octave_read_value<double> (is);
00348 }
00349
00350 return cx;
00351
00352 }
00353
00354
00355
00356
00357 static inline float
00358 read_float_inf_nan_na (std::istream& is, char c0, char sign = '+')
00359 {
00360 float d = 0.0;
00361
00362 switch (c0)
00363 {
00364 case 'i': case 'I':
00365 {
00366 char c1 = is.get ();
00367 if (c1 == 'n' || c1 == 'N')
00368 {
00369 char c2 = is.get ();
00370 if (c2 == 'f' || c2 == 'F')
00371 d = octave_Float_Inf;
00372 else
00373 is.setstate (std::ios::failbit);
00374 }
00375 else
00376 is.setstate (std::ios::failbit);
00377 }
00378 break;
00379
00380 case 'n': case 'N':
00381 {
00382 char c1 = is.get ();
00383 if (c1 == 'a' || c1 == 'A')
00384 {
00385 char c2 = is.get ();
00386 if (c2 == 'n' || c2 == 'N')
00387 d = octave_Float_NaN;
00388 else
00389 d = octave_Float_NA;
00390 }
00391 else
00392 is.setstate (std::ios::failbit);
00393 }
00394 break;
00395
00396 default:
00397 abort ();
00398 }
00399
00400 return d;
00401 }
00402
00403
00404
00405 template <>
00406 float
00407 octave_read_value (std::istream& is)
00408 {
00409 float d = 0.0;
00410
00411
00412
00413 std::ios::streampos pos = is.tellg ();
00414
00415 char c1 = ' ';
00416
00417 while (isspace (c1))
00418 c1 = is.get ();
00419
00420 bool neg = false;
00421
00422 switch (c1)
00423 {
00424 case '-':
00425 neg = true;
00426
00427
00428 case '+':
00429 {
00430 char c2 = 0;
00431 c2 = is.get ();
00432 if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
00433 d = read_float_inf_nan_na (is, c2);
00434 else
00435 {
00436 is.putback (c2);
00437 is >> d;
00438 }
00439
00440 if (neg && ! is.fail ())
00441 d = -d;
00442 }
00443 break;
00444
00445 case 'i': case 'I':
00446 case 'n': case 'N':
00447 d = read_float_inf_nan_na (is, c1);
00448 break;
00449
00450 default:
00451 is.putback (c1);
00452 is >> d;
00453 break;
00454 }
00455
00456 std::ios::iostate status = is.rdstate ();
00457 if (status & std::ios::failbit)
00458 {
00459 is.clear ();
00460 is.seekg (pos);
00461 is.setstate (status);
00462 }
00463
00464 return d;
00465 }
00466
00467 template <>
00468 FloatComplex
00469 octave_read_value (std::istream& is)
00470 {
00471 float re = 0.0, im = 0.0;
00472
00473 FloatComplex cx = 0.0;
00474
00475 char ch = ' ';
00476
00477 while (isspace (ch))
00478 ch = is.get ();
00479
00480 if (ch == '(')
00481 {
00482 re = octave_read_value<float> (is);
00483 ch = is.get ();
00484
00485 if (ch == ',')
00486 {
00487 im = octave_read_value<float> (is);
00488 ch = is.get ();
00489
00490 if (ch == ')')
00491 cx = FloatComplex (re, im);
00492 else
00493 is.setstate (std::ios::failbit);
00494 }
00495 else if (ch == ')')
00496 cx = re;
00497 else
00498 is.setstate (std::ios::failbit);
00499 }
00500 else
00501 {
00502 is.putback (ch);
00503 cx = octave_read_value<float> (is);
00504 }
00505
00506 return cx;
00507
00508 }
00509
00510 void
00511 octave_write_double (std::ostream& os, double d)
00512 {
00513 if (lo_ieee_is_NA (d))
00514 os << "NA";
00515 else if (lo_ieee_isnan (d))
00516 os << "NaN";
00517 else if (lo_ieee_isinf (d))
00518 os << (d < 0 ? "-Inf" : "Inf");
00519 else
00520 os << d;
00521 }
00522
00523 void
00524 octave_write_complex (std::ostream& os, const Complex& c)
00525 {
00526 os << "(";
00527 octave_write_double (os, real (c));
00528 os << ",";
00529 octave_write_double (os, imag (c));
00530 os << ")";
00531 }
00532
00533 void
00534 octave_write_float (std::ostream& os, float d)
00535 {
00536 if (lo_ieee_is_NA (d))
00537 os << "NA";
00538 else if (lo_ieee_isnan (d))
00539 os << "NaN";
00540 else if (lo_ieee_isinf (d))
00541 os << (d < 0 ? "-Inf" : "Inf");
00542 else
00543 os << d;
00544 }
00545
00546 void
00547 octave_write_float_complex (std::ostream& os, const FloatComplex& c)
00548 {
00549 os << "(";
00550 octave_write_float (os, real (c));
00551 os << ",";
00552 octave_write_float (os, imag (c));
00553 os << ")";
00554 }