Branch data Line data Source code
1 : : /*
2 : : Copyright (C) 2012-2014 Jeremiah Martell
3 : : All rights reserved.
4 : :
5 : : Redistribution and use in source and binary forms, with or without modification,
6 : : are permitted provided that the following conditions are met:
7 : :
8 : : - Redistributions of source code must retain the above copyright notice,
9 : : this list of conditions and the following disclaimer.
10 : : - Redistributions in binary form must reproduce the above copyright notice,
11 : : this list of conditions and the following disclaimer in the documentation
12 : : and/or other materials provided with the distribution.
13 : : - Neither the name of Jeremiah Martell nor the name of GeekHorse nor the
14 : : name of Pinto nor the names of its contributors may be used to endorse
15 : : or promote products derived from this software without specific prior
16 : : written permission.
17 : :
18 : : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 : : ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 : : WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 : : DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22 : : ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 : : (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 : : LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 : : ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 : : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 : : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 : : */
29 : :
30 : : /******************************************************************************/
31 : : /*!
32 : : \file
33 : : Dynamic text structure functions.
34 : : */
35 : : #define PINTO_FILE_NUMBER 2
36 : :
37 : : /******************************************************************************/
38 : : #include <string.h>
39 : :
40 : : #include "pinto.h"
41 : : #include "pintoInternal.h"
42 : :
43 : : /******************************************************************************/
44 : : /* How much increase the size of our buffer, via realloc, if we need more */
45 : : s32 PINTO_TEXT_SIZE_GROWTH = 1024;
46 : :
47 : : /******************************************************************************/
48 : : const char valueToChar[ 64 ] = {
49 : : '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
50 : : 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
51 : : 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
52 : : 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
53 : : 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
54 : : 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
55 : : 'Y', 'Z', ':', ';' };
56 : :
57 : : /******************************************************************************/
58 : : /*!
59 : : \brief Initialize a text object.
60 : : \param[out] text_A The new text object.
61 : : Will be allocated with the pintoHook memory functions. Caller is
62 : : responsible for freeing by passing the text object to pintoTextFree().
63 : : \return PINTO_RC
64 : : */
65 : 403334 : PINTO_RC pintoTextInit( PintoText **text_A )
66 : : {
67 : : /* DATA */
68 : 403334 : PINTO_RC rc = PINTO_RC_SUCCESS;
69 : :
70 : 403334 : PintoText *newText = NULL;
71 : :
72 : :
73 : : /* CODE */
74 [ + + ]: 403334 : ERR_IF( text_A == NULL, PINTO_RC_ERROR_PRECOND );
75 [ + + ]: 403333 : ERR_IF( (*text_A) != NULL, PINTO_RC_ERROR_PRECOND );
76 : :
77 [ + + ]: 403332 : PINTO_CALLOC( newText, PintoText, 1 );
78 : :
79 [ + + ]: 403269 : PINTO_CALLOC( newText->string, char, PINTO_TEXT_SIZE_GROWTH );
80 : 403206 : newText->allocedSize = PINTO_TEXT_SIZE_GROWTH;
81 : :
82 : 403206 : newText->usedSize = 0;
83 : 403206 : newText->index = 0;
84 : :
85 : : /* give back */
86 : 403206 : (*text_A) = newText;
87 : 403206 : newText = NULL;
88 : :
89 : :
90 : : /* CLEANUP */
91 : : cleanup:
92 : :
93 [ + + ]: 403334 : if ( newText != NULL )
94 : : {
95 : 63 : pintoHookFree( newText->string );
96 : 63 : newText->string = NULL;
97 : :
98 : 63 : pintoHookFree( newText );
99 : 63 : newText = NULL;
100 : : }
101 : :
102 : 403334 : return rc;
103 : : }
104 : :
105 : : /******************************************************************************/
106 : : /*!
107 : : \brief Frees a text object.
108 : : \param[in] text_F Text object to be freed. Will be freed with
109 : : pintoHookFree(). On return, text_F will be NULL.
110 : : \return void
111 : : */
112 : 906453 : void pintoTextFree( PintoText **text_F )
113 : : {
114 : : /* CODE */
115 [ + + ][ + + ]: 906453 : if ( text_F == NULL || (*text_F) == NULL )
116 : : {
117 : 704707 : return;
118 : : }
119 : :
120 : 201746 : pintoHookFree( (*text_F)->string );
121 : 201746 : (*text_F)->string = NULL;
122 : :
123 : 201746 : pintoHookFree( (*text_F) );
124 : 201746 : (*text_F) = NULL;
125 : :
126 : 906453 : return;
127 : : }
128 : :
129 : : /******************************************************************************/
130 : : /*!
131 : : \brief Adds a character to the text object.
132 : : \param[in] text Text object to add to.
133 : : \param[in] ch Character to add.
134 : : \return PINTO_RC
135 : :
136 : : Will not add a character that isn't used in encoding, which makes the rest
137 : : of the code simpler as we don't have to deal with invalid characters.
138 : : */
139 : 282404282 : PINTO_RC pintoTextAddChar( PintoText *text, char ch )
140 : : {
141 : : /* DATA */
142 : 282404282 : PINTO_RC rc = PINTO_RC_SUCCESS;
143 : :
144 : 282404282 : char *reallocedText = NULL;
145 : :
146 : :
147 : : /* CODE */
148 [ + + ]: 282404282 : ERR_IF( text == NULL, PINTO_RC_ERROR_PRECOND );
149 : :
150 : : /* only add characters that are valid.
151 : : skipping invalid characters allows clients to wordwrap
152 : : the text, or add tabs or spaces. */
153 [ + + ][ + + ]: 282404281 : if ( ch < '#' || ch > 'z' || ch == '[' || ch == '\\' || ch == ']' || ch == '_' || ch == '`' )
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ]
154 : : {
155 : : /* not a valid character, don't add */
156 : : goto cleanup;
157 : : }
158 : :
159 : : /* No text should ever reach this size, so we put this in to prevent
160 : : the buffer from growing too big.
161 : : The fear is a malicious person crafting a small pinto encoding, that will
162 : : deflate to take up huge amounts of ram ... if you consider more than 16MB to be huge :)
163 : : That probably won't happen in this function, but we still enforce the constraint */
164 [ + + ]: 282404258 : ERR_IF( text->usedSize + 1 > ( PINTO_MAX_WIDTH * PINTO_MAX_HEIGHT ), PINTO_RC_ERROR_FORMAT_TOO_LONG );
165 : :
166 : : /* do we need to resize our buffer? */
167 [ + + ]: 282404257 : if ( text->usedSize + 1 >= text->allocedSize )
168 : : {
169 [ + + ]: 270417 : PINTO_REALLOC( reallocedText, text->string, char, text->allocedSize + PINTO_TEXT_SIZE_GROWTH );
170 : :
171 : 269830 : text->allocedSize += PINTO_TEXT_SIZE_GROWTH;
172 : 269830 : text->string = reallocedText;
173 : : }
174 : :
175 : : /* add */
176 : 282403670 : text->string[ text->usedSize ] = ch;
177 : 282403670 : text->usedSize += 1;
178 : 282403670 : text->string[ text->usedSize ] = '\0';
179 : :
180 : :
181 : : /* CLEANUP */
182 : : cleanup:
183 : :
184 : 282404282 : return rc;
185 : : }
186 : :
187 : : /******************************************************************************/
188 : : /*!
189 : : \brief Used to see if we're at the end of the text.
190 : : \param[in] text Text.
191 : : \return s32 True if we're at the end of the text.
192 : : */
193 : 8338617 : s32 pintoTextAtEnd( PintoText *text )
194 : : {
195 : : /* CODE */
196 : : PARANOID_ERR_IF( text == NULL );
197 : :
198 : 8338617 : return text->index == text->usedSize;
199 : : }
200 : :
201 : : /******************************************************************************/
202 : : /*!
203 : : \brief Peeks at next character in text.
204 : : \param[in] text Text.
205 : : \param[out] ch Next character in text.
206 : : \return PINTO_RC
207 : : */
208 : 99899817 : PINTO_RC pintoTextPeekChar( PintoText *text, char *ch )
209 : : {
210 : : /* DATA */
211 : 99899817 : PINTO_RC rc = PINTO_RC_SUCCESS;
212 : :
213 : :
214 : : /* CODE */
215 : : PARANOID_ERR_IF( text == NULL );
216 : : PARANOID_ERR_IF( ch == NULL );
217 : :
218 [ + + ]: 99899817 : ERR_IF( text->index == text->usedSize, PINTO_RC_ERROR_FORMAT_INVALID );
219 : :
220 : 99899809 : (*ch) = text->string[ text->index ];
221 : :
222 : :
223 : : /* CLEANUP */
224 : : cleanup:
225 : :
226 : 99899817 : return rc;
227 : : }
228 : :
229 : : /******************************************************************************/
230 : : /*!
231 : : \brief Gets the next character in text.
232 : : \param[in] text Text.
233 : : \param[out] ch Next character in text.
234 : : \return PINTO_RC
235 : : */
236 : 8431524 : PINTO_RC pintoTextGetChar( PintoText *text, char *ch )
237 : : {
238 : : /* DATA */
239 : 8431524 : PINTO_RC rc = PINTO_RC_SUCCESS;
240 : :
241 : :
242 : : /* CODE */
243 : : PARANOID_ERR_IF( text == NULL );
244 : : PARANOID_ERR_IF( ch == NULL );
245 : :
246 [ + + ]: 8431524 : ERR_IF( text->index == text->usedSize, PINTO_RC_ERROR_FORMAT_INVALID );
247 : :
248 : 8431523 : (*ch) = text->string[ text->index ];
249 : :
250 : 8431523 : text->index += 1;
251 : :
252 : :
253 : : /* CLEANUP */
254 : : cleanup:
255 : :
256 : 8431524 : return rc;
257 : : }
258 : :
259 : : /******************************************************************************/
260 : : /*!
261 : : \brief Adds an encoded value to text.
262 : : \param[in] text Text.
263 : : \param[in] value Value to add.
264 : : \return PINTO_RC
265 : :
266 : : If the value is within 0-63, it is encoded as a single character. See
267 : : valueToChar[] for the mapping.
268 : :
269 : : If the value is higher, then it's encoding like the following:
270 : :
271 : : 0 - 63 V
272 : : 64 - 127 #V
273 : : 128 - 191 $V
274 : : 192 - 255 %V
275 : : 256 - 319 'V
276 : : 320 - 383 (V
277 : : 384 - 447 )V
278 : : 448 - 511 *V
279 : : 512 - 575 +V
280 : : 576 - 639 ,V
281 : : 640 - 703 -V
282 : : 704 - 767 .V
283 : : 768 - 831 /V
284 : : 832 - 4095 <VV
285 : : 4096 - 262143 =VVV
286 : : 262144 - 16777215 >VVVV
287 : :
288 : : Values 0-63, 832-4095, 4096-262143, and 262144-16777215 are encoded in
289 : : a straight-forward manner. You decode the value as a base-64 number.
290 : : A is A
291 : : <AB is (A * 64) + B
292 : : =ABC is (A * 64 * 64) + (B * 64) + (C)
293 : : >ABCD is (A * 64 * 64 * 64) + (B * 64 * 64) + (C * 64) + D
294 : :
295 : : Values 64-831 are encoded differently.
296 : : #A is 64 + A
297 : : $A is 128 + A
298 : : %A is 192 + A
299 : : ...and so on.
300 : : This is an enhancement so those values only use 2 characters instead of
301 : : the straight-forward 3 character <AB format.
302 : :
303 : : Examples:
304 : : Value 0 is encoded as "0"
305 : : Value 10 is encoded as "a"
306 : : Value 35 is encoded as "z"
307 : : Value 36 is encoded as "A"
308 : : Value 61 is encoded as "Z"
309 : : Value 62 is encoded as ":"
310 : : Value 63 is encoded as ";"
311 : : Value 64 is encoded as "#0"
312 : : Value 66 is encoded as "#2"
313 : : Value 127 is encoded as "#;"
314 : : Value 128 is encoded as "$0"
315 : : Value 832 is encoded as "<d0"
316 : : Value 833 is encoded as "<d1"
317 : : */
318 : 119056721 : PINTO_RC pintoTextAddValue( PintoText *text, s32 value )
319 : : {
320 : : /* DATA */
321 : 119056721 : PINTO_RC rc = PINTO_RC_SUCCESS;
322 : :
323 : :
324 : : /* CODE */
325 : : PARANOID_ERR_IF( text == NULL );
326 : : PARANOID_ERR_IF( value < 0 );
327 : : PARANOID_ERR_IF( value >= (64 * 64 * 64 * 64) );
328 : :
329 [ + + ]: 119056721 : if ( value < 64 )
330 : : {
331 : 70560431 : rc = pintoTextAddChar( text, valueToChar[ value % 64 ] );
332 [ + + ]: 70560431 : ERR_IF_PASSTHROUGH;
333 : : }
334 [ + + ]: 48496290 : else if ( value < (64 * 14) )
335 : : {
336 : 27485711 : rc = pintoTextAddChar( text, '\"' + ( value / 64 ) );
337 [ + + ]: 27485711 : ERR_IF_PASSTHROUGH;
338 : :
339 : 27485708 : rc = pintoTextAddChar( text, valueToChar[ value % 64 ] );
340 [ + + ]: 27485708 : ERR_IF_PASSTHROUGH;
341 : : }
342 [ + + ]: 21010579 : else if ( value < (64 * 64) )
343 : : {
344 : 4230793 : rc = pintoTextAddChar( text, '<' );
345 [ + + ]: 4230793 : ERR_IF_PASSTHROUGH;
346 : :
347 : 4230788 : rc = pintoTextAddChar( text, valueToChar[ ( (value) / 64 ) % 64 ] );
348 [ + + ]: 4230788 : ERR_IF_PASSTHROUGH;
349 : :
350 : 4230783 : rc = pintoTextAddChar( text, valueToChar[ (value) % 64 ] );
351 [ + + ]: 4230783 : ERR_IF_PASSTHROUGH;
352 : : }
353 [ + + ]: 16779786 : else if ( value < (64 * 64 * 64) )
354 : : {
355 : 264028 : rc = pintoTextAddChar( text, '=' );
356 [ + + ]: 264028 : ERR_IF_PASSTHROUGH;
357 : :
358 : 264026 : rc = pintoTextAddChar( text, valueToChar[ ( (value) / (64 * 64) ) % 64 ] );
359 [ + + ]: 264026 : ERR_IF_PASSTHROUGH;
360 : :
361 : 264024 : rc = pintoTextAddChar( text, valueToChar[ ( (value) / (64 ) ) % 64 ] );
362 [ + + ]: 264024 : ERR_IF_PASSTHROUGH;
363 : :
364 : 264022 : rc = pintoTextAddChar( text, valueToChar[ (value) % 64 ] );
365 [ + + ]: 264022 : ERR_IF_PASSTHROUGH;
366 : : }
367 : : else
368 : : {
369 : : PARANOID_ERR_IF( value >= (64 * 64 * 64 * 64) );
370 : :
371 : 16515758 : rc = pintoTextAddChar( text, '>' );
372 [ + + ]: 16515758 : ERR_IF_PASSTHROUGH;
373 : :
374 : 16515756 : rc = pintoTextAddChar( text, valueToChar[ ( (value) / (64 * 64 * 64) ) % 64 ] );
375 [ + + ]: 16515756 : ERR_IF_PASSTHROUGH;
376 : :
377 : 16515754 : rc = pintoTextAddChar( text, valueToChar[ ( (value) / (64 * 64 ) ) % 64 ] );
378 [ + + ]: 16515754 : ERR_IF_PASSTHROUGH;
379 : :
380 : 16515752 : rc = pintoTextAddChar( text, valueToChar[ ( (value) / (64 ) ) % 64 ] );
381 [ + + ]: 16515752 : ERR_IF_PASSTHROUGH;
382 : :
383 : 16515750 : rc = pintoTextAddChar( text, valueToChar[ (value) % 64 ] );
384 [ + + ]: 16515750 : ERR_IF_PASSTHROUGH;
385 : : }
386 : :
387 : :
388 : : /* CLEANUP */
389 : : cleanup:
390 : :
391 : 119056721 : return rc;
392 : : }
393 : :
394 : : /******************************************************************************/
395 : : /*!
396 : : \brief Gets an encoded value from text.
397 : : \param[in] text Text.
398 : : \param[in,out] value The encoded value.
399 : : \return PINTO_RC
400 : :
401 : : Decodes an encoded value. See pintoTextAddValue() for the encoding.
402 : : */
403 : 117975098 : PINTO_RC pintoTextGetValue( PintoText *text, s32 *value )
404 : : {
405 : : /* DATA */
406 : 117975098 : PINTO_RC rc = PINTO_RC_SUCCESS;
407 : :
408 : 117975098 : char ch = 0;
409 : :
410 : :
411 : : /* CODE */
412 : : PARANOID_ERR_IF( text == NULL );
413 : : PARANOID_ERR_IF( value == NULL );
414 : :
415 [ + + ]: 117975098 : ERR_IF( text->index == text->usedSize, PINTO_RC_ERROR_FORMAT_INVALID );
416 : :
417 : 117975095 : (*value) = 0;
418 : :
419 : 117975095 : ch = text->string[ text->index ];
420 : :
421 : : /* No valid character has a lower value than '#', so we don't have to test
422 : : for "ch >= '#'". Just testing for "ch <= '/'" is enough. */
423 [ + + ]: 117975095 : if ( ch <= '/' )
424 : : {
425 : : PARANOID_ERR_IF( ch < '#' );
426 : :
427 : 27485600 : text->index += 1;
428 : :
429 : 27485600 : (*value) = ch - '\"';
430 : :
431 : 27485600 : rc = pintoTextUpdateValue( text, value );
432 [ + + ]: 27485600 : ERR_IF_PASSTHROUGH;
433 : : }
434 [ + + ]: 90489495 : else if ( ch == '<' )
435 : : {
436 : 4230655 : text->index += 1;
437 : :
438 : 4230655 : rc = pintoTextUpdateValue( text, value );
439 [ + + ]: 4230655 : ERR_IF_PASSTHROUGH;
440 : :
441 : 4230654 : rc = pintoTextUpdateValue( text, value );
442 [ + + ]: 4230654 : ERR_IF_PASSTHROUGH;
443 : : }
444 [ + + ]: 86258840 : else if ( ch == '=' )
445 : : {
446 : 263999 : text->index += 1;
447 : :
448 : 263999 : rc = pintoTextUpdateValue( text, value );
449 [ + + ]: 263999 : ERR_IF_PASSTHROUGH;
450 : :
451 : 263998 : rc = pintoTextUpdateValue( text, value );
452 [ + + ]: 263998 : ERR_IF_PASSTHROUGH;
453 : :
454 : 263997 : rc = pintoTextUpdateValue( text, value );
455 [ + + ]: 263997 : ERR_IF_PASSTHROUGH;
456 : : }
457 [ + + ]: 85994841 : else if ( ch == '>' )
458 : : {
459 : 16515747 : text->index += 1;
460 : :
461 : 16515747 : rc = pintoTextUpdateValue( text, value );
462 [ + + ]: 16515747 : ERR_IF_PASSTHROUGH;
463 : :
464 : 16515746 : rc = pintoTextUpdateValue( text, value );
465 [ + + ]: 16515746 : ERR_IF_PASSTHROUGH;
466 : :
467 : 16515745 : rc = pintoTextUpdateValue( text, value );
468 [ + + ]: 16515745 : ERR_IF_PASSTHROUGH;
469 : :
470 : 16515744 : rc = pintoTextUpdateValue( text, value );
471 [ + + ]: 16515744 : ERR_IF_PASSTHROUGH;
472 : : }
473 : : else
474 : : {
475 : 69479094 : rc = pintoTextUpdateValue( text, value );
476 [ + + ]: 69479094 : ERR_IF_PASSTHROUGH;
477 : : }
478 : :
479 : :
480 : : /* CLEANUP */
481 : : cleanup:
482 : :
483 : 117975098 : return rc;
484 : : }
485 : :
486 : : /******************************************************************************/
487 : : /*!
488 : : \brief Reads next character in text, and uses it to update value.
489 : : \param[in] text Text.
490 : : \param[in,out] value Value to be updated.
491 : : \return PINTO_RC
492 : :
493 : : Value parameter is first multiplied by 64. The next character in text is
494 : : read and decoded to a number in 0-63, then added to value.
495 : :
496 : : Basically this function does:
497 : : value = (value * 64) + nextCharacterValue;
498 : :
499 : : This is used for decoding numbers that were encoded with multiple
500 : : characters.
501 : :
502 : : See pintoTextGetValue() for more details.
503 : : */
504 : 174162417 : PINTO_RC pintoTextUpdateValue( PintoText *text, s32 *value )
505 : : {
506 : : /* DATA */
507 : 174162417 : PINTO_RC rc = PINTO_RC_SUCCESS;
508 : :
509 : 174162417 : char ch = 0;
510 : :
511 : :
512 : : /* CODE */
513 : : PARANOID_ERR_IF( text == NULL );
514 : : PARANOID_ERR_IF( value == NULL );
515 : :
516 [ + + ]: 174162417 : ERR_IF( text->index == text->usedSize, PINTO_RC_ERROR_FORMAT_INVALID );
517 : :
518 : 174162413 : (*value) *= 64;
519 : :
520 : 174162413 : ch = text->string[ text->index ];
521 : :
522 [ + + ][ + + ]: 174162413 : if ( ch >= '0' && ch <= '9' )
523 : : {
524 : 75084234 : (*value) += ( ch - '0' );
525 : : }
526 [ + + ]: 99078179 : else if ( ch >= 'a' )
527 : : {
528 : : /* No valid character has a higher value
529 : : than 'z', so we don't have to test for
530 : : "ch <= 'z'". Just testing for "ch >= 'a'"
531 : : is enough. */
532 : : PARANOID_ERR_IF( ch > 'z' );
533 : :
534 : 51408706 : (*value) += 10 + ( ch - 'a' );
535 : : }
536 [ + + ][ + + ]: 47669473 : else if ( ch >= 'A' && ch <= 'Z' )
537 : : {
538 : 44364961 : (*value) += 36 + ( ch - 'A' );
539 : : }
540 [ + + ]: 3304512 : else if ( ch == ':' )
541 : : {
542 : 1650363 : (*value) += 62;
543 : : }
544 [ + + ]: 1654149 : else if ( ch == ';' )
545 : : {
546 : 1654128 : (*value) += 63;
547 : : }
548 : : else
549 : : {
550 : 21 : ERR_IF( 1, PINTO_RC_ERROR_FORMAT_INVALID );
551 : : }
552 : :
553 : 174162392 : text->index += 1;
554 : :
555 : :
556 : : /* CLEANUP */
557 : : cleanup:
558 : :
559 : 174162417 : return rc;
560 : : }
561 : :
562 : : /******************************************************************************/
563 : : /*!
564 : : \brief Frees a text object and gives back old string.
565 : : \param[in] text Text.
566 : : \param[out] string_A Will be string of text. Caller is
567 : : responsible for freeing by passing to pintoHookFree().
568 : : \return void
569 : : */
570 : 201460 : void pintoTextFreeAndGetString( PintoText **text_F, char **string_A )
571 : : {
572 : : /* CODE */
573 : : PARANOID_ERR_IF( text_F == NULL );
574 : : PARANOID_ERR_IF( (*text_F) == NULL );
575 : : PARANOID_ERR_IF( string_A == NULL );
576 : : PARANOID_ERR_IF( (*string_A) != NULL );
577 : :
578 : : /* giveback */
579 : : PARANOID_ERR_IF( (*text_F)->string == NULL );
580 : 201460 : (*string_A) = (*text_F)->string;
581 : 201460 : (*text_F)->string = NULL;
582 : :
583 : 201460 : pintoHookFree( (*text_F) );
584 : 201460 : (*text_F) = NULL;
585 : :
586 : 201460 : return;
587 : : }
588 : :
589 : : /******************************************************************************/
590 : : /*!
591 : : \brief Helps the inflate function by duplicating previous characters and
592 : : adding them to the end of the text.
593 : : \param[in] text Text.
594 : : \param[in] distance Amount of characters from the end to start copying.
595 : : \param[in] length Amount of characters to copy.
596 : : \return PINTO_RC
597 : :
598 : : Will work even if length is greater than distance.
599 : : For example, if the text was:
600 : : "ABCDE"
601 : : With distance=2 and length=5, then the text would become:
602 : : "ABCDEDEDED"
603 : : */
604 : 1190576 : PINTO_RC pintoTextInflateHelper( PintoText *text, s32 distance, s32 length )
605 : : {
606 : : /* DATA */
607 : 1190576 : PINTO_RC rc = PINTO_RC_SUCCESS;
608 : :
609 : 1190576 : char *reallocedText = NULL;
610 : :
611 : 1190576 : s32 i = 0;
612 : 1190576 : s32 j = 0;
613 : :
614 : :
615 : : /* CODE */
616 : : PARANOID_ERR_IF( text == NULL );
617 : : PARANOID_ERR_IF( distance < 0 );
618 : : PARANOID_ERR_IF( length < 0 );
619 : :
620 [ + + ]: 1190576 : ERR_IF( distance == 0, PINTO_RC_ERROR_FORMAT_INVALID );
621 [ + + ]: 1190574 : ERR_IF( length == 0, PINTO_RC_ERROR_FORMAT_INVALID );
622 : :
623 : : /* make sure distance is not too big */
624 [ + + ]: 1190572 : ERR_IF( text->usedSize - distance < 0, PINTO_RC_ERROR_FORMAT_INVALID );
625 : :
626 : : /* do we need to resize our buffer? */
627 [ + + ]: 1190570 : if ( text->usedSize + length >= text->allocedSize )
628 : : {
629 : : /* No text should ever reach this size, so we put this in to prevent
630 : : the buffer from growing too big.
631 : : The fear is a malicious person crafting a small pinto encoding, that will
632 : : deflate to take up huge amounts of ram ... if you consider more than 16MB to be huge :) */
633 [ + + ]: 98106 : ERR_IF( text->usedSize + length > ( PINTO_MAX_WIDTH * PINTO_MAX_HEIGHT ), PINTO_RC_ERROR_FORMAT_TOO_LONG );
634 : :
635 : : /* *** */
636 [ + + ]: 98105 : PINTO_REALLOC( reallocedText, text->string, char, text->allocedSize + length );
637 : :
638 : 98102 : text->allocedSize += length;
639 : 98102 : text->string = reallocedText;
640 : : }
641 : :
642 : : /* add */
643 : 1190566 : j = text->usedSize - distance;
644 : :
645 [ + + ]: 164489449 : while ( i < length )
646 : : {
647 : 163298883 : text->string[ text->usedSize ] = text->string[ j ];
648 : 163298883 : text->usedSize += 1;
649 : 163298883 : text->string[ text->usedSize ] = '\0';
650 : :
651 : : /* next character */
652 : 163298883 : i += 1;
653 : 163298883 : j += 1;
654 : : }
655 : :
656 : :
657 : : /* CLEANUP */
658 : : cleanup:
659 : :
660 : 1190576 : return rc;
661 : : }
662 : :
|