Statistiques
| Révision :

root / approxBasisSollya / read-lines-from-file.c @ 304

Historique | Voir | Annoter | Télécharger (11,42 ko)

1 299 storres
/** @file read-lines-from-file.c */
2 299 storres
/******************************************************************************/
3 299 storres
/**
4 299 storres
 * Read lines from a text file, filtering out empty, #-comment lines,
5 299 storres
 * leading spaces and tab, trailing comments.
6 299 storres
 *
7 299 storres
 * @author: ST
8 299 storres
 * @date: 2016-10-21
9 299 storres
 *
10 299 storres
 */
11 299 storres
12 299 storres
/* Includes according to the "general to particular" rule. */
13 299 storres
/* includes of system headers */
14 299 storres
#include <stdlib.h>
15 299 storres
#include <stdio.h>
16 299 storres
#include <libgen.h>
17 299 storres
18 299 storres
/* includes of project headers */
19 299 storres
20 299 storres
/* includes of local headers */
21 299 storres
#include <read-lines-from-file.h>
22 299 storres
23 299 storres
/* Types, constants and macros definitions */
24 299 storres
25 299 storres
/* Global variables */
26 299 storres
27 299 storres
/* Functions */
28 299 storres
29 299 storres
/** Scout the file for lines count and maximum lines length.
30 299 storres
 * The file is specified by its name.
31 299 storres
 * The data are returned through pointer arguments.
32 299 storres
 * @param fileName (in);
33 299 storres
 * @param linesCountPtr (in/out);
34 299 storres
 * @param maxLineLengthPtr (in/out);
35 299 storres
 * @return 0 if OK and != 0 if something goes wrong. */
36 299 storres
37 299 storres
int
38 299 storres
rlff_scout_file_from_name(char* fileName,
39 299 storres
                          unsigned int* linesCountPtr,
40 299 storres
                          unsigned int* maxLineLengthPtr);
41 299 storres
42 299 storres
/** Scout the file for lines count and maximum lines length.
43 299 storres
 * The file is specified by a handle open on it in "read" mode (at least).
44 299 storres
 * The data are returned through pointer arguments.
45 299 storres
 * @param fileHandle (in);
46 299 storres
 * @param linesCountPtr (in/out);
47 299 storres
 * @param maxLineLengthPtr (in/out);
48 299 storres
* @return 0 if OK and != 0 if something goes wrong. */
49 299 storres
50 299 storres
int
51 299 storres
rlff_scout_file_from_handle(FILE* fileHandle,
52 299 storres
                            unsigned int* linesCountPtr,
53 299 storres
                            unsigned int* maxLineLengthPtr);
54 299 storres
55 299 storres
/** Dealloc a readLines struct that has been initialized (even partly)
56 299 storres
 * @see read-lines-from-file.h#rlff_free_lines.*/
57 299 storres
void
58 299 storres
rlff_free_lines(rlff_readLines_t* linesRead)
59 299 storres
{
60 299 storres
  if (linesRead == NULL) { return; }
61 299 storres
  if (linesRead->lines == NULL) { return; }
62 299 storres
  free(linesRead->lines);
63 299 storres
  free(linesRead);
64 299 storres
} /* End free_lines. */
65 299 storres
66 299 storres
/** @see read-lines-from-file.h#rlff_get_line_at. */
67 299 storres
char*
68 299 storres
rlff_get_line_at(rlff_readLines_t* linesRead, unsigned int lineIndex)
69 299 storres
{
70 299 storres
  if (linesRead == NULL)
71 299 storres
  {
72 299 storres
    #ifndef NDEBUG
73 299 storres
    fprintf(stderr,
74 299 storres
            "\n%s: linesRead is a NULL pointer.\n",
75 299 storres
            __func__);
76 299 storres
    #endif
77 299 storres
    return NULL;
78 299 storres
  }
79 299 storres
  if (lineIndex > (linesRead->linesNum -1))
80 299 storres
  {
81 299 storres
    #ifndef NDEBUG
82 299 storres
    fprintf(stderr,
83 304 storres
            "\n%s: requested line (%d) is beyond\n",
84 299 storres
            __func__,
85 299 storres
            lineIndex);
86 299 storres
    fprintf(stderr,
87 299 storres
            "maximum index (%d).\n",
88 299 storres
            linesRead->linesNum -1);
89 299 storres
    #endif
90 299 storres
    return NULL;
91 299 storres
  }
92 304 storres
  return linesRead->lines + lineIndex * linesRead->linesLength;
93 299 storres
} /* End rlff_get_line_at. */
94 299 storres
95 299 storres
/** @see read-lines-from-file.h#rlff_print_lines */
96 299 storres
void
97 299 storres
  rlff_print_lines(rlff_readLines_t* linesRead)
