Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(11374)

Side by Side Diff: Modules/_decimal/libmpdec/memory.c

Issue 7652: Merge C version of decimal into py3k.
Patch Set: Created 7 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Modules/_decimal/libmpdec/literature/umodarith.lisp ('k') | Modules/_decimal/libmpdec/memory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2008-2010 Stefan Krah. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28
29 #include "mpdecimal.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include "typearith.h"
33 #include "memory.h"
34
35
36 /* Guaranteed minimum allocation for a coefficient. May be changed once
37 at program start using mpd_setminalloc(). */
38 mpd_ssize_t MPD_MINALLOC = MPD_MINALLOC_MIN;
39
40 /* Custom allocation and free functions */
41 void *(* mpd_mallocfunc)(size_t size) = malloc;
42 void *(* mpd_reallocfunc)(void *ptr, size_t size) = realloc;
43 void *(* mpd_callocfunc)(size_t nmemb, size_t size) = calloc;
44 void (* mpd_free)(void *ptr) = free;
45
46
47 /* emulate calloc if it is not available */
48 void *
49 mpd_callocfunc_em(size_t nmemb, size_t size)
50 {
51 void *ptr;
52 size_t req;
53 mpd_size_t overflow;
54
55 #if MPD_SIZE_MAX < SIZE_MAX
56 /* full_coverage test only */
57 if (nmemb > MPD_SIZE_MAX || size > MPD_SIZE_MAX) {
58 return NULL;
59 }
60 #endif
61
62 req = mul_size_t_overflow((mpd_size_t)nmemb, (mpd_size_t)size,
63 &overflow);
64 if (overflow) {
65 return NULL;
66 }
67
68 ptr = mpd_mallocfunc(req);
69 if (ptr == NULL) {
70 return NULL;
71 }
72 /* used on uint32_t or uint64_t */
73 memset(ptr, 0, req);
74
75 return ptr;
76 }
77
78
79 /* malloc with overflow checking */
80 void *
81 mpd_alloc(mpd_size_t nmemb, mpd_size_t size)
82 {
83 mpd_size_t req, overflow;
84
85 req = mul_size_t_overflow(nmemb, size, &overflow);
86 if (overflow) {
87 return NULL;
88 }
89
90 return mpd_mallocfunc(req);
91 }
92
93 /* calloc with overflow checking */
94 void *
95 mpd_calloc(mpd_size_t nmemb, mpd_size_t size)
96 {
97 mpd_size_t overflow;
98
99 (void)mul_size_t_overflow(nmemb, size, &overflow);
100 if (overflow) {
101 return NULL;
102 }
103
104 return mpd_callocfunc(nmemb, size);
105 }
106
107 /* realloc with overflow checking */
108 void *
109 mpd_realloc(void *ptr, mpd_size_t nmemb, mpd_size_t size, uint8_t *err)
110 {
111 void *new;
112 mpd_size_t req, overflow;
113
114 req = mul_size_t_overflow(nmemb, size, &overflow);
115 if (overflow) {
116 *err = 1;
117 return ptr;
118 }
119
120 new = mpd_reallocfunc(ptr, req);
121 if (new == NULL) {
122 *err = 1;
123 return ptr;
124 }
125
126 return new;
127 }
128
129 /* struct hack malloc with overflow checking */
130 void *
131 mpd_sh_alloc(mpd_size_t struct_size, mpd_size_t nmemb, mpd_size_t size)
132 {
133 mpd_size_t req, overflow;
134
135 req = mul_size_t_overflow(nmemb, size, &overflow);
136 if (overflow) {
137 return NULL;
138 }
139
140 req = add_size_t_overflow(req, struct_size, &overflow);
141 if (overflow) {
142 return NULL;
143 }
144
145 return mpd_mallocfunc(req);
146 }
147
148
149 /* Allocate a new decimal with a coefficient of length 'nwords'. In case
150 of an error the return value is NULL. */
151 mpd_t *
152 mpd_qnew_size(mpd_ssize_t nwords)
153 {
154 mpd_t *result;
155
156 nwords = (nwords < MPD_MINALLOC) ? MPD_MINALLOC : nwords;
157
158 result = mpd_alloc(1, sizeof *result);
159 if (result == NULL) {
160 return NULL;
161 }
162
163 result->data = mpd_alloc(nwords, sizeof *result->data);
164 if (result->data == NULL) {
165 mpd_free(result);
166 return NULL;
167 }
168
169 result->flags = 0;
170 result->exp = 0;
171 result->digits = 0;
172 result->len = 0;
173 result->alloc = nwords;
174
175 return result;
176 }
177
178 /* Allocate a new decimal with a coefficient of length MPD_MINALLOC.
179 In case of an error the return value is NULL. */
180 mpd_t *
181 mpd_qnew(void)
182 {
183 return mpd_qnew_size(MPD_MINALLOC);
184 }
185
186 /* Allocate new decimal. Caller can check for NULL or MPD_Malloc_error.
187 Raises on error. */
188 mpd_t *
189 mpd_new(mpd_context_t *ctx)
190 {
191 mpd_t *result;
192
193 result = mpd_qnew();
194 if (result == NULL) {
195 mpd_addstatus_raise(ctx, MPD_Malloc_error);
196 }
197 return result;
198 }
199
200 /* Convert a static coefficient to a larger dynamic one with length 'nwords'.
201 Existing data is copied. */
202 int
203 mpd_switch_to_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
204 {
205 mpd_uint_t *p = result->data;
206
207 assert(nwords >= result->alloc);
208
209 result->data = mpd_alloc(nwords, sizeof *result->data);
210 if (result->data == NULL) {
211 result->data = p;
212 mpd_set_qnan(result);
213 mpd_set_positive(result);
214 result->exp = result->digits = result->len = 0;
215 *status |= MPD_Malloc_error;
216 return 0;
217 }
218
219 memcpy(result->data, p, result->len * (sizeof *result->data));
220 result->alloc = nwords;
221 mpd_set_dynamic_data(result);
222 return 1;
223 }
224
225 /* Convert a static coefficient to a dynamic one with length 'nwords'.
226 Existing data is zeroed. */
227 int
228 mpd_switch_to_dyn_zero(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
229 {
230 mpd_uint_t *p = result->data;
231
232 result->data = mpd_calloc(nwords, sizeof *result->data);
233 if (result->data == NULL) {
234 result->data = p;
235 mpd_set_qnan(result);
236 mpd_set_positive(result);
237 result->exp = result->digits = result->len = 0;
238 *status |= MPD_Malloc_error;
239 return 0;
240 }
241
242 result->alloc = nwords;
243 mpd_set_dynamic_data(result);
244
245 return 1;
246 }
247
248 /* Resize a dynamic coefficient to length 'nwords'. If resize to smaller
249 fails, the previous memory area is reused without returning an error. */
250 int
251 mpd_realloc_dyn(mpd_t *result, mpd_ssize_t nwords, uint32_t *status)
252 {
253 uint8_t err = 0;
254
255 result->data = mpd_realloc(result->data, nwords, sizeof *result->data, & err);
256 if (!err) {
257 result->alloc = nwords;
258 }
259 else if (nwords > result->alloc) {
260 mpd_set_qnan(result);
261 mpd_set_positive(result);
262 result->exp = result->digits = result->len = 0;
263 *status |= MPD_Malloc_error;
264 return 0;
265 }
266
267 return 1;
268 }
269
270
OLDNEW
« no previous file with comments | « Modules/_decimal/libmpdec/literature/umodarith.lisp ('k') | Modules/_decimal/libmpdec/memory.h » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+