xref: /trunk/main/basic/source/comp/buffer.cxx (revision a3cdc23e488c57f3433f22cd4458e65c27aa499c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_basic.hxx"
24 
25 #include "sbcomp.hxx"
26 #include "buffer.hxx"
27 #include <string.h>
28 
29 const static sal_uInt32 UP_LIMIT=0xFFFFFF00L;
30 
31 // Der SbiBuffer wird in Inkrements von mindestens 16 Bytes erweitert.
32 // Dies ist notwendig, da viele Klassen von einer Pufferlänge
33 // von x*16 Bytes ausgehen.
34 
35 SbiBuffer::SbiBuffer( SbiParser* p, short n )
36 {
37     pParser = p;
38     n = ( (n + 15 ) / 16 ) * 16;
39     if( !n ) n = 16;
40     pBuf  = NULL;
41     pCur  = NULL;
42     nInc  = n;
43     nSize =
44     nOff  = 0;
45 }
46 
47 SbiBuffer::~SbiBuffer()
48 {
49     delete[] pBuf;
50 }
51 
52 // Rausreichen des Puffers
53 // Dies führt zur Löschung des Puffers!
54 
55 char* SbiBuffer::GetBuffer()
56 {
57     char* p = pBuf;
58     pBuf = NULL;
59     pCur = NULL;
60     return p;
61 }
62 
63 // Test, ob der Puffer n Bytes aufnehmen kann.
64 // Im Zweifelsfall wird er vergrössert
65 
66 sal_Bool SbiBuffer::Check( sal_uInt16 n )
67 {
68     if( !n ) return sal_True;
69     if( ( static_cast<sal_uInt32>( nOff )+ n ) >  static_cast<sal_uInt32>( nSize ) )
70     {
71         if( nInc == 0 )
72             return sal_False;
73         sal_uInt16 nn = 0;
74         while( nn < n ) nn = nn + nInc;
75         char* p;
76         if( ( static_cast<sal_uInt32>( nSize ) + nn ) > UP_LIMIT ) p = NULL;
77         else p = new char [nSize + nn];
78         if( !p )
79         {
80             pParser->Error( SbERR_PROG_TOO_LARGE );
81             nInc = 0;
82             delete[] pBuf; pBuf = NULL;
83             return sal_False;
84         }
85         else
86         {
87             if( nSize ) memcpy( p, pBuf, nSize );
88             delete[] pBuf;
89             pBuf = p;
90             pCur = pBuf + nOff;
91             nSize = nSize + nn;
92         }
93     }
94     return sal_True;
95 }
96 
97 // Angleich des Puffers auf die übergebene Byte-Grenze
98 
99 void SbiBuffer::Align( sal_Int32 n )
100 {
101     if( nOff % n ) {
102         sal_uInt32 nn =( ( nOff + n ) / n ) * n;
103         if( nn <= UP_LIMIT )
104         {
105             nn = nn - nOff;
106             if( Check( static_cast<sal_uInt16>(nn) ) )
107             {
108                 memset( pCur, 0, nn );
109                 pCur += nn;
110                 nOff = nOff + nn;
111             }
112         }
113     }
114 }
115 
116 // Patch einer Location
117 
118 void SbiBuffer::Patch( sal_uInt32 off, sal_uInt32 val )
119 {
120     if( ( off + sizeof( sal_uInt32 ) ) < nOff )
121     {
122         sal_uInt16 val1 = static_cast<sal_uInt16>( val & 0xFFFF );
123         sal_uInt16 val2 = static_cast<sal_uInt16>( val >> 16 );
124         sal_uInt8* p = (sal_uInt8*) pBuf + off;
125         *p++ = (char) ( val1 & 0xFF );
126         *p++ = (char) ( val1 >> 8 );
127         *p++ = (char) ( val2 & 0xFF );
128         *p   = (char) ( val2 >> 8 );
129     }
130 }
131 
132 // Forward References auf Labels und Prozeduren
133 // bauen eine Kette auf. Der Anfang der Kette ist beim übergebenen
134 // Parameter, das Ende der Kette ist 0.
135 
136 void SbiBuffer::Chain( sal_uInt32 off )
137 {
138     if( off && pBuf )
139     {
140         sal_uInt8 *ip;
141         sal_uInt32 i = off;
142         sal_uInt32 val1 = (nOff & 0xFFFF);
143         sal_uInt32 val2 = (nOff >> 16);
144         do
145         {
146             ip = (sal_uInt8*) pBuf + i;
147             sal_uInt8* pTmp = ip;
148                 i =  *pTmp++; i |= *pTmp++ << 8; i |= *pTmp++ << 16; i |= *pTmp++ << 24;
149 
150             if( i >= nOff )
151             {
152                 pParser->Error( SbERR_INTERNAL_ERROR, "BACKCHAIN" );
153                 break;
154             }
155             *ip++ = (char) ( val1 & 0xFF );
156             *ip++ = (char) ( val1 >> 8 );
157             *ip++ = (char) ( val2 & 0xFF );
158             *ip   = (char) ( val2 >> 8 );
159         } while( i );
160     }
161 }
162 
163 sal_Bool SbiBuffer::operator +=( sal_Int8 n )
164 {
165     if( Check( 1 ) )
166     {
167         *pCur++ = (char) n; nOff++; return sal_True;
168     } else return sal_False;
169 }
170 
171 sal_Bool SbiBuffer::operator +=( sal_uInt8 n )
172 {
173     if( Check( 1 ) )
174     {
175         *pCur++ = (char) n; nOff++; return sal_True;
176     } else return sal_False;
177 }
178 
179 sal_Bool SbiBuffer::operator +=( sal_Int16 n )
180 {
181     if( Check( 2 ) )
182     {
183         *pCur++ = (char) ( n & 0xFF );
184         *pCur++ = (char) ( n >> 8 );
185         nOff += 2; return sal_True;
186     } else return sal_False;
187 }
188 
189 sal_Bool SbiBuffer::operator +=( sal_uInt16 n )
190 {
191     if( Check( 2 ) )
192     {
193         *pCur++ = (char) ( n & 0xFF );
194         *pCur++ = (char) ( n >> 8 );
195         nOff += 2; return sal_True;
196     } else return sal_False;
197 }
198 
199 sal_Bool SbiBuffer::operator +=( sal_uInt32 n )
200 {
201     if( Check( 4 ) )
202     {
203         sal_uInt16 n1 = static_cast<sal_uInt16>( n & 0xFFFF );
204         sal_uInt16 n2 = static_cast<sal_uInt16>( n >> 16 );
205         if ( operator +=( n1 ) && operator +=( n2 ) )
206             return sal_True;
207         return sal_True;
208     }
209     return sal_False;
210 }
211 
212 sal_Bool SbiBuffer::operator +=( sal_Int32 n )
213 {
214     return operator +=( (sal_uInt32) n );
215 }
216 
217 sal_Bool SbiBuffer::operator +=( const String& n )
218 {
219     sal_uInt16 l = n.Len() + 1;
220     if( Check( l ) )
221     {
222         ByteString aByteStr( n, gsl_getSystemTextEncoding() );
223         memcpy( pCur, aByteStr.GetBuffer(), l );
224         pCur += l;
225         nOff = nOff + l;
226         return sal_True;
227     }
228     else return sal_False;
229 }
230 
231 sal_Bool SbiBuffer::Add( const void* p, sal_uInt16 len )
232 {
233     if( Check( len ) )
234     {
235         memcpy( pCur, p, len );
236         pCur += len;
237         nOff = nOff + len;
238         return sal_True;
239     } else return sal_False;
240 }
241 
242 /* vim: set noet sw=4 ts=4: */
243