98 299 storres
{
99 299 storres
  unsigned int i = 0;
100 299 storres
  if (linesRead == NULL) { return; }
101 299 storres
  for (i = 0 ; i < linesRead->linesNum ; i++)
102 299 storres
  {
103 299 storres
    fprintf(stdout,
104 299 storres
            "%s\n",
105 299 storres
            rlff_get_line_at(linesRead, i));
106 299 storres
  }
107 299 storres
} /* End rlff_print_lines. */
108 299 storres
109 299 storres
/** @see read-lines-from-file.h#rlff_read_lines_from file_name */
110 299 storres
rlff_readLines_t*
111 299 storres
rlff_read_lines_from_file_name(char* fileName)
112 299 storres
{
113 299 storres
  FILE* linesFile               = NULL;
114 299 storres
115 299 storres
  /* Current character position in read file. Starts at 0. */
116 299 storres
  rlff_readLines_t* linesRead   = NULL;
117 299 storres
118 299 storres
  /* Argument check. */
119 299 storres
  if (fileName == NULL)
120 299 storres
  {
121 299 storres
    #ifndef NDEBUG
122 299 storres
    fprintf(stderr,
123 299 storres
            "\n%s: fileName is a NULL pointer.\n",
124 299 storres
            __func__);
125 299 storres
    #endif
126 299 storres
    return NULL;
127 299 storres
  }
128 299 storres
  /* Try to open the file in read-only mode. */
129 299 storres
  linesFile = fopen(fileName, "r");
130 299 storres
  if (linesFile == NULL)
131 299 storres
  {
132 299 storres
    #ifndef NDEBUG
133 299 storres
    fprintf(stderr,
134 299 storres
            "\n%s: could not open file %s.\n",
135 299 storres
            __func__,
136 299 storres
            fileName);
137 299 storres
    #endif
138 299 storres
    return NULL;
139 299 storres
  }
140 299 storres
  linesRead = rlff_read_lines_from_file_handle(linesFile);
141 299 storres
  fclose(linesFile);
142 299 storres
  return linesRead;
143 299 storres
} /* End rlff_read_lines_from_file_name. */
144 299 storres
145 299 storres
/** @see read-lines-from-file.h#rlff_read_lines_from file_handle */
146 299 storres
rlff_readLines_t*
147 299 storres
rlff_read_lines_from_file_handle(FILE* fileHandle)
148 299 storres
{
149 299 storres
  char c                        = '\0';
150 299 storres
  char* bufferCurrentLinePtr    = NULL;
151 299 storres
  char* bufferCurrentCharPtr    = NULL;
152 299 storres
  /* Current character position in read file. Starts at 0. */
153 299 storres
  rlff_readLines_t* linesRead   = NULL;
154 299 storres
  unsigned int rlffLinesCount   = 0;
155 299 storres
  unsigned int rlffLinesLength  = 0;
156 299 storres
157 299 storres
  /* Argument check. */
158 299 storres
  if (fileHandle == NULL)
159 299 storres
  {
160 299 storres
    #ifndef NDEBUG
161 299 storres
    fprintf(stderr,
162 299 storres
            "\n%s: fileHandle is a NULL pointer.\n",
163 299 storres
            __func__);
164 299 storres
    #endif
165 299 storres
    return NULL;
166 299 storres
  }
167 299 storres
  /* Get the file data. */
168 299 storres
  if (rlff_scout_file_from_handle(fileHandle,
169 299 storres
                                  &rlffLinesCount,
170 299 storres
                                  &rlffLinesLength))
171 299 storres
  {
172 299 storres
    #ifndef NDEBUG
173 299 storres
    fprintf(stderr,
174 299 storres
            "\n%s: could not scout the file.\n",
175 299 storres
            __func__);
176 299 storres
    #endif
177 299 storres
    return NULL;
178 299 storres
  }
179 299 storres
  /* Try to allocate the pointer returned structure. */
180 299 storres
  linesRead = malloc(sizeof(rlff_readLines_t));
181 299 storres
  if (linesRead == NULL)
182 299 storres
  {
183 299 storres
    #ifndef NDEBUG
184 299 storres
    fprintf(stderr,
185 299 storres
            "\n%s: could not alloc memory for the rlff_readLines_t.\n",
186 299 storres
            __func__);
187 299 storres
    #endif
188 299 storres
    return NULL;
189 299 storres
  }
190 299 storres
191 299 storres
  linesRead->linesNum     = rlffLinesCount;
192 304 storres
  linesRead->linesLength  = rlffLinesLength;
193 299 storres
  if ((rlffLinesCount == 0) || (rlffLinesLength == 0))
194 299 storres
  {
195 299 storres
    /* The file is somehow empty: not an actual error. */
196 299 storres
    linesRead->linesNum     = 0;
197 304 storres
    linesRead->linesLength  = 0;
198 299 storres
    linesRead->lines        = NULL;
199 299 storres
    return linesRead;
200 299 storres
  }
201 299 storres
  /* Try to allocate the lines buffer. */
202 299 storres
  linesRead->lines =
203 299 storres
      malloc(rlffLinesCount * rlffLinesLength * sizeof(char));
204 299 storres
  if (linesRead->lines == NULL)
205 299 storres
  {
206 299 storres
    #ifndef NDEBUG
207 299 storres
    fprintf(stderr,
208 299 storres
            "\n%s: could not alloc memory for the lines buffer.\n",
209 299 storres
            __func__);
210 299 storres
    #endif
211 299 storres
    free(linesRead);
212 299 storres
    return NULL;
213 299 storres
  }
214 299 storres
  bufferCurrentLinePtr = linesRead->lines;
215 299 storres
  bufferCurrentCharPtr = bufferCurrentLinePtr;
216 299 storres
  /* Get the chars of the file. */
217 299 storres
  while ((c = fgetc(fileHandle)) != EOF)
218 299 storres
  {
219 299 storres
    /* Skipping initial spaces. */
220 299 storres
    while((c == ' ') || (c == '\t'))
221 299 storres
    {
222 299 storres
      c = fgetc(fileHandle);
223 299 storres
      if (c == EOF)
224 299 storres
      {
225 299 storres
        return linesRead;
226 299 storres
      }
227 299 storres
    } /* End while */
228 299 storres
    /* A line of spaces or an empty line. */
229 299 storres
    if (c == '\n')
230 299 storres
    {
231 299 storres
      continue;
232 299 storres
    }
233 299 storres
    /* First character afer spaces is '#'.  Read the comment
234 299 storres
     * to the end of the line or of the file. */
235 299 storres
    if (c == '#')
236 299 storres
    {
237 299 storres
      while(((c = fgetc(fileHandle)) != EOF) && (c != '\n')) {}
238 299 storres
      if (c == '\n')
239 299 storres
      {
240 299 storres
        continue;
241 299 storres
      }
242 299 storres
      else /* c == EOF */
243 299 storres
      {
244 299 storres
        return linesRead;
245 299 storres
      }
246 299 storres
    } /* End c == '#'. */
247 299 storres
    *bufferCurrentCharPtr = c;
248 299 storres
    bufferCurrentCharPtr++;
249 299 storres
    /* A line with usefull content. */
250 299 storres
    while(((c = fgetc(fileHandle)) != EOF) && (c != '\n') && (c != '#'))
251 299 storres
    {
252 299 storres
      *bufferCurrentCharPtr = c;
253 299 storres
      bufferCurrentCharPtr++;
254 299 storres
    }
255 299 storres
    if (c == '#')
256 299 storres
    {
257 299 storres
      while(((c = fgetc(fileHandle)) != EOF) && (c != '\n')) {}
258 299 storres
    }
259 299 storres
    if (c == EOF)
260 299 storres
    {
261 299 storres
        return linesRead;
262 299 storres
    } /* End c == EOF. */
263 299 storres
    /* End of a line with useful content. */
264 299 storres
    /* At the end of a useful lines. */
265 299 storres
    if (c == '\n')
266 299 storres
    {
267 299 storres
      *bufferCurrentCharPtr = '\0';
268 299 storres
      /* Delete trailing spaces. */
269 299 storres
      while (bufferCurrentCharPtr > bufferCurrentLinePtr)
270 299 storres
      {
271 299 storres
        bufferCurrentCharPtr--;
272 299 storres
        if ((*bufferCurrentCharPtr == ' ') ||
273 299 storres
            (*bufferCurrentCharPtr == '\t'))
274 299 storres
        {
275 299 storres
          *bufferCurrentCharPtr = '\0';
276 299 storres
        }
277 299 storres
        else
278 299 storres
        {
279 299 storres
          break;
280 299 storres
        }
281 299 storres
      } /* End while. */
282 304 storres
      bufferCurrentLinePtr += linesRead->linesLength;
283 299 storres
      bufferCurrentCharPtr = bufferCurrentLinePtr;
284 299 storres
    } /* End c == '\n'. */
285 299 storres
  } /* End main while; ancillary*/
286 299 storres
  /* Normal reading exit. */
287 299 storres
  return linesRead;
288 299 storres
} /* End rlff_read_lines_from_file_handle. */
289 299 storres
290 299 storres
int
291 299 storres
rlff_scout_file_from_name(char* fileName,
292 299 storres
                          unsigned int* linesCountPtr,
293 299 storres
                          unsigned int* maxLineLengthPtr)
