00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CATStreamRAM.h"
00016 #include "CATStreamFile.h"
00017 #include "CATStreamSub.h"
00018
00019
00020 const CATInt32 kCATSTREAM_DEFSIZE = 1024*10;
00021
00022 CATStreamRAM::CATStreamRAM() : CATStream()
00023 {
00024 fRamCache = 0;
00025 fCacheSize = 0;
00026 fSize = 0;
00027 fCurPos = 0;
00028 }
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 CATStreamRAM::~CATStreamRAM()
00039 {
00040 if (fRamCache != 0)
00041 {
00042 this->Close();
00043 }
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 CATResult CATStreamRAM::Open(const CATWChar* name, OPEN_MODE mode)
00058 {
00059 CATASSERT(fRamCache == 0, "Trying to open an already open stream!");
00060 if (fRamCache != 0)
00061 {
00062
00063 (void)this->Close();
00064 }
00065
00066
00067 fStreamName = name;
00068
00069 fCacheSize = 0;
00070
00071 try
00072 {
00073 fRamCache = new CATUInt8[kCATSTREAM_DEFSIZE];
00074 fCacheSize = kCATSTREAM_DEFSIZE;
00075 }
00076 catch (...)
00077 {
00078 fRamCache = 0;
00079 }
00080
00081 if (fRamCache == 0)
00082 {
00083 return CATRESULT(CAT_ERR_OUT_OF_MEMORY);
00084 }
00085
00086 return CAT_SUCCESS;
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 CATResult CATStreamRAM::Close()
00098 {
00099 CATASSERT(fRamCache != 0, "Attempting to close an already closed stream.");
00100
00101 CATASSERT(fSubCount == 0, "There are still substreams left open!");
00102 if (fSubCount != 0)
00103 {
00104 return CATRESULT(CAT_ERR_FILE_HAS_OPEN_SUBSTREAMS);
00105 }
00106
00107 fStreamName = "";
00108 fCacheSize = 0;
00109
00110 if (fRamCache == 0)
00111 {
00112 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00113 }
00114
00115 delete [] fRamCache;
00116 fRamCache = 0;
00117
00118 return CAT_SUCCESS;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 bool CATStreamRAM::IsOpen()
00128 {
00129 return (fRamCache != 0);
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 CATResult CATStreamRAM::Read(void* buffer, CATUInt32& length)
00147 {
00148 CATASSERT(fRamCache != 0, "Reading from closed file.");
00149 CATASSERT(buffer != 0, "Null buffer passed to read.");
00150
00151 if (!IsOpen())
00152 {
00153 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00154 }
00155
00156 if (fCurPos >= fSize)
00157 {
00158 length = 0;
00159 return CATRESULT(CAT_STAT_FILE_AT_EOF);
00160 }
00161
00162 CATUInt32 amountRead = 0;
00163
00164 CATResult result = CAT_SUCCESS;
00165
00166 if ((CATInt32)(fCurPos + length) >= fSize)
00167 {
00168 result = CATRESULT(CAT_STAT_FILE_AT_EOF);
00169 amountRead = fSize - fCurPos;
00170 }
00171 else
00172 {
00173 amountRead = length;
00174 }
00175
00176 memcpy(buffer,fRamCache + fCurPos, amountRead);
00177 fCurPos += amountRead;
00178 length = amountRead;
00179
00180 return result;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 CATResult CATStreamRAM::Write(const void* buffer, CATUInt32 length)
00194 {
00195 CATASSERT(fRamCache != 0, "Reading from closed file.");
00196 CATASSERT(buffer != 0, "Null buffer passed to read.");
00197
00198 if (!IsOpen())
00199 {
00200 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00201 }
00202
00203 CATUInt32 amountWritten = length;
00204 if ((CATInt32)(fCurPos + amountWritten) > fCacheSize)
00205 {
00206 CATResult result = ReallocCache(amountWritten + fCurPos);
00207 if (CATFAILED(result))
00208 {
00209 return result;
00210 }
00211 }
00212
00213 memcpy(fRamCache + fCurPos, buffer, amountWritten);
00214 fCurPos += amountWritten;
00215 if (fCurPos > fSize)
00216 {
00217 fSize = fCurPos;
00218 }
00219
00220 return CAT_SUCCESS;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 CATResult CATStreamRAM::Size(CATInt64& filesize)
00233 {
00234 CATASSERT(fRamCache != 0, "File must be opened first.");
00235 if (!IsOpen())
00236 {
00237 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00238 }
00239
00240 filesize = fSize;
00241
00242 return CAT_SUCCESS;
00243 }
00244
00245
00246
00247
00248 bool CATStreamRAM::IsSeekable()
00249 {
00250 return true;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 CATResult CATStreamRAM::SeekRelative(CATInt32 offset)
00262 {
00263 CATASSERT(fRamCache != 0, "File must be opened first.");
00264 if (!IsOpen())
00265 {
00266 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00267 }
00268
00269 if (fCurPos + offset < 0)
00270 {
00271 fCurPos = 0;
00272 return CATRESULTFILE(CAT_ERR_FILE_SEEK,this->fStreamName);
00273 }
00274
00275 if (fCurPos + offset > fCacheSize)
00276 {
00277 CATResult result = ReallocCache(fCurPos + offset);
00278 if (CATFAILED(result))
00279 return result;
00280 }
00281
00282 fCurPos += offset;
00283 if (fCurPos > fSize)
00284 fSize = fCurPos;
00285
00286 return CAT_SUCCESS;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 CATResult CATStreamRAM::SeekAbsolute(CATInt64 position)
00299 {
00300 CATASSERT(fRamCache != 0, "File must be opened first.");
00301 if (!IsOpen())
00302 {
00303 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00304 }
00305
00306 if (position > fCacheSize)
00307 {
00308 CATResult result = ReallocCache((CATInt32)position);
00309 if (CATFAILED(result))
00310 {
00311 return result;
00312 }
00313 }
00314
00315 fCurPos = (CATInt32)position;
00316
00317 if (fCurPos > fSize)
00318 {
00319 fSize = fCurPos;
00320 }
00321
00322 return CAT_SUCCESS;
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 CATResult CATStreamRAM::SeekFromEnd(CATInt32 offset)
00333 {
00334 return SeekAbsolute(fSize - offset);
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 CATResult CATStreamRAM::GetPosition(CATInt64& position)
00347 {
00348 CATASSERT(fRamCache != 0, "File must be opened first.");
00349 if (!IsOpen())
00350 {
00351 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00352 }
00353
00354 position = fCurPos;
00355 return CAT_SUCCESS;
00356 }
00357
00358
00359
00360
00361 CATString CATStreamRAM::GetName() const
00362 {
00363 return fStreamName;
00364 }
00365
00366
00367
00368
00369
00370
00371 CATResult CATStreamRAM::ReallocCache( CATInt32 minLength )
00372 {
00373
00374 CATUInt8* newRam = 0;
00375
00376
00377 CATInt32 newSize = fCacheSize*2;
00378
00379
00380 if ( minLength > newSize)
00381 {
00382 newSize = minLength * 2;
00383 }
00384
00385 try
00386 {
00387 newRam = new CATUInt8[newSize];
00388 }
00389 catch (...)
00390 {
00391 newRam = 0;
00392 }
00393
00394 if (newRam == 0)
00395 {
00396 return CATRESULT(CAT_ERR_OUT_OF_MEMORY);
00397 }
00398
00399 CATTRACE((CATString)"Reallocating from " << fCacheSize << " to " << newSize);
00400
00401
00402 memcpy(newRam,fRamCache,fSize);
00403 delete [] fRamCache;
00404 fRamCache = newRam;
00405 fCacheSize = newSize;
00406 return CAT_SUCCESS;
00407 }
00408
00409
00410
00411
00412 CATResult CATStreamRAM::ShrinkCache()
00413 {
00414
00415 CATUInt8* newRam = 0;
00416
00417
00418 CATInt32 newSize = fSize;
00419
00420 try
00421 {
00422 newRam = new CATUInt8[newSize];
00423 }
00424 catch (...)
00425 {
00426 newRam = 0;
00427 }
00428
00429 if (newRam == 0)
00430 {
00431 return CATRESULT(CAT_ERR_OUT_OF_MEMORY);
00432 }
00433
00434 memcpy(newRam, fRamCache, fSize);
00435 delete [] fRamCache;
00436 fRamCache = newRam;
00437 fCacheSize = newSize;
00438 return CAT_SUCCESS;
00439 }
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 CATResult CATStreamRAM::FromFile(const CATWChar* pathName)
00454 {
00455 CATResult result = CAT_SUCCESS;
00456
00457 CATASSERT(fRamCache == 0, "Trying to open an already open stream!");
00458 if (fRamCache != 0)
00459 {
00460
00461 (void)this->Close();
00462 }
00463
00464 CATStreamFile *fileStream = new CATStreamFile();
00465 if (CATFAILED(result = fileStream->Open(pathName,CATStream::READ_ONLY)))
00466 {
00467 delete fileStream;
00468 return result;
00469 }
00470
00471 CATInt64 fileSize = 0;
00472 fileStream->Size(fileSize);
00473
00474 this->fCacheSize = (CATInt32)fileSize;
00475 this->fSize = fCacheSize;
00476
00477 try
00478 {
00479 this->fRamCache = new CATUInt8[fSize];
00480 }
00481 catch (...)
00482 {
00483 this->fRamCache = 0;
00484 }
00485
00486 if (fRamCache == 0)
00487 {
00488 fCacheSize = 0;
00489 fSize = 0;
00490 fileStream->Close();
00491 delete fileStream;
00492 return CATRESULT(CAT_ERR_OUT_OF_MEMORY);
00493 }
00494
00495 CATUInt32 readSize = (CATUInt32)fSize;
00496 result = fileStream->Read(fRamCache,readSize);
00497
00498 CATASSERT((CATInt32)readSize == fSize, "Error reading entire file!");
00499
00500 (void)fileStream->Close();
00501 delete fileStream;
00502
00503 return result;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 CATResult CATStreamRAM::ToFile(const CATWChar* pathName, bool overwrite)
00515 {
00516 CATResult result = CAT_SUCCESS;
00517
00518 CATASSERT(fRamCache != 0, "Trying to open an already open stream!");
00519 if (fRamCache == 0)
00520 {
00521 return CATRESULT(CAT_ERR_FILE_NOT_OPEN);
00522 }
00523
00524 CATStreamFile *fileStream = new CATStreamFile();
00525 if (overwrite == false)
00526 {
00527 if (CATSUCCEEDED(result = fileStream->Open(pathName,CATStream::READ_ONLY)))
00528 {
00529 fileStream->Close();
00530 delete fileStream;
00531 return CATRESULT(CAT_ERR_FILE_ALREADY_EXISTS);
00532 }
00533 }
00534
00535 if (CATFAILED(result = fileStream->Open(pathName,CATStream::READ_WRITE_CREATE_TRUNC)))
00536 {
00537 fileStream->Close();
00538 delete fileStream;
00539 return result;
00540 }
00541
00542 result = fileStream->Write(fRamCache,fSize);
00543
00544 (void)fileStream->Close();
00545 delete fileStream;
00546
00547
00548 return result;
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558 CATUInt8* CATStreamRAM::GetRawCache()
00559 {
00560 return fRamCache;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 CATResult CATStreamRAM::ReadAbs(void *buffer, CATUInt32& length, CATInt64 position)
00578 {
00579 CATResult result = CAT_SUCCESS;
00580 CATInt64 orgPos = 0;
00581
00582 if (CATFAILED(result = this->GetPosition(orgPos)))
00583 {
00584 return result;
00585 }
00586
00587
00588 if (CATFAILED(result = this->SeekAbsolute(position)))
00589 {
00590 this->SeekAbsolute(orgPos);
00591 return result;
00592 }
00593
00594 if (CATFAILED(result = this->Read(buffer,length)))
00595 {
00596 this->SeekAbsolute(orgPos);
00597 return result;
00598 }
00599
00600 return this->SeekAbsolute(orgPos);
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 CATResult CATStreamRAM::WriteAbs(const void *buffer, CATUInt32 length, CATInt64 position)
00617 {
00618 CATResult result = CAT_SUCCESS;
00619 CATInt64 orgPos = 0;
00620
00621 if (CATFAILED(result = this->GetPosition(orgPos)))
00622 {
00623 return result;
00624 }
00625
00626
00627 if (CATFAILED(result = this->SeekAbsolute(position)))
00628 {
00629 this->SeekAbsolute(orgPos);
00630 return result;
00631 }
00632
00633 if (CATFAILED(result = this->Write(buffer,length)))
00634 {
00635 this->SeekAbsolute(orgPos);
00636 return result;
00637 }
00638
00639 return this->SeekAbsolute(orgPos);
00640 }
00641