Add basic APIs including var_int32 getter and setters
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -26,8 +26,13 @@ src/.libs/
|
||||
src/Makefile
|
||||
src/libprogbuf.la
|
||||
src/libprogbuf.lo
|
||||
src/test_progbuf
|
||||
src/*.o
|
||||
src/check_progbuf
|
||||
src/check_progbuf.log
|
||||
src/check_progbuf.trs
|
||||
src/progbuf.lo
|
||||
src/test-suite.log
|
||||
test-driver
|
||||
stamp-h1
|
||||
.idea/
|
||||
.vscode/
|
||||
build/
|
||||
|
||||
3
build-debug.sh
Executable file
3
build-debug.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
./configure CPPFLAGS=-DDEBUG CFLAGS="-g -O0" && make
|
||||
3
build-release.sh
Executable file
3
build-release.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
./configure && make
|
||||
@@ -3,6 +3,7 @@ AM_INIT_AUTOMAKE([-Wall -Werror gnu])
|
||||
AC_PROG_CC
|
||||
AM_PROG_AR
|
||||
LT_INIT
|
||||
PKG_CHECK_MODULES([CHECK], [check])
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf aclocal.m4 config.sub configure depcomp m4 ar-lib compile config.guess config.h install-sh Makefile Makefile.in autom4te.cache config.h.in ltmain.sh missing libtool config.status config.log INSTALL stamp-h1 src/Makefile.in src/.libs src/.deps src/*.o src/Makefile src/libprogbuf.la src/progbuf.lo src/test_progbuf build config.h.in~
|
||||
rm -rf aclocal.m4 config.sub configure depcomp m4 ar-lib compile config.guess config.h install-sh test-driver Makefile Makefile.in autom4te.cache config.h.in ltmain.sh missing libtool config.status config.log INSTALL stamp-h1 src/Makefile.in src/.libs src/.deps src/*.o src/Makefile src/libprogbuf.la src/progbuf.lo src/check_progbuf build config.h.in~
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
find src -iname *.h -o -iname *.c | xargs clang-format -style=GNU -i
|
||||
find ./src -iname *.h -o -iname *.c | xargs clang-format -style=GNU -i
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ libprogbuf_la_SOURCES = progbuf.c
|
||||
libprogbuf_la_LDFLAGS = -version-info 0:1:0
|
||||
include_HEADERS = progbuf.h
|
||||
|
||||
bin_PROGRAMS = test_progbuf
|
||||
test_progbuf_SOURCES = test_progbuf.c
|
||||
test_progbuf_LDADD = libprogbuf.la
|
||||
noinst_PROGRAMS = check_progbuf
|
||||
TESTS = check_progbuf
|
||||
check_progbuf_SOURCES = check_progbuf.c
|
||||
check_progbuf_CFLAGS = $(CFLAGS) $(CHECK_CFLAGS)
|
||||
check_progbuf_LDADD = libprogbuf.la $(LDFLAGS) $(CHECK_LIBS)
|
||||
check_progbuf_LDFLAGS = -no-install
|
||||
|
||||
372
src/check_progbuf.c
Normal file
372
src/check_progbuf.c
Normal file
@@ -0,0 +1,372 @@
|
||||
#include <check.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "progbuf.h"
|
||||
|
||||
START_TEST (test_progbuf_alloc_version)
|
||||
{
|
||||
int ret;
|
||||
long message_tag;
|
||||
|
||||
ret = progbuf_get_message_tag (NULL, &message_tag);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
progbuf_h buf = progbuf_alloc (1);
|
||||
|
||||
ck_assert (buf);
|
||||
|
||||
ret = progbuf_get_message_tag (buf, NULL);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_tag (buf, &message_tag);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
ck_assert (message_tag == 1);
|
||||
|
||||
size_t size;
|
||||
ret = progbuf_get_message_buffer (buf, NULL, &size);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ck_assert (size == 1);
|
||||
|
||||
ret = progbuf_free (buf);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
parametric_test_progbuf_write_read_long (const long val,
|
||||
const int expected_val_size)
|
||||
{
|
||||
progbuf_h buf = progbuf_alloc (1);
|
||||
|
||||
ck_assert (buf);
|
||||
|
||||
long p_val = val;
|
||||
|
||||
int ret = progbuf_set_long (buf, p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
size_t size;
|
||||
ret = progbuf_get_message_buffer (buf, NULL, &size);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ck_assert (size == 1 + 1 + expected_val_size);
|
||||
|
||||
progbuf_it_h iter = progbuf_iter_alloc (buf);
|
||||
|
||||
ck_assert (iter);
|
||||
|
||||
ret = progbuf_get_long (iter, &p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
ck_assert (val == p_val);
|
||||
|
||||
struct progbuf_it_s *iter_internal = iter;
|
||||
|
||||
ck_assert (iter_internal->read_pos == 1 + 1 + expected_val_size);
|
||||
|
||||
ret = progbuf_iter_free (iter);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ret = progbuf_free (buf);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
}
|
||||
|
||||
START_TEST (test_progbuf_write_read_positive_long)
|
||||
{
|
||||
parametric_test_progbuf_write_read_long (0, 1);
|
||||
parametric_test_progbuf_write_read_long (1, 1);
|
||||
parametric_test_progbuf_write_read_long (0x3F, 1);
|
||||
|
||||
parametric_test_progbuf_write_read_long (0x7F, 2);
|
||||
parametric_test_progbuf_write_read_long (0x1FFF, 2);
|
||||
|
||||
parametric_test_progbuf_write_read_long (0x3FFF, 3);
|
||||
parametric_test_progbuf_write_read_long (0xFFFFF, 3);
|
||||
|
||||
parametric_test_progbuf_write_read_long (0x1FFFFF, 4);
|
||||
parametric_test_progbuf_write_read_long (0x7FFFFFF, 4);
|
||||
|
||||
parametric_test_progbuf_write_read_long (0xFFFFFFF, 5);
|
||||
parametric_test_progbuf_write_read_long (0x7FFFFFFF, 5);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_progbuf_write_read_negative_long)
|
||||
{
|
||||
parametric_test_progbuf_write_read_long (-1, 1);
|
||||
parametric_test_progbuf_write_read_long (-0x3F, 1);
|
||||
|
||||
parametric_test_progbuf_write_read_long (-0x7F, 2);
|
||||
parametric_test_progbuf_write_read_long (-0x1FFF, 2);
|
||||
|
||||
parametric_test_progbuf_write_read_long (-0x3FFF, 3);
|
||||
parametric_test_progbuf_write_read_long (-0xFFFFF, 3);
|
||||
|
||||
parametric_test_progbuf_write_read_long (-0x1FFFFF, 4);
|
||||
parametric_test_progbuf_write_read_long (-0x7FFFFFF, 4);
|
||||
|
||||
parametric_test_progbuf_write_read_long (-0xFFFFFFF, 5);
|
||||
parametric_test_progbuf_write_read_long (-0x7FFFFFFF, 5);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_progbuf_write_read_ulong)
|
||||
{
|
||||
progbuf_h buf = progbuf_alloc (1);
|
||||
|
||||
ck_assert (buf);
|
||||
|
||||
unsigned long val = 0xFFFFFFFF;
|
||||
unsigned long p_val = val;
|
||||
|
||||
int ret = progbuf_set_ulong (buf, p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
size_t size;
|
||||
|
||||
ret = progbuf_get_message_buffer (NULL, NULL, NULL);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_buffer (NULL, NULL, &size);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_buffer (buf, NULL, NULL);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_buffer (buf, NULL, &size);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ck_assert (size == 1 + 6);
|
||||
|
||||
progbuf_it_h iter = progbuf_iter_alloc (buf);
|
||||
|
||||
ck_assert (iter);
|
||||
|
||||
ret = progbuf_get_ulong (iter, &p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
ck_assert (val == p_val);
|
||||
|
||||
struct progbuf_it_s *iter_internal = iter;
|
||||
|
||||
ck_assert (iter_internal->read_pos == 1 + 6);
|
||||
|
||||
ret = progbuf_iter_free (iter);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ret = progbuf_free (buf);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
parametric_test_progbuf_write_read_longlong (const long long val,
|
||||
const int expected_val_size)
|
||||
{
|
||||
progbuf_h buf = progbuf_alloc (1);
|
||||
|
||||
ck_assert (buf);
|
||||
|
||||
long long p_val = val;
|
||||
|
||||
int ret = progbuf_set_longlong (buf, p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
size_t size;
|
||||
ret = progbuf_get_message_buffer (buf, NULL, &size);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ck_assert (size == 1 + 1 + expected_val_size);
|
||||
|
||||
progbuf_it_h iter = progbuf_iter_alloc (buf);
|
||||
|
||||
ck_assert (iter);
|
||||
|
||||
ret = progbuf_get_longlong (iter, &p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
ck_assert (val == p_val);
|
||||
|
||||
struct progbuf_it_s *iter_internal = iter;
|
||||
|
||||
ck_assert (iter_internal->read_pos == 1 + 1 + expected_val_size);
|
||||
|
||||
ret = progbuf_iter_free (iter);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ret = progbuf_free (buf);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
}
|
||||
|
||||
START_TEST (test_progbuf_write_read_positive_longlong)
|
||||
{
|
||||
parametric_test_progbuf_write_read_longlong (0, 1);
|
||||
parametric_test_progbuf_write_read_longlong (1, 1);
|
||||
parametric_test_progbuf_write_read_longlong (0x3F, 1);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x7F, 2);
|
||||
parametric_test_progbuf_write_read_longlong (0x1FFF, 2);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x3FFF, 3);
|
||||
parametric_test_progbuf_write_read_longlong (0xFFFFF, 3);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x1FFFFF, 4);
|
||||
parametric_test_progbuf_write_read_longlong (0x7FFFFFF, 4);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0xFFFFFFF, 5);
|
||||
parametric_test_progbuf_write_read_longlong (0x3FFFFFFFF, 5);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x7FFFFFFFF, 6);
|
||||
parametric_test_progbuf_write_read_longlong (0x1FFFFFFFFFF, 6);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x3FFFFFFFFFF, 7);
|
||||
parametric_test_progbuf_write_read_longlong (0xFFFFFFFFFFFF, 7);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x1FFFFFFFFFFFF, 8);
|
||||
parametric_test_progbuf_write_read_longlong (0x7FFFFFFFFFFFFF, 8);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0xFFFFFFFFFFFFFF, 9);
|
||||
parametric_test_progbuf_write_read_longlong (0x3FFFFFFFFFFFFFFF, 9);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (0x7FFFFFFFFFFFFFFF, 10);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_progbuf_write_read_negative_longlong)
|
||||
{
|
||||
parametric_test_progbuf_write_read_longlong (-1, 1);
|
||||
parametric_test_progbuf_write_read_longlong (-0x3F, 1);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x7F, 2);
|
||||
parametric_test_progbuf_write_read_longlong (-0x1FFF, 2);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x3FFF, 3);
|
||||
parametric_test_progbuf_write_read_longlong (-0xFFFFF, 3);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x1FFFFF, 4);
|
||||
parametric_test_progbuf_write_read_longlong (-0x7FFFFFF, 4);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0xFFFFFFF, 5);
|
||||
parametric_test_progbuf_write_read_longlong (-0x7FFFFFFF, 5);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x7FFFFFFFF, 6);
|
||||
parametric_test_progbuf_write_read_longlong (-0x1FFFFFFFFFF, 6);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x3FFFFFFFFFF, 7);
|
||||
parametric_test_progbuf_write_read_longlong (-0xFFFFFFFFFFFF, 7);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x1FFFFFFFFFFFF, 8);
|
||||
parametric_test_progbuf_write_read_longlong (-0x7FFFFFFFFFFFFF, 8);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0xFFFFFFFFFFFFFF, 9);
|
||||
parametric_test_progbuf_write_read_longlong (-0x3FFFFFFFFFFFFFFF, 9);
|
||||
|
||||
parametric_test_progbuf_write_read_longlong (-0x7FFFFFFFFFFFFFFF, 10);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_progbuf_write_read_ulonglong)
|
||||
{
|
||||
progbuf_h buf = progbuf_alloc (1);
|
||||
|
||||
ck_assert (buf);
|
||||
|
||||
unsigned long long val = 0xFFFFFFFFFFFFFFFF;
|
||||
unsigned long long p_val = val;
|
||||
|
||||
int ret = progbuf_set_ulonglong (buf, p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
size_t size;
|
||||
|
||||
ret = progbuf_get_message_buffer (NULL, NULL, NULL);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_buffer (NULL, NULL, &size);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_buffer (buf, NULL, NULL);
|
||||
ck_assert (ret == PROGBUF_ERROR_NULL_PARAM);
|
||||
|
||||
ret = progbuf_get_message_buffer (buf, NULL, &size);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ck_assert (size == 1 + 1 + 10);
|
||||
|
||||
progbuf_it_h iter = progbuf_iter_alloc (buf);
|
||||
|
||||
ck_assert (iter);
|
||||
|
||||
ret = progbuf_get_ulonglong (iter, &p_val);
|
||||
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
ck_assert (val == p_val);
|
||||
|
||||
struct progbuf_it_s *iter_internal = iter;
|
||||
|
||||
ck_assert (iter_internal->read_pos == 1 + 1 + 10);
|
||||
|
||||
ret = progbuf_iter_free (iter);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
|
||||
ret = progbuf_free (buf);
|
||||
ck_assert (ret == PROGBUF_SUCCESS);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *
|
||||
progbuf_suite (void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc_basic, *tc_long, *tc_longlong;
|
||||
|
||||
s = suite_create ("progbuf test suite");
|
||||
|
||||
tc_basic = tcase_create ("basic");
|
||||
|
||||
tcase_add_test (tc_basic, test_progbuf_alloc_version);
|
||||
|
||||
tc_long = tcase_create ("encode_long");
|
||||
|
||||
tcase_add_test (tc_long, test_progbuf_write_read_positive_long);
|
||||
tcase_add_test (tc_long, test_progbuf_write_read_negative_long);
|
||||
tcase_add_test (tc_long, test_progbuf_write_read_ulong);
|
||||
|
||||
tc_longlong = tcase_create ("encode_longlong");
|
||||
|
||||
tcase_add_test (tc_longlong, test_progbuf_write_read_positive_longlong);
|
||||
tcase_add_test (tc_longlong, test_progbuf_write_read_negative_longlong);
|
||||
tcase_add_test (tc_longlong, test_progbuf_write_read_ulonglong);
|
||||
|
||||
suite_add_tcase (s, tc_basic);
|
||||
suite_add_tcase (s, tc_long);
|
||||
suite_add_tcase (s, tc_longlong);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int number_failed;
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
|
||||
s = progbuf_suite ();
|
||||
sr = srunner_create (s);
|
||||
|
||||
srunner_run_all (sr, CK_NORMAL);
|
||||
number_failed = srunner_ntests_failed (sr);
|
||||
srunner_free (sr);
|
||||
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
25
src/common.h
25
src/common.h
@@ -1,12 +1,31 @@
|
||||
#ifndef LIBPROGBUF_COMMON_H
|
||||
#define LIBPROGBUF_COMMON_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define ABS(N) ((N<0)?(-N):(N))
|
||||
|
||||
#define PROGBUF_INIT_BUFSIZ 128
|
||||
|
||||
#define PROGBUF_TYPE_VAR_INT 0x00
|
||||
#define PROGBUF_TYPE_FLOAT32 0x01
|
||||
#define PROGBUF_TYPE_FLOAT64 0x02
|
||||
#define PROGBUF_TYPE_BYTE 0x03
|
||||
#define PROGBUF_TYPE_ARRAY 0x04
|
||||
|
||||
struct progbuf_s
|
||||
{
|
||||
int message_tag;
|
||||
int version;
|
||||
char *buffer;
|
||||
int bufsiz;
|
||||
long message_tag;
|
||||
int header_size;
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct progbuf_it_s
|
||||
{
|
||||
struct progbuf_s* buf;
|
||||
size_t read_pos;
|
||||
};
|
||||
|
||||
#endif // LIBPROGBUF_COMMON_H
|
||||
|
||||
305
src/progbuf.c
305
src/progbuf.c
@@ -2,28 +2,309 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
typedef long long longlong;
|
||||
typedef unsigned long long ulonglong;
|
||||
|
||||
#define DETERMINE_VAR_SIZE(type) \
|
||||
static inline int determine_var_##type##_size (type value) \
|
||||
{ \
|
||||
type mask; \
|
||||
memset (&mask, 0xFF, sizeof (mask)); \
|
||||
\
|
||||
mask <<= 6; \
|
||||
\
|
||||
if ((value & mask) == 0) \
|
||||
return 1; \
|
||||
\
|
||||
int s = 2; \
|
||||
while (1) \
|
||||
{ \
|
||||
mask <<= 7; \
|
||||
\
|
||||
if ((value & mask) == 0) \
|
||||
return s; \
|
||||
\
|
||||
s++; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_VAR_SIZE(type) \
|
||||
static inline int read_var_##type (progbuf_it_h iter, type *value, \
|
||||
int *negative) \
|
||||
{ \
|
||||
type tmp = 0; \
|
||||
size_t prev_read_pos = iter->read_pos; \
|
||||
\
|
||||
int i = 0; \
|
||||
char byte; \
|
||||
const int bitsize = sizeof (type) * 8; \
|
||||
while (i < bitsize) \
|
||||
{ \
|
||||
byte = iter->buf->buffer[iter->read_pos++]; \
|
||||
if (i == 0) \
|
||||
{ \
|
||||
*negative = byte & 0x40; \
|
||||
tmp |= (type)(byte & 0x3F) << i; \
|
||||
i += 6; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tmp |= (type)(byte & 0x7F) << i; \
|
||||
i += 7; \
|
||||
} \
|
||||
\
|
||||
if ((byte & 0x80) == 0) \
|
||||
{ \
|
||||
*value = tmp; \
|
||||
return 0; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
iter->read_pos = prev_read_pos; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define WRITE_VAR_SIZE(type) \
|
||||
static inline void write_var_##type (progbuf_h buf, type value, int size, \
|
||||
int negative) \
|
||||
{ \
|
||||
for (int i = 0; i < size - 1; ++i) \
|
||||
{ \
|
||||
if (i == 0) \
|
||||
{ \
|
||||
if (negative) \
|
||||
{ \
|
||||
buf->buffer[buf->size] = (char)((value & 0x3F) | 0xC0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
buf->buffer[buf->size] = (char)((value & 0x3F) | 0x80); \
|
||||
} \
|
||||
value = (type)((type)value >> 6); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
buf->buffer[buf->size + i] = (char)((value & 0x7F) | 0x80); \
|
||||
value = (type)((type)value >> 7); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (size == 1 && negative) \
|
||||
{ \
|
||||
buf->buffer[buf->size] = (char)value | 0x40; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
buf->buffer[buf->size + (size - 1)] = (char)value; \
|
||||
} \
|
||||
\
|
||||
buf->size += size; \
|
||||
}
|
||||
|
||||
static inline int
|
||||
check_buffer_and_expand (progbuf_h buf, int size)
|
||||
{
|
||||
if (buf->size + size > buf->capacity)
|
||||
{
|
||||
char *newbuf = malloc (buf->capacity * 2);
|
||||
if (!newbuf)
|
||||
return PROGBUF_ERROR_MEM_ALLOC;
|
||||
|
||||
memcpy (newbuf, buf->buffer, buf->capacity);
|
||||
free (buf->buffer);
|
||||
buf->buffer = newbuf;
|
||||
buf->capacity *= 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DETERMINE_VAR_SIZE (uint)
|
||||
READ_VAR_SIZE (uint)
|
||||
WRITE_VAR_SIZE (uint)
|
||||
|
||||
DETERMINE_VAR_SIZE (ulong)
|
||||
READ_VAR_SIZE (ulong)
|
||||
WRITE_VAR_SIZE (ulong)
|
||||
|
||||
DETERMINE_VAR_SIZE (ulonglong)
|
||||
READ_VAR_SIZE (ulonglong)
|
||||
WRITE_VAR_SIZE (ulonglong)
|
||||
|
||||
#define PROGBUF_SET(type, utype) \
|
||||
int progbuf_set_##type (progbuf_h buf, type value) \
|
||||
{ \
|
||||
int val_size, ret; \
|
||||
\
|
||||
if (!buf) \
|
||||
return PROGBUF_ERROR_NULL_PARAM; \
|
||||
\
|
||||
val_size = determine_var_##utype##_size (ABS (value)); \
|
||||
ret = check_buffer_and_expand (buf, val_size + 1); \
|
||||
if (ret != 0) \
|
||||
return ret; \
|
||||
\
|
||||
buf->buffer[buf->size] = PROGBUF_TYPE_VAR_INT; \
|
||||
buf->size++; \
|
||||
\
|
||||
write_var_##utype (buf, ABS (value), val_size, value < 0); \
|
||||
\
|
||||
return PROGBUF_SUCCESS; \
|
||||
}
|
||||
|
||||
#define PROGBUF_GET(type, utype) \
|
||||
int progbuf_get_##type (progbuf_it_h iter, type *value) \
|
||||
{ \
|
||||
if (!iter || !value) \
|
||||
return PROGBUF_ERROR_NULL_PARAM; \
|
||||
\
|
||||
if (iter->read_pos >= iter->buf->size) \
|
||||
return PROGBUF_ERROR_END_OF_ITER; \
|
||||
\
|
||||
char val_type = iter->buf->buffer[iter->read_pos]; \
|
||||
\
|
||||
if ((val_type & PROGBUF_TYPE_VAR_INT) != PROGBUF_TYPE_VAR_INT) \
|
||||
return PROGBUF_ERROR_UNEXPECTED_TYPE; \
|
||||
\
|
||||
iter->read_pos++; \
|
||||
\
|
||||
utype u_value; \
|
||||
int negative; \
|
||||
if (read_var_##utype (iter, &u_value, &negative) != 0) \
|
||||
{ \
|
||||
iter->read_pos--; \
|
||||
return PROGBUF_ERROR_READ; \
|
||||
} \
|
||||
\
|
||||
*value = (negative ? -u_value : u_value); \
|
||||
\
|
||||
return PROGBUF_SUCCESS; \
|
||||
}
|
||||
|
||||
PROGBUF_SET (int, uint)
|
||||
PROGBUF_GET (int, uint)
|
||||
|
||||
PROGBUF_SET (uint, uint)
|
||||
PROGBUF_GET (uint, uint)
|
||||
|
||||
PROGBUF_SET (long, ulong)
|
||||
PROGBUF_GET (long, ulong)
|
||||
|
||||
PROGBUF_SET (ulong, ulong)
|
||||
PROGBUF_GET (ulong, ulong)
|
||||
|
||||
PROGBUF_SET (longlong, ulonglong)
|
||||
PROGBUF_GET (longlong, ulonglong)
|
||||
|
||||
PROGBUF_SET (ulonglong, ulonglong)
|
||||
PROGBUF_GET (ulonglong, ulonglong)
|
||||
|
||||
progbuf_h
|
||||
progbuf_alloc (int message_tag, int version)
|
||||
progbuf_alloc (long message_tag)
|
||||
{
|
||||
struct progbuf_s *buf = calloc (1, sizeof (struct progbuf_s));
|
||||
struct progbuf_s *buf = malloc (sizeof (struct progbuf_s));
|
||||
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
buf->buffer = malloc (PROGBUF_INIT_BUFSIZ);
|
||||
if (!buf->buffer)
|
||||
{
|
||||
free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf->capacity = PROGBUF_INIT_BUFSIZ;
|
||||
buf->size = 0;
|
||||
buf->message_tag = message_tag;
|
||||
|
||||
int tag_size = determine_var_ulong_size (ABS (message_tag));
|
||||
write_var_ulong (buf, ABS (message_tag), tag_size, message_tag < 0);
|
||||
buf->header_size = tag_size;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
progbuf_free (progbuf_h buf)
|
||||
progbuf_it_h
|
||||
progbuf_iter_alloc (progbuf_h buf)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
if (buf->buffer)
|
||||
free (buf->buffer);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
free (buf);
|
||||
}
|
||||
struct progbuf_it_s *iter = malloc (sizeof (struct progbuf_it_s));
|
||||
|
||||
if (!iter)
|
||||
return 0;
|
||||
|
||||
iter->buf = buf;
|
||||
iter->read_pos = buf->header_size;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
int
|
||||
progbuf_set_int (progbuf_h buf, int value)
|
||||
progbuf_free (progbuf_h buf)
|
||||
{
|
||||
return -1;
|
||||
if (!buf)
|
||||
return PROGBUF_ERROR_NULL_PARAM;
|
||||
|
||||
free (buf->buffer);
|
||||
free (buf);
|
||||
|
||||
return PROGBUF_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
progbuf_iter_free (progbuf_it_h iter)
|
||||
{
|
||||
if (!iter)
|
||||
return PROGBUF_ERROR_NULL_PARAM;
|
||||
|
||||
free (iter);
|
||||
|
||||
return PROGBUF_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
progbuf_get_message_tag (progbuf_h buf, long *message_tag)
|
||||
{
|
||||
if (!buf || !message_tag)
|
||||
return PROGBUF_ERROR_NULL_PARAM;
|
||||
|
||||
*message_tag = buf->message_tag;
|
||||
|
||||
return PROGBUF_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
progbuf_get_message_buffer (progbuf_h buf, char **buffer, size_t *size)
|
||||
{
|
||||
if (!buf || (!buffer && !size))
|
||||
return PROGBUF_ERROR_NULL_PARAM;
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
*buffer = buf->buffer;
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
*size = buf->size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
progbuf_iter_reset (progbuf_it_h iter)
|
||||
{
|
||||
if (!iter)
|
||||
return PROGBUF_ERROR_NULL_PARAM;
|
||||
|
||||
iter->read_pos = iter->buf->header_size;
|
||||
|
||||
return PROGBUF_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,42 @@
|
||||
#ifndef LIBPROGBUF_H
|
||||
#define LIBPROGBUF_H
|
||||
|
||||
typedef struct progbuf_s *progbuf_h;
|
||||
#include <stddef.h>
|
||||
|
||||
#define PROGBUF_SUCCESS 0
|
||||
#define PROGBUF_ERROR_NULL_PARAM -1
|
||||
#define PROGBUF_ERROR_MEM_ALLOC -2
|
||||
#define PROGBUF_ERROR_END_OF_ITER -3
|
||||
#define PROGBUF_ERROR_UNEXPECTED_TYPE -4
|
||||
#define PROGBUF_ERROR_READ -5
|
||||
#define PROGBUF_ERROR_INCORRECT_SIGN -6
|
||||
|
||||
typedef struct progbuf_s *progbuf_h;
|
||||
typedef struct progbuf_it_s *progbuf_it_h;
|
||||
|
||||
progbuf_h progbuf_alloc (long message_tag);
|
||||
|
||||
int progbuf_get_message_tag (progbuf_h buf, long *message_tag);
|
||||
int progbuf_get_message_buffer (progbuf_h buf, char **buffer, size_t *size);
|
||||
int progbuf_free (progbuf_h buf);
|
||||
|
||||
progbuf_h progbuf_alloc (int message_tag, int version);
|
||||
void progbuf_free (progbuf_h buf);
|
||||
int progbuf_set_int (progbuf_h buf, int value);
|
||||
int progbuf_get_int (progbuf_it_h iter, int *value);
|
||||
int progbuf_set_uint (progbuf_h buf, unsigned int value);
|
||||
int progbuf_get_uint (progbuf_it_h iter, unsigned int *value);
|
||||
|
||||
int progbuf_set_long (progbuf_h buf, long value);
|
||||
int progbuf_get_long (progbuf_it_h iter, long *value);
|
||||
int progbuf_set_ulong (progbuf_h buf, unsigned long value);
|
||||
int progbuf_get_ulong (progbuf_it_h iter, unsigned long *value);
|
||||
|
||||
int progbuf_set_longlong (progbuf_h buf, long long value);
|
||||
int progbuf_get_longlong (progbuf_it_h iter, long long *value);
|
||||
int progbuf_set_ulonglong (progbuf_h buf, unsigned long long value);
|
||||
int progbuf_get_ulonglong (progbuf_it_h iter, unsigned long long *value);
|
||||
|
||||
progbuf_it_h progbuf_iter_alloc (progbuf_h buf);
|
||||
int progbuf_iter_free (progbuf_it_h iter);
|
||||
int progbuf_iter_reset (progbuf_it_h iter);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#include "progbuf.h"
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
progbuf_h buf = progbuf_alloc (1, 1);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user