diff --git a/qmake/fougdatax.pro b/qmake/fougdatax.pro index 892f436..6a39903 100644 --- a/qmake/fougdatax.pro +++ b/qmake/fougdatax.pro @@ -30,7 +30,9 @@ HEADERS += \ ../src/transfer.h \ \ ../src/internal/convert.h \ - ../src/internal/ascii_parse.h + ../src/internal/ascii_parse.h \ + ../src/internal/byte_swap.h \ + ../src/internal/byte_codec.h SOURCES += \ ../src/endian.c \ @@ -55,19 +57,28 @@ contains(DATAX, stl) { #DEFINES += FOUG_STLB_READWRITE_ALIGNSAFE HEADERS += \ + ../src/libstl/stl_error.h \ + ../src/libstl/stl_format.h \ ../src/libstl/stl_global.h \ + ../src/libstl/stl_triangle.h \ ../src/libstl/stla_read.h \ ../src/libstl/stla_write.h \ ../src/libstl/stlb_read.h \ ../src/libstl/stlb_write.h \ - ../src/libstl/stl_triangle.h \ - ../src/libstl/stlb_triangle.h + ../src/libstl/stlb_triangle.h \ + \ + ../src/internal/libstl/stlb_byte_swap.h \ + ../src/internal/libstl/stlb_rw_common.h SOURCES += \ + ../src/libstl/stl_format.c \ ../src/libstl/stla_read.c \ ../src/libstl/stla_write.c \ ../src/libstl/stlb_read.c \ - ../src/libstl/stlb_write.c + ../src/libstl/stlb_write.c \ + \ + ../src/internal/libstl/stlb_byte_swap.c \ + ../src/internal/libstl/stlb_rw_common.c libstl_inc.path = $$PREFIX_DIR/include/datax/libstl libstl_inc.files = ../src/libstl/*.h @@ -141,4 +152,7 @@ contains(DATAX, occ_support) { OTHER_FILES += \ ../doc/main_page.cpp \ - ../doc/Doxyfile + ../doc/Doxyfile \ + \ + ../src/config.h.cmake + diff --git a/src/endian.c b/src/endian.c index 8d087fc..bfc12cd 100644 --- a/src/endian.c +++ b/src/endian.c @@ -2,15 +2,12 @@ #include "internal/convert.h" -#ifdef FOUG_HAVE_MSVC_BUILTIN_BSWAP_FUNC -# include -#endif #include typedef union { uint32_t integer; - uint8_t bytes[4]; + uint8_t bytes[4]; } _internal_foug_int_bytes_32_convert_t; /*! Endianness (byte order) of the host's CPU architecture */ @@ -29,122 +26,3 @@ foug_endianness_t foug_host_endianness() return FOUG_OTHER_ENDIAN; } -/*! Returns \p val with the order of bytes reversed. - * - * Uses compiler builtin functions if available - */ -uint16_t foug_uint16_bswap(uint16_t val) -{ -#ifdef FOUG_HAVE_GCC_BUILTIN_BSWAP_FUNC - return __builtin_bswap16(val); -#elif defined(FOUG_HAVE_MSVC_BUILTIN_BSWAP_FUNC) - return _byteswap_ushort(val); -#else - return ((val & 0x00FF) << 8) | ((val >> 8) & 0x00FF); -#endif -} - -/*! Read a 16bit integer from memory-location \p bytes (little-endian byte order) */ -uint16_t foug_decode_uint16_le(const uint8_t* bytes) -{ - /* |0 |1 | */ - /* |BB|AA| -> 0xAABB */ - return (bytes[1] << 8) | bytes[0]; -} - -/*! Read a 16bit integer from memory-location \p bytes (big-endian byte order) */ -uint16_t foug_decode_uint16_be(const uint8_t* bytes) -{ - /* |0 |1 | */ - /* |AA|BB| -> 0xAABB */ - return (bytes[0] << 8) | bytes[1]; -} - -/*! Write 16bit integer \p val to the memory location at \p bytes in little-endian byte order */ -void foug_encode_uint16_le(uint16_t val, uint8_t* bytes) -{ - bytes[0] = val & 0xFF; - bytes[1] = (val >> 8) & 0xFF; -} - -/*! Returns \p val with the order of bytes reversed. - * - * Uses compiler builtin functions if available - */ -uint32_t foug_uint32_bswap(uint32_t val) -{ -#ifdef FOUG_HAVE_GCC_BUILTIN_BSWAP_FUNC - return __builtin_bswap32(val); -#elif defined(FOUG_HAVE_MSVC_BUILTIN_BSWAP_FUNC) - return _byteswap_ulong(val); -#else - return - ((val & 0x000000FF) << 24) - | ((val & 0x0000FF00) << 8) - | ((val >> 8) & 0x0000FF00) - | ((val >> 24) & 0x000000FF); -#endif -} - -/*! Read a 32bit integer from memory-location \p bytes (little-endian byte order) */ -uint32_t foug_decode_uint32_le(const uint8_t* bytes) -{ - /* |DD|CC|BB|AA| -> 0xAABBCCDD */ - return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); -} - -/*! Read a 32bit integer from memory-location \p bytes (mixed-endian byte order) */ -uint32_t foug_decode_uint32_me(const uint8_t* bytes) -{ - /* |DD|CC|BB|AA| -> 0xCCDDAABB */ - return (bytes[0] >> 8) | (bytes[2] << 8) | (bytes[3] << 8) | (bytes[1] << 8); -} - -/*! Read a 32bit integer from memory-location \p bytes (big-endian byte order) */ -uint32_t foug_decode_uint32_be(const uint8_t* bytes) -{ - /* |DD|CC|BB|AA| -> 0xDDCCBBAA */ - return bytes[3] | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24); -} - -/*! Write 32bit integer \p val to the memory location at \p bytes in little-endian byte order */ -void foug_encode_uint32_le(uint32_t val, uint8_t* bytes) -{ - bytes[0] = val & 0xFF; - bytes[1] = (val >> 8) & 0xFF; - bytes[2] = (val >> 16) & 0xFF; - bytes[3] = (val >> 24) & 0xFF; -} - -/*! Write 32bit integer \p val to the memory location at \p bytes in big-endian byte order */ -void foug_encode_uint32_be(uint32_t val, uint8_t* bytes) -{ - bytes[0] = (val >> 24) & 0xFF; - bytes[1] = (val >> 16) & 0xFF; - bytes[2] = (val >> 8) & 0xFF; - bytes[3] = val & 0xFF; -} - -/*! Read a 32bit real from memory-location \p bytes (little-endian byte order) */ -foug_real32_t foug_decode_real32_le(const uint8_t* bytes) -{ - return foug_convert_real32(foug_decode_uint32_le(bytes)); -} - -/*! Read a 32bit real from memory-location \p bytes (mixed-endian byte order) */ -foug_real32_t foug_decode_real32_me(const uint8_t* bytes) -{ - return foug_convert_real32(foug_decode_uint32_me(bytes)); -} - -/*! Read a 32bit real from memory-location \p bytes (big-endian byte order) */ -foug_real32_t foug_decode_real32_be(const uint8_t* bytes) -{ - return foug_convert_real32(foug_decode_uint32_be(bytes)); -} - -/*! Write 32bit real \p val to the memory location at \p bytes in little-endian byte order */ -void foug_encode_real32_le(foug_real32_t val, uint8_t* bytes) -{ - foug_encode_uint32_le(foug_convert_uint32(val), bytes); -} diff --git a/src/endian.h b/src/endian.h index 6302783..d3d33b2 100644 --- a/src/endian.h +++ b/src/endian.h @@ -13,21 +13,4 @@ typedef enum FOUG_LIB_EXPORT foug_endianness_t foug_host_endianness(); -FOUG_LIB_EXPORT uint16_t foug_uint16_bswap(uint16_t val); -FOUG_LIB_EXPORT uint16_t foug_decode_uint16_le(const uint8_t* bytes); -FOUG_LIB_EXPORT uint16_t foug_decode_uint16_be(const uint8_t* bytes); -FOUG_LIB_EXPORT void foug_encode_uint16_le(uint16_t val, uint8_t* bytes); - -FOUG_LIB_EXPORT uint32_t foug_uint32_bswap(uint32_t val); -FOUG_LIB_EXPORT uint32_t foug_decode_uint32_le(const uint8_t* bytes); -FOUG_LIB_EXPORT uint32_t foug_decode_uint32_me(const uint8_t* bytes); -FOUG_LIB_EXPORT uint32_t foug_decode_uint32_be(const uint8_t* bytes); -FOUG_LIB_EXPORT void foug_encode_uint32_le(uint32_t val, uint8_t* bytes); -FOUG_LIB_EXPORT void foug_encode_uint32_be(uint32_t val, uint8_t* bytes); - -FOUG_LIB_EXPORT foug_real32_t foug_decode_real32_le(const uint8_t* bytes); -FOUG_LIB_EXPORT foug_real32_t foug_decode_real32_me(const uint8_t* bytes); -FOUG_LIB_EXPORT foug_real32_t foug_decode_real32_be(const uint8_t* bytes); -FOUG_LIB_EXPORT void foug_encode_real32_le(foug_real32_t val, uint8_t* bytes); - #endif /* FOUG_ENDIAN_H */ diff --git a/src/global.h b/src/global.h index 41da2b1..26aa5e1 100644 --- a/src/global.h +++ b/src/global.h @@ -20,7 +20,10 @@ # define FOUG_LIB_EXPORT #endif /* FOUG_LIB_DLL */ -#include "config.h" /* Generated by build system */ +/* "config.h" is generated by cmake, it should reside in the out-of-source build dir. + * In CMakeFiles.txt, the directory where resides "config.h" is added to the include path list + */ +#include "config.h" #ifdef FOUG_HAVE_STDINT_H # include @@ -48,4 +51,14 @@ typedef int8_t foug_bool_t; typedef float foug_real32_t; typedef double foug_real64_t; +#ifndef FOUG_INLINE +# if defined(__GNUC__) +# define FOUG_INLINE __inline__ /* Compatible with C90 */ +# elif defined(_MSC_VER) +# define FOUG_INLINE __inline +# else +# define FOUG_INLINE +# endif +#endif /* !FOUG_INLINE */ + #endif /* FOUG_C_GLOBAL_H */ diff --git a/src/internal/byte_codec.h b/src/internal/byte_codec.h new file mode 100644 index 0000000..86adf3c --- /dev/null +++ b/src/internal/byte_codec.h @@ -0,0 +1,68 @@ +/* Warning : this header has no multi-inclusion guard. It must be included only once in the + * translation unit of use. The reason is that all functions defined here are meant to + * be inlined for performance purpose + */ + +#include "../global.h" + +/*! Read a 16bit integer from memory-location \p bytes (little-endian byte order) */ +FOUG_INLINE static uint16_t foug_decode_uint16_le(const uint8_t* bytes) +{ + /* |0 |1 | */ + /* |BB|AA| -> 0xAABB */ + return (bytes[1] << 8) | bytes[0]; +} + +/*! Read a 16bit integer from memory-location \p bytes (big-endian byte order) */ +FOUG_INLINE static uint16_t foug_decode_uint16_be(const uint8_t* bytes) +{ + /* |0 |1 | */ + /* |AA|BB| -> 0xAABB */ + return (bytes[0] << 8) | bytes[1]; +} + +/*! Write 16bit integer \p val to the memory location at \p bytes in little-endian byte order */ +FOUG_INLINE static void foug_encode_uint16_le(uint16_t val, uint8_t* bytes) +{ + bytes[0] = val & 0xFF; + bytes[1] = (val >> 8) & 0xFF; +} + +/*! Read a 32bit integer from memory-location \p bytes (little-endian byte order) */ +FOUG_INLINE static uint32_t foug_decode_uint32_le(const uint8_t* bytes) +{ + /* |DD|CC|BB|AA| -> 0xAABBCCDD */ + return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); +} + +/*! Read a 32bit integer from memory-location \p bytes (mixed-endian byte order) */ +FOUG_INLINE static uint32_t foug_decode_uint32_me(const uint8_t* bytes) +{ + /* |DD|CC|BB|AA| -> 0xCCDDAABB */ + return (bytes[0] >> 8) | (bytes[2] << 8) | (bytes[3] << 8) | (bytes[1] << 8); +} + +/*! Read a 32bit integer from memory-location \p bytes (big-endian byte order) */ +FOUG_INLINE static uint32_t foug_decode_uint32_be(const uint8_t* bytes) +{ + /* |DD|CC|BB|AA| -> 0xDDCCBBAA */ + return bytes[3] | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24); +} + +/*! Write 32bit integer \p val to the memory location at \p bytes in little-endian byte order */ +FOUG_INLINE static void foug_encode_uint32_le(uint32_t val, uint8_t* bytes) +{ + bytes[0] = val & 0xFF; + bytes[1] = (val >> 8) & 0xFF; + bytes[2] = (val >> 16) & 0xFF; + bytes[3] = (val >> 24) & 0xFF; +} + +/*! Write 32bit integer \p val to the memory location at \p bytes in big-endian byte order */ +FOUG_INLINE static void foug_encode_uint32_be(uint32_t val, uint8_t* bytes) +{ + bytes[0] = (val >> 24) & 0xFF; + bytes[1] = (val >> 16) & 0xFF; + bytes[2] = (val >> 8) & 0xFF; + bytes[3] = val & 0xFF; +} diff --git a/src/internal/byte_swap.h b/src/internal/byte_swap.h new file mode 100644 index 0000000..61aced9 --- /dev/null +++ b/src/internal/byte_swap.h @@ -0,0 +1,38 @@ +/* Warning : this header has no multi-inclusion guard. It must be included only once in the + * translation unit of use. The reason is that all functions defined here are meant to + * be inlined for performance purpose + */ + +#include "../global.h" + +#ifdef FOUG_HAVE_MSVC_BUILTIN_BSWAP_FUNC +# include +#endif + +/*! Returns \p val with the order of bytes reversed, uses compiler builtin functions if available */ +FOUG_INLINE static uint16_t foug_uint16_bswap(uint16_t val) +{ +#ifdef FOUG_HAVE_GCC_BUILTIN_BSWAP_FUNC + return __builtin_bswap16(val); +#elif defined(FOUG_HAVE_MSVC_BUILTIN_BSWAP_FUNC) + return _byteswap_ushort(val); +#else + return ((val & 0x00FF) << 8) | ((val >> 8) & 0x00FF); +#endif +} + +/*! Returns \p val with the order of bytes reversed, uses compiler builtin functions if available */ +FOUG_INLINE static uint32_t foug_uint32_bswap(uint32_t val) +{ +#ifdef FOUG_HAVE_GCC_BUILTIN_BSWAP_FUNC + return __builtin_bswap32(val); +#elif defined(FOUG_HAVE_MSVC_BUILTIN_BSWAP_FUNC) + return _byteswap_ulong(val); +#else + return + ((val & 0x000000FF) << 24) + | ((val & 0x0000FF00) << 8) + | ((val >> 8) & 0x0000FF00) + | ((val >> 24) & 0x000000FF); +#endif +} diff --git a/src/internal/convert.c b/src/internal/convert.c index 12b6ae1..f549e3a 100644 --- a/src/internal/convert.c +++ b/src/internal/convert.c @@ -1,21 +1,15 @@ #include "convert.h" -typedef union -{ - uint32_t as_integer; - foug_real32_t as_float; -} _internal_foug_int_real_32_convert_t; - foug_real32_t foug_convert_real32(uint32_t val) { - _internal_foug_int_real_32_convert_t conv; - conv.as_integer = val; + foug_uint32_float_t conv; + conv.as_uint32 = val; return conv.as_float; } uint32_t foug_convert_uint32(foug_real32_t val) { - _internal_foug_int_real_32_convert_t conv; + foug_uint32_float_t conv; conv.as_float = val; - return conv.as_integer; + return conv.as_uint32; } diff --git a/src/internal/convert.h b/src/internal/convert.h index 035916a..95516a3 100644 --- a/src/internal/convert.h +++ b/src/internal/convert.h @@ -1,9 +1,15 @@ -#ifndef FOUG_CONVERT_H -#define FOUG_CONVERT_H +#ifndef FOUG_INTERNAL_CONVERT_H +#define FOUG_INTERNAL_CONVERT_H #include "../global.h" +typedef union +{ + uint32_t as_uint32; + float as_float; +} foug_uint32_float_t; + foug_real32_t foug_convert_real32(uint32_t val); uint32_t foug_convert_uint32(foug_real32_t val); -#endif /* FOUG_CONVERT_H */ +#endif /* FOUG_INTERNAL_CONVERT_H */ diff --git a/src/internal/libstl/stlb_byte_swap.c b/src/internal/libstl/stlb_byte_swap.c new file mode 100644 index 0000000..5cb9e7c --- /dev/null +++ b/src/internal/libstl/stlb_byte_swap.c @@ -0,0 +1,14 @@ +#include "stlb_byte_swap.h" + +#include "../byte_swap.h" + +void foug_stlb_triangle_bswap(foug_stlb_triangle_t* triangle) +{ + int i; + uint32_t* uintcoord_ptr = (uint32_t*)&(triangle->data.normal.x); + + for (i = 0; i < 12; ++i) + *(uintcoord_ptr + i) = foug_uint32_bswap(*(uintcoord_ptr + i)); + if (triangle->attribute_byte_count != 0) + triangle->attribute_byte_count = foug_uint16_bswap(triangle->attribute_byte_count); +} diff --git a/src/internal/libstl/stlb_byte_swap.h b/src/internal/libstl/stlb_byte_swap.h new file mode 100644 index 0000000..943e94d --- /dev/null +++ b/src/internal/libstl/stlb_byte_swap.h @@ -0,0 +1,9 @@ +#ifndef FOUG_INTERNAL_STLB_ENDIAN_H +#define FOUG_INTERNAL_STLB_ENDIAN_H + +#include "../../global.h" +#include "../../libstl/stlb_triangle.h" + +void foug_stlb_triangle_bswap(foug_stlb_triangle_t* triangle); + +#endif /* FOUG_INTERNAL_STLB_ENDIAN_H */ diff --git a/src/internal/libstl/stlb_rw_common.c b/src/internal/libstl/stlb_rw_common.c new file mode 100644 index 0000000..78bbf45 --- /dev/null +++ b/src/internal/libstl/stlb_rw_common.c @@ -0,0 +1,19 @@ +#include "stlb_rw_common.h" + +#include "../../error.h" +#include "../../libstl/stl_error.h" + +int foug_stlb_check_params(const foug_transfer_t *trsf, + foug_endianness_t byte_order) +{ + if (trsf == NULL) + return FOUG_DATAX_NULL_TRANSFER_ERROR; + if (trsf->buffer == NULL) + return FOUG_DATAX_NULL_BUFFER_ERROR; + if (trsf->buffer_size < FOUG_STLB_MIN_CONTENTS_SIZE) + return FOUG_DATAX_INVALID_BUFFER_SIZE_ERROR; + if (byte_order != FOUG_LITTLE_ENDIAN && byte_order != FOUG_BIG_ENDIAN) + return FOUG_STLB_READWRITE_UNSUPPORTED_BYTE_ORDER; + + return FOUG_DATAX_NO_ERROR; +} diff --git a/src/internal/libstl/stlb_rw_common.h b/src/internal/libstl/stlb_rw_common.h new file mode 100644 index 0000000..0ab8275 --- /dev/null +++ b/src/internal/libstl/stlb_rw_common.h @@ -0,0 +1,19 @@ +#ifndef FOUG_INTERNAL_STLB_RW_COMMON_H +#define FOUG_INTERNAL_STLB_RW_COMMON_H + +#include "../../global.h" +#include "../../endian.h" +#include "../../transfer.h" +#include "../../libstl/stlb_triangle.h" + +typedef struct +{ + uint32_t facet_count; + uint32_t i_facet_offset; + void (*fix_endian_func)(foug_stlb_triangle_t*); +} foug_readwrite_helper; + +int foug_stlb_check_params(const foug_transfer_t* trsf, + foug_endianness_t byte_order); + +#endif /* FOUG_INTERNAL_STLB_RW_COMMON_H */ diff --git a/src/libstl/stla_read.c b/src/libstl/stla_read.c index d3249af..c68b9d2 100644 --- a/src/libstl/stla_read.c +++ b/src/libstl/stla_read.c @@ -1,7 +1,8 @@ #include "stla_read.h" -#include "../error.h" #include "../internal/ascii_parse.h" +#include "../error.h" +#include "stl_error.h" #include #include @@ -101,26 +102,27 @@ static void foug_stream_fwd_iterator_stla_read_hook(void* cookie, } } -foug_bool_t parsing_can_continue(const foug_stla_parse_data_t* data) +FOUG_INLINE static foug_bool_t parsing_can_continue(const foug_stla_parse_data_t* data) { if (data->error || data->stream_iterator_cookie.is_stop_requested) return 0; return 1; } -static const char* current_token_as_identifier(const foug_stla_parse_data_t* data) +FOUG_INLINE static const char* current_token_as_identifier(const foug_stla_parse_data_t* data) { return data->token == ID_token ? data->string_buffer.ptr : ""; } -static int get_current_token_as_real32(const foug_stla_parse_data_t* data, foug_real32_t* value_ptr) +FOUG_INLINE static int get_current_token_as_real32(const foug_stla_parse_data_t* data, + foug_real32_t* value_ptr) { if (data->token == FLOAT_token) return foug_get_real32(data->string_buffer.ptr, value_ptr); return -3; } -static void parsing_error(foug_stla_parse_data_t* data) +FOUG_INLINE static void parsing_error(foug_stla_parse_data_t* data) { data->error = 1; data->token = unknown_token; diff --git a/src/libstl/stla_write.c b/src/libstl/stla_write.c index 4218de5..c5bdb93 100644 --- a/src/libstl/stla_write.c +++ b/src/libstl/stla_write.c @@ -1,6 +1,7 @@ #include "stla_write.h" #include "../error.h" +#include "stl_error.h" #include #include diff --git a/src/libstl/stlb_read.c b/src/libstl/stlb_read.c index a9936c2..09508c1 100644 --- a/src/libstl/stlb_read.c +++ b/src/libstl/stlb_read.c @@ -2,24 +2,17 @@ #include "../endian.h" #include "../error.h" +#include "stl_error.h" + #include "../internal/convert.h" +#include "../internal/byte_swap.h" +#include "../internal/libstl/stlb_byte_swap.h" +#include "../internal/libstl/stlb_rw_common.h" #include -typedef struct -{ - foug_endianness_t host_endianness; - foug_endianness_t stream_endianness; -} _internal_foug_endianness_info_t; - -typedef struct -{ - uint32_t facet_count; - uint32_t i_facet_offset; - _internal_foug_endianness_info_t endian_info; -} _internal_foug_read_params_helper; - -static void read_triangle_memcpy(const uint8_t* buffer, foug_stlb_triangle_t* triangle) +FOUG_INLINE static void read_triangle_memcpy(const uint8_t* buffer, + foug_stlb_triangle_t* triangle) { /* *triangle = *((foug_stlb_triangle_t*)(buffer)); */ memcpy(triangle, buffer, FOUG_STLB_TRIANGLE_RAWSIZE); @@ -41,10 +34,10 @@ static void read_triangle_alignsafe(const uint8_t* buffer, foug_stlb_triangle_t* static void foug_stlb_read_facets(foug_stlb_geom_input_t* geom, const uint8_t* buffer, - const _internal_foug_read_params_helper* params) + const foug_readwrite_helper* rparams) { - const uint32_t facet_count = params->facet_count; - const uint32_t i_facet_offset = params->i_facet_offset; + const uint32_t facet_count = rparams->facet_count; + const uint32_t i_facet_offset = rparams->i_facet_offset; foug_stlb_triangle_t triangle; uint32_t buffer_offset; uint32_t i_facet; @@ -62,6 +55,9 @@ static void foug_stlb_read_facets(foug_stlb_geom_input_t* geom, #endif buffer_offset += FOUG_STLB_TRIANGLE_RAWSIZE; + if (rparams->fix_endian_func != NULL) + rparams->fix_endian_func(&triangle); + /* Declare triangle */ geom->process_triangle_func(geom->cookie, i_facet_offset + i_facet, @@ -74,22 +70,20 @@ int foug_stlb_read(foug_stlb_geom_input_t* geom, foug_transfer_t* trsf, foug_endianness_t byte_order) { - _internal_foug_read_params_helper read_params; + const foug_endianness_t host_byte_order = foug_host_endianness(); + foug_readwrite_helper rparams; uint32_t total_facet_count = 0; /* Count of facets as declared in the stream */ int error = FOUG_DATAX_NO_ERROR; /* Helper variable to store function result error code */ /* Check validity of input parameters */ - if (trsf->buffer == NULL) - return FOUG_DATAX_NULL_BUFFER_ERROR; - if (trsf->buffer_size < FOUG_STLB_MIN_CONTENTS_SIZE) - return FOUG_DATAX_INVALID_BUFFER_SIZE_ERROR; - if (byte_order != FOUG_LITTLE_ENDIAN) - return FOUG_STLB_READ_UNSUPPORTED_BYTE_ORDER; + error = foug_stlb_check_params(trsf, byte_order); + if (foug_datax_error(error)) + return error; - /* Initialize read_params */ - memset(&read_params, 0, sizeof(_internal_foug_read_params_helper)); - read_params.endian_info.host_endianness = foug_host_endianness(); - read_params.endian_info.stream_endianness = byte_order; + /* Initialize rparams */ + memset(&rparams, 0, sizeof(foug_readwrite_helper)); + if (host_byte_order != byte_order) + rparams.fix_endian_func = foug_stlb_triangle_bswap; /* Read header */ { @@ -107,21 +101,23 @@ int foug_stlb_read(foug_stlb_geom_input_t* geom, if (foug_stream_read(&trsf->stream, trsf->buffer, sizeof(uint32_t), 1) != 1) return FOUG_STLB_READ_FACET_COUNT_ERROR; - total_facet_count = foug_decode_uint32_le(trsf->buffer); + memcpy(&total_facet_count, trsf->buffer, sizeof(uint32_t)); + if (host_byte_order != byte_order) + total_facet_count = foug_uint32_bswap(total_facet_count); if (geom != NULL && geom->begin_triangles_func != NULL) geom->begin_triangles_func(geom->cookie, total_facet_count); /* Read triangles */ while (foug_datax_no_error(error) - && read_params.i_facet_offset < total_facet_count) + && rparams.i_facet_offset < total_facet_count) { - read_params.facet_count = foug_stream_read(&trsf->stream, + rparams.facet_count = foug_stream_read(&trsf->stream, trsf->buffer, FOUG_STLB_TRIANGLE_RAWSIZE, trsf->buffer_size / FOUG_STLB_TRIANGLE_RAWSIZE); if (foug_stream_error(&trsf->stream) != 0) error = FOUG_DATAX_STREAM_ERROR; - else if (read_params.facet_count > 0) + else if (rparams.facet_count > 0) error = FOUG_DATAX_NO_ERROR; else break; /* Exit if no facet to read */ @@ -129,9 +125,9 @@ int foug_stlb_read(foug_stlb_geom_input_t* geom, if (foug_datax_no_error(error)) { uint8_t progress_pc; - foug_stlb_read_facets(geom, trsf->buffer, &read_params); - read_params.i_facet_offset += read_params.facet_count; - progress_pc = foug_percentage(0, total_facet_count, read_params.i_facet_offset); + foug_stlb_read_facets(geom, trsf->buffer, &rparams); + rparams.i_facet_offset += rparams.facet_count; + progress_pc = foug_percentage(0, total_facet_count, rparams.i_facet_offset); if (!foug_task_control_handle_progress(&trsf->task_control, progress_pc)) error = FOUG_DATAX_TASK_STOPPED_ERROR; } @@ -143,7 +139,7 @@ int foug_stlb_read(foug_stlb_geom_input_t* geom, geom->end_triangles_func(geom->cookie); } - if (foug_datax_no_error(error) && read_params.i_facet_offset != total_facet_count) + if (foug_datax_no_error(error) && rparams.i_facet_offset != total_facet_count) error = FOUG_STLB_READ_FACET_COUNT_ERROR; return error; } diff --git a/src/libstl/stlb_write.c b/src/libstl/stlb_write.c index fd4323d..0895ac3 100644 --- a/src/libstl/stlb_write.c +++ b/src/libstl/stlb_write.c @@ -2,9 +2,16 @@ #include "../endian.h" #include "../error.h" +#include "stl_error.h" + +#include "../internal/byte_codec.h" +#include "../internal/libstl/stlb_byte_swap.h" +#include "../internal/libstl/stlb_rw_common.h" + #include -static void write_triangle_memcpy(const foug_stlb_triangle_t* triangle, uint8_t* buffer) +FOUG_INLINE static void write_triangle_memcpy(const foug_stlb_triangle_t* triangle, + uint8_t* buffer) { memcpy(buffer, triangle, FOUG_STLB_TRIANGLE_RAWSIZE); } @@ -25,9 +32,10 @@ static void write_triangle_alignsafe(const foug_stlb_triangle_t* triangle, uint8 static void foug_stlb_write_facets(const foug_stlb_geom_output_t* geom, uint8_t* buffer, - uint32_t ifacet_start, - uint32_t facet_count) + const foug_readwrite_helper* wparams) { + const uint32_t facet_count = wparams->facet_count; + const uint32_t i_facet_offset = wparams->i_facet_offset; foug_stlb_triangle_t triangle; uint32_t buffer_offset; uint32_t i_facet; @@ -37,10 +45,13 @@ static void foug_stlb_write_facets(const foug_stlb_geom_output_t* geom, triangle.attribute_byte_count = 0; buffer_offset = 0; - for (i_facet = ifacet_start; i_facet < (ifacet_start + facet_count); ++i_facet) { + for (i_facet = i_facet_offset; i_facet < (i_facet_offset + facet_count); ++i_facet) { geom->get_triangle_func(geom->cookie, i_facet, &triangle.data); if (geom->get_attr_byte_count_func != NULL) - geom->get_attr_byte_count_func(geom->cookie, &triangle.attribute_byte_count); + geom->get_attr_byte_count_func(geom->cookie, i_facet, &triangle.attribute_byte_count); + + if (wparams->fix_endian_func != NULL) + wparams->fix_endian_func(&triangle); #ifdef FOUG_STLB_READWRITE_ALIGNSAFE write_triangle_alignsafe(&triangle, buffer + buffer_offset); @@ -56,20 +67,23 @@ int foug_stlb_write(const foug_stlb_geom_output_t* geom, foug_transfer_t* trsf, foug_endianness_t byte_order) { + foug_readwrite_helper wparams; const uint32_t facet_count = geom != NULL ? geom->triangle_count : 0; - uint32_t i_facet; - uint32_t buffer_facet_count; - uint32_t ifacet_start; - int error; + uint32_t i_facet = 0; + int error = FOUG_DATAX_NO_ERROR; - if (trsf->buffer == NULL) - return FOUG_DATAX_NULL_BUFFER_ERROR; - if (trsf->buffer_size < FOUG_STLB_MIN_CONTENTS_SIZE) - return FOUG_DATAX_INVALID_BUFFER_SIZE_ERROR; + /* Check validity of input parameters */ + error = foug_stlb_check_params(trsf, byte_order); + if (foug_datax_error(error)) + return error; if (geom == NULL || geom->get_triangle_func == NULL) return FOUG_STLB_WRITE_NULL_GET_TRIANGLE_FUNC; - if (byte_order != FOUG_LITTLE_ENDIAN/* && byte_order != FOUG_BIG_ENDIAN*/) - return FOUG_STLB_WRITE_UNSUPPORTED_BYTE_ORDER; + + /* Initialize wparams */ + memset(&wparams, 0, sizeof(foug_readwrite_helper)); + if (foug_host_endianness() != byte_order) + wparams.fix_endian_func = foug_stlb_triangle_bswap; + wparams.facet_count = trsf->buffer_size / FOUG_STLB_TRIANGLE_RAWSIZE; /* Write header */ { @@ -95,23 +109,20 @@ int foug_stlb_write(const foug_stlb_geom_output_t* geom, return FOUG_DATAX_STREAM_ERROR; /* Write triangles */ - error = FOUG_DATAX_NO_ERROR; - - buffer_facet_count = trsf->buffer_size / FOUG_STLB_TRIANGLE_RAWSIZE; - ifacet_start = 0; for (i_facet = 0; i_facet < facet_count && foug_datax_no_error(error); - i_facet += buffer_facet_count) + i_facet += wparams.facet_count) { /* Write to buffer */ - if (buffer_facet_count > (facet_count - ifacet_start)) - buffer_facet_count = facet_count - ifacet_start; - foug_stlb_write_facets(geom, trsf->buffer, ifacet_start, buffer_facet_count); - ifacet_start += buffer_facet_count; + if (wparams.facet_count > (facet_count - wparams.i_facet_offset)) + wparams.facet_count = facet_count - wparams.i_facet_offset; + + foug_stlb_write_facets(geom, trsf->buffer, &wparams); + wparams.i_facet_offset += wparams.facet_count; /* Write buffer to stream */ - if (foug_stream_write(&trsf->stream, trsf->buffer, FOUG_STLB_TRIANGLE_RAWSIZE, buffer_facet_count) - != buffer_facet_count) + if (foug_stream_write(&trsf->stream, trsf->buffer, FOUG_STLB_TRIANGLE_RAWSIZE, wparams.facet_count) + != wparams.facet_count) { error = FOUG_DATAX_STREAM_ERROR; }