Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1281195
  • 博文数量: 168
  • 博客积分: 3483
  • 博客等级: 中校
  • 技术积分: 1696
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-06 13:17
文章分类

全部博文(168)

文章存档

2015年(6)

2014年(9)

2013年(47)

2012年(11)

2011年(13)

2010年(18)

2009年(11)

2008年(42)

2007年(11)

分类: C/C++

2012-09-02 23:36:03

写个小工测试程序,希望可以命令行指定参数 转化成二进制数据,发送或写入设备:

需要一个类似 perl python lua 等脚本语言中的pack类似的函数,网上找了好久没找到-
找到lua的struct.pack代码修改一个C版本的,分享如下:

点击(此处)折叠或打开

  1. /*
  2. ** {======================================================
  3. ** Library for packing/unpacking structures.
  4. ** $Id: struct.c,v 1.4 2012/07/04 18:54:29 roberto Exp $
  5. ** See Copyright Notice at the end of this file
  6. ** =======================================================
  7. */
  8. /*
  9. ** Valid formats:
  10. ** > - big endian
  11. ** < - little endian
  12. ** ![num] - alignment
  13. ** b/B - signed/unsigned byte
  14. ** h/H - signed/unsigned short
  15. ** l/L - signed/unsigned long
  16. ** T - size_t
  17. ** xn - pading with size `n'
  18. ** i/In - signed/unsigned integer with size `n' (default is size of int)
  19. ** cn - sequence of `n' chars (from/to a string); when packing, n==0 means
  20.         the whole string; when unpacking, n==0 means use the previous
  21.         read number as the string length
  22. ** s - zero-terminated string
  23. ** f - float
  24. ** d - double
  25. ** ' ' - ignored
  26. */


  27. #include <assert.h>
  28. #include <ctype.h>
  29. #include <limits.h>
  30. #include <stddef.h>
  31. #include <string.h>

  32. #include <stdlib.h>
  33. #include <stdio.h>

  34. /* maximum size (in bytes) for integral types */
  35. #define MAXINTSIZE    32
  36. #define MAXLINTSIZE    64

  37. /* is 'x' a power of 2? */
  38. #define isp2(x)        ((x) > 0 && ((x) & ((x) - 1)) == 0)

  39. /* dummy structure to get alignment requirements */
  40. struct cD {
  41.   char c;
  42.   double d;
  43. };

  44. #define PADDING        (sizeof(struct cD) - sizeof(double))
  45. #define MAXALIGN     (PADDING > sizeof(int) ? PADDING : sizeof(int))

  46. /* endian options */
  47. #define BIG    0
  48. #define LITTLE    1

  49. static union {
  50.   int dummy;
  51.   char endian;
  52. } const native = {1};


  53. typedef struct Header {
  54.   int endian;
  55.   int align;
  56. } Header;


  57. static int getnum (const char **fmt, int df) {
  58.   if (!isdigit(**fmt)) /* no number? */
  59.     return df; /* return default value */
  60.   else {
  61.     int a = 0;
  62.     do {
  63.       a = a*10 + *((*fmt)++) - '0';
  64.     } while (isdigit(**fmt));
  65.     return a;
  66.   }
  67. }


  68. #define defaultoptions(h)    ((h)->endian = native.endian, (h)->align = 1)


  69. static size_t haveArg (char opt) {
  70.   switch (opt) {
  71.     case 'B': case 'b':
  72.     case 'H': case 'h':
  73.     case 'L': case 'l':
  74.     case 'T':
  75.     case 'f':
  76.     case 'd':
  77.     //case 'x':
  78.     case 'c':
  79.     case 'i': case 'I':
  80.       return 1;
  81.     default: return 0;
  82.   }
  83. }
  84. static size_t optsize (char opt, const char **fmt) {
  85.   switch (opt) {
  86.     case 'B': case 'b': return sizeof(char);
  87.     case 'H': case 'h': return sizeof(short);
  88.     case 'L': case 'l': return sizeof(long);
  89.     case 'T': return sizeof(size_t);
  90.     case 'f': return sizeof(float);
  91.     case 'd': return sizeof(double);
  92.     case 'x': return getnum(fmt, 1);
  93.     case 'c': return getnum(fmt, 1);
  94.     case 'i': case 'I': {
  95.       int sz = getnum(fmt, sizeof(int));
  96. #if 0
  97.       if (sz > MAXINTSIZE)
  98.         fprintf(stderr, "integral size %d is larger than limit of %d\n",
  99.                 sz, MAXINTSIZE);
  100. #endif
  101.       return sz;
  102.     }
  103.     default: return 0; /* other cases do not need alignment */
  104.   }
  105. }

  106. /*
  107. ** return number of bytes needed to align an element of size 'size'
  108. ** at current position 'len'
  109. */
  110. static int gettoalign (size_t len, Header *h, int opt, size_t size) {
  111.   if (size == 0 || opt == 'c') return 0;
  112.   if (size > (size_t)h->align)
  113.     size = h->align; /* respect max. alignment */
  114.   return (size - (len & (size - 1))) & (size - 1);
  115. }

  116. /*
  117. ** options to control endianess and alignment
  118. */
  119. static void controloptions (int opt, const char **fmt,
  120.                             Header *h) {
  121.   switch (opt) {
  122.     case ' ': return; /* ignore white spaces */
  123.     case '>': h->endian = BIG; return;
  124.     case '<': h->endian = LITTLE; return;
  125.     case '!': {
  126.       int a = getnum(fmt, MAXALIGN);
  127.       if (!isp2(a))
  128.         ;//fprintf(stderror, "alignment %d is not a power of 2\n", a);
  129.       h->align = a;
  130.       return;
  131.     }
  132.     default: {
  133.       ;//fprintf(stderror, "invalid format option '%c'\n", opt);
  134.     }
  135.   }
  136. }


  137. static void correctbytes (char *b, int size, int endian) {
  138.   if (endian != native.endian) {
  139.     int i = 0;
  140.     while (i < --size) {
  141.       char temp = b[i];
  142.       b[i++] = b[size];
  143.       b[size] = temp;
  144.     }
  145.   }
  146. }

  147. static void strtoint(char *buff, char *strNum, int endian, int size)
  148. {
  149.   unsigned long long value = strtoull(strNum, NULL, 0);

  150.   if (endian == LITTLE) {
  151.     int i;
  152.     for (i = 0; i < size; i++) {
  153.       buff[i] = (value & 0xff);
  154.       value >>= 8;
  155.     }
  156.   }
  157.   else {
  158.     int i;
  159.     for (i = size - 1; i >= 0; i--) {
  160.       buff[i] = (value & 0xff);
  161.       value >>= 8;
  162.     }
  163.   }
  164. }

  165. static int b_pack (char *b, int argc, char **argv) {
  166.   char buff[MAXLINTSIZE];
  167.   const char *fmt = argv[0];
  168.   //printf("%s\n", fmt);
  169.   size_t size = 0;
  170.   Header h;
  171.   int arg = 1;
  172.   size_t totalsize = 0;
  173.   size_t idx = 0;

  174.   defaultoptions(&h);
  175.   while (*fmt != '\0') {
  176.     int opt = *fmt++;
  177.     if (arg > argc - 1 && haveArg(opt))
  178.       break;
  179.     size = optsize(opt, &fmt);
  180.     int toalign = gettoalign(totalsize, &h, opt, size);
  181.     totalsize += toalign;
  182.     while (toalign-- > 0) b[idx++] = '\0';
  183.     //printf("idx == %zu, size == %zu\n", idx, size);
  184.     switch (opt) {
  185.       case 'b': case 'B': case 'h': case 'H':
  186.       case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
  187.         strtoint(buff, argv[arg++], h.endian, size);
  188.         memcpy(&b[idx], buff, size);
  189.         break;
  190.       }
  191.       case 'x': {
  192.         memset(&b[idx], '\0', size);
  193.         break;
  194.       }
  195.       case 'f': {
  196.         float f = (float)strtof(argv[arg++], NULL);
  197.         memcpy(&b[idx], &f, size);
  198.         break;
  199.       }
  200.       case 'd': {
  201.         double d = (float)strtod(argv[arg++], NULL);
  202.         memcpy(&b[idx], &d, size);
  203.         break;
  204.       }
  205.       case 'c': case 's': {
  206.         size_t l;
  207.         const char *s = argv[arg++];
  208.         l = strlen(s);
  209.         if (size == 0) size = l;
  210.         memcpy(&b[idx], s, size);
  211.         if (opt == 's') {
  212.           b[idx+size] = '\0'; /* add zero at the end */
  213.           size++;
  214.         }
  215.         break;
  216.       }
  217.       default: controloptions(opt, &fmt, &h);
  218.     }
  219.     idx += size;
  220.     totalsize += size;
  221.   }
  222.   return totalsize;
  223. }

  224. #ifdef YPACK_TEST
  225. int main(int argc, char **argv)
  226. {
  227.   char buf[512] = { 0 };
  228.   size_t size = 0;

  229.   size = b_pack(buf, argc-1, argv + 1);
  230.   write(1, buf, size);
  231.   return 0;
  232. }
  233. #endif

  234. /******************************************************************************
  235. * Copyright (C) 2010-2012 Lua.org, PUC-Rio. All rights reserved.
  236. *
  237. * Permission is hereby granted, free of charge, to any person obtaining
  238. * a copy of this software and associated documentation files (the
  239. * "Software"), to deal in the Software without restriction, including
  240. * without limitation the rights to use, copy, modify, merge, publish,
  241. * distribute, sublicense, and/or sell copies of the Software, and to
  242. * permit persons to whom the Software is furnished to do so, subject to
  243. * the following conditions:
  244. *
  245. * The above copyright notice and this permission notice shall be
  246. * included in all copies or substantial portions of the Software.
  247. *
  248. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  249. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  250. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  251. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  252. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  253. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  254. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  255. ******************************************************************************/



阅读(5923) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~