#include #include #include #include #include #define SUBDIR "/items" static void recurse_catalog(TidyDoc doc, TidyNode tnod, const char *image_dir, struct icclient_catalog **catalog) { for (TidyNode child = tidyGetChild(tnod); child; child = tidyGetNext(child)) { ctmbstr name = tidyNodeGetName(child); if (!name) continue; if (strcmp(name, "img")) { recurse_catalog(doc, child, image_dir, catalog); continue; } char prefix[strlen(image_dir) + strlen(SUBDIR) + 1]; sprintf(prefix, "%s%s", image_dir, SUBDIR); size_t prefix_len = strlen(prefix); bool bail = false; for (TidyAttr attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr)) if (!strcmp(tidyAttrName(attr), "src") && strncmp(tidyAttrValue(attr), prefix, prefix_len)) { bail = true; break; } if (bail) continue; struct icclient_product *product = malloc(sizeof(struct icclient_product)); memset(product, '\0', sizeof(struct icclient_product)); for (TidyAttr attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr)) { name = tidyAttrName(attr); ctmbstr value = tidyAttrValue(attr); if (!strcmp(name, "src")) { size_t len = strlen(value) - prefix_len; product->image = malloc(len + 1); strncpy(product->image, value + prefix_len, len + 1); } else if (!strcmp(name, "alt")) { product->description = malloc(strlen(value) + 1); strcpy(product->description, value); } else if (!strcmp(name, "title")) { product->sku = malloc(strlen(value + 1)); strcpy(product->sku, value); } } (*catalog)->length++; *catalog = realloc(*catalog, sizeof(struct icclient_catalog) + sizeof(struct icclient_product *[(*catalog)->length])); (*catalog)->products[(*catalog)->length - 1] = product; } } struct icclient_catalog *catalog(const char *response, const char *image_dir) { TidyDoc tdoc = tidyCreate(); TidyBuffer output = {0}; tidyParseString(tdoc, response); tidySaveBuffer(tdoc, &output); struct icclient_catalog *catalog = malloc(sizeof(struct icclient_catalog)); catalog->length = 0; recurse_catalog(tdoc, tidyGetRoot(tdoc), image_dir, &catalog); tidyBufFree(&output); tidyRelease(tdoc); return catalog; }