dump.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include "pbc.h"
  6. static void
  7. read_file(const char *filename , struct pbc_slice *slice) {
  8. FILE *f = fopen(filename, "rb");
  9. if (f == NULL) {
  10. fprintf(stderr, "Can't open file %s\n", filename);
  11. exit(1);
  12. }
  13. fseek(f,0,SEEK_END);
  14. slice->len = ftell(f);
  15. fseek(f,0,SEEK_SET);
  16. slice->buffer = malloc(slice->len);
  17. fread(slice->buffer, 1 , slice->len , f);
  18. fclose(f);
  19. }
  20. static void
  21. dump_bytes(const char *data, size_t len) {
  22. size_t i;
  23. for (i = 0; i < len; i++)
  24. if (i == 0)
  25. fprintf(stdout, "%02x", 0xff & data[i]);
  26. else
  27. fprintf(stdout, " %02x", 0xff & data[i]);
  28. }
  29. static void dump_message(struct pbc_rmessage *m, int level);
  30. static void
  31. dump_value(struct pbc_rmessage *m, const char *key, int type, int idx, int level) {
  32. int i;
  33. for (i=0;i<level;i++) {
  34. printf(" ");
  35. }
  36. printf("%s",key);
  37. if (type & PBC_REPEATED) {
  38. printf("[%d]",idx);
  39. type -= PBC_REPEATED;
  40. }
  41. printf(": ");
  42. uint32_t low;
  43. uint32_t hi;
  44. double real;
  45. const char *str;
  46. int str_len;
  47. switch(type) {
  48. case PBC_INT:
  49. low = pbc_rmessage_integer(m, key, idx, NULL);
  50. printf("%d", (int) low);
  51. break;
  52. case PBC_REAL:
  53. real = pbc_rmessage_real(m, key , idx);
  54. printf("%lf", real);
  55. break;
  56. case PBC_BOOL:
  57. low = pbc_rmessage_integer(m, key, idx, NULL);
  58. printf("%s", low ? "true" : "false");
  59. break;
  60. case PBC_ENUM:
  61. str = pbc_rmessage_string(m, key , idx , NULL);
  62. printf("[%s]", str);
  63. break;
  64. case PBC_STRING:
  65. str = pbc_rmessage_string(m, key , idx , NULL);
  66. printf("'%s'", str);
  67. break;
  68. case PBC_MESSAGE:
  69. printf("\n");
  70. dump_message(pbc_rmessage_message(m, key, idx),level+1);
  71. return;
  72. case PBC_FIXED64:
  73. low = pbc_rmessage_integer(m, key, idx, &hi);
  74. printf("0x%8x%8x",hi,low);
  75. break;
  76. case PBC_FIXED32:
  77. low = pbc_rmessage_integer(m, key, idx, NULL);
  78. printf("0x%x",low);
  79. break;
  80. case PBC_BYTES:
  81. str = pbc_rmessage_string(m, key, idx, &str_len);
  82. dump_bytes(str, str_len);
  83. break;
  84. default:
  85. printf("unknown");
  86. break;
  87. }
  88. printf("\n");
  89. }
  90. static void
  91. dump_message(struct pbc_rmessage *m, int level) {
  92. int t = 0;
  93. const char *key = NULL;
  94. for (;;) {
  95. t = pbc_rmessage_next(m, &key);
  96. if (key == NULL)
  97. break;
  98. if (t & PBC_REPEATED) {
  99. int n = pbc_rmessage_size(m, key);
  100. int i;
  101. for (i=0;i<n;i++) {
  102. dump_value(m, key , t , i , level);
  103. }
  104. } else {
  105. dump_value(m, key , t , 0 , level);
  106. }
  107. }
  108. }
  109. static void
  110. dump(const char *proto, const char * message, struct pbc_slice *data) {
  111. struct pbc_env * env = pbc_new();
  112. struct pbc_slice pb;
  113. read_file(proto, &pb);
  114. int r = pbc_register(env, &pb);
  115. if (r!=0) {
  116. fprintf(stderr, "Can't register %s\n", proto);
  117. exit(1);
  118. }
  119. struct pbc_rmessage * m = pbc_rmessage_new(env , message , data);
  120. if (m == NULL) {
  121. fprintf(stderr, "Decoding message '%s' failed\n",message);
  122. exit(1);
  123. }
  124. dump_message(m,0);
  125. }
  126. static void
  127. push_byte(int byte, struct pbc_slice *data , int idx) {
  128. if (idx >= data->len) {
  129. data->len *= 2;
  130. data->buffer = realloc(data->buffer, data->len);
  131. }
  132. ((uint8_t *)data->buffer)[idx] = (uint8_t)byte;
  133. }
  134. static void
  135. read_stdin(int mode, struct pbc_slice *data) {
  136. data->len = 128;
  137. data->buffer = malloc(data->len);
  138. int idx = 0;
  139. while(!feof(stdin)) {
  140. int byte;
  141. int r = scanf("%d" , &byte);
  142. if (r == 0) {
  143. break;
  144. }
  145. push_byte(byte, data, idx);
  146. ++idx;
  147. }
  148. data->len = idx;
  149. }
  150. static void
  151. usage(const char *argv0) {
  152. printf(" -h help.\n"
  153. " -p <filename.pb> protobuf file\n"
  154. " -m <messagename>\n"
  155. " -d <datafile>\n"
  156. " -D input from stdin (DEC number)\n"
  157. );
  158. }
  159. int
  160. main(int argc , char * argv[])
  161. {
  162. int ch;
  163. const char * proto = NULL;
  164. const char * message = NULL;
  165. const char * datafile = NULL;
  166. int mode = 0;
  167. while ((ch = getopt(argc, argv, "hDp:m:d:")) != -1) {
  168. switch(ch) {
  169. case 'h':
  170. usage(argv[0]);
  171. return 0;
  172. case 'p':
  173. proto = optarg;
  174. break;
  175. case 'm':
  176. message = optarg;
  177. break;
  178. case 'd':
  179. datafile = optarg;
  180. break;
  181. case 'D':
  182. mode = 10;
  183. break;
  184. default:
  185. usage(argv[0]);
  186. return 1;
  187. }
  188. }
  189. if (proto == NULL || message == NULL) {
  190. usage(argv[0]);
  191. return 1;
  192. }
  193. struct pbc_slice data;
  194. if (datafile == NULL) {
  195. read_stdin(mode, &data);
  196. } else {
  197. read_file(datafile , &data);
  198. }
  199. dump(proto , message , &data);
  200. return 0;
  201. }