PandA-2024.02
support.c
Go to the documentation of this file.
1 #include "support.h"
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <assert.h>
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <fcntl.h>
10 #include <sys/stat.h>
11 
12 // In general, fd_printf is used for individual values.
13 #define SUFFICIENT_SPRINTF_SPACE 256
14 // It'd be nice if dprintf was c99. But it ain't.
15 static inline int fd_printf(int fd, const char *format, ...) {
16  va_list args;
17  int buffered, written, status;
18  char buffer[SUFFICIENT_SPRINTF_SPACE];
19  va_start(args, format);
20  buffered = vsnprintf(buffer, SUFFICIENT_SPRINTF_SPACE, format, args);
21  va_end(args);
22  assert(buffered<SUFFICIENT_SPRINTF_SPACE && "Overran fd_printf buffer---output possibly corrupt");
23  written = 0;
24  while(written<buffered) {
25  status = write(fd, &buffer[written], buffered-written);
26  assert(status>=0 && "Write failed");
27  written += status;
28  }
29  assert(written==buffered && "Wrote more data than given");
30  return written;
31 }
32 
34 char *readfile(int fd) {
35  char *p;
36  struct stat s;
37  off_t len;
38  ssize_t bytes_read, status;
39 
40  assert(fd>1 && "Invalid file descriptor");
41  assert(0==fstat(fd, &s) && "Couldn't determine file size");
42  len = s.st_size;
43  assert(len>0 && "File is empty");
44  p = (char *)malloc(len+1);
45  bytes_read = 0;
46  while( bytes_read<len ) {
47  status = read(fd, &p[bytes_read], len-bytes_read);
48  assert(status>=0 && "read() failed");
49  bytes_read+=status;
50  }
51  p[len] = (char)0; // Add NULL terminator
52  close(fd);
53  return p;
54 }
55 
56 char *find_section_start(char *s, int n) {
57  int i=0;
58 
59  assert(n>=0 && "Invalid section number");
60  if(n==0)
61  return s;
62 
63  // Find the nth "%%\n" substring (if *s==0, there wasn't one)
64  while(i<n && (*s)!=(char)0) {
65  // This comparison will short-circuit before overrunning the string, so no length check.
66  if( s[0]=='%' && s[1]=='%' && s[2]=='\n' ) {
67  i++;
68  }
69  s++;
70  }
71  if(*s!=(char)0)
72  return s+2; // Skip the section header itself, return pointer to the content
73  return s; // Hit the end, return an empty string
74 }
75 
77 int parse_string(char *s, char *arr, int n) {
78  int k;
79  assert(s!=NULL && "Invalid input string");
80 
81  if( n<0 ) { // terminated string
82  k = 0;
83  while( s[k]!=(char)0 && s[k+1]!=(char)0 && s[k+2]!=(char)0
84  && !(s[k]=='\n' && s[k+1]=='%' && s[k+2]=='%') ) {
85  k++;
86  }
87  } else { // fixed-length string
88  k = n;
89  }
90 
91  memcpy( arr, s, k );
92  if( n<0 )
93  arr[k] = 0;
94 
95  return 0;
96 }
97 
98 #define generate_parse_TYPE_array(TYPE, STRTOTYPE) \
99 int parse_##TYPE##_array(char *s, TYPE *arr, int n) { \
100  char *line, *endptr; \
101  int i=0; \
102  TYPE v; \
103  \
104  assert(s!=NULL && "Invalid input string"); \
105  \
106  line = strtok(s,"\n"); \
107  while( line!=NULL && i<n ) { \
108  endptr = line; \
109  /*errno=0;*/ \
110  v = (TYPE)(STRTOTYPE(line, &endptr)); \
111  if( (*endptr)!=(char)0 ) { \
112  fprintf(stderr, "Invalid input: line %d of section\n", i); \
113  } \
114  /*assert((*endptr)==(char)0 && "Invalid input character"); */\
115  /*if( errno!=0 ) { \
116  fprintf(stderr, "Couldn't convert string \"%s\": line %d of section\n", line, i); \
117  }*/ \
118  /*assert(errno==0 && "Couldn't convert the string"); */\
119  arr[i] = v; \
120  i++; \
121  line[strlen(line)] = '\n'; /* Undo the strtok replacement.*/ \
122  line = strtok(NULL,"\n"); \
123  } \
124  if(line!=NULL) { /* stopped because we read all the things */ \
125  line[strlen(line)] = '\n'; /* Undo the strtok replacement.*/ \
126  } \
127  \
128  return 0; \
129 }
130 
131 #define strtol_10(a,b) strtol(a,b,10)
140 
141 generate_parse_TYPE_array(float, strtof)
142 generate_parse_TYPE_array(double, strtod)
143 
144 int write_string(int fd, char *arr, int n) {
146  int status, written;
147  assert(fd>1 && "Invalid file descriptor");
148  if( n<0 ) { // NULL-terminated string
149  n = strlen(arr);
150  }
151  written = 0;
152  while(written<n) {
153  status = write(fd, &arr[written], n-written);
154  assert(status>=0 && "Write failed");
155  written += status;
156  }
157  // Write terminating '\n'
158  do {
159  status = write(fd, "\n", 1);
160  assert(status>=0 && "Write failed");
161  } while(status==0);
162 
163  return 0;
164 }
165 
166 // Not strictly necessary, but nice for future-proofing.
167 #define generate_write_TYPE_array(TYPE, FORMAT) \
168 int write_##TYPE##_array(int fd, TYPE *arr, int n) { \
169  int i; \
170  assert(fd>1 && "Invalid file descriptor"); \
171  for( i=0; i<n; i++ ) { \
172  fd_printf(fd, "%" FORMAT "\n", arr[i]); \
173  } \
174  return 0; \
175 }
176 
178 generate_write_TYPE_array(uint16_t, PRIu16)
179 generate_write_TYPE_array(uint32_t, PRIu32)
180 generate_write_TYPE_array(uint64_t, PRIu64)
181 generate_write_TYPE_array(int8_t, PRId8)
182 generate_write_TYPE_array(int16_t, PRId16)
183 generate_write_TYPE_array(int32_t, PRId32)
184 generate_write_TYPE_array(int64_t, PRId64)
185 
186 generate_write_TYPE_array(float, ".16f")
187 generate_write_TYPE_array(double, ".16f")
188 
189 int write_section_header(int fd) {
190  assert(fd>1 && "Invalid file descriptor");
191  fd_printf(fd, "%%%%\n"); // Just prints %%
192  return 0;
193 }
#define generate_parse_TYPE_array(TYPE, STRTOTYPE)
Definition: support.c:98
#define NULL
#define strtol_10(a, b)
Definition: support.c:131
#define SUFFICIENT_SPRINTF_SPACE
Definition: support.c:13
#define generate_write_TYPE_array(TYPE, FORMAT)
Definition: support.c:167
int parse_string(char *s, char *arr, int n)
Definition: support.c:77
static const uint32_t k[]
Definition: sha-256.c:22
int write_string(int fd, char *arr, int n)
int write_section_header(int fd)
char * readfile(int fd)
Definition: support.c:34
char * find_section_start(char *s, int n)
Definition: support.c:56
static int fd_printf(int fd, const char *format,...)
Definition: support.c:15
short int read(short int *data)
Definition: read.c:3

Generated on Mon Feb 12 2024 13:02:49 for PandA-2024.02 by doxygen 1.8.13