0024931: Stack overflow when writing large shapes to XML
[occt.git] / src / LDOM / LDOM_OSStream.cxx
1 // Created on: 2001-10-01
2 // Created by: Julia DOROVSKIKH
3 // Copyright (c) 2001-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <LDOM_OSStream.hxx>
17 #include <NCollection_DefineAlloc.hxx>
18 #include <NCollection_IncAllocator.hxx>
19 #include <string.h>
20 #include <Standard.hxx>
21 #include <Standard_Integer.hxx>
22
23 // One element of sequence
24 /* Can only be allocated by the allocator and assumes it is IncAllocator, so 
25    no destructor is required.
26 */
27 class 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
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)
39   {
40   }
41
42 friend class LDOM_SBuffer;
43 };
44
45 //=======================================================================
46 //function : LDOM_SBuffer()
47 //purpose  : 
48 //=======================================================================
49 LDOM_SBuffer::LDOM_SBuffer (const Standard_Integer theMaxBuf)
50      : myMaxBuf (theMaxBuf), myLength(0),
51        myAlloc (new NCollection_IncAllocator)
52 {
53   myFirstString = new (myAlloc) LDOM_StringElem (theMaxBuf, myAlloc);
54   myCurString   = myFirstString;
55 }
56
57 //=======================================================================
58 //function : ~LDOM_SBuffer()
59 //purpose  : 
60 //=======================================================================
61 LDOM_SBuffer::~LDOM_SBuffer ()
62 {
63   //no destruction is required as IncAllocator is used
64 }
65
66 //=======================================================================
67 //function : Clear()
68 //purpose  : 
69 //=======================================================================
70 void LDOM_SBuffer::Clear ()
71 {
72   myAlloc       = new NCollection_IncAllocator;
73   myFirstString = new (myAlloc) LDOM_StringElem (myMaxBuf, myAlloc);
74   myLength      = 0;
75   myCurString   = myFirstString;
76 }
77
78 //=======================================================================
79 //function : str()
80 //purpose  : 
81 //=======================================================================
82 Standard_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 //=======================================================================
103 int LDOM_SBuffer::overflow(int c)
104 {
105   char cc = (char)c;
106   return xsputn(&cc,1);
107 }
108
109 //=======================================================================
110 //function : underflow
111 //purpose  : redefined virtual
112 //=======================================================================
113
114 int 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 //=======================================================================
126 int 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   {
136     LDOM_StringElem* aNextElem = new (myAlloc) LDOM_StringElem(Max(aLen, myMaxBuf), myAlloc);
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;
148     LDOM_StringElem* aNextElem = new (myAlloc) LDOM_StringElem(Max(aLen, myMaxBuf), myAlloc);
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 //=======================================================================
167 LDOM_OSStream::LDOM_OSStream (const Standard_Integer theMaxBuf)
168      : Standard_OStream (&myBuffer), myBuffer (theMaxBuf)
169 {
170   init(&myBuffer);
171 }