Statistiques
| Révision :

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

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

1
/** @file read-lines-from-file.c */
2
/******************************************************************************/
3
/**
4
 * Read lines from a text file, filtering out empty, #-comment lines,
5
 * leading spaces and tab, trailing comments.
6
 * 
7
 * @author: ST
8
 * @date: 2016-10-21
9
 *
10
 */
11

    
12
/* Includes according to the "general to particular" rule. */
13
/* includes of system headers */
14
#include <stdlib.h>
15
#include <stdio.h>
16
#include <libgen.h>
17

    
18
/* includes of project headers */
19

    
20
/* includes of local headers */
21
#include <read-lines-from-file.h>
22

    
23
/* Types, constants and macros definitions */
24

    
25
/* Global variables */
26

    
27
/* Functions */
28

    
29
/** Scout the file for lines count and maximum lines length.
30
 * The file is specified by its name.
31
 * The data are returned through pointer arguments.
32
 * @param fileName (in);
33
 * @param linesCountPtr (in/out);
34
 * @param maxLineLengthPtr (in/out);
35
 * @return 0 if OK and != 0 if something goes wrong. */
36

    
37
int
38
rlff_scout_file_from_name(char* fileName,
39
                          unsigned int* linesCountPtr,
40
                          unsigned int* maxLineLengthPtr);
41

    
42
/** Scout the file for lines count and maximum lines length.
43
 * The file is specified by a handle open on it in "read" mode (at least).
44
 * The data are returned through pointer arguments.
45
 * @param fileHandle (in);
46
 * @param linesCountPtr (in/out);
47
 * @param maxLineLengthPtr (in/out);
48
* @return 0 if OK and != 0 if something goes wrong. */
49

    
50
int
51
rlff_scout_file_from_handle(FILE* fileHandle,
52
                            unsigned int* linesCountPtr,
53
                            unsigned int* maxLineLengthPtr);
54

    
55
/** Dealloc a readLines struct that has been initialized (even partly)
56
 * @see read-lines-from-file.h#rlff_free_lines.*/
57
void 
58
rlff_free_lines(rlff_readLines_t* linesRead)
59
{
60
  if (linesRead == NULL) { return; }
61
  if (linesRead->lines == NULL) { return; }
62
  free(linesRead->lines);
63
  free(linesRead);
64
} /* End free_lines. */
65

    
66
/** @see read-lines-from-file.h#rlff_get_line_at. */ 
67
char*
68
rlff_get_line_at(rlff_readLines_t* linesRead, unsigned int lineIndex)
69
{
70
  if (linesRead == NULL)
71
  {
72
    #ifndef NDEBUG
73
    fprintf(stderr,
74
            "\n%s: linesRead is a NULL pointer.\n",
75
            __func__);
76
    #endif
77
    return NULL;
78
  }
79
  if (lineIndex > (linesRead->linesNum -1))
80
  {
81
    #ifndef NDEBUG
82
    fprintf(stderr,
83
            "\n%s: requested line inted (%d) is beyhond\n",
84
            __func__,
85
            lineIndex);
86
    fprintf(stderr,
87
            "maximum index (%d).\n",
88
            linesRead->linesNum -1);
89
    #endif
90
    return NULL;
91
  }
92
  return linesRead->lines + lineIndex * linesRead->linesLenght;
93
} /* End rlff_get_line_at. */
94

    
95
/** @see read-lines-from-file.h#rlff_print_lines */
96
void
97
  rlff_print_lines(rlff_readLines_t* linesRead)