294 299 storres
{
295 299 storres
  FILE* linesFileHandle         = NULL;
296 299 storres
  int returnValue               = 0;
297 299 storres
298 299 storres
  /* Arguments check. */
299 299 storres
  if ((fileName         == NULL)    ||
300 299 storres
      (linesCountPtr    == NULL)  ||
301 299 storres
      (maxLineLengthPtr == NULL))
302 299 storres
  {
303 299 storres
    #ifndef NDEBUG
304 299 storres
    if (fileName == NULL)
305 299 storres
    {
306 299 storres
      fprintf(stderr,
307 299 storres
              "\n%s: \"fileName\" is a NULL pointer.\n",
308 299 storres
              __func__);
309 299 storres
    }
310 299 storres
    if (linesCountPtr == NULL)
311 299 storres
    {
312 299 storres
      fprintf(stderr,
313 299 storres
              "\n%s: \"linesCountPtr\" is a NULL pointer.\n",
314 299 storres
              __func__);
315 299 storres
    }
316 299 storres
    if (maxLineLengthPtr == NULL)
317 299 storres
    {
318 299 storres
      fprintf(stderr,
319 299 storres
              "\n%s: \"maxLineLengthPtr\" is a NULL pointer.\n",
320 299 storres
              __func__);
321 299 storres
    }
322 299 storres
    #endif
323 299 storres
    return 1;
324 299 storres
  } /* End arguments check. */
325 299 storres
326 299 storres
  /* Open file and deal with errors. */
327 299 storres
  linesFileHandle = fopen(fileName, "r");
328 299 storres
  if (linesFileHandle == NULL)
329 299 storres
  {
330 299 storres
    fprintf(stderr,
331 299 storres
            "\n%s: could not open file %s.\n",
332 299 storres
            __func__,
333 299 storres
            fileName);
334 299 storres
    return 1;
335 299 storres
  }
336 299 storres
  *linesCountPtr      = 0;
337 299 storres
  *maxLineLengthPtr   = 0;
338 299 storres
  /* Scan the file. */
339 299 storres
  returnValue = rlff_scout_file_from_handle(linesFileHandle,
340 299 storres
                                            linesCountPtr,
341 299 storres
                                            maxLineLengthPtr);
342 299 storres
  fclose(linesFileHandle);
343 299 storres
  return returnValue;
344 299 storres
} /* End rlff_scout_file_from_name. */
345 299 storres
346 299 storres
int
347 299 storres
rlff_scout_file_from_handle(FILE* fileHandle,
348 299 storres
                            unsigned int* linesCountPtr,
349 299 storres
                            unsigned int* maxLineLengthPtr)
