sd_stdio_c_iface.cpp File Reference
#include "sd_stdio_c_iface.h"
#include <SD.h>

Description

This code contains implementations for stdio.h file functions using Arduino SD File libraries.

Author
Scott Fazackerley

Since the Arduino library doesn't have definitions for standard I/O file functions, we have to write our own.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1.Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2.Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3.Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Definition in file sd_stdio_c_iface.cpp.

Include dependency graph for sd_stdio_c_iface.cpp:

Classes

struct  _SD_File
 A structure that translates a file object to a C-compatible struct. More...
 

Functions

int sd_fclose (SD_FILE *stream)
 
int sd_feof (SD_FILE *stream)
 
int sd_fflush (SD_FILE *stream)
 
int sd_fsetpos (SD_FILE *stream, ion_fpos_t *pos)
 
int sd_fgetpos (SD_FILE *stream, ion_fpos_t *pos)
 
SD_FILE * sd_fopen (char *filename, char *mode)
 
size_t sd_fread (void *ptr, size_t size, size_t nmemb, SD_FILE *stream)
 
int sd_fseek (SD_FILE *stream, long int offset, int whence)
 
long int sd_ftell (SD_FILE *stream)
 
size_t sd_fwrite (void *ptr, size_t size, size_t nmemb, SD_FILE *stream)
 
int sd_remove (char *filename)
 
void sd_rewind (SD_FILE *stream)
 
int SD_File_Begin (uint8_t csPin)
 
void sd_printint (int i)
 
int SD_File_Exists (char *filepath)
 
int SD_File_Delete_All ()
 

Function Documentation

int sd_fclose ( SD_FILE *  stream)

Definition at line 54 of file sd_stdio_c_iface.cpp.

56  {
57  if (stream) {
58  stream->f.close();
59  }
60 
61  delete stream;
62  return 0;
63 }
int sd_feof ( SD_FILE *  stream)

Definition at line 66 of file sd_stdio_c_iface.cpp.

68  {
69  if (stream->eof == 1) {
70 #if DEBUG
71  Serial.println("EOF");
72 #endif
73  return -1; /* end of file has been reached */
74  }
75  else {
76 #if DEBUG
77  Serial.println("NOT EOF");
78 #endif
79  return 0; /* end of file has not been reached */
80  }
81 }
int sd_fflush ( SD_FILE *  stream)

Definition at line 84 of file sd_stdio_c_iface.cpp.

86  {
87  stream->f.flush();
88  return 0;
89 }
int sd_fgetpos ( SD_FILE *  stream,
ion_fpos_t pos 
)

Definition at line 100 of file sd_stdio_c_iface.cpp.

103  {
104  *pos = (stream) ? stream->f.position() : 0;
105  return 0;
106 }
int SD_File_Begin ( uint8_t  csPin)

Definition at line 357 of file sd_stdio_c_iface.cpp.

359  {
360  return SD.begin(csPin);
361 }
int SD_File_Delete_All ( )

Definition at line 378 of file sd_stdio_c_iface.cpp.

379  {
380  File root = SD.open("/");
381 
382  while (true) {
383  File entry = root.openNextFile();
384 
385  if (!entry) {
386  break;
387  }
388 
389  entry.close();
390 
391  bool is_ok = SD.remove(entry.name());
392 
393  if (!is_ok) {
394  return false;
395  }
396  }
397 
398  return true;
399 }
int SD_File_Exists ( char *  filepath)

Definition at line 371 of file sd_stdio_c_iface.cpp.

373  {
374  return (int) (SD.exists(filepath));
375 }

Here is the caller graph for this function:

SD_FILE* sd_fopen ( char *  filename,
char *  mode 
)

Definition at line 109 of file sd_stdio_c_iface.cpp.

112  {
113  uint8_t operation;
114  ion_boolean_t seek_start = boolean_false;
115 
116  if ((strcmp(mode, "r") == 0) || (strcmp(mode, "rb") == 0)) {
117  /* Open a file for reading. The file must exist. */
118  /* check to see if file exists */
119 
120  if (!SD.exists(filename)) {
121  return NULL;
122  }
123 
124  operation = FILE_READ;
125  }
126  else if ((strcmp(mode, "w") == 0) || (strcmp(mode, "wb") == 0)) {
127  /* Create an empty file for writing. */
128  /* If a file with the same name already exists */
129  /* its content is erased and the file is */
130  /* considered as a new empty file. */
131 
132  if (SD.exists(filename)) {
133  SD.remove(filename);
134  }
135 
136  operation = FILE_WRITE;
137  /* Open a file for update both reading and writing. The file must exist. */
138  }
139  else if (strstr(mode, "r+") != NULL) {
140  if (!SD.exists(filename)) {
141  return NULL;
142  }
143 
144  operation = FILE_WRITE;
145  seek_start = boolean_true;
146  }
147  /* Create an empty file for both reading and writing. */
148  else if (strstr(mode, "w+") != NULL) {
149  if (SD.exists(filename)) {
150  SD.remove(filename);
151  }
152 
153  operation = FILE_WRITE;
154  }
155  else if (strcmp(mode, "a+") == 0) {
156  operation = FILE_WRITE;
157  }
158  else {
159  return 0; /*incorrect args */
160  }
161 
162  _SD_File *file = new struct _SD_File ();
163 
164  (file)->f = SD.open(filename, operation);
165 
166  if (!((file)->f)) {
167  return 0;
168  }
169 
170  if (seek_start) {
171  file->f.seek(0);
172  }
173 
174  return file;
175 }
A structure that translates a file object to a C-compatible struct.
char ion_boolean_t
A boolean type.
Definition: kv_system.h:269
size_t sd_fread ( void *  ptr,
size_t  size,
size_t  nmemb,
SD_FILE *  stream 
)

