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 FT_INTERNAL_DEBUG_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->chunk = 10; /* chunks of 10 items */ |
69 | arrstack->count = 0; |
70 | arrstack->totalSize = 0; |
71 | arrstack->ptr = NULL; |
72 | } |
73 | |
74 | |
75 | FT_LOCAL_DEF( void ) |
76 | cf2_arrstack_finalize( CF2_ArrStack arrstack ) |
77 | { |
78 | FT_Memory memory = arrstack->memory; /* for FT_FREE */ |
79 | |
80 | |
81 | FT_ASSERT( arrstack ); |
82 | |
83 | arrstack->allocated = 0; |
84 | arrstack->count = 0; |
85 | arrstack->totalSize = 0; |
86 | |
87 | /* free the data buffer */ |
88 | FT_FREE( arrstack->ptr ); |
89 | } |
90 | |
91 | |
92 | /* allocate or reallocate the buffer size; */ |
93 | /* return false on memory error */ |
94 | static FT_Bool |
95 | cf2_arrstack_setNumElements( CF2_ArrStack arrstack, |
96 | size_t numElements ) |
97 | { |
98 | FT_ASSERT( arrstack ); |
99 | |
100 | { |
101 | FT_Error error = FT_Err_Ok; /* for FT_REALLOC */ |
102 | FT_Memory memory = arrstack->memory; /* for FT_REALLOC */ |
103 | |
104 | size_t newSize = numElements * arrstack->sizeItem; |
105 | |
106 | |
107 | if ( numElements > FT_LONG_MAX / arrstack->sizeItem ) |
108 | goto exit; |
109 | |
110 | |
111 | FT_ASSERT( newSize > 0 ); /* avoid realloc with zero size */ |
112 | |
113 | if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) ) |
114 | { |
115 | arrstack->allocated = numElements; |
116 | arrstack->totalSize = newSize; |
117 | |
118 | if ( arrstack->count > numElements ) |
119 | { |
120 | /* we truncated the list! */ |
121 | CF2_SET_ERROR( arrstack->error, Stack_Overflow ); |
122 | arrstack->count = numElements; |
123 | return FALSE; |
124 | } |
125 | |
126 | return TRUE; /* success */ |
127 | } |
128 | } |
129 | |
130 | exit: |
131 | /* if there's not already an error, store this one */ |
132 | CF2_SET_ERROR( arrstack->error, Out_Of_Memory ); |
133 | |
134 | return FALSE; |
135 | } |
136 | |
137 | |
138 | /* set the count, ensuring allocation is sufficient */ |
139 | FT_LOCAL_DEF( void ) |
140 | cf2_arrstack_setCount( CF2_ArrStack arrstack, |
141 | size_t numElements ) |
142 | { |
143 | FT_ASSERT( arrstack ); |
144 | |
145 | if ( numElements > arrstack->allocated ) |
146 | { |
147 | /* expand the allocation first */ |
148 | if ( !cf2_arrstack_setNumElements( arrstack, numElements ) ) |
149 | return; |
150 | } |
151 | |
152 | arrstack->count = numElements; |
153 | } |
154 | |
155 | |
156 | /* clear the count */ |
157 | FT_LOCAL_DEF( void ) |
158 | cf2_arrstack_clear( CF2_ArrStack arrstack ) |
159 | { |
160 | FT_ASSERT( arrstack ); |
161 | |
162 | arrstack->count = 0; |
163 | } |
164 | |
165 | |
166 | /* current number of items */ |
167 | FT_LOCAL_DEF( size_t ) |
168 | cf2_arrstack_size( const CF2_ArrStack arrstack ) |
169 | { |
170 | FT_ASSERT( arrstack ); |
171 | |
172 | return arrstack->count; |
173 | } |
174 | |
175 | |
176 | FT_LOCAL_DEF( void* ) |
177 | cf2_arrstack_getBuffer( const CF2_ArrStack arrstack ) |
178 | { |
179 | FT_ASSERT( arrstack ); |
180 | |
181 | return arrstack->ptr; |
182 | } |
183 | |
184 | |
185 | /* return pointer to the given element */ |
186 | FT_LOCAL_DEF( void* ) |
187 | cf2_arrstack_getPointer( const CF2_ArrStack arrstack, |
188 | size_t idx ) |
189 | { |
190 | void* newPtr; |
191 | |
192 | |
193 | FT_ASSERT( arrstack ); |
194 | |
195 | if ( idx >= arrstack->count ) |
196 | { |
197 | /* overflow */ |
198 | CF2_SET_ERROR( arrstack->error, Stack_Overflow ); |
199 | idx = 0; /* choose safe default */ |
200 | } |
201 | |
202 | newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem; |
203 | |
204 | return newPtr; |
205 | } |
206 | |
207 | |
208 | /* push (append) an element at the end of the list; */ |
209 | /* return false on memory error */ |
210 | /* TODO: should there be a length param for extra checking? */ |
211 | FT_LOCAL_DEF( void ) |
212 | cf2_arrstack_push( CF2_ArrStack arrstack, |
213 | const void* ptr ) |
214 | { |
215 | FT_ASSERT( arrstack ); |
216 | |
217 | if ( arrstack->count == arrstack->allocated ) |
218 | { |
219 | /* grow the buffer by one chunk */ |
220 | if ( !cf2_arrstack_setNumElements( |
221 | arrstack, arrstack->allocated + arrstack->chunk ) ) |
222 | { |
223 | /* on error, ignore the push */ |
224 | return; |
225 | } |
226 | } |
227 | |
228 | FT_ASSERT( ptr ); |
229 | |
230 | { |
231 | size_t offset = arrstack->count * arrstack->sizeItem; |
232 | void* newPtr = (FT_Byte*)arrstack->ptr + offset; |
233 | |
234 | |
235 | FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem ); |
236 | arrstack->count += 1; |
237 | } |
238 | } |
239 | |
240 | |
241 | /* END */ |
242 | |