JunkBox_Lib  1.10.2
bvh_tool.c
Go to the documentation of this file.
1 
7 #include "xtools.h"
8 #include "bvh_tool.h"
9 
10 
12 // Basic Function of BVHData
13 //
14 
15 BVHData* new_BVHData(void)
16 {
17  BVHData* bvh = NULL;
18 
19  bvh = (BVHData*)malloc(sizeof(BVHData));
20  if (bvh==NULL) return NULL;
21 
22  init_BVHData(bvh);
23 
24  return bvh;
25 }
26 
27 
28 void del_BVHData(BVHData** bvh)
29 {
30  if (bvh==NULL || *bvh==NULL) return;
31 
32  clear_BVHData(*bvh);
33  free(*bvh);
34 
35  *bvh = NULL;
36  return;
37 }
38 
39 
40 void init_BVHData(BVHData* bvh)
41 {
42  if (bvh==NULL) return;
43 
44  memset(bvh, 0, sizeof(BVHData));
45  bvh->state = JBXL_NORMAL;
46 
47  return;
48 }
49 
50 
51 void clear_BVHData(BVHData* bvh)
52 {
53  if (bvh==NULL) return;
54 
55  if (bvh->hierarchy!=NULL) {
56  del_tTree(&bvh->hierarchy);
57  bvh->hierarchy = NULL;
58  }
59  if (bvh->motion!=NULL) {
60  free(bvh->motion);
61  bvh->motion = NULL;
62  }
63  if (bvh->offset!=NULL) {
64  free(bvh->offset);
65  bvh->offset = NULL;
66  }
67 
68  init_BVHData(bvh);
69 
70  return;
71 }
72 
73 
74 
76 // Tiny Tools
77 //
78 
88 {
89  char* pp;
90  UNUSED(pp);
91 
92  if (fp==NULL) return NULL;
93 
94  char line[LBUF+1];
95  line[LBUF] = '\0';
96 
97  pp = fgets(line, LBUF, fp);
98  char* pack = pack_char(line, ' ');
99  if (pack==NULL) return NULL;
100  //
101  replace_str(pack, LBUF, " :", ":");
102  //replace_str(pack, LBUF, " {", "\n{\n");
103  //replace_str(pack, LBUF, " }", "\n}\n");
104 
105  tList* list = awk_tList(pack, ' ');
106  free(pack);
107 
108  return list;
109 }
110 
111 
121 tList* bvh_find_line(FILE* fp, const char* key)
122 {
123  if (fp==NULL || key==NULL) return NULL;
124 
125  tList* list = bvh_get_seq_data(fp);
126 
127  while (!feof(fp)) {
128  if (!strcasecmp((char*)list->ldat.key.buf, key)) return list;
129 
130  del_tList(&list);
131  list = bvh_get_seq_data(fp);
132  }
133 
134  return NULL;
135 }
136 
137 
139 {
140  int cnt = 0;
141 
142  if (pp==NULL) return 0;
143  while(pp->esis!=NULL) pp = pp->esis;
144 
145  do {
146  cnt += pp->ldat.lv;
147  if (pp->next!=NULL) cnt += bvh_count_channels(pp->next);
148  pp = pp->ysis;
149  } while(pp!=NULL);
150 
151  return cnt;
152 }
153 
154 
156 {
157  int cnt = 0;
158 
159  if (pp==NULL) return 0;
160  while(pp->esis!=NULL) pp = pp->esis;
161 
162  do {
163  cnt++;
164  if (pp->next!=NULL) cnt += bvh_count_joints(pp->next);
165  pp = pp->ysis;
166  } while(pp!=NULL);
167 
168  return cnt;
169 }
170 
171 
180 void bvh_get_offset(tTree* pp, vector** vect)
181 {
182  if (pp==NULL) return;
183 
184  while(pp->esis!=NULL) pp = pp->esis;
185 
186  do {
187  if (*vect!=NULL) {
188  **vect = *(vector*)pp->ldat.ptr;
189  (*vect)++;
190  }
191 
192  if (pp->next!=NULL) bvh_get_offset(pp->next, vect);
193  pp = pp->ysis;
194  } while(pp!=NULL);
195 
196  return;
197 }
198 
199 
205 void bvh_get_parameter(BVHData* bvh)
206 {
207  if (bvh==NULL || bvh->hierarchy==NULL) return;
208 
209  bvh->joint_num = 0;
210  bvh->channels = 0;
211 
212  _bvh_recsv_get_parameter(bvh->hierarchy, bvh);
213 }
214 
215 
216 void _bvh_recsv_get_parameter(tTree* pp, BVHData* bvh)
217 {
218  if (pp==NULL) return;
219 
220  while(pp->esis!=NULL) pp = pp->esis;
221 
222  do {
223  bvh->channels += pp->ldat.lv;
224  bvh->joint_num++;
225 
226  if (pp->next!=NULL) _bvh_recsv_get_parameter(pp->next, bvh);
227  pp = pp->ysis;
228  } while(pp!=NULL);
229 
230  return;
231 }
232 
233 
234 void _bvh_space_format(FILE* fp, int depth)
235 {
236  int i;
237 
238  for (i=0; i<depth;i++) fprintf(fp, " ");
239 }
240 
241 
242 
244 // BVH FILE I/O
245 //
246 
251 BVHData* bvh_read_file(const char* fn)
252 {
253  BVHData* bvh = NULL;
254 
255  FILE* fp = fopen(fn, "r");
256  if (fp==NULL) return NULL;
257 
258  bvh = bvh_parse_data(fp);
259  fclose(fp);
260 
261  return bvh;
262 }
263 
264 
274 int bvh_write_file(const char* fn, BVHData* bvh)
275 {
276  if (fn==NULL || bvh==NULL) return JBXL_ARGS_ERROR;
277  if (bvh->hierarchy==NULL || bvh->motion==NULL || bvh->state<0) return JBXL_ARGS_ERROR;
278 
279  FILE* fp = fopen(fn, "w");
280  if (fp==NULL) return JBXL_FILE_OPEN_ERROR;
281 
282  int ret = bvh_print_data(fp, bvh);
283  fclose(fp);
284 
285  return ret;
286 }
287 
288 
289 int bvh_print_data(FILE* fp, BVHData* bvh)
290 {
291  if (bvh==NULL || bvh->hierarchy==NULL || bvh->motion==NULL) return JBXL_ARGS_ERROR;
292  if (fp==NULL) return JBXL_FILE_OPEN_ERROR;
293 
294  int ret = JBXL_BVH_HIERARCHY_ERROR;
295 
296  int hrt = bvh_print_hierarchy(fp, bvh);
297  if (hrt>=0) {
298  ret = JBXL_BVH_MOTION_ERROR;
299  int mrt = bvh_print_motion(fp, bvh);
300  if (mrt>=0) ret = 0;
301  }
302 
303  return ret;
304 }
305 
306 
307 int bvh_print_hierarchy(FILE* fp, BVHData* bvh)
308 {
309  if (fp==NULL || bvh==NULL || bvh->hierarchy==NULL) return JBXL_ARGS_ERROR;
310 
311  fprintf(fp, "%s\n", BVH_STR_HIERARCHY);
312 
313  int ret = _bvh_recsv_print_hierarchy(fp, bvh->hierarchy);
314  fflush(fp);
315 
316  return ret;
317 }
318 
319 
320 int _bvh_recsv_print_hierarchy(FILE* fp, tTree* tree)
321 {
322  if (tree!=NULL) {
323  while(tree->esis!=NULL) tree = tree->esis;
324  do {
325  int i;
326  tList_data ld = tree->ldat;
327 
329  if (ld.id==BVH_NODE_ROOT || ld.id==BVH_NODE_JOINT || ld.id==BVH_NODE_END) {
330  _bvh_space_format(fp, tree->depth-1);
331 
332  if (ld.id==BVH_NODE_ROOT) fprintf(fp, "%s", BVH_STR_ROOT);
333  else if (ld.id==BVH_NODE_JOINT) fprintf(fp, "%s", BVH_STR_JOINT);
334  else fprintf(fp, "%s", BVH_STR_END);
335 
336  // NAME
337  if (ld.key.buf!=NULL) fprintf(fp, " %s", ld.key.buf);
338  fprintf(fp, "\n");
339  _bvh_space_format(fp, tree->depth-1);
340  fprintf(fp, "{\n");
341 
342  // OFFSET
343  _bvh_space_format(fp, tree->depth);
344  fprintf(fp, "%s", BVH_STR_OFFSET);
345  vector* vect = (vector*)ld.ptr;
346  if (vect!=NULL) {
347  fprintf(fp, " %f %f %f\n", vect->x, vect->y, vect->z);
348  }
349  else {
350  fprintf(fp, " %f %f %f\n", 0.0, 0.0, 0.0);
351  }
352 
353  // CHANNELS
354  if (ld.lv>0 && ld.val.buf!=NULL) {
355  _bvh_space_format(fp, tree->depth);
356  fprintf(fp, "%s %d", BVH_STR_CHANNELS, ld.lv);
357  for (i=0; i<ld.lv*2; i+=2) {
358  if (ld.val.buf[i]=='P') {
359  if (ld.val.buf[i+1]=='X') fprintf(fp, " %s", BVH_STR_PX);
360  else if (ld.val.buf[i+1]=='Y') fprintf(fp, " %s", BVH_STR_PY);
361  else if (ld.val.buf[i+1]=='Z') fprintf(fp, " %s", BVH_STR_PZ);
362  }
363  else if (ld.val.buf[i]=='R') {
364  if (ld.val.buf[i+1]=='X') fprintf(fp, " %s", BVH_STR_RX);
365  else if (ld.val.buf[i+1]=='Y') fprintf(fp, " %s", BVH_STR_RY);
366  else if (ld.val.buf[i+1]=='Z') fprintf(fp, " %s", BVH_STR_RZ);
367  }
368  }
369  fprintf(fp, "\n");
370  }
371  }
372 
373  //
374  if (tree->next!=NULL) {
375  _bvh_recsv_print_hierarchy(fp, tree->next);
376  }
377 
378  _bvh_space_format(fp, tree->depth-1);
379  fprintf(fp, "}\n");
380 
381  tree = tree->ysis;
382  } while(tree!=NULL);
383  }
384 
385  return 0;
386 }
387 
388 
389 int bvh_print_motion(FILE* fp, BVHData* bvh)
390 {
391  if (fp==NULL || bvh==NULL || bvh->motion==NULL) return JBXL_ARGS_ERROR;
392 
393  fprintf(fp, "%s\n", BVH_STR_MOTION);
394  fprintf(fp, "%s %d\n", BVH_STR_FRAMES, bvh->frame_num);
395  fprintf(fp, "%s %f\n", BVH_STR_FRAME_TIME, bvh->frame_time);
396 
397  int i, j;
398 
399  for (j=0; j<bvh->frame_num; j++) {
400  int jpos = j*bvh->channels;
401  for (i=0; i<bvh->channels; i++) {
402  fprintf(fp, "%f ", bvh->motion[jpos+i]);
403  }
404  fprintf(fp, "\n");
405  }
406 
407  fflush(fp);
408 
409  return 0;
410 }
411 
412 
413 
415 // BVH Parser
416 //
417 
418 BVHData* bvh_parse_data(FILE* fp)
419 {
420  BVHData* bvh = NULL;
421  tList* list = NULL;
422 
423  if (fp==NULL) return NULL;
424 
425  // Search HIERARCHY
426  list = bvh_find_line(fp, BVH_STR_HIERARCHY);
427  if (list==NULL) return bvh;
428  del_tList(&list);
429 
430  // HIERARCHY
431  bvh = new_BVHData();
432  if (bvh==NULL) return NULL;
433  bvh->state = JBXL_ERROR;
434 
435  bvh->hierarchy = bvh_parse_hierarchy(NULL, fp);
436  if (bvh->hierarchy==NULL) {
437  del_BVHData(&bvh);
438  return NULL;
439  }
440 
441  //bvh->joint_num = bvh_count_joints(bvh->hierarchy);
442  //bvh->channels = bvh_count_channels(bvh->hierarchy);
443  bvh_get_parameter(bvh);
444 
445  // OFFSET
446  bvh->offset = (vector*)malloc(sizeof(vector)*bvh->joint_num);
447  if (bvh->offset!=NULL) {
448  memset(bvh->offset, 0, sizeof(vector)*bvh->joint_num);
449  vector* vect = bvh->offset;
450  bvh_get_offset(bvh->hierarchy, &vect);
451  }
452 
453  // search MOTION
454  list = bvh_find_line(fp, BVH_STR_MOTION);
455  if (list==NULL) return bvh;
456  del_tList(&list);
457 
458  list = bvh_find_line(fp, BVH_STR_FRAMES);
459  if (list==NULL || list->next==NULL) return bvh;
460  bvh->frame_num = atoi((char*)list->next->ldat.key.buf);
461  del_tList(&list);
462 
463  list = bvh_find_line(fp, BVH_STR_FRAME);
464  if (list==NULL || list->next==NULL || list->next->next==NULL) return bvh;
465  if (strcasecmp(BVH_STR_TIME, (char*)list->next->ldat.key.buf)) return bvh;
466  bvh->frame_time = atof((char*)list->next->next->ldat.key.buf);
467  if (bvh->frame_time!=0.0) bvh->framepsec = (int)(1./bvh->frame_time);
468  else bvh->framepsec = 30;
469  del_tList(&list);
470 
471  // MOTION
472  bvh_parse_motion(bvh, fp);
473  if (bvh->frame_num>0) bvh->state = JBXL_NORMAL;
474 
475  return bvh;
476 }
477 
478 
479 //
480 void bvh_parse_motion(BVHData* bvh, FILE* fp)
481 {
482  if (bvh==NULL || fp==NULL) return;
483  if (bvh->channels<=0 || bvh->frame_num<=0) return;
484 
485  unsigned long int len = bvh->channels*bvh->frame_num*sizeof(double);
486  bvh->motion = (double*)malloc(len);
487  if (bvh->motion==NULL) return;
488  memset(bvh->motion, 0, len);
489 
490  //
491  tList* list = bvh_get_seq_data(fp);
492 
493  int j = 0;
494  while (!feof(fp) && list!=NULL) {
495  if (list->ldat.key.buf==NULL) {
496  del_tList(&list);
497  break;
498  }
499 
500  int jptr = j*bvh->channels;
501  tList* lt = list;
502 
503  int i = 0;
504  while (i<bvh->channels && lt!=NULL) {
505  bvh->motion[jptr+i] = atof((char*)lt->ldat.key.buf);
506  lt = lt->next;
507  i++;
508  }
509  j++;
510 
511  del_tList(&list);
512  list = bvh_get_seq_data(fp);
513  }
514 
515  bvh->frame_num = j;
516 
517  return;
518 }
519 
520 
521 //
522 tTree* bvh_parse_hierarchy(tTree* tree, FILE* fp)
523 {
524  int endf = FALSE;
525  tTree* next = NULL;
526  //
527  tList* list = bvh_get_seq_data(fp);
528 
529  while (list!=NULL) {
530  //
531  char* cmp = (char*)list->ldat.key.buf;
532  if (cmp!=NULL) {
533  //
534  // ROOT
535  if (!strcasecmp(cmp, BVH_STR_ROOT)) {
536  endf = TRUE;
537  if (list->next==NULL) {
538  next = add_tTree_node_bystr(tree, BVH_NODE_ROOT, 0, "", NULL, NULL, 0);
539  if (tree==NULL) tree = next;
540  }
541  else {
542  next = add_tTree_node_bystr(tree, BVH_NODE_ROOT, 0, (char*)list->next->ldat.key.buf, NULL, NULL, 0);
543  if (tree==NULL) tree = next;
544  }
545  }
546 
547  //
548  // JOINT
549  else if (!strcasecmp(cmp, BVH_STR_JOINT)) {
550  if (list->next==NULL) {
551  next = add_tTree_node_bystr(tree, BVH_NODE_JOINT, 0, "", NULL, NULL, 0);
552  if (tree==NULL) tree = next;
553  }
554  else {
555  next = add_tTree_node_bystr(tree, BVH_NODE_JOINT, 0, (char*)list->next->ldat.key.buf, NULL, NULL, 0);
556  if (tree==NULL) tree = next;
557  }
558  }
559 
560  //
561  // END
562  else if (!strcasecmp(cmp, BVH_STR_END)) {
563  if (list->next==NULL) {
564  next = add_tTree_node_bystr(tree, BVH_NODE_END, 0, "", NULL, NULL, 0);
565  }
566  else {
567  next = add_tTree_node_bystr(tree, BVH_NODE_END, 0, (char*)list->next->ldat.key.buf, NULL, NULL, 0);
568  }
569  }
570 
571  //
572  // OFFSET
573  else if (!strcasecmp(cmp, BVH_STR_OFFSET)) {
574  //
575  tList* lt = list;
576 
577  vector* vect = (vector*)malloc(sizeof(vector));
578  memset(vect, 0, sizeof(vector));
579  //
580  if (lt->next!=NULL) {
581  lt = lt->next;
582  vect->x = atof((char*)lt->ldat.key.buf);
583  }
584  if (lt->next!=NULL) {
585  lt = lt->next;
586  vect->y = atof((char*)lt->ldat.key.buf);
587  }
588  if (lt->next!=NULL) {
589  lt = lt->next;
590  vect->z = atof((char*)lt->ldat.key.buf);
591  }
592 
593  if (tree!=NULL) {
594  tree->ldat.ptr = (void*)vect;
595  tree->ldat.sz = sizeof(vector);
596  }
597  }
598 
599  //
600  // CHANNELS
601  else if (!strcasecmp(cmp, BVH_STR_CHANNELS)) {
602  //
603  int i, num = 0;
604  tList* lt = list;
605 
606  if (lt->next!=NULL) {
607  lt = lt->next;
608  num = atoi((char*)lt->ldat.key.buf);
609  }
610  if (tree!=NULL) tree->ldat.lv = num;
611 
612  //
613  if (num>0) {
614  Buffer channel = make_Buffer(13); // strlen("PXPYPZRXRYRZ") + 1
615 
616  for (i=0; i<num; i++) {
617  if (lt->next!=NULL) {
618  lt = lt->next;
619  if (!strcasecmp((char*)lt->ldat.key.buf, BVH_STR_PX)) {
620  cat_s2Buffer("PX", &channel);
621  }
622  else if (!strcasecmp((char*)lt->ldat.key.buf, BVH_STR_PY)) {
623  cat_s2Buffer("PY", &channel);
624  }
625  else if (!strcasecmp((char*)lt->ldat.key.buf, BVH_STR_PZ)) {
626  cat_s2Buffer("PZ", &channel);
627  }
628  else if (!strcasecmp((char*)lt->ldat.key.buf, BVH_STR_RX)) {
629  cat_s2Buffer("RX", &channel);
630  }
631  else if (!strcasecmp((char*)lt->ldat.key.buf, BVH_STR_RY)) {
632  cat_s2Buffer("RY", &channel);
633  }
634  else if (!strcasecmp((char*)lt->ldat.key.buf, BVH_STR_RZ)) {
635  cat_s2Buffer("RZ", &channel);
636  }
637  }
638  }
639 
640  if (tree!=NULL) tree->ldat.val = channel;
641  }
642  }
643 
644  //
645  else if (!strcmp(cmp, "{")) {
646  if (next!=NULL) {
647  bvh_parse_hierarchy(next, fp);
648  if (endf) {
649  del_tList(&list);
650  return tree;
651  }
652  }
653  }
654 
655  //
656  else if (!strcmp(cmp, "}")) {
657  del_tList(&list);
658  return tree;
659  }
660  }
661 
662  del_tList(&list);
663  list = bvh_get_seq_data(fp);
664  }
665 
666  return tree;
667 }
668 
Buffer make_Buffer(int sz)
Buffer型変数のバッファ部をつくり出す.
Definition: buffer.c:71
#define cat_s2Buffer(src, dst)
cat_b2Buffer()
Definition: buffer.h:122
void bvh_get_parameter(BVHData *bvh)
Definition: bvh_tool.c:205
int bvh_count_channels(tTree *pp)
Definition: bvh_tool.c:138
BVHData * new_BVHData(void)
Definition: bvh_tool.c:15
void bvh_parse_motion(BVHData *bvh, FILE *fp)
Definition: bvh_tool.c:480
tTree * bvh_parse_hierarchy(tTree *tree, FILE *fp)
Definition: bvh_tool.c:522
tList * bvh_get_seq_data(FILE *fp)
Definition: bvh_tool.c:87
BVHData * bvh_read_file(const char *fn)
Definition: bvh_tool.c:251
int bvh_count_joints(tTree *pp)
Definition: bvh_tool.c:155
void clear_BVHData(BVHData *bvh)
Definition: bvh_tool.c:51
int bvh_print_hierarchy(FILE *fp, BVHData *bvh)
Definition: bvh_tool.c:307
int bvh_print_data(FILE *fp, BVHData *bvh)
Definition: bvh_tool.c:289
void bvh_get_offset(tTree *pp, vector **vect)
Definition: bvh_tool.c:180
BVHData * bvh_parse_data(FILE *fp)
Definition: bvh_tool.c:418
tList * bvh_find_line(FILE *fp, const char *key)
Definition: bvh_tool.c:121
void del_BVHData(BVHData **bvh)
Definition: bvh_tool.c:28
void init_BVHData(BVHData *bvh)
Definition: bvh_tool.c:40
int _bvh_recsv_print_hierarchy(FILE *fp, tTree *tree)
Definition: bvh_tool.c:320
int bvh_write_file(const char *fn, BVHData *bvh)
Definition: bvh_tool.c:274
int bvh_print_motion(FILE *fp, BVHData *bvh)
Definition: bvh_tool.c:389
void _bvh_space_format(FILE *fp, int depth)
Definition: bvh_tool.c:234
void _bvh_recsv_get_parameter(tTree *pp, BVHData *bvh)
Definition: bvh_tool.c:216
BVHツールプログラム ヘッダ
#define BVH_STR_TIME
Definition: bvh_tool.h:31
#define BVH_NODE_END
Definition: bvh_tool.h:17
#define BVH_STR_OFFSET
Definition: bvh_tool.h:26
#define BVH_STR_ROOT
Definition: bvh_tool.h:22
#define BVH_STR_RX
Definition: bvh_tool.h:37
#define BVH_NODE_JOINT
Definition: bvh_tool.h:16
#define BVH_STR_END
Definition: bvh_tool.h:24
#define BVH_STR_RY
Definition: bvh_tool.h:38
#define BVH_STR_PX
Definition: bvh_tool.h:34
#define BVH_STR_FRAME_TIME
Definition: bvh_tool.h:33
#define BVH_STR_MOTION
Definition: bvh_tool.h:20
#define BVH_STR_JOINT
Definition: bvh_tool.h:23
#define BVH_STR_HIERARCHY
Definition: bvh_tool.h:19
#define BVH_STR_FRAME
Definition: bvh_tool.h:30
#define BVH_STR_RZ
Definition: bvh_tool.h:39
#define BVH_NODE_ROOT
Definition: bvh_tool.h:15
#define BVH_STR_PZ
Definition: bvh_tool.h:36
#define BVH_STR_PY
Definition: bvh_tool.h:35
#define BVH_STR_CHANNELS
Definition: bvh_tool.h:27
#define BVH_STR_FRAMES
Definition: bvh_tool.h:29
#define UNUSED(x)
Definition: common.h:264
#define LBUF
Definition: common.h:146
#define TRUE
Definition: common.h:226
#define FALSE
Definition: common.h:223
void line(WSGraph vp, int x1, int y1, int x2, int y2, int cc)
Definition: graph.c:462
#define JBXL_ERROR
エラー
Definition: jbxl_state.h:34
#define JBXL_ARGS_ERROR
不正な引数(NULLなど)
Definition: jbxl_state.h:42
#define JBXL_BVH_MOTION_ERROR
MOTIONデータの書き込み失敗
Definition: jbxl_state.h:145
#define JBXL_NORMAL
正常
Definition: jbxl_state.h:32
#define JBXL_FILE_OPEN_ERROR
ファイルオープン エラー
Definition: jbxl_state.h:44
#define JBXL_BVH_HIERARCHY_ERROR
HIERARCHYデータの書き込み失敗
Definition: jbxl_state.h:144
unsigned char unsigned long * len
Definition: jpeg_tool.h:96
Definition: buffer.h:35
Definition: matrix.h:29
double z
z方向成分
Definition: matrix.h:32
double y
y方向成分
Definition: matrix.h:31
double x
x方向成分
Definition: matrix.h:30
tList * awk_tList(char *str, char cc)
文字列を区切り文字で区切って,各項目をリストのキー部に入れて返す.
Definition: tlist.c:1805
tList * del_tList(tList **pp)
指定したリストノード以降のリストを削除.
Definition: tlist.c:735
char * replace_str(char *buf, int len, const char *frm, const char *tos)
文字列 buf中の frmを tosに書き換えたものを返す.free() してはいけない.
Definition: tools.c:1282
#define pack_char(s, c)
pack_char_len()
Definition: tools.h:236
tTree * del_tTree(tTree **pp)
指定したノード以下のツリーを削除する.
Definition: ttree.c:628
tTree * add_tTree_node_bystr(tTree *pp, int id, int lv, const char *key, const char *val, void *ptr, int sz)
ノードを末っ子としてリストに追加.
Definition: ttree.c:202
汎用拡張ツールヘッダ