📄 su_taglist.c
字号:
}/** Make a linear tag list. */tagi_t *tl_vllist(tag_type_t tag, tag_value_t value, va_list ap){ va_list aq; tagi_t *t, *rv; tagi_t const *next; tagi_t tagi[2]; int size; va_copy(aq, ap); size = tl_vllen(tag, value, aq); va_end(aq); t = rv = malloc(size); tagi[0].t_tag = tag; tagi[0].t_value = value; tagi[1].t_tag = tag_any; tagi[1].t_value = 0; for (;;) { next = tl_next(tagi); if (next != tagi + 1) break; if (tagi->t_tag != tag_skip) *t++ = *tagi; tagi->t_tag = va_arg(ap, tag_type_t); tagi->t_value = va_arg(ap, tag_value_t); } for (; next; next = tl_next(next)) *t++ = *next; t->t_tag = NULL; t->t_value = 0; t++; assert((char *)rv + size == (char *)t); return rv;}/** Make a linear tag list until TAG_END() */tagi_t *tl_llist(tag_type_t tag, tag_value_t value, ...){ va_list ap; tagi_t *t; va_start(ap, value); t = tl_vllist(tag, value, ap); va_end(ap); return t;}/** Free a tag list allocated by tl_list(), tl_llist() or tl_vlist(). */void tl_vfree(tagi_t *t){ if (t) free(t);}/** Convert a string to the a value of a tag. */int t_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value){ if (tt == NULL || s == NULL || return_value == NULL) return -1; if (tt->tt_class->tc_scan) { return tt->tt_class->tc_scan(tt, home, s, return_value); } else { *return_value = (tag_value_t)0; return 0; }}/* ====================================================================== *//* null tag */tagi_t const *t_null_next(tagi_t const *t){ return NULL;}tagi_t *t_null_move(tagi_t *dst, tagi_t const *src){ memset(dst, 0, sizeof(*dst)); return dst + 1;}tagi_t *t_null_dup(tagi_t *dst, tagi_t const *src, void **bb){ memset(dst, 0, sizeof(*dst)); return dst + 1;}tagi_t *t_null_copy(tagi_t *dst, tagi_t const *src, void **bb){ memset(dst, 0, sizeof(*dst)); return dst + 1;}tagi_t const * t_null_find(tag_type_t tt, tagi_t const lst[]){ return NULL;}tagi_t *t_null_filter(tagi_t *dst, tagi_t const filter[], tagi_t const *src, void **bb){ if (TAG_TYPE_OF(src) == tag_null) { if (dst) { dst->t_tag = NULL; dst->t_value = 0; } return dst + 1; } return dst;}tag_class_t null_tag_class[1] = {{ sizeof(null_tag_class), /* tc_next */ t_null_next, /* tc_len */ NULL, /* tc_move */ t_null_move, /* tc_xtra */ NULL, /* tc_dup */ t_null_dup, /* tc_free */ NULL, /* tc_find */ t_null_find, /* tc_snprintf */ NULL, /* tc_filter */ t_null_filter, /* tc_ref_set */ NULL, /* tc_scan */ NULL, }};tag_typedef_t tag_null = TAG_TYPEDEF(tag_null, null);/* ====================================================================== *//* end tag */tagi_t *t_end_filter(tagi_t *dst, tagi_t const filter[], tagi_t const *src, void **bb){ return dst;}tag_class_t end_tag_class[1] = {{ sizeof(end_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ NULL, /* tc_filter */ t_end_filter, /* tc_ref_set */ NULL, /* tc_scan */ NULL, }};/* ====================================================================== *//* skip tag - placeholder in tag list */tagi_t const *t_skip_next(tagi_t const *t){ return t + 1;}tagi_t *t_skip_move(tagi_t *dst, tagi_t const *src){ return dst;}size_t t_skip_len(tagi_t const *t){ return 0;}tagi_t *t_skip_dup(tagi_t *dst, tagi_t const *src, void **bb){ return dst;}tagi_t *t_skip_filter(tagi_t *dst, tagi_t const filter[], tagi_t const *src, void **bb){ return dst;}tag_class_t skip_tag_class[1] = {{ sizeof(skip_tag_class), /* tc_next */ t_skip_next, /* tc_len */ t_skip_len, /* tc_move */ t_skip_move, /* tc_xtra */ NULL, /* tc_dup */ t_skip_dup, /* tc_free */ NULL, /* tc_find */ t_null_find, /* tc_snprintf */ NULL, /* tc_filter */ t_skip_filter, /* tc_ref_set */ NULL, /* tc_scan */ NULL, }};tag_typedef_t tag_skip = TAG_TYPEDEF(tag_skip, skip);/* ====================================================================== *//* next tag - jump to next tag list */tagi_t const *t_next_next(tagi_t const *t){ return (tagi_t *)(t->t_value);}tagi_t *t_next_move(tagi_t *dst, tagi_t const *src){ if (!src->t_value) return t_null_move(dst, src); return dst;}size_t t_next_len(tagi_t const *t){ if (!t->t_value) return sizeof(*t); return 0;}tagi_t *t_next_dup(tagi_t *dst, tagi_t const *src, void **bb){ if (!src->t_value) return t_null_dup(dst, src, bb); return dst;}tagi_t *t_next_filter(tagi_t *dst, tagi_t const filter[], tagi_t const *src, void **bb){ return dst;}tag_class_t next_tag_class[1] = {{ sizeof(next_tag_class), /* tc_next */ t_next_next, /* tc_len */ t_next_len, /* tc_move */ t_next_move, /* tc_xtra */ NULL, /* tc_dup */ t_next_dup, /* tc_free */ NULL, /* tc_find */ t_null_find, /* tc_snprintf */ NULL, /* tc_filter */ t_next_filter, /* tc_ref_set */ NULL, /* tc_scan */ NULL, }};tag_typedef_t tag_next = TAG_TYPEDEF(tag_next, next);/* ====================================================================== *//* any tag - match to any tag when filtering */tagi_t *t_any_filter(tagi_t *dst, tagi_t const filter[], tagi_t const *src, void **bb){ if (!src) return dst; else if (dst) { return t_dup(dst, src, bb); } else { dst = (tagi_t *)((char *)dst + t_len(src)); *bb = (char *)*bb + t_xtra(src, (size_t)*bb); return dst; }} tag_class_t any_tag_class[1] = {{ sizeof(any_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ NULL, /* tc_filter */ t_any_filter, /* tc_ref_set */ NULL, /* tc_scan */ NULL, }};tag_typedef_t tag_any = TAG_TYPEDEF(tag_any, any);/* ====================================================================== *//* ns tag - match to any tag with same namespace when filtering */statictagi_t *t_ns_filter(tagi_t *dst, tagi_t const filter[], tagi_t const *src, void **bb){ char const *match, *ns; if (!src) return dst; assert(filter); match = TAG_TYPE_OF(filter)->tt_ns; ns = TAG_TYPE_OF(src)->tt_ns; if (match == NULL) /* everything matches with this */; else if (match == ns) /* namespaces matche */; else if (ns == NULL) /* no match */ return dst; else if (strcmp(match, ns)) /* no match */ return dst; if (dst) { return t_dup(dst, src, bb); } else { dst = (tagi_t *)((char *)dst + t_len(src)); *bb = (char *)*bb + t_xtra(src, (size_t)*bb); return dst; }} tag_class_t ns_tag_class[1] = {{ sizeof(any_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ NULL, /* tc_filter */ t_ns_filter, /* tc_ref_set */ NULL, /* tc_scan */ NULL, }};/* ====================================================================== *//* int tag - pass integer value */int t_int_snprintf(tagi_t const *t, char b[], size_t size){ return snprintf(b, size, "%i", (int)t->t_value);}int t_int_ref_set(tag_type_t tt, void *ref, tagi_t const value[]){ *(int *)ref = (int)value->t_value; return 1;}int t_int_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value){ int value; char *rest; value = strtol(s, &rest, 0); if (s != rest) { *return_value = (tag_value_t)value; return 1; } else { *return_value = (tag_value_t)0; return -1; }}tag_class_t int_tag_class[1] = {{ sizeof(int_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_int_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_int_ref_set, /* tc_scan */ t_int_scan, }};/* ====================================================================== *//* uint tag - pass unsigned integer value */int t_uint_snprintf(tagi_t const *t, char b[], size_t size){ return snprintf(b, size, "%u", (unsigned)t->t_value);}int t_uint_ref_set(tag_type_t tt, void *ref, tagi_t const value[]){ *(unsigned *)ref = (unsigned)value->t_value; return 1;}int t_uint_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value){ unsigned value; char *rest; value = strtoul(s, &rest, 0); if (s != rest) { *return_value = (tag_value_t)value; return 1; } else { *return_value = (tag_value_t)0; return -1; }}tag_class_t uint_tag_class[1] = {{ sizeof(int_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_uint_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_uint_ref_set, /* tc_scan */ t_uint_scan, }};/* ====================================================================== *//* bool tag - pass boolean value */int t_bool_snprintf(tagi_t const *t, char b[], size_t size){ return snprintf(b, size, "%s", t->t_value ? "true" : "false");}int t_bool_ref_set(tag_type_t tt, void *ref, tagi_t const value[]){ *(int *)ref = (value->t_value != 0); return 1;}int t_bool_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value){ int retval; int value = 0; if (strncasecmp(s, "true", 4) == 0 && strlen(s + 4) == strspn(s + 4, " \t\r\n")) { value = 1, retval = 1; } else if (strncasecmp(s, "false", 5) == 0 && strlen(s + 5) == strspn(s + 5, " \t\r\n")) { value = 0, retval = 1; } else { retval = t_int_scan(tt, home, s, return_value); value = *return_value != 0; } if (retval == 1) *return_value = (tag_value_t)value; else *return_value = (tag_value_t)0; return retval;}tag_class_t bool_tag_class[1] = {{ sizeof(bool_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_bool_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_bool_ref_set, /* tc_scan */ t_bool_scan, }};/* ====================================================================== *//* ptr tag - pass pointer value */int t_ptr_snprintf(tagi_t const *t, char b[], size_t size){ return snprintf(b, size, "%p", (void *)t->t_value);}int t_ptr_ref_set(tag_type_t tt, void *ref, tagi_t const value[]){ *(void **)ref = (void *)value->t_value; return 1;}/* This is not usually very safe, so it is not used */int t_ptr_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value){ int retval; void *ptr; retval = sscanf(s, "%p", &ptr); if (retval == 1) *return_value = (tag_value_t)ptr; else *return_value = (tag_value_t)NULL; return retval;}tag_class_t ptr_tag_class[1] = {{ sizeof(ptr_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_ptr_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ NULL, }};/* ====================================================================== *//* str tag - pass string value */int t_str_snprintf(tagi_t const *t, char b[], size_t size){ if (t->t_value) return snprintf(b, size, "\"%s\"", (char const *)t->t_value); else return snprintf(b, size, "<null>");}int t_str_scan(tag_type_t tt, su_home_t *home, char const *s, tag_value_t *return_value){ int retval; s = su_strdup(home, s); if (s) *return_value = (tag_value_t)s, retval = 1; else *return_value = (tag_value_t)NULL, retval = -1; return retval;}tagi_t *t_str_dup(tagi_t *dst, tagi_t const *src, void **bb){ dst->t_tag = src->t_tag; if (src->t_value) { char const *s = (char const *)src->t_value; int len = strlen(s) + 1; dst->t_value = (tag_value_t)strcpy(*bb, s); *bb = (char *)*bb + len; } else dst->t_value = (tag_value_t)0; return dst + 1;}size_t t_str_xtra(tagi_t const *t, size_t offset){ return t->t_value ? strlen((char *)t->t_value) + 1 : 0;}tag_class_t str_tag_class[1] = {{ sizeof(str_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ t_str_xtra, /* tc_dup */ t_str_dup, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_str_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ t_str_scan, }};/* ====================================================================== *//* cstr tag - pass constant string value (no need to dup) *//** Tag class for constant strings */tag_class_t cstr_tag_class[1] = {{ sizeof(cstr_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_str_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ t_str_scan, }};/* ====================================================================== *//* ref tag - pass reference */tag_class_t ref_tag_class[1] = {{ sizeof(ref_tag_class), /* tc_next */ NULL, /* tc_len */ NULL, /* tc_move */ NULL, /* tc_xtra */ NULL, /* tc_dup */ NULL, /* tc_free */ NULL, /* tc_find */ NULL, /* tc_snprintf */ t_ptr_snprintf, /* tc_filter */ NULL, /* tc_ref_set */ t_ptr_ref_set, /* tc_scan */ NULL, }};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -