1 2 /*+-----------------------------------------------------------------** 3 ** OpenScop Library ** 4 **-----------------------------------------------------------------** 5 ** strings.c ** 6 **-----------------------------------------------------------------** 7 ** First version: 13/07/2011 ** 8 **-----------------------------------------------------------------** 9 10 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 *****************************************************************************/ 62 63# include <stdlib.h> 64# include <stdio.h> 65# include <ctype.h> 66# include <string.h> 67 68# include <osl/macros.h> 69# include <osl/util.h> 70# include <osl/interface.h> 71# include <osl/strings.h> 72 73 74/*+*************************************************************************** 75 * Structure display function * 76 *****************************************************************************/ 77 78 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. 88 */ 89void osl_strings_idump(FILE * file, osl_strings_p strings, int level) { 90 int i, nb_strings; 91 92 for (i = 0; i < level; i++) 93 fprintf(file, "|\t"); 94 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"); 101 } 102 else 103 fprintf(file, "+-- NULL strings\n"); 104 105 // A blank line. 106 for (i = 0; i <= level; i++) 107 fprintf(file, "|\t"); 108 fprintf(file, "\n"); 109} 110 111 112/** 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. 118 */ 119void osl_strings_dump(FILE * file, osl_strings_p strings) { 120 osl_strings_idump(file, strings, 0); 121} 122 123 124/** 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. 130 */ 131char * osl_strings_sprint(osl_strings_p strings) { 132 int i; 133 int high_water_mark = OSL_MAX_STRING; 134 char * string = NULL; 135 char buffer[OSL_MAX_STRING]; 136 137 OSL_malloc(string, char *, high_water_mark * sizeof(char)); 138 string[0] = '\0'; 139 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); 146 } 147 sprintf(buffer, "\n"); 148 osl_util_safe_strcat(&string, buffer, &high_water_mark); 149 } 150 else { 151 sprintf(buffer, "# NULL strings\n"); 152 osl_util_safe_strcat(&string, buffer, &high_water_mark); 153 } 154 155 return string; 156} 157 158 159/** 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. 165 */ 166void osl_strings_print(FILE * file, osl_strings_p strings) { 167 char * string; 168 169 string = osl_strings_sprint(strings); 170 if (string != NULL) { 171 fprintf(file, "%s", string); 172 free(string); 173 } 174} 175 176 177/*+*************************************************************************** 178 * Structure display function * 179 *****************************************************************************/ 180 181 182/** 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. 193 */ 194osl_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; 201 202 // Skip blank/commented lines and spaces before the strings. 203 osl_util_sskip_blank_and_comments(input); 204 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++; 211 212 if (count != 0) 213 nb_strings++; 214 215 if ((!*s) || (*s == '#') || (*s == '\n')) 216 break; 217 else 218 s++; 219 } 220 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; 225 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++; 235 } 236 237 // Update the input pointer to the end of the strings structure. 238 *input = s; 239 240 // Build the strings structure 241 strings = osl_strings_malloc(); 242 strings->string = string; 243 } 244 245 return strings; 246} 247 248 249/** 250 * osl_strings_read function. 251 * this function reads a strings structure from a file (possibly stdin) 252 * complying to the OpenScop textual format and returns a pointer to this 253 * structure. 254 * parameter nb_strings). 255 * \param[in] file The file where to read the strings structure. 256 * \return The strings structure that has been read. 257 */ 258osl_strings_p osl_strings_read(FILE * file) { 259 char buffer[OSL_MAX_STRING], * start; 260 osl_strings_p strings; 261 262 start = osl_util_skip_blank_and_comments(file, buffer); 263 strings = osl_strings_sread(&start); 264 265 return strings; 266} 267 268 269/*+*************************************************************************** 270 * Memory allocation/deallocation function * 271 *****************************************************************************/ 272 273 274/** 275 * osl_strings_malloc function: 276 * This function allocates the memory space for an osl_strings_t 277 * structure and sets its fields with default values. Then it returns a 278 * pointer to the allocated space. 279 * \return A pointer to an empty strings structure with fields set to 280 * default values. 281 */ 282osl_strings_p osl_strings_malloc() { 283 osl_strings_p strings; 284 285 OSL_malloc(strings, osl_strings_p, sizeof(osl_strings_t)); 286 strings->string = NULL; 287 288 return strings; 289} 290 291 292/** 293 * osl_strings_free function: 294 * this function frees the allocated memory for a strings data structure. 295 * \param[in] strings The strings structure we want to free. 296 */ 297void osl_strings_free(osl_strings_p strings) { 298 int i; 299 300 if (strings != NULL) { 301 if (strings->string != NULL) { 302 i = 0; 303 while (strings->string[i] != NULL) { 304 free(strings->string[i]); 305 i++; 306 } 307 free(strings->string); 308 } 309 free(strings); 310 } 311} 312 313 314/*+*************************************************************************** 315 * Processing functions * 316 *****************************************************************************/ 317 318 319/** 320 * osl_strings_clone function. 321 * this function builds and return a "hard copy" (not a pointer copy) of an 322 * strings structure provided as parameter. 323 * \param[in] strings The strings structure to clone. 324 * \return The clone of the strings structure. 325 */ 326osl_strings_p osl_strings_clone(osl_strings_p strings) { 327 int i, nb_strings; 328 osl_strings_p clone = NULL; 329 330 if (strings == NULL) 331 return NULL; 332 333 clone = osl_strings_malloc(); 334 if ((nb_strings = osl_strings_size(strings)) == 0) 335 return clone; 336 337 OSL_malloc(clone->string, char **, (nb_strings + 1) * sizeof(char *)); 338 clone->string[nb_strings] = NULL; 339 for (i = 0; i < nb_strings; i++) 340 OSL_strdup(clone->string[i], strings->string[i]); 341 342 return clone; 343} 344 345 346/** 347 * osl_strings_equal function: 348 * this function returns true if the two strings structures are the same 349 * (content-wise), false otherwise. 350 * \param[in] s1 The first strings structure. 351 * \param[in] s2 The second strings structure. 352 * \return 1 if s1 and s2 are the same (content-wise), 0 otherwise. 353 */ 354int osl_strings_equal(osl_strings_p s1, osl_strings_p s2) { 355 int i, nb_s1; 356 357 if (s1 == s2) 358 return 1; 359 360 if (((s1 == NULL) && (s2 != NULL)) || 361 ((s1 != NULL) && (s2 == NULL)) || 362 ((nb_s1 = osl_strings_size(s1)) != osl_strings_size(s2))) 363 return 0; 364 365 for (i = 0; i < nb_s1; i++) 366 if (strcmp(s1->string[i], s2->string[i]) != 0) 367 return 0; 368 369 return 1; 370} 371 372 373/** 374 * osl_strings_size function: 375 * this function returns the number of elements in the NULL-terminated 376 * strings array of the strings structure. 377 * \param[in] strings The strings structure we need to know the size. 378 * \return The number of strings in the strings structure. 379 */ 380int osl_strings_size(osl_strings_p strings) { 381 int size = 0; 382 383 if ((strings != NULL) && (strings->string != NULL)) { 384 while (strings->string[size] != NULL) { 385 size++; 386 } 387 } 388 389 return size; 390} 391 392 393/** 394 * osl_strings_encapsulate function: 395 * this function builds a new strings structure to encapsulate the string 396 * provided as a parameter (the reference to this string is used directly). 397 * \param[in] string The string to encapsulate in a strings structure. 398 * \return A new strings structure containing only the provided string. 399 */ 400osl_strings_p osl_strings_encapsulate(char * string) { 401 osl_strings_p capsule = osl_strings_malloc(); 402 403 OSL_malloc(capsule->string, char **, 2 * sizeof(char *)); 404 capsule->string[0] = string; 405 capsule->string[1] = NULL; 406 407 return capsule; 408} 409 410 411/** 412 * osl_strings_interface function: 413 * this function creates an interface structure corresponding to the strings 414 * structure and returns it). 415 * \return An interface structure for the strings structure. 416 */ 417osl_interface_p osl_strings_interface() { 418 osl_interface_p interface = osl_interface_malloc(); 419 420 interface->URI = strdup(OSL_URI_STRINGS); 421 interface->idump = (osl_idump_f)osl_strings_idump; 422 interface->sprint = (osl_sprint_f)osl_strings_sprint; 423 interface->sread = (osl_sread_f)osl_strings_sread; 424 interface->malloc = (osl_malloc_f)osl_strings_malloc; 425 interface->free = (osl_free_f)osl_strings_free; 426 interface->clone = (osl_clone_f)osl_strings_clone; 427 interface->equal = (osl_equal_f)osl_strings_equal; 428 429 return interface; 430} 431 432 433/** 434 * osl_strings_generate function: 435 * this function generates a new strings structure containing 436 * 'nb_strings' strings of the form "prefixXX" where XX goes from 1 to 437 * nb_strings. 438 * \param[in] prefix The prefix of the generated strings. 439 * \param[in] nb_strings The number of strings to generate. 440 * \return A new strings structure containing generated strings. 441 */ 442osl_strings_p osl_strings_generate(char * prefix, int nb_strings) { 443 char ** strings = NULL; 444 char buff[strlen(prefix) + 16]; // TODO: better (log10(INT_MAX) ?) :-D. 445 int i; 446 osl_strings_p generated; 447 448 if (nb_strings) { 449 OSL_malloc(strings, char **, sizeof(char *) * (nb_strings + 1)); 450 strings[nb_strings] = NULL; 451 for (i = 0; i < nb_strings; i++) { 452 sprintf(buff, "%s%d", prefix, i + 1); 453 strings[i] = strdup(buff); 454 if (strings[i] == NULL) 455 OSL_error("memory overflow"); 456 } 457 } 458 459 generated = osl_strings_malloc(); 460 generated->string = strings; 461 return generated; 462} 463