00001
00025 #include "magic/mtextstream.h"
00026
00027 #include <ctype.h>
00028 #include <math.h>
00029 #include <stdarg.h>
00030
00031 BEGIN_NAMESPACE (MagiC);
00032
00033 TextOStream sout (stdout);
00034 TextOStream serr (stderr);
00035 TextIStream stin (stdin);
00036
00037
00038
00043 inline void checkDevice (const IODevice* dev)
00044 {
00045 if (!dev)
00046 throw stream_failure (i18n("Operated stream not associated with a device."));
00047 }
00048
00050
00051
00052
00053
00054
00056
00067 void TextStream::copy (const TextStream& other)
00068 {
00069 mFieldWidth = other.mFieldWidth;
00070 mFillChar = other.mFillChar;
00071 mPrecision = other.mPrecision;
00072 mBase = other.mBase;
00073 }
00074
00075
00077
00078
00079
00080
00081
00083
00084
00096 TextOStream::TextOStream (FILE* strm )
00097 : OStream (strm)
00098 {
00099 }
00100
00101
00104 TextOStream::TextOStream (TextOStream& orig)
00105 : OStream (orig)
00106 {
00107 }
00108
00109
00119 TextOStream::TextOStream (String& buffer,
00120 int mode)
00121 : OStream (buffer, mode)
00122 {
00123 }
00124
00126 TextOStream& TextOStream::printf (const char* sformat, ...)
00127 {
00128 if (!mpDevice)
00129 return *this;
00130
00131 va_list args;
00132 va_start (args, sformat);
00133
00134
00135 String buffer = vstrformat (sformat, args);
00136
00137
00138 mpDevice->writeBlock (buffer);
00139
00140 va_end (args);
00141
00142 if (isAutoFlush())
00143 mpDevice->flush();
00144
00145 return *this;
00146 }
00147
00148 void TextOStream::copy (const TextOStream& other)
00149 {
00150 OStream::copy (other);
00151 TextStream::copy (other);
00152 }
00153
00155 TextOStream& TextOStream::operator<< (const char* str)
00156 {
00157 if (mpDevice)
00158 mpDevice->writeBlock (str, strlen (str));
00159 return *this;
00160 }
00161
00162 TextOStream& TextOStream::operator<< (const char c)
00163 {
00164 if (mpDevice)
00165 mpDevice->putch (c);
00166 return *this;
00167 }
00168
00169 TextOStream& TextOStream::operator<< (int x)
00170 {
00171 if (mpDevice)
00172 mpDevice->writeBlock (String(x));
00173 return *this;
00174 }
00175
00176 TextOStream& TextOStream::operator<< (long x)
00177 {
00178 if (mpDevice)
00179 mpDevice->writeBlock (String(x));
00180 return *this;
00181 }
00182
00183 TextOStream& TextOStream::operator<< (float x)
00184 {
00185 if (mpDevice)
00186 mpDevice->writeBlock (String(x));
00187 return *this;
00188 }
00189
00190 TextOStream& TextOStream::operator<< (double x)
00191 {
00192 if (mpDevice)
00193 mpDevice->writeBlock (String(x));
00194 return *this;
00195 }
00196
00197 TextOStream& TextOStream::operator<< (const String& str)
00198 {
00199 if (mpDevice)
00200 mpDevice->writeBlock (str);
00201 return *this;
00202 }
00203
00204 uint TextOStream::writeRawBytes (const char* str, uint length)
00205 {
00206 if (mpDevice)
00207 return mpDevice->writeBlock (str, length);
00208
00209 return 0;
00210 }
00211
00212
00213
00215
00216
00217
00218
00219
00220
00221
00223
00225 TextIStream& TextIStream::operator>> (char& rCh)
00226 {
00227 checkDevice (mpDevice);
00228
00229
00230 rCh = mpDevice->getch ();
00231
00232 return *this;
00233 }
00234
00236 TextIStream& TextIStream::operator>> (long& rValue)
00237 {
00238
00239
00240 checkDevice (mpDevice);
00241
00242
00243 rValue = 0;
00244 int sign = 1;
00245 while (! mpDevice->atEnd()) {
00246 char ch = mpDevice->getch ();
00247
00248 if (isdigit(ch))
00249 rValue = rValue*10 + long (ch - '0');
00250 else if (ch == '-')
00251 sign = -1;
00252 else if (ch == '+')
00253 sign = 1;
00254 else {
00255
00256 mpDevice->ungetch (ch);
00257 break;
00258 }
00259 }
00260
00261 rValue *= sign;
00262
00263 return *this;
00264 }
00265
00267 TextIStream& TextIStream::operator>> (int& rValue)
00268 {
00269
00270
00271 long lvalue = 0;
00272 *this >> lvalue;
00273
00274
00275 rValue = int (lvalue);
00276
00277 return *this;
00278 }
00279
00293 TextIStream& TextIStream::operator>> (double& rValue)
00294 {
00295 checkDevice (mpDevice);
00296
00297
00298 enum states {NONE, SIGNFOUND, DOTFOUND, EXPFOUND, EXPSIGNFOUND, END} state = NONE;
00299 char ch = 0;
00300 int sign = 1;
00301 double fract = 1.0;
00302 int exp = 0;
00303 int expsign = 1;
00304
00305
00306 ch = mpDevice->getch ();
00307 while (isspace (ch))
00308 ch = mpDevice->getch ();
00309
00310
00311 rValue = 0;
00312 while ((!mpDevice->atEnd()) && (state != END)) {
00313
00314 switch (state) {
00315 case NONE:
00316
00317 if (state == NONE && ch == '-') {
00318 sign = -1;
00319 break;
00320 } else if (state == NONE && ch == '+') {
00321 sign = 1;
00322 break;
00323 }
00324 state = SIGNFOUND;
00325
00326
00327 case SIGNFOUND:
00328 if (isdigit(ch)) {
00329 rValue = rValue*10.0 + float (ch - '0');
00330 } else if (ch == '.')
00331 state = DOTFOUND;
00332 else if (ch == 'e' || ch == 'E')
00333 state = EXPFOUND;
00334 else
00335 state = END;
00336 break;
00337
00338 case DOTFOUND:
00339 if (isdigit (ch)) {
00340
00341 fract /= 10.0;
00342 rValue = rValue + double (ch - '0')*fract;
00343 } else if (ch == 'e' || ch == 'E')
00344 state = EXPFOUND;
00345 else
00346 state = END;
00347 break;
00348
00349 case EXPFOUND:
00350
00351 if (ch == '-') {
00352 expsign = -1;
00353 break;
00354 } else if (ch == '+') {
00355 expsign = 1;
00356 break;
00357 }
00358 state = EXPSIGNFOUND;
00359
00360
00361 case EXPSIGNFOUND:
00362 if (isdigit(ch))
00363 exp = exp*10 + int (ch - '0');
00364 else
00365 state = END;
00366 break;
00367
00368 case END:
00369 break;
00370 };
00371
00372
00373 ch = mpDevice->getch ();
00374 }
00375
00376 if (state == END) {
00377
00378 mpDevice->ungetch (ch);
00379 }
00380
00381
00382 rValue *= sign;
00383
00384
00385 if (exp != 0)
00386 rValue *= pow (10, double (exp*expsign));
00387
00388 return *this;
00389 }
00390
00404 TextIStream& TextIStream::operator>> (float& rValue)
00405 {
00406
00407 double dvalue = 0.0;
00408 *this >> dvalue;
00409
00410
00411 rValue = float (dvalue);
00412
00413 return *this;
00414 }
00415
00422 TextIStream& TextIStream::operator>> (String& str)
00423 {
00424
00425
00426 str.operator<< (*this);
00427
00428 return *this;
00429 }
00430
00431
00434 TextIStream& TextIStream::read (char* p,
00435 int n )
00436 {
00437 String buffer;
00438 buffer << *this;
00439
00440 if ((buffer.length() > 0) && (n > 0))
00441 strncpy (p,
00442 (CONSTR) buffer,
00443 (uint(n) > buffer.length())? buffer.length() : n);
00444
00445 return *this;
00446 }
00447
00448
00451 uint TextIStream::readRawBytes (char* data,
00452 uint maxlen)
00453 {
00454 if (mpDevice)
00455 return mpDevice->readBlock (data, maxlen);
00456 else
00457 return 0;
00458 }
00459
00465 int TextIStream::readLine (String& linebuf)
00466 {
00467 if (!mpDevice || !mpDevice->isOpen() || mpDevice->atEnd())
00468 return 0;
00469
00470 linebuf.empty ();
00471
00472
00473 char buffer [1024+1];
00474 int bytesRead = 0;
00475 int totalRead = 0;
00476 while ((bytesRead = mpDevice->readLine (buffer, 1024))) {
00477 linebuf.append (buffer);
00478 totalRead += bytesRead;
00479
00480
00481
00482 if (bytesRead < 1024)
00483 break;
00484 }
00485
00486 return totalRead;
00487 }
00488
00489 END_NAMESPACE;
00490
00491