写个小工测试程序,希望可以命令行指定参数 转化成二进制数据,发送或写入设备:
需要一个类似 perl python lua 等脚本语言中的pack类似的函数,网上找了好久没找到-
找到lua的struct.pack代码修改一个C版本的,分享如下:
- /*
- ** {======================================================
- ** Library for packing/unpacking structures.
- ** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $
- ** See Copyright Notice at the end of this file
- ** =======================================================
- */
- /*
- ** Valid formats:
- ** > - big endian
- ** < - little endian
- ** ![num] - alignment
- ** b/B - signed/unsigned byte
- ** h/H - signed/unsigned short
- ** l/L - signed/unsigned long
- ** T - size_t
- ** xn - pading with size `n'
- ** i/In - signed/unsigned integer with size `n' (default is size of int)
- ** cn - sequence of `n' chars (from/to a string); when packing, n==0 means
- the whole string; when unpacking, n==0 means use the previous
- read number as the string length
- ** s - zero-terminated string
- ** f - float
- ** d - double
- ** ' ' - ignored
- */
- #include <assert.h>
- #include <ctype.h>
- #include <limits.h>
- #include <stddef.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- /* maximum size (in bytes) for integral types */
- #define MAXINTSIZE 32
- #define MAXLINTSIZE 64
- /* is 'x' a power of 2? */
- #define isp2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0)
- /* dummy structure to get alignment requirements */
- struct cD {
- char c;
- double d;
- };
- #define PADDING (sizeof(struct cD) - sizeof(double))
- #define MAXALIGN (PADDING > sizeof(int) ? PADDING : sizeof(int))
- /* endian options */
- #define BIG 0
- #define LITTLE 1
- static union {
- int dummy;
- char endian;
- } const native = {1};
- typedef struct Header {
- int endian;
- int align;
- } Header;
- static int getnum (const char **fmt, int df) {
- if (!isdigit(**fmt)) /* no number? */
- return df; /* return default value */
- else {
- int a = 0;
- do {
- a = a*10 + *((*fmt)++) - '0';
- } while (isdigit(**fmt));
- return a;
- }
- }
- #define defaultoptions(h) ((h)->endian = native.endian, (h)->align = 1)
- static size_t haveArg (char opt) {
- switch (opt) {
- case 'B': case 'b':
- case 'H': case 'h':
- case 'L': case 'l':
- case 'T':
- case 'f':
- case 'd':
- //case 'x':
- case 'c':
- case 'i': case 'I':
- return 1;
- default: return 0;
- }
- }
- static size_t optsize (char opt, const char **fmt) {
- switch (opt) {
- case 'B': case 'b': return sizeof(char);
- case 'H': case 'h': return sizeof(short);
- case 'L': case 'l': return sizeof(long);
- case 'T': return sizeof(size_t);
- case 'f': return sizeof(float);
- case 'd': return sizeof(double);
- case 'x': return getnum(fmt, 1);
- case 'c': return getnum(fmt, 1);
- case 'i': case 'I': {
- int sz = getnum(fmt, sizeof(int));
- #if 0
- if (sz > MAXINTSIZE)
- fprintf(stderr, "integral size %d is larger than limit of %d\n",
- sz, MAXINTSIZE);
- #endif
- return sz;
- }
- default: return 0; /* other cases do not need alignment */
- }
- }
- /*
- ** return number of bytes needed to align an element of size 'size'
- ** at current position 'len'
- */
- static int gettoalign (size_t len, Header *h, int opt, size_t size) {
- if (size == 0 || opt == 'c') return 0;
- if (size > (size_t)h->align)
- size = h->align; /* respect max. alignment */
- return (size - (len & (size - 1))) & (size - 1);
- }
- /*
- ** options to control endianess and alignment
- */
- static void controloptions (int opt, const char **fmt,
- Header *h) {
- switch (opt) {
- case ' ': return; /* ignore white spaces */
- case '>': h->endian = BIG; return;
- case '<': h->endian = LITTLE; return;
- case '!': {
- int a = getnum(fmt, MAXALIGN);
- if (!isp2(a))
- ;//fprintf(stderror, "alignment %d is not a power of 2\n", a);
- h->align = a;
- return;
- }
- default: {
- ;//fprintf(stderror, "invalid format option '%c'\n", opt);
- }
- }
- }
- static void correctbytes (char *b, int size, int endian) {
- if (endian != native.endian) {
- int i = 0;
- while (i < --size) {
- char temp = b[i];
- b[i++] = b[size];
- b[size] = temp;
- }
- }
- }
- static void strtoint(char *buff, char *strNum, int endian, int size)
- {
- unsigned long long value = strtoull(strNum, NULL, 0);
- if (endian == LITTLE) {
- int i;
- for (i = 0; i < size; i++) {
- buff[i] = (value & 0xff);
- value >>= 8;
- }
- }
- else {
- int i;
- for (i = size - 1; i >= 0; i--) {
- buff[i] = (value & 0xff);
- value >>= 8;
- }
- }
- }
- static int b_pack (char *b, int argc, char **argv) {
- char buff[MAXLINTSIZE];
- const char *fmt = argv[0];
- //printf("%s\n", fmt);
- size_t size = 0;
- Header h;
- int arg = 1;
- size_t totalsize = 0;
- size_t idx = 0;
- defaultoptions(&h);
- while (*fmt != '\0') {
- int opt = *fmt++;
- if (arg > argc - 1 && haveArg(opt))
- break;
- size = optsize(opt, &fmt);
- int toalign = gettoalign(totalsize, &h, opt, size);
- totalsize += toalign;
- while (toalign-- > 0) b[idx++] = '\0';
- //printf("idx == %zu, size == %zu\n", idx, size);
- switch (opt) {
- case 'b': case 'B': case 'h': case 'H':
- case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
- strtoint(buff, argv[arg++], h.endian, size);
- memcpy(&b[idx], buff, size);
- break;
- }
- case 'x': {
- memset(&b[idx], '\0', size);
- break;
- }
- case 'f': {
- float f = (float)strtof(argv[arg++], NULL);
- memcpy(&b[idx], &f, size);
- break;
- }
- case 'd': {
- double d = (float)strtod(argv[arg++], NULL);
- memcpy(&b[idx], &d, size);
- break;
- }
- case 'c': case 's': {
- size_t l;
- const char *s = argv[arg++];
- l = strlen(s);
- if (size == 0) size = l;
- memcpy(&b[idx], s, size);
- if (opt == 's') {
- b[idx+size] = '\0'; /* add zero at the end */
- size++;
- }
- break;
- }
- default: controloptions(opt, &fmt, &h);
- }
- idx += size;
- totalsize += size;
- }
- return totalsize;
- }
- #ifdef YPACK_TEST
- int main(int argc, char **argv)
- {
- char buf[512] = { 0 };
- size_t size = 0;
- size = b_pack(buf, argc-1, argv + 1);
- write(1, buf, size);
- return 0;
- }
- #endif
- /******************************************************************************
- * Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ******************************************************************************/
阅读(5917) | 评论(0) | 转发(1) |