Definition at line 178 of file sd_stdio_c_iface.cpp.

183  {
184  /* read is the size of bytes * num of size-bytes */
185  int num_bytes = stream->f.read((char *) ptr, size * nmemb);
186 
187 #if DEBUG
188  Serial.print("Bytes read : ");
189  Serial.println(num_bytes);
190 #endif
191 
192  if (num_bytes < size * nmemb) {
193 #if DEBUG
194  Serial.println("End of file");
195 #endif
196  stream->eof = 1;
197  }
198 
199  return num_bytes / size;
200 }
int sd_fseek ( SD_FILE *  stream,
long int  offset,
int  whence 
)

Definition at line 203 of file sd_stdio_c_iface.cpp.

207  {
208  if (NULL == stream) {
209  return -1;
210  }
211 
212  unsigned long cur_pos = stream->f.position();
213  unsigned long cur_end = stream->f.size();
214 
215  stream->eof = 0;
216 
217  switch (whence) {
218  case SEEK_SET: /* seek from current position */
219  {
220  if (offset < 0) {
221  return -1; /* can't seek before file */
222  }
223 
224  if (offset > cur_end) {
225  if (!stream->f.seek(cur_end)) {
226  return -1;
227  }
228 
229  unsigned long bytes_to_pad = offset - cur_end;
230  char payload = 0x0;
231  size_t num_written = sd_fwrite(&payload, sizeof(payload), bytes_to_pad, stream);
232 
233  if (num_written != bytes_to_pad) {
234  return -1;
235  }
236 
237  /* The file-position indicator has been implicitly moved by the write - no seek needed to be done now */
238  return 0;
239  }
240 
241  return stream->f.seek(offset) ? 0 : -1;
242  break;
243  }
244 
245  case SEEK_CUR: {
246  if (offset + cur_pos > cur_end) {
247  if (!stream->f.seek(cur_end)) {
248  return -1;
249  }
250 
251  unsigned long bytes_to_pad = (offset + cur_pos) - cur_end;
252  char payload = 0x0;
253  size_t num_written = sd_fwrite(&payload, sizeof(payload), bytes_to_pad, stream);
254 
255  if (num_written != bytes_to_pad) {
256  return -1;
257  }
258 
259  /* The file-position indicator has been implicitly moved by the write - no seek needed to be done now */
260  return 0;
261  }
262 
263  if (offset - cur_pos < 0) {
264  return -1; /* too far past beginning of the file - assumes that offset is negative */
265  }
266 
267  return stream->f.seek(cur_pos + offset) ? 0 : -1;
268  break;
269  }
270 
271  case SEEK_END: {
272  if (offset > 0) {
273  if (!stream->f.seek(cur_end)) {
274  return -1;
275  }
276 
277  unsigned long bytes_to_pad = offset;
278  char payload = 0x0;
279  size_t num_written = sd_fwrite(&payload, sizeof(payload), bytes_to_pad, stream);
280 
281  if (num_written != bytes_to_pad) {
282  return -1;
283  }
284 
285  /* The file-position indicator has been implicitly moved by the write - no seek needed to be done now */
286  return 0;
287  }
288 
289  return stream->f.seek(cur_end + offset) ? 0 : -1;
290  break;
291  }
292 
293  default:
294  return -1;
295  }
296 }
size_t sd_fwrite(void *ptr, size_t size, size_t nmemb, SD_FILE *stream)

Here is the call graph for this function:

int sd_fsetpos ( SD_FILE *  stream,
ion_fpos_t pos 
)

Definition at line 92 of file sd_stdio_c_iface.cpp.

95  {
96  return (stream) ? !(stream->f.seek(*pos)) : 1;
97 }
long int sd_ftell ( SD_FILE *  stream)

Definition at line 299 of file sd_stdio_c_iface.cpp.

301  {
302  long int pos = (stream) ? stream->f.position() : -1;
303 
304 #if DEBUG
305  Serial.print("cur pos: ");
306  Serial.println(pos);
307 #endif
308  return pos;
309 }
size_t sd_fwrite ( void *  ptr,
size_t  size,
size_t  nmemb,
SD_FILE *  stream 
)

Definition at line 312 of file sd_stdio_c_iface.cpp.

317  {
318  size_t idx;
319  size_t bytes_written = 0;
320  size_t total_count = 0;
321 
322  /* for each element, continue to write */
323  for (idx = 0; idx < nmemb; idx++) {
324  bytes_written = stream->f.write((uint8_t *) ptr, size);
325 
326  if (bytes_written != size) {
327  return total_count;
328  }
329 
330  total_count += 1;
331  }
332 
333  if (total_count != nmemb) {
334  return -1;
335  }
336  else {
337  return total_count;
338  }
339 }

Here is the caller graph for this function:

void sd_printint ( int  i)

Definition at line 364 of file sd_stdio_c_iface.cpp.

366  {
367  Serial.println(i);
368 }
int sd_remove ( char *  filename)

Definition at line 342 of file sd_stdio_c_iface.cpp.

344  {
345  return SD.remove(filename) ? 0 : 1;
346 }
void sd_rewind ( SD_FILE *  stream)

Definition at line 349 of file sd_stdio_c_iface.cpp.

351  {
352  stream->eof = 0;
353  stream->f.seek(0);
354 }