f57ff458d51ad70d00053dc3ec1ffaa794c4fb78
[runtime.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
20 #include "silcruntime.h"
21
22 #ifndef SILC_STACKTRACE
23
24 #define SILC_MAX_ALLOC (1024 * 1024L * 1024L)
25
26 void *silc_malloc(size_t size)
27 {
28   void *addr;
29
30   if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
31     if (size == 0)
32       silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
33     else
34       silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
35                                    "Allocation by %d", size);
36     return NULL;
37   }
38
39   addr = malloc(size);
40   if (silc_unlikely(!addr))
41     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
42
43   return addr;
44 }
45
46 void *silc_calloc(size_t items, size_t size)
47 {
48   void *addr;
49
50   if (silc_unlikely(size * items <= 0 || size * items >= SILC_MAX_ALLOC)) {
51     if (size == 0)
52       silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
53     else
54       silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
55                                    "Allocation by %d", size);
56     return NULL;
57   }
58
59   addr = calloc(items, size);
60   if (silc_unlikely(!addr))
61     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
62
63   return addr;
64 }
65
66 void *silc_realloc(void *ptr, size_t size)
67 {
68   void *addr;
69   if (silc_unlikely(size <= 0 || size >= SILC_MAX_ALLOC)) {
70     if (size == 0)
71       silc_set_errno_nofail(SILC_ERR_ZERO_ALLOCATION);
72     else
73       silc_set_errno_reason_nofail(SILC_ERR_TOO_LARGE_ALLOCATION,
74                                    "Allocation by %d", size);
75     return NULL;
76   }
77
78   addr = realloc(ptr, size);
79   if (silc_unlikely(!addr))
80     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
81
82   return addr;
83 }
84
85 void silc_free(void *ptr)
86 {
87   free(ptr);
88 }
89
90 void *silc_memdup(const void *ptr, size_t size)
91 {
92   unsigned char *addr;
93
94   addr = silc_malloc(size + 1);
95   if (silc_unlikely(!addr)) {
96     silc_set_errno_nofail(SILC_ERR_OUT_OF_MEMORY);
97     return NULL;
98   }
99   memcpy((void *)addr, ptr, size);
100   addr[size] = '\0';
101   return (void *)addr;
102 }
103
104 char *silc_strdup(const char *str)
105 {
106   return silc_memdup(str, strlen(str));
107 }
108
109 #endif /* !SILC_STACKTRACE */
110
111 /* SilcStack aware routines */
112
113 void *silc_smalloc(SilcStack stack, SilcUInt32 size)
114 {
115   return stack ? silc_stack_malloc(stack, size) : silc_malloc(size);
116 }
117
118 void silc_sfree(SilcStack stack, void *ptr)
119 {
120   if (stack) {
121 #ifdef SILC_DEBUG
122     if (ptr)
123       *(unsigned char *)ptr = 'F';
124 #endif /* SILC_DEBUG */
125     return;
126   }
127   silc_free(ptr);
128 }
129
130 void *silc_scalloc(SilcStack stack, SilcUInt32 items, SilcUInt32 size)
131 {
132   unsigned char *addr;
133
134   if (!stack)
135     return silc_calloc(items, size);
136
137   addr = silc_stack_malloc(stack, items * size);
138   if (silc_unlikely(!addr))
139     return NULL;
140   memset(addr, 0, items * size);
141   return (void *)addr;
142 }
143
144 void *silc_srealloc(SilcStack stack, SilcUInt32 old_size,
145                     void *ptr, SilcUInt32 size)
146 {
147   void *new_ptr;
148
149   if (!stack)
150     return silc_realloc(ptr, size);
151
152   new_ptr = silc_stack_realloc(stack, old_size, ptr, size);
153   if (!new_ptr) {
154     new_ptr = silc_smalloc(stack, size);
155     if (!new_ptr)
156       return NULL;
157     memcpy(new_ptr, ptr, old_size > size ? size : old_size);
158   }
159
160   return new_ptr;
161 }
162
163 void *silc_smemdup(SilcStack stack, const void *ptr, SilcUInt32 size)
164 {
165   unsigned char *addr;
166
167   if (!stack)
168     return silc_memdup(ptr, size);
169
170   addr = silc_stack_malloc(stack, size + 1);
171   if (silc_unlikely(!addr))
172     return NULL;
173   memcpy((void *)addr, ptr, size);
174   addr[size] = '\0';
175   return (void *)addr;
176 }
177
178 char *silc_sstrdup(SilcStack stack, const char *str)
179 {
180   SilcInt32 size = strlen(str);
181   char *addr;
182
183   if (!stack)
184     return silc_memdup(str, size);
185
186   addr = silc_stack_malloc(stack, size + 1);
187   if (silc_unlikely(!addr))
188     return NULL;
189   memcpy((void *)addr, str, size);
190   addr[size] = '\0';
191   return addr;
192 }