Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sven Gestegård Robertz
LabComm
Commits
5aba36c4
Commit
5aba36c4
authored
Apr 11, 2013
by
Sven Robertz
Browse files
adapted sig_parser to varint
parent
506eb33b
Changes
2
Show whitespace changes
Inline
Side-by-side
lib/c/experimental/labcomm_parser.c
deleted
100644 → 0
View file @
506eb33b
/* labcomm_parser.c:
* an example parser for labcomm signatures, illustrating how to skip samples
* based on their signature. Intended as an embryo for introducing this
* functionality into the lib to allow a channel to survive types with no
* registered handler.
*/
#include
<stdlib.h>
#include
<stdio.h>
#include
<string.h>
#define DEBUG
#define FALSE 0
#define TRUE 1
#define USER_ID_BASE 0x00000080
typedef
enum
{
TYPE_DECL
=
0x00000001
,
SAMPLE_DECL
=
0x00000002
,
ARRAY_DECL
=
0x00000010
,
STRUCT_DECL
=
0x00000011
,
TYPE_BOOLEAN
=
0x00000020
,
TYPE_BYTE
=
0x00000021
,
TYPE_SHORT
=
0x00000022
,
TYPE_INTEGER
=
0x00000023
,
TYPE_LONG
=
0x00000024
,
TYPE_FLOAT
=
0x00000025
,
TYPE_DOUBLE
=
0x00000026
,
TYPE_STRING
=
0x00000027
}
labcomm_type
;
void
error
(
char
*
s
)
{
fprintf
(
stderr
,
"%s"
,
s
);
fprintf
(
stderr
,
"
\n
exiting
\n
"
);
exit
(
1
);
}
#define BUF_SIZE 1024
#define STACK_SIZE 16
/* internal type: stack for the parser */
typedef
struct
{
unsigned
char
*
c
;
unsigned
int
size
;
unsigned
int
capacity
;
unsigned
int
idx
;
unsigned
int
*
stack
;
unsigned
int
top
;
}
buffer
;
/* aux method for reading a big endian uint32 from a char* (i.e. ntohl but for explicit char*) */
static
int
unpack32
(
unsigned
char
*
c
,
unsigned
int
idx
)
{
unsigned
int
b0
=
(
c
[
idx
])
<<
3
;
unsigned
int
b1
=
(
c
[
idx
+
1
])
<<
2
;
unsigned
int
b2
=
(
c
[
idx
+
2
])
<<
1
;
unsigned
int
b3
=
c
[
idx
+
3
];
return
b0
|
b1
|
b2
|
b3
;
}
void
dumpStack
(
buffer
*
b
)
{
#ifdef DEBUG
int
i
;
printf
(
"=== stack: "
);
for
(
i
=
0
;
i
<
STACK_SIZE
;
i
++
)
{
//HERE BE DRAGONS
printf
(
"%2.2x "
,
b
->
stack
[
i
]);
}
printf
(
" top==%d
\n
"
,
b
->
top
);
#endif
}
void
push
(
buffer
*
b
,
unsigned
int
e
)
{
b
->
stack
[
b
->
top
]
=
e
;
b
->
top
=
b
->
top
-
1
;
dumpStack
(
b
);
}
unsigned
int
pop
(
buffer
*
b
)
{
b
->
top
=
b
->
top
+
1
;
return
b
->
stack
[
b
->
top
];
}
int
init_buffer
(
buffer
*
b
,
size_t
size
,
size_t
stacksize
)
{
b
->
c
=
malloc
(
size
);
b
->
capacity
=
size
;
b
->
idx
=
0
;
b
->
stack
=
calloc
(
stacksize
,
sizeof
(
b
->
stack
));
b
->
top
=
stacksize
-
1
;
return
b
->
c
==
NULL
||
b
->
stack
==
NULL
;
}
int
more
(
buffer
*
b
)
{
return
b
->
idx
<
b
->
size
;
}
unsigned
char
get
(
buffer
*
b
)
{
return
b
->
c
[
b
->
idx
++
];
}
unsigned
char
peek
(
buffer
*
b
)
{
return
b
->
c
[
b
->
idx
];
}
void
advance
(
buffer
*
b
)
{
b
->
idx
++
;
}
void
advancen
(
buffer
*
b
,
size_t
n
)
{
b
->
idx
+=
n
;
}
unsigned
int
peek32
(
buffer
*
b
)
{
return
unpack32
(
b
->
c
,
b
->
idx
);
}
void
advance32
(
buffer
*
b
)
{
b
->
idx
+=
4
;
}
unsigned
int
get32
(
buffer
*
b
)
{
unsigned
int
res
=
peek32
(
b
);
advance32
(
b
);
return
res
;
}
void
getStr
(
buffer
*
b
,
char
*
dest
,
size_t
size
)
{
int
rem
=
b
->
size
-
b
->
idx
;
if
(
size
>
rem
)
size
=
rem
;
strncpy
(
dest
,
&
b
->
c
[
b
->
idx
],
size
);
b
->
idx
+=
size
;
}
//XXX experimental
#define MAX_SIGNATURES 10
#define MAX_NAME_LEN 32
#define MAX_SIG_LEN 128
unsigned
int
signatures_length
[
MAX_SIGNATURES
];
unsigned
char
signatures_name
[
MAX_SIGNATURES
][
MAX_NAME_LEN
];
//HERE BE DRAGONS: add range checks
unsigned
char
signatures
[
MAX_SIGNATURES
][
MAX_SIG_LEN
];
unsigned
int
get_signature_len
(
unsigned
int
uid
){
return
signatures_length
[
uid
-
USER_ID_BASE
];
}
unsigned
char
*
get_signature_name
(
unsigned
int
uid
){
return
&
signatures_name
[
uid
-
USER_ID_BASE
][
1
];
}
unsigned
char
*
get_signature
(
unsigned
int
uid
){
return
signatures
[
uid
-
USER_ID_BASE
];
}
void
dump_signature
(
unsigned
int
uid
){
int
i
;
unsigned
int
len
=
get_signature_len
(
uid
);
printf
(
"signature for uid %x : %s (len=%d):
\n
"
,
uid
,
get_signature_name
(
uid
),
len
);
unsigned
char
*
sig
=
get_signature
(
uid
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
printf
(
"%2.2x "
,
sig
[
i
]);
if
(
(
i
+
1
)
%
8
==
0
)
printf
(
"
\n
"
);
}
printf
(
"
\n
"
);
}
int
labcomm_sizeof
(
unsigned
int
type
)
{
switch
(
type
)
{
case
TYPE_BOOLEAN
:
case
TYPE_BYTE
:
return
1
;
case
TYPE_SHORT
:
return
2
;
case
TYPE_INTEGER
:
case
TYPE_FLOAT
:
return
4
;
case
TYPE_LONG
:
case
TYPE_DOUBLE
:
return
8
;
default:
printf
(
"labcomm_sizeof(%x)
\n
"
,
type
);
error
(
"labcomm_sizeof should only be called for primitive types"
);
}
}
int
accept_packet
(
buffer
*
d
);
int
accept_type_decl
(
buffer
*
d
);
int
accept_sample_decl
(
buffer
*
d
);
int
accept_user_id
(
buffer
*
d
);
int
accept_string
(
buffer
*
d
);
int
accept_string_length
(
buffer
*
d
);
int
accept_char
(
buffer
*
d
);
int
accept_type
(
buffer
*
d
);
int
accept_basic_type
(
buffer
*
d
);
int
accept_boolean_type
(
buffer
*
d
);
int
accept_byte_type
(
buffer
*
d
);
int
accept_short_type
(
buffer
*
d
);
int
accept_integer_type
(
buffer
*
d
);
int
accept_long_type
(
buffer
*
d
);
int
accept_float_type
(
buffer
*
d
);
int
accept_long_type
(
buffer
*
d
);
int
accept_string_type
(
buffer
*
d
);
int
accept_array_decl
(
buffer
*
d
);
int
accept_number_of_indices
(
buffer
*
d
);
int
accept_indices
(
buffer
*
d
);
int
accept_variable_index
(
buffer
*
d
);
int
accept_fixed_index
(
buffer
*
d
);
int
accept_struct_decl
(
buffer
*
d
);
int
accept_number_of_fields
(
buffer
*
d
);
int
accept_field
(
buffer
*
d
);
int
accept_sample_data
(
buffer
*
d
);
int
accept_packed_sample_data
(
buffer
*
d
);
int
read_file
(
FILE
*
f
,
buffer
*
b
)
{
int
s
=
fread
(
b
->
c
,
sizeof
(
char
),
b
->
capacity
,
f
);
b
->
size
=
s
;
b
->
idx
=
0
;
return
s
;
}
void
test_read
(
buffer
*
buf
)
{
int
r
=
read_file
(
stdin
,
buf
);
printf
(
"read %d bytes:
\n\n
"
,
r
);
int
i
;
for
(
i
=
0
;
i
<
r
;
i
++
)
{
printf
(
"%x "
,
buf
->
c
[
i
]);
if
(
i
%
8
==
7
)
printf
(
"
\n
"
);
}
printf
(
"
\n
"
);
}
int
main
()
{
buffer
buf
;
if
(
init_buffer
(
&
buf
,
BUF_SIZE
,
STACK_SIZE
)
)
{
printf
(
"failed to init buffer
\n
"
);
exit
(
1
);
}
test_read
(
&
buf
);
do
{
printf
(
"trying to read another packet
\n
"
);
}
while
(
more
(
&
buf
)
&&
accept_packet
(
&
buf
));
printf
(
"done
\n
"
);
}
int
accept_packet
(
buffer
*
d
)
{
if
(
accept_type_decl
(
d
))
{
printf
(
"*** got type decl
\n
"
);
}
else
if
(
accept_sample_decl
(
d
))
{
printf
(
"*** got sample decl
\n
"
);
}
else
if
(
accept_sample_data
(
d
))
{
printf
(
"*** got sample data
\n
"
);
}
else
{
// error("unexpected %x, expecting packet", d->c[d->idx]);
error
(
"packet"
);
}
}
int
accept_type_decl
(
buffer
*
d
){
unsigned
int
type
=
peek32
(
d
)
;
if
(
type
==
TYPE_DECL
)
{
advance32
(
d
);
accept_user_id
(
d
);
unsigned
int
uid
=
pop
(
d
);
accept_string
(
d
);
// ignore, for now. This should do something as
// char *name = (char*) pop(d);
// store or print name
// free(name)
accept_type
(
d
);
unsigned
int
type
=
pop
(
d
);
//push(d, type);
return
TRUE
;
}
else
{
return
FALSE
;
}
}
int
accept_sample_decl
(
buffer
*
d
){
unsigned
int
type
=
peek32
(
d
)
;
if
(
type
==
SAMPLE_DECL
)
{
advance32
(
d
);
accept_user_id
(
d
);
unsigned
int
nstart
=
d
->
idx
;
unsigned
int
uid
=
pop
(
d
);
accept_string
(
d
);
unsigned
int
start
=
d
->
idx
;
unsigned
int
nlen
=
pop
(
d
);
accept_type
(
d
);
unsigned
int
dt
=
pop
(
d
);
unsigned
int
end
=
d
->
idx
;
unsigned
int
len
=
end
-
start
;
if
(
len
<=
MAX_SIG_LEN
)
{
signatures_length
[
uid
-
USER_ID_BASE
]
=
len
;
memcpy
(
signatures_name
[
uid
-
USER_ID_BASE
],
&
d
->
c
[
nstart
+
3
],
nlen
+
1
);
}
else
{
error
(
"sig longer than max length (this ought to be dynamic...)"
);
}
if
(
nlen
<
MAX_NAME_LEN
)
{
// reserve space for terminating NULL
signatures_name
[
uid
-
USER_ID_BASE
][
nlen
+
1
]
=
0
;
memcpy
(
signatures
[
uid
-
USER_ID_BASE
],
&
d
->
c
[
start
],
len
);
}
else
{
error
(
"sig name longer than max length (this ought to be dynamic..."
);
}
printf
(
"signature for uid %x: %s (start=%x,end=%x, nlen=%d,len=%d)
\n
"
,
uid
,
get_signature_name
(
uid
),
start
,
end
,
nlen
,
len
);
return
TRUE
;
}
else
{
return
FALSE
;
}
}
int
accept_user_id
(
buffer
*
d
){
unsigned
int
uid
=
peek32
(
d
);
if
(
uid
>=
USER_ID_BASE
)
{
push
(
d
,
uid
);
advance32
(
d
);
//printf("uid = %x\n", uid);
return
TRUE
;
}
else
{
return
FALSE
;
}
}
int
accept_string
(
buffer
*
d
){
unsigned
int
len
=
get32
(
d
);
push
(
d
,
len
);
char
*
str
=
malloc
(
len
);
getStr
(
d
,
str
,
len
);
printf
(
"%s
\n
"
,
str
);
#ifdef RETURN_STRINGS
push
(
d
,
str
);
#else
free
(
str
);
#endif
return
TRUE
;
}
// included above
// int accept_string_length(buffer *d){
// unsigned int uid = get32(d);
// return TRUE;
//}
//int accept_char(buffer *d){
//}
int
accept_type
(
buffer
*
d
){
if
(
accept_basic_type
(
d
))
{
}
else
if
(
accept_user_id
(
d
))
{
//printf("user_id \n");
}
else
if
(
accept_array_decl
(
d
))
{
//printf("array_decl \n");
}
else
if
(
accept_struct_decl
(
d
))
{
//printf("struct_decl \n");
}
else
{
return
FALSE
;
}
}
int
accept_basic_type
(
buffer
*
d
){
unsigned
int
type
=
peek32
(
d
);
switch
(
type
)
{
case
TYPE_BOOLEAN
:
//printf("boolean \n");
break
;
case
TYPE_BYTE
:
//printf("byte \n");
break
;
case
TYPE_SHORT
:
//printf("short \n");
break
;
case
TYPE_INTEGER
:
//printf("integer \n");
break
;
case
TYPE_LONG
:
//printf("long \n");
break
;
case
TYPE_FLOAT
:
//printf("float \n");
break
;
case
TYPE_DOUBLE
:
//printf("double \n");
break
;
case
TYPE_STRING
:
//printf("string \n");
break
;
default
:
return
FALSE
;
}
advance32
(
d
);
push
(
d
,
type
);
return
TRUE
;
}
#if 0 // handle all basic types above
int accept_boolean_type(buffer *d){
}
int accept_byte_type(buffer *d){
}
int accept_short_type(buffer *d){
}
int accept_integer_type(buffer *d){
}
int accept_long_type(buffer *d){
}
int accept_float_type(buffer *d){
}
int accept_string_type(buffer *d){
}
#endif
int
accept_array_decl
(
buffer
*
d
){
unsigned
int
tid
=
peek32
(
d
);
if
(
tid
==
ARRAY_DECL
)
{
advance32
(
d
);
unsigned
int
nidx
=
get32
(
d
);
printf
(
"%d dim array: "
,
nidx
);
int
i
;
unsigned
int
numVar
=
0
;
unsigned
int
size
=
1
;
for
(
i
=
0
;
i
<
nidx
;
i
++
)
{
unsigned
int
idx
=
get32
(
d
);
if
(
idx
==
0
)
{
numVar
++
;
printf
(
"variable index (numVar=%d), "
,
numVar
);
}
else
{
printf
(
"fixed index: %d, "
,
idx
);
size
*=
idx
;
}
printf
(
"
\n
"
);
}
unsigned
int
et
=
accept_type
(
d
);
printf
(
"array element type: %x
\n
"
,
et
);
pop
(
d
);
//push(d,tid);
return
TRUE
;
}
else
{
return
FALSE
;
}
}
#if 0
int accept_number_of_indices(buffer *d){
}
int accept_indices(buffer *d){
}
int accept_variable_index(buffer *d){
}
int accept_fixed_index(buffer *d){
}
#endif
int
accept_struct_decl
(
buffer
*
d
){
unsigned
int
tid
=
peek32
(
d
);
if
(
tid
==
STRUCT_DECL
)
{
advance32
(
d
);
unsigned
int
nf
=
get32
(
d
);
printf
(
"%d field struct: "
,
nf
);
int
i
;
int
numVar
=
0
;
int
size
=
0
;
for
(
i
=
0
;
i
<
nf
;
i
++
)
{
accept_field
(
d
);
}
push
(
d
,
tid
);
return
TRUE
;
}
else
{
return
FALSE
;
}
}
#if 0
int accept_number_of_fields(buffer *d){
}
#endif
int
accept_field
(
buffer
*
d
){
accept_string
(
d
);
// ignore, for now
accept_type
(
d
);
unsigned
int
type
=
pop
(
d
);
printf
(
"field: %x
\n
"
,
type
);
}
int
accept_sample_data
(
buffer
*
d
){
accept_user_id
(
d
);
unsigned
int
uid
=
pop
(
d
);
printf
(
"sample data... %x
\n
"
,
uid
);
#ifdef DEBUG
dump_signature
(
uid
);
#endif
unsigned
int
siglen
=
get_signature_len
(
uid
);
unsigned
char
*
sig
=
get_signature
(
uid
);
skip_packed_sample_data
(
d
,
sig
,
siglen
);
return
TRUE
;
}
//int accept_packed_sample_data(buffer *d){
int
skip_type
(
unsigned
int
,
buffer
*
,
unsigned
char
*
,
unsigned
int
,
unsigned
int
*
)
;
int
skip_array
(
buffer
*
d
,
unsigned
char
*
sig
,
unsigned
int
len
,
unsigned
int
*
pos
)
{
unsigned
int
skip
=
0
;
unsigned
int
tot_nbr_elem_tmp
=
1
;
unsigned
int
nIdx
=
unpack32
(
sig
,
*
pos
);
printf
(
"skip_array: nIdx = %d
\n
"
,
nIdx
);
*
pos
+=
4
;
unsigned
int
idx
[
nIdx
];
unsigned
int
nVar
=
0
;
unsigned
int
i
;
for
(
i
=
0
;
i
<
nIdx
;
i
++
)
{
idx
[
i
]
=
unpack32
(
sig
,
*
pos
);
*
pos
+=
4
;
printf
(
"skip_array: idx[%d]=%d
\n
"
,
i
,
idx
[
i
]);
if
(
idx
[
i
]
==
0
)
{
nVar
++
;
}
else
{
tot_nbr_elem_tmp
*=
idx
[
i
];
}
}
unsigned
int
var
[
nVar
];
for
(
i
=
0
;
i
<
nVar
;
i
++
)
{
var
[
i
]
=
get32
(
d
);
printf
(
"skip_array: var[%d]=%d
\n
"
,
i
,
var
[
i
]);
}
unsigned
int
type
=
unpack32
(
sig
,
*
pos
);
*
pos
+=
4
;
unsigned
int
elemSize
=
labcomm_sizeof
(
type
);
skip
=
elemSize
*
tot_nbr_elem_tmp
;
printf
(
"skip_array: skip: %d * %d = %d
\n
"
,
elemSize
,
tot_nbr_elem_tmp
,
skip
);
advancen
(
d
,
skip
);
skip
+=
nVar
;
return
skip
;
}
int
skip_struct
(
buffer
*
d
,
unsigned
char
*
sig
,
unsigned
int
len
,
unsigned
int
*
pos
)
{
unsigned
int
nFields
=
unpack32
(
sig
,
*
pos
);
*
pos
+=
4
;
unsigned
int
i
;
unsigned
int
skipped
=
0
;
printf
(
"skip_struct (%d fields)
\n
"
,
nFields
);
for
(
i
=
0
;
i
<
nFields
;
i
++
)
{
//skip name
unsigned
int
namelen
=
unpack32
(
sig
,
*
pos
);
*
pos
+=
(
4
+
namelen
);
// 32bit len + actual string
#ifdef DEBUG
printf
(
"namelen==%d
\n
"
,
namelen
);
#endif
unsigned
int
type
=
unpack32
(
sig
,
*
pos
);
*
pos
+=
4
;
#ifdef DEBUG
printf
(
"type == %x
\n
"
,
type
);
#endif
skipped
+=
skip_type
(
type
,
d
,
sig
,
len
,
pos
);
}
return
skipped
;
}
#ifndef QUIET
/* print and skip */
int
skip_type
(
unsigned
int
type
,
buffer
*
d
,
unsigned
char
*
sig
,
unsigned
int
len
,
unsigned
int
*
pos
)
{
int
skipped
=
0
;
printf
(
"skip_type %x:"
,
type
);
switch
(
type
)
{
case
TYPE_BOOLEAN
:
printf
(
"boolean [%d]
\n
"
,
get
(
d
));
skipped
++
;
break
;
case
TYPE_BYTE
:
printf
(
"byte [%d]
\n
"
,
get
(
d
));
skipped
++
;
break
;
case
TYPE_SHORT
:
//XXX not supported
advancen
(
d
,
2
);
skipped
+=
2
;
break
;
case
TYPE_INTEGER
:
printf
(
"integer [%d]
\n
"
,
get32
(
d
));
skipped
+=
4
;
break
;
case
TYPE_FLOAT
:
//XXX not supported
advancen
(
d
,
4
);
skipped
+=
4
;
break
;
case
TYPE_LONG
:
case
TYPE_DOUBLE
:
//XXX not supported
advancen
(
d
,
8
);
skipped
+=
8
;
break
;
case
TYPE_STRING
:
{
unsigned
int
len
=
get32
(
d
);
//advancen(d,len);
int
i
;
printf
(
"string ["
);
for
(
i
=
0
;
i
<
len
;
i
++
)
printf
(
"%c"
,
get
(
d
));
printf
(
"]
\n
"
);
skipped
+=
len
+
4
;
break
;}
case
ARRAY_DECL
:
printf
(
"array
\n
"
);
skipped
+=
skip_array
(
d
,
sig
,
len
,
pos
);
case
STRUCT_DECL
:
printf
(
"struct
\n
"
);
skipped
+=
skip_struct
(
d
,
sig
,
len
,
pos
);