Skip to content

Commit

Permalink
Initial implementation for bitstream file parser
Browse files Browse the repository at this point in the history
  • Loading branch information
matwey committed Jul 22, 2017
1 parent e298af6 commit 134133c
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 0 deletions.
23 changes: 23 additions & 0 deletions include/bit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef _BIT_H
#define _BIT_H

#include <memory.h>

struct bit {
const void* data;
size_t size;

const char* ncd_filename;
const char* part_name;
const char* date;
const char* time;
size_t bit_length;

const char* error_str;
};

int bit_init(struct bit* bit, const void* data, size_t size);

const char* bit_get_error_string(struct bit* bit);

#endif // _BIT_H
137 changes: 137 additions & 0 deletions src/bit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include <bit.h>

#include <stdint.h>
#include <string.h>

#include <arpa/inet.h>

static int bit_do_parse_field1_2(struct bit* bit) {
static const uint8_t header[] = {0x00,0x09,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x00,0x00,0x01};

if (bit->size < sizeof(header) || memcmp(bit->data, header, sizeof(header)) != 0) {
bit->error_str = "Wrong bit header";
return -1;
}

bit->data += sizeof(header);
bit->size -= sizeof(header);

return 0;
}

static int bit_do_parse_field_str(struct bit* bit, uint8_t key, const char** str) {
uint16_t len;

if (bit->size < sizeof(key) + sizeof(len)) {
bit->error_str = "Too few bytes";
return -1;
}

if (((uint8_t*)bit->data)[0] != key) {
bit->error_str = "Incorrent field key";
return -1;
}

bit->data += sizeof(key);
bit->size -= sizeof(key);

memcpy(&len, bit->data, sizeof(len));
len = htons(len);

bit->data += sizeof(len);
bit->size -= sizeof(len);

if (bit->size < len) {
bit->error_str = "Too few bytes";
return -1;
}

/* string is null-terminated */
*str = bit->data;
bit->data += len;
bit->size -= len;

return 0;
}

static int bit_do_parse_field2_3(struct bit* bit) {
return bit_do_parse_field_str(bit, 'a', &bit->ncd_filename);
}

static int bit_do_parse_field4(struct bit* bit) {
return bit_do_parse_field_str(bit, 'b', &bit->part_name);
}

static int bit_do_parse_field5(struct bit* bit) {
return bit_do_parse_field_str(bit, 'c', &bit->date);
}

static int bit_do_parse_field6(struct bit* bit) {
return bit_do_parse_field_str(bit, 'd', &bit->time);
}

static int bit_do_parse_field7(struct bit* bit) {
uint32_t len;
const uint8_t key = 'e';

if (bit->size < sizeof(key) + sizeof(len)) {
bit->error_str = "Too few bytes";
return -1;
}

if (((uint8_t*)bit->data)[0] != key) {
bit->error_str = "Incorrent field key";
return -1;
}

bit->data += sizeof(key);
bit->size -= sizeof(key);

memcpy(&len, bit->data, sizeof(len));
len = htonl(len);

bit->bit_length = len;
bit->data += sizeof(len);
bit->size -= sizeof(len);

if (bit->size < len) {
bit->error_str = "Too few bytes";
return -1;
}

bit->data += len;
bit->size -= len;

return 0;
}

/*
* http://www.fpga-faq.com/FAQ_Pages/0026_Tell_me_about_bit_files.htm
*/
static int bit_do_parse(struct bit* bit) {
if (bit_do_parse_field1_2(bit) < 0)
return -1;
if (bit_do_parse_field2_3(bit) < 0)
return -1;
if (bit_do_parse_field4(bit) < 0)
return -1;
if (bit_do_parse_field5(bit) < 0)
return -1;
if (bit_do_parse_field6(bit) < 0)
return -1;
if (bit_do_parse_field7(bit) < 0)
return -1;

return 0;
}

int bit_init(struct bit* bit, const void* data, size_t size) {
bit->data = data;
bit->size = size;

return bit_do_parse(bit);
}

const char* bit_get_error_string(struct bit* bit) {
return bit->error_str;
}
71 changes: 71 additions & 0 deletions test/bit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <check.h>
#include <stdlib.h>

#include <bit.h>

START_TEST (test_bit_init1) {
static const uint8_t data[] = {
0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x0a,
0x78, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x6e, 0x63, 0x64, 0x00, 0x62, 0x00, 0x0c, 0x76, 0x31, 0x30,
0x30, 0x30, 0x65, 0x66, 0x67, 0x38, 0x36, 0x30, 0x00, 0x63, 0x00, 0x0b, 0x32, 0x30, 0x30, 0x31,
0x2f, 0x30, 0x38, 0x2f, 0x31, 0x30, 0x00, 0x64, 0x00, 0x09, 0x30, 0x36, 0x3a, 0x35, 0x35, 0x3a,
0x30, 0x34, 0x00, 0x65, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff};

struct bit bit;
ck_assert_int_eq(bit_init(&bit, data, sizeof(data)), 0);
ck_assert_str_eq(bit.ncd_filename, "xform.ncd");
ck_assert_str_eq(bit.part_name, "v1000efg860");
ck_assert_str_eq(bit.date, "2001/08/10");
ck_assert_str_eq(bit.time, "06:55:04");
ck_assert_uint_eq(bit.bit_length, 4);
}
END_TEST

START_TEST (test_bit_init2) {
static const uint8_t data[] = {
0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x1a,
0x6f, 0x76, 0x33, 0x2e, 0x6e, 0x63, 0x64, 0x3b, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x3d, 0x30,
0x78, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x00, 0x62, 0x00, 0x0c, 0x36, 0x73, 0x6c,
0x78, 0x39, 0x74, 0x71, 0x67, 0x31, 0x34, 0x34, 0x00, 0x63, 0x00, 0x0b, 0x32, 0x30, 0x31, 0x34,
0x2f, 0x31, 0x31, 0x2f, 0x31, 0x30, 0x00, 0x64, 0x00, 0x09, 0x31, 0x36, 0x3a, 0x33, 0x31, 0x3a,
0x30, 0x37, 0x00, 0x65, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff};

struct bit bit;
ck_assert_int_eq(bit_init(&bit, data, sizeof(data)), 0);
ck_assert_str_eq(bit.ncd_filename, "ov3.ncd;UserID=0xFFFFFFFF");
ck_assert_str_eq(bit.part_name, "6slx9tqg144");
ck_assert_str_eq(bit.date, "2014/11/10");
ck_assert_str_eq(bit.time, "16:31:07");
ck_assert_uint_eq(bit.bit_length, 4);
}
END_TEST

Suite* range_suite(void) {
Suite *s;
TCase *tc_core;

s = suite_create("bit");

tc_core = tcase_create("Core");

tcase_add_test(tc_core, test_bit_init1);
tcase_add_test(tc_core, test_bit_init2);
suite_add_tcase(s, tc_core);

return s;
}

int main(void) {
int number_failed;
Suite *s;
SRunner *sr;

s = range_suite();
sr = srunner_create(s);

srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? 0 : 1;
}

0 comments on commit 134133c

Please sign in to comment.