Annotate

util-src/struct.c @ 13196:eca44e058eed

util.human.io: Use tail call in test to get correct line numbers This is probably not guaranteed to work and might vary with Lua version, but it's good enough for me to get accurate line numbers out of Busted that don't all point to the test() function.
author Kim Alvefur <zash@zash.se>
date Sun, 16 Jul 2023 18:42:58 +0200
parent 12976:a187600ec7d6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12354
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 /*
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 ** {======================================================
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 ** Library for packing/unpacking structures.
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 ** $Id: struct.c,v 1.8 2018/05/16 11:00:23 roberto Exp $
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 ** See Copyright Notice at the end of this file
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 ** =======================================================
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 /*
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 ** Valid formats:
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 ** > - big endian
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 ** < - little endian
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 ** ![num] - alignment
12387
05c250fa335a Spelling: Fix various spelling mistakes (thanks timeless)
Kim Alvefur <zash@zash.se>
parents: 12354
diff changeset
13 ** x - padding
12354
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 ** b/B - signed/unsigned byte
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 ** h/H - signed/unsigned short
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 ** l/L - signed/unsigned long
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 ** T - size_t
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 ** i/In - signed/unsigned integer with size 'n' (default is size of int)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 ** cn - sequence of 'n' chars (from/to a string); when packing, n==0 means
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 the whole string; when unpacking, n==0 means use the previous
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 read number as the string length
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 ** s - zero-terminated string
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 ** f - float
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 ** d - double
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 ** ' ' - ignored
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 #include <ctype.h>
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 #include <limits.h>
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 #include <stddef.h>
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 #include <string.h>
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 #include "lua.h"
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 #include "lauxlib.h"
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 /* basic integer type */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 #if !defined(STRUCT_INT)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 #define STRUCT_INT long
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 #endif
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 typedef STRUCT_INT Inttype;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 /* corresponding unsigned version */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 typedef unsigned STRUCT_INT Uinttype;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 /* maximum size (in bytes) for integral types */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 #define MAXINTSIZE 32
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 /* is 'x' a power of 2? */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 #define isp2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 /* dummy structure to get alignment requirements */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 struct cD {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 char c;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 double d;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 };
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 #define PADDING (sizeof(struct cD) - sizeof(double))
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 #define MAXALIGN (PADDING > sizeof(int) ? PADDING : sizeof(int))
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 /* endian options */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 #define BIG 0
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70 #define LITTLE 1
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73 static union {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 int dummy;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
75 char endian;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
76 } const native = {1};
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
77
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
78
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 typedef struct Header {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 int endian;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 int align;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82 } Header;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 static int getnum (const char **fmt, int df) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
86 if (!isdigit(**fmt)) /* no number? */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
87 return df; /* return default value */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
88 else {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
89 int a = 0;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
90 do {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
91 a = a*10 + *((*fmt)++) - '0';
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
92 } while (isdigit(**fmt));
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
93 return a;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
94 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
95 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
96
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
97
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
98 #define defaultoptions(h) ((h)->endian = native.endian, (h)->align = 1)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
99
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
100
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
101
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
102 static size_t optsize (lua_State *L, char opt, const char **fmt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
103 switch (opt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
104 case 'B': case 'b': return sizeof(char);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
105 case 'H': case 'h': return sizeof(short);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
106 case 'L': case 'l': return sizeof(long);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
107 case 'T': return sizeof(size_t);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
108 case 'f': return sizeof(float);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
109 case 'd': return sizeof(double);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
110 case 'x': return 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
111 case 'c': return getnum(fmt, 1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
112 case 'i': case 'I': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
113 int sz = getnum(fmt, sizeof(int));
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
114 if (sz > MAXINTSIZE)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
115 luaL_error(L, "integral size %d is larger than limit of %d",
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
116 sz, MAXINTSIZE);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
117 return sz;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
118 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
119 default: return 0; /* other cases do not need alignment */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
120 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
121 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
122
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
123
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
124 /*
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
125 ** return number of bytes needed to align an element of size 'size'
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
126 ** at current position 'len'
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
127 */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
128 static int gettoalign (size_t len, Header *h, int opt, size_t size) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
129 if (size == 0 || opt == 'c') return 0;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
130 if (size > (size_t)h->align)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
131 size = h->align; /* respect max. alignment */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
132 return (size - (len & (size - 1))) & (size - 1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
133 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
134
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
135
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
136 /*
12853
e1a71e83d430 util.struct: Fix typo in comment
Kim Alvefur <zash@zash.se>
parents: 12575
diff changeset
137 ** options to control endianness and alignment
12354
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
138 */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
139 static void controloptions (lua_State *L, int opt, const char **fmt,
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
140 Header *h) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
141 switch (opt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
142 case ' ': return; /* ignore white spaces */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
143 case '>': h->endian = BIG; return;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
144 case '<': h->endian = LITTLE; return;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
145 case '!': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
146 int a = getnum(fmt, MAXALIGN);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
147 if (!isp2(a))
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
148 luaL_error(L, "alignment %d is not a power of 2", a);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
149 h->align = a;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
150 return;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
151 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
152 default: {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
153 const char *msg = lua_pushfstring(L, "invalid format option '%c'", opt);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
154 luaL_argerror(L, 1, msg);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
155 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
156 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
157 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
158
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
159
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
160 static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian,
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
161 int size) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
162 lua_Number n = luaL_checknumber(L, arg);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
163 Uinttype value;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
164 char buff[MAXINTSIZE];
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
165 if (n < 0)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
166 value = (Uinttype)(Inttype)n;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
167 else
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
168 value = (Uinttype)n;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
169 if (endian == LITTLE) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
170 int i;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
171 for (i = 0; i < size; i++) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
172 buff[i] = (value & 0xff);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
173 value >>= 8;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
174 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
175 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
176 else {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
177 int i;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
178 for (i = size - 1; i >= 0; i--) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
179 buff[i] = (value & 0xff);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
180 value >>= 8;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
181 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
182 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
183 luaL_addlstring(b, buff, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
184 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
185
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
186
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
187 static void correctbytes (char *b, int size, int endian) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
188 if (endian != native.endian) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
189 int i = 0;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
190 while (i < --size) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
191 char temp = b[i];
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
192 b[i++] = b[size];
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
193 b[size] = temp;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
194 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
195 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
196 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
197
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
198
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
199 static int b_pack (lua_State *L) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
200 luaL_Buffer b;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
201 const char *fmt = luaL_checkstring(L, 1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
202 Header h;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
203 int arg = 2;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
204 size_t totalsize = 0;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
205 defaultoptions(&h);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
206 lua_pushnil(L); /* mark to separate arguments from string buffer */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
207 luaL_buffinit(L, &b);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
208 while (*fmt != '\0') {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
209 int opt = *fmt++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
210 size_t size = optsize(L, opt, &fmt);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
211 int toalign = gettoalign(totalsize, &h, opt, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
212 totalsize += toalign;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
213 while (toalign-- > 0) luaL_addchar(&b, '\0');
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
214 switch (opt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
215 case 'b': case 'B': case 'h': case 'H':
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
216 case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
217 putinteger(L, &b, arg++, h.endian, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
218 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
219 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
220 case 'x': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
221 luaL_addchar(&b, '\0');
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
222 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
223 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
224 case 'f': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
225 float f = (float)luaL_checknumber(L, arg++);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
226 correctbytes((char *)&f, size, h.endian);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
227 luaL_addlstring(&b, (char *)&f, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
228 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
229 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
230 case 'd': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
231 double d = luaL_checknumber(L, arg++);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
232 correctbytes((char *)&d, size, h.endian);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
233 luaL_addlstring(&b, (char *)&d, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
234 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
235 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
236 case 'c': case 's': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
237 size_t l;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
238 const char *s = luaL_checklstring(L, arg++, &l);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
239 if (size == 0) size = l;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
240 luaL_argcheck(L, l >= (size_t)size, arg, "string too short");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
241 luaL_addlstring(&b, s, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
242 if (opt == 's') {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
243 luaL_addchar(&b, '\0'); /* add zero at the end */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
244 size++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
245 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
246 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
247 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
248 default: controloptions(L, opt, &fmt, &h);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
249 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
250 totalsize += size;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
251 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
252 luaL_pushresult(&b);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
253 return 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
254 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
255
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
256
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
257 static lua_Number getinteger (const char *buff, int endian,
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
258 int issigned, int size) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
259 Uinttype l = 0;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
260 int i;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
261 if (endian == BIG) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
262 for (i = 0; i < size; i++) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
263 l <<= 8;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
264 l |= (Uinttype)(unsigned char)buff[i];
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
265 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
266 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
267 else {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
268 for (i = size - 1; i >= 0; i--) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
269 l <<= 8;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
270 l |= (Uinttype)(unsigned char)buff[i];
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
271 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
272 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
273 if (!issigned)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
274 return (lua_Number)l;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
275 else { /* signed format */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
276 Uinttype mask = (Uinttype)(~((Uinttype)0)) << (size*8 - 1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
277 if (l & mask) /* negative value? */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
278 l |= mask; /* signal extension */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
279 return (lua_Number)(Inttype)l;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
280 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
281 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
282
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
283
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
284 static int b_unpack (lua_State *L) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
285 Header h;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
286 const char *fmt = luaL_checkstring(L, 1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
287 size_t ld;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
288 const char *data = luaL_checklstring(L, 2, &ld);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
289 size_t pos = (size_t)luaL_optinteger(L, 3, 1) - 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
290 int n = 0; /* number of results */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
291 luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
292 defaultoptions(&h);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
293 while (*fmt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
294 int opt = *fmt++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
295 size_t size = optsize(L, opt, &fmt);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
296 pos += gettoalign(pos, &h, opt, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
297 luaL_argcheck(L, size <= ld - pos, 2, "data string too short");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
298 /* stack space for item + next position */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
299 luaL_checkstack(L, 2, "too many results");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
300 switch (opt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
301 case 'b': case 'B': case 'h': case 'H':
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
302 case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
303 int issigned = islower(opt);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
304 lua_Number res = getinteger(data+pos, h.endian, issigned, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
305 lua_pushnumber(L, res); n++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
306 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
307 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
308 case 'x': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
309 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
310 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
311 case 'f': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
312 float f;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
313 memcpy(&f, data+pos, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
314 correctbytes((char *)&f, sizeof(f), h.endian);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
315 lua_pushnumber(L, f); n++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
316 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
317 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
318 case 'd': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
319 double d;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
320 memcpy(&d, data+pos, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
321 correctbytes((char *)&d, sizeof(d), h.endian);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
322 lua_pushnumber(L, d); n++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
323 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
324 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
325 case 'c': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
326 if (size == 0) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
327 if (n == 0 || !lua_isnumber(L, -1))
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
328 luaL_error(L, "format 'c0' needs a previous size");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
329 size = lua_tonumber(L, -1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
330 lua_pop(L, 1); n--;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
331 luaL_argcheck(L, size <= ld - pos, 2, "data string too short");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
332 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
333 lua_pushlstring(L, data+pos, size); n++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
334 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
335 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
336 case 's': {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
337 const char *e = (const char *)memchr(data+pos, '\0', ld - pos);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
338 if (e == NULL)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
339 luaL_error(L, "unfinished string in data");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
340 size = (e - (data+pos)) + 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
341 lua_pushlstring(L, data+pos, size - 1); n++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
342 break;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
343 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
344 default: controloptions(L, opt, &fmt, &h);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
345 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
346 pos += size;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
347 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
348 lua_pushinteger(L, pos + 1); /* next position */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
349 return n + 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
350 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
351
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
352
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
353 static int b_size (lua_State *L) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
354 Header h;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
355 const char *fmt = luaL_checkstring(L, 1);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
356 size_t pos = 0;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
357 defaultoptions(&h);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
358 while (*fmt) {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
359 int opt = *fmt++;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
360 size_t size = optsize(L, opt, &fmt);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
361 pos += gettoalign(pos, &h, opt, size);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
362 if (opt == 's')
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
363 luaL_argerror(L, 1, "option 's' has no fixed size");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
364 else if (opt == 'c' && size == 0)
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
365 luaL_argerror(L, 1, "option 'c0' has no fixed size");
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
366 if (!isalnum(opt))
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
367 controloptions(L, opt, &fmt, &h);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
368 pos += size;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
369 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
370 lua_pushinteger(L, pos);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
371 return 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
372 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
373
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
374 /* }====================================================== */
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
375
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
376
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
377
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
378 static const struct luaL_Reg thislib[] = {
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
379 {"pack", b_pack},
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
380 {"unpack", b_unpack},
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
381 {"size", b_size},
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
382 {NULL, NULL}
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
383 };
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
384
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
385
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
386 LUALIB_API int luaopen_util_struct (lua_State *L);
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
387
12976
a187600ec7d6 util: Add compat for prosody module name change to C sources
Kim Alvefur <zash@zash.se>
parents: 12853
diff changeset
388 LUALIB_API int luaopen_prosody_util_struct (lua_State *L) {
12575
1f6f05a98fcd util-src: Remove Lua 5.1 compat macros
Kim Alvefur <zash@zash.se>
parents: 12387
diff changeset
389 luaL_newlib(L, thislib);
12354
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
390 return 1;
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
391 }
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
392
12976
a187600ec7d6 util: Add compat for prosody module name change to C sources
Kim Alvefur <zash@zash.se>
parents: 12853
diff changeset
393 LUALIB_API int luaopen_util_struct (lua_State *L) {
a187600ec7d6 util: Add compat for prosody module name change to C sources
Kim Alvefur <zash@zash.se>
parents: 12853
diff changeset
394 return luaopen_prosody_util_struct(L);
a187600ec7d6 util: Add compat for prosody module name change to C sources
Kim Alvefur <zash@zash.se>
parents: 12853
diff changeset
395 }
a187600ec7d6 util: Add compat for prosody module name change to C sources
Kim Alvefur <zash@zash.se>
parents: 12853
diff changeset
396
12354
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
397
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
398 /******************************************************************************
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
399 * Copyright (C) 2010-2018 Lua.org, PUC-Rio. All rights reserved.
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
400 *
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
401 * Permission is hereby granted, free of charge, to any person obtaining
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
402 * a copy of this software and associated documentation files (the
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
403 * "Software"), to deal in the Software without restriction, including
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
404 * without limitation the rights to use, copy, modify, merge, publish,
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
405 * distribute, sublicense, and/or sell copies of the Software, and to
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
406 * permit persons to whom the Software is furnished to do so, subject to
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
407 * the following conditions:
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
408 *
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
409 * The above copyright notice and this permission notice shall be
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
410 * included in all copies or substantial portions of the Software.
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
411 *
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
412 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
413 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
414 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
415 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
416 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
417 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
418 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
419 ******************************************************************************/
3ce3633527af util.struct: Import Roberto 'struct' library v0.3
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
420