98
{
99
  unsigned int i = 0;
100
  if (linesRead == NULL) { return; }
101
  for (i = 0 ; i < linesRead->linesNum ; i++)
102
  {
103
    fprintf(stdout,
104
            "%s\n",
105
            rlff_get_line_at(linesRead, i));
106
  }
107
} /* End rlff_print_lines. */
108

    
109
/** @see read-lines-from-file.h#rlff_read_lines_from file_name */
110
rlff_readLines_t*
111
rlff_read_lines_from_file_name(char* fileName)
112
{
113
  FILE* linesFile               = NULL;
114

    
115
  /* Current character position in read file. Starts at 0. */
116
  rlff_readLines_t* linesRead   = NULL;
117
  
118
  /* Argument check. */
119
  if (fileName == NULL)
120
  {
121
    #ifndef NDEBUG
122
    fprintf(stderr,
123
            "\n%s: fileName is a NULL pointer.\n",
124
            __func__);
125
    #endif
126
    return NULL;
127
  }
128
  /* Try to open the file in read-only mode. */
129
  linesFile = fopen(fileName, "r");
130
  if (linesFile == NULL) 
131
  {
132
    #ifndef NDEBUG
133
    fprintf(stderr, 
134
            "\n%s: could not open file %s.\n",
135
            __func__,
136
            fileName);
137
    #endif
138
    return NULL;
139
  }
140
  linesRead = rlff_read_lines_from_file_handle(linesFile);
141
  fclose(linesFile);
142
  return linesRead;
143
} /* End rlff_read_lines_from_file_name. */
144

    
145
/** @see read-lines-from-file.h#rlff_read_lines_from file_handle */
146
rlff_readLines_t*
147
rlff_read_lines_from_file_handle(FILE* fileHandle)
148
{
149
  char c                        = '\0';
150
  char* bufferCurrentLinePtr    = NULL;
151
  char* bufferCurrentCharPtr    = NULL;
152
  /* Current character position in read file. Starts at 0. */
153
  rlff_readLines_t* linesRead   = NULL;
154
  unsigned int rlffLinesCount   = 0;
155
  unsigned int rlffLinesLength  = 0;
156

    
157
  /* Argument check. */
158
  if (fileHandle == NULL)
159
  {
160
    #ifndef NDEBUG
161
    fprintf(stderr,
162
            "\n%s: fileHandle is a NULL pointer.\n",
163
            __func__);
164
    #endif
165
    return NULL;
166
  }
167
  /* Get the file data. */
168
  if (rlff_scout_file_from_handle(fileHandle,
169
                                  &rlffLinesCount,
170
                                  &rlffLinesLength))
171
  {
172
    #ifndef NDEBUG
173
    fprintf(stderr,
174
            "\n%s: could not scout the file.\n",
175
            __func__);
176
    #endif
177
    return NULL;
178
  }
179
  /* Try to allocate the pointer returned structure. */
180
  linesRead = malloc(sizeof(rlff_readLines_t));
181
  if (linesRead == NULL)
182
  {
183
    #ifndef NDEBUG
184
    fprintf(stderr,
185
            "\n%s: could not alloc memory for the rlff_readLines_t.\n",
186
            __func__);
187
    #endif
188
    return NULL;
189
  }
190

    
191
  linesRead->linesNum     = rlffLinesCount;
192
  linesRead->linesLenght  = rlffLinesLength;
193
  if ((rlffLinesCount == 0) || (rlffLinesLength == 0))
194
  {
195
    /* The file is somehow empty: not an actual error. */
196
    linesRead->linesNum     = 0;
197
    linesRead->linesLenght  = 0;
198
    linesRead->lines        = NULL;
199
    return linesRead;
200
  }
201
  /* Try to allocate the lines buffer. */
202
  linesRead->lines =
203
      malloc(rlffLinesCount * rlffLinesLength * sizeof(char));
204
  if (linesRead->lines == NULL)
205
  {
206
    #ifndef NDEBUG
207
    fprintf(stderr,
208
            "\n%s: could not alloc memory for the lines buffer.\n",
209
            __func__);
210
    #endif
211
    free(linesRead);
212
    return NULL;
213
  }
214
  bufferCurrentLinePtr = linesRead->lines;
215
  bufferCurrentCharPtr = bufferCurrentLinePtr;
216
  /* Get the chars of the file. */
217
  while ((c = fgetc(fileHandle)) != EOF)
218
  {
219
    /* Skipping initial spaces. */
220
    while((c == ' ') || (c == '\t'))
221
    {
222
      c = fgetc(fileHandle);
223
      if (c == EOF)
224
      {
225
        return linesRead;
226
      }
227
    } /* End while */
228
    /* A line of spaces or an empty line. */
229
    if (c == '\n')
230
    {
231
      continue;
232
    }
233
    /* First character afer spaces is '#'.  Read the comment
234
     * to the end of the line or of the file. */
235
    if (c == '#')
236
    {
237
      while(((c = fgetc(fileHandle)) != EOF) && (c != '\n')) {}
238
      if (c == '\n')
239
      {
240
        continue;
241
      }
242
      else /* c == EOF */
243
      {
244
        return linesRead;
245
      }
246
    } /* End c == '#'. */
247
    *bufferCurrentCharPtr = c;
248
    bufferCurrentCharPtr++;
249
    /* A line with usefull content. */
250
    while(((c = fgetc(fileHandle)) != EOF) && (c != '\n') && (c != '#'))
251
    {
252
      *bufferCurrentCharPtr = c;
253
      bufferCurrentCharPtr++;
254
    }
255
    if (c == '#')
256
    {
257
      while(((c = fgetc(fileHandle)) != EOF) && (c != '\n')) {}
258
    }
259
    if (c == EOF)
260
    {
261
        return linesRead;
262
    } /* End c == EOF. */
263
    /* End of a line with useful content. */
264
    /* At the end of a useful lines. */
265
    if (c == '\n')
266
    {
267
      *bufferCurrentCharPtr = '\0';
268
      /* Delete trailing spaces. */
269
      while (bufferCurrentCharPtr > bufferCurrentLinePtr)
270
      {
271
        bufferCurrentCharPtr--;
272
        if ((*bufferCurrentCharPtr == ' ') ||
273
            (*bufferCurrentCharPtr == '\t'))
274
        {
275
          *bufferCurrentCharPtr = '\0';
276
        }
277
        else
278
        {
279
          break;
280
        }
281
      } /* End while. */
282
      bufferCurrentLinePtr += linesRead->linesLenght;
283
      bufferCurrentCharPtr = bufferCurrentLinePtr;
284
    } /* End c == '\n'. */
285
  } /* End main while; ancillary*/
286
  /* Normal reading exit. */
287
  return linesRead;
288
} /* End rlff_read_lines_from_file_handle. */
289

    
290
int
291
rlff_scout_file_from_name(char* fileName,
292
                          unsigned int* linesCountPtr,
293
                          unsigned int* maxLineLengthPtr)
