silc_srealloc now allocates new block if reallocation fails.
[crypto.git] / lib / silcutil / silcmemory.c
1 /*
2
3   silcmemory.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1999 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22
23 #ifndef SILC_STACKTRACE
24
25 #define SILC_MAX_ALLOC (1024 * 1024L * 1024L)
26
27 void *silc_malloc(size_t size)
28 {
29   void *addr;
30
31   if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
32     if (size == 0)
33       silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
34     else
35       silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
36                                    "Allocation by %d", size);
37     return NULL;
38   }
39
40   addr = malloc(size);
41   if (silc_unlikely(!addr))
42     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
43
44   return addr;
45 }
46
47 void *silc_calloc(size_t items, size_t size)
48 {
49   void *addr;
50
51   if (silc_unlikely(size * items <= 0 || size * items >= SILC_MAX_ALLOC)) {
52     if (size == 0)
53       silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
54     else
55       silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
56                                    "Allocation by %d", size);
57     return NULL;
58   }
59
60   addr = calloc(items, size);
61   if (silc_unlikely(!addr))
62     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
63
64   return addr;
65 }
66
67 void *silc_realloc(void *ptr, size_t size)
68 {
69   void *addr;
70   if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
71     if (size == 0)
72       silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
73     else
74       silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
75                                    "Allocation by %d", size);
76     return NULL;
77   }
78
79   addr = realloc(ptr, size);
80   if (silc_unlikely(!addr))
81     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
82
83   return addr;
84 }
85
86 void silc_free(void *ptr)
87 {
88   free(ptr);
89 }
90
91 void *silc_memdup(const void *ptr, size_t size)
92 {
93   unsigned char *addr;
94
95   addr = silc_malloc(size + 1);
96   if (silc_unlikely(!addr)) {
97     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
98     return NULL;
99   }
100   memcpy((void *)addr, ptr, size);
101   addr[size] = '\0';
102   return (void *)addr;
103 }
104
105 char *silc_strdup(const char *str)
106 {
107   return silc_memdup(str, strlen(str));
108 }
109
110 #endif /* !SILC_STACKTRACE */
111
112 /* SilcStack aware routines */
113
114 void *silc_smalloc(SilcStack stack, SilcUInt32 size)
115 {
116   return stack ? silc_stack_malloc(stack, size) : silc_malloc(size);
117 }
118
119 void silc_sfree(SilcStack stack, void *ptr)
120 {
121   if (stack) {
122 #ifdef SILC_DEBUG
123     if (ptr)
124       *(unsigned char *)ptr = 'F';
125 #endif /* SILC_DEBUG */
126     return;
127   }
128   silc_free(ptr);
129 }
130
131 void *silc_scalloc(SilcStack stack, SilcUInt32 items, SilcUInt32 size)
132 {
133   unsigned char *addr;
134
135   if (!stack)
136     return silc_calloc(items, size);
137
138   addr = silc_stack_malloc(stack, items * size);
139   if (silc_unlikely(!addr))
140     return NULL;
141   memset(addr, 0, items * size);
142   return (void *)addr;
143 }
144
145 void *silc_srealloc(SilcStack stack, SilcUInt32 old_size,
146                     void *ptr, SilcUInt32 size)
147 {
148   void *new_ptr;
149
150   if (!stack)
151     return silc_realloc(ptr, size);
152
153   new_ptr = silc_stack_realloc(stack, old_size, ptr, size);
154   if (!new_ptr) {
155     new_ptr = silc_smalloc(stack, size);
156     if (!new_ptr)
157       return NULL;
158     memcpy(new_ptr, ptr, old_size);
159   }
160
161   return new_ptr;
162 }
163
164 void *silc_smemdup(SilcStack stack, const void *ptr, SilcUInt32 size)
165 {
166   unsigned char *addr;
167
168   if (!stack)
169     return silc_memdup(ptr, size);
170
171   addr = silc_stack_malloc(stack, size + 1);
172   if (silc_unlikely(!addr))
173     return NULL;
174   memcpy((void *)addr, ptr, size);
175   addr[size] = '\0';
176   return (void *)addr;
177 }
178
179 char *silc_sstrdup(SilcStack stack, const char *str)
180 {
181   SilcInt32 size = strlen(str);
182   char *addr;
183
184   if (!stack)
185     return silc_memdup(str, size);
186
187   addr = silc_stack_malloc(stack, size + 1);
188   if (silc_unlikely(!addr))
189     return NULL;
190   memcpy((void *)addr, str, size);
191   addr[size] = '\0';
192   return addr;
193 }