CFx SDK Documentation 2024 SP0
Loading...
Searching...
No Matches
MemFileStreamImpl.h
Go to the documentation of this file.
1
2// Copyright (C) 2002-2022, 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-2022 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"
34
35#ifdef OD_HAVE_UNISTD_FILE
36#include <unistd.h>
37#endif
38
39#ifdef OD_HAVE_WINDOWS_STORAGE_FILE
40#include <windows.storage.h>
41#endif
42
43#ifdef OD_HAVE_WRL_FILE
44#include <wrl/client.h>
45#include <wrl/wrappers/corewrappers.h>
46#endif
47
48//DD:EXPORT_ON
49
54{
55#define TEMPFILE_PREFIX "tx$"
56
60 static OdString getTempFile(OdDbBaseHostAppServices* pHostAppServices, const OdAnsiString& prefix = TEMPFILE_PREFIX)
61 {
62 OdString tmpDir = pHostAppServices->getTempPath();
63#if defined(_WINRT)
64 GUID result;
65 if (CoCreateGuid(&result) < 0)
66 return OdString::kEmpty;
67 tmpDir = tmpDir.format(L"%ls%llx%x%x.tmp", tmpDir.c_str(), result.Data1, result.Data2, result.Data3);
68
69#elif defined(_WIN32) // Win 32 + 64 bit
70 OdChar tmpFile[MAX_PATH];
71 ::GetTempFileName(tmpDir.c_str(), !prefix.isEmpty() ? OdString(prefix).c_str() : L"tmp", 0, tmpFile);
72 if (odStrLen(tmpFile))
73 tmpDir = OdString(tmpFile, (int)odStrLen(tmpFile));
74#else
75 char tmpFile[4096]; // sufficient for Win, Linux, Mac
76 tmpFile[0] = 0;
77
78 OdAnsiCharArray dstBuf;
79 int lenStr = tmpDir.getLength();
80 dstBuf.reserve(lenStr * 4); // UTF-8 can use up to 4 bytes per character
81 OdCharMapper::unicodeToUtf8(tmpDir.c_str(), lenStr, dstBuf);
82 strcat(tmpFile, (const char*)dstBuf.asArrayPtr());
83
84 strcat(tmpFile, !prefix.isEmpty() ? prefix.c_str() : "tmp");
85#ifdef OD_HAVE_MKSTEMPS_FUNC
86 strcat(tmpFile, "XXXXXX.tmp");
87 int fileDescriptor = mkstemps(tmpFile, 4);
88#else
89 strcat(tmpFile, "XXXXXX");
90 int fileDescriptor = mkstemp(tmpFile);
91#endif
92 if (fileDescriptor == -1)
93 {
94 tmpFile[0] = 0;
95 }
96 else
97 close(fileDescriptor);
98 // Convert Utf8 back to Unicode
99 OdAnsiString ansiTmpFile(tmpFile);
100 OdCharArray buf;
101 OdCharMapper::utf8ToUnicode(ansiTmpFile.c_str(), ansiTmpFile.getLength(), buf);
102 tmpDir = OdString(buf.getPtr(), buf.size() - 1);
103#endif
104 return tmpDir;
105 }
106
107} // namespace
108
109/*
110same as OdMemoryStreamImpl, except that it uses a much larger PageSize, and a filled page
111is swapped to an automatically created + associated temporary disk file;
112the page data is then deleted, and if accessed, swapped-in from file again before accessing;
113the PAGE's size should be at least 512 kB
114*/
115
121class PAGE
122{
123public:
131};
132
138
139
145template <class TBase = OdMemFileStreamDummyBase>
146class OdMemFileStreamImpl : public TBase
147{
148 friend class OdMemoryStream;
149
150 OdUInt64 m_numPages;
151 PAGE* m_pFirstPage;
152 PAGE* m_pCurrPage;
153 PAGE* m_pLastPage;
154
160 class PageSwitcher
161 {
162 // the *singleton* data buffer
163
165 PAGE* m_activePage;
166 OdString m_sTmpFileName;
167 OdStreamBufPtr m_pTmpFile;
168 OdDbBaseHostAppServices* m_pHostAppServices;
169
173 bool releaseDiskFile(bool deleteIt)
174 {
175 m_pTmpFile = NULL;
176 if (deleteIt && !m_sTmpFileName.isEmpty()) {
177#ifdef OD_HAVE_REMOVE_FUNC
178 remove(m_sTmpFileName);
179#else
180 DeleteFile(OdString(m_sTmpFileName).c_str());
181#endif
182 }
183 m_sTmpFileName.empty();
184 m_activePage = 0;
185 return true;
186 };
187
188 public:
192 PageSwitcher()
193 : m_activePage(NULL)
194 {
195 };
196
200 ~PageSwitcher()
201 {
202 setBufferSize(0);
203 releaseDiskFile(true);
204 };
205
206 void setAppServices(OdDbBaseHostAppServices* pHostAppServices)
207 {
208 m_pHostAppServices = pHostAppServices;
209 }
210
216 inline void setBufferSize(OdUInt32 pageSize) { m_dataBuffer.resize(pageSize); };
217
223 inline OdUInt8* dataBuffer(PAGE* pPage) { return m_dataBuffer.asArrayPtr();};
224
230 inline OdUInt32 dataSize(PAGE* pPage) { return m_dataBuffer.length(); };
231
235 inline PAGE* activePage() const { return m_activePage; };
236
242 inline void setActivePage(PAGE* pPage) { m_activePage = pPage; };
243
250 inline bool isActivePage(PAGE* pPage) const { return (pPage == m_activePage); };
251
258 inline bool isModified(PAGE* pPage) const { return pPage->m_modified; };
259
266 inline void setModified(PAGE* pPage, bool modified) { pPage->m_modified = modified; };
267
274 inline bool isSaved(PAGE* pPage) const { return pPage->m_savedToFile; };
275
282 inline void setSaved(PAGE* pPage, bool saved) { pPage->m_savedToFile = saved; };
283
289 inline OdUInt64 filePosition(PAGE* pPage) const { return pPage->m_nFilePos; };
290
297 inline void setFilePosition(PAGE* pPage, OdUInt64 seekPos) { pPage->m_nFilePos = seekPos; };
298
304 void initializePage(PAGE* pPage)
305 {
306 ODA_ASSERT(pPage);
307 pPage->m_pPrevPage = 0;
308 pPage->m_pNextPage = 0;
309 pPage->m_data = dataBuffer(pPage);
310 setModified(pPage, false);
311 setSaved(pPage, false);
312 setFilePosition(pPage, 0);
313 };
314
318 OdStreamBufPtr& diskFile()
319 {
320 if (!m_pTmpFile.isNull())
321 return m_pTmpFile;
322
323 // determine temporary filename
324 if (m_pHostAppServices)
325 {
326 m_sTmpFileName = TmpFileHelper::getTempFile(m_pHostAppServices);
327 m_pTmpFile = odrxSystemServices()->createFile(m_sTmpFileName,
331 ODA_ASSERT(!m_pTmpFile.isNull());
332 return m_pTmpFile;
333 }
334 else
335 throw OdError(eNullObjectPointer);
336 };
337
344 bool savePage(PAGE* pPage)
345 {
346 if (pPage && isSaved(pPage) && !isModified(pPage)) // no need to save here
347 return true;
348
349 if (!pPage || diskFile().isNull())
350 return false;
351
352 if (isSaved(pPage))
353 {
354 diskFile()->seek(filePosition(pPage), OdDb::kSeekFromStart);
355 }
356 else
357 {
358 diskFile()->seek(0, OdDb::kSeekFromEnd);
359 setFilePosition(pPage, diskFile()->tell());
360 }
361 diskFile()->putBytes(dataBuffer(pPage), dataSize(pPage));
362
363 setModified(pPage, false);
364 setSaved(pPage, true);
365 return true;
366 };
367
374 bool loadPage(PAGE* pPage)
375 {
376 if (!pPage)
377 return false;
378 if (isActivePage(pPage) && !isModified(pPage)) // no need to (re-)load here
379 return true;
380
381 if (isSaved(pPage) && !diskFile().isNull())
382 {
383 diskFile()->seek(filePosition(pPage), OdDb::kSeekFromStart);
384 diskFile()->getBytes(dataBuffer(pPage), dataSize(pPage));
385 }
386
387 setModified(pPage, false);
388 setActivePage(pPage);
389 return true;
390 };
391
397 bool ensurePage(PAGE* pPage)
398 {
399 ODA_ASSERT(pPage);
400 return isActivePage(pPage) ? true : switchToPage(pPage);
401 };
402
410 bool switchToPage(PAGE* pPage)
411 {
412 ODA_ASSERT(pPage);
413 if (isActivePage(pPage))
414 return true;
415 savePage(activePage());
416 return loadPage(pPage);
417 };
418
424 bool rewind(PAGE* pPage)
425 {
426 ODA_ASSERT(pPage);
427 // 'pPage' is loaded at next read/write access
428 return isActivePage(pPage) ? true : savePage(activePage());
429 }
430
436 bool truncate(PAGE* pPage)
437 {
438 ODA_ASSERT(pPage);
439 bool wasSaved = isSaved(pPage);
440 setModified(pPage, false);
441 setSaved(pPage, false);
442 if (!wasSaved || diskFile().isNull())
443 {
444 return true;
445 }
446
447 diskFile()->seek(filePosition(pPage), OdDb::kSeekFromStart);
448 diskFile()->truncate();
449 return true;
450 };
451 }; // class PageSwitcher
452
453 PageSwitcher m_pageSwitcher;
454
458 OdMemFileStreamImpl& operator= (const OdMemFileStreamImpl&) {return *this;}
459
460protected:
464
468 inline PageSwitcher& pageSwitcher() { return m_pageSwitcher; };
469
473 inline OdUInt64 allocated() const { return m_numPages * m_nPageDataSize; }
474 inline OdUInt64 curPageNo() const { return (m_nCurPos / m_nPageDataSize); }
476 inline OdUInt32 leftInCurPage() const { return (m_pCurrPage ? m_nPageDataSize - posInCurPage() : 0); }
477
481 void addPage();
482
486 void seekNextPage(bool bCreateNew = false);
487
491 inline void seekPrevPage()
492 {
493 if(m_pCurrPage->m_pPrevPage)
494 {
497 m_pCurrPage = m_pCurrPage->m_pPrevPage;
498 pageSwitcher().switchToPage(m_pCurrPage);
499 }
500 else
501 throw OdError(eEndOfFile);
502 }
503
504 inline OdUInt8* currPos() { return m_pCurrPage->m_data + posInCurPage(); }
505 inline const OdUInt8* currPos() const { return m_pCurrPage->m_data + posInCurPage(); }
506
507public:
508 OdMemFileStreamImpl(OdUInt32 nPageDataSize = 0x00200000) // 2MB
509 : m_numPages(0)
510 , m_pFirstPage(0)
511 , m_pCurrPage(0)
512 , m_pLastPage(0)
513 , m_nCurPos(0)
514 , m_nEndPos(0)
515 , m_nPageDataSize(0)
516 {
517 setPageDataSize(nPageDataSize);
519 }
520
522 {
523 pageSwitcher().setAppServices(pHostAppServices);
524 }
525
530
536 void setPageDataSize(OdUInt32 nPageSize)
537 {
538 m_nPageDataSize = nPageSize;
539 pageSwitcher().setBufferSize(nPageSize);
540 }
541
545 void reserve(OdUInt64 nSize)
546 {
547 while(nSize > allocated())
548 addPage();
549 }
550
555 {
556 return m_nEndPos;
557 }
558
566
571 {
572 return m_nCurPos;
573 }
574
579 bool isEof()
580 {
581 return (m_nCurPos>=m_nEndPos);
582 }
583
589
597 void getBytes(void* buffer, OdUInt32 nLen);
598
605 void putByte(OdUInt8 val);
606
614 void putBytes(const void* buffer, OdUInt32 nLen);
615
616 //void copyDataTo(TBase* pDest, OdUInt32 nSrcStart = 0, OdUInt32 nSrcEnd = 0)
617 //{
618 // TBase::copyDataTo(pDest, nSrcStart, nSrcEnd);
619 //}
620
624 void rewind()
625 {
626 m_nCurPos = 0;
627 m_pCurrPage = m_pFirstPage;
628 if(m_pCurrPage)
629 {
630 pageSwitcher().rewind(m_pCurrPage);
631 }
632 }
633
637 void truncate()
638 {
639 if(m_pCurrPage)
640 {
641 pageSwitcher().truncate(m_pCurrPage);
642 PAGE* pNext, *pCurr = m_pCurrPage->m_pNextPage;
643 m_pCurrPage->m_pNextPage = 0;
644 m_pLastPage = m_pCurrPage;
646 while(pCurr)
647 {
648 pNext = pCurr->m_pNextPage;
649 pCurr->m_data = 0;
650 if (pageSwitcher().activePage() == pCurr)
651 {
652 pageSwitcher().setActivePage(0);
653 }
654 ::odrxFree(pCurr);
655 --m_numPages;
656 pCurr = pNext;
657 }
658 }
659 }
660
665};
666
668
669template <class TBase>
671{
672 PAGE* pNext, *pCurr = m_pFirstPage;
673 while(pCurr)
674 {
675 pNext = pCurr->m_pNextPage;
676 pCurr->m_data = 0;
677 if (pageSwitcher().activePage() == pCurr)
678 {
679 int t=0;
680 }
681 ::odrxFree(pCurr);
682 pCurr = pNext;
683 }
684 m_pFirstPage = 0;
685}
686
687template <class TBase>
689{
690 PAGE* pPage = (PAGE*)::odrxAlloc(sizeof(PAGE));
691 if (!pPage)
692 throw OdError(eOutOfMemory);
693
694 pageSwitcher().initializePage(pPage);
695
696 pPage->m_pPrevPage = m_pLastPage;
697 if(m_pLastPage)
698 {
699 m_pLastPage->m_pNextPage = pPage;
700 if(!m_pCurrPage)
701 {
702 m_pCurrPage = pPage;
703 pageSwitcher().switchToPage(m_pCurrPage);
704 }
705 pPage->m_nPageStartAddr = pPage->m_pPrevPage->m_nPageStartAddr + m_nPageDataSize;
706 }
707 else
708 {
709 m_pFirstPage = m_pCurrPage = pPage;
710 pPage->m_nPageStartAddr = 0;
711 pageSwitcher().switchToPage(m_pCurrPage);
712 }
713 m_pLastPage = pPage;
714 ++m_numPages;
715}
716
717template <class TBase>
719{
720 if(bCreateNew)
721 {
722 if(!m_pCurrPage)
723 {
724 addPage();
725 return;
726 }
727 if(!m_pCurrPage->m_pNextPage)
728 addPage();
729 }
730 if(m_pCurrPage->m_pNextPage)
731 {
732 m_pCurrPage = m_pCurrPage->m_pNextPage;
733 m_nCurPos += leftInCurPage();
734 pageSwitcher().switchToPage(m_pCurrPage);
735 }
736 else
737 throw OdError(eEndOfFile);
738}
739
740template <class TBase>
742{
743 OdUInt64 nNewPos;
744 switch(from)
745 {
747 nNewPos = m_nEndPos + offset;
748 break;
750 nNewPos = m_nCurPos + offset;
751 break;
753 if(!offset)
754 {
755 rewind();
756 return 0;
757 }
758 nNewPos = offset;
759 break;
760 default:
761 throw OdError(eInvalidInput);
762 break;
763 };
764
765 if(nNewPos != m_nCurPos)
766 {
767 if (nNewPos > m_nEndPos)
768 throw OdError( eEndOfFile );
769
770 OdInt64 nFromEnd = m_nEndPos - nNewPos;
771
772 bool bForward = false;
773 bool bBack = false;
774 if (m_pCurrPage)
775 {
776 if (nNewPos >= m_pCurrPage->m_nPageStartAddr)
777 {
778 bForward = true;
779 }
780 else
781 {
782 bBack = true;
783 }
784 }
785
786 if (nFromEnd == 0)
787 {
788 m_pCurrPage = m_pLastPage;
789 bForward = true;
790 }
791 else if (bForward)
792 {
793 if (nFromEnd < ((OdInt64)nNewPos - (OdInt64)m_pCurrPage->m_nPageStartAddr))
794 {
795 m_pCurrPage = m_pLastPage;
796 bForward = false;
797 }
798 }
799 else if (bBack)
800 {
801 if (nNewPos < (m_pCurrPage->m_nPageStartAddr - nNewPos))
802 {
803 m_pCurrPage = m_pFirstPage;
804 bForward = true;
805 }
806 }
807 else
808 {
809 if (nNewPos <= (OdUInt64)nFromEnd)
810 {
811 m_pCurrPage = m_pFirstPage;
812 bForward = true;
813 }
814 else
815 {
816 m_pCurrPage = m_pLastPage;
817 }
818 }
819
820 m_nCurPos = nNewPos;
821 if (bForward)
822 {
823 nNewPos = nNewPos / m_nPageDataSize * m_nPageDataSize ;
824 while(m_pCurrPage && m_pCurrPage->m_nPageStartAddr < nNewPos)
825 {
826 m_pCurrPage = m_pCurrPage->m_pNextPage;
827 }
828 }
829 else
830 {
831 while(m_pCurrPage->m_nPageStartAddr > m_nCurPos)
832 {
833 m_pCurrPage = m_pCurrPage->m_pPrevPage;
834 }
835 }
836 pageSwitcher().switchToPage(m_pCurrPage);
837 }
838 return m_nCurPos;
839}
840
841template <class TBase>
843{
844 OdUInt8 ret;
845 if(m_nCurPos < m_nEndPos)
846 {
847 pageSwitcher().ensurePage(m_pCurrPage);
848 OdUInt32 nPosInPage = posInCurPage();
849 ret = m_pCurrPage->m_data[nPosInPage];
850 ++m_nCurPos;
851 if ((nPosInPage + 1) == m_nPageDataSize)
852 m_pCurrPage = m_pCurrPage->m_pNextPage;
853 }
854 else
855 {
856 throw OdError(eEndOfFile);
857 }
858 return ret;
859}
860
861template <class TBase>
863{
864 if (nLen==0)
865 return;
866
867 OdUInt64 nNewPos = m_nCurPos + nLen;
868 if(nNewPos <= m_nEndPos)
869 {
870 OdUInt8* pDest = (OdUInt8*)buffer;
871 OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
872 if(nToCopy)
873 {
874 pageSwitcher().ensurePage(m_pCurrPage);
875 ::memcpy(pDest, currPos(), nToCopy);
876 pDest += nToCopy;
877 nLen -= nToCopy;
878 }
879 while(nLen)
880 {
881 seekNextPage();
882 nToCopy = odmin(m_nPageDataSize, nLen);
883 ::memcpy(pDest, m_pCurrPage->m_data, nToCopy);
884 pDest += nToCopy;
885 nLen -= nToCopy;
886 }
887 m_nCurPos = nNewPos;
888 if(m_nCurPos && (m_nCurPos % m_nPageDataSize)==0)
889 m_pCurrPage = m_pCurrPage->m_pNextPage;
890 }
891 else
892 {
893 throw OdError(eEndOfFile);
894 }
895}
896
897template <class TBase>
899{
900 if(!m_pCurrPage)
901 {
902 seekNextPage(true);
903 }
904 pageSwitcher().ensurePage(m_pCurrPage);
905 pageSwitcher().setModified(m_pCurrPage, true);
906 OdUInt64 nPosInPage = posInCurPage();
907 m_pCurrPage->m_data[nPosInPage] = val;
908 ++m_nCurPos;
909 m_nEndPos = odmax(m_nCurPos, m_nEndPos);
910 if ((nPosInPage + 1) == m_nPageDataSize)
911 {
912 m_pCurrPage = m_pCurrPage->m_pNextPage;
913 }
914}
915
916template <class TBase>
918{
919 if (nLen == 0)
920 {
921 return;
922 }
923 const OdUInt8* pSrc = (const OdUInt8*)buffer;
924 OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
925 if(nToCopy)
926 {
927 pageSwitcher().ensurePage(m_pCurrPage);
928 pageSwitcher().setModified(m_pCurrPage, true);
929 ::memcpy(currPos(), pSrc, nToCopy);
930 pSrc += nToCopy;
931 nLen -= nToCopy;
932 }
933 while(nLen)
934 {
935 seekNextPage(true);
936 pageSwitcher().setModified(m_pCurrPage, true);
937 nToCopy = odmin(m_nPageDataSize, nLen);
938 ::memcpy(m_pCurrPage->m_data, pSrc, nToCopy);
939 pSrc += nToCopy;
940 nLen -= nToCopy;
941 }
942 m_nCurPos += nToCopy;
943 if(m_nCurPos && (m_nCurPos % m_nPageDataSize)==0)
944 {
945 m_pCurrPage = m_pCurrPage->m_pNextPage;
946 }
947 m_nEndPos = odmax(m_nCurPos, m_nEndPos);
948}
949
950//DD:EXPORT_OFF
951
952#endif // !defined(_MEMORYFILESTREAMIMPL_H_INCLUDED_)
953
#define ODA_ASSERT(exp)
Definition: DebugStuff.h:57
true
Definition: DimVarDefs.h:2046
#define TEMPFILE_PREFIX
ALLOCDLL_EXPORT void * odrxAlloc(size_t nBytes)
ALLOCDLL_EXPORT void odrxFree(void *pMemBlock)
#define odStrLen(str)
Definition: OdPlatform.h:272
#define odmin(X, Y)
Definition: OdPlatform.h:34
#define MAX_PATH
Definition: OdPlatform.h:72
#define odmax(X, Y)
Definition: OdPlatform.h:35
unsigned int OdUInt32
unsigned char OdUInt8
wchar_t OdChar
FIRSTDLL_EXPORT OdRxSystemServices * odrxSystemServices()
const T * asArrayPtr() const
Definition: OdArray.h:1590
size_type length() const
Definition: OdArray.h:1537
size_type size() const
Definition: OdArray.h:1247
void reserve(size_type reserveLength)
Definition: OdArray.h:1281
const T * getPtr() const
Definition: OdArray.h:1600
void resize(size_type logicalLength, const T &value)
Definition: OdArray.h:1185
bool isNull() const
Definition: BaseObjectPtr.h:86
static void unicodeToUtf8(const OdChar *srcBuf, int srcSize, OdAnsiCharArray &dstBuf)
static bool utf8ToUnicode(const char *srcBuf, int srcSize, OdCharArray &dstBuf)
virtual OdString getTempPath() const
Definition: Int64.h:43
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:144
const OdChar * c_str() const
Definition: OdString.h:203
FIRSTDLL_EXPORT_STATIC static const OdString kEmpty
Definition: OdString.h:98
int getLength() const
Definition: OdString.h:133
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:49
@ kSeekFromCurrent
Definition: OdStreamBuf.h:51
@ kSeekFromStart
Definition: OdStreamBuf.h:50
@ kSeekFromEnd
Definition: OdStreamBuf.h:52
@ kShareDenyReadWrite
@ kCreateAlways
@ kFileWrite