294
{
295
  FILE* linesFileHandle         = NULL;
296
  int returnValue               = 0;
297

    
298
  /* Arguments check. */
299
  if ((fileName         == NULL)    || 
300
      (linesCountPtr    == NULL)  ||
301
      (maxLineLengthPtr == NULL))
302
  {
303
    #ifndef NDEBUG
304
    if (fileName == NULL)
305
    {
306
      fprintf(stderr,
307
              "\n%s: \"fileName\" is a NULL pointer.\n",
308
              __func__);
309
    }
310
    if (linesCountPtr == NULL)
311
    {
312
      fprintf(stderr,
313
              "\n%s: \"linesCountPtr\" is a NULL pointer.\n",
314
              __func__);
315
    }
316
    if (maxLineLengthPtr == NULL)
317
    {
318
      fprintf(stderr,
319
              "\n%s: \"maxLineLengthPtr\" is a NULL pointer.\n",
320
              __func__);
321
    }
322
    #endif
323
    return 1;
324
  } /* End arguments check. */
325
  
326
  /* Open file and deal with errors. */
327
  linesFileHandle = fopen(fileName, "r");
328
  if (linesFileHandle == NULL)
329
  {
330
    fprintf(stderr, 
331
            "\n%s: could not open file %s.\n",
332
            __func__,
333
            fileName);
334
    return 1;
335
  }
336
  *linesCountPtr      = 0;
337
  *maxLineLengthPtr   = 0;
338
  /* Scan the file. */
339
  returnValue = rlff_scout_file_from_handle(linesFileHandle,
340
                                            linesCountPtr,
341
                                            maxLineLengthPtr);
342
  fclose(linesFileHandle);
343
  return returnValue;
344
} /* End rlff_scout_file_from_name. */
345

    
346
int
347
rlff_scout_file_from_handle(FILE* fileHandle,
348
                            unsigned int* linesCountPtr,
349
                            unsigned int* maxLineLengthPtr)
