X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fbuck2obj.c;h=7d651dfe6b65f6941f375a4c32ef53f88033c06d;hb=a010e5f6e075097c0d6362d40fb49e812e99e185;hp=7c931d825cd95d18228e0a75d2074910f0b7aeda;hpb=7a637b8684e729832a7f9fd2f75f2d16eb902b80;p=libucw.git diff --git a/lib/buck2obj.c b/lib/buck2obj.c index 7c931d82..7d651dfe 100644 --- a/lib/buck2obj.c +++ b/lib/buck2obj.c @@ -1,28 +1,25 @@ /* - * Bucket -> Object converter + * Generating Objects from Buckets * * (c) 2004, Robert Spalek + * (c) 2004, Martin Mares */ #include "lib/lib.h" #include "lib/unaligned.h" #include "lib/pools.h" #include "lib/fastbuf.h" -#include "charset/unicode.h" +#include "lib/unicode.h" #include "lib/object.h" #include "lib/bucket.h" #include "lib/lizard.h" -#include "lib/buck2obj.h" +#include "lib/bbuf.h" #include #include #include -#define RET_ERR(num) ({ errno = num; return NULL; }) - -#define GBUF_TYPE byte -#define GBUF_PREFIX(x) bb_##x -#include "lib/gbuf.h" +#define RET_ERR(num) ({ errno = num; return -1; }) struct buck2obj_buf { @@ -83,73 +80,110 @@ decode_attributes(byte *ptr, byte *end, struct odes *o, uns can_overwrite) return ptr; } -struct odes * -obj_read_bucket(struct buck2obj_buf *buf, struct mempool *pool, uns buck_type, uns buck_len, struct fastbuf *body, uns *body_start) +int +buck2obj_parse(struct buck2obj_buf *buf, uns buck_type, uns buck_len, struct fastbuf *body, struct odes *o_hdr, uns *body_start, struct odes *o_body) { - struct odes *o = obj_new(pool); - - if (buck_type == BUCKET_TYPE_PLAIN || buck_type == BUCKET_TYPE_V30) + if (buck_type == BUCKET_TYPE_PLAIN) + { + if (body_start) + *body_start = 0; + obj_read_multi(body, o_hdr); // ignore empty lines, read until EOF or NUL + } + else if (buck_type == BUCKET_TYPE_V30) { - if (!body_start) // header + body: ignore empty lines, read until EOF + sh_off_t start = btell(body); + obj_read(body, o_hdr); // end on EOF or the first empty line + if (body_start) + *body_start = btell(body) - start; + else { - obj_read_multi(body, o); + obj_read(body, o_body); bgetc(body); } - else // header only: end on EOF or the first empty line - { - sh_off_t start = btell(body); - obj_read(body, o); - *body_start = btell(body) - start; - } } else if (buck_type == BUCKET_TYPE_V33 || buck_type == BUCKET_TYPE_V33_LIZARD) { /* Read all the bucket into 1 buffer, 0-copy if possible. */ - int can_overwrite = bconfig(body, BCONFIG_CAN_OVERWRITE, -1); - /* FIXME: This could be cached in buck2obj_buf */ byte *ptr, *end; uns len = bdirect_read_prepare(body, &ptr); + uns copied = 0; if (len < buck_len - || (can_overwrite < 2 && buck_type == BUCKET_TYPE_V33)) + || (body->can_overwrite_buffer < 2 && buck_type == BUCKET_TYPE_V33)) { /* Copy if the original buffer is too small. * If it is write-protected, copy it also if it is uncompressed. */ bb_grow(&buf->bb, buck_len); len = bread(body, buf->bb.ptr, buck_len); ptr = buf->bb.ptr; + copied = 1; } end = ptr + len; byte *start = ptr; - ptr = decode_attributes(ptr, end, o, 0); // header + ptr = decode_attributes(ptr, end, o_hdr, 0); // header if (body_start) { *body_start = ptr - start; - return o; + if (!copied) + bdirect_read_commit(body, ptr); + return 0; } - if (buck_type == BUCKET_TYPE_V33) - ; - else if (buck_type == BUCKET_TYPE_V33_LIZARD) // decompression + if (buck_type == BUCKET_TYPE_V33_LIZARD) // decompression { + if (ptr + 4 > end) + RET_ERR(EINVAL); len = GET_U32(ptr); ptr += 4; byte *new_ptr = lizard_decompress_safe(ptr, buf->lizard, len); if (!new_ptr) - return NULL; + return -1; + if (!copied) + bdirect_read_commit(body, end); ptr = new_ptr; end = ptr + len; + copied = 1; } - else // unknown bucket type - RET_ERR(EINVAL); - ptr = decode_attributes(ptr, end, o, 2); // body - + ptr = decode_attributes(ptr, end, o_body, 2); // body if (ptr != end) RET_ERR(EINVAL); - /* If the bucket fit into the fastbuf buffer, can_overwrite == 2, and - * buck_type == BUCKET_TYPE_V33, then bflush(body) is needed before - * anything else than sequential read. */ + if (!copied) + bdirect_read_commit_modified(body, ptr); } else RET_ERR(EINVAL); - return o; + return 0; +} + +struct odes * +obj_read_bucket(struct buck2obj_buf *buf, struct mempool *pool, uns buck_type, uns buck_len, struct fastbuf *body, uns *body_start) +{ + struct odes *o = obj_new(pool); + if (buck2obj_parse(buf, buck_type, buck_len, body, o, body_start, o) < 0) + return NULL; + else + return o; +} + +int +obj_read(struct fastbuf *f, struct odes *o) +{ + byte buf[MAX_ATTR_SIZE]; + + while (bgets(f, buf, sizeof(buf))) + { + if (!buf[0]) + return 1; + obj_add_attr(o, buf[0], buf+1); + } + return 0; +} + +void +obj_read_multi(struct fastbuf *f, struct odes *o) +{ + /* Read a multi-part object ending with either EOF or a NUL character */ + byte buf[MAX_ATTR_SIZE]; + while (bpeekc(f) > 0 && bgets(f, buf, sizeof(buf))) + if (buf[0]) + obj_add_attr(o, buf[0], buf+1); }