CFx SDK Documentation 2026 SP0
Loading...
Searching...
No Matches
MemFileStreamImpl.h
Go to the documentation of this file.
1
2// Copyright (C) 2002-2024, Open Design Alliance (the "Alliance").
3// All rights reserved.
4//
5// This software and its documentation and related materials are owned by
6// the Alliance. The software may only be incorporated into application
7// programs owned by members of the Alliance, subject to a signed
8// Membership Agreement and Supplemental Software License Agreement with the
9// Alliance. The structure and organization of this software are the valuable
10// trade secrets of the Alliance and its suppliers. The software is also
11// protected by copyright law and international treaty provisions. Application
12// programs incorporating this software must include the following statement
13// with their copyright notices:
14//
15// This application incorporates Open Design Alliance software pursuant to a license
16// agreement with Open Design Alliance.
17// Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance.
18// All rights reserved.
19//
20// By use of this software, its documentation or related materials, you
21// acknowledge and accept the above terms.
23
24// MemFileStreamImpl.h : implementation for the OdMemFileStreamImpl class.
25//
27
28#if !defined(_MEMORYFILESTREAMIMPL_H_INCLUDED_)
29#define _MEMORYFILESTREAMIMPL_H_INCLUDED_
30
31#include "RxObjectImpl.h"
32#include "MemoryStream.h"
33#include "OdAlloc.h"
35
36#ifdef OD_HAVE_UNISTD_FILE
37#include <unistd.h>
38#endif
39
40#ifdef OD_HAVE_WINDOWS_STORAGE_FILE
41#include <windows.storage.h>
42#endif
43
44#ifdef OD_HAVE_WRL_FILE
45#include <wrl/client.h>
46#include <wrl/wrappers/corewrappers.h>
47#endif
48
49//DD:EXPORT_ON
50
55{
56#define TEMPFILE_PREFIX "tx$"
57
61 static OdString getTempFile(OdDbBaseHostAppServices* pHostAppServices, const OdAnsiString& prefix = TEMPFILE_PREFIX)
62 {
63 OdString tmpDir = pHostAppServices->getTempPath();
64#if defined(_WINRT)
65 GUID result;
66 if (CoCreateGuid(&result) < 0)
67 return OdString::kEmpty;
68 tmpDir = tmpDir.format(L"%ls%llx%x%x.tmp", tmpDir.c_str(), result.Data1, result.Data2, result.Data3);
69
70#elif defined(_WIN32) // Win 32 + 64 bit
71 OdChar tmpFile[MAX_PATH];
72 ::GetTempFileName(tmpDir.c_str(), !prefix.isEmpty() ? OdString(prefix).c_str() : L"tmp", 0, tmpFile);
73 if (odStrLen(tmpFile))
74 tmpDir = OdString(tmpFile, (int)odStrLen(tmpFile));
75#else
76 char tmpFile[4096]; // sufficient for Win, Linux, Mac
77 tmpFile[0] = 0;
78
79 OdAnsiCharArray dstBuf;
80 int lenStr = tmpDir.getLength();
81 dstBuf.reserve(lenStr * 4); // UTF-8 can use up to 4 bytes per character
82 OdCharMapper::unicodeToUtf8(tmpDir.c_str(), lenStr, dstBuf);
83 strcat(tmpFile, (const char*)dstBuf.asArrayPtr());
84
85 strcat(tmpFile, !prefix.isEmpty() ? prefix.c_str() : "tmp");
86#ifdef OD_HAVE_MKSTEMPS_FUNC
87 strcat(tmpFile, "XXXXXX.tmp");
88 int fileDescriptor = mkstemps(tmpFile, 4);
89#else
90 strcat(tmpFile, "XXXXXX");
91 int fileDescriptor = mkstemp(tmpFile);
92#endif
93 if (fileDescriptor == -1)
94 {
95 tmpFile[0] = 0;
96 }
97 else
98 close(fileDescriptor);
99 // Convert Utf8 back to Unicode
100 OdAnsiString ansiTmpFile(tmpFile);
101 OdCharArray buf;
102 OdCharMapper::utf8ToUnicode(ansiTmpFile.c_str(), ansiTmpFile.getLength(), buf);
103 tmpDir = OdString(buf.getPtr(), buf.size() - 1);
104#endif
105 return tmpDir;
106 }
107
108} // namespace
109
110/*
111same as OdMemoryStreamImpl, except that it uses a much larger PageSize, and a filled page
112is swapped to an automatically created + associated temporary disk file;
113the page data is then deleted, and if accessed, swapped-in from file again before accessing;
114the PAGE's size should be at least 512 kB
115*/
116
133
139
140
146template <class TBase = OdMemFileStreamDummyBase>
147class OdMemFileStreamImpl : public TBase
148{
149 friend class OdMemoryStream;
150
151 OdUInt64 m_numPages;
152 PAGE* m_pFirstPage;
153 PAGE* m_pCurrPage;
154 PAGE* m_pLastPage;
155
161 class PageSwitcher
162 {
163 // the *singleton* data buffer
164
166 PAGE* m_activePage;
167 OdString m_sTmpFileName;
168 OdStreamBufPtr m_pTmpFile;
169 OdDbBaseHostAppServices* m_pHostAppServices;
170
174 bool releaseDiskFile(bool deleteIt)
175 {
176 m_pTmpFile = NULL;
177 if (deleteIt && !m_sTmpFileName.isEmpty()) {
178#ifdef OD_HAVE_REMOVE_FUNC
179 remove(m_sTmpFileName);
180#else
181 DeleteFile(OdString(m_sTmpFileName).c_str());
182#endif
183 }
184 m_sTmpFileName.empty();
185 m_activePage = 0;
186 return true;
187 };
188
189 public:
193 PageSwitcher()
194 : m_activePage(NULL)
195 {
196 };
197
201 ~PageSwitcher()
202 {
203 setBufferSize(0);
204 releaseDiskFile(true);
205 };
206
207 void setAppServices(OdDbBaseHostAppServices* pHostAppServices)
208 {
209 m_pHostAppServices = pHostAppServices;
210 }
211
217 inline void setBufferSize(OdUInt32 pageSize) { m_dataBuffer.resize(pageSize); };
218
224 inline OdUInt8* dataBuffer(PAGE* pPage) { return m_dataBuffer.asArrayPtr();};
225
231 inline OdUInt32 dataSize(PAGE* pPage) { return m_dataBuffer.length(); };
232
236 inline PAGE* activePage() const { return m_activePage; };
237
243 inline void setActivePage(PAGE* pPage) { m_activePage = pPage; };
244
251 inline bool isActivePage(PAGE* pPage) const { return (pPage == m_activePage); };
252
259 inline bool isModified(PAGE* pPage) const { return pPage->m_modified; };
260
267 inline void setModified(PAGE* pPage, bool modified) { pPage->m_modified = modified; };
268
275 inline bool isSaved(PAGE* pPage) const { return pPage->m_savedToFile; };
276
283 inline void setSaved(PAGE* pPage, bool saved) { pPage->m_savedToFile = saved; };
284
290 inline OdUInt64 filePosition(PAGE* pPage) const { return pPage->m_nFilePos; };
291
298 inline void setFilePosition(PAGE* pPage, OdUInt64 seekPos) { pPage->m_nFilePos = seekPos; };
299
305 void initializePage(PAGE* pPage)
306 {
307 ODA_ASSERT(pPage);
308 pPage->m_pPrevPage = 0;
309 pPage->m_pNextPage = 0;
310 pPage->m_data = dataBuffer(pPage);
311 setModified(pPage, false);
312 setSaved(pPage, false);
313 setFilePosition(pPage, 0);
314 };
315
319 OdStreamBufPtr& diskFile()
320 {
321 if (!m_pTmpFile.isNull())
322 return m_pTmpFile;
323
324 // determine temporary filename
325 if (m_pHostAppServices)
326 {
327 m_sTmpFileName = TmpFileHelper::getTempFile(m_pHostAppServices);
328 m_pTmpFile = odrxSystemServices()->createFile(m_sTmpFileName,
332 ODA_ASSERT(!m_pTmpFile.isNull());
333 return m_pTmpFile;
334 }
335 else
336 throw OdError(eNullObjectPointer);
337 };
338
345 bool savePage(PAGE* pPage)
346 {
347 if (pPage && isSaved(pPage) && !isModified(pPage)) // no need to save here
348 return true;
349
350 if (!pPage || diskFile().isNull())
351 return false;
352
353 if (isSaved(pPage))
354 {
355 diskFile()->seek(filePosition(pPage), OdDb::kSeekFromStart);
356 }
357 else
358 {
359 diskFile()->seek(0, OdDb::kSeekFromEnd);
360 setFilePosition(pPage, diskFile()->tell());
361 }
362 diskFile()->putBytes(dataBuffer(pPage), dataSize(pPage));
363
364 setModified(pPage, false);
365 setSaved(pPage, true);
366 return true;
367 };
368
375 bool loadPage(PAGE* pPage)
376 {
377 if (!pPage)
378 return false;
379 if (isActivePage(pPage) && !isModified(pPage)) // no need to (re-)load here
380 return true;
381
382 if (isSaved(pPage) && !diskFile().isNull())
383 {
384 diskFile()->seek(filePosition(pPage), OdDb::kSeekFromStart);
385 diskFile()->getBytes(dataBuffer(pPage), dataSize(pPage));
386 }
387
388 setModified(pPage, false);
389 setActivePage(pPage);
390 return true;
391 };
392
398 bool ensurePage(PAGE* pPage)
399 {
400 ODA_ASSERT(pPage);
401 return isActivePage(pPage) ? true : switchToPage(pPage);
402 };
403
411 bool switchToPage(PAGE* pPage)
412 {
413 ODA_ASSERT(pPage);
414 if (isActivePage(pPage))
415 return true;
416 savePage(activePage());
417 return loadPage(pPage);
418 };
419
425 bool rewind(PAGE* pPage)
426 {
427 ODA_ASSERT(pPage);
428 // 'pPage' is loaded at next read/write access
429 return isActivePage(pPage) ? true : savePage(activePage());
430 }
431
437 bool truncate(PAGE* pPage)
438 {
439 ODA_ASSERT(pPage);
440 bool wasSaved = isSaved(pPage);
441 setModified(pPage, false);
442 setSaved(pPage, false);
443 if (!wasSaved || diskFile().isNull())
444 {
445 return true;
446 }
447
448 diskFile()->seek(filePosition(pPage), OdDb::kSeekFromStart);
449 diskFile()->truncate();
450 return true;
451 };
452 }; // class PageSwitcher
453
454 PageSwitcher m_pageSwitcher;
455
459 OdMemFileStreamImpl& operator= (const OdMemFileStreamImpl&) {return *this;}
460
461protected:
465
469 inline PageSwitcher& pageSwitcher() { return m_pageSwitcher; };
470
474 inline OdUInt64 allocated() const { return m_numPages * m_nPageDataSize; }
475 inline OdUInt64 curPageNo() const { return (m_nCurPos / m_nPageDataSize); }
477 inline OdUInt32 leftInCurPage() const { return (m_pCurrPage ? m_nPageDataSize - posInCurPage() : 0); }
478
482 void addPage();
483
487 void seekNextPage(bool bCreateNew = false);
488
492 inline void seekPrevPage()
493 {
494 if(m_pCurrPage->m_pPrevPage)
495 {
498 m_pCurrPage = m_pCurrPage->m_pPrevPage;
499 pageSwitcher().switchToPage(m_pCurrPage);
500 }
501 else
502 throw OdError(eEndOfFile);
503 }
504
505 inline OdUInt8* currPos() { return m_pCurrPage->m_data + posInCurPage(); }
506 inline const OdUInt8* currPos() const { return m_pCurrPage->m_data + posInCurPage(); }
507
508public:
509 OdMemFileStreamImpl(OdUInt32 nPageDataSize = 0x00200000) // 2MB
510 : m_numPages(0)
511 , m_pFirstPage(0)
512 , m_pCurrPage(0)
513 , m_pLastPage(0)
514 , m_nCurPos(0)
515 , m_nEndPos(0)
516 , m_nPageDataSize(0)
517 {
518 setPageDataSize(nPageDataSize);
520 }
521
523 {
524 pageSwitcher().setAppServices(pHostAppServices);
525 }
526
531
537 void setPageDataSize(OdUInt32 nPageSize)
538 {
539 m_nPageDataSize = nPageSize;
540 pageSwitcher().setBufferSize(nPageSize);
541 }
542
546 void reserve(OdUInt64 nSize)
547 {
548 while(nSize > allocated())
549 addPage();
550 }
551
556 {
557 return m_nEndPos;
558 }
559
567
572 {
573 return m_nCurPos;
574 }
575
580 bool isEof()
581 {
582 return (m_nCurPos>=m_nEndPos);
583 }
584
590
598 void getBytes(void* buffer, OdUInt32 nLen);
599
606 void putByte(OdUInt8 val);
607
615 void putBytes(const void* buffer, OdUInt32 nLen);
616
617 //void copyDataTo(TBase* pDest, OdUInt32 nSrcStart = 0, OdUInt32 nSrcEnd = 0)
618 //{
619 // TBase::copyDataTo(pDest, nSrcStart, nSrcEnd);
620 //}
621
625 void rewind()
626 {
627 m_nCurPos = 0;
628 m_pCurrPage = m_pFirstPage;
629 if(m_pCurrPage)
630 {
631 pageSwitcher().rewind(m_pCurrPage);
632 }
633 }
634
638 void truncate()
639 {
640 if(m_pCurrPage)
641 {
642 pageSwitcher().truncate(m_pCurrPage);
643 PAGE* pNext, *pCurr = m_pCurrPage->m_pNextPage;
644 m_pCurrPage->m_pNextPage = 0;
645 m_pLastPage = m_pCurrPage;
647 while(pCurr)
648 {
649 pNext = pCurr->m_pNextPage;
650 pCurr->m_data = 0;
651 if (pageSwitcher().activePage() == pCurr)
652 {
653 pageSwitcher().setActivePage(0);
654 }
655 ::odrxFree(pCurr);
656 --m_numPages;
657 pCurr = pNext;
658 }
659 }
660 }
661
666};
667
669
670template <class TBase>
672{
673 PAGE* pNext, *pCurr = m_pFirstPage;
674 while(pCurr)
675 {
676 pNext = pCurr->m_pNextPage;
677 pCurr->m_data = 0;
678 if (pageSwitcher().activePage() == pCurr)
679 {
680 int t=0;
681 }
682 ::odrxFree(pCurr);
683 pCurr = pNext;
684 }
685 m_pFirstPage = 0;
686}
687
688template <class TBase>
690{
691 PAGE* pPage = (PAGE*)::odrxAlloc(sizeof(PAGE));
692 if (!pPage)
693 throw OdError(eOutOfMemory);
694
695 pageSwitcher().initializePage(pPage);
696
697 pPage->m_pPrevPage = m_pLastPage;
698 if(m_pLastPage)
699 {
700 m_pLastPage->m_pNextPage = pPage;
701 if(!m_pCurrPage)
702 {
703 m_pCurrPage = pPage;
704 pageSwitcher().switchToPage(m_pCurrPage);
705 }
707 }
708 else
709 {
710 m_pFirstPage = m_pCurrPage = pPage;
711 pPage->m_nPageStartAddr = 0;
712 pageSwitcher().switchToPage(m_pCurrPage);
713 }
714 m_pLastPage = pPage;
715 ++m_numPages;
716}
717
718template <class TBase>
720{
721 if(bCreateNew)
722 {
723 if(!m_pCurrPage)
724 {
725 addPage();
726 return;
727 }
728 if(!m_pCurrPage->m_pNextPage)
729 addPage();
730 }
731 if(m_pCurrPage->m_pNextPage)
732 {
733 m_pCurrPage = m_pCurrPage->m_pNextPage;
735 pageSwitcher().switchToPage(m_pCurrPage);
736 }
737 else
738 throw OdError(eEndOfFile);
739}
740
741template <class TBase>
743{
744 OdUInt64 nNewPos;
745 switch(from)
746 {
748 nNewPos = m_nEndPos + offset;
749 break;
751 nNewPos = m_nCurPos + offset;
752 break;
754 if(!offset)
755 {
756 rewind();
757 return 0;
758 }
759 nNewPos = offset;
760 break;
761 default:
762 throw OdError(eInvalidInput);
763 break;
764 };
765
766 if(nNewPos != m_nCurPos)
767 {
768 if (nNewPos > m_nEndPos)
769 throw OdError( eEndOfFile );
770
771 OdInt64 nFromEnd = m_nEndPos - nNewPos;
772
773 bool bForward = false;
774 bool bBack = false;
775 if (m_pCurrPage)
776 {
777 if (nNewPos >= m_pCurrPage->m_nPageStartAddr)
778 {
779 bForward = true;
780 }
781 else
782 {
783 bBack = true;
784 }
785 }
786
787 if (nFromEnd == 0)
788 {
789 m_pCurrPage = m_pLastPage;
790 bForward = true;
791 }
792 else if (bForward)
793 {
794 if (nFromEnd < ((OdInt64)nNewPos - (OdInt64)m_pCurrPage->m_nPageStartAddr))
795 {
796 m_pCurrPage = m_pLastPage;
797 bForward = false;
798 }
799 }
800 else if (bBack)
801 {
802 if (nNewPos < (m_pCurrPage->m_nPageStartAddr - nNewPos))
803 {
804 m_pCurrPage = m_pFirstPage;
805 bForward = true;
806 }
807 }
808 else
809 {
810 if (nNewPos <= (OdUInt64)nFromEnd)
811 {
812 m_pCurrPage = m_pFirstPage;
813 bForward = true;
814 }
815 else
816 {
817 m_pCurrPage = m_pLastPage;
818 }
819 }
820
821 m_nCurPos = nNewPos;
822 if (bForward)
823 {
824 nNewPos = nNewPos / m_nPageDataSize * m_nPageDataSize ;
825 while(m_pCurrPage && m_pCurrPage->m_nPageStartAddr < nNewPos)
826 {
827 m_pCurrPage = m_pCurrPage->m_pNextPage;
828 }
829 }
830 else
831 {
832 while(m_pCurrPage->m_nPageStartAddr > m_nCurPos)
833 {
834 m_pCurrPage = m_pCurrPage->m_pPrevPage;
835 }
836 }
837 pageSwitcher().switchToPage(m_pCurrPage);
838 }
839 return m_nCurPos;
840}
841
842template <class TBase>
844{
845 OdUInt8 ret;
846 if(m_nCurPos < m_nEndPos)
847 {
848 pageSwitcher().ensurePage(m_pCurrPage);
849 OdUInt32 nPosInPage = posInCurPage();
850 ret = m_pCurrPage->m_data[nPosInPage];
851 ++m_nCurPos;
852 if ((nPosInPage + 1) == m_nPageDataSize)
853 m_pCurrPage = m_pCurrPage->m_pNextPage;
854 }
855 else
856 {
857 throw OdError(eEndOfFile);
858 }
859 return ret;
860}
861
862template <class TBase>
864{
865 if (nLen==0)
866 return;
867
868 OdUInt64 nNewPos = m_nCurPos + nLen;
869 if(nNewPos <= m_nEndPos)
870 {
871 OdUInt8* pDest = (OdUInt8*)buffer;
872 OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
873 if(nToCopy)
874 {
875 pageSwitcher().ensurePage(m_pCurrPage);
876 ::memcpy(pDest, currPos(), nToCopy);
877 pDest += nToCopy;
878 nLen -= nToCopy;
879 }
880 while(nLen)
881 {
882 seekNextPage();
883 nToCopy = odmin(m_nPageDataSize, nLen);
884 ::memcpy(pDest, m_pCurrPage->m_data, nToCopy);
885 pDest += nToCopy;
886 nLen -= nToCopy;
887 }
888 m_nCurPos = nNewPos;
890 m_pCurrPage = m_pCurrPage->m_pNextPage;
891 }
892 else
893 {
894 throw OdError(eEndOfFile);
895 }
896}
897
898template <class TBase>
900{
901 if(!m_pCurrPage)
902 {
903 seekNextPage(true);
904 }
905 pageSwitcher().ensurePage(m_pCurrPage);
906 pageSwitcher().setModified(m_pCurrPage, true);
907 OdUInt64 nPosInPage = posInCurPage();
908 m_pCurrPage->m_data[nPosInPage] = val;
909 ++m_nCurPos;
911 if ((nPosInPage + 1) == m_nPageDataSize)
912 {
913 m_pCurrPage = m_pCurrPage->m_pNextPage;
914 }
915}
916
917template <class TBase>
919{
920 if (nLen == 0)
921 {
922 return;
923 }
924 const OdUInt8* pSrc = (const OdUInt8*)buffer;
925 OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
926 if(nToCopy)
927 {
928 pageSwitcher().ensurePage(m_pCurrPage);
929 pageSwitcher().setModified(m_pCurrPage, true);
930 ::memcpy(currPos(), pSrc, nToCopy);
931 pSrc += nToCopy;
932 nLen -= nToCopy;
933 }
934 while(nLen)
935 {
936 seekNextPage(true);
937 pageSwitcher().setModified(m_pCurrPage, true);
938 nToCopy = odmin(m_nPageDataSize, nLen);
939 ::memcpy(m_pCurrPage->m_data, pSrc, nToCopy);
940 pSrc += nToCopy;
941 nLen -= nToCopy;
942 }
943 m_nCurPos += nToCopy;
945 {
946 m_pCurrPage = m_pCurrPage->m_pNextPage;
947 }
949}
950
951//DD:EXPORT_OFF
952
953#endif // !defined(_MEMORYFILESTREAMIMPL_H_INCLUDED_)
954
OdSmartPtr< OdStreamBuf > OdStreamBufPtr
#define ODA_ASSERT(exp)
Definition DebugStuff.h:57
true
#define TEMPFILE_PREFIX
ALLOCDLL_EXPORT void * odrxAlloc(size_t nBytes)
ALLOCDLL_EXPORT void odrxFree(void *pMemBlock)
OdArray< char, OdMemoryAllocator< char > > OdAnsiCharArray
OdArray< OdChar, OdMemoryAllocator< OdChar > > OdCharArray
#define odStrLen(str)
ODRX_CONSTEXPR const T & odmin(const T &a, const T &b)
Definition OdPlatform.h:64
ODRX_CONSTEXPR const T & odmax(const T &a, const T &b)
Definition OdPlatform.h:38
#define MAX_PATH
unsigned int OdUInt32
unsigned char OdUInt8
wchar_t OdChar
OdString OdString
Definition OdString.h:1258
FIRSTDLL_EXPORT OdRxSystemServices * odrxSystemServices()
const T * asArrayPtr() const
Definition OdArray.h:1612
size_type size() const
Definition OdArray.h:1254
void reserve(size_type reserveLength)
Definition OdArray.h:1288
const T * getPtr() const
Definition OdArray.h:1622
static void unicodeToUtf8(const OdChar *srcBuf, int srcSize, OdAnsiCharArray &dstBuf)
static bool utf8ToUnicode(const char *srcBuf, int srcSize, OdCharArray &dstBuf)
virtual OdString getTempPath() const
OdUInt64 seek(OdInt64 offset, OdDb::FilerSeekType whence)
void reserve(OdUInt64 nSize)
void putByte(OdUInt8 val)
void putBytes(const void *buffer, OdUInt32 nLen)
void setPageDataSize(OdUInt32 nPageSize)
OdUInt32 leftInCurPage() const
OdUInt64 curPageNo() const
void getBytes(void *buffer, OdUInt32 nLen)
void seekNextPage(bool bCreateNew=false)
void setAppServices(OdDbBaseHostAppServices *pHostAppServices)
OdUInt64 allocated() const
OdUInt32 posInCurPage() const
OdMemFileStreamImpl(OdUInt32 nPageDataSize=0x00200000)
const OdUInt8 * currPos() const
PageSwitcher & pageSwitcher()
OdUInt32 pageDataSize() const
virtual OdStreamBufPtr createFile(const OdString &filename, Oda::FileAccessMode accessMode=Oda::kFileRead, Oda::FileShareMode shareMode=Oda::kShareDenyNo, Oda::FileCreationDisposition creationDisposition=Oda::kOpenExisting)
OdString & format(const OdChar *formatString,...)
void empty()
bool isEmpty() const
Definition OdString.h:146
const OdChar * c_str() const
Definition OdString.h:205
FIRSTDLL_EXPORT_STATIC static const OdString kEmpty
Definition OdString.h:100
int getLength() const
Definition OdString.h:135
bool m_savedToFile
PAGE * m_pNextPage
OdUInt64 m_nFilePos
bool m_modified
PAGE * m_pPrevPage
OdUInt8 * m_data
OdUInt64 m_nPageStartAddr
GLuint buffer
Definition gles2_ext.h:178
GLintptr offset
Definition gles2_ext.h:183
FilerSeekType
Definition OdStreamBuf.h:90
@ kSeekFromCurrent
Definition OdStreamBuf.h:92
@ kSeekFromStart
Definition OdStreamBuf.h:91
@ kSeekFromEnd
Definition OdStreamBuf.h:93
@ kShareDenyReadWrite
Definition OdStreamBuf.h:66
@ kCreateAlways
Definition OdStreamBuf.h:76
FileAccessMode
Definition OdStreamBuf.h:48
@ kFileWrite
Definition OdStreamBuf.h:51
@ kFileRead
Definition OdStreamBuf.h:49