CFx SDK Documentation  2023 SP0
MemoryStreamImpl.h
Go to the documentation of this file.
1 // Copyright (C) 2002-2017, 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 Teigha(R) software pursuant to a license
16 // agreement with Open Design Alliance.
17 // Teigha(R) Copyright (C) 2002-2017 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 
51 template <class TBase = OdMemoryStreamDummyBase>
52 class 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;}
67 protected:
71 
72  inline OdUInt64 allocated() const { return m_numPages * m_nPageDataSize; }
73  inline OdUInt64 curPageNo() const { return (m_nCurPos / m_nPageDataSize); }
74  inline OdUInt32 posInCurPage() const { return OdUInt32(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(); }
91 public:
92  OdMemoryStreamImpl(OdUInt32 nPageDataSize = 0x400)
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 
136  OdUInt8 getByte();
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  pCurr = pNext;
166  }
167  }
168  }
169 
171 };
172 
174 
178 template <class TBase>
180 {
181  PAGE* pNext, *pCurr = m_pFirstPage;
182  while(pCurr)
183  {
184  pNext = pCurr->m_pNextPage;
185  ::odrxFree(pCurr);
186  pCurr = pNext;
187  }
188  m_pFirstPage = 0;
189 }
190 
191 template <class TBase>
193 {
194  PAGE* pPage = (PAGE*)::odrxAlloc(sizeof(PAGE)-1+m_nPageDataSize);
195  if (!pPage)
196  throw OdError(eOutOfMemory);
197  pPage->m_pPrevPage = m_pLastPage;
198  pPage->m_pNextPage = 0;
199  if(m_pLastPage)
200  {
201  m_pLastPage->m_pNextPage = pPage;
202  if(!m_pCurrPage)
203  m_pCurrPage = pPage;
204  pPage->m_nPageStartAddr = pPage->m_pPrevPage->m_nPageStartAddr + m_nPageDataSize;
205  }
206  else
207  {
208  m_pFirstPage = m_pCurrPage = pPage;
209  pPage->m_nPageStartAddr = 0;
210  }
211  m_pLastPage = pPage;
212  ++m_numPages;
213 }
214 
215 template <class TBase>
217 {
218  if(bCreateNew)
219  {
220  if(!m_pCurrPage)
221  {
222  addPage();
223  return;
224  }
225  if(!m_pCurrPage->m_pNextPage)
226  addPage();
227  }
228  if(m_pCurrPage->m_pNextPage)
229  {
230  m_pCurrPage = m_pCurrPage->m_pNextPage;
231  m_nCurPos += leftInCurPage();
232  }
233  else
234  throw OdError(eEndOfFile);
235 }
236 
237 template <class TBase>
239 {
240  OdUInt64 nNewPos;
241  switch(from)
242  {
243  case OdDb::kSeekFromEnd:
244  nNewPos = m_nEndPos + offset;
245  break;
247  nNewPos = m_nCurPos + offset;
248  break;
250  if(!offset)
251  {
252  rewind();
253  return 0;
254  }
255  nNewPos = offset;
256  break;
257  default:
258  throw OdError(eInvalidInput);
259  break;
260  };
261  if(nNewPos != m_nCurPos)
262  {
263  if (nNewPos > m_nEndPos)
264  throw OdError( eEndOfFile );
265 
266  OdInt64 nFromEnd = m_nEndPos - nNewPos;
267 
268  bool bForward = false;
269  bool bBack = false;
270  if (m_pCurrPage)
271  {
272  if (nNewPos >= m_pCurrPage->m_nPageStartAddr)
273  {
274  bForward = true;
275  }
276  else
277  {
278  bBack = true;
279  }
280  }
281 
282  if (nFromEnd == 0)
283  {
284  m_pCurrPage = m_pLastPage;
285  bForward = true;
286  }
287  else if (bForward)
288  {
289  if (nFromEnd < ((OdInt64)nNewPos - (OdInt64)m_pCurrPage->m_nPageStartAddr))
290  {
291  m_pCurrPage = m_pLastPage;
292  bForward = false;
293  }
294  }
295  else if (bBack)
296  {
297  if (nNewPos < (m_pCurrPage->m_nPageStartAddr - nNewPos))
298  {
299  m_pCurrPage = m_pFirstPage;
300  bForward = true;
301  }
302  }
303  else
304  {
305  if (nNewPos <= (OdUInt64)nFromEnd)
306  {
307  m_pCurrPage = m_pFirstPage;
308  bForward = true;
309  }
310  else
311  {
312  m_pCurrPage = m_pLastPage;
313  }
314  }
315  m_nCurPos = nNewPos;
316  if (bForward)
317  {
318  nNewPos = nNewPos / m_nPageDataSize * m_nPageDataSize ;
319  while(m_pCurrPage && m_pCurrPage->m_nPageStartAddr < nNewPos)
320  {
321  m_pCurrPage = m_pCurrPage->m_pNextPage;
322  }
323  }
324  else
325  {
326  while(m_pCurrPage->m_nPageStartAddr > m_nCurPos)
327  {
328  m_pCurrPage = m_pCurrPage->m_pPrevPage;
329  }
330  }
331  }
332  return m_nCurPos;
333 }
334 
335 template <class TBase>
337 {
338 #ifndef TD_STRICT_ALIGNMENT
339  if (leftInCurPage() >= nLen)
340  return currPos();
341 #endif
342  return NULL;
343 }
344 
345 template <class TBase>
347 {
348  OdUInt8 ret;
349  if(m_nCurPos < m_nEndPos)
350  {
351  OdUInt32 nPosInPage = posInCurPage();
352  ret = m_pCurrPage->m_data[nPosInPage];
353  ++m_nCurPos;
354  if ((nPosInPage + 1) == m_nPageDataSize)
355  m_pCurrPage = m_pCurrPage->m_pNextPage;
356  }
357  else
358  {
359  throw OdError(eEndOfFile);
360  }
361  return ret;
362 }
363 
364 template <class TBase>
366 {
367  if (nLen==0)
368  return;
369 
370  OdUInt64 nNewPos = m_nCurPos + nLen;
371  if(nNewPos <= m_nEndPos)
372  {
373  OdUInt8* pDest = (OdUInt8*)buffer;
374  OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
375  if(nToCopy)
376  {
377  ::memcpy(pDest, currPos(), nToCopy);
378  pDest += nToCopy;
379  nLen -= nToCopy;
380  }
381  while(nLen)
382  {
383  seekNextPage();
384  nToCopy = odmin(m_nPageDataSize, nLen);
385  ::memcpy(pDest, m_pCurrPage->m_data, nToCopy);
386  pDest += nToCopy;
387  nLen -= nToCopy;
388  }
389  m_nCurPos = nNewPos;
390  if(m_nCurPos && (m_nCurPos % m_nPageDataSize)==0)
391  m_pCurrPage = m_pCurrPage->m_pNextPage;
392  }
393  else
394  {
395  throw OdError(eEndOfFile);
396  }
397 }
398 
399 template <class TBase>
401 {
402  if(!m_pCurrPage)
403  {
404  seekNextPage(true);
405  }
406  OdUInt64 nPosInPage = posInCurPage();
407  m_pCurrPage->m_data[nPosInPage] = val;
408  ++m_nCurPos;
409  m_nEndPos = odmax(m_nCurPos, m_nEndPos);
410  if ((nPosInPage + 1) == m_nPageDataSize)
411  m_pCurrPage = m_pCurrPage->m_pNextPage;
412 }
413 
414 template <class TBase>
416 {
417  if (nLen == 0)
418  {
419  return;
420  }
421  const OdUInt8* pSrc = (const OdUInt8*)buffer;
422  OdUInt32 nToCopy = odmin(leftInCurPage(), nLen);
423  if(nToCopy)
424  {
425  ::memcpy(currPos(), pSrc, nToCopy);
426  pSrc += nToCopy;
427  nLen -= nToCopy;
428  }
429  while(nLen)
430  {
431  seekNextPage(true);
432  nToCopy = odmin(m_nPageDataSize, nLen);
433  ::memcpy(m_pCurrPage->m_data, pSrc, nToCopy);
434  pSrc += nToCopy;
435  nLen -= nToCopy;
436  }
437  m_nCurPos += nToCopy;
438  if(m_nCurPos && (m_nCurPos % m_nPageDataSize)==0)
439  m_pCurrPage = m_pCurrPage->m_pNextPage;
440  m_nEndPos = odmax(m_nCurPos, m_nEndPos);
441 }
442 
443 //DD:EXPORT_OFF
444 
445 #endif // !defined(_MEMORYSTREAMIMPL_H_INCLUDED_)
446 
#define NULL
Definition: GsProperties.h:177
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
const OdUInt8 * currPos() const
OdUInt32 leftInCurPage() const
OdUInt64 allocated() const
OdUInt64 seek(OdInt64 offset, OdDb::FilerSeekType whence)
OdUInt32 pageDataSize() const
OdMemoryStreamImpl(OdUInt32 nPageDataSize=0x400)
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