#include "comment.h" #include "list.h" #include "xmalloc.h" #include "utf8_encode.h" #include "utf8_decode.h" #include #include #include #include extern char *program_name; extern const char *charset; static void comment_free(struct comment *comment) { free(comment->key); free(comment->utf8_val); free(comment->val); free(comment); } void comments_free(struct list_head *comment_head) { struct list_head *item, *next; item = comment_head->next; while (item != comment_head) { next = item->next; comment_free(list_entry(item, struct comment, node)); item = next; } } void comments_remove(struct list_head *comment_head, const struct list_head *delete_head) { struct list_head *ditem, *item; list_for_each(ditem, delete_head) { struct comment *dcomment; dcomment = list_entry(ditem, struct comment, node); item = comment_head->next; while (item != comment_head) { struct list_head *next = item->next; struct comment *comment; comment = list_entry(item, struct comment, node); if (strcasecmp(dcomment->key, comment->key) == 0) { list_del(&comment->node); comment_free(comment); } item = next; } } } /* remove all but the last comment with same key */ void comments_uniq(struct list_head *comment_head) { struct list_head *litem, *ritem; litem = comment_head->next; while (litem != comment_head) { struct list_head *lnext = litem->next; struct comment *lcomment; lcomment = list_entry(litem, struct comment, node); ritem = lnext; while (ritem != comment_head) { struct comment *rcomment; rcomment = list_entry(ritem, struct comment, node); if (strcasecmp(lcomment->key, rcomment->key) == 0) { /* remove litem */ list_del(&lcomment->node); comment_free(lcomment); break; } ritem = ritem->next; } litem = lnext; } } struct comment *comment_get(const struct list_head *comment_head, const char *name) { struct list_head *item; list_for_each(item, comment_head) { struct comment *comment; comment = list_entry(item, struct comment, node); if (strcasecmp(comment->key, name) == 0) return comment; } return NULL; } static void comment_add_full(struct list_head *comment_head, char *key, char *val, char *utf8_val) { struct comment *comment; struct list_head *item; int i; for (i = 0; key[i]; i++) key[i] = toupper(key[i]); comment = (struct comment *)xmalloc(sizeof(struct comment)); comment->key = key; comment->utf8_val = utf8_val; comment->val = val; /* keep comments alphabetically sorted by key */ item = comment_head->next; while (item != comment_head) { struct comment *c; int rc; c = list_entry(item, struct comment, node); rc = strcasecmp(key, c->key); if (rc < 0) break; if (rc == 0) { /* same key */ if (strcmp(utf8_val, c->utf8_val) == 0) { /* identical tags. don't add */ comment_free(comment); return; } /* new comments are added after old ones * actually thes 2 rows are not needed */ item = item->next; break; } item = item->next; } /* add before item */ list_add_tail(&comment->node, item); } void comment_add(struct list_head *comment_head, const char *key, const char *val) { char *utf8_val; if (utf8_encode(val, charset, &utf8_val)) { fprintf(stderr, "%s: error: can't convert `%s' to UTF8: %s\n", program_name, val, strerror(errno)); exit(1); } comment_add_full(comment_head, xstrdup(key), xstrdup(val), utf8_val); } void comment_add_utf8(struct list_head *comment_head, const char *key, const char *utf8_val) { char *val; if (utf8_decode(utf8_val, charset, &val)) { fprintf(stderr, "%s: error: can't convert `%s' to %s: %s\n", program_name, utf8_val, charset, strerror(errno)); exit(1); } comment_add_full(comment_head, xstrdup(key), val, xstrdup(utf8_val)); } void comment_add_any(struct list_head *comment_head, const char *key, const char *v, const char *v_charset) { char *utf8_val, *val; if (utf8_encode(v, v_charset, &utf8_val)) { fprintf(stderr, "%s: error: can't convert `%s' from %s to UTF8: %s\n", program_name, v, v_charset, strerror(errno)); exit(1); } if (utf8_decode(utf8_val, charset, &val)) { fprintf(stderr, "%s: error: can't convert `%s' to %s: %s\n", program_name, utf8_val, charset, strerror(errno)); exit(1); } comment_add_full(comment_head, xstrdup(key), val, utf8_val); } void comments_print(const struct list_head *comment_head) { struct list_head *item; list_for_each(item, comment_head) { struct comment *comment; comment = list_entry(item, struct comment, node); printf("%s=%s\n", comment->key, comment->val); } }