/src/cairo/util/cairo-script/cairo-script-stack.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk> |
3 | | * |
4 | | * This library is free software; you can redistribute it and/or |
5 | | * modify it either under the terms of the GNU Lesser General Public |
6 | | * License version 2.1 as published by the Free Software Foundation |
7 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
8 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
9 | | * notice, a recipient may use your version of this file under either |
10 | | * the MPL or the LGPL. |
11 | | * |
12 | | * You should have received a copy of the LGPL along with this library |
13 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
15 | | * You should have received a copy of the MPL along with this library |
16 | | * in the file COPYING-MPL-1.1 |
17 | | * |
18 | | * The contents of this file are subject to the Mozilla Public License |
19 | | * Version 1.1 (the "License"); you may not use this file except in |
20 | | * compliance with the License. You may obtain a copy of the License at |
21 | | * http://www.mozilla.org/MPL/ |
22 | | * |
23 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
24 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
25 | | * the specific language governing rights and limitations. |
26 | | * |
27 | | * The Original Code is the cairo graphics library. |
28 | | * |
29 | | * The Initial Developer of the Original Code is Chris Wilson. |
30 | | * |
31 | | * Contributor(s): |
32 | | * Chris Wilson <chris@chris-wilson.co.uk> |
33 | | */ |
34 | | |
35 | | #include "config.h" |
36 | | |
37 | | #include "cairo-script-private.h" |
38 | | |
39 | | #include <limits.h> /* INT_MAX */ |
40 | | #include <string.h> |
41 | | |
42 | | csi_status_t |
43 | | _csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size) |
44 | 996k | { |
45 | 996k | csi_status_t status = CSI_STATUS_SUCCESS; |
46 | | |
47 | 996k | stack->len = 0; |
48 | 996k | stack->size = size; |
49 | | /* assert ((unsigned) size < INT_MAX / sizeof (csi_object_t)); */ |
50 | 996k | stack->objects = _csi_alloc (ctx, size * sizeof (csi_object_t)); |
51 | 996k | if (_csi_unlikely (stack->objects == NULL)) |
52 | 0 | status = _csi_error (CSI_STATUS_NO_MEMORY); |
53 | | |
54 | 996k | return status; |
55 | 996k | } |
56 | | |
57 | | void |
58 | | _csi_stack_fini (csi_t *ctx, csi_stack_t *stack) |
59 | 946k | { |
60 | 946k | csi_integer_t n; |
61 | | |
62 | 2.34M | for (n = 0; n < stack->len; n++) |
63 | 1.39M | csi_object_free (ctx, &stack->objects[n]); |
64 | | |
65 | 946k | _csi_free (ctx, stack->objects); |
66 | 946k | } |
67 | | |
68 | | csi_status_t |
69 | | _csi_stack_roll (csi_t *ctx, |
70 | | csi_stack_t *stack, |
71 | | csi_integer_t mod, csi_integer_t n) |
72 | 12 | { |
73 | 12 | csi_object_t stack_copy[128]; |
74 | 12 | csi_object_t *copy; |
75 | 12 | csi_integer_t last, i, len; |
76 | | |
77 | 12 | switch (mod) { /* special cases */ |
78 | 0 | case 1: |
79 | 0 | last = stack->len - 1; |
80 | 0 | stack_copy[0] = stack->objects[last]; |
81 | 0 | for (i = last; --n; i--) |
82 | 0 | stack->objects[i] = stack->objects[i-1]; |
83 | 0 | stack->objects[i] = stack_copy[0]; |
84 | 0 | return CSI_STATUS_SUCCESS; |
85 | 0 | case -1: |
86 | 0 | last = stack->len - 1; |
87 | 0 | stack_copy[0] = stack->objects[i = last - n + 1]; |
88 | 0 | for (; --n; i++) |
89 | 0 | stack->objects[i] = stack->objects[i+1]; |
90 | 0 | stack->objects[i] = stack_copy[0]; |
91 | 0 | return CSI_STATUS_SUCCESS; |
92 | 12 | } |
93 | | |
94 | | /* fall back to a copy */ |
95 | 12 | if (n > ARRAY_LENGTH (stack_copy)) { |
96 | 0 | if (_csi_unlikely ((unsigned) n > INT_MAX / sizeof (csi_object_t))) |
97 | 0 | return _csi_error (CSI_STATUS_NO_MEMORY); |
98 | 0 | copy = _csi_alloc (ctx, n * sizeof (csi_object_t)); |
99 | 0 | if (copy == NULL) |
100 | 0 | return _csi_error (CSI_STATUS_NO_MEMORY); |
101 | 0 | } else |
102 | 12 | copy = stack_copy; |
103 | | |
104 | 12 | i = stack->len - n; |
105 | 12 | memcpy (copy, stack->objects + i, n * sizeof (csi_object_t)); |
106 | 12 | mod = -mod; |
107 | 12 | if (mod < 0) |
108 | 1 | mod += n; |
109 | 12 | last = mod; |
110 | 13 | for (len = n; n--; i++) { |
111 | 1 | stack->objects[i] = copy[last]; |
112 | 1 | if (++last == len) |
113 | 1 | last = 0; |
114 | 1 | } |
115 | | |
116 | 12 | if (copy != stack_copy) |
117 | 0 | _csi_free (ctx, copy); |
118 | | |
119 | 12 | return CSI_STATUS_SUCCESS; |
120 | 12 | } |
121 | | |
122 | | csi_status_t |
123 | | _csi_stack_grow (csi_t *ctx, csi_stack_t *stack, csi_integer_t cnt) |
124 | 2.44k | { |
125 | 2.44k | csi_integer_t newsize; |
126 | 2.44k | csi_object_t *newstack; |
127 | | |
128 | 2.44k | if (_csi_likely (cnt <= stack->size)) |
129 | 0 | return CSI_STATUS_SUCCESS; |
130 | 2.44k | if (_csi_unlikely ((unsigned) cnt >= INT_MAX / sizeof (csi_object_t))) |
131 | 0 | return _csi_error (CSI_STATUS_NO_MEMORY); |
132 | | |
133 | 2.44k | newsize = stack->size; |
134 | 2.44k | do { |
135 | 2.44k | newsize *= 2; |
136 | 2.44k | } while (newsize <= cnt); |
137 | | |
138 | 2.44k | newstack = _csi_realloc (ctx, |
139 | 2.44k | stack->objects, |
140 | 2.44k | newsize * sizeof (csi_object_t)); |
141 | 2.44k | if (_csi_unlikely (newstack == NULL)) |
142 | 0 | return _csi_error (CSI_STATUS_NO_MEMORY); |
143 | | |
144 | 2.44k | stack->objects = newstack; |
145 | 2.44k | stack->size = newsize; |
146 | | |
147 | 2.44k | return CSI_STATUS_SUCCESS; |
148 | 2.44k | } |
149 | | |
150 | | csi_status_t |
151 | | _csi_stack_push_internal (csi_t *ctx, csi_stack_t *stack, |
152 | | const csi_object_t *obj) |
153 | 2.44k | { |
154 | 2.44k | csi_status_t status; |
155 | | |
156 | 2.44k | status = _csi_stack_grow (ctx, stack, stack->size + 1); |
157 | 2.44k | if (_csi_unlikely (status)) |
158 | 0 | return status; |
159 | | |
160 | 2.44k | stack->objects[stack->len++] = *obj; |
161 | 2.44k | return CSI_STATUS_SUCCESS; |
162 | 2.44k | } |
163 | | |
164 | | csi_object_t * |
165 | | _csi_stack_peek (csi_stack_t *stack, csi_integer_t i) |
166 | 49.2k | { |
167 | 49.2k | if (_csi_unlikely (stack->len < i)) |
168 | 0 | return NULL; |
169 | | |
170 | 49.2k | return &stack->objects[stack->len - i -1]; |
171 | 49.2k | } |
172 | | |
173 | | void |
174 | | _csi_stack_pop (csi_t *ctx, csi_stack_t *stack, csi_integer_t count) |
175 | 0 | { |
176 | 0 | if (_csi_unlikely (stack->len < count)) |
177 | 0 | count = stack->len; |
178 | |
|
179 | 0 | while (count--) |
180 | 0 | csi_object_free (ctx, &stack->objects[--stack->len]); |
181 | 0 | } |
182 | | |
183 | | csi_status_t |
184 | | _csi_stack_exch (csi_stack_t *stack) |
185 | 551 | { |
186 | 551 | csi_object_t tmp; |
187 | 551 | csi_integer_t n; |
188 | | |
189 | 551 | if (_csi_unlikely (stack->len < 2)) |
190 | 2 | return _csi_error (CSI_STATUS_INVALID_SCRIPT); |
191 | | |
192 | 549 | n = stack->len - 1; |
193 | 549 | tmp = stack->objects[n]; |
194 | 549 | stack->objects[n] = stack->objects[n - 1]; |
195 | 549 | stack->objects[n - 1] = tmp; |
196 | | |
197 | 549 | return CSI_STATUS_SUCCESS; |
198 | 551 | } |