diff options
author | Josh Haberman <jhaberman@gmail.com> | 2011-08-21 12:26:17 -0700 |
---|---|---|
committer | Josh Haberman <jhaberman@gmail.com> | 2011-08-21 12:26:17 -0700 |
commit | 9d2fcd3692dfb8c69e02ac55f817562cef7426e1 (patch) | |
tree | bb78b30b7313d123b466ecba164d72291e895c15 /upb | |
parent | 6c6013e51e196c54df4f0f7db78e31dab59e2bc5 (diff) |
Some progress on upb_stdio.
It's still not correct, but it's closer.
Diffstat (limited to 'upb')
-rw-r--r-- | upb/bytestream.c | 63 | ||||
-rw-r--r-- | upb/bytestream.h | 1 |
2 files changed, 39 insertions, 25 deletions
diff --git a/upb/bytestream.c b/upb/bytestream.c index 846b8ee..976b139 100644 --- a/upb/bytestream.c +++ b/upb/bytestream.c @@ -35,30 +35,46 @@ static upb_stdio_buf *upb_stdio_findbuf(upb_stdio *s, uint64_t ofs) { return bsearch(&ofs, s->bufs, s->nbuf, sizeof(*s->bufs), &upb_stdio_cmpbuf); } -//static upb_strlen_t upb_stdio_read(void *src, uint32_t ofs, upb_buf *b, -// upb_status *status) { -// upb_stdio *stdio = (upb_stdio*)src; -// size_t read = fread(buf, 1, BLOCK_SIZE, stdio->file); -// if(read < (size_t)BLOCK_SIZE) { -// // Error or EOF. -// if(feof(stdio->file)) { -// upb_seterr(status, UPB_EOF, ""); -// } else if(ferror(stdio->file)) { -// upb_status_fromerrno(s); -// return 0; -// } -// } -// b->len = read; -// stdio->next_ofs += read; -// return stdio->next_ofs; -//} +static upb_stdio_buf *upb_stdio_rotatebufs(upb_stdio *s) { + upb_stdio_buf *reuse[s->nbuf]; + uint32_t num_reused = 0, num_inuse = 0; + + // Could sweep only a subset of bufs if this was a hotspot. + for (uint32_t i = 0; i < s->nbuf; i++) { + upb_stdio_buf *buf = s->bufs[i]; + if (buf->refcount > 0) { + s->bufs[num_inuse++] = buf; + } else { + reuse[num_reused++] = buf; + } + } + assert(num_reused + num_inuse == s->nbuf); + memcpy(s->bufs + num_inuse, reuse, num_reused * sizeof(upb_stdio_buf*)); + if (num_reused == 0) { + ++s->nbuf; + s->bufs = realloc(s->bufs, s->nbuf * sizeof(*s->bufs)); + s->bufs[s->nbuf-1] = malloc(sizeof(upb_stdio_buf) + BUF_SIZE); + return s->bufs[s->nbuf-1]; + } + return s->bufs[s->nbuf-num_reused]; +} size_t upb_stdio_fetch(void *src, uint64_t ofs, upb_status *s) { - (void)src; (void)ofs; - (void)s; - - return 0; + upb_stdio *stdio = (upb_stdio*)src; + upb_stdio_buf *buf = upb_stdio_rotatebufs(stdio); + size_t read = fread(&buf->data, 1, BUF_SIZE, stdio->file); + if(read < (size_t)BUF_SIZE) { + // Error or EOF. + if(feof(stdio->file)) { + upb_status_setf(s, UPB_EOF, ""); + } else if(ferror(stdio->file)) { + upb_status_fromerrno(s); + return 0; + } + } + buf->len = read; + return buf->ofs + buf->len; } void upb_stdio_read(void *src, uint64_t src_ofs, size_t len, char *dst) { @@ -88,6 +104,7 @@ void upb_stdio_refregion(void *src, uint64_t ofs, size_t len) { len -= (BUF_SIZE - ofs); ++buf->refcount; while (len > 0) { + len -= BUF_SIZE; ++buf; ++buf->refcount; } @@ -218,10 +235,6 @@ void upb_stringsink_uninit(upb_stringsink *s) { free(s->str); } -// Resets the stringsink to a state where it will append to the given string. -// The string must be newly created or recycled. The stringsink will take a -// reference on the string, so the caller need not ensure that it outlives the -// stringsink. A stringsink can be reset multiple times. void upb_stringsink_reset(upb_stringsink *s, char *str, size_t size) { free(s->str); s->str = str; diff --git a/upb/bytestream.h b/upb/bytestream.h index cff177b..6ea0328 100644 --- a/upb/bytestream.h +++ b/upb/bytestream.h @@ -199,6 +199,7 @@ INLINE int32_t upb_bytesink_printf(upb_bytesink *sink, upb_status *status, typedef struct { uint64_t ofs; + uint32_t len; uint32_t refcount; char data[]; } upb_stdio_buf; |