ref: c6821e9c478e8c1e4effdba02cfe7d56a78c3cd9
dir: /amf.c/
#include <u.h> #include <libc.h> #include "amf.h" enum { Anum, Abool, Astr, Aobj, Aarr = 8, Aend, Alstr = 12, }; #define atleast(x) do{ \ if(p == nil) \ return nil; \ if(e-p < x){ \ werrstr("buffer short"); \ return nil; \ } \ }while(0) u8int * amfbool(u8int *p, u8int *e, int v) { atleast(2); *p++ = Abool; *p++ = !!v; return p; } u8int * amfbyte(u8int *p, u8int *e, u8int byte) { atleast(1); *p++ = byte; return p; } u8int * amfi16(u8int *p, u8int *e, s16int i) { atleast(2); *p++ = i >> 8; *p++ = i; return p; } u8int * amfi24(u8int *p, u8int *e, s32int i) { atleast(3); *p++ = i >> 16; *p++ = i >> 8; *p++ = i; return p; } u8int * amfi32(u8int *p, u8int *e, s32int i) { atleast(4); *p++ = i >> 24; *p++ = i >> 16; *p++ = i >> 8; *p++ = i; return p; } u8int * amfnum(u8int *p, u8int *e, double v) { union { double v; u64int u; }x; atleast(1+8); *p++ = Anum; x.v = v; *p++ = x.u >> 56; *p++ = x.u >> 48; *p++ = x.u >> 40; *p++ = x.u >> 32; *p++ = x.u >> 24; *p++ = x.u >> 16; *p++ = x.u >> 8; *p++ = x.u; return p; } u8int * amfstr(u8int *p, u8int *e, char *s) { int n; n = strlen(s); if(n <= 0xffff){ atleast(1+2+n); *p++ = Astr; return (u8int*)memmove(amfi16(p, e, n), s, n) + n; } atleast(1+4+n); *p++ = Alstr; return (u8int*)memmove(amfi32(p, e, n), s, n) + n; } u8int * amfarr(u8int *p, u8int *e) { return amfbyte(p, e, Aarr); } u8int * amfobj(u8int *p, u8int *e) { return amfbyte(p, e, Aobj); } u8int * amfend(u8int *p, u8int *e) { return amfi24(p, e, Aend); } static u8int * amfkv(u8int *p, u8int *e, char *name) { int n; if((n = strlen(name)) > 0xffff){ werrstr("string too long"); return nil; } atleast(2+n); p = amfi16(p, e, n); return (u8int*)memmove(p, name, n) + n; } u8int * amfkvbool(u8int *p, u8int *e, char *name, int v) { return amfbool(amfkv(p, e, name), e, v); } u8int * amfkvnum(u8int *p, u8int *e, char *name, double v) { return amfnum(amfkv(p, e, name), e, v); } u8int * amfkvstr(u8int *p, u8int *e, char *name, char *v) { return amfstr(amfkv(p, e, name), e, v); } u8int * amfbyteget(u8int *p, u8int *e, u8int *byte) { atleast(1); *byte = *p; return p+1; } u8int * amfi16get(u8int *p, u8int *e, s16int *i) { atleast(2); *i = p[0]<<8 | p[1]; return p+2; } u8int * amfi24get(u8int *p, u8int *e, s32int *i) { atleast(3); *i = p[0]<<16 | p[1]<<8 | p[2]; return p+3; } u8int * amfi32get(u8int *p, u8int *e, s32int *i) { atleast(4); *i = p[0]<<16 | p[1]<<16 | p[2]<<8 | p[3]; return p+4; }