1local bit = require("bit") 2local ffi = require("ffi") 3local band = bit.band 4local bnot = bit.bnot 5 6 7local m = {} 8local Uint8Bound = 256 -- bound is the max uintN + 1 9local Uint16Bound = 65536 10local Uint32Bound = 4294967296 11 12if not table.unpack then 13 table.unpack = unpack 14end 15 16if not table.pack then 17 table.pack = pack 18end 19 20m.GetAlignSize = function(k, size) 21 return band((bnot(k) + 1), (size - 1)) 22end 23 24 25local function pack_I1(n) 26 return string.char(n) 27end 28local function pack_i1(n) 29 if n < 0 then 30 n = Uint8Bound + n 31 end 32 return pack_I1(n) 33end 34 35local function unpack_I1(n, pos) 36 return string.byte(n, pos) 37end 38local function unpack_i1(n, pos) 39 local res = unpack_I1(n, pos) 40 if res >= Uint8Bound / 2 then 41 return res - Uint8Bound 42 end 43 return res 44end 45 46local b2 = ffi.new("unsigned char[2]") 47local function pack_I2(n) 48 for i = 0, 1 do 49 b2[i] = bit.band(n, 255) 50 n = bit.rshift(n, 8) 51 end 52 return ffi.string(b2, 2) 53end 54local function pack_i2(n) 55 if n < 0 then 56 n = Uint16Bound + n 57 end 58 return pack_I2(n) 59end 60 61local function unpack_I2(n, pos) 62 local a, b = string.byte(n, pos, pos + 1) 63 return b * Uint8Bound + a 64end 65local function unpack_i2(n, pos) 66 local res = unpack_I2(n, pos) 67 if res >= Uint16Bound / 2 then 68 return res - Uint16Bound 69 end 70 return res 71end 72 73local b4 = ffi.new("unsigned char[4]") 74local function pack_I4(n) 75 for i = 0, 3 do 76 b4[i] = bit.band(n, 255) 77 n = bit.rshift(n, 8) 78 end 79 return ffi.string(b4, 4) 80end 81local function pack_i4(n) 82 if n < 0 then 83 n = Uint32Bound + n 84 end 85 return pack_I4(n) 86end 87 88local function unpack_I4(n, pos) 89 local a, b, c, d = string.byte(n, pos, pos + 3) 90 return Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a 91end 92local function unpack_i4(n, pos) 93 local res = unpack_I4(n, pos) 94 if res >= Uint32Bound / 2 then 95 return res - Uint32Bound 96 end 97 return res 98end 99 100local b8 = ffi.new("unsigned char[8]") 101local function pack_I8(n) 102 n = ffi.cast("unsigned long long", n) 103 local hi = math.floor(tonumber(n / Uint32Bound)) 104 local li = n % Uint32Bound 105 for i = 0, 3 do 106 b8[i] = bit.band(li, 255) 107 li = bit.rshift(li, 8) 108 end 109 for i = 4, 7 do 110 b8[i] = bit.band(hi, 255) 111 hi = bit.rshift(hi, 8) 112 end 113 return ffi.string(b8, 8) 114end 115local function pack_i8(n) 116 n = ffi.cast("signed long long", n) 117 return pack_I8(n) 118end 119 120local function unpack_I8(n, pos) 121 local a, b, c, d = string.byte(n, pos, pos + 3) 122 local li = Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a 123 local a, b, c, d = string.byte(n, pos + 4, pos + 7) 124 local hi = Uint8Bound * (Uint8Bound * ((Uint8Bound * d) + c) + b) + a 125 return ffi.cast("unsigned long long", hi) * Uint32Bound + li 126end 127local function unpack_i8(n, pos) 128 local res = unpack_I8(n, pos) 129 return ffi.cast("signed long long", res) 130end 131 132local bf = ffi.new("float[1]") 133local function pack_f(n) 134 bf[0] = n 135 return ffi.string(bf, 4) 136end 137 138local function unpack_f(n, pos) 139 ffi.copy(bf, ffi.cast("char *", n) + pos - 1, 4) 140 return tonumber(bf[0]) 141end 142 143local bd = ffi.new("double[1]") 144local function pack_d(n) 145 bd[0] = n 146 return ffi.string(bd, 8) 147end 148 149local function unpack_d(n, pos) 150 ffi.copy(bd, ffi.cast("char *", n) + pos - 1, 8) 151 return tonumber(bd[0]) 152end 153 154 155m.string_pack = function(fmt, i, ...) 156 if fmt == "<I1" then 157 return pack_I1(i) 158 elseif fmt == "<I2" then 159 return pack_I2(i) 160 elseif fmt == "<I4" then 161 return pack_I4(i) 162 elseif fmt == "<I8" then 163 return pack_I8(i) 164 elseif fmt == "<i1" then 165 return pack_i1(i) 166 elseif fmt == "<i2" then 167 return pack_i2(i) 168 elseif fmt == "<i4" then 169 return pack_i4(i) 170 elseif fmt == "<i8" then 171 return pack_i8(i) 172 elseif fmt == "<f" then 173 return pack_f(i) 174 elseif fmt == "<d" then 175 return pack_d(i) 176 else 177 error(string.format("FIXME: support fmt %s", fmt)) 178 end 179end 180 181 182m.string_unpack = function(fmt, s, pos) 183 if not pos then 184 pos = 1 185 end 186 187 if fmt == "<I1" then 188 return unpack_I1(s, pos) 189 elseif fmt == "<I2" then 190 return unpack_I2(s, pos) 191 elseif fmt == "<I4" then 192 return unpack_I4(s, pos) 193 elseif fmt == "<I8" then 194 return unpack_I8(s, pos) 195 elseif fmt == "<i1" then 196 return unpack_i1(s, pos) 197 elseif fmt == "<i2" then 198 return unpack_i2(s, pos) 199 elseif fmt == "<i4" then 200 return unpack_i4(s, pos) 201 elseif fmt == "<i8" then 202 return unpack_i8(s, pos) 203 elseif fmt == "<f" then 204 return unpack_f(s, pos) 205 elseif fmt == "<d" then 206 return unpack_d(s, pos) 207 else 208 error(string.format("FIXME: support fmt %s", fmt)) 209 end 210end 211 212 213return m 214