Skip to content

Instantly share code, notes, and snippets.

@asmuth
Last active December 16, 2015 17:19
Show Gist options
  • Save asmuth/5469371 to your computer and use it in GitHub Desktop.
Save asmuth/5469371 to your computer and use it in GitHub Desktop.
product listview rendering in c (WIP)
// This file is part of the "LoveOS" project
// (c) 2013 DaWanda GmbH, Paul Asmuth <paul@paulasmuth.com>, et al.
// All rights reserved.
#include "plv.h"
#include "ruby.h"
VALUE loveos_render = Qnil;
// glue code to call the plv_load_json + plv_render methods from ruby
VALUE method_render_product_listview_from_json(VALUE self, VALUE json, VALUE lang) {
VALUE res;
char* buf;
plv_data* plv;
if (rb_type(json) != RUBY_T_STRING) {
rb_raise(rb_eTypeError, "first argument (json) must be a string");
return 0;
}
if (rb_type(lang) != RUBY_T_STRING) {
rb_raise(rb_eTypeError, "second argument (lang) must be a string");
return 0;
}
plv = calloc(1, sizeof(plv_data));
if (!plv_load_json(plv, RSTRING_PTR(json), RSTRING_PTR(lang))) {
rb_raise(rb_eRuntimeError, "error loading product_listview JSON, invalid structure?");
free(plv);
return 1;
}
buf = plv_render(plv);
res = rb_str_new2(buf);
free(buf);
free(plv);
return res;
}
void Init_loveos_render() {
loveos_render = rb_define_module("NativeRender");
rb_define_method(loveos_render, "render_product_listview_from_json",
method_render_product_listview_from_json, 2);
}
// This file is part of the "LoveOS" project
// (c) 2013 DaWanda GmbH, Paul Asmuth <paul@paulasmuth.com>, et al.
// All rights reserved.
#include "plv.h"
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
#include <string.h>
// loads a product_listview json blob (from sqltap) into the plv struct
// returns 0 on error, 1 on success
int plv_load_json(plv_data* plv, char* json, char* lang) {
json_t *root, *product, *images, *image, *user, *shop, *translations;
json_error_t error;
if (!(root = json_loads(json, 0, &error)))
return PLV_LOAD_ERROR;
if (!json_is_object(root))
goto error;
if (!(product = json_object_get(root, "product")))
goto error;
if (!(user = json_object_get(product, "user")))
goto error;
if (!(shop = json_object_get(user, "shop")))
goto error;
if (!(images = json_object_get(product, "images")))
goto error;
if (!(translations = json_object_get(product, "translations")))
goto error;
if (!json_is_array(images))
goto error;
if (!json_is_array(translations))
goto error;
if (!(image = json_array_get(images, 0)))
goto error;
plv_load_json_attr(product, plv->id, "id");
plv_load_json_attr(product, plv->slug, "slug");
plv_load_json_attr(product, plv->cents, "cents");
plv_load_json_attr(image, plv->image_filename, "filename");
plv_load_json_attr(shop, plv->shop_name, "subdomain");
plv_load_json_attr(product, plv->price_unit, "unit");
plv_load_json_attr(product, plv->cents, "cents");
plv_load_json_attr(product, plv->currency, "currency");
plv_load_json_attr(product, plv->price_milli_units_per_item,
"milli_units_per_item");
plv_load_json_translations(plv, translations, lang);
json_decref(root);
return PLV_LOAD_SUCCESS;
error:
json_decref(root);
return PLV_LOAD_ERROR;
}
// it ain't pretty but its fast... remember to free the return value
// after use (!)
char* plv_render(plv_data* plv) {
size_t buf_size = sizeof(plv_data) + 4096;
char* buf = calloc(1, buf_size);
plv_prepare(plv);
// oh yeah, we can render the listview with one big printf ;)
snprintf(buf, buf_size, PLV_TEMPLATE,
plv->url,
plv->image_url,
plv->url,
plv->title,
plv->shop_name,
plv->shop_name,
plv->price_milli_units_per_item,
plv->price_unit,
plv->price / 100.0,
plv->currency
);
return buf;
}
void plv_prepare(plv_data* plv) {
char s3_folder_id_str[16] = "\0";
// prepare id and price
plv->id_int = atoi(plv->id);
plv->price = atoi(plv->cents);
// prepare product url
snprintf(plv->url, PLV_ATTR_SIZE, "/product/%s-%s",
plv->id, plv->slug);
// prepare image url
if ((plv->id_int / PLV_S3_MAX_ID + 1) > 1)
snprintf(s3_folder_id_str, 16, "%i", plv->id_int / PLV_S3_MAX_ID + 1);
snprintf(plv->image_url, PLV_ATTR_SIZE, "http://%s/Product%s/%i/%i/listview/%s",
PLV_S3_HOST,
s3_folder_id_str,
plv->id_int / 1000,
plv->id_int,
plv->image_filename
);
// prepare product title
}
void plv_render_string(char** buf, const char* str) {
strncpy(*buf, str, PLV_ATTR_SIZE);
*buf += strlen(str);
}
void plv_load_json_attr(json_t* base, char* dst, const char* attr) {
json_t* tmp = json_object_get(base, attr);
if (json_is_string(tmp))
strncpy(dst, json_string_value(tmp), PLV_ATTR_SIZE);
}
void plv_load_json_translations(plv_data* plv, json_t* translations, char* lang) {
json_t *translation, *tmp;
int n;
for (n = (int) json_array_size(translations); n > 0; n--) {
translation = json_array_get(translations, n - 1);
tmp = json_object_get(translation, "attribute");
if (strcmp(json_string_value(tmp), "title"))
continue;
tmp = json_object_get(translation, "text");
if (json_is_string(tmp))
strncpy(plv->title, json_string_value(tmp), PLV_ATTR_SIZE);
tmp = json_object_get(translation, "language");
if (!strcmp(json_string_value(tmp), lang))
break;
}
}
// This file is part of the "LoveOS" project
// (c) 2013 DaWanda GmbH, Paul Asmuth <paul@paulasmuth.com>, et al.
// All rights reserved.
#ifndef PLV_H
#define PLV_H
#include <jansson.h>
#define PLV_ATTR_SIZE 1024
#define PLV_LOAD_ERROR 0
#define PLV_LOAD_SUCCESS 1
#define PLV_S3_HOST "dawandaimages.s3.amazonaws.com"
#define PLV_S3_MAX_ID 31991150
#define PLV_TEMPLATE \
"<li>\
<article class='product'>\
<a href='#pin' class='product-pin-action'>pin this product</a>\
<a href='%s' class='product-pic'>\
<img src='%s' />\
<a href='%s' class='product-title'>%s</a>\
<a href='/shop/%s' class='product-shop'>%s</a>\
<section class='price discounted converted has-pp'\
data-milli-units-per-item='%s' data-unit='%s'>%.2f %s</section>\
</a>\
</article>\
</li>"
typedef struct {
char id[PLV_ATTR_SIZE];
int id_int;
char slug[PLV_ATTR_SIZE];
char url[PLV_ATTR_SIZE];
char image_url[PLV_ATTR_SIZE];
char image_filename[PLV_ATTR_SIZE];
char title[PLV_ATTR_SIZE];
char shop_name[PLV_ATTR_SIZE];
char cents[PLV_ATTR_SIZE];
char currency[PLV_ATTR_SIZE];
int price;
char price_milli_units_per_item[PLV_ATTR_SIZE];
char price_unit[PLV_ATTR_SIZE];
} plv_data;
int plv_load_json(plv_data* plv, char* json, char* lang);
void plv_load_json_attr(json_t* base, char* dst, const char* attr);
void plv_load_json_translations(plv_data* plv, json_t* translations, char* lang);
char* plv_render(plv_data* plv);
void plv_prepare(plv_data* plv);
void plv_render_string(char** buf, const char* str);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment