3 * https://github.com/carmesim/libstring
5 * Copyright (c) 2020 VinÃcius R. Miguel, Ivan dos Santos Muniz
6 * <vinicius.miguel at unifesp.br>
7 * <ivan.muniz at unifesp.br>
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #include "libstring.h"
31 void * __malloc(size_t size
)
33 void * ptr
= malloc(size
);
36 fprintf(stderr
, "Fatal error: malloc failed.\n");
43 * Portable and simple reimplementation of strlen
44 * Does not totally conform to the C ISO standard, but is good enough for our uses.
46 size_t __strlen(const char *s
) {
48 for (i
= 0; s
[i
] != '\0'; i
++) ;
52 char * __memcpy(char * dest
, const char *src
, size_t n
) {
60 void __strcpy(char *dest
, const char *src
, size_t size
)
64 fprintf(stderr
, "__strcpy should not be called with size==0\n");
68 size_t source_len
= __strlen(src
);
71 if (size
-1 < source_len
) // Truncate to the size of the smaller string
79 __memcpy(dest
, src
, n
); // Copy the contents of src to dest
80 dest
[n
] = '\0'; // Null-terminate dest.
84 * \struct alloc_node A single node of the allocation linked list.
85 * \param nbytes The number of bytes to be allocated.
86 * \property val A pointer to struct cstr.
87 * \property next A pointer to the next node in the allocation list.
92 struct alloc_node
* next
;
95 /* We'll keep a simple linked list of heap allocations as to allow for string_free_all() */
96 struct alloc_node
* alloc_list_head
= NULL
;
99 * \brief Allocates memory for a cstr_t * and adds it to the allocation list.
100 * \param nbytes The number of bytes to be allocated.
102 cstr_t
* string_alloc (size_t nbytes
)
104 if (!alloc_list_head
) // If the list's head hasn't been initialized
106 alloc_list_head
= __malloc(sizeof(struct alloc_node
));
107 alloc_list_head
->val
= __malloc(sizeof(struct cstr
));
108 alloc_list_head
->val
->value
= __malloc(nbytes
* sizeof(char));
109 alloc_list_head
->val
->size
= nbytes
;
110 alloc_list_head
->val
->reserved
= nbytes
;
111 alloc_list_head
->next
= NULL
;
112 return alloc_list_head
->val
;
115 struct alloc_node
* current
= alloc_list_head
;
116 while (current
->next
)
117 current
= current
->next
;
119 current
->next
= __malloc(sizeof(struct alloc_node
));
120 current
->next
->val
= __malloc(sizeof(struct cstr
));
121 current
->next
->val
->value
= __malloc(nbytes
);
122 current
->next
->val
->size
= nbytes
;
123 current
->next
->val
->reserved
= nbytes
;
124 current
->next
->next
= NULL
;
125 return current
->next
->val
;
129 * \brief Frees all heap memory allocated by libstring.
131 void string_free_all (void)
133 struct alloc_node
* current
= alloc_list_head
;
136 struct alloc_node
* temp
= current
;
137 current
= current
->next
;
138 free(temp
->val
->value
);
145 * \brief Alters a string to contain only lower-case characters.
146 * \param origin The string whose value will be converted to lower-case characters. This parameters does not get modified.
147 * \retval lower A brand new cstr_t * that contains the altered value.
148 * Makes use of bit manipulation to alter the ASCII values.
150 cstr_t
* string_to_lower_case(cstr_t
* origin
)
153 lower
= string_init(origin
->value
);
154 __strcpy(lower
->value
, origin
->value
, origin
->size
);
157 for(i
=0; i
<lower
->size
; i
++)
159 if ((lower
->value
[i
] >= 'A') && (lower
->value
[i
] <= 'Z'))
161 lower
->value
[i
] |= ' ';
168 * \brief Alters a string to contain only lower-case characters.
169 * \param origin The string whose value will be converted to upper-case characters. This parameters does not get modified.
170 * \retval upper A brand new cstr_t * that contains the altered value.
171 * Makes use of bit manipulation to alter the ASCII values.
173 cstr_t
* string_to_upper_case(cstr_t
* origin
)
176 upper
= string_init(origin
->value
);
177 __strcpy(upper
->value
, origin
->value
, origin
->size
);
180 for(i
=0; i
<upper
->size
; i
++)
182 if ((upper
->value
[i
] >= 'a') && (upper
->value
[i
] <= 'z'))
184 upper
->value
[i
] &= '_';
191 * \brief Initializes a new string, a poitner to cstr_t
192 * \param origin The char array to be the value of the new string.
193 * \retval upper A brand new cstr_t *.
194 * Adds to the allocation list.
196 cstr_t
* string_init(const char * origin
)
198 cstr_t
* new = string_alloc(__strlen(origin
)+1);
199 __strcpy(new->value
, origin
, __strlen(origin
));
204 * \brief Initializes a new string, a poitner to cstr_t
205 * \param str The cstr_t * whose capacity will be altered.
206 * \param capacity The new memory reserve of the cstr_t *.
207 * \retval bool Returns true if the operation was succesful, false otherwise.
209 bool string_reserve(cstr_t
*str
, size_t capacity
)
213 fprintf(stderr
, "String not initialized.\n");
217 if (capacity
< str
->size
)
219 //! TODO: Implement truncation?
220 fprintf(stderr
, "New capacity supplied is smaller than the string's current size.\n");
224 char * val_backup
= __malloc(str
->size
+ 1);
225 str
->value
= realloc(str
->value
, capacity
);
226 if(!str
->value
) // realloc failed
228 //! TODO: needs testing
229 //! I couldn't get realloc to fail in order to test
230 fprintf(stderr
, "Reallocation failed with capacity %zu\n", capacity
);
231 str
->value
= val_backup
;
235 //! In this case, reallocation worked
236 free (val_backup
); //! Get rid of the backup
237 str
->reserved
= capacity
;
241 //! \brief string_swap Swaps the content of str1 with str2.
242 //! \param str1 An initialized cstr_t *.
243 //! \param str2 An initialized cstr_t *.
244 //! \return A success-run boolean.
246 bool string_swap(cstr_t
* str1
, cstr_t
* str2
)
250 fprintf(stderr
, "In string_swap: str1 unitialized.\n");
255 fprintf(stderr
, "In string_swap: str2 unitialized.\n");
259 size_t str1_val_size
= str1
->size
;
260 char * str1_val_backup
= malloc(str1_val_size
+ 1);
263 fprintf(stderr
, "In string_swap: malloc failed.\n");
267 __strcpy(str1_val_backup
, str1
->value
, str1_val_size
);
268 size_t str1_res_backup
= str1
->reserved
;
270 str1
->value
= str2
->value
;
271 str1
->size
= str2
->size
;
272 str1
->reserved
= str2
->reserved
;
274 str2
->value
= str1_val_backup
;
275 str2
->size
= str1_val_size
;
276 str2
->reserved
= str1_res_backup
;