0024931: Stack overflow when writing large shapes to XML
[occt.git] / src / LDOM / LDOM_OSStream.cxx
CommitLineData
b311480e 1// Created on: 2001-10-01
2// Created by: Julia DOROVSKIKH
973c2be1 3// Copyright (c) 2001-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16#include <LDOM_OSStream.hxx>
70167e69
RL
17#include <NCollection_DefineAlloc.hxx>
18#include <NCollection_IncAllocator.hxx>
7fd59977 19#include <string.h>
70167e69 20#include <Standard.hxx>
7fd59977 21#include <Standard_Integer.hxx>
22
23// One element of sequence
70167e69
RL
24/* Can only be allocated by the allocator and assumes it is IncAllocator, so
25 no destructor is required.
26*/
7fd59977 27class LDOM_StringElem
28{
29 char* buf; // pointer on data string
30 int len; // quantity of really written data
31 LDOM_StringElem* next; // pointer on the next element of a sequence
32
70167e69
RL
33 DEFINE_NCOLLECTION_ALLOC
34
35 LDOM_StringElem (int aLen, const Handle_NCollection_BaseAllocator& theAlloc) :
36 buf (reinterpret_cast<char*> (theAlloc->Allocate (aLen))),
37 len (0),
38 next (0)
7fd59977 39 {
7fd59977 40 }
41
7fd59977 42friend class LDOM_SBuffer;
43};
44
45//=======================================================================
46//function : LDOM_SBuffer()
47//purpose :
48//=======================================================================
49LDOM_SBuffer::LDOM_SBuffer (const Standard_Integer theMaxBuf)
70167e69
RL
50 : myMaxBuf (theMaxBuf), myLength(0),
51 myAlloc (new NCollection_IncAllocator)
7fd59977 52{
70167e69
RL
53 myFirstString = new (myAlloc) LDOM_StringElem (theMaxBuf, myAlloc);
54 myCurString = myFirstString;
7fd59977 55}
56
57//=======================================================================
58//function : ~LDOM_SBuffer()
59//purpose :
60//=======================================================================
61LDOM_SBuffer::~LDOM_SBuffer ()
62{
70167e69 63 //no destruction is required as IncAllocator is used
7fd59977 64}
65
66//=======================================================================
67//function : Clear()
68//purpose :
69//=======================================================================
70void LDOM_SBuffer::Clear ()
71{
70167e69
RL
72 myAlloc = new NCollection_IncAllocator;
73 myFirstString = new (myAlloc) LDOM_StringElem (myMaxBuf, myAlloc);
74 myLength = 0;
75 myCurString = myFirstString;
7fd59977 76}
77
78//=======================================================================
79//function : str()
80//purpose :
81//=======================================================================
82Standard_CString LDOM_SBuffer::str () const
83{
84 char* aRetStr = new char [myLength + 1];
85
86 LDOM_StringElem* aCurElem = myFirstString;
87 int aCurLen = 0;
88 while (aCurElem)
89 {
90 strncpy(aRetStr + aCurLen, aCurElem->buf, aCurElem->len);
91 aCurLen += aCurElem->len;
92 aCurElem = aCurElem->next;
93 }
94 *(aRetStr + myLength) = '\0';
95
96 return aRetStr;
97}
98
99//=======================================================================
100//function : overflow()
101//purpose : redefined virtual
102//=======================================================================
103int LDOM_SBuffer::overflow(int c)
104{
8263fcd3 105 char cc = (char)c;
7fd59977 106 return xsputn(&cc,1);
107}
108
109//=======================================================================
110//function : underflow
111//purpose : redefined virtual
112//=======================================================================
113
114int LDOM_SBuffer::underflow()
115{
116 return EOF;
117}
118
119//int LDOM_SBuffer::uflow()
120//{ return EOF; }
121
122//=======================================================================
123//function : xsputn()
124//purpose : redefined virtual
125//=======================================================================
126int LDOM_SBuffer::xsputn(const char* aStr, int n)
127{
128 int aLen = n + 1;
129 int freeLen = myMaxBuf - myCurString->len - 1;
130 if (freeLen >= n)
131 {
132 strncpy(myCurString->buf + myCurString->len, aStr, aLen);
133 }
134 else if (freeLen <= 0)
135 {
70167e69 136 LDOM_StringElem* aNextElem = new (myAlloc) LDOM_StringElem(Max(aLen, myMaxBuf), myAlloc);
7fd59977 137 myCurString->next = aNextElem;
138 myCurString = aNextElem;
139 strncpy(myCurString->buf + myCurString->len, aStr, aLen);
140 }
141 else // 0 < freeLen < n
142 {
143 // copy string by parts
144 strncpy(myCurString->buf + myCurString->len, aStr, freeLen);
145 myCurString->len += freeLen;
146 *(myCurString->buf + myCurString->len) = '\0';
147 aLen -= freeLen;
70167e69 148 LDOM_StringElem* aNextElem = new (myAlloc) LDOM_StringElem(Max(aLen, myMaxBuf), myAlloc);
7fd59977 149 myCurString->next = aNextElem;
150 myCurString = aNextElem;
151 strncpy(myCurString->buf + myCurString->len, aStr + freeLen, aLen);
152 }
153 myCurString->len += aLen - 1;
154 *(myCurString->buf + myCurString->len) = '\0';
155
156 myLength += n;
157 return n;
158}
159
160//streamsize LDOM_SBuffer::xsgetn(char* s, streamsize n)
161//{ return _IO_default_xsgetn(this, s, n); }
162
163//=======================================================================
164//function : LDOM_OSStream()
165//purpose : Constructor
166//=======================================================================
167LDOM_OSStream::LDOM_OSStream (const Standard_Integer theMaxBuf)
168 : Standard_OStream (&myBuffer), myBuffer (theMaxBuf)
169{
170 init(&myBuffer);
171}