CmDataStream.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "CmDataStream.h"
  25. #include "CmDebug.h"
  26. #include "CmException.h"
  27. namespace CamelotEngine
  28. {
  29. //-----------------------------------------------------------------------
  30. //-----------------------------------------------------------------------
  31. template <typename T> DataStream& DataStream::operator >>(T& val)
  32. {
  33. read(static_cast<void*>(&val), sizeof(T));
  34. return *this;
  35. }
  36. //-----------------------------------------------------------------------
  37. String DataStream::getLine(bool trimAfter)
  38. {
  39. char tmpBuf[OGRE_STREAM_TEMP_SIZE];
  40. String retString;
  41. size_t readCount;
  42. // Keep looping while not hitting delimiter
  43. while ((readCount = read(tmpBuf, OGRE_STREAM_TEMP_SIZE-1)) != 0)
  44. {
  45. // Terminate string
  46. tmpBuf[readCount] = '\0';
  47. char* p = strchr(tmpBuf, '\n');
  48. if (p != 0)
  49. {
  50. // Reposition backwards
  51. skip((long)(p + 1 - tmpBuf - readCount));
  52. *p = '\0';
  53. }
  54. retString += tmpBuf;
  55. if (p != 0)
  56. {
  57. // Trim off trailing CR if this was a CR/LF entry
  58. if (retString.length() && retString[retString.length()-1] == '\r')
  59. {
  60. retString.erase(retString.length()-1, 1);
  61. }
  62. // Found terminator, break out
  63. break;
  64. }
  65. }
  66. if (trimAfter)
  67. {
  68. StringUtil::trim(retString);
  69. }
  70. return retString;
  71. }
  72. //-----------------------------------------------------------------------
  73. size_t DataStream::readLine(char* buf, size_t maxCount, const String& delim)
  74. {
  75. // Deal with both Unix & Windows LFs
  76. bool trimCR = false;
  77. if (delim.find_first_of('\n') != String::npos)
  78. {
  79. trimCR = true;
  80. }
  81. char tmpBuf[OGRE_STREAM_TEMP_SIZE];
  82. size_t chunkSize = std::min(maxCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
  83. size_t totalCount = 0;
  84. size_t readCount;
  85. while (chunkSize && (readCount = read(tmpBuf, chunkSize)) != 0)
  86. {
  87. // Terminate
  88. tmpBuf[readCount] = '\0';
  89. // Find first delimiter
  90. size_t pos = strcspn(tmpBuf, delim.c_str());
  91. if (pos < readCount)
  92. {
  93. // Found terminator, reposition backwards
  94. skip((long)(pos + 1 - readCount));
  95. }
  96. // Are we genuinely copying?
  97. if (buf)
  98. {
  99. memcpy(buf+totalCount, tmpBuf, pos);
  100. }
  101. totalCount += pos;
  102. if (pos < readCount)
  103. {
  104. // Trim off trailing CR if this was a CR/LF entry
  105. if (trimCR && totalCount && buf[totalCount-1] == '\r')
  106. {
  107. --totalCount;
  108. }
  109. // Found terminator, break out
  110. break;
  111. }
  112. // Adjust chunkSize for next time
  113. chunkSize = std::min(maxCount-totalCount, (size_t)OGRE_STREAM_TEMP_SIZE-1);
  114. }
  115. // Terminate
  116. buf[totalCount] = '\0';
  117. return totalCount;
  118. }
  119. //-----------------------------------------------------------------------
  120. size_t DataStream::skipLine(const String& delim)
  121. {
  122. char tmpBuf[OGRE_STREAM_TEMP_SIZE];
  123. size_t total = 0;
  124. size_t readCount;
  125. // Keep looping while not hitting delimiter
  126. while ((readCount = read(tmpBuf, OGRE_STREAM_TEMP_SIZE-1)) != 0)
  127. {
  128. // Terminate string
  129. tmpBuf[readCount] = '\0';
  130. // Find first delimiter
  131. size_t pos = strcspn(tmpBuf, delim.c_str());
  132. if (pos < readCount)
  133. {
  134. // Found terminator, reposition backwards
  135. skip((long)(pos + 1 - readCount));
  136. total += pos + 1;
  137. // break out
  138. break;
  139. }
  140. total += readCount;
  141. }
  142. return total;
  143. }
  144. //-----------------------------------------------------------------------
  145. String DataStream::getAsString(void)
  146. {
  147. // Read the entire buffer - ideally in one read, but if the size of
  148. // the buffer is unknown, do multiple fixed size reads.
  149. size_t bufSize = (mSize > 0 ? mSize : 4096);
  150. char* pBuf = (char*)malloc(sizeof(char) * bufSize);
  151. // Ensure read from begin of stream
  152. seek(0);
  153. String result;
  154. while (!eof())
  155. {
  156. size_t nr = read(pBuf, bufSize);
  157. result.append(pBuf, nr);
  158. }
  159. free(pBuf);
  160. return result;
  161. }
  162. //-----------------------------------------------------------------------
  163. //-----------------------------------------------------------------------
  164. MemoryDataStream::MemoryDataStream(void* pMem, size_t inSize, bool freeOnClose, bool readOnly)
  165. : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  166. {
  167. mData = mPos = static_cast<UINT8*>(pMem);
  168. mSize = inSize;
  169. mEnd = mData + mSize;
  170. mFreeOnClose = freeOnClose;
  171. assert(mEnd >= mPos);
  172. }
  173. //-----------------------------------------------------------------------
  174. MemoryDataStream::MemoryDataStream(const String& name, void* pMem, size_t inSize,
  175. bool freeOnClose, bool readOnly)
  176. : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  177. {
  178. mData = mPos = static_cast<UINT8*>(pMem);
  179. mSize = inSize;
  180. mEnd = mData + mSize;
  181. mFreeOnClose = freeOnClose;
  182. assert(mEnd >= mPos);
  183. }
  184. //-----------------------------------------------------------------------
  185. MemoryDataStream::MemoryDataStream(DataStream& sourceStream,
  186. bool freeOnClose, bool readOnly)
  187. : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  188. {
  189. // Copy data from incoming stream
  190. mSize = sourceStream.size();
  191. if (mSize == 0 && !sourceStream.eof())
  192. {
  193. // size of source is unknown, read all of it into memory
  194. String contents = sourceStream.getAsString();
  195. mSize = contents.size();
  196. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  197. mPos = mData;
  198. memcpy(mData, contents.data(), mSize);
  199. mEnd = mData + mSize;
  200. }
  201. else
  202. {
  203. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  204. mPos = mData;
  205. mEnd = mData + sourceStream.read(mData, mSize);
  206. mFreeOnClose = freeOnClose;
  207. }
  208. assert(mEnd >= mPos);
  209. }
  210. //-----------------------------------------------------------------------
  211. MemoryDataStream::MemoryDataStream(DataStreamPtr& sourceStream,
  212. bool freeOnClose, bool readOnly)
  213. : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  214. {
  215. // Copy data from incoming stream
  216. mSize = sourceStream->size();
  217. if (mSize == 0 && !sourceStream->eof())
  218. {
  219. // size of source is unknown, read all of it into memory
  220. String contents = sourceStream->getAsString();
  221. mSize = contents.size();
  222. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  223. mPos = mData;
  224. memcpy(mData, contents.data(), mSize);
  225. mEnd = mData + mSize;
  226. }
  227. else
  228. {
  229. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  230. mPos = mData;
  231. mEnd = mData + sourceStream->read(mData, mSize);
  232. mFreeOnClose = freeOnClose;
  233. }
  234. assert(mEnd >= mPos);
  235. }
  236. //-----------------------------------------------------------------------
  237. MemoryDataStream::MemoryDataStream(const String& name, DataStream& sourceStream,
  238. bool freeOnClose, bool readOnly)
  239. : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  240. {
  241. // Copy data from incoming stream
  242. mSize = sourceStream.size();
  243. if (mSize == 0 && !sourceStream.eof())
  244. {
  245. // size of source is unknown, read all of it into memory
  246. String contents = sourceStream.getAsString();
  247. mSize = contents.size();
  248. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  249. mPos = mData;
  250. memcpy(mData, contents.data(), mSize);
  251. mEnd = mData + mSize;
  252. }
  253. else
  254. {
  255. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  256. mPos = mData;
  257. mEnd = mData + sourceStream.read(mData, mSize);
  258. mFreeOnClose = freeOnClose;
  259. }
  260. assert(mEnd >= mPos);
  261. }
  262. //-----------------------------------------------------------------------
  263. MemoryDataStream::MemoryDataStream(const String& name, const DataStreamPtr& sourceStream,
  264. bool freeOnClose, bool readOnly)
  265. : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  266. {
  267. // Copy data from incoming stream
  268. mSize = sourceStream->size();
  269. if (mSize == 0 && !sourceStream->eof())
  270. {
  271. // size of source is unknown, read all of it into memory
  272. String contents = sourceStream->getAsString();
  273. mSize = contents.size();
  274. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  275. mPos = mData;
  276. memcpy(mData, contents.data(), mSize);
  277. mEnd = mData + mSize;
  278. }
  279. else
  280. {
  281. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  282. mPos = mData;
  283. mEnd = mData + sourceStream->read(mData, mSize);
  284. mFreeOnClose = freeOnClose;
  285. }
  286. assert(mEnd >= mPos);
  287. }
  288. //-----------------------------------------------------------------------
  289. MemoryDataStream::MemoryDataStream(size_t inSize, bool freeOnClose, bool readOnly)
  290. : DataStream(static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  291. {
  292. mSize = inSize;
  293. mFreeOnClose = freeOnClose;
  294. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  295. mPos = mData;
  296. mEnd = mData + mSize;
  297. assert(mEnd >= mPos);
  298. }
  299. //-----------------------------------------------------------------------
  300. MemoryDataStream::MemoryDataStream(const String& name, size_t inSize,
  301. bool freeOnClose, bool readOnly)
  302. : DataStream(name, static_cast<UINT16>(readOnly ? READ : (READ | WRITE)))
  303. {
  304. mSize = inSize;
  305. mFreeOnClose = freeOnClose;
  306. mData = (UINT8*)malloc(sizeof(UINT8) * mSize);
  307. mPos = mData;
  308. mEnd = mData + mSize;
  309. assert(mEnd >= mPos);
  310. }
  311. //-----------------------------------------------------------------------
  312. MemoryDataStream::~MemoryDataStream()
  313. {
  314. close();
  315. }
  316. //-----------------------------------------------------------------------
  317. size_t MemoryDataStream::read(void* buf, size_t count)
  318. {
  319. size_t cnt = count;
  320. // Read over end of memory?
  321. if (mPos + cnt > mEnd)
  322. cnt = mEnd - mPos;
  323. if (cnt == 0)
  324. return 0;
  325. assert (cnt<=count);
  326. memcpy(buf, mPos, cnt);
  327. mPos += cnt;
  328. return cnt;
  329. }
  330. //---------------------------------------------------------------------
  331. size_t MemoryDataStream::write(const void* buf, size_t count)
  332. {
  333. size_t written = 0;
  334. if (isWriteable())
  335. {
  336. written = count;
  337. // we only allow writing within the extents of allocated memory
  338. // check for buffer overrun & disallow
  339. if (mPos + written > mEnd)
  340. written = mEnd - mPos;
  341. if (written == 0)
  342. return 0;
  343. memcpy(mPos, buf, written);
  344. mPos += written;
  345. }
  346. return written;
  347. }
  348. //-----------------------------------------------------------------------
  349. size_t MemoryDataStream::readLine(char* buf, size_t maxCount,
  350. const String& delim)
  351. {
  352. // Deal with both Unix & Windows LFs
  353. bool trimCR = false;
  354. if (delim.find_first_of('\n') != String::npos)
  355. {
  356. trimCR = true;
  357. }
  358. size_t pos = 0;
  359. // Make sure pos can never go past the end of the data
  360. while (pos < maxCount && mPos < mEnd)
  361. {
  362. if (delim.find(*mPos) != String::npos)
  363. {
  364. // Trim off trailing CR if this was a CR/LF entry
  365. if (trimCR && pos && buf[pos-1] == '\r')
  366. {
  367. // terminate 1 character early
  368. --pos;
  369. }
  370. // Found terminator, skip and break out
  371. ++mPos;
  372. break;
  373. }
  374. buf[pos++] = *mPos++;
  375. }
  376. // terminate
  377. buf[pos] = '\0';
  378. return pos;
  379. }
  380. //-----------------------------------------------------------------------
  381. size_t MemoryDataStream::skipLine(const String& delim)
  382. {
  383. size_t pos = 0;
  384. // Make sure pos can never go past the end of the data
  385. while (mPos < mEnd)
  386. {
  387. ++pos;
  388. if (delim.find(*mPos++) != String::npos)
  389. {
  390. // Found terminator, break out
  391. break;
  392. }
  393. }
  394. return pos;
  395. }
  396. //-----------------------------------------------------------------------
  397. void MemoryDataStream::skip(long count)
  398. {
  399. size_t newpos = (size_t)( ( mPos - mData ) + count );
  400. assert( mData + newpos <= mEnd );
  401. mPos = mData + newpos;
  402. }
  403. //-----------------------------------------------------------------------
  404. void MemoryDataStream::seek( size_t pos )
  405. {
  406. assert( mData + pos <= mEnd );
  407. mPos = mData + pos;
  408. }
  409. //-----------------------------------------------------------------------
  410. size_t MemoryDataStream::tell(void) const
  411. {
  412. //mData is start, mPos is current location
  413. return mPos - mData;
  414. }
  415. //-----------------------------------------------------------------------
  416. bool MemoryDataStream::eof(void) const
  417. {
  418. return mPos >= mEnd;
  419. }
  420. //-----------------------------------------------------------------------
  421. void MemoryDataStream::close(void)
  422. {
  423. if (mFreeOnClose && mData)
  424. {
  425. free(mData);
  426. mData = 0;
  427. }
  428. }
  429. //-----------------------------------------------------------------------
  430. //-----------------------------------------------------------------------
  431. FileDataStream::FileDataStream(std::ifstream* s, bool freeOnClose)
  432. : DataStream(), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
  433. {
  434. // calculate the size
  435. mpInStream->seekg(0, std::ios_base::end);
  436. mSize = (size_t)mpInStream->tellg();
  437. mpInStream->seekg(0, std::ios_base::beg);
  438. determineAccess();
  439. }
  440. //-----------------------------------------------------------------------
  441. FileDataStream::FileDataStream(const String& name,
  442. std::ifstream* s, bool freeOnClose)
  443. : DataStream(name), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
  444. {
  445. // calculate the size
  446. mpInStream->seekg(0, std::ios_base::end);
  447. mSize = (size_t)mpInStream->tellg();
  448. mpInStream->seekg(0, std::ios_base::beg);
  449. determineAccess();
  450. }
  451. //-----------------------------------------------------------------------
  452. FileDataStream::FileDataStream(const String& name,
  453. std::ifstream* s, size_t inSize, bool freeOnClose)
  454. : DataStream(name), mpInStream(s), mpFStreamRO(s), mpFStream(0), mFreeOnClose(freeOnClose)
  455. {
  456. // Size is passed in
  457. mSize = inSize;
  458. determineAccess();
  459. }
  460. //---------------------------------------------------------------------
  461. FileDataStream::FileDataStream(std::fstream* s, bool freeOnClose)
  462. : DataStream(false), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
  463. {
  464. // writeable!
  465. // calculate the size
  466. mpInStream->seekg(0, std::ios_base::end);
  467. mSize = (size_t)mpInStream->tellg();
  468. mpInStream->seekg(0, std::ios_base::beg);
  469. determineAccess();
  470. }
  471. //-----------------------------------------------------------------------
  472. FileDataStream::FileDataStream(const String& name,
  473. std::fstream* s, bool freeOnClose)
  474. : DataStream(name, false), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
  475. {
  476. // writeable!
  477. // calculate the size
  478. mpInStream->seekg(0, std::ios_base::end);
  479. mSize = (size_t)mpInStream->tellg();
  480. mpInStream->seekg(0, std::ios_base::beg);
  481. determineAccess();
  482. }
  483. //-----------------------------------------------------------------------
  484. FileDataStream::FileDataStream(const String& name,
  485. std::fstream* s, size_t inSize, bool freeOnClose)
  486. : DataStream(name, false), mpInStream(s), mpFStreamRO(0), mpFStream(s), mFreeOnClose(freeOnClose)
  487. {
  488. // writeable!
  489. // Size is passed in
  490. mSize = inSize;
  491. determineAccess();
  492. }
  493. //---------------------------------------------------------------------
  494. void FileDataStream::determineAccess()
  495. {
  496. mAccess = 0;
  497. if (mpInStream)
  498. mAccess |= READ;
  499. if (mpFStream)
  500. mAccess |= WRITE;
  501. }
  502. //-----------------------------------------------------------------------
  503. FileDataStream::~FileDataStream()
  504. {
  505. close();
  506. }
  507. //-----------------------------------------------------------------------
  508. size_t FileDataStream::read(void* buf, size_t count)
  509. {
  510. mpInStream->read(static_cast<char*>(buf), static_cast<std::streamsize>(count));
  511. return mpInStream->gcount();
  512. }
  513. //-----------------------------------------------------------------------
  514. size_t FileDataStream::write(const void* buf, size_t count)
  515. {
  516. size_t written = 0;
  517. if (isWriteable() && mpFStream)
  518. {
  519. mpFStream->write(static_cast<const char*>(buf), static_cast<std::streamsize>(count));
  520. written = count;
  521. }
  522. return written;
  523. }
  524. //-----------------------------------------------------------------------
  525. size_t FileDataStream::readLine(char* buf, size_t maxCount,
  526. const String& delim)
  527. {
  528. if (delim.empty())
  529. {
  530. CM_EXCEPT(InvalidParametersException, "No delimiter provided");
  531. }
  532. if (delim.size() > 1)
  533. {
  534. gDebug().log("WARNING: FileStreamDataStream::readLine - using only first delimeter", "DataStream");
  535. }
  536. // Deal with both Unix & Windows LFs
  537. bool trimCR = false;
  538. if (delim.at(0) == '\n')
  539. {
  540. trimCR = true;
  541. }
  542. // maxCount + 1 since count excludes terminator in getline
  543. mpInStream->getline(buf, static_cast<std::streamsize>(maxCount+1), delim.at(0));
  544. size_t ret = mpInStream->gcount();
  545. // three options
  546. // 1) we had an eof before we read a whole line
  547. // 2) we ran out of buffer space
  548. // 3) we read a whole line - in this case the delim character is taken from the stream but not written in the buffer so the read data is of length ret-1 and thus ends at index ret-2
  549. // in all cases the buffer will be null terminated for us
  550. if (mpInStream->eof())
  551. {
  552. // no problem
  553. }
  554. else if (mpInStream->fail())
  555. {
  556. // Did we fail because of maxCount hit? No - no terminating character
  557. // in included in the count in this case
  558. if (ret == maxCount)
  559. {
  560. // clear failbit for next time
  561. mpInStream->clear();
  562. }
  563. else
  564. {
  565. CM_EXCEPT(InternalErrorException, "Streaming error occurred");
  566. }
  567. }
  568. else
  569. {
  570. // we need to adjust ret because we want to use it as a
  571. // pointer to the terminating null character and it is
  572. // currently the length of the data read from the stream
  573. // i.e. 1 more than the length of the data in the buffer and
  574. // hence 1 more than the _index_ of the NULL character
  575. --ret;
  576. }
  577. // trim off CR if we found CR/LF
  578. if (trimCR && buf[ret-1] == '\r')
  579. {
  580. --ret;
  581. buf[ret] = '\0';
  582. }
  583. return ret;
  584. }
  585. //-----------------------------------------------------------------------
  586. void FileDataStream::skip(long count)
  587. {
  588. #if defined(STLPORT)
  589. // Workaround for STLport issues: After reached eof of file stream,
  590. // it's seems the stream was putted in intermediate state, and will be
  591. // fail if try to repositioning relative to current position.
  592. // Note: tellg() fail in this case too.
  593. if (mpInStream->eof())
  594. {
  595. mpInStream->clear();
  596. // Use seek relative to either begin or end to bring the stream
  597. // back to normal state.
  598. mpInStream->seekg(0, std::ios::end);
  599. }
  600. #endif
  601. mpInStream->clear(); //Clear fail status in case eof was set
  602. mpInStream->seekg(static_cast<std::ifstream::pos_type>(count), std::ios::cur);
  603. }
  604. //-----------------------------------------------------------------------
  605. void FileDataStream::seek( size_t pos )
  606. {
  607. mpInStream->clear(); //Clear fail status in case eof was set
  608. mpInStream->seekg(static_cast<std::streamoff>(pos), std::ios::beg);
  609. }
  610. //-----------------------------------------------------------------------
  611. size_t FileDataStream::tell(void) const
  612. {
  613. mpInStream->clear(); //Clear fail status in case eof was set
  614. return (size_t)mpInStream->tellg();
  615. }
  616. //-----------------------------------------------------------------------
  617. bool FileDataStream::eof(void) const
  618. {
  619. return mpInStream->eof();
  620. }
  621. //-----------------------------------------------------------------------
  622. void FileDataStream::close(void)
  623. {
  624. if (mpInStream)
  625. {
  626. // Unfortunately, there is no file-specific shared class hierarchy between fstream and ifstream (!!)
  627. if (mpFStreamRO)
  628. mpFStreamRO->close();
  629. if (mpFStream)
  630. {
  631. mpFStream->flush();
  632. mpFStream->close();
  633. }
  634. if (mFreeOnClose)
  635. {
  636. // delete the stream too
  637. if (mpFStreamRO)
  638. delete mpFStreamRO;
  639. if (mpFStream)
  640. delete mpFStream;
  641. mpInStream = 0;
  642. mpFStreamRO = 0;
  643. mpFStream = 0;
  644. }
  645. }
  646. }
  647. }