Switch to NULL-terminated array of strings
[openscop.git] / source / strings.c
blobefa8e404ac39f54ae503208746920e6d08b19edc
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>
67 # include <openscop/strings.h>
70 /*+***************************************************************************
71 * Structure display function *
72 *****************************************************************************/
75 /**
76 * openscop_strings_idump function:
77 * this function displays an array of strings into a file (file, possibly
78 * stdout) in a way that trends to be understandable. It includes an
79 * indentation level (level) in order to work with others
80 * print_structure functions.
81 * \param[in] file The file where the information has to be printed.
82 * \param[in] strings The array of strings that has to be printed.
83 * \param[in] level Number of spaces before printing, for each line.
84 * \param[in] title A string to use as a title for the array of strings.
86 void openscop_strings_idump(FILE * file, char ** strings, int level,
87 char * title) {
88 int i, nb_strings;
90 for (i = 0; i <= level; i++)
91 fprintf(file, "|\t");
93 if ((strings != NULL) &&
94 ((nb_strings = openscop_strings_size(strings)) > 0)) {
95 fprintf(file, "+-- %s:", title);
96 for (i = 0; i < nb_strings; i++)
97 fprintf(file, " %s", strings[i]);
98 fprintf(file, "\n");
100 else
101 fprintf(file, "+-- No %s\n", title);
103 // A blank line.
104 for (i = 0; i <= level+1; i++)
105 fprintf(file, "|\t");
106 fprintf(file, "\n");
111 * openscop_strings_print function:
112 * this function prints the content of an array of strings
113 * into a file (file, possibly stdout) in the OpenScop textual format.
114 * \param[in] file The file where the information has to be printed.
115 * \param[in] strings The array of strings that has to be printed.
116 * \param[in] provided Boolean set to 1 to print a "provided" boolean
117 * before the string list, 0 otherwise.
118 * \param[in] print Boolean set to 1 to print the strings, 0 otherwise.
119 * \param[in] title A string to use as a title for the array of strings.
121 void openscop_strings_print(FILE * file, char ** strings,
122 int provided, int print, char * title) {
123 int i, nb_strings;
125 if ((print != 0) &&
126 ((nb_strings = openscop_strings_size(strings)) > 0)) {
127 if (provided) {
128 fprintf(file, "# %s are provided\n", title);
129 fprintf(file, "1\n");
131 fprintf(file, "# %s\n", title);
132 for (i = 0; i < nb_strings; i++)
133 fprintf(file, "%s ", strings[i]);
134 fprintf(file, "\n\n");
136 else {
137 if (provided) {
138 fprintf(file, "# %s are not provided\n", title);
139 fprintf(file, "0\n\n");
145 /*+***************************************************************************
146 * Structure display function *
147 *****************************************************************************/
151 * openscop_strings_read function.
152 * this function reads an array of strings from a file (possibly stdin)
153 * complying to the OpenScop textual format and returns a pointer to this
154 * array as well as the number of elements of this array (through the
155 * parameter nb_strings).
156 * \param[in] file The file where to read the array of strings.
157 * \return The array of strings that has been read.
159 char ** openscop_strings_read(FILE * file) {
160 char str[OPENSCOP_MAX_STRING];
161 char tmp[OPENSCOP_MAX_STRING];
162 char * s, * start;
163 char ** strings = NULL;
164 int nb_strings;
165 int i, count;
167 // Skip blank/commented lines and spaces.
168 start = openscop_util_skip_blank_and_comments(file, str);
170 // Count the actual number of strings.
171 nb_strings = 0;
172 s = start;
173 while (1) {
174 for (count = 0; *s && ! isspace(*s) && *s != '#'; count++)
175 s++;
177 if (count != 0)
178 nb_strings++;
180 if ((*s == '#') || (*s == '\n'))
181 break;
182 else
183 ++s;
186 if (nb_strings > 0) {
187 // Allocate the array of strings. Make it NULL-terminated.
188 OPENSCOP_malloc(strings, char **, sizeof(char *) * (nb_strings + 1));
189 strings[nb_strings] = NULL;
191 // Read the desired number of strings.
192 s = start;
193 for (i = 0; i < nb_strings; i++) {
194 for (count = 0; *s && ! isspace(*s) && *s != '#'; count++)
195 tmp[count] = *(s++);
196 tmp[count] = '\0';
197 strings[i] = strdup(tmp);
198 if (strings[i] == NULL)
199 OPENSCOP_error("memory overflow");
200 if (*s != '#')
201 ++s;
205 return strings;
209 /*+***************************************************************************
210 * Memory allocation/deallocation function *
211 *****************************************************************************/
215 * openscop_strings_generate function:
216 * This function generates an array of size 'nb_strings' of strings of the
217 * form "prefixXX" where XX goes from 1 to nb.
218 * \param[in] prefix The prefix of the generated names.
219 * \param[in] nb_strings The number of strings to generate.
220 * \return An array of 'nb' generated strings.
222 char ** openscop_strings_generate(char * prefix, int nb_strings) {
223 char ** strings = NULL;
224 char buff[strlen(prefix) + 16]; // TODO: better (log10(INT_MAX) ?) :-D.
225 int i;
227 if (nb_strings) {
228 OPENSCOP_malloc(strings, char **, sizeof(char *) * (nb_strings + 1));
229 strings[nb_strings] = NULL;
230 for (i = 0; i < nb_strings; i++) {
231 sprintf(buff, "%s%d", prefix, i + 1);
232 strings[i] = strdup(buff);
233 if (strings[i] == NULL)
234 OPENSCOP_error("memory overflow");
238 return strings;
243 * openscop_strings_free function:
244 * this function frees the allocated memory for an array of strings.
245 * \param[in] strings The array of strings we want to free.
247 void openscop_strings_free(char ** strings) {
248 int i;
250 if (strings != NULL) {
251 i = 0;
252 while(strings[i] != NULL) {
253 free(strings[i]);
254 i++;
256 free(strings);
261 /*+***************************************************************************
262 * Processing functions *
263 *****************************************************************************/
267 * openscop_strings_clone internal function.
268 * this function builds and return a "hard copy" (not a pointer copy) of an
269 * array of strings provided as parameter.
270 * \param[in] strings The array of strings to clone.
271 * \return The clone of the array of strings.
273 char ** openscop_strings_clone(char ** strings) {
274 int i, nb_strings;
275 char ** clone;
277 if ((strings == NULL) ||
278 ((nb_strings = openscop_strings_size(strings)) == 0))
279 return NULL;
281 OPENSCOP_malloc(clone, char **, (nb_strings + 1) * sizeof(char *));
282 clone[nb_strings] = NULL;
283 for (i = 0; i < nb_strings; i++) {
284 clone[i] = strdup(strings[i]);
285 if (clone[i] == NULL)
286 OPENSCOP_error("memory overflow");
289 return clone;
294 * openscop_strings_equal function:
295 * this function returns true if the two arrays of strings are the same
296 * (content-wise), false otherwise.
297 * \param[in] s1 The first array of strings.
298 * \param[in] s2 The second array of strings.
299 * \return 1 if s1 and s2 are the same (content-wise), 0 otherwise.
301 int openscop_strings_equal(char ** s1, char ** s2) {
302 int i, nb_s1;
304 if (s1 == s2)
305 return 1;
307 if (((s1 == NULL) && (s2 != NULL)) ||
308 ((s1 != NULL) && (s2 == NULL)) ||
309 ((nb_s1 = openscop_strings_size(s1)) !=
310 openscop_strings_size(s2)))
311 return 0;
313 for (i = 0; i < nb_s1; i++)
314 if (strcmp(s1[i], s2[i]) != 0)
315 return 0;
317 return 1;
322 * openscop_strings_size function:
323 * this function returns the number of elements in the NULL-terminated
324 * strings array.
325 * \param[in] strings The array of strings we need to know the size.
326 * \return The number of elements in the array of strings.
328 int openscop_strings_size(char ** strings) {
329 int size = 0;
331 if (strings != NULL) {
332 while(strings[size] != NULL) {
333 size++;
337 return size;
342 * openscop_strings_complete function:
343 * this function completes an array of strings with generated strings.
344 * \param[in,out] strings Pointer to the initial array of strings.
345 * \param[in] prefix The prefix of the generated names.
346 * \param[in] nb_complete The desired number of strings in the new array.
348 void openscop_strings_complete(char *** strings, char * prefix,
349 int nb_complete) {
350 int i, nb_new;
351 char ** completion;
353 nb_new = nb_complete - openscop_strings_size(*strings);
354 if (nb_new < 0) {
355 fprintf(stderr, "[OpenScop] Error: asked to complete the following "
356 "string array but it would be smaller than the original "
357 "(desired length: %d):\n", nb_complete);
358 openscop_strings_idump(stderr, *strings, -1, "To be completed");
359 exit(1);
362 if (nb_new > 0) {
363 OPENSCOP_realloc(*strings, char **, (nb_complete + 1) * sizeof(char *));
364 *strings[nb_complete] = NULL;
365 completion = openscop_strings_generate(prefix, nb_new);
366 for (i = 0; i < nb_new; i++)
367 (*strings)[i + openscop_strings_size(*strings)] = completion[i];
368 free(completion);