| #include "stdinc.h" |
| #include "dat.h" |
| #include "fns.h" |
| |
| void |
| fmtzbinit(Fmt *f, ZBlock *b) |
| { |
| memset(f, 0, sizeof *f); |
| #ifdef PLAN9PORT |
| fmtlocaleinit(f, nil, nil, nil); |
| #endif |
| f->start = b->data; |
| f->to = f->start; |
| f->stop = (char*)f->start + b->len; |
| } |
| |
| #define ROUNDUP(p, n) ((void*)(((uintptr)(p)+(n)-1)&~(uintptr)((n)-1))) |
| |
| enum { |
| OverflowCheck = 32 |
| }; |
| static char zmagic[] = "1234567890abcdefghijklmnopqrstuvxyz"; |
| |
| ZBlock * |
| alloczblock(u32int size, int zeroed, uint blocksize) |
| { |
| uchar *p, *data; |
| ZBlock *b; |
| static ZBlock z; |
| int n; |
| |
| if(blocksize == 0) |
| blocksize = 32; /* try for cache line alignment */ |
| |
| n = size+OverflowCheck+sizeof(ZBlock)+blocksize+8; |
| p = malloc(n); |
| if(p == nil){ |
| seterr(EOk, "out of memory"); |
| return nil; |
| } |
| |
| data = ROUNDUP(p, blocksize); |
| b = ROUNDUP(data+size+OverflowCheck, 8); |
| if(0) fprint(2, "alloc %p-%p data %p-%p b %p-%p\n", |
| p, p+n, data, data+size, b, b+1); |
| *b = z; |
| b->data = data; |
| b->free = p; |
| b->len = size; |
| b->_size = size; |
| if(zeroed) |
| memset(b->data, 0, size); |
| memmove(b->data+size, zmagic, OverflowCheck); |
| return b; |
| } |
| |
| void |
| freezblock(ZBlock *b) |
| { |
| if(b){ |
| if(memcmp(b->data+b->_size, zmagic, OverflowCheck) != 0) |
| abort(); |
| memset(b->data+b->_size, 0, OverflowCheck); |
| free(b->free); |
| } |
| } |
| |
| ZBlock* |
| packet2zblock(Packet *p, u32int size) |
| { |
| ZBlock *b; |
| |
| if(p == nil) |
| return nil; |
| b = alloczblock(size, 0, 0); |
| if(b == nil) |
| return nil; |
| if(packetcopy(p, b->data, 0, size) < 0){ |
| freezblock(b); |
| return nil; |
| } |
| return b; |
| } |
| |
| Packet* |
| zblock2packet(ZBlock *zb, u32int size) |
| { |
| Packet *p; |
| |
| if(zb == nil) |
| return nil; |
| p = packetalloc(); |
| packetappend(p, zb->data, size); |
| return p; |
| } |
| |