Last active
August 29, 2015 14:11
-
-
Save NickBeeuwsaert/995300d192d71ef5a7d4 to your computer and use it in GitHub Desktop.
C functions for reading data out of a binary function, similar to pythons struct module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // endian.h | |
| // | |
| // Created by Nick Beeuwsaert on 5/17/14. | |
| // Copyright (c) 2014 Nick Beeuwsaert. | |
| // MIT Licensed. | |
| // | |
| #ifndef __ENDIAN_H__ | |
| #define __ENDIAN_H__ | |
| #if defined(__linux__) || defined(__CYGWIN__) | |
| # include <endian.h> | |
| #elif defined(__APPLE__) | |
| #include <libkern/OSByteOrder.h> | |
| #define le16toh(x) OSSwapLittleToHostInt16(x) | |
| #define htole16(x) OSSwapHostToLittleInt16(x) | |
| #define be16toh(x) OSSwapBigToHostInt16(x) | |
| #define htobe16(x) OSSwapHostToBigInt16(x) | |
| #define le32toh(x) OSSwapLittleToHostInt32(x) | |
| #define htole32(x) OSSwapHostToLittleInt32(x) | |
| #define be32toh(x) OSSwapBigToHostInt32(x) | |
| #define htobe32(x) OSSwapHostToBigInt32(x) | |
| #define le64toh(x) OSSwapLittleToHostInt64(x) | |
| #define htole64(x) OSSwapHostToLittleInt64(x) | |
| #define be64toh(x) OSSwapBigToHostInt64(x) | |
| #define htobe64(x) OSSwapHostToBigInt64(x) | |
| #elif defined(__OpenBSD__) | |
| #include <sys/endian.h> | |
| #elif defined(_WIN32) || defined(__MINGW32__) | |
| #if BYTE_ORDER == BIG_ENDIAN | |
| //XBox 360 | |
| #define htobe16(x) (x) | |
| #define htole16(x) __builtin_bswap16(x) | |
| #define be16toh(x) (x) | |
| #define le16toh(x) __builtin_bswap16(x) | |
| #define htobe32(x) (x) | |
| #define htole32(x) __builtin_bswap32(x) | |
| #define be32toh(x) (x) | |
| #define le32toh(x) __builtin_bswap32(x) | |
| #define htobe64(x) (x) | |
| #define htole64(x) __builtin_bswap64(x) | |
| #define be64toh(x) (x) | |
| #define le64toh(x) __builtin_bswap64(x) | |
| #elif BYTE_ORDER == LITTLE_ENDIAN | |
| #define htobe16(x) htons(x) | |
| #define htole16(x) (x) | |
| #define be16toh(x) ntohs(x) | |
| #define le16toh(x) (x) | |
| #define htobe32(x) htonl(x) | |
| #define htole32(x) (x) | |
| #define be32toh(x) ntohl(x) | |
| #define le32toh(x) (x) | |
| #define htobe64(x) htonll(x) | |
| #define htole64(x) (x) | |
| #define be64toh(x) ntohll(x) | |
| #define le64toh(x) (x) | |
| #else | |
| #error bad byte order | |
| #endif | |
| #else | |
| #error platform not supported | |
| #endif | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Pack.cpp | |
| // | |
| // Created by Nick Beeuwsaert on 5/17/14. | |
| // Copyright (c) 2014 Nick Beeuwsaert. | |
| // MIT Licensed. | |
| // | |
| #include "Pack.h" | |
| #include <stdarg.h> | |
| #include <stdlib.h> | |
| #include <stdbool.h> | |
| #include <ctype.h> | |
| #include "endian.h" | |
| void unpack(FILE* f, const char *fmt, ...){ | |
| va_list ap; | |
| bool big_endian = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; | |
| va_start(ap, fmt); | |
| for(;*fmt != '\0'; fmt++){ | |
| unsigned long int length=1; | |
| if(isdigit(*fmt)){ | |
| length = strtoul(fmt, (char**)&fmt, 10); | |
| } | |
| switch(*fmt){ | |
| case '>': | |
| case '<': | |
| big_endian = *fmt=='>'; | |
| break; | |
| case 'I': | |
| case 'i': | |
| { | |
| uint32_t *data = va_arg(ap, uint32_t*); | |
| while(length-->0){ | |
| //file.read((char*)data, sizeof(uint32_t)); | |
| fread(data, sizeof(uint32_t), 1, f); | |
| *(data++) = big_endian?be32toh(*data):le32toh(*data); | |
| } | |
| }break; | |
| case 'H': | |
| case 'h': | |
| { | |
| uint16_t *data = va_arg(ap, uint16_t*); | |
| while(length-->0){ | |
| //file.read((char*)data, sizeof(uint16_t)); | |
| fread(data, sizeof(uint16_t), 1, f); | |
| *(data++) = big_endian?be16toh(*data):le16toh(*data); | |
| } | |
| }break; | |
| // B and c could probably be to same thing.... | |
| case 'B': | |
| case 'b': | |
| { | |
| uint8_t *str_bytes = va_arg(ap, uint8_t*); | |
| fread(str_bytes, sizeof(uint8_t), length, f); | |
| //file.read((char*)str_bytes, length); | |
| }break; | |
| case 'c':{ | |
| char *str = va_arg(ap, char*); | |
| fread(str, sizeof(char), length, f); | |
| //file.read(str, length); | |
| }break; | |
| case 'x': | |
| //file.seekg(length, file.cur); | |
| fseek(f, length, SEEK_CUR); | |
| continue; | |
| } | |
| } | |
| va_end(ap); | |
| } | |
| unsigned int calcsize(const char *fmt){ | |
| unsigned int size = 0; | |
| for(;*fmt != '\0'; fmt++){ | |
| unsigned long int length=1; | |
| if(isdigit(*fmt)){ | |
| length = strtoul(fmt, (char**)&fmt, 10); | |
| } | |
| switch(*fmt){ | |
| case 'I': | |
| case 'i': | |
| size += length * 4; | |
| break; | |
| case 'H': | |
| case 'h': | |
| size += length * 2; | |
| break; | |
| case 'B': | |
| case 'b': | |
| case 'c': | |
| case 'x': | |
| size += length; | |
| break; | |
| } | |
| } | |
| return size; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Pack.h | |
| // | |
| // Created by Nick Beeuwsaert on 5/17/14. | |
| // Copyright (c) 2014 Nick Beeuwsaert. | |
| // MIT Licensed. | |
| // | |
| #ifndef __PACK_H__ | |
| #define __PACK_H__ | |
| #include <stdio.h> | |
| /** | |
| * Unpacks the data from file into variables | |
| * Supposed to work similar to how python's struct works | |
| * > Means switch to Big Endian | |
| * < Means switch to Little Endian | |
| * H means read a short (uint16_t) | |
| * I means read a int (uint32_t) | |
| * B means read a byte | |
| * c means read a character | |
| * x means skip a byte | |
| * you can prefix a format character with a number to | |
| * mark how many of the following type to read | |
| * unlike pythons struct, the case of the letter doesn't matter | |
| * | |
| * @param file The file to read data from | |
| * @param format The format to use to read | |
| * @param ... Variables to write out to | |
| */ | |
| void unpack(FILE *, const char *, ...); | |
| /** | |
| * Calculates the size of the fmt passed | |
| * See unpack for fmt description | |
| * | |
| * @param fmt The format | |
| */ | |
| unsigned int calcsize(const char*); | |
| #endif /* __PACK_H__ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment