summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/cff/cf2arrst.c
blob: 89f3e9f1d741964fc0711e22746cd11799781fe5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/***************************************************************************/
/*                                                                         */
/*  cf2arrst.c                                                             */
/*                                                                         */
/*    Adobe's code for Array Stacks (body).                                */
/*                                                                         */
/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
/*                                                                         */
/*  This software, and all works of authorship, whether in source or       */
/*  object code form as indicated by the copyright notice(s) included      */
/*  herein (collectively, the "Work") is made available, and may only be   */
/*  used, modified, and distributed under the FreeType Project License,    */
/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
/*  FreeType Project License, each contributor to the Work hereby grants   */
/*  to any individual or legal entity exercising permissions granted by    */
/*  the FreeType Project License and this section (hereafter, "You" or     */
/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
/*  royalty-free, irrevocable (except as stated in this section) patent    */
/*  license to make, have made, use, offer to sell, sell, import, and      */
/*  otherwise transfer the Work, where such license applies only to those  */
/*  patent claims licensable by such contributor that are necessarily      */
/*  infringed by their contribution(s) alone or by combination of their    */
/*  contribution(s) with the Work to which such contribution(s) was        */
/*  submitted.  If You institute patent litigation against any entity      */
/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
/*  the Work or a contribution incorporated within the Work constitutes    */
/*  direct or contributory patent infringement, then any patent licenses   */
/*  granted to You under this License for that Work shall terminate as of  */
/*  the date such litigation is filed.                                     */
/*                                                                         */
/*  By using, modifying, or distributing the Work you indicate that you    */
/*  have read and understood the terms and conditions of the               */
/*  FreeType Project License as well as those provided in this section,    */
/*  and you accept them fully.                                             */
/*                                                                         */
/***************************************************************************/


#include "cf2ft.h"
#include FT_INTERNAL_DEBUG_H

#include "cf2glue.h"
#include "cf2arrst.h"

#include "cf2error.h"


  /*
   * CF2_ArrStack uses an error pointer, to enable shared errors.
   * Shared errors are necessary when multiple objects allow the program
   * to continue after detecting errors.  Only the first error should be
   * recorded.
   */

  FT_LOCAL_DEF( void )
  cf2_arrstack_init( CF2_ArrStack  arrstack,
                     FT_Memory     memory,
                     FT_Error*     error,
                     size_t        sizeItem )
  {
    FT_ASSERT( arrstack != NULL );

    /* initialize the structure */
    arrstack->memory    = memory;
    arrstack->error     = error;
    arrstack->sizeItem  = sizeItem;
    arrstack->allocated = 0;
    arrstack->chunk     = 10;    /* chunks of 10 items */
    arrstack->count     = 0;
    arrstack->totalSize = 0;
    arrstack->ptr       = NULL;
  }


  FT_LOCAL_DEF( void )
  cf2_arrstack_finalize( CF2_ArrStack  arrstack )
  {
    FT_Memory  memory = arrstack->memory;     /* for FT_FREE */


    FT_ASSERT( arrstack != NULL );

    arrstack->allocated = 0;
    arrstack->count     = 0;
    arrstack->totalSize = 0;

    /* free the data buffer */
    FT_FREE( arrstack->ptr );
  }


  /* allocate or reallocate the buffer size; */
  /* return false on memory error */
  static FT_Bool
  cf2_arrstack_setNumElements( CF2_ArrStack  arrstack,
                               size_t        numElements )
  {
    FT_ASSERT( arrstack != NULL );

    {
      FT_Error   error  = FT_Err_Ok;        /* for FT_REALLOC */
      FT_Memory  memory = arrstack->memory; /* for FT_REALLOC */

      size_t  newSize = numElements * arrstack->sizeItem;


      if ( numElements > FT_LONG_MAX / arrstack->sizeItem )
        goto exit;


      FT_ASSERT( newSize > 0 );   /* avoid realloc with zero size */

      if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
      {
        arrstack->allocated = numElements;
        arrstack->totalSize = newSize;

        if ( arrstack->count > numElements )
        {
          /* we truncated the list! */
          CF2_SET_ERROR( arrstack->error, Stack_Overflow );
          arrstack->count = numElements;
          return FALSE;
        }

        return TRUE;     /* success */
      }
    }

  exit:
    /* if there's not already an error, store this one */
    CF2_SET_ERROR( arrstack->error, Out_Of_Memory );

    return FALSE;
  }


  /* set the count, ensuring allocation is sufficient */
  FT_LOCAL_DEF( void )
  cf2_arrstack_setCount( CF2_ArrStack  arrstack,
                         size_t        numElements )
  {
    FT_ASSERT( arrstack != NULL );

    if ( numElements > arrstack->allocated )
    {
      /* expand the allocation first */
      if ( !cf2_arrstack_setNumElements( arrstack, numElements ) )
        return;
    }

    arrstack->count = numElements;
  }


  /* clear the count */
  FT_LOCAL_DEF( void )
  cf2_arrstack_clear( CF2_ArrStack  arrstack )
  {
    FT_ASSERT( arrstack != NULL );

    arrstack->count = 0;
  }


  /* current number of items */
  FT_LOCAL_DEF( size_t )
  cf2_arrstack_size( const CF2_ArrStack  arrstack )
  {
    FT_ASSERT( arrstack != NULL );

    return arrstack->count;
  }


  FT_LOCAL_DEF( void* )
  cf2_arrstack_getBuffer( const CF2_ArrStack  arrstack )
  {
    FT_ASSERT( arrstack != NULL );

    return arrstack->ptr;
  }


  /* return pointer to the given element */
  FT_LOCAL_DEF( void* )
  cf2_arrstack_getPointer( const CF2_ArrStack  arrstack,
                           size_t              idx )
  {
    void*  newPtr;


    FT_ASSERT( arrstack != NULL );

    if ( idx >= arrstack->count )
    {
      /* overflow */
      CF2_SET_ERROR( arrstack->error, Stack_Overflow );
      idx = 0;    /* choose safe default */
    }

    newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem;

    return newPtr;
  }


  /* push (append) an element at the end of the list;         */
  /* return false on memory error                             */
  /* TODO: should there be a length param for extra checking? */
  FT_LOCAL_DEF( void )
  cf2_arrstack_push( CF2_ArrStack  arrstack,
                     const void*   ptr )
  {
    FT_ASSERT( arrstack != NULL );

    if ( arrstack->count == arrstack->allocated )
    {
      /* grow the buffer by one chunk */
      if ( !cf2_arrstack_setNumElements(
             arrstack, arrstack->allocated + arrstack->chunk ) )
      {
        /* on error, ignore the push */
        return;
      }
    }

    FT_ASSERT( ptr != NULL );

    {
      size_t  offset = arrstack->count * arrstack->sizeItem;
      void*   newPtr = (FT_Byte*)arrstack->ptr + offset;


      FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem );
      arrstack->count += 1;
    }
  }


/* END */