basic ios read, write, and stream creation
This commit is contained in:
		
							parent
							
								
									fa0e134dd8
								
							
						
					
					
						commit
						755bb33714
					
				|  | @ -31,7 +31,7 @@ release: $(OBJS) | |||
| 
 | ||||
| test: | ||||
| 	make clean | ||||
| 	make release CFLAGS=-DENABLE_LLT_TEST | ||||
| 	make debug CFLAGS=-DENABLE_LLT_TEST | ||||
| 	gcc $(TESTSRC) $(TARGET) -o $(TESTER) -lm | ||||
| 	./$(TESTER) | ||||
| 
 | ||||
|  |  | |||
|  | @ -46,14 +46,14 @@ void snprint_cplx(char *s, size_t cnt, double re, double im, | |||
|     if (!fzi) { | ||||
|         len = sl = strlen(s); | ||||
|         if (dbl_equals(im, -1)) { | ||||
|             while (len-sl < (size_t)width-2 && len < (space-3)) | ||||
|             while ((long)(len-sl) < (long)(width-2) && len < (space-3)) | ||||
|                 s[len++] = ' '; | ||||
|             s[len] =   '-'; | ||||
|             s[len+1] = 'i'; | ||||
|             s[len+2] = '\0'; | ||||
|         } | ||||
|         else if (dbl_equals(im, 1)) { | ||||
|             while (len-sl < (size_t)width-1 && len < (space-2)) | ||||
|             while ((long)(len-sl) < (long)(width-1) && len < (space-2)) | ||||
|                 s[len++] = ' '; | ||||
|             s[len] =   'i'; | ||||
|             s[len+1] = '\0'; | ||||
|  |  | |||
							
								
								
									
										173
									
								
								llt/ios.c
								
								
								
								
							
							
						
						
									
										173
									
								
								llt/ios.c
								
								
								
								
							|  | @ -5,6 +5,7 @@ | |||
| #include <limits.h> | ||||
| #include <errno.h> | ||||
| #include <wchar.h> | ||||
| #include <stdio.h> // for printf | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| #include <malloc.h> | ||||
|  | @ -15,6 +16,8 @@ | |||
| #include <unistd.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/select.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "dtypes.h" | ||||
|  | @ -223,7 +226,7 @@ static size_t _writebuf_force(ios_t *s, char *data, size_t n) | |||
| 
 | ||||
| /* interface functions, low level */ | ||||
| 
 | ||||
| size_t ios_read(ios_t *s, char *dest, size_t n, int all) | ||||
| static size_t _ios_read(ios_t *s, char *dest, size_t n, int all) | ||||
| { | ||||
|     size_t tot = 0; | ||||
|     size_t got, avail; | ||||
|  | @ -289,12 +292,23 @@ size_t ios_read(ios_t *s, char *dest, size_t n, int all) | |||
|     return tot; | ||||
| } | ||||
| 
 | ||||
| size_t ios_read(ios_t *s, char *dest, size_t n) | ||||
| { | ||||
|     return _ios_read(s, dest, n, 0); | ||||
| } | ||||
| 
 | ||||
| size_t ios_readall(ios_t *s, char *dest, size_t n) | ||||
| { | ||||
|     return _ios_read(s, dest, n, 1); | ||||
| } | ||||
| 
 | ||||
| size_t ios_write(ios_t *s, char *data, size_t n) | ||||
| { | ||||
|     if (n == 0) return 0; | ||||
|     size_t space; | ||||
|     size_t wrote = 0; | ||||
| 
 | ||||
|     if (s->state == bst_none) s->state = bst_wr; | ||||
|     if (s->state == bst_wr) | ||||
|         space = s->maxsize - s->bpos; | ||||
|     else | ||||
|  | @ -308,9 +322,21 @@ size_t ios_write(ios_t *s, char *data, size_t n) | |||
|         return wrote; | ||||
|     } | ||||
|     else if (n <= space) { | ||||
|         if (s->bm == bm_line) { | ||||
|             char *nl; | ||||
|             if ((nl=(char*)memrchr(data, '\n', n)) != NULL) { | ||||
|                 size_t linesz = nl-data+1; | ||||
|                 s->bm = bm_block; | ||||
|                 wrote += ios_write(s, data, linesz); | ||||
|                 ios_flush(s); | ||||
|                 s->bm = bm_line; | ||||
|                 n -= linesz; | ||||
|                 data += linesz; | ||||
|             } | ||||
|         } | ||||
|         memcpy(s->buf + s->bpos, data, n); | ||||
|         s->bpos += n; | ||||
|         wrote = n; | ||||
|         wrote += n; | ||||
|     } | ||||
|     else { | ||||
|         s->state = bst_wr; | ||||
|  | @ -331,6 +357,13 @@ size_t ios_write(ios_t *s, char *data, size_t n) | |||
| off_t ios_seek(ios_t *s, off_t pos) | ||||
| { | ||||
|     s->_eof = 0; | ||||
|     if (s->bm == bm_mem) { | ||||
|         if ((size_t)pos > s->size) | ||||
|             return -1; | ||||
|         s->bpos = pos; | ||||
|         return s->bpos; | ||||
|     } | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| off_t ios_seek_end(ios_t *s) | ||||
|  | @ -548,21 +581,155 @@ int ios_copyall(ios_t *to, ios_t *from) | |||
|     return ios_copy_(to, from, 0, 1); | ||||
| } | ||||
| 
 | ||||
| static void _ios_init(ios_t *s) | ||||
| { | ||||
|     // put all fields in a sane initial state
 | ||||
|     s->bm = bm_block; | ||||
|     s->state = bst_none; | ||||
|     s->errcode = 0; | ||||
|     s->buf = NULL; | ||||
|     s->maxsize = 0; | ||||
|     s->size = 0; | ||||
|     s->bpos = 0; | ||||
|     s->ndirty = 0; | ||||
|     s->tally = 0; | ||||
|     s->fd = -1; | ||||
|     s->byteswap = 0; | ||||
|     s->ownbuf = 0; | ||||
|     s->ownfd = 0; | ||||
|     s->_eof = 0; | ||||
|     s->rereadable = 0; | ||||
| } | ||||
| 
 | ||||
| /* stream object initializers. we do no allocation. */ | ||||
| 
 | ||||
| ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite) | ||||
| { | ||||
|     int fd; | ||||
|     int flags = O_RDWR; | ||||
|     if (create) flags |= O_CREAT; | ||||
|     if (rewrite) flags |= O_TRUNC; | ||||
|     fd = open(fname, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH/*644*/); | ||||
|     if (fd == -1) { | ||||
|         s->fd = -1; | ||||
|         return NULL; | ||||
|     } | ||||
|     s = ios_fd(s, fd, 1); | ||||
|     s->ownfd = 1; | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| ios_t *ios_mem(ios_t *s, size_t initsize) | ||||
| { | ||||
|     _ios_init(s); | ||||
|     s->bm = bm_mem; | ||||
|     _buf_realloc(s, initsize); | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| ios_t *ios_fd(ios_t *s, long fd) | ||||
| ios_t *ios_str(ios_t *s, char *str) | ||||
| { | ||||
|     size_t n = strlen(str); | ||||
|     if (ios_mem(s, n+1)==NULL) return NULL; | ||||
|     ios_write(s, str, n+1); | ||||
|     ios_seek(s, 0); | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| ios_t *ios_fd(ios_t *s, long fd, int isfile) | ||||
| { | ||||
|     _ios_init(s); | ||||
|     s->fd = fd; | ||||
|     if (isfile) s->rereadable = 1; | ||||
|     _buf_init(s, bm_block); | ||||
|     s->ownfd = 0; | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| ios_t *ios_stdin() | ||||
| { | ||||
|     static ios_t *_ios_stdin = NULL; | ||||
|     if (_ios_stdin == NULL) { | ||||
|         _ios_stdin = malloc(sizeof(ios_t)); | ||||
|         ios_fd(_ios_stdin, STDIN_FILENO, 0); | ||||
|     } | ||||
|     return _ios_stdin; | ||||
| } | ||||
| 
 | ||||
| ios_t *ios_stdout() | ||||
| { | ||||
|     static ios_t *_ios_stdout = NULL; | ||||
|     if (_ios_stdout == NULL) { | ||||
|         _ios_stdout = malloc(sizeof(ios_t)); | ||||
|         ios_fd(_ios_stdout, STDOUT_FILENO, 0); | ||||
|         _ios_stdout->bm = bm_line; | ||||
|     } | ||||
|     return _ios_stdout; | ||||
| } | ||||
| 
 | ||||
| ios_t *ios_stderr() | ||||
| { | ||||
|     static ios_t *_ios_stderr = NULL; | ||||
|     if (_ios_stderr == NULL) { | ||||
|         _ios_stderr = malloc(sizeof(ios_t)); | ||||
|         ios_fd(_ios_stderr, STDERR_FILENO, 0); | ||||
|         _ios_stderr->bm = bm_none; | ||||
|     } | ||||
|     return _ios_stderr; | ||||
| } | ||||
| 
 | ||||
| /* higher level interface */ | ||||
| 
 | ||||
| int ios_putc(int c, ios_t *s) | ||||
| { | ||||
|     char ch = (char)c; | ||||
| 
 | ||||
|     return (int)ios_write(s, &ch, 1); | ||||
| } | ||||
| 
 | ||||
| int ios_getc(ios_t *s) | ||||
| { | ||||
|     if (s->_eof) return IOS_EOF; | ||||
|     char ch; | ||||
|     size_t n = ios_read(s, &ch, 1); | ||||
|     if (n < 1) | ||||
|         return IOS_EOF; | ||||
|     return (int)ch; | ||||
| } | ||||
| 
 | ||||
| int ios_ungetc(int c, ios_t *s) | ||||
| { | ||||
|     if (s->state == bst_wr) | ||||
|         return IOS_EOF; | ||||
|     if (s->bpos > 0) { | ||||
|         s->bpos--; | ||||
|         s->buf[s->bpos] = (char)c; | ||||
|         return c; | ||||
|     } | ||||
|     if (s->size == s->maxsize) { | ||||
|         if (_buf_realloc(s, s->maxsize*2) == NULL) | ||||
|             return IOS_EOF; | ||||
|     } | ||||
|     memmove(s->buf + 1, s->buf, s->size); | ||||
|     s->buf[0] = (char)c; | ||||
|     s->size++; | ||||
|     return c; | ||||
| } | ||||
| 
 | ||||
| int ios_printf(ios_t *s, char *format, ...) | ||||
| { | ||||
|     char *str; | ||||
|     va_list args; | ||||
| 
 | ||||
|     va_start(args, format); | ||||
|     // TODO: avoid copy
 | ||||
|     int c = vasprintf(&str, format, args); | ||||
|     va_end(args); | ||||
| 
 | ||||
|     if (c == -1) return c; | ||||
| 
 | ||||
|     ios_write(s, str, c); | ||||
| 
 | ||||
|     free(str); | ||||
|     return c; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										26
									
								
								llt/ios.h
								
								
								
								
							
							
						
						
									
										26
									
								
								llt/ios.h
								
								
								
								
							|  | @ -61,7 +61,8 @@ typedef struct { | |||
| } ios_t; | ||||
| 
 | ||||
| /* low-level interface functions */ | ||||
| size_t ios_read(ios_t *s, char *dest, size_t n, int all); | ||||
| size_t ios_read(ios_t *s, char *dest, size_t n); | ||||
| size_t ios_readall(ios_t *s, char *dest, size_t n); | ||||
| size_t ios_write(ios_t *s, char *data, size_t n); | ||||
| off_t ios_seek(ios_t *s, off_t pos);   // absolute seek
 | ||||
| off_t ios_seek_end(ios_t *s); | ||||
|  | @ -87,8 +88,12 @@ int ios_copyall(ios_t *to, ios_t *from); | |||
| /* stream creation */ | ||||
| ios_t *ios_file(ios_t *s, char *fname, int create, int rewrite); | ||||
| ios_t *ios_mem(ios_t *s, size_t initsize); | ||||
| ios_t *ios_fd(ios_t *s, long fd); | ||||
| ios_t *ios_str(ios_t *s, char *str); | ||||
| ios_t *ios_fd(ios_t *s, long fd, int isfile); | ||||
| // todo: ios_socket
 | ||||
| ios_t *ios_stdin(); | ||||
| ios_t *ios_stdout(); | ||||
| ios_t *ios_stderr(); | ||||
| 
 | ||||
| /* high-level functions - output */ | ||||
| int ios_putnum(ios_t *s, char *data, uint32_t type); | ||||
|  | @ -112,13 +117,13 @@ int ios_prevutf8(ios_t *s); | |||
| 
 | ||||
| /* stdio-style functions */ | ||||
| #define IOS_EOF (-1) | ||||
| int ios_putc(ios_t *s, int c); | ||||
| int ios_putc(int c, ios_t *s); | ||||
| //wint_t ios_putwc(ios_t *s, wchar_t wc);
 | ||||
| int ios_getc(ios_t *s); | ||||
| //wint_t ios_getwc(ios_t *s);
 | ||||
| int ios_ungetc(ios_t *s, int c); | ||||
| int ios_ungetc(int c, ios_t *s); | ||||
| //wint_t ios_ungetwc(ios_t *s, wint_t wc);
 | ||||
| #define ios_puts(s, str) ios_write(s, str, strlen(str)) | ||||
| #define ios_puts(str, s) ios_write(s, str, strlen(str)) | ||||
| 
 | ||||
| /*
 | ||||
|   With memory streams, mixed reads and writes are equivalent to performing | ||||
|  | @ -164,21 +169,18 @@ int ios_ungetc(ios_t *s, int c); | |||
| 
 | ||||
|   design points: | ||||
|   - data-source independence, including memory streams | ||||
|   - support 64-bit and large files | ||||
|   - efficient, low-latency buffering | ||||
|   - unget | ||||
|   - expose buffer to user, allow user-owned buffers | ||||
|   - allow direct I/O, don't always go through buffer | ||||
|   - buffer-internal seeking. makes seeking back 1-2 bytes very fast, | ||||
|     and makes it possible for sockets where it otherwise wouldn't be | ||||
|   - special support for utf8 | ||||
|   - tries to allow switching between reading and writing | ||||
|   - support 64-bit and large files | ||||
|   - efficient, low-latency buffering | ||||
|   - special support for utf8 | ||||
|   - type-aware functions with byte-order swapping service | ||||
|   - position counter for meaningful data offsets with sockets | ||||
| 
 | ||||
|   note: | ||||
|   the current code needs to be mostly rewritten. the design should be | ||||
|   as follows: | ||||
|   theory of operation: | ||||
| 
 | ||||
|   the buffer is a view of part of a file/stream. you can seek, read, and | ||||
|   write around in it as much as you like, as if it were just a string. | ||||
|  |  | |||
|  | @ -43,6 +43,8 @@ int main() | |||
|     printf("u8 took %.4f sec (%d)\n\n", clock_now()-t0, j); | ||||
|     */ | ||||
| 
 | ||||
|     test_ios(); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -111,3 +113,32 @@ void test_dblprint() | |||
| 
 | ||||
|     prettyreal(DBL_EPSILON); | ||||
| } | ||||
| 
 | ||||
| void test_ios() | ||||
| { | ||||
|     ios_t *out = ios_stdout(); | ||||
|     ios_t *in = ios_stdin(); | ||||
| 
 | ||||
|     ios_putc('a', out); | ||||
|     ios_putc('b', out); | ||||
|     ios_putc('\n', out); | ||||
| 
 | ||||
|     char c[80]; | ||||
|     size_t i=0; | ||||
|     ios_t sts; | ||||
|     ios_str(&sts, "Test string."); | ||||
|     c[i++] = ios_getc(&sts); | ||||
|     c[i++] = ios_getc(&sts); | ||||
|     c[i++] = ios_getc(&sts); | ||||
|     c[i++] = '\0'; | ||||
|     printf("got: \"%s\"\n", c); | ||||
| 
 | ||||
|     ios_t ms; | ||||
|     ios_mem(&ms, 10); | ||||
|     int j; | ||||
|     for(j=0; j < 16; j++) | ||||
|         ios_puts("passersby were amazed by the ", &ms); | ||||
|     size_t bs; | ||||
|     char *bigstr = ios_takebuf(&ms, &bs); | ||||
|     printf("got: \"%s\" (size %d)\n", bigstr, bs); | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 JeffBezanson
						JeffBezanson