350
{
351
  char c                        = '\0';
352
  unsigned int charsCount       = 0;
353
  /* Arguments check. */
354
  if ((fileHandle       == NULL)  ||
355
      (linesCountPtr    == NULL)  ||
356
      (maxLineLengthPtr == NULL))
357
  {
358
    #ifndef NDEBUG
359
    if (fileHandle == NULL)
360
    {
361
      fprintf(stderr,
362
              "\n%s: \"fileHandle\" is a NULL pointer.\n",
363
              __func__);
364
    }
365
    if (linesCountPtr == NULL)
366
    {
367
      fprintf(stderr,
368
              "\n%s: \"linesCountPtr\" is a NULL pointer.\n",
369
              __func__);
370
    }
371
    if (maxLineLengthPtr == NULL)
372
    {
373
      fprintf(stderr,
374
              "\n%s: \"maxLineLengthPtr\" is a NULL pointer.\n",
375
              __func__);
376
    }
377
    #endif
378
    return 1;
379
  } /* End arguments check. */
380

    
381
  *linesCountPtr      = 0;
382
  *maxLineLengthPtr   = 0;
383
  /* Scan the file. */
384
  while((c = fgetc(fileHandle)) != EOF)
385
  {
386
    (*linesCountPtr)++;
387
    charsCount++;
388
    while((c == ' ') || (c == '\t'))
389
    {
390
      c = fgetc(fileHandle);
391
      if (c == EOF)
392
      {
393
        (*linesCountPtr)--;
394
        return 0;
395
      }
396
    } /* End while */
397
    /* A line of spaces. */
398
    if (c == '\n')
399
    {
400
      (*linesCountPtr)--;
401
      charsCount = 0;
402
      continue;
403
    }
404
    /* First character after spaces is '#'.  Read the comment
405
     * to the end of the line or of the file. */
406
    if (c == '#')
407
    {
408
      (*linesCountPtr)--;
409
      charsCount = 0;
410
      while(((c = fgetc(fileHandle)) != EOF) && (c != '\n')) {}
411
      if (c == '\n')
412
      {
413
        continue;
414
      }
415
      else /* c == EOF */
416
      {
417
        break;
418
      }
419
    } /* End c == '#'. */
420
    while(((c = fgetc(fileHandle)) != EOF) && (c != '\n'))
421
    {
422
      charsCount++;
423
    }
424
    if (c == EOF)
425
    {
426
      /* Allow for space of the terminal '\0'. */
427
      if (charsCount + 1 > *maxLineLengthPtr)
428
      {
429
        (*maxLineLengthPtr) = charsCount + 1;
430
      }
431
      break;
432
    } /* End c == EOF. */
433
    if (c == '\n')
434
    {
435
      /* Allow for space of the terminal '\0'. */
436
      if (charsCount + 1 > *maxLineLengthPtr)
437
      {
438
        (*maxLineLengthPtr) = charsCount + 1;
439
      }
440
      charsCount = 0;
441
    } /* End c == '\n'. */
442
  } /* End while. */
443
  return 0;
444
} /* End rlff_scout_file_from_handle. */