1 | /**************************************************************************** |
2 | * |
3 | * psarrst.c |
4 | * |
5 | * Adobe's code for Array Stacks (body). |
6 | * |
7 | * Copyright 2007-2013 Adobe Systems Incorporated. |
8 | * |
9 | * This software, and all works of authorship, whether in source or |
10 | * object code form as indicated by the copyright notice(s) included |
11 | * herein (collectively, the "Work") is made available, and may only be |
12 | * used, modified, and distributed under the FreeType Project License, |
13 | * LICENSE.TXT. Additionally, subject to the terms and conditions of the |
14 | * FreeType Project License, each contributor to the Work hereby grants |
15 | * to any individual or legal entity exercising permissions granted by |
16 | * the FreeType Project License and this section (hereafter, "You" or |
17 | * "Your") a perpetual, worldwide, non-exclusive, no-charge, |
18 | * royalty-free, irrevocable (except as stated in this section) patent |
19 | * license to make, have made, use, offer to sell, sell, import, and |
20 | * otherwise transfer the Work, where such license applies only to those |
21 | * patent claims licensable by such contributor that are necessarily |
22 | * infringed by their contribution(s) alone or by combination of their |
23 | * contribution(s) with the Work to which such contribution(s) was |
24 | * submitted. If You institute patent litigation against any entity |
25 | * (including a cross-claim or counterclaim in a lawsuit) alleging that |
26 | * the Work or a contribution incorporated within the Work constitutes |
27 | * direct or contributory patent infringement, then any patent licenses |
28 | * granted to You under this License for that Work shall terminate as of |
29 | * the date such litigation is filed. |
30 | * |
31 | * By using, modifying, or distributing the Work you indicate that you |
32 | * have read and understood the terms and conditions of the |
33 | * FreeType Project License as well as those provided in this section, |
34 | * and you accept them fully. |
35 | * |
36 | */ |
37 | |
38 | |
39 | #include "psft.h" |
40 | #include <freetype/internal/ftdebug.h> |
41 | |
42 | #include "psglue.h" |
43 | #include "psarrst.h" |
44 | |
45 | #include "pserror.h" |
46 | |
47 | |
48 | /* |
49 | * CF2_ArrStack uses an error pointer, to enable shared errors. |
50 | * Shared errors are necessary when multiple objects allow the program |
51 | * to continue after detecting errors. Only the first error should be |
52 | * recorded. |
53 | */ |
54 | |
55 | FT_LOCAL_DEF( void ) |
56 | cf2_arrstack_init( CF2_ArrStack arrstack, |
57 | FT_Memory memory, |
58 | FT_Error* error, |
59 | size_t sizeItem ) |
60 | { |
61 | FT_ASSERT( arrstack ); |
62 | |
63 | /* initialize the structure */ |
64 | arrstack->memory = memory; |
65 | arrstack->error = error; |
66 | arrstack->sizeItem = sizeItem; |
67 | arrstack->allocated = 0; |
68 | arrstack->count = 0; |
69 | arrstack->totalSize = 0; |
70 | arrstack->ptr = NULL; |
71 | } |
72 | |
73 | |
74 | FT_LOCAL_DEF( void ) |
75 | cf2_arrstack_finalize( CF2_ArrStack arrstack ) |
76 | { |
77 | FT_Memory memory = arrstack->memory; /* for FT_FREE */ |
78 | |
79 | |
80 | FT_ASSERT( arrstack ); |
81 | |
82 | arrstack->allocated = 0; |
83 | arrstack->count = 0; |
84 | arrstack->totalSize = 0; |
85 | |
86 | /* free the data buffer */ |
87 | FT_FREE( arrstack->ptr ); |
88 | } |
89 | |
90 | |
91 | /* allocate or reallocate the buffer size; */ |
92 | /* return false on memory error */ |
93 | static FT_Bool |
94 | cf2_arrstack_setNumElements( CF2_ArrStack arrstack, |
95 | size_t numElements ) |
96 | { |
97 | FT_ASSERT( arrstack ); |
98 | |
99 | { |
100 | FT_Error error = FT_Err_Ok; /* for FT_REALLOC */ |
101 | FT_Memory memory = arrstack->memory; /* for FT_REALLOC */ |
102 | |
103 | size_t newSize = numElements * arrstack->sizeItem; |
104 | |
105 | |
106 | if ( numElements > FT_LONG_MAX / arrstack->sizeItem ) |
107 | goto exit; |
108 | |
109 | |
110 | FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */ |
111 | |
112 | if ( !FT_QREALLOC( arrstack->ptr, arrstack->totalSize, newSize ) ) |
113 | { |
114 | arrstack->allocated = numElements; |
115 | arrstack->totalSize = newSize; |
116 | |
117 | if ( arrstack->count > numElements ) |
118 | { |
119 | /* we truncated the list! */ |
120 | CF2_SET_ERROR( arrstack->error, Stack_Overflow ); |
121 | arrstack->count = numElements; |
122 | return FALSE; |
123 | } |
124 | |
125 | return TRUE; /* success */ |
126 | } |
127 | } |
128 | |
129 | exit: |
130 | /* if there's not already an error, store this one */ |
131 | CF2_SET_ERROR( arrstack->error, Out_Of_Memory ); |
132 | |
133 | return FALSE; |
134 | } |
135 | |
136 | |
137 | /* set the count, ensuring allocation is sufficient */ |
138 | FT_LOCAL_DEF( void ) |
139 | cf2_arrstack_setCount( CF2_ArrStack arrstack, |
140 | size_t numElements ) |
141 | { |
142 | FT_ASSERT( arrstack ); |
143 | |
144 | if ( numElements > arrstack->allocated ) |
145 | { |
146 | /* expand the allocation first */ |
147 | if ( !cf2_arrstack_setNumElements( arrstack, numElements ) ) |
148 | return; |
149 | } |
150 | |
151 | arrstack->count = numElements; |
152 | } |
153 | |
154 | |
155 | /* clear the count */ |
156 | FT_LOCAL_DEF( void ) |
157 | cf2_arrstack_clear( CF2_ArrStack arrstack ) |
158 | { |
159 | FT_ASSERT( arrstack ); |
160 | |
161 | arrstack->count = 0; |
162 | } |
163 | |
164 | |
165 | /* current number of items */ |
166 | FT_LOCAL_DEF( size_t ) |
167 | cf2_arrstack_size( const CF2_ArrStack arrstack ) |
168 | { |
169 | FT_ASSERT( arrstack ); |
170 | |
171 | return arrstack->count; |
172 | } |
173 | |
174 | |
175 | FT_LOCAL_DEF( void* ) |
176 | cf2_arrstack_getBuffer( const CF2_ArrStack arrstack ) |
177 | { |
178 | FT_ASSERT( arrstack ); |
179 | |
180 | return arrstack->ptr; |
181 | } |
182 | |
183 | |
184 | /* return pointer to the given element */ |
185 | FT_LOCAL_DEF( void* ) |
186 | cf2_arrstack_getPointer( const CF2_ArrStack arrstack, |
187 | size_t idx ) |
188 | { |
189 | void* newPtr; |
190 | |
191 | |
192 | FT_ASSERT( arrstack ); |
193 | |
194 | if ( idx >= arrstack->count ) |
195 | { |
196 | /* overflow */ |
197 | CF2_SET_ERROR( arrstack->error, Stack_Overflow ); |
198 | idx = 0; /* choose safe default */ |
199 | } |
200 | |
201 | newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem; |
202 | |
203 | return newPtr; |
204 | } |
205 | |
206 | |
207 | /* push (append) an element at the end of the list; */ |
208 | /* return false on memory error */ |
209 | /* TODO: should there be a length param for extra checking? */ |
210 | FT_LOCAL_DEF( void ) |
211 | cf2_arrstack_push( CF2_ArrStack arrstack, |
212 | const void* ptr ) |
213 | { |
214 | FT_ASSERT( arrstack ); |
215 | |
216 | if ( arrstack->count == arrstack->allocated ) |
217 | { |
218 | /* increase the buffer size */ |
219 | if ( !cf2_arrstack_setNumElements( |
220 | arrstack, arrstack->allocated * 2 + 16 ) ) |
221 | { |
222 | /* on error, ignore the push */ |
223 | return; |
224 | } |
225 | } |
226 | |
227 | FT_ASSERT( ptr ); |
228 | |
229 | { |
230 | size_t offset = arrstack->count * arrstack->sizeItem; |
231 | void* newPtr = (FT_Byte*)arrstack->ptr + offset; |
232 | |
233 | |
234 | FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem ); |
235 | arrstack->count += 1; |
236 | } |
237 | } |
238 | |
239 | |
240 | /* END */ |
241 | |