CFx SDK Documentation 2024 SP0
Loading...
Searching...
No Matches
MemoryStreamImpl.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
25
26
27// MemoryStreamImpl.h: implementation for the OdMemoryStreamImpl class.
28//
30
31#if !defined(_MEMORYSTREAMIMPL_H_INCLUDED_)
32#define _MEMORYSTREAMIMPL_H_INCLUDED_
33
34#include "RxObjectImpl.h"
35#include "MemoryStream.h"
36#include "OdAlloc.h"
37
38//DD:EXPORT_ON
39
40
46
51template <class TBase = OdMemoryStreamDummyBase>
52class OdMemoryStreamImpl : public TBase
53{
54 friend class OdMemoryStream;
55 struct PAGE
56 {
57 PAGE* m_pNextPage;
58 PAGE* m_pPrevPage;
59 OdUInt64 m_nPageStartAddr;
60 OdUInt8 m_data[1];
61 };
62 OdUInt64 m_numPages;
63 PAGE* m_pFirstPage;
64 PAGE* m_pCurrPage;
65 PAGE* m_pLastPage;
66 OdMemoryStreamImpl& operator= (const OdMemoryStreamImpl&) {return *this;}
67protected:
71
72 inline OdUInt64 allocated() const { return m_numPages * m_nPageDataSize; }
73 inline OdUInt64 curPageNo() const { return (m_nCurPos / m_nPageDataSize); }
75 inline OdUInt32 leftInCurPage() const { return (m_pCurrPage ? m_nPageDataSize - posInCurPage() : 0); }
76 void addPage();
77 void seekNextPage(bool bCreateNew = false);
78 inline void seekPrevPage()
79 {
80 if(m_pCurrPage->m_pPrevPage)
81 {
84 m_pCurrPage = m_pCurrPage->m_pPrevPage;
85 }
86 else
87 throw OdError(eEndOfFile);
88 }
89 inline OdUInt8* currPos() { return m_pCurrPage->m_data + posInCurPage(); }
90 inline const OdUInt8* currPos() const { return m_pCurrPage->m_data + posInCurPage(); }
91public:
92 OdMemoryStreamImpl(OdUInt32 nPageDataSize = 0x2000)
93 : m_numPages(0)
94 , m_pFirstPage(0)
95 , m_pCurrPage(0)
96 , m_pLastPage(0)
97 , m_nCurPos(0)
98 , m_nEndPos(0)
99 , m_nPageDataSize(nPageDataSize)
100 {
101 }
102
103 // The methods correspond to OdMemoryStream interface
104 //
106
107 void setPageDataSize(OdUInt32 nPageSize) { m_nPageDataSize = nPageSize; }
108
109 void reserve(OdUInt64 nSize)
110 {
111 while(nSize > allocated())
112 addPage();
113 }
114
115 // The methods correspond to OdStreamBuf interface
116 //
118 {
119 return m_nEndPos;
120 }
121
123
124 const void *pageAlignedAddress(OdUInt32 nLen);
125
127 {
128 return m_nCurPos;
129 }
130
131 bool isEof()
132 {
133 return (m_nCurPos>=m_nEndPos);
134 }
135
137 void getBytes(void* buffer, OdUInt32 nLen);
138
139 void putByte(OdUInt8 val);
140 void putBytes(const void* buffer, OdUInt32 nLen);
141
142 //void copyDataTo(TBase* pDest, OdUInt32 nSrcStart = 0, OdUInt32 nSrcEnd = 0)
143 //{
144 // TBase::copyDataTo(pDest, nSrcStart, nSrcEnd);
145 //}
146
147 void rewind()
148 {
149 m_nCurPos = 0;
150 m_pCurrPage = m_pFirstPage;
151 }
152
153 void truncate()
154 {
155 if(m_pCurrPage)
156 {
157 PAGE* pNext, *pCurr = m_pCurrPage->m_pNextPage;
158 m_pCurrPage->m_pNextPage = 0;
159 m_pLastPage = m_pCurrPage;
161 while(pCurr)
162 {
163 pNext = pCurr->m_pNextPage;
164 ::odrxFree(pCurr);
165 --m_numPages;
166 pCurr = pNext;
167 }
168 }
169 }
170
172};
173
175
179template <class TBase>
181{
182 PAGE* pNext, *pCurr = m_pFirstPage;
183 while(pCurr)
184 {
185 pNext = pCurr->m_pNextPage;
186 ::odrxFree(pCurr);
187 pCurr = pNext;
188 }
189 m_pFirstPage = 0;
190}
191
192template <class TBase>
194{
195 PAGE* pPage = (PAGE*)::odrxAlloc(sizeof(PAGE)-1+m_nPageDataSize);
196 if (!pPage)
197 throw OdError(eOutOfMemory);
198 pPage->m_pPrevPage = m_pLastPage;
199 pPage->m_pNextPage = 0;
200 if(m_pLastPage)
201 {
202 m_pLastPage->m_pNextPage = pPage;
203 if(!m_pCurrPage)
204 m_pCurrPage = pPage;
205 pPage->m_nPageStartAddr = pPage->m_pPrevPage->m_nPageStartAddr + m_nPageDataSize;
206 }
207 else
208 {
209 m_pFirstPage = m_pCurrPage = pPage;
210 pPage->m_nPageStartAddr = 0;
211 }
212 m_pLastPage = pPage;
213 ++m_numPages;
214}
215
216template <class TBase>
218{
219 if(bCreateNew)
220 {
221 if(!m_pCurrPage)
222 {
223 addPage();
224 return;
225 }
226 if(!m_pCurrPage->m_pNextPage)
227 addPage();
228 }
229 if(m_pCurrPage->m_pNextPage)
230 {
231 m_pCurrPage = m_pCurrPage->m_pNextPage;
232 m_nCurPos += leftInCurPage();
233 }
234 else
235 throw OdError(eEndOfFile);
236}
237
238template <class TBase>
240{
241 OdUInt64 nNewPos;
242 switch(from)
243 {
245 nNewPos = m_nEndPos + offset;
246 break;
248 nNewPos = m_nCurPos + offset;
249 break;
251 if(!offset)
252 {
253 rewind();
254 return 0;
255 }
256 nNewPos = offset;
257 break;
258 default:
259 throw OdError(eInvalidInput);
260 break;
261 };
262 if(nNewPos != m_nCurPos)
263 {
264 if (nNewPos > m_nEndPos)
265 throw OdError( eEndOfFile );
266
267 OdInt64 nFromEnd = m_nEndPos - nNewPos;
268
269 bool bForward = false;
270 bool bBack = false;
271 if (m_pCurrPage)
272 {
273 if (nNewPos >= m_pCurrPage->m_nPageStartAddr)
274 {
275 bForward = true;
276 }
277 else
278 {
279 bBack = true;
280 }
281 }
282
283 if (nFromEnd == 0)
284 {
285 m_pCurrPage = m_pLastPage;
286 bForward = true;
287 }
288 else if (bForward)
289 {
290 if (nFromEnd < ((OdInt64)nNewPos - (OdInt64)m_pCurrPage->m_nPageStartAddr))
291 {
292 m_pCurrPage = m_pLastPage;
293 bForward = false;
294 }
295 }
296 else if (bBack)
297 {
298 if (nNewPos < (m_pCurrPage->m_nPageStartAddr - nNewPos))
299 {
300 m_pCurrPage = m_pFirstPage;
301 bForward = true;
302 }
303 }
304 else
305 {
306 if (nNewPos <= (OdUInt64)nFromEnd)
307 {
308 m_pCurrPage = m_pFirstPage;
309 bForward = true;
310 }
311 else
312 {
313 m_pCurrPage = m_pLastPage;
314 }
315 }
316 m_nCurPos = nNewPos;
317 if (bForward)
318 {
319 nNewPos = nNewPos / m_nPageDataSize * m_nPageDataSize ;
320 while(m_pCurrPage && m_pCurrPage->m_nPageStartAddr < nNewPos)
321 {
322 m_pCurrPage = m_pCurrPage->m_pNextPage;
323 }
324 }
325 else
326 {
327 while(m_pCurrPage->m_nPageStartAddr > m_nCurPos)
328 {
329 m_pCurrPage = m_pCurrPage->m_pPrevPage;
330 }
331 }
332 }
333 return m_nCurPos;
334}
335
336template <class TBase>
338{
339#ifndef TD_STRICT_ALIGNMENT
340 if (leftInCurPage() >= nLen)
341 return currPos();
342#endif
343 return NULL;
344}
345
346template <class TBase>
348{
349 OdUInt8 ret;
350 if(m_nCurPos < m_nEndPos)
351 {
352 OdUInt32 nPosInPage = posInCurPage();
353 ret = m_pCurrPage->m_data[nPosInPage];
354 ++m_nCurPos;
355 if ((nPosInPage + 1) == m_nPageDataSize)
356 m_pCurrPage = m_pCurrPage->m_pNextPage;
357 }
358 else
359 {
360 throw OdError(eEndOfFile);
361 }
362 return ret;
363}
364
365template <class TBase>
367{
368 if (nLen==0)
369 return;
370
371 OdUInt64 nNewPos = m_nCurPos + nLen;
372 if(nNewPos <= m_nEndPos)
373 {
374 OdUInt8* pDest = (OdUInt8*)buffer;
375 OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
376 if(nToCopy)
377 {
378 ::memcpy(pDest, currPos(), nToCopy);
379 pDest += nToCopy;
380 nLen -= nToCopy;
381 }
382 while(nLen)
383 {
384 seekNextPage();
385 nToCopy = odmin(m_nPageDataSize, nLen);
386 ::memcpy(pDest, m_pCurrPage->m_data, nToCopy);
387 pDest += nToCopy;
388 nLen -= nToCopy;
389 }
390 m_nCurPos = nNewPos;
391 if(m_nCurPos && (m_nCurPos % m_nPageDataSize)==0)
392 m_pCurrPage = m_pCurrPage->m_pNextPage;
393 }
394 else
395 {
396 throw OdError(eEndOfFile);
397 }
398}
399
400template <class TBase>
402{
403 if(!m_pCurrPage)
404 {
405 seekNextPage(true);
406 }
407 OdUInt64 nPosInPage = posInCurPage();
408 m_pCurrPage->m_data[nPosInPage] = val;
409 ++m_nCurPos;
410 m_nEndPos = odmax(m_nCurPos, m_nEndPos);
411 if ((nPosInPage + 1) == m_nPageDataSize)
412 m_pCurrPage = m_pCurrPage->m_pNextPage;
413}
414
415template <class TBase>
417{
418 if (nLen == 0)
419 {
420 return;
421 }
422 const OdUInt8* pSrc = (const OdUInt8*)buffer;
423 OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
424 if(nToCopy)
425 {
426 ::memcpy(currPos(), pSrc, nToCopy);
427 pSrc += nToCopy;
428 nLen -= nToCopy;
429 }
430 while(nLen)
431 {
432 seekNextPage(true);
433 nToCopy = odmin(m_nPageDataSize, nLen);
434 ::memcpy(m_pCurrPage->m_data, pSrc, nToCopy);
435 pSrc += nToCopy;
436 nLen -= nToCopy;
437 }
438 m_nCurPos += nToCopy;
439 if(m_nCurPos && (m_nCurPos % m_nPageDataSize)==0)
440 m_pCurrPage = m_pCurrPage->m_pNextPage;
441 m_nEndPos = odmax(m_nCurPos, m_nEndPos);
442}
443
444//DD:EXPORT_OFF
445
446#endif // !defined(_MEMORYSTREAMIMPL_H_INCLUDED_)
447
ALLOCDLL_EXPORT void * odrxAlloc(size_t nBytes)
ALLOCDLL_EXPORT void odrxFree(void *pMemBlock)
#define odmin(X, Y)
Definition: OdPlatform.h:34
#define odmax(X, Y)
Definition: OdPlatform.h:35
unsigned int OdUInt32
unsigned char OdUInt8
Definition: Int64.h:43
void putBytes(const void *buffer, OdUInt32 nLen)
void seekNextPage(bool bCreateNew=false)
void getBytes(void *buffer, OdUInt32 nLen)
OdUInt32 posInCurPage() const
void putByte(OdUInt8 val)
void setPageDataSize(OdUInt32 nPageSize)
OdUInt64 curPageNo() const
OdUInt32 leftInCurPage() const
OdMemoryStreamImpl(OdUInt32 nPageDataSize=0x2000)
OdUInt64 allocated() const
OdUInt64 seek(OdInt64 offset, OdDb::FilerSeekType whence)
const OdUInt8 * currPos() const
OdUInt32 pageDataSize() const
const void * pageAlignedAddress(OdUInt32 nLen)
void reserve(OdUInt64 nSize)
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