Jeroen Demeyer on Thu, 10 Sep 2015 20:07:16 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: Reading a stream from a C string |
On 2015-09-08 19:22, Bill Allombert wrote:
Alas this is not implemented. At minimum one would need to implement an 'input_method' which handle C strings.
This (attached patch) works for me. It adds a function gp_read_file_from_str() which is like gp_read_file() but from a string.
Note that there is a hack involved: a cast of FILE* to char** for the third argument of fgets(). Perhaps using a void* in all cases would be cleaner.
I added a helper function gp_read_from_input() which is general enough that it could be used to implement gp_read_file() and gp_read_stream() also. I didn't do this since I wanted some feedback first.
Jeroen.
commit 28079d92ab10d95ab0a8616fc12012d50b7b9f41 Author: Jeroen Demeyer <jdemeyer@cage.ugent.be> Date: Thu Sep 10 19:35:22 2015 +0200 New function gp_read_file_from_str diff --git a/src/headers/paridecl.h b/src/headers/paridecl.h index b17bced..107484f 100644 --- a/src/headers/paridecl.h +++ b/src/headers/paridecl.h @@ -2459,6 +2459,7 @@ void err_flush(void); void err_printf(const char* pat, ...); GEN gp_getenv(const char *s); GEN gp_read_file(const char *s); +GEN gp_read_file_from_str(const char *s); GEN gp_read_stream(FILE *f); GEN gp_readvec_file(char *s); GEN gp_readvec_stream(FILE *f); diff --git a/src/headers/paripriv.h b/src/headers/paripriv.h index e9526fb..76d047a 100644 --- a/src/headers/paripriv.h +++ b/src/headers/paripriv.h @@ -484,13 +484,13 @@ int path_is_absolute(char *s); typedef struct input_method { /* mandatory */ - char * (*fgets)(char *,int,FILE*); char * (*getline)(char**, int f, struct input_method*, filtre_t *F); int free; /* boolean: must we free the output of getline() ? */ /* for interactive methods */ const char *prompt, *prompt_cont; /* for non-interactive methods */ FILE *file; + char * (*fgets)(char *, int, FILE*); } input_method; int input_loop(filtre_t *F, input_method *IM); diff --git a/src/language/es.c b/src/language/es.c index 2ac5919..20f347f 100644 --- a/src/language/es.c +++ b/src/language/es.c @@ -261,6 +261,21 @@ gp_read_stream(FILE *fi) delete_buffer(b); return x; } +static GEN +gp_read_from_input(input_method* IM, int loop) +{ + Buffer *b = new_buffer(); + GEN x = gnil; + filtre_t F; + do { + init_filtre(&F, b); + if (!input_loop(&F, IM)) break; + if (*(b->buf)) x = readseq(b->buf); + } while (loop); + delete_buffer(b); + return x; +} + GEN gp_read_file(const char *s) { @@ -283,6 +298,41 @@ gp_read_file(const char *s) popinfile(); return x; } +static char* +string_gets(char *s, int size, const char **ptr) +{ + /* f is actually a const char** */ + const char *in = *ptr; + int i; + char c; + + /* Copy from in to s */ + for (i = 0; i+1 < size && in[i] != 0;) + { + s[i] = c = in[i]; i++; + if (c == '\n') break; + } + s[i] = 0; /* Terminating 0 byte */ + if (i == 0) return NULL; + + *ptr += i; + return s; +} + +GEN +gp_read_file_from_str(const char *s) +{ + input_method IM; + const char *ptr = s; + + IM.file = (FILE*)(&ptr); + IM.fgets = (char* (*)(char*, int, FILE*))&string_gets; + IM.getline = &file_input; + IM.free = 0; + + return gp_read_from_input(&IM, 1); +} + GEN gp_readvec_stream(FILE *fi) {