00001 #include <string.h>
00002 #include "data.h"
00003
00004
00005
00006
00007
00008 #define MSK(n) (1 << (7 - ((n) & 7)))
00009 #define BIT(s,l,n) s[(n)>>3] & MSK(n)
00010 #define CLRB(s,l,n) s[(n)>>3] &= ~MSK(n)
00011 #define SETB(s,l,n) s[(n)>>3] |= MSK(n)
00012
00013 static unsigned int fld(naContext c, unsigned char* s,
00014 int slen, int bit, int flen)
00015 {
00016 int i;
00017 unsigned int fld = 0;
00018 if(bit + flen > 8*slen) naRuntimeError(c, "bitfield out of bounds");
00019 for(i=0; i<flen; i++) if(BIT(s, slen, bit+flen-i-1)) fld |= (1<<i);
00020 return fld;
00021 }
00022
00023 static void setfld(naContext c, unsigned char* s, int slen,
00024 int bit, int flen, unsigned int fld)
00025 {
00026 int i;
00027 if(bit + flen > 8*slen) naRuntimeError(c, "bitfield out of bounds");
00028 for(i=0; i<flen; i++)
00029 if(fld & (1<<i)) SETB(s, slen, i+bit);
00030 else CLRB(s, slen, i+bit);
00031 }
00032
00033 static naRef dofld(naContext c, int argc, naRef* args, int sign)
00034 {
00035 naRef s = argc > 0 ? args[0] : naNil();
00036 int bit = argc > 1 ? (int)naNumValue(args[1]).num : -1;
00037 int len = argc > 2 ? (int)naNumValue(args[2]).num : -1;
00038 unsigned int f;
00039 if(!naIsString(s) || !MUTABLE(args[0]) || bit < 0 || len < 0)
00040 naRuntimeError(c, "missing/bad argument to fld/sfld");
00041 f = fld(c, (void*)naStr_data(s), naStr_len(s), bit, len);
00042 if(!sign) return naNum(f);
00043 if(f & (1 << (len-1))) f |= ~((1<<len)-1);
00044 return naNum((signed int)f);
00045 }
00046
00047 static naRef f_sfld(naContext c, naRef me, int argc, naRef* args)
00048 {
00049 return dofld(c, argc, args, 1);
00050 }
00051
00052 static naRef f_fld(naContext c, naRef me, int argc, naRef* args)
00053 {
00054 return dofld(c, argc, args, 0);
00055 }
00056
00057 static naRef f_setfld(naContext c, naRef me, int argc, naRef* args)
00058 {
00059 naRef s = argc > 0 ? args[0] : naNil();
00060 int bit = argc > 1 ? (int)naNumValue(args[1]).num : -1;
00061 int len = argc > 2 ? (int)naNumValue(args[2]).num : -1;
00062 naRef val = argc > 3 ? naNumValue(args[3]) : naNil();
00063 if(!argc || !MUTABLE(args[0])|| bit < 0 || len < 0 || IS_NIL(val))
00064 naRuntimeError(c, "missing/bad argument to setfld");
00065 setfld(c, (void*)naStr_data(s), naStr_len(s), bit, len, (unsigned int)val.num);
00066 return naNil();
00067 }
00068
00069 static naRef f_buf(naContext c, naRef me, int argc, naRef* args)
00070 {
00071 naRef len = argc ? naNumValue(args[0]) : naNil();
00072 if(IS_NIL(len)) naRuntimeError(c, "missing/bad argument to buf");
00073 return naStr_buf(naNewString(c), (int)len.num);
00074 }
00075
00076 static naCFuncItem funcs[] = {
00077 { "sfld", f_sfld },
00078 { "fld", f_fld },
00079 { "setfld", f_setfld },
00080 { "buf", f_buf },
00081 { 0 }
00082 };
00083
00084 naRef naInit_bits(naContext c)
00085 {
00086 return naGenLib(c, funcs);
00087 }