p2  0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
buffile.c
Go to the documentation of this file.
1 
8 #define __USE_XOPEN2K8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 //#include <errno.h>
13 #include "p2.h"
14 
15 #ifndef SANDBOX
16 
17 // i686-w64-mingw32 /include/stdio.h has asprintf defined
18 // i386-mingw32 not
19 #if POTION_WIN32 && !defined(__MINGW_SCANF_FORMAT)
20 int vasprintf (char **strp, const char *fmt, __VALIST ap);
21 int asprintf (char **string_ptr, const char *format, ...);
22 #endif
23 
24 #if defined(__linux__) || defined(__CYGWIN__)
25 #define HAVE_FMEMOPEN
26 #endif
27 
28 struct PNBufFile {
31  FILE * file;
33 };
34 typedef vPN(BufFile) pn_ffile;
35 const int BufFileSize = sizeof(struct PNBufFile) - sizeof(struct PNData);
36 
42 PN potion_buffile_fopen(Potion *P, PN cl, PN ign, PN path, PN modestr) {
43  FILE *file;
44  struct PNBufFile *self;
45  if (!(file = fopen(PN_STR_PTR(path), PN_STR_PTR(modestr))))
46  return potion_io_error(P, "open");
47  self = (struct PNBufFile *)potion_data_alloc(P, sizeof(struct PNBufFile));
48  self->siz = BufFileSize;
49  self->file = file;
50  self->path = path;
51  return (PN)self;
52 }
58  struct PNBufFile *self;
59  self = (struct PNBufFile *)potion_data_alloc(P, sizeof(struct PNBufFile));
60  self->siz = BufFileSize;
61  self->file = tmpfile();
62  if (!self->file)
63  return potion_io_error(P, "tmpfile");
64  self->path = PN_NIL;
65  return (PN)self;
66 }
73 PN potion_buffile_fdopen(Potion *P, PN cl, pn_ffile self, PN fd, PN modestr) {
74  FILE *file;
75  if (!(file = fdopen(PN_INT(fd), PN_STR_PTR(modestr))))
76  return potion_io_error(P, "fdopen");
77  self->siz = BufFileSize;
78  self->file = file;
79  self->path = PN_NIL;
80  return (PN)self;
81 }
82 
92 PN potion_buffile_freopen(Potion *P, PN cl, pn_ffile self, PN path, PN modestr, pn_ffile stream) {
93  FILE *file;
94  if ((PN_TYPE(stream) != PN_TUSER) ||
95  !(file = freopen(PN_STR_PTR(path), PN_STR_PTR(modestr), stream->file))) {
96  return potion_io_error(P, "freopen");
97  }
98  self->siz = BufFileSize;
99  self->file = file;
100  self->path = stream->path;
101  return (PN)self;
102 }
103 
104 #ifdef HAVE_FMEMOPEN
105 
113 PN potion_buffile_fmemopen(Potion *P, PN cl, PN buf, PN modestr) {
114  FILE *file;
115  struct PNBufFile *self;
116  if (!(file = fmemopen(PN_STR_PTR(buf), PN_STR_LEN(buf), PN_STR_PTR(modestr))))
117  return potion_io_error(P, "fmemopen");
118  self = (struct PNBufFile *)potion_data_alloc(P, sizeof(struct PNBufFile));
119  self->siz = BufFileSize;
120  self->file = file;
121  self->path = PN_NIL;
122  return (PN)self;
123 }
124 #endif
125 
129 PN potion_buffile_fclose(Potion *P, PN cl, pn_ffile self) {
130  return PN_NUM(fclose(self->file));
131 }
135 PN potion_buffile_fgetc(Potion *P, PN cl, pn_ffile self) {
136  return PN_NUM(fgetc(self->file));
137 }
142 PN potion_buffile_fgets(Potion *P, PN cl, pn_ffile self) {
143  char line[1024];
144  if (fgets(line, 1024, self->file) != NULL)
145  return potion_byte_str(P, line);
146  return PN_NIL;
147 }
154 PN potion_buffile_fread(Potion *P, PN cl, pn_ffile self, PN buf, PN size, PN nitems) {
155  int r = fread(PN_STR_PTR(buf), PN_INT(size), PN_INT(nitems), self->file);
156  if (r < PN_INT(nitems))
157  return potion_io_error(P, "fread");
158  return PN_NUM(r);
159 }
166 PN potion_buffile_fwrite(Potion *P, PN cl, pn_ffile self, PN buf, PN size, PN nitems) {
167  if (!size && (!nitems || PN_INT(nitems) == 1)) {
168  size = potion_send(buf, PN_STR("length"));
169  nitems = PN_NUM(1);
170  }
171  switch (PN_TYPE(buf)) {
172  case PN_TSTRING:
173  case PN_TBYTES: break;
174  case PN_NIL: return PN_NIL;
175  default: return potion_type_error(P, buf);
176  }
177  int r = fwrite(PN_STR_PTR(buf), PN_INT(size), PN_INT(nitems), self->file);
178  if (r < PN_INT(nitems))
179  return potion_io_error(P, "fwrite");
180  return PN_NUM(r);
181 }
186 PN potion_buffile_fputc(Potion *P, PN cl, pn_ffile self, PN byte) {
187  return PN_NUM(fputc(PN_INT(byte), self->file));
188 }
193 PN potion_buffile_fputs(Potion *P, PN cl, pn_ffile self, PN str) {
194  int r;
195  if (!(r=fputs(PN_STR_PTR(str), self->file)))
196  return potion_io_error(P, "fputs");
197  return PN_NUM(r);
198 }
202 PN potion_buffile_fflush(Potion *P, PN cl, pn_ffile self) {
203  if (fflush(self->file))
204  return potion_io_error(P, "fflush");
205  return PN_TRUE;
206 }
212 PN potion_buffile_fseek(Potion *P, PN cl, pn_ffile self, PN offset, PN whence) {
213  if (fseek(self->file, PN_INT(offset), PN_INT(whence)))
214  return potion_io_error(P, "fseek");
215  return PN_TRUE;
216 }
221 PN potion_buffile_ftell(Potion *P, PN cl, pn_ffile self) {
222  long r = ftell(self->file);
223  if (r == -1)
224  return potion_io_error(P, "ftell");
225  return PN_NUM(r);
226 }
230 PN potion_buffile_feof(Potion *P, PN cl, pn_ffile self) {
231  int r = feof(self->file);
232  return r ? PN_TRUE : PN_FALSE;
233 }
236 PN potion_buffile_fileno(Potion *P, PN cl, pn_ffile self) {
237  return PN_NUM(fileno(self->file));
238 }
242 PN potion_buffile_unlink(Potion *P, PN cl, pn_ffile self) {
243  if (fileno(self->file) != -1) fclose(self->file);
244  if (!self->path || unlink(PN_STR_PTR(self->path))) {
245  return potion_io_error(P, "unlink");
246  }
247  return PN_TRUE;
248 }
249 #ifndef __MINGW32__
250 
252 PN potion_buffile_flockfile(Potion *P, PN cl, pn_ffile self) {
253  flockfile(self->file); return PN_TRUE;
254 }
258 PN potion_buffile_ftrylockfile(Potion *P, PN cl, pn_ffile self) {
259  return PN_NUM(ftrylockfile(self->file));
260 }
263 PN potion_buffile_funlockfile(Potion *P, PN cl, pn_ffile self) {
264  funlockfile(self->file); return PN_TRUE;
265 }
266 #endif
267 
271 #if 0
272 PN potion_buffile_fprintf(Potion *P, PN cl, pn_ffile self, PN fmt, ...) {
273  return fprintf(self->file, potion_send(obj, PN_string));
274 }
275 #endif
276 
278 PN potion_buffile_string(Potion *P, PN cl, pn_ffile self) {
279  int fd = fileno(self->file), rv;
280  char *buf;
281  PN str;
282  if (self->path != PN_NIL && fd != -1) {
283  rv = asprintf(&buf, "<buffile %s fd: %d>", PN_STR_PTR(self->path), fd);
284  } else if (fd != -1) {
285  rv = asprintf(&buf, "<buffile %p fd: %d>", self->file, fd);
286  } else {
287  rv = asprintf(&buf, "<closed buffile %p>", self->file);
288  }
289  if (rv == -1) potion_allocation_error();
290  str = potion_str(P, buf);
291  free(buf);
292  return str;
293 }
294 
295 DLLEXPORT
297  PN ffile_vt = potion_type_new2(P, PN_TUSER, PN_VTABLE(PN_TFILE), PN_STR("BufFile"));
298  potion_type_constructor_is(ffile_vt, PN_FUNC(potion_buffile_fopen, "path=S,mode=S"));
299  //potion_class_method(ffile_vt, "fd", potion_buffile_fdopen, "fd=N,mode=S");
300  potion_method(P->lobby, "fopen", potion_buffile_fopen, "path=S,mode=S");
301  potion_method(ffile_vt, "fdopen", potion_buffile_fdopen, "fd=N,mode=S");
302  potion_method(ffile_vt, "freopen", potion_buffile_freopen, "path=S,mode=S,buffile=o");
303 #ifdef HAVE_FMEMOPEN
304  potion_method(PN_VTABLE(PN_TBYTES), "fmemopen", potion_buffile_fmemopen, "mode=S");
305 #endif
306  potion_method(ffile_vt, "close", potion_buffile_fclose, 0);
307  potion_method(ffile_vt, "fread", potion_buffile_fread, "buf=S,size=N,n:=1");
308  potion_method(ffile_vt, "write", potion_buffile_fwrite, "buf=S|size=N,n:=1");
309  //potion_method(ffile_vt, "fprintf", potion_buffile_fprintf, "fmt=S|...");
310  potion_method(ffile_vt, "fgetc", potion_buffile_fgetc, 0);
311  potion_method(ffile_vt, "fgets", potion_buffile_fgets, 0);
312  potion_method(ffile_vt, "fputc", potion_buffile_fputc, "byte=N");
313  potion_method(ffile_vt, "fputs", potion_buffile_fputs, "str=S");
314  potion_method(ffile_vt, "fflush", potion_buffile_fflush, 0);
315  potion_method(ffile_vt, "fseek", potion_buffile_fseek, "offset=N, whence=N");
316  potion_method(ffile_vt, "ftell", potion_buffile_ftell, 0);
317  potion_method(ffile_vt, "feof", potion_buffile_feof, 0);
318  potion_method(ffile_vt, "fileno", potion_buffile_fileno, 0);
319 #ifndef __MINGW32__
320  potion_method(ffile_vt, "flockfile", potion_buffile_flockfile, 0);
321  potion_method(ffile_vt, "ftrylockfile", potion_buffile_ftrylockfile, 0);
322  potion_method(ffile_vt, "funlockfile", potion_buffile_funlockfile, 0);
323 #endif
324  potion_method(ffile_vt, "unlink", potion_buffile_unlink, 0);
325  potion_method(ffile_vt, "string", potion_buffile_string, 0);
326  potion_method(P->lobby, "tmpfile", potion_buffile_tmpfile, 0);
327 }
328 
329 #endif /*SANDBOX */
PN potion_buffile_tmpfile(Potion *P, PN cl, PN ign)
Definition: buffile.c:57
PN path
Definition: buffile.c:32
PN potion_str(Potion *, const char *)
Definition: string.c:33
PN potion_buffile_freopen(Potion *P, PN cl, pn_ffile self, PN path, PN modestr, pn_ffile stream)
Definition: buffile.c:92
#define PN_TSTRING
Definition: potion.h:112
PN potion_buffile_ftell(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:221
PN potion_buffile_fileno(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:236
#define PN_TUSER
Definition: potion.h:130
PN potion_buffile_fseek(Potion *P, PN cl, pn_ffile self, PN offset, PN whence)
Definition: buffile.c:212
struct to wrap arbitrary data that we may want to allocate from Potion.
Definition: potion.h:326
PN PN potion_byte_str(Potion *, const char *)
Definition: string.c:331
#define potion_method(RCV, MSG, FN, SIG)
Definition: potion.h:789
#define PN_TFILE
Definition: potion.h:117
static struct PNData * potion_data_alloc(Potion *P, int siz)
Definition: potion.h:765
PN_SIZE siz
Definition: buffile.c:30
#define PN_STR_LEN(x)
Definition: potion.h:223
PN potion_buffile_fflush(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:202
PN PN_string
Definition: internal.c:14
#define PN_TBYTES
Definition: potion.h:121
#define PN_STR(x)
Definition: potion.h:219
PN potion_buffile_ftrylockfile(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:258
#define PN_INT(x)
Definition: potion.h:214
#define PN_NUM(i)
Definition: potion.h:213
PN potion_buffile_flockfile(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:252
unsigned int PN_SIZE
Definition: potion.h:79
PN_OBJECT_HEADER
Definition: buffile.c:29
PN lobby
root namespace
Definition: potion.h:657
PN potion_buffile_fputc(Potion *P, PN cl, pn_ffile self, PN byte)
Definition: buffile.c:186
PN potion_io_error(Potion *P, const char *msg)
Definition: internal.c:259
DLLEXPORT void Potion_Init_buffile(Potion *P)
Definition: buffile.c:296
PN potion_type_error(Potion *P, PN obj)
Definition: internal.c:273
PN potion_buffile_fgets(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:142
#define PN_FALSE
Definition: potion.h:141
#define DLLEXPORT
Definition: potion.h:58
FILE * file
Definition: buffile.c:31
PN_SIZE siz
Definition: potion.h:328
PN potion_buffile_fclose(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:129
#define PN_TRUE
Definition: potion.h:142
PN potion_buffile_unlink(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:242
PN potion_buffile_fputs(Potion *P, PN cl, pn_ffile self, PN str)
Definition: buffile.c:193
PN potion_buffile_fgetc(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:135
PN potion_buffile_fwrite(Potion *P, PN cl, pn_ffile self, PN buf, PN size, PN nitems)
Definition: buffile.c:166
PN potion_buffile_string(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:278
PN potion_buffile_fread(Potion *P, PN cl, pn_ffile self, PN buf, PN size, PN nitems)
Definition: buffile.c:154
PN potion_buffile_fdopen(Potion *P, PN cl, pn_ffile self, PN fd, PN modestr)
Definition: buffile.c:73
the global interpreter state P. currently singleton (not threads yet)
Definition: potion.h:653
#define PN_TYPE(x)
Definition: potion.h:133
The p2 API.
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
Definition: potion.h:781
PN potion_type_new2(Potion *P, PNType t, PN self, PN name)
create a named type
Definition: objmodel.c:224
void potion_allocation_error(void)
Definition: internal.c:305
#define vPN(t)
Definition: buffile.c:34
volatile _PN PN
Definition: potion.h:81
#define PN_NIL
Definition: potion.h:139
#define PN_FUNC(f, s)
Definition: potion.h:228
void potion_type_constructor_is(PN vt, PN cl)
set default constructor
Definition: objmodel.c:250
#define PN_STR_PTR(x)
Definition: potion.h:222
#define PN_VTABLE(t)
Definition: potion.h:136
PN potion_buffile_feof(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:230
PN potion_buffile_funlockfile(Potion *P, PN cl, pn_ffile self)
Definition: buffile.c:263