350 299 storres
{
351 299 storres
  char c                        = '\0';
352 299 storres
  unsigned int charsCount       = 0;
353 299 storres
  /* Arguments check. */
354 299 storres
  if ((fileHandle       == NULL)  ||
355 299 storres
      (linesCountPtr    == NULL)  ||
356 299 storres
      (maxLineLengthPtr == NULL))
357 299 storres
  {
358 299 storres
    #ifndef NDEBUG
359 299 storres
    if (fileHandle == NULL)
360 299 storres
    {
361 299 storres
      fprintf(stderr,
362 299 storres
              "\n%s: \"fileHandle\" is a NULL pointer.\n",
363 299 storres
              __func__);
364 299 storres
    }
365 299 storres
    if (linesCountPtr == NULL)
366 299 storres
    {
367 299 storres
      fprintf(stderr,
368 299 storres
              "\n%s: \"linesCountPtr\" is a NULL pointer.\n",
369 299 storres
              __func__);
370 299 storres
    }
371 299 storres
    if (maxLineLengthPtr == NULL)
372 299 storres
    {
373 299 storres
      fprintf(stderr,
374 299 storres
              "\n%s: \"maxLineLengthPtr\" is a NULL pointer.\n",
375 299 storres
              __func__);
376 299 storres
    }
377 299 storres
    #endif
378 299 storres
    return 1;
379 299 storres
  } /* End arguments check. */
380 299 storres
381 299 storres
  *linesCountPtr      = 0;
382 299 storres
  *maxLineLengthPtr   = 0;
383 299 storres
  /* Scan the file. */
384 299 storres
  while((c = fgetc(fileHandle)) != EOF)
385 299 storres
  {
386 299 storres
    (*linesCountPtr)++;
387 299 storres
    charsCount++;
388 299 storres
    while((c == ' ') || (c == '\t'))
389 299 storres
    {
390 299 storres
      c = fgetc(fileHandle);
391 299 storres
      if (c == EOF)
392 299 storres
      {
393 299 storres
        (*linesCountPtr)--;
394 299 storres
        return 0;
395 299 storres
      }
396 299 storres
    } /* End while */
397 299 storres
    /* A line of spaces. */
398 299 storres
    if (c == '\n')
399 299 storres
    {
400 299 storres
      (*linesCountPtr)--;
401 299 storres
      charsCount = 0;
402 299 storres
      continue;
403 299 storres
    }
404 299 storres
    /* First character after spaces is '#'.  Read the comment
405 299 storres
     * to the end of the line or of the file. */
406 299 storres
    if (c == '#')
407 299 storres
    {
408 299 storres
      (*linesCountPtr)--;
409 299 storres
      charsCount = 0;
410 299 storres
      while(((c = fgetc(fileHandle)) != EOF) && (c != '\n')) {}
411 299 storres
      if (c == '\n')
412 299 storres
      {
413 299 storres
        continue;
414 299 storres
      }
415 299 storres
      else /* c == EOF */
416 299 storres
      {
417 299 storres
        break;
418 299 storres
      }
419 299 storres
    } /* End c == '#'. */
420 299 storres
    while(((c = fgetc(fileHandle)) != EOF) && (c != '\n'))
421 299 storres
    {
422 299 storres
      charsCount++;
423 299 storres
    }
424 299 storres
    if (c == EOF)
425 299 storres
    {
426 299 storres
      /* Allow for space of the terminal '\0'. */
427 299 storres
      if (charsCount + 1 > *maxLineLengthPtr)
428 299 storres
      {
429 299 storres
        (*maxLineLengthPtr) = charsCount + 1;
430 299 storres
      }
431 299 storres
      break;
432 299 storres
    } /* End c == EOF. */
433 299 storres
    if (c == '\n')
434 299 storres
    {
435 299 storres
      /* Allow for space of the terminal '\0'. */
436 299 storres
      if (charsCount + 1 > *maxLineLengthPtr)
437 299 storres
      {
438 299 storres
        (*maxLineLengthPtr) = charsCount + 1;
439 299 storres
      }
440 299 storres
      charsCount = 0;
441 299 storres
    } /* End c == '\n'. */
442 299 storres
  } /* End while. */
443 299 storres
  return 0;
444 299 storres
} /* End rlff_scout_file_from_handle. */