summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2011-08-21 12:26:17 -0700
committerJosh Haberman <jhaberman@gmail.com>2011-08-21 12:26:17 -0700
commit9d2fcd3692dfb8c69e02ac55f817562cef7426e1 (patch)
treebb78b30b7313d123b466ecba164d72291e895c15 /upb
parent6c6013e51e196c54df4f0f7db78e31dab59e2bc5 (diff)
Some progress on upb_stdio.
It's still not correct, but it's closer.
Diffstat (limited to 'upb')
-rw-r--r--upb/bytestream.c63
-rw-r--r--upb/bytestream.h1
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;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback