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 ) cf2_arrstack_init(CF2_ArrStack arrstack,FT_Memory memory,FT_Error * error,size_t sizeItem)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 ) cf2_arrstack_finalize(CF2_ArrStack arrstack)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 cf2_arrstack_setNumElements(CF2_ArrStack arrstack,size_t numElements)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 ) cf2_arrstack_setCount(CF2_ArrStack arrstack,size_t numElements)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 ) cf2_arrstack_clear(CF2_ArrStack arrstack)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 ) cf2_arrstack_size(const CF2_ArrStack arrstack)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* ) cf2_arrstack_getBuffer(const CF2_ArrStack arrstack)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* ) cf2_arrstack_getPointer(const CF2_ArrStack arrstack,size_t idx)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 ) cf2_arrstack_push(CF2_ArrStack arrstack,const void * ptr)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