GCS  0.2.3
gu_str.h
1 /*
2  * Copyright (C) 2010 Codership Oy <info@codership.com>
3  */
4 
5 #ifndef GU_STR_H
6 #define GU_STR_H
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
12 
16 static inline char* gu_str_append(char* str, size_t* off,
17  const char* app, size_t app_len)
18 {
19  char* tmp;
20  assert(str == NULL || *(str + *off - 1) == '\0');
21  tmp = realloc(str, *off + app_len + 1);
22  if (tmp != NULL)
23  {
24  memcpy(tmp + *off, app, app_len + 1);
25  *off += app_len + 1;
26  }
27  return tmp;
28 }
29 
33 static inline const char* gu_str_next(const char* str)
34 {
35  return strchr(str, '\0') + 1;
36 }
37 
41 static inline const char* gu_str_advance(const char* str, size_t n)
42 {
43  const char* ptr = str;
44  while (n-- > 0)
45  {
46  ptr = gu_str_next(ptr);
47  }
48  return ptr;
49 }
50 
51 
52 /*
53  * Utilities to construct and scan tables from null terminated strings.
54  * The table format is the following:
55  *
56  * name\0\columns\0\rows\0
57  * colname0\0colname1\0...
58  * elem00\0elem01\0elem02\0...
59  * elem10\0elem11\0elem\12\...
60  * .
61  * .
62  * .
63  */
64 
65 
66 static inline char* gu_str_table_set_name(char* str, size_t* off, const char* name)
67 {
68  return gu_str_append(str, off, name, strlen(name));
69 }
70 
71 static inline const char* gu_str_table_get_name(const char* str)
72 {
73  return str;
74 }
75 
76 static inline char* gu_str_table_append_size(char* str, size_t* off, size_t n)
77 {
78  char buf[10];
79  size_t len = snprintf(buf, sizeof(buf), "%zu", n);
80  return gu_str_append(str, off, buf, len);
81 }
82 
83 static inline char* gu_str_table_set_n_cols(char* str, size_t* off, size_t n)
84 {
85  return gu_str_table_append_size(str, off, n);
86 }
87 
88 static inline size_t gu_str_table_get_n_cols(const char* str)
89 {
90  str = gu_str_advance(str, 1);
91  return strtoul(str, NULL, 0);
92 }
93 
94 static inline char* gu_str_table_set_n_rows(char* str, size_t* off, size_t n)
95 {
96  return gu_str_table_append_size(str, off, n);
97 }
98 
99 static inline size_t gu_str_table_get_n_rows(const char* str)
100 {
101  str = gu_str_advance(str, 2);
102  return strtoul(str, NULL, 0);
103 }
104 
105 
106 static inline char* gu_str_table_set_cols(char* str,
107  size_t *off,
108  size_t n,
109  const char* cols[])
110 {
111  size_t i;
112  for (i = 0; i < n; ++i)
113  {
114  str = gu_str_append(str, off, cols[i], strlen(cols[i]));
115  }
116  return str;
117 }
118 
119 static inline char* gu_str_table_append_row(char* str,
120  size_t *off,
121  size_t n,
122  const char* row[])
123 {
124  size_t i;
125  for (i = 0; i < n; ++i)
126  {
127  str = gu_str_append(str, off, row[i], strlen(row[i]));
128  }
129  return str;
130 }
131 
132 
133 static inline const char* gu_str_table_get_cols(const char* str, size_t n,
134  char const* row[])
135 {
136  size_t i;
137  str = gu_str_advance(str, 3);
138  for (i = 0; i < n; i++)
139  {
140  row[i] = str;
141  str = gu_str_next(str);
142  }
143  return str;
144 }
145 
146 
147 static inline const char* gu_str_table_rows_begin(const char* str, size_t n)
148 {
149  return gu_str_advance(str, 3 + n);
150 }
151 
152 static inline const char* gu_str_table_row_get(const char* str,
153  size_t n,
154  char const* row[])
155 {
156  size_t i;
157  for (i = 0; i < n; ++i)
158  {
159  row[i] = str;
160  str = gu_str_next(str);
161  }
162  return str;
163 }
164 
165 static inline void gu_str_table_print_row(FILE* file, size_t n,
166  const char* const row[])
167 {
168  size_t i;
169  for (i = 0; i < n; ++i)
170  {
171  fprintf(file, "%s ", row[i]);
172  }
173  fprintf(file, "\n");
174 }
175 
176 static inline void gu_str_table_print(FILE* file, const char* str)
177 {
178  size_t i;
179  size_t n_cols, n_rows;
180  const char* ptr;
181  char const**vec;
182  fprintf(file, "%s\n", gu_str_table_get_name(str));
183  n_cols = gu_str_table_get_n_cols(str);
184  n_rows = gu_str_table_get_n_rows(str);
185 
186  vec = malloc(n_cols*sizeof(char*));
187  ptr = gu_str_table_get_cols(str, n_cols, vec);
188  gu_str_table_print_row(file, n_cols, vec);
189  for (i = 0; i < n_rows; ++i)
190  {
191  ptr = gu_str_table_row_get(ptr, n_cols, vec);
192  gu_str_table_print_row(file, n_cols, vec);
193  }
194  free(vec);
195 }
196 
197 
198 #endif /* GU_STR_H */