ref: f6d84677e9cd1cd4725391a577295ff561e09443
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;
}