APPFS
Advanced practical programming for scientists
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
splitline.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <assert.h>
9 #include <stdbool.h>
10 #include <string.h>
11 #include <ctype.h>
12 
13 #include "mshell.h"
14 #include "splitline.h"
15 
17 {
18  int size;
19  int used;
20  char* line;
21  char** field;
22 };
23 
24 #define LFS_INITIAL_SIZE 100
25 
26 static bool is_valid(const LFS* lfs)
27 {
28  if (NULL == lfs || NULL == lfs->line || NULL == lfs->field)
29  return false;
30  if (lfs->size < LFS_INITIAL_SIZE || lfs->size < lfs->used || lfs->used < 0)
31  return false;
32  return true;
33 }
34 
35 void lfs_free(LFS* lfs)
36 {
37  assert(is_valid(lfs));
38 
39  free(lfs->line);
40  free(lfs->field);
41  free(lfs);
42 }
43 
44 LFS* lfs_split_line(LFS* lfs, const char* line, const char* comment)
45 {
46  assert(NULL != line);
47  assert(NULL != comment);
48 
49  if (NULL == lfs)
50  {
51  lfs = calloc(1, sizeof(*lfs));
52  lfs->size = LFS_INITIAL_SIZE;
53  lfs->field = calloc((size_t)lfs->size, sizeof(*lfs->field));
54  }
55  else
56  {
57  assert(is_valid(lfs));
58 
59  lfs->used = 0;
60 
61  free(lfs->line);
62  }
63  lfs->line = strdup(line); // strdup = strcpy(malloc(strlen(s)), s);
64 
65  char* s = strpbrk(lfs->line, comment);
66 
67  if (NULL != s) /* else line is not terminated or too long */
68  *s = '\0'; /* clip comment */
69 
70  /* Check for garbage characters, this includes "\n", "\r"
71  */
72  for(s = lfs->line; *s != '\0'; s++)
73  if (!isprint(*s))
74  *s = ' ';
75 
76  s = lfs->line;
77 
78  while(isspace(*s))
79  s++;
80 
81  while(*s != '\0')
82  {
83  assert(lfs->used <= lfs->size);
84 
85  if (lfs->used == lfs->size)
86  lfs->field = realloc(lfs->field, sizeof(*lfs->field) * (lfs->size *= 2)); // good idea to write like this?
87 
88  assert(!isspace(*s));
89 
90  lfs->field[lfs->used] = s;
91  lfs->used++;
92 
93  while(*s != '\0' && !isspace(*s))
94  s++;
95 
96  if (*s == '\0')
97  continue;
98 
99  *s++ = '\0';
100 
101  //printf("field[%d]=\"%s\"\n", lfs->used - 1, lfs->field[lfs->used - 1]);
102 
103  while(isspace(*s))
104  s++;
105  }
106  return lfs;
107 }
108 
109 int lfs_used_fields(const LFS* lfs)
110 {
111  assert(is_valid(lfs));
112 
113  return lfs->used;
114 }
115 
116 const char* lfs_get_field(const LFS* lfs, int fno)
117 {
118  assert(is_valid(lfs));
119 
120  /* Design decision:
121  */
122  assert(fno >= 0);
123  assert(fno < lfs->used);
124 
125  /* The above could be dependend on the input.
126  * we have to make sure it is not.
127  * otherwise:
128  * if (fno >= lfs->used) return NULL
129  * problem: we always have to check.
130  * Design by contract
131  */
132  return lfs->field[fno];
133 }
134 
135 void lfs_print(const LFS* lfs, FILE* fp)
136 {
137  assert(is_valid(lfs));
138  assert(NULL != fp);
139 
140  for(int i = 0; i < lfs->used; i++)
141  fprintf(fp, "Field %3d: \"%s\"\n", i, lfs->field[i]);
142 }
static bool is_valid(const LFS *lfs)
Definition: splitline.c:26
#define strdup(a)
Definition: mshell.h:56
Split line into fields Header.
char ** field
Definition: splitline.c:21
const char * lfs_get_field(const LFS *lfs, int fno)
Definition: splitline.c:116
void lfs_free(LFS *lfs)
Definition: splitline.c:35
#define LFS_INITIAL_SIZE
Definition: splitline.c:24
void lfs_print(const LFS *lfs, FILE *fp)
Definition: splitline.c:135
int lfs_used_fields(const LFS *lfs)
Definition: splitline.c:109
#define calloc(a, b)
Definition: mshell.h:54
#define realloc(a, b)
Definition: mshell.h:55
char * line
Definition: splitline.c:20
LFS * lfs_split_line(LFS *lfs, const char *line, const char *comment)
Definition: splitline.c:44
#define free(a)
Definition: mshell.h:57