Merge branch 'master' of github.com:periscop/openscop
[openscop.git] / source / strings.c
blobef1ad80c2398aba354eb4ca3594e60317f9f2d44
2 /*+-----------------------------------------------------------------**
3 ** OpenScop Library **
4 **-----------------------------------------------------------------**
5 ** strings.c **
6 **-----------------------------------------------------------------**
7 ** First version: 13/07/2011 **
8 **-----------------------------------------------------------------**
11 *****************************************************************************
12 * OpenScop: Structures and formats for polyhedral tools to talk together *
13 *****************************************************************************
14 * ,___,,_,__,,__,,__,,__,,_,__,,_,__,,__,,___,_,__,,_,__, *
15 * / / / // // // // / / / // // / / // / /|,_, *
16 * / / / // // // // / / / // // / / // / / / /\ *
17 * |~~~|~|~~~|~~~|~~~|~~~|~|~~~|~|~~~|~~~|~~~|~|~~~|~|~~~|/_/ \ *
18 * | G |C| P | = | L | P |=| = |C| = | = | = |=| = |=| C |\ \ /\ *
19 * | R |l| o | = | e | l |=| = |a| = | = | = |=| = |=| L | \# \ /\ *
20 * | A |a| l | = | t | u |=| = |n| = | = | = |=| = |=| o | |\# \ \ *
21 * | P |n| l | = | s | t |=| = |d| = | = | = | | |=| o | | \# \ \ *
22 * | H | | y | | e | o | | = |l| | | = | | | | G | | \ \ \ *
23 * | I | | | | e | | | | | | | | | | | | | \ \ \ *
24 * | T | | | | | | | | | | | | | | | | | \ \ \ *
25 * | E | | | | | | | | | | | | | | | | | \ \ \ *
26 * | * |*| * | * | * | * |*| * |*| * | * | * |*| * |*| * | / \* \ \ *
27 * | O |p| e | n | S | c |o| p |-| L | i | b |r| a |r| y |/ \ \ / *
28 * '---'-'---'---'---'---'-'---'-'---'---'---'-'---'-'---' '--' *
29 * *
30 * Copyright (C) 2008 University Paris-Sud 11 and INRIA *
31 * *
32 * (3-clause BSD license) *
33 * Redistribution and use in source and binary forms, with or without *
34 * modification, are permitted provided that the following conditions *
35 * are met: *
36 * *
37 * 1. Redistributions of source code must retain the above copyright notice, *
38 * this list of conditions and the following disclaimer. *
39 * 2. Redistributions in binary form must reproduce the above copyright *
40 * notice, this list of conditions and the following disclaimer in the *
41 * documentation and/or other materials provided with the distribution. *
42 * 3. The name of the author may not be used to endorse or promote products *
43 * derived from this software without specific prior written permission. *
44 * *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
55 * *
56 * OpenScop Library, a library to manipulate OpenScop formats and data *
57 * structures. Written by: *
58 * Cedric Bastoul <Cedric.Bastoul@u-psud.fr> and *
59 * Louis-Noel Pouchet <Louis-Noel.pouchet@inria.fr> *
60 * *
61 *****************************************************************************/
63 # include <stdlib.h>
64 # include <stdio.h>
65 # include <ctype.h>
66 # include <string.h>
68 # include <osl/macros.h>
69 # include <osl/util.h>
70 # include <osl/interface.h>
71 # include <osl/strings.h>
74 /*+***************************************************************************
75 * Structure display function *
76 *****************************************************************************/
79 /**
80 * osl_strings_idump function:
81 * this function displays an array of strings into a file (file, possibly
82 * stdout) in a way that trends to be understandable. It includes an
83 * indentation level (level) in order to work with others
84 * idump functions.
85 * \param[in] file The file where the information has to be printed.
86 * \param[in] strings The array of strings that has to be printed.
87 * \param[in] level Number of spaces before printing, for each line.
89 void osl_strings_idump(FILE * file, osl_strings_p strings, int level) {
90 int i, nb_strings;
92 for (i = 0; i < level; i++)
93 fprintf(file, "|\t");
95 if (strings != NULL) {
96 nb_strings = osl_strings_size(strings);
97 fprintf(file, "+-- osl_strings_t:");
98 for (i = 0; i < nb_strings; i++)
99 fprintf(file, " %s", strings->string[i]);
100 fprintf(file, "\n");
102 else
103 fprintf(file, "+-- NULL strings\n");
105 // A blank line.
106 for (i = 0; i <= level; i++)
107 fprintf(file, "|\t");
108 fprintf(file, "\n");
113 * osl_strings_dump function:
114 * this function prints the content of an osl_strings_t structure
115 * (*strings) into a file (file, possibly stdout).
116 * \param[in] file The file where the information has to be printed.
117 * \param[in] strings The strings structure which has to be printed.
119 void osl_strings_dump(FILE * file, osl_strings_p strings) {
120 osl_strings_idump(file, strings, 0);
125 * osl_strings_sprint function:
126 * this function prints the content of an osl_strings_t structure
127 * (*strings) into a string (returned) in the OpenScop textual format.
128 * \param[in] strings The strings structure which has to be printed.
129 * \return A string containing the OpenScop dump of the strings structure.
131 char * osl_strings_sprint(osl_strings_p strings) {
132 size_t i;
133 int high_water_mark = OSL_MAX_STRING;
134 char * string = NULL;
135 char buffer[OSL_MAX_STRING];
137 OSL_malloc(string, char *, high_water_mark * sizeof(char));
138 string[0] = '\0';
140 if (strings != NULL) {
141 for (i = 0; i < osl_strings_size(strings); i++) {
142 sprintf(buffer, "%s", strings->string[i]);
143 osl_util_safe_strcat(&string, buffer, &high_water_mark);
144 if (i < osl_strings_size(strings) - 1)
145 osl_util_safe_strcat(&string, " ", &high_water_mark);
147 sprintf(buffer, "\n");
148 osl_util_safe_strcat(&string, buffer, &high_water_mark);
150 else {
151 sprintf(buffer, "# NULL strings\n");
152 osl_util_safe_strcat(&string, buffer, &high_water_mark);
155 return string;
160 * osl_strings_print function:
161 * this function prints the content of an osl_strings_t structure
162 * (*body) into a file (file, possibly stdout) in the OpenScop format.
163 * \param[in] file File where informations are printed.
164 * \param[in] strings The strings whose information has to be printed.
166 void osl_strings_print(FILE * file, osl_strings_p strings) {
167 char * string;
169 string = osl_strings_sprint(strings);
170 if (string != NULL) {
171 fprintf(file, "%s", string);
172 free(string);
177 /*+***************************************************************************
178 * Structure display function *
179 *****************************************************************************/
183 * osl_strings_sread function:
184 * this function reads a strings structure from a string complying to the
185 * OpenScop textual format and returns a pointer to this strings structure.
186 * The input string should only contain the list of strings this function
187 * has to read (comments at the end of the line are accepted). The input
188 * parameter is updated to the position in the input string this function
189 * reach right after reading the strings structure.
190 * \param[in,out] input The input string where to find a strings structure.
191 * Updated to the position after what has been read.
192 * \return A pointer to the strings structure that has been read.
194 osl_strings_p osl_strings_sread(char ** input) {
195 char tmp[OSL_MAX_STRING];
196 char * s;
197 char ** string = NULL;
198 int nb_strings;
199 int i, count;
200 osl_strings_p strings = NULL;
202 // Skip blank/commented lines and spaces before the strings.
203 osl_util_sskip_blank_and_comments(input);
205 // Count the actual number of strings.
206 nb_strings = 0;
207 s = *input;
208 while (1) {
209 for (count = 0; *s && !isspace(*s) && *s != '#'; count++)
210 s++;
212 if (count != 0)
213 nb_strings++;
215 if ((!*s) || (*s == '#') || (*s == '\n'))
216 break;
217 else
218 s++;
221 if (nb_strings > 0) {
222 // Allocate the array of strings. Make it NULL-terminated.
223 OSL_malloc(string, char **, sizeof(char *) * (nb_strings + 1));
224 string[nb_strings] = NULL;
226 // Read the desired number of strings.
227 s = *input;
228 for (i = 0; i < nb_strings; i++) {
229 for (count = 0; *s && !isspace(*s) && *s != '#'; count++)
230 tmp[count] = *(s++);
231 tmp[count] = '\0';
232 OSL_strdup(string[i], tmp);
233 if (*s != '#')
234 s++;
237 // Update the input pointer to the end of the strings structure.
238 *input = s;
240 // Build the strings structure
241 strings = osl_strings_malloc();
242 free(strings->string);
243 strings->string = string;
246 return strings;
251 * osl_strings_read function.
252 * this function reads a strings structure from a file (possibly stdin)
253 * complying to the OpenScop textual format and returns a pointer to this
254 * structure.
255 * parameter nb_strings).
256 * \param[in] file The file where to read the strings structure.
257 * \return The strings structure that has been read.
259 osl_strings_p osl_strings_read(FILE * file) {
260 char buffer[OSL_MAX_STRING], * start;
261 osl_strings_p strings;
263 start = osl_util_skip_blank_and_comments(file, buffer);
264 strings = osl_strings_sread(&start);
266 return strings;
270 /*+***************************************************************************
271 * Memory allocation/deallocation function *
272 *****************************************************************************/
276 * osl_strings_malloc function:
277 * This function allocates the memory space for an osl_strings_t
278 * structure and sets its fields with default values. Then it returns a
279 * pointer to the allocated space.
280 * \return A pointer to an empty strings structure with fields set to
281 * default values.
283 osl_strings_p osl_strings_malloc() {
284 osl_strings_p strings;
286 OSL_malloc(strings, osl_strings_p, sizeof(osl_strings_t));
287 OSL_malloc(strings->string, char**, sizeof(char*));
288 strings->string[0] = NULL;
290 return strings;
295 * osl_strings_free function:
296 * this function frees the allocated memory for a strings data structure.
297 * \param[in] strings The strings structure we want to free.
299 void osl_strings_free(osl_strings_p strings) {
300 int i;
302 if (strings != NULL) {
303 if (strings->string != NULL) {
304 i = 0;
305 while (strings->string[i] != NULL) {
306 free(strings->string[i]);
307 i++;
309 free(strings->string);
311 free(strings);
316 /*+***************************************************************************
317 * Processing functions *
318 *****************************************************************************/
322 * osl_strings_clone function.
323 * this function builds and return a "hard copy" (not a pointer copy) of an
324 * strings structure provided as parameter.
325 * \param[in] strings The strings structure to clone.
326 * \return The clone of the strings structure.
328 osl_strings_p osl_strings_clone(osl_strings_p strings) {
329 int i, nb_strings;
330 osl_strings_p clone = NULL;
332 if (strings == NULL)
333 return NULL;
335 clone = osl_strings_malloc();
336 if ((nb_strings = osl_strings_size(strings)) == 0)
337 return clone;
339 free(clone->string);
340 OSL_malloc(clone->string, char **, (nb_strings + 1) * sizeof(char *));
341 clone->string[nb_strings] = NULL;
342 for (i = 0; i < nb_strings; i++)
343 OSL_strdup(clone->string[i], strings->string[i]);
345 return clone;
349 * osl_strings_find function.
350 * this function finds the string in the strings.
351 * \param[in,out] strings The strings structure.
352 * \param[in] string The string to find in strings.
353 * \return the index where is the string, osl_strings_size if not found
355 size_t osl_strings_find(osl_strings_p strings, char const * const string) {
356 size_t i;
357 for (i = 0; i < osl_strings_size(strings); ++i) {
358 if (strcmp(strings->string[i], string) == 0) { return i; }
360 return i;
365 * osl_strings_add function.
366 * this function adds a copy of the string in the strings.
367 * \param[in,out] strings The strings structure.
368 * \param[in] string The string to add in strings.
370 void osl_strings_add(osl_strings_p strings, char const * const string) {
371 size_t original_size = osl_strings_size(strings);
372 OSL_realloc(strings->string, char**, sizeof(char*) * (original_size + 1 + 1));
373 strings->string[original_size + 1] = NULL;
374 strings->string[original_size] = malloc(sizeof(char) * (strlen(string) + 1));
375 strcpy(strings->string[original_size], string);
380 * osl_strings_equal function:
381 * this function returns true if the two strings structures are the same
382 * (content-wise), false otherwise.
383 * \param[in] s1 The first strings structure.
384 * \param[in] s2 The second strings structure.
385 * \return 1 if s1 and s2 are the same (content-wise), 0 otherwise.
387 int osl_strings_equal(osl_strings_p s1, osl_strings_p s2) {
388 size_t i, nb_s1;
390 if (s1 == s2)
391 return 1;
393 if (((s1 == NULL) && (s2 != NULL)) ||
394 ((s1 != NULL) && (s2 == NULL)) ||
395 ((nb_s1 = osl_strings_size(s1)) != osl_strings_size(s2)))
396 return 0;
398 for (i = 0; i < nb_s1; i++)
399 if (strcmp(s1->string[i], s2->string[i]) != 0)
400 return 0;
402 return 1;
407 * osl_strings_size function:
408 * this function returns the number of elements in the NULL-terminated
409 * strings array of the strings structure.
410 * \param[in] strings The strings structure we need to know the size.
411 * \return The number of strings in the strings structure.
413 size_t osl_strings_size(osl_const_strings_const_p strings) {
414 size_t size = 0;
416 if ((strings != NULL) && (strings->string != NULL)) {
417 while (strings->string[size] != NULL) {
418 size++;
422 return size;
427 * osl_strings_encapsulate function:
428 * this function builds a new strings structure to encapsulate the string
429 * provided as a parameter (the reference to this string is used directly).
430 * \param[in] string The string to encapsulate in a strings structure.
431 * \return A new strings structure containing only the provided string.
433 osl_strings_p osl_strings_encapsulate(char * string) {
434 osl_strings_p capsule = osl_strings_malloc();
435 free(capsule->string);
436 OSL_malloc(capsule->string, char **, 2 * sizeof(char *));
437 capsule->string[0] = string;
438 capsule->string[1] = NULL;
440 return capsule;
445 * osl_strings_interface function:
446 * this function creates an interface structure corresponding to the strings
447 * structure and returns it).
448 * \return An interface structure for the strings structure.
450 osl_interface_p osl_strings_interface() {
451 osl_interface_p interface = osl_interface_malloc();
453 OSL_strdup(interface->URI, OSL_URI_STRINGS);
454 interface->idump = (osl_idump_f)osl_strings_idump;
455 interface->sprint = (osl_sprint_f)osl_strings_sprint;
456 interface->sread = (osl_sread_f)osl_strings_sread;
457 interface->malloc = (osl_malloc_f)osl_strings_malloc;
458 interface->free = (osl_free_f)osl_strings_free;
459 interface->clone = (osl_clone_f)osl_strings_clone;
460 interface->equal = (osl_equal_f)osl_strings_equal;
462 return interface;
467 * osl_strings_generate function:
468 * this function generates a new strings structure containing
469 * 'nb_strings' strings of the form "prefixXX" where XX goes from 1 to
470 * nb_strings.
471 * \param[in] prefix The prefix of the generated strings.
472 * \param[in] nb_strings The number of strings to generate.
473 * \return A new strings structure containing generated strings.
475 osl_strings_p osl_strings_generate(char * prefix, int nb_strings) {
476 char ** strings = NULL;
477 char buff[strlen(prefix) + 16]; // TODO: better (log10(INT_MAX) ?) :-D.
478 int i;
479 osl_strings_p generated;
481 if (nb_strings) {
482 OSL_malloc(strings, char **, sizeof(char *) * (nb_strings + 1));
483 strings[nb_strings] = NULL;
484 for (i = 0; i < nb_strings; i++) {
485 sprintf(buff, "%s%d", prefix, i + 1);
486 OSL_strdup(strings[i], buff);
487 if (strings[i] == NULL)
488 OSL_error("memory overflow");
492 generated = osl_strings_malloc();
493 free(generated->string);
494 generated->string = strings;
495 return generated;
499 * \brief Concatenate two osl_strings into one. The parameter are cloned and not modified.
501 * \param dest[out] A pointer to the destination osl_strings.
502 * \param str1[in] The first osl_strings.
503 * \param str2[in] The second osl_strings.
505 void osl_strings_add_strings(
506 osl_strings_p * dest,
507 osl_strings_p str1,
508 osl_strings_p str2) {
509 struct osl_strings * res = NULL;
510 unsigned int i = 0;
512 res = osl_strings_clone(str1);
513 while (str2->string[i] != NULL) {
514 osl_strings_add(res, str2->string[i]);
515 i++;
518 *dest = res;