Add MSVC support for zero-length arrays and packed structs.

This commit is contained in:
Grant Paul 2016-11-15 16:37:43 -08:00 committed by onhachoe
parent 8a433f1394
commit daa326ae9f
4 changed files with 143 additions and 92 deletions

View File

@ -30,6 +30,19 @@
extern "C" {
#endif
#if _MSC_VER
#define __BOM_PACKED_STRUCT_BEGIN __pragma(pack(push, 1))
#define __BOM_PACKED_STRUCT_END __pragma(pack(pop))
#else
#define __BOM_PACKED_STRUCT_BEGIN
#define __BOM_PACKED_STRUCT_END __attribute__((packed))
#endif
#if _MSC_VER
__pragma(warning(push))
__pragma(warning(disable: 4200))
#endif
/**
* Build of Materials format (BOM)
*
@ -62,7 +75,7 @@ extern "C" {
* in the tree has indexes pointing to both key and value data for that item.
*/
struct bom_header {
__BOM_PACKED_STRUCT_BEGIN struct bom_header {
char magic[8]; // = BOMStore
uint32_t version; // = 1?
uint32_t block_count; // = 73 = 0x49?
@ -70,52 +83,56 @@ struct bom_header {
uint32_t index_length; // Length of second part
uint32_t variables_offset;
uint32_t trailer_len; // FIXME: What does this data at the end mean?
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_index {
__BOM_PACKED_STRUCT_BEGIN struct bom_index {
uint32_t address;
uint32_t length;
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_index_header {
__BOM_PACKED_STRUCT_BEGIN struct bom_index_header {
uint32_t count; // FIXME: What is this? It is not the length of the array...
struct bom_index index[0];
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_variable {
__BOM_PACKED_STRUCT_BEGIN struct bom_variable {
uint32_t index;
uint8_t length;
char name[0]; // length
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_variables {
__BOM_PACKED_STRUCT_BEGIN struct bom_variables {
uint32_t count; // Number of entries that follow
struct bom_variable first[0];
} __attribute__((packed));
// Followed by bom_variable entries
} __BOM_PACKED_STRUCT_END;
struct bom_tree { // 21 bytes
__BOM_PACKED_STRUCT_BEGIN struct bom_tree { // 21 bytes
char magic[4]; // = "tree"
uint32_t version;
uint32_t child; // FIXME: Not sure about this one...
uint32_t node_size; // byte count of each entry in the tree (BOMPaths)
uint32_t path_count; // total number of paths in all leaves combined
uint8_t unknown3;
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_tree_entry_indexes {
__BOM_PACKED_STRUCT_BEGIN struct bom_tree_entry_indexes {
uint32_t value_index;
uint32_t key_index;
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_tree_entry {
__BOM_PACKED_STRUCT_BEGIN struct bom_tree_entry {
uint16_t is_leaf; // if 0 then this entry refers to other BOMPaths entries
uint16_t count; // for leaf, count of paths. for top level, (# of leafs - 1)
uint32_t forward; // next leaf, when there are multiple leafs
uint32_t backward; // previous leaf, when there are multiple leafs
struct bom_tree_entry_indexes indexes[0];
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
#if _MSC_VER
__pragma(warning(pop))
#endif
#ifdef __cplusplus
}
#endif

View File

@ -8,6 +8,7 @@
*/
#include <bom/bom.h>
#include <bom/bom_format.h>
#include <libutil/Options.h>
#include <memory>
@ -260,6 +261,11 @@ Help(std::string const &error = std::string())
}
extern "C" {
#if _MSC_VER
__pragma(warning(push))
__pragma(warning(disable: 4200))
#endif
enum bom_path_type {
bom_path_type_file = 1, // BOMPathInfo2 is exe=88 regular=35 bytes
bom_path_type_directory = 2, // BOMPathInfo2 is 31 bytes
@ -267,7 +273,7 @@ extern "C" {
bom_path_type_device = 4 // BOMPathInfo2 is 35 bytes
};
struct bom_path_info_2 {
__BOM_PACKED_STRUCT_BEGIN struct bom_path_info_2 {
uint8_t type; // See types above
uint8_t unknown0; // = 1?
uint16_t architecture; // Not sure exactly what this means...
@ -285,17 +291,21 @@ extern "C" {
char linkName[0];
// FIXME: executable files have a buch of other crap here:
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_path_info_1 {
__BOM_PACKED_STRUCT_BEGIN struct bom_path_info_1 {
uint32_t id;
uint32_t index; // Pointer to BOMPathInfo2
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
struct bom_file {
__BOM_PACKED_STRUCT_BEGIN struct bom_file {
uint32_t parent; // Parent BOMPathInfo1->id
char name[0];
} __attribute__((packed));
} __BOM_PACKED_STRUCT_END;
#if _MSC_VER
__pragma(warning(pop))
#endif
}
int

View File

@ -39,6 +39,19 @@
extern "C" {
#endif
#if _MSC_VER
#define __CAR_PACKED_STRUCT_BEGIN __pragma(pack(push, 1))
#define __CAR_PACKED_STRUCT_END __pragma(pack(pop))
#else
#define __CAR_PACKED_STRUCT_BEGIN
#define __CAR_PACKED_STRUCT_END __attribute__((packed))
#endif
#if _MSC_VER
__pragma(warning(push))
__pragma(warning(disable: 4200))
#endif
/**
* Compiled Asset Archive format (car)
*
@ -82,10 +95,10 @@ extern "C" {
*
*/
struct car_attribute_pair {
__CAR_PACKED_STRUCT_BEGIN struct car_attribute_pair {
uint16_t identifier;
uint16_t value;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
enum car_attribute_identifier {
car_attribute_identifier_element = 1,
@ -180,7 +193,7 @@ enum car_attribute_identifier_size_class_value {
};
// values seem to be little endian, unlike BOM
struct car_header {
__CAR_PACKED_STRUCT_BEGIN struct car_header {
char magic[4]; // RATC
uint32_t ui_version; // 31 01 00 00
@ -196,64 +209,64 @@ struct car_header {
uint32_t schema_version; // 04 00 00 00
uint32_t color_space_id; // 01 00 00 00
uint32_t key_semantics; // 01 00 00 00
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_extended_metadata {
__CAR_PACKED_STRUCT_BEGIN struct car_extended_metadata {
char magic[4]; // 'META'
char contents[1024]; // string
};
} __CAR_PACKED_STRUCT_END;
struct car_key_format {
__CAR_PACKED_STRUCT_BEGIN struct car_key_format {
char magic[4]; // 'tmfk'
uint32_t reserved;
uint32_t num_identifiers;
uint32_t identifier_list[0];
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
// length is key length
typedef char car_facet_key;
struct car_facet_value {
__CAR_PACKED_STRUCT_BEGIN struct car_facet_value {
// ????
struct {
__CAR_PACKED_STRUCT_BEGIN struct {
uint16_t x;
uint16_t y;
} hot_spot;
} hot_spot __CAR_PACKED_STRUCT_END;
uint16_t attributes_count;
struct car_attribute_pair attributes[0];
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_part_element_key {
__CAR_PACKED_STRUCT_BEGIN struct car_part_element_key {
uint32_t part_element_id; // maybe id? increments
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_part_element_value {
__CAR_PACKED_STRUCT_BEGIN struct car_part_element_value {
uint32_t unknown1;
uint32_t unknown2;
char name[0]; // length - 8
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
// flat list of short values in the order of the attributes from the keyformat plus a trailing null
typedef uint16_t car_rendition_key;
struct car_rendition_info_header {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_header {
uint32_t magic;
uint32_t length;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_value {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_value {
char magic[4]; // CTSI is Core Theme Structured Image
uint32_t version; // current known version is 1
struct {
__CAR_PACKED_STRUCT_BEGIN struct {
unsigned int is_header_flagged_fpo : 1;
unsigned int is_excluded_from_contrast_filter : 1;
unsigned int is_vector : 1;
unsigned int is_opaque : 1;
unsigned int bitmap_encoding : 4;
unsigned int reserved : 24;
} flags;
} flags __CAR_PACKED_STRUCT_END;
uint32_t width;
uint32_t height;
@ -262,23 +275,23 @@ struct car_rendition_value {
uint32_t color_space_id : 4; // colorspace ID. 0 for sRGB, all else for generic rgb, used only if pixelFormat 'ARGB'
uint32_t reserved : 28;
struct {
__CAR_PACKED_STRUCT_BEGIN struct {
uint32_t modification_date; // modification date in seconds since 1970?
uint16_t layout; // layout/type of the rendition
uint16_t reserved; // always zero
char name[128];
} metadata;
} metadata __CAR_PACKED_STRUCT_END;
uint32_t info_len; // size of the list of information after header but before bitmap
struct {
__CAR_PACKED_STRUCT_BEGIN struct {
uint32_t bitmap_count;
uint32_t reserved;
uint32_t payload_size; // size of all the proceeding information info_len + data
} bitmaps;
} bitmaps __CAR_PACKED_STRUCT_END;
struct car_rendition_info_header info[0];
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
enum car_rendition_value_pixel_format {
car_rendition_value_pixel_format_argb = 'ARGB', // color + alpha
@ -316,55 +329,55 @@ enum car_rendition_value_layout {
car_rendition_value_layout_asset_pack = 1004,
};
struct car_rendition_info_slice {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_slice {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_slices {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_slices {
struct car_rendition_info_header header;
uint32_t nslices;
struct car_rendition_info_slice slices[0];
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_metrics_metric {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_metrics_metric {
uint32_t width;
uint32_t height;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_metrics {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_metrics {
struct car_rendition_info_header header;
uint32_t nmetrics; // todo should the below be an array?
struct car_rendition_info_metrics_metric top_right_inset;
struct car_rendition_info_metrics_metric bottom_left_inset;
struct car_rendition_info_metrics_metric image_size;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_composition {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_composition {
struct car_rendition_info_header header;
uint32_t blend_mode;
float opacity;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_uti {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_uti {
struct car_rendition_info_header header;
uint32_t uti_length;
char uti[0];
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_bitmap_info {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_bitmap_info {
struct car_rendition_info_header header;
uint32_t exif_orientation;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_bytes_per_row {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_bytes_per_row {
struct car_rendition_info_header header;
uint32_t bytes_per_row;
} __attribute__((packed));
} __CAR_PACKED_STRUCT_END;
struct car_rendition_info_reference {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_info_reference {
struct car_rendition_info_header header;
uint32_t magic; // INLK
uint32_t padding; // always 0?
@ -375,7 +388,7 @@ struct car_rendition_info_reference {
uint16_t layout; // since rendition header says internal link
uint16_t key_length;
car_rendition_key key[0]; // rendition containing data
};
} __CAR_PACKED_STRUCT_END;
enum car_rendition_info_magic {
car_rendition_info_magic_slices = 1001,
@ -388,33 +401,33 @@ enum car_rendition_info_magic {
car_rendition_info_magic_alpha_cropped_frame = 1011,
};
struct car_rendition_data_header1 {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_data_header1 {
char magic[4]; // CELM
struct {
__CAR_PACKED_STRUCT_BEGIN struct {
unsigned int unknown1 : 1;
unsigned int unknown2 : 1;
unsigned int reserved : 30;
} flags;
} flags __CAR_PACKED_STRUCT_END;
uint32_t compression; // see magic below
uint32_t length; // length of data
uint8_t data[0]; // length
};
} __CAR_PACKED_STRUCT_END;
struct car_rendition_data_header2 {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_data_header2 {
char magic[4]; // KCBC
uint32_t unknown1;
uint32_t unknown2;
uint32_t unknown3;
uint32_t length;
uint8_t data[0];
};
} __CAR_PACKED_STRUCT_END;
struct car_rendition_data_header_raw {
__CAR_PACKED_STRUCT_BEGIN struct car_rendition_data_header_raw {
char magic[4]; // DWAR
uint32_t unknown1;
uint32_t length; // length of data
uint8_t data[0];
};
} __CAR_PACKED_STRUCT_END;
enum car_rendition_data_compression_magic {
car_rendition_data_compression_magic_rle = 0,
@ -445,6 +458,10 @@ extern const char *const car_bezels_variable;
extern const char *const car_attribute_identifier_names[_car_attribute_identifier_count];
#if _MSC_VER
__pragma(warning(pop))
#endif
#ifdef __cplusplus
}
#endif

View File

@ -12,28 +12,34 @@
#include <car/AttributeList.h>
#include <car/car_format.h>
struct test_car_facet_value {
struct car_facet_value header;
struct car_attribute_pair attributes[3];
} __attribute__((packed));
static struct test_car_facet_value test_facet_value_s = {
{
{ 0, 0 },
3,
},
{
static struct car_facet_value *
TestFacetValue(size_t *size)
{
static struct car_attribute_pair const attributes[] = {
{ car_attribute_identifier_element, 85 },
{ car_attribute_identifier_part, 181 },
{ car_attribute_identifier_identifier, 4258 },
}
};
};
static struct car_facet_value *test_facet_value = &(test_facet_value_s.header);
static struct car_facet_value *facet_value = nullptr;
static size_t const facet_value_size = sizeof(*facet_value) + sizeof(attributes);
if (facet_value == nullptr) {
facet_value = static_cast<car_facet_value *>(malloc(facet_value_size));
facet_value->hot_spot = { 0, 0 };
facet_value->attributes_count = sizeof(attributes) / sizeof(*attributes);
memcpy(&facet_value->attributes, &attributes, sizeof(attributes));
}
if (size != nullptr) {
*size = facet_value_size;
}
return facet_value;
}
TEST(Facet, Deserialize)
{
auto facet = car::Facet::Load("name", test_facet_value);
auto facet = car::Facet::Load("name", TestFacetValue(nullptr));
EXPECT_EQ(facet.name(), "name");
EXPECT_EQ(*facet.attributes().get(car_attribute_identifier_element), 85);
EXPECT_EQ(*facet.attributes().get(car_attribute_identifier_part), 181);
@ -42,8 +48,9 @@ TEST(Facet, Deserialize)
TEST(Facet, Serialize)
{
std::vector<uint8_t> test_facet_value_vector(reinterpret_cast<uint8_t *>(test_facet_value),
reinterpret_cast<uint8_t *>(test_facet_value) + sizeof(test_facet_value_s));
size_t test_facet_value_size = 0;
uint8_t *test_facet_value = reinterpret_cast<uint8_t *>(TestFacetValue(&test_facet_value_size));
std::vector<uint8_t> test_facet_value_vector(test_facet_value, test_facet_value + test_facet_value_size);
car::AttributeList attributes = car::AttributeList({
{ car_attribute_identifier_element, 85 },