1/*
2 * Copyright 2008-2018 Aerospike, Inc.
3 *
4 * Portions may be licensed to Aerospike, Inc. under one or more contributor
5 * license agreements.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
8 * use this file except in compliance with the License. You may obtain a copy of
9 * the License at http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17#include <aerospike/mod_lua_bytes.h>
18#include <aerospike/as_val.h>
19#include <aerospike/mod_lua_val.h>
20#include <aerospike/mod_lua_iterator.h>
21#include <aerospike/mod_lua_reg.h>
22#include <citrusleaf/alloc.h>
23#include <citrusleaf/cf_byte_order.h>
24#include <stddef.h>
25#include <string.h>
26
27#include "internal.h"
28
29/*******************************************************************************
30 * MACROS
31 ******************************************************************************/
32
33#define OBJECT_NAME "bytes"
34#define CLASS_NAME "Bytes"
35
36/*******************************************************************************
37 * BOX FUNCTIONS
38 ******************************************************************************/
39
40as_bytes * mod_lua_tobytes(lua_State * l, int index) {
41 mod_lua_box * box = mod_lua_tobox(l, index, CLASS_NAME);
42 return (as_bytes *) mod_lua_box_value(box);
43}
44
45as_bytes * mod_lua_pushbytes(lua_State * l, as_bytes * b) {
46 mod_lua_box * box = mod_lua_pushbox(l, MOD_LUA_SCOPE_LUA, b, CLASS_NAME);
47 return (as_bytes *) mod_lua_box_value(box);
48}
49
50static as_bytes * mod_lua_checkbytes(lua_State * l, int index) {
51 mod_lua_box * box = mod_lua_checkbox(l, index, CLASS_NAME);
52 return (as_bytes *) mod_lua_box_value(box);
53}
54
55static int mod_lua_bytes_gc(lua_State * l) {
56 mod_lua_freebox(l, 1, CLASS_NAME);
57 return 0;
58}
59
60/*******************************************************************************
61 * FUNCTIONS
62 ******************************************************************************/
63
64static int mod_lua_bytes_size(lua_State * l)
65{
66 // we expect 1 arg
67 if ( lua_gettop(l) != 1 ) {
68 lua_pushinteger(l, 0);
69 return 1;
70 }
71
72 as_bytes * b = mod_lua_checkbytes(l, 1);
73
74 // check preconditions:
75 // - b != NULL
76 if ( !b ) {
77 lua_pushinteger(l, 0);
78 return 1;
79 }
80
81 lua_pushinteger(l, as_bytes_size(b));
82 return 1;
83}
84
85/*
86static int mod_lua_bytes_capacity(lua_State * l)
87{
88 // we expect 1 arg
89 if ( lua_gettop(l) != 1 ) {
90 lua_pushinteger(l, 0);
91 return 1;
92 }
93
94 as_bytes * b = mod_lua_checkbytes(l, 1);
95
96 // check preconditions:
97 // - b != NULL
98 if ( !b ) {
99 lua_pushinteger(l, 0);
100 return 1;
101 }
102
103 lua_pushinteger(l, as_bytes_capacity(b));
104 return 1;
105}
106*/
107
108static int mod_lua_bytes_ensure(lua_State *l)
109{
110 // we expect 2 args
111 if ( lua_gettop(l) != 2) {
112 lua_pushboolean(l, false);
113 return 1;
114 }
115
116 as_bytes * b = mod_lua_checkbytes(l, 1);
117 lua_Integer c = luaL_optinteger(l, 2, 0);
118 int r = luaL_optint(l, 3, 0);
119
120 // check preconditions:
121 // - b != NULL
122 // - 0 <= c <= INT32_MAX
123 if ( !b ||
124 c < 0 || c > UINT32_MAX ||
125 r < 0 || r > 1) {
126 lua_pushboolean(l, false);
127 return 1;
128 }
129
130 bool res = as_bytes_ensure(b, (uint32_t) c, r==1);
131 lua_pushboolean(l, res);
132 return 1;
133}
134
135/*
136static int mod_lua_bytes_truncate(lua_State *l)
137{
138 // we expect 2 args
139 if ( lua_gettop(l) != 2) {
140 lua_pushboolean(l, false);
141 return 1;
142 }
143
144 as_bytes * b = mod_lua_checkbytes(l, 1);
145 lua_Integer n = luaL_optinteger(l, 2, 0);
146
147 // check preconditions:
148 // - b != NULL
149 // - 0 <= v <= INT32_MAX
150 if ( !b ||
151 n < 0 || n > UINT32_MAX ) {
152 lua_pushboolean(l, false);
153 return 1;
154 }
155
156 bool res = as_bytes_truncate(b, (uint32_t) n);
157 lua_pushboolean(l, res);
158 return 1;
159}
160*/
161
162static int mod_lua_bytes_new(lua_State * l)
163{
164 int argc = lua_gettop(l);
165
166 as_bytes * bytes = NULL;
167
168 if ( argc == 1 ) {
169 // no arguments
170 bytes = as_bytes_new(0);
171 }
172 else if ( argc == 2 ) {
173 // single integer argument for capacity
174 lua_Integer n = luaL_optinteger(l, 2, 0);
175 bytes = as_bytes_new((uint32_t) n);
176 }
177
178 if ( !bytes ) {
179 return 0;
180 }
181
182 mod_lua_pushbytes(l, bytes);
183 return 1;
184}
185
186static int mod_lua_bytes_tostring(lua_State * l)
187{
188 // we expect 1 arg
189 if ( lua_gettop(l) != 1 ) {
190 lua_pushinteger(l, 0);
191 return 1;
192 }
193
194 mod_lua_box * box = mod_lua_checkbox(l, 1, CLASS_NAME);
195 as_val * val = mod_lua_box_value(box);
196 char * str = NULL;
197
198 if ( val ) {
199 str = as_val_tostring(val);
200 }
201
202 if ( str ) {
203 lua_pushstring(l, str);
204 cf_free(str);
205 }
206 else {
207 lua_pushstring(l, "Bytes()");
208 }
209
210 return 1;
211}
212
213/**
214 * Get the type of bytes:
215 *
216 * ----------{.c}
217 * uint bytes.type(bytes b)
218 * ----------
219 *
220 */
221static int mod_lua_bytes_get_type(lua_State * l)
222{
223 // we expect atleast 1 arg
224 if ( lua_gettop(l) < 1 ) {
225 return 0;
226 }
227
228 as_bytes * b = mod_lua_checkbytes(l, 1);
229
230 // check preconditions:
231 // - b != NULL
232 if ( !b ) {
233 return 0;
234 }
235
236 lua_pushinteger(l, as_bytes_get_type(b));
237 return 1;
238}
239
240/**
241 * Set the type of bytes:
242 *
243 * ----------{.c}
244 * bool bytes.type(bytes b, uint 5)
245 * ----------
246 */
247static int mod_lua_bytes_set_type(lua_State * l)
248{
249 // we expect 2 args
250 if ( lua_gettop(l) != 2 ) {
251 lua_pushboolean(l, false);
252 return 1;
253 }
254
255 as_bytes * b = mod_lua_checkbytes(l, 1);
256 lua_Integer t = luaL_optinteger(l, 2, 0);
257
258 // check preconditions:
259 // - b != NULL
260 if ( !b || !t ) {
261 lua_pushboolean(l, false);
262 return 1;
263 }
264
265 as_bytes_set_type(b, (as_bytes_type)t);
266 lua_pushboolean(l, true);
267 return 1;
268}
269
270
271/******************************************************************************
272 * APPEND FUNCTIONS
273 *****************************************************************************/
274
275/**
276 * Append a byte value.
277 *
278 * ----------{.c}
279 * bool bytes.append_byte(bytes b, uint8 v)
280 * ----------
281 *
282 * @param b The bytes to set a value in.
283 * @param v The uint8_t value append to b.
284 *
285 * @return On success, true. Otherwise, false on error.
286 */
287static int mod_lua_bytes_append_byte(lua_State * l)
288{
289 // we expect 2 args
290 if ( lua_gettop(l) != 2 ) {
291 lua_pushboolean(l, false);
292 return 1;
293 }
294
295 as_bytes * b = mod_lua_checkbytes(l, 1);
296 lua_Integer v = luaL_optinteger(l, 2, 0);
297
298 // check preconditions:
299 // - b != NULL
300 // - UINT8_MIN <= v <= UINT8_MAX
301 if ( !b ||
302 v < 0 || v > UINT8_MAX ) {
303 lua_pushboolean(l, false);
304 return 1;
305 }
306
307 bool res = false;
308 uint32_t pos = b->size;
309 uint32_t size = 1;
310
311 // ensure we have capacity, if not, then resize
312 if ( as_bytes_ensure(b, pos + size, true) == true ) {
313 // write the bytes
314 res = as_bytes_append_byte(b, (uint8_t)v);
315 }
316
317 lua_pushboolean(l, res);
318 return 1;
319}
320
321/**
322 * Append a big endian int16 value.
323 *
324 * ----------{.c}
325 * bool bytes.append_int16_be(bytes b, int16 v)
326 * ----------
327 *
328 * @param b The bytes to set a value in.
329 * @param v The int16_t value to append to b.
330 *
331 * @return On success, true. Otherwise, false on error.
332 */
333static int mod_lua_bytes_append_int16_be(lua_State * l)
334{
335 // we expect 2 args
336 if ( lua_gettop(l) != 2 ) {
337 lua_pushboolean(l, false);
338 return 1;
339 }
340
341 as_bytes * b = mod_lua_checkbytes(l, 1);
342 lua_Integer v = luaL_optinteger(l, 2, 0);
343
344 // check preconditions:
345 // - b != NULL
346 // - INT32_MIN <= v <= INT32_MAX
347 if ( !b ||
348 v < INT16_MIN || v > INT16_MAX ) {
349 lua_pushboolean(l, false);
350 return 1;
351 }
352
353 bool res = false;
354 uint32_t pos = b->size;
355 uint32_t size = 2;
356
357 // ensure we have capacity, if not, then resize
358 if ( as_bytes_ensure(b, pos + size, true) == true ) {
359 // write the bytes
360 int16_t val = cf_swap_to_be16((int16_t) v);
361 res = as_bytes_append_int16(b, val);
362 }
363
364 lua_pushboolean(l, res);
365 return 1;
366}
367
368/**
369 * Append a little endian int16 value.
370 *
371 * ----------{.c}
372 * bool bytes.append_int16_le(bytes b, int16 v)
373 * ----------
374 *
375 * @param b The bytes to set a value in.
376 * @param v The int16_t value to append to b.
377 *
378 * @return On success, true. Otherwise, false on error.
379 */
380static int mod_lua_bytes_append_int16_le(lua_State * l)
381{
382 // we expect 2 args
383 if ( lua_gettop(l) != 2 ) {
384 lua_pushboolean(l, false);
385 return 1;
386 }
387
388 as_bytes * b = mod_lua_checkbytes(l, 1);
389 lua_Integer v = luaL_optinteger(l, 2, 0);
390
391 // check preconditions:
392 // - b != NULL
393 // - INT32_MIN <= v <= INT32_MAX
394 if ( !b ||
395 v < INT16_MIN || v > INT16_MAX ) {
396 lua_pushboolean(l, false);
397 return 1;
398 }
399
400 bool res = false;
401 uint32_t pos = b->size;
402 uint32_t size = 2;
403
404 // ensure we have capacity, if not, then resize
405 if ( as_bytes_ensure(b, pos + size, true) == true ) {
406 // write the bytes
407 int16_t val = cf_swap_to_le16((int16_t) v);
408 res = as_bytes_append_int16(b, val);
409 }
410
411 lua_pushboolean(l, res);
412 return 1;
413}
414
415/**
416 * Append a big endian int32 value.
417 *
418 * ----------{.c}
419 * bool bytes.append_int32_be(b, v)
420 * ----------
421 *
422 * @param b The bytes to set a value in.
423 * @param v The int32_t value to append to b.
424 *
425 * @return On success, true. Otherwise, false on error.
426 */
427static int mod_lua_bytes_append_int32_be(lua_State * l)
428{
429 // we expect 2 args
430 if ( lua_gettop(l) != 2 ) {
431 lua_pushboolean(l, false);
432 return 1;
433 }
434
435 as_bytes * b = mod_lua_checkbytes(l, 1);
436 lua_Integer v = luaL_optinteger(l, 2, 0);
437
438 // check preconditions:
439 // - b != NULL
440 // - INT32_MIN <= v <= INT32_MAX
441 if ( !b ||
442 v < INT32_MIN || v > INT32_MAX ) {
443 lua_pushboolean(l, false);
444 return 1;
445 }
446
447 bool res = false;
448 uint32_t pos = b->size;
449 uint32_t size = 4;
450
451 // ensure we have capacity, if not, then resize
452 if ( as_bytes_ensure(b, pos + size, true) == true ) {
453 // write the bytes
454 int32_t val = cf_swap_to_be32((int32_t) v);
455 res = as_bytes_append_int32(b, val);
456 }
457
458 lua_pushboolean(l, res);
459 return 1;
460}
461
462/**
463 * Append a little endian int32 value.
464 *
465 * ----------{.c}
466 * bool bytes.append_int32_le(b, v)
467 * ----------
468 *
469 * @param b The bytes to set a value in.
470 * @param v The int32_t value to append to b.
471 *
472 * @return On success, true. Otherwise, false on error.
473 */
474static int mod_lua_bytes_append_int32_le(lua_State * l)
475{
476 // we expect 2 args
477 if ( lua_gettop(l) != 2 ) {
478 lua_pushboolean(l, false);
479 return 1;
480 }
481
482 as_bytes * b = mod_lua_checkbytes(l, 1);
483 lua_Integer v = luaL_optinteger(l, 2, 0);
484
485 // check preconditions:
486 // - b != NULL
487 // - INT32_MIN <= v <= INT32_MAX
488 if ( !b ||
489 v < INT32_MIN || v > INT32_MAX ) {
490 lua_pushboolean(l, false);
491 return 1;
492 }
493
494 bool res = false;
495 uint32_t pos = b->size;
496 uint32_t size = 4;
497
498 // ensure we have capacity, if not, then resize
499 if ( as_bytes_ensure(b, pos + size, true) == true ) {
500 // write the bytes
501 int32_t val = cf_swap_to_le32((int32_t) v);
502 res = as_bytes_append_int32(b, val);
503 }
504
505 lua_pushboolean(l, res);
506 return 1;
507}
508
509/**
510 * Append a big endian int64 value.
511 *
512 * ----------{.c}
513 * bool bytes.append_int64_be(b, v)
514 * ----------
515 *
516 * @param b The bytes to set a value in.
517 * @param v The int64_t value to append to b.
518 *
519 * @return On success, true. Otherwise, false on error.
520 */
521static int mod_lua_bytes_append_int64_be(lua_State * l)
522{
523 // we expect 2 args
524 if ( lua_gettop(l) != 2 ) {
525 lua_pushboolean(l, false);
526 return 1;
527 }
528
529 as_bytes * b = mod_lua_checkbytes(l, 1);
530 lua_Integer v = luaL_optinteger(l, 2, 0);
531
532 // check preconditions:
533 // - b != NULL
534 if ( !b ) {
535 lua_pushboolean(l, false);
536 return 1;
537 }
538
539 bool res = false;
540 uint32_t pos = b->size;
541 uint32_t size = 8;
542
543 // ensure we have capacity, if not, then resize
544 if ( as_bytes_ensure(b, pos + size, true) == true ) {
545 // write the bytes
546 int64_t val = cf_swap_to_be64((int64_t) v);
547 res = as_bytes_append_int64(b, val);
548 }
549
550 lua_pushboolean(l, res);
551 return 1;
552}
553
554/**
555 * Append a little endian int64 value.
556 *
557 * ----------{.c}
558 * bool bytes.append_int64_le(b, v)
559 * ----------
560 *
561 * @param b The bytes to set a value in.
562 * @param v The int64_t value to append to b.
563 *
564 * @return On success, true. Otherwise, false on error.
565 */
566static int mod_lua_bytes_append_int64_le(lua_State * l)
567{
568 // we expect 2 args
569 if ( lua_gettop(l) != 2 ) {
570 lua_pushboolean(l, false);
571 return 1;
572 }
573
574 as_bytes * b = mod_lua_checkbytes(l, 1);
575 lua_Integer v = luaL_optinteger(l, 2, 0);
576
577 // check preconditions:
578 // - b != NULL
579 if ( !b ) {
580 lua_pushboolean(l, false);
581 return 1;
582 }
583
584 bool res = false;
585 uint32_t pos = b->size;
586 uint32_t size = 8;
587
588 // ensure we have capacity, if not, then resize
589 if ( as_bytes_ensure(b, pos + size, true) == true ) {
590 // write the bytes
591 int64_t val = cf_swap_to_le64((int64_t) v);
592 res = as_bytes_append_int64(b, val);
593 }
594
595 lua_pushboolean(l, res);
596 return 1;
597}
598
599/**
600 * Append an integer in variable 7-bit format at specified index.
601 * The high bit indicates if more bytes are used.
602 *
603 * ----------{.c}
604 * bool bytes.append_var_int(b, v)
605 * ----------
606 *
607 * @param b The bytes to set a value in.
608 * @param v The integer value to append to b.
609 *
610 * @return number of bytes used to store integer
611 */
612static int mod_lua_bytes_append_var_int(lua_State * l)
613{
614 // we expect 2 args
615 if ( lua_gettop(l) != 2 ) {
616 lua_pushinteger(l, 0);
617 return 1;
618 }
619
620 as_bytes * b = mod_lua_checkbytes(l, 1);
621 lua_Integer v = luaL_optinteger(l, 2, 0);
622
623 // check preconditions:
624 // - b != NULL
625 // - INT32_MIN <= v <= INT32_MAX
626 if ( !b ||
627 v < INT32_MIN || v > INT32_MAX ) {
628 lua_pushinteger(l, 0);
629 return 1;
630 }
631
632 uint32_t size = 0;
633 uint32_t pos = b->size;
634
635 // ensure we have capacity, if not, then resize
636 if ( as_bytes_ensure(b, pos + 5, true) == true ) {
637 size = as_bytes_set_var_int(b, pos, (uint32_t)v);
638 }
639
640 lua_pushinteger(l, size);
641 return 1;
642}
643
644/**
645 * Append a NULL-terminated string value.
646 *
647 * ----------{.c}
648 * bool bytes.append_string(bytes b, string v)
649 * ----------
650 *
651 * @param b The bytes to set a value in.
652 * @param v The NULL-terminated string value to append to b.
653 *
654 * @return On success, true. Otherwise, false on error.
655 */
656static int mod_lua_bytes_append_string(lua_State * l)
657{
658 // we expect 2 args
659 if ( lua_gettop(l) != 2 ) {
660 lua_pushboolean(l, false);
661 return 1;
662 }
663
664 as_bytes * b = mod_lua_checkbytes(l, 1);
665 size_t n = 0;
666 const char * v = luaL_optlstring(l, 2, NULL, &n);
667
668 // check preconditions:
669 // - b != NULL
670 // - v != NULL
671 // - n != 0
672 if ( !b || !v || !n ) {
673 lua_pushboolean(l, false);
674 return 1;
675 }
676
677 bool res = false;
678 uint32_t pos = b->size;
679 uint32_t size = (uint32_t)n;
680
681 // ensure we have capacity, if not, then resize
682 if ( as_bytes_ensure(b, pos + size, true) == true ) {
683 // write the bytes
684 res = as_bytes_append(b, (uint8_t *) v, size);
685 }
686
687 lua_pushboolean(l, res);
688 return 1;
689}
690
691/**
692 * Append a NULL-terminated string value.
693 *
694 * ----------{.c}
695 * bool bytes.append_string(bytes b, bytes v, uint32 n)
696 * ----------
697 *
698 * @param b The bytes to set a value in.
699 * @param v The bytes value to append to b.
700 * @param n The number of bytes to append to b.
701 *
702 * @return On success, true. Otherwise, false on error.
703 */
704static int mod_lua_bytes_append_bytes(lua_State * l)
705{
706 // we expect 3 args
707 if ( lua_gettop(l) != 3 ) {
708 lua_pushboolean(l, false);
709 return 1;
710 }
711
712 as_bytes * b = mod_lua_checkbytes(l, 1);
713 as_bytes * v = mod_lua_checkbytes(l, 2);
714 lua_Integer n = luaL_optinteger(l, 3, 0);
715
716 // check preconditions:
717 // - b != NULL
718 // - v != NULL
719 // - UINT32_MIN <= n <= UINT32_MAX
720 if ( !b ||
721 !v ||
722 n < 0 || n > UINT32_MAX ) {
723 lua_pushboolean(l, false);
724 return 1;
725 }
726
727 bool res = false;
728 uint32_t pos = b->size;
729 uint32_t size = n > v->size ? v->size : (uint32_t)n;
730
731 // ensure we have capacity, if not, then resize
732 if ( as_bytes_ensure(b, pos + size, true) == true ) {
733 // write the bytes
734 res = as_bytes_append(b, (uint8_t *) v->value, size);
735 }
736
737 lua_pushboolean(l, res);
738 return 1;
739}
740
741/******************************************************************************
742 * SET FUNCTIONS
743 *****************************************************************************/
744
745/**
746 * Set a byte value at specified index.
747 *
748 * ----------{.c}
749 * bool bytes.set_byte(bytes b, uint32 i, uint8 v)
750 * ----------
751 *
752 * @param b The bytes to set a value in.
753 * @param i The index in b to set the value of.
754 * @param v The uint8_t value to set at i.
755 *
756 * @return On success, true. Otherwise, false on error.
757 */
758static int mod_lua_bytes_set_byte(lua_State * l)
759{
760 // we expect 3 args
761 if ( lua_gettop(l) != 3 ) {
762 lua_pushboolean(l, false);
763 return 1;
764 }
765
766 as_bytes * b = mod_lua_checkbytes(l, 1);
767 lua_Integer i = luaL_optinteger(l, 2, 0);
768 lua_Integer v = luaL_optinteger(l, 3, 0);
769
770 // check preconditions:
771 // - b != NULL
772 // - 1 <= i <= UINT32_MAX
773 // - 0 <= v <= UINT8_MAX
774 if ( !b ||
775 i < 1 || i > UINT32_MAX ||
776 v < 0 || v > UINT8_MAX ) {
777 lua_pushboolean(l, false);
778 return 1;
779 }
780
781 bool res = false;
782 uint32_t pos = (uint32_t)(i - 1);
783 uint32_t size = 1;
784
785 // ensure we have capacity, if not, then resize
786 if ( as_bytes_ensure(b, pos + size, true) == true ) {
787 // write the bytes
788 res = as_bytes_set_byte(b, pos, (uint8_t)v);
789 }
790
791 lua_pushboolean(l, res);
792 return 1;
793}
794
795/**
796 * Set a big endian int16 value at specified index.
797 *
798 * ----------{.c}
799 * bool bytes.set_int16_be(bytes b, uint32 i, int16 v)
800 * ----------
801 *
802 * @param b The bytes to set a value in.
803 * @param i The index in b to set the value of.
804 * @param v The int16_t value to set at i.
805 *
806 * @return On success, true. Otherwise, false on error.
807 */
808static int mod_lua_bytes_set_int16_be(lua_State * l)
809{
810 // we expect 3 args
811 if ( lua_gettop(l) != 3 ) {
812 lua_pushboolean(l, false);
813 return 1;
814 }
815
816 as_bytes * b = mod_lua_checkbytes(l, 1);
817 lua_Integer i = luaL_optinteger(l, 2, 0);
818 lua_Integer v = luaL_optinteger(l, 3, 0);
819
820 // check preconditions:
821 // - b != NULL
822 // - 1 <= i <= UINT32_MAX
823 // - INT16_MIN <= v <= INT16_MAX
824 if ( !b ||
825 i < 1 || i > UINT32_MAX ||
826 v < INT16_MIN || v > INT16_MAX ) {
827 lua_pushboolean(l, false);
828 return 1;
829 }
830
831 bool res = false;
832 uint32_t pos = (uint32_t)(i - 1);
833 uint32_t size = 2;
834
835 // ensure we have capacity, if not, then resize
836 if ( as_bytes_ensure(b, pos + size, true) == true ) {
837 // write the bytes
838 int16_t val = cf_swap_to_be16((int16_t) v);
839 res = as_bytes_set_int16(b, pos, val);
840 }
841
842 lua_pushboolean(l, res);
843 return 1;
844}
845
846/**
847 * Set a little endian int16 value at specified index.
848 *
849 * ----------{.c}
850 * bool bytes.set_int16_le(bytes b, uint32 i, int16 v)
851 * ----------
852 *
853 * @param b The bytes to set a value in.
854 * @param i The index in b to set the value of.
855 * @param v The int16_t value to set at i.
856 *
857 * @return On success, true. Otherwise, false on error.
858 */
859static int mod_lua_bytes_set_int16_le(lua_State * l)
860{
861 // we expect 3 args
862 if ( lua_gettop(l) != 3 ) {
863 lua_pushboolean(l, false);
864 return 1;
865 }
866
867 as_bytes * b = mod_lua_checkbytes(l, 1);
868 lua_Integer i = luaL_optinteger(l, 2, 0);
869 lua_Integer v = luaL_optinteger(l, 3, 0);
870
871 // check preconditions:
872 // - b != NULL
873 // - 1 <= i <= UINT32_MAX
874 // - INT16_MIN <= v <= INT16_MAX
875 if ( !b ||
876 i < 1 || i > UINT32_MAX ||
877 v < INT16_MIN || v > INT16_MAX ) {
878 lua_pushboolean(l, false);
879 return 1;
880 }
881
882 bool res = false;
883 uint32_t pos = (uint32_t)(i - 1);
884 uint32_t size = 2;
885
886 // ensure we have capacity, if not, then resize
887 if ( as_bytes_ensure(b, pos + size, true) == true ) {
888 // write the bytes
889 int16_t val = cf_swap_to_le16((int16_t) v);
890 res = as_bytes_set_int16(b, pos, val);
891 }
892
893 lua_pushboolean(l, res);
894 return 1;
895}
896
897/**
898 * Set a big endian int32 value at specified index.
899 *
900 * ----------{.c}
901 * bool bytes.set_int32_be(bytes b, uint32 i, int32 v)
902 * ----------
903 *
904 * @param b The bytes to set a value in.
905 * @param i The index in b to set the value of.
906 * @param v The int32_t value to set at i.
907 *
908 * @return On success, true. Otherwise, false on error.
909 */
910static int mod_lua_bytes_set_int32_be(lua_State * l)
911{
912 // we expect 3 args
913 if ( lua_gettop(l) != 3 ) {
914 lua_pushboolean(l, false);
915 return 1;
916 }
917
918 as_bytes * b = mod_lua_checkbytes(l, 1);
919 lua_Integer i = luaL_optinteger(l, 2, 0);
920 lua_Integer v = luaL_optinteger(l, 3, 0);
921
922 // check preconditions:
923 // - b != NULL
924 // - 1 <= i <= UINT32_MAX
925 // - INT32_MIN <= v <= INT32_MAX
926 if ( !b ||
927 i < 1 || i > UINT32_MAX ||
928 v < INT32_MIN || v > INT32_MAX ) {
929 lua_pushboolean(l, false);
930 return 1;
931 }
932
933 bool res = false;
934 uint32_t pos = (uint32_t)(i - 1);
935 uint32_t size = 4;
936
937 // ensure we have capacity, if not, then resize
938 if ( as_bytes_ensure(b, pos + size, true) == true ) {
939 // write the bytes
940 int32_t val = cf_swap_to_be32((int32_t) v);
941 res = as_bytes_set_int32(b, pos, val);
942 }
943
944 lua_pushboolean(l, res);
945 return 1;
946}
947
948/**
949 * Set a little endian int32 value at specified index.
950 *
951 * ----------{.c}
952 * bool bytes.set_int32_le(bytes b, uint32 i, int32 v)
953 * ----------
954 *
955 * @param b The bytes to set a value in.
956 * @param i The index in b to set the value of.
957 * @param v The int32_t value to set at i.
958 *
959 * @return On success, true. Otherwise, false on error.
960 */
961static int mod_lua_bytes_set_int32_le(lua_State * l)
962{
963 // we expect 3 args
964 if ( lua_gettop(l) != 3 ) {
965 lua_pushboolean(l, false);
966 return 1;
967 }
968
969 as_bytes * b = mod_lua_checkbytes(l, 1);
970 lua_Integer i = luaL_optinteger(l, 2, 0);
971 lua_Integer v = luaL_optinteger(l, 3, 0);
972
973 // check preconditions:
974 // - b != NULL
975 // - 1 <= i <= UINT32_MAX
976 // - INT32_MIN <= v <= INT32_MAX
977 if ( !b ||
978 i < 1 || i > UINT32_MAX ||
979 v < INT32_MIN || v > INT32_MAX ) {
980 lua_pushboolean(l, false);
981 return 1;
982 }
983
984 bool res = false;
985 uint32_t pos = (uint32_t)(i - 1);
986 uint32_t size = 4;
987
988 // ensure we have capacity, if not, then resize
989 if ( as_bytes_ensure(b, pos + size, true) == true ) {
990 // write the bytes
991 int32_t val = cf_swap_to_le32((int32_t) v);
992 res = as_bytes_set_int32(b, pos, val);
993 }
994
995 lua_pushboolean(l, res);
996 return 1;
997}
998
999/**
1000 * Set a big endian int64_t value at specified index.
1001 *
1002 * ----------{.c}
1003 * bool bytes.set_int64_be(bytes b, uint32 i, int64 v)
1004 * ----------
1005 *
1006 * @param b The bytes to set a value in.
1007 * @param i The index in b to set the value of.
1008 * @param v The int64_t value to set at i.
1009 *
1010 * @return On success, true. Otherwise, false on error.
1011 */
1012static int mod_lua_bytes_set_int64_be(lua_State * l)
1013{
1014 // we expect 3 args
1015 if ( lua_gettop(l) != 3 ) {
1016 lua_pushboolean(l, false);
1017 return 1;
1018 }
1019
1020 as_bytes * b = mod_lua_checkbytes(l, 1);
1021 lua_Integer i = luaL_optinteger(l, 2, 0);
1022 lua_Integer v = luaL_optinteger(l, 3, 0);
1023
1024 // check preconditions:
1025 // - b != NULL
1026 // - 1 <= i <= UINT32_MAX
1027 if ( !b ||
1028 i < 1 || i > UINT32_MAX ) {
1029 lua_pushboolean(l, false);
1030 return 1;
1031 }
1032
1033 bool res = false;
1034 uint32_t pos = (uint32_t)(i - 1);
1035 uint32_t size = 8;
1036
1037 // ensure we have capacity, if not, then resize
1038 if ( as_bytes_ensure(b, pos + size, true) == true ) {
1039 // write the bytes
1040 int64_t val = cf_swap_to_be64((int64_t) v);
1041 res = as_bytes_set_int64(b, pos, val);
1042 }
1043
1044 lua_pushboolean(l, res);
1045 return 1;
1046}
1047
1048/**
1049 * Set a little endian int64_t value at specified index.
1050 *
1051 * ----------{.c}
1052 * bool bytes.set_int64_le(bytes b, uint32 i, int64 v)
1053 * ----------
1054 *
1055 * @param b The bytes to set a value in.
1056 * @param i The index in b to set the value of.
1057 * @param v The int64_t value to set at i.
1058 *
1059 * @return On success, true. Otherwise, false on error.
1060 */
1061static int mod_lua_bytes_set_int64_le(lua_State * l)
1062{
1063 // we expect 3 args
1064 if ( lua_gettop(l) != 3 ) {
1065 lua_pushboolean(l, false);
1066 return 1;
1067 }
1068
1069 as_bytes * b = mod_lua_checkbytes(l, 1);
1070 lua_Integer i = luaL_optinteger(l, 2, 0);
1071 lua_Integer v = luaL_optinteger(l, 3, 0);
1072
1073 // check preconditions:
1074 // - b != NULL
1075 // - 1 <= i <= UINT32_MAX
1076 if ( !b ||
1077 i < 1 || i > UINT32_MAX ) {
1078 lua_pushboolean(l, false);
1079 return 1;
1080 }
1081
1082 bool res = false;
1083 uint32_t pos = (uint32_t)(i - 1);
1084 uint32_t size = 8;
1085
1086 // ensure we have capacity, if not, then resize
1087 if ( as_bytes_ensure(b, pos + size, true) == true ) {
1088 // write the bytes
1089 int64_t val = cf_swap_to_le64((int64_t) v);
1090 res = as_bytes_set_int64(b, pos, val);
1091 }
1092
1093 lua_pushboolean(l, res);
1094 return 1;
1095}
1096
1097/**
1098 * Encode an integer in variable 7-bit format at specified index.
1099 * The high bit indicates if more bytes are used.
1100 *
1101 * ----------{.c}
1102 * bool bytes.set_var_int(bytes b, uint32 i, int32 v)
1103 * ----------
1104 *
1105 * @param b The bytes to set a value in.
1106 * @param i The index in b to set the value of.
1107 * @param v The integer value to set at i.
1108 *
1109 * @return number of bytes used to store integer
1110 */
1111static int mod_lua_bytes_set_var_int(lua_State * l)
1112{
1113 // we expect 3 args
1114 if ( lua_gettop(l) != 3 ) {
1115 lua_pushinteger(l, 0);
1116 return 1;
1117 }
1118
1119 as_bytes * b = mod_lua_checkbytes(l, 1);
1120 lua_Integer i = luaL_optinteger(l, 2, 0);
1121 lua_Integer v = luaL_optinteger(l, 3, 0);
1122
1123 // check preconditions:
1124 // - b != NULL
1125 // - 1 <= i <= UINT32_MAX
1126 // - INT32_MIN <= v <= INT32_MAX
1127 if ( !b ||
1128 i < 1 || i > UINT32_MAX ||
1129 v < INT32_MIN || v > INT32_MAX ) {
1130 lua_pushinteger(l, 0);
1131 return 1;
1132 }
1133
1134 uint32_t size = 0;
1135 uint32_t pos = (uint32_t)(i - 1);
1136
1137 // ensure we have capacity, if not, then resize
1138 if ( as_bytes_ensure(b, pos + 5, true) == true ) {
1139 size = as_bytes_set_var_int(b, pos, (uint32_t)v);
1140 }
1141
1142 lua_pushinteger(l, size);
1143 return 1;
1144}
1145
1146/**
1147 * Set an NULL-terminated string value at specified index.
1148 *
1149 * ----------{.c}
1150 * bool bytes.set_string(bytes b, uint32 i, string v)
1151 * ----------
1152 *
1153 * @param b The bytes to set a value in.
1154 * @param i The index in b to set the value of.
1155 * @param v The NULL-terminated string value to set at i.
1156 *
1157 * @return On success, true. Otherwise, false on error.
1158 */
1159static int mod_lua_bytes_set_string(lua_State * l)
1160{
1161 // we expect 3 args
1162 if ( lua_gettop(l) != 3 ) {
1163 lua_pushboolean(l, false);
1164 return 1;
1165 }
1166
1167 as_bytes * b = mod_lua_checkbytes(l, 1);
1168 lua_Integer i = luaL_optinteger(l, 2, 0);
1169 size_t n = 0;
1170 const char * v = luaL_optlstring(l, 3, NULL, &n);
1171
1172 // check preconditions:
1173 // - b != NULL
1174 // - 1 <= i <= UINT32_MAX
1175 // - v != NULL
1176 if ( !b ||
1177 i < 1 || i > UINT32_MAX ||
1178 !v ) {
1179 lua_pushboolean(l, false);
1180 return 1;
1181 }
1182
1183 bool res = false;
1184 uint32_t pos = (uint32_t)(i - 1);
1185 uint32_t size = (uint32_t)n;
1186
1187 // ensure we have capacity, if not, then resize
1188 if ( as_bytes_ensure(b, pos + size, true) == true ) {
1189 // write the bytes
1190 res = as_bytes_set(b, pos, (uint8_t *) v, size);
1191 }
1192
1193 lua_pushboolean(l, res);
1194 return 1;
1195}
1196
1197/**
1198 * Copy `n` data from bytes `v` to bytes `b` value at specified index.
1199 *
1200 * ----------{.c}
1201 * bool bytes.set_bytes(bytes b, uint32 i, bytes v, uint32 n)
1202 * ----------
1203 *
1204 * @param b The bytes to set a value in.
1205 * @param i The index in b to set the value of.
1206 * @param v The NULL-terminated string value to set at i.
1207 * @param n The number of bytes to copy from v in to b.
1208 *
1209 * @return On success, true. Otherwise, false on error.
1210 */
1211static int mod_lua_bytes_set_bytes(lua_State * l)
1212{
1213 // we expect 3 args
1214 if ( lua_gettop(l) != 4 ) {
1215 lua_pushboolean(l, false);
1216 return 1;
1217 }
1218
1219 as_bytes * b = mod_lua_checkbytes(l, 1);
1220 lua_Integer i = luaL_optinteger(l, 2, 0);
1221 as_bytes * v = mod_lua_checkbytes(l, 3);
1222 lua_Integer n = luaL_optinteger(l, 4, 0);
1223
1224 // check preconditions:
1225 // - b != NULL
1226 // - 1 <= i <= UINT32_MAX
1227 // - v != NULL
1228 // - 0 <= n <= UINT32_MAX
1229 if ( !b ||
1230 i < 1 || i > UINT32_MAX ||
1231 !v ||
1232 n < 0 || n > UINT32_MAX ) {
1233 lua_pushboolean(l, false);
1234 return 1;
1235 }
1236
1237 bool res = false;
1238 uint32_t pos = (uint32_t)(i - 1);
1239 uint32_t size = n > v->size ? v->size : (uint32_t)n;
1240
1241 // ensure we have capacity, if not, then resize
1242 if ( as_bytes_ensure(b, pos + size, true) == true ) {
1243 // write the bytes
1244 res = as_bytes_set(b, pos, (uint8_t *) v->value, (uint32_t) n);
1245 }
1246
1247 lua_pushboolean(l, res);
1248 return 1;
1249}
1250
1251/******************************************************************************
1252 * GET FUNCTIONS
1253 *****************************************************************************/
1254
1255/**
1256 * Get an uint8_t value from the specified index.
1257 *
1258 * ----------{.c}
1259 * uint8 bytes.get_byte(bytes b, uint32 i)
1260 * ----------
1261 *
1262 * @param b The bytes to get a value from.
1263 * @param i The index in b to get the value of.
1264 *
1265 * @return On success, the value. Otherwise nil on failure.
1266 */
1267static int mod_lua_bytes_get_byte(lua_State * l)
1268{
1269 // we expect exactly 2 args
1270 if ( lua_gettop(l) != 2) {
1271 return 0;
1272 }
1273
1274 as_bytes * b = mod_lua_checkbytes(l, 1);
1275 lua_Integer i = luaL_optinteger(l, 2, 0);
1276
1277 // check preconditions:
1278 // - b != NULL
1279 // - 1 <= i <= UINT32_MAX
1280 if ( !b ||
1281 i < 1 || i > UINT32_MAX ) {
1282 return 0;
1283 }
1284
1285 uint32_t pos = (uint32_t)(i - 1);
1286 uint8_t val = 0;
1287
1288 // get returns 0 on failure
1289 if ( as_bytes_get_byte(b, pos, &val) == 0 ) {
1290 return 0;
1291 }
1292
1293 lua_pushinteger(l, val);
1294 return 1;
1295}
1296
1297/**
1298 * Get a big endian int16 value from the specified index.
1299 *
1300 * ----------{.c}
1301 * int16 bytes.get_int16_be(bytes b, uint32 i)
1302 * ----------
1303 *
1304 * @param b The bytes to get a value from.
1305 * @param i The index in b to get the value of.
1306 *
1307 * @return On success, the value. Otherwise nil on failure.
1308 */
1309static int mod_lua_bytes_get_int16_be(lua_State * l)
1310{
1311 // we expect exactly 2 args
1312 if ( lua_gettop(l) != 2) {
1313 return 0;
1314 }
1315
1316 as_bytes * b = mod_lua_checkbytes(l, 1);
1317 lua_Integer i = luaL_optinteger(l, 2, 0);
1318
1319 // check preconditions:
1320 // - b != NULL
1321 // - 1 <= i <= UINT32_MAX
1322 if ( !b ||
1323 i < 1 || i > UINT32_MAX ) {
1324 return 0;
1325 }
1326
1327 uint32_t pos = (uint32_t)(i - 1);
1328 int16_t val = 0;
1329
1330 // get returns 0 on failure
1331 if ( as_bytes_get_int16(b, pos, &val) == 0 ) {
1332 return 0;
1333 }
1334
1335 int16_t res = cf_swap_from_be16(val);
1336 lua_pushinteger(l, res);
1337 return 1;
1338}
1339
1340/**
1341 * Get a little endian int16 value from the specified index.
1342 *
1343 * ----------{.c}
1344 * int16 bytes.get_int16_le(bytes b, uint32 i)
1345 * ----------
1346 *
1347 * @param b The bytes to get a value from.
1348 * @param i The index in b to get the value of.
1349 *
1350 * @return On success, the value. Otherwise nil on failure.
1351 */
1352static int mod_lua_bytes_get_int16_le(lua_State * l)
1353{
1354 // we expect exactly 2 args
1355 if ( lua_gettop(l) != 2) {
1356 return 0;
1357 }
1358
1359 as_bytes * b = mod_lua_checkbytes(l, 1);
1360 lua_Integer i = luaL_optinteger(l, 2, 0);
1361
1362 // check preconditions:
1363 // - b != NULL
1364 // - 1 <= i <= UINT32_MAX
1365 if ( !b ||
1366 i < 1 || i > UINT32_MAX ) {
1367 return 0;
1368 }
1369
1370 uint32_t pos = (uint32_t)(i - 1);
1371 int16_t val = 0;
1372
1373 // get returns 0 on failure
1374 if ( as_bytes_get_int16(b, pos, &val) == 0 ) {
1375 return 0;
1376 }
1377
1378 int16_t res = cf_swap_from_le16(val);
1379 lua_pushinteger(l, res);
1380 return 1;
1381}
1382
1383/**
1384 * Get a big endian int32 value from the specified index.
1385 *
1386 * ----------{.c}
1387 * int32 bytes.get_int32_be(bytes b, uint32 i)
1388 * ----------
1389 *
1390 * @param b The bytes to get a value from.
1391 * @param i The index in b to get the value of.
1392 *
1393 * @return On success, the value. Otherwise nil on failure.
1394 */
1395static int mod_lua_bytes_get_int32_be(lua_State * l)
1396{
1397 // we expect exactly 2 args
1398 if ( lua_gettop(l) != 2) {
1399 return 0;
1400 }
1401
1402 as_bytes * b = mod_lua_checkbytes(l, 1);
1403 lua_Integer i = luaL_optinteger(l, 2, 0);
1404
1405 // check preconditions:
1406 // - b != NULL
1407 // - 1 <= i <= UINT32_MAX
1408 if ( !b ||
1409 i < 1 || i > UINT32_MAX ) {
1410 return 0;
1411 }
1412
1413 uint32_t pos = (uint32_t)(i - 1);
1414 int32_t val = 0;
1415
1416 // get returns 0 on failure
1417 if ( as_bytes_get_int32(b, pos, &val) == 0 ) {
1418 return 0;
1419 }
1420
1421 int32_t res = cf_swap_from_be32(val);
1422 lua_pushinteger(l, res);
1423 return 1;
1424}
1425
1426/**
1427 * Get a little endian int32 value from the specified index.
1428 *
1429 * ----------{.c}
1430 * int32 bytes.get_int32_le(bytes b, uint32 i)
1431 * ----------
1432 *
1433 * @param b The bytes to get a value from.
1434 * @param i The index in b to get the value of.
1435 *
1436 * @return On success, the value. Otherwise nil on failure.
1437 */
1438static int mod_lua_bytes_get_int32_le(lua_State * l)
1439{
1440 // we expect exactly 2 args
1441 if ( lua_gettop(l) != 2) {
1442 return 0;
1443 }
1444
1445 as_bytes * b = mod_lua_checkbytes(l, 1);
1446 lua_Integer i = luaL_optinteger(l, 2, 0);
1447
1448 // check preconditions:
1449 // - b != NULL
1450 // - 1 <= i <= UINT32_MAX
1451 if ( !b ||
1452 i < 1 || i > UINT32_MAX ) {
1453 return 0;
1454 }
1455
1456 uint32_t pos = (uint32_t)(i - 1);
1457 int32_t val = 0;
1458
1459 // get returns 0 on failure
1460 if ( as_bytes_get_int32(b, pos, &val) == 0 ) {
1461 return 0;
1462 }
1463
1464 int32_t res = cf_swap_from_le32(val);
1465 lua_pushinteger(l, res);
1466 return 1;
1467}
1468
1469/**
1470 * Get a big endian int64 value from the specified index.
1471 *
1472 * ----------{.c}
1473 * int64 bytes.get_int64_be(bytes b, uint32 i)
1474 * ----------
1475 *
1476 * @param b The bytes to get a value from.
1477 * @param i The index in b to get the value of.
1478 *
1479 * @return On success, the value. Otherwise nil on failure.
1480 */
1481static int mod_lua_bytes_get_int64_be(lua_State * l)
1482{
1483 // we expect exactly 2 args
1484 if ( lua_gettop(l) != 2) {
1485 return 0;
1486 }
1487
1488 as_bytes * b = mod_lua_checkbytes(l, 1);
1489 lua_Integer i = luaL_optinteger(l, 2, 0);
1490
1491 // check preconditions:
1492 // - b != NULL
1493 // - 1 <= i <= UINT32_MAX
1494 if ( !b ||
1495 i < 1 || i > UINT32_MAX ) {
1496 return 0;
1497 }
1498
1499 uint32_t pos = (uint32_t)(i - 1);
1500 int64_t val = 0;
1501
1502 // get returns 0 on failure
1503 if ( as_bytes_get_int64(b, pos, &val) == 0 ) {
1504 return 0;
1505 }
1506
1507 int64_t res = cf_swap_from_be64(val);
1508 lua_pushinteger(l, res);
1509 return 1;
1510}
1511
1512/**
1513 * Get a little endian int64 value from the specified index.
1514 *
1515 * ----------{.c}
1516 * int64 bytes.get_int64_le(bytes b, uint32 i)
1517 * ----------
1518 *
1519 * @param b The bytes to get a value from.
1520 * @param i The index in b to get the value of.
1521 *
1522 * @return On success, the value. Otherwise nil on failure.
1523 */
1524static int mod_lua_bytes_get_int64_le(lua_State * l)
1525{
1526 // we expect exactly 2 args
1527 if ( lua_gettop(l) != 2) {
1528 return 0;
1529 }
1530
1531 as_bytes * b = mod_lua_checkbytes(l, 1);
1532 lua_Integer i = luaL_optinteger(l, 2, 0);
1533
1534 // check preconditions:
1535 // - b != NULL
1536 // - 1 <= i <= UINT32_MAX
1537 if ( !b ||
1538 i < 1 || i > UINT32_MAX ) {
1539 return 0;
1540 }
1541
1542 uint32_t pos = (uint32_t)(i - 1);
1543 int64_t val = 0;
1544
1545 // get returns 0 on failure
1546 if ( as_bytes_get_int64(b, pos, &val) == 0 ) {
1547 return 0;
1548 }
1549
1550 int64_t res = cf_swap_from_le64(val);
1551 lua_pushinteger(l, res);
1552 return 1;
1553}
1554
1555/**
1556 * Decode an integer in variable 7-bit format.
1557 * The high bit indicates if more bytes are used.
1558 *
1559 * ----------{.c}
1560 * int bytes.get_var_int(bytes b, uint32 i)
1561 * ----------
1562 *
1563 * @param b The bytes to get a value from.
1564 * @param i The index in b to get the value of.
1565 *
1566 * @return On success, the value. Otherwise nil on failure.
1567 */
1568static int mod_lua_bytes_get_var_int(lua_State * l)
1569{
1570 // we expect exactly 2 args
1571 if ( lua_gettop(l) != 2) {
1572 return 0;
1573 }
1574
1575 as_bytes * b = mod_lua_checkbytes(l, 1);
1576 lua_Integer i = luaL_optinteger(l, 2, 0);
1577
1578 // check preconditions:
1579 // - b != NULL
1580 // - 1 <= i <= UINT32_MAX
1581 if ( !b ||
1582 i < 1 || i > UINT32_MAX ) {
1583 return 0;
1584 }
1585
1586 uint32_t pos = (uint32_t)(i - 1);
1587 uint32_t val = 0;
1588 uint32_t size = as_bytes_get_var_int(b, pos, &val);
1589
1590 lua_pushinteger(l, val);
1591 lua_pushinteger(l, size);
1592 return 2;
1593}
1594
1595/**
1596 * Get an bytes value from the specified index.
1597 *
1598 * ----------{.c}
1599 * bytes bytes.get_bytes(bytes b, uint32 i, uint32 n)
1600 * ----------
1601 *
1602 * @param b The bytes to get a value from.
1603 * @param i The index in b to get the value from.
1604 * @param n The the length of the bytes to copy.
1605 *
1606 * @return On success, the value. Otherwise nil on failure.
1607 */
1608
1609static int mod_lua_bytes_get_string(lua_State * l)
1610{
1611 // we expect exactly 3 args
1612 if ( lua_gettop(l) != 3 ) {
1613 return 0;
1614 }
1615
1616 as_bytes * b = mod_lua_checkbytes(l, 1);
1617 lua_Integer i = luaL_optinteger(l, 2, 0);
1618 lua_Integer n = luaL_optinteger(l, 3, 0);
1619
1620 // check preconditions:
1621 // - b != NULL
1622 // - 1 <= i <= UINT32_MAX
1623 // - 0 <= n <= UINT32_MAX
1624 if ( !b ||
1625 i < 1 || i > UINT32_MAX ||
1626 n < 0 || n > UINT32_MAX ) {
1627 return 0;
1628 }
1629
1630 uint32_t pos = (uint32_t)(i - 1);
1631 uint32_t len = (uint32_t) n;
1632 char * val = (char *) cf_calloc(len + 1, sizeof(char));
1633
1634 if ( !val ) {
1635 return 0;
1636 }
1637
1638 // copy into the the string
1639 memcpy(val, b->value + pos, len);
1640 val[len] = '\0';
1641
1642 lua_pushlstring(l, val, len);
1643 cf_free(val);
1644 return 1;
1645}
1646
1647
1648/**
1649 * Get an bytes value from the specified index.
1650 *
1651 * ----------{.c}
1652 * bytes bytes.get_bytes(bytes b, uint32 i, uint32 n)
1653 * ----------
1654 *
1655 * @param b The bytes to get a value from.
1656 * @param i The index in b to get the value from.
1657 * @param n The the length of the bytes to copy.
1658 *
1659 * @return On success, the value. Otherwise nil on failure.
1660 */
1661static int mod_lua_bytes_get_bytes(lua_State * l)
1662{
1663 // we expect exactly 3 args
1664 if ( lua_gettop(l) != 3 ) {
1665 return 0;
1666 }
1667
1668 as_bytes * b = mod_lua_checkbytes(l, 1);
1669 lua_Integer i = luaL_optinteger(l, 2, 0);
1670 lua_Integer n = luaL_optinteger(l, 3, 0);
1671
1672 // check preconditions:
1673 // - b != NULL
1674 // - 1 <= i <= UINT32_MAX
1675 // - 0 <= n <= UINT32_MAX
1676 if ( !b ||
1677 i < 1 || i > UINT32_MAX ||
1678 n < 0 || n > UINT32_MAX ) {
1679 return 0;
1680 }
1681
1682 uint32_t pos = (uint32_t)(i - 1);
1683 uint32_t len = (uint32_t) n;
1684 uint8_t * raw = (uint8_t *) cf_calloc(len, sizeof(uint8_t));
1685
1686 if ( !raw ) {
1687 return 0;
1688 }
1689
1690 // copy into the the buffer
1691 memcpy(raw, b->value + pos, len);
1692
1693 // create a new bytes
1694 as_bytes * val = as_bytes_new_wrap(raw, len, true);
1695
1696 if ( !val ) {
1697 return 0;
1698 }
1699
1700 mod_lua_pushbytes(l, val);
1701 return 1;
1702}
1703
1704/******************************************************************************
1705 * OBJECT TABLE
1706 *****************************************************************************/
1707
1708static const luaL_reg bytes_object_table[] = {
1709
1710 {"size", mod_lua_bytes_size},
1711 {"set_size", mod_lua_bytes_ensure},
1712
1713 {"get_type", mod_lua_bytes_get_type},
1714 {"set_type", mod_lua_bytes_set_type},
1715
1716 {"get_string", mod_lua_bytes_get_string},
1717 {"get_bytes", mod_lua_bytes_get_bytes},
1718 {"get_byte", mod_lua_bytes_get_byte},
1719 {"get_int16", mod_lua_bytes_get_int16_be},
1720 {"get_int16_be", mod_lua_bytes_get_int16_be},
1721 {"get_int16_le", mod_lua_bytes_get_int16_le},
1722 {"get_int32", mod_lua_bytes_get_int32_be},
1723 {"get_int32_be", mod_lua_bytes_get_int32_be},
1724 {"get_int32_le", mod_lua_bytes_get_int32_le},
1725 {"get_int64", mod_lua_bytes_get_int64_be},
1726 {"get_int64_be", mod_lua_bytes_get_int64_be},
1727 {"get_int64_le", mod_lua_bytes_get_int64_le},
1728 {"get_var_int", mod_lua_bytes_get_var_int},
1729
1730 {"set_string", mod_lua_bytes_set_string},
1731 {"set_bytes", mod_lua_bytes_set_bytes},
1732 {"set_byte", mod_lua_bytes_set_byte},
1733 {"set_int16", mod_lua_bytes_set_int16_be},
1734 {"set_int16_be", mod_lua_bytes_set_int16_be},
1735 {"set_int16_le", mod_lua_bytes_set_int16_le},
1736 {"set_int32", mod_lua_bytes_set_int32_be},
1737 {"set_int32_be", mod_lua_bytes_set_int32_be},
1738 {"set_int32_le", mod_lua_bytes_set_int32_le},
1739 {"set_int64", mod_lua_bytes_set_int64_be},
1740 {"set_int64_be", mod_lua_bytes_set_int64_be},
1741 {"set_int64_le", mod_lua_bytes_set_int64_le},
1742 {"set_var_int", mod_lua_bytes_set_var_int},
1743
1744 {"append_string", mod_lua_bytes_append_string},
1745 {"append_bytes", mod_lua_bytes_append_bytes},
1746 {"append_byte", mod_lua_bytes_append_byte},
1747 {"append_int16", mod_lua_bytes_append_int16_be},
1748 {"append_int16_be", mod_lua_bytes_append_int16_be},
1749 {"append_int16_le", mod_lua_bytes_append_int16_le},
1750 {"append_int32", mod_lua_bytes_append_int32_be},
1751 {"append_int32_be", mod_lua_bytes_append_int32_be},
1752 {"append_int32_le", mod_lua_bytes_append_int32_le},
1753 {"append_int64", mod_lua_bytes_append_int64_be},
1754 {"append_int64_be", mod_lua_bytes_append_int64_be},
1755 {"append_int64_le", mod_lua_bytes_append_int64_le},
1756 {"append_var_int", mod_lua_bytes_append_var_int},
1757
1758 {0, 0}
1759};
1760
1761static const luaL_reg bytes_object_metatable[] = {
1762 {"__call", mod_lua_bytes_new},
1763 {0, 0}
1764};
1765
1766/******************************************************************************
1767 * CLASS TABLE
1768 *****************************************************************************/
1769
1770/*
1771static const luaL_reg bytes_class_table[] = {
1772 {"putX", mod_lua_bytes_tostring},
1773 {0, 0}
1774};
1775*/
1776
1777static const luaL_reg bytes_class_metatable[] = {
1778 {"__index", mod_lua_bytes_get_byte},
1779 {"__newindex", mod_lua_bytes_set_byte},
1780 {"__len", mod_lua_bytes_size},
1781 {"__tostring", mod_lua_bytes_tostring},
1782 {"__gc", mod_lua_bytes_gc},
1783 {0, 0}
1784};
1785
1786/******************************************************************************
1787 * REGISTER
1788 *****************************************************************************/
1789
1790int mod_lua_bytes_register(lua_State * l) {
1791 mod_lua_reg_object(l, OBJECT_NAME, bytes_object_table, bytes_object_metatable);
1792 mod_lua_reg_class(l, CLASS_NAME, NULL, bytes_class_metatable);
1793 return 1;
1794}
1795