#include "ruby.h" #include "version.h" #ifndef TEMPLATESSIZE #define TEMPLATESSIZE 20 #endif typedef struct app_struct { VALUE id; int app_templates[TEMPLATESSIZE]; int app_templates_index; int index; VALUE templates; struct app_struct *next; } app_struct; app_struct *app_push(app_struct **p, VALUE id, int app_template, VALUE templates) { if (p == NULL) return NULL; app_struct *n = malloc(sizeof(app_struct)); if (n == NULL) return NULL; int current_index = 0; if((*p) != NULL) current_index = (*p)->index + 1; n->next = *p; *p = n; n->id = id; n->app_templates[0] = app_template; n->app_templates_index = 1; n->index = current_index; n->templates = templates; return *p; } void app_push_template(app_struct *p, int app_template, VALUE template) { p->app_templates[p->app_templates_index++] = app_template; rb_ary_push(p->templates, template); } void app_remove(app_struct **p) { if (p != NULL && *p != NULL) { app_struct *n = *p; *p = (*p)->next; free(n); } } app_struct *app_search(app_struct **n, VALUE id) { if(n == NULL || *n == NULL) return NULL; if((*n)->id == id) return *n; return &(*app_search(&(*n)->next, id)); } int app_template_search(app_struct *n, int app_template_id) { return app_template_search_n(n, app_template_id, 0); } int app_template_search_n(app_struct *n, int app_template_id, int index) { if(index >= n->app_templates_index) return 0; if(app_template_id == n->app_templates[index]) return 1; return app_template_search_n(n, app_template_id, ++index); } VALUE rb_mSweat; VALUE rb_Sweat_candy(VALUE self, VALUE apps_array) { VALUE apps = rb_ary_new(); VALUE cApp = rb_const_get(rb_cObject, rb_intern("App")); VALUE cApp_template = rb_const_get(rb_cObject, rb_intern("AppTemplate")); app_struct *app_list = NULL; app_struct *current_app_struct; int i; for(i = 0; i < RARRAY(apps_array)->len; ++i) { VALUE hash = rb_ary_entry(apps_array, i); VALUE current_app_id = rb_hash_aref(hash, rb_str_new2("app_id")); VALUE current_app_template_id = rb_hash_aref(hash, rb_str_new2("app_template_id")); if(NIL_P(current_app_template_id)) continue; int current_app_template_id_int = FIX2INT(current_app_template_id); VALUE current_app_instance = rb_funcall(cApp, rb_intern("find"), 1, current_app_id); if(NIL_P(current_app_instance)) continue; current_app_struct = app_search(&app_list, current_app_id); if(current_app_struct == NULL) { VALUE hash_app = rb_funcall(current_app_instance, rb_intern("as_json"), 0); VALUE installation_repository_app = rb_funcall(current_app_instance, rb_intern("installation_repository_app"), 0); VALUE app_template = rb_funcall(cApp_template, rb_intern("find"), 1, current_app_template_id); VALUE templates = rb_ary_new(); rb_ary_push(templates, rb_funcall(app_template, rb_intern("as_json"), 0)); rb_hash_aset(hash_app, rb_str_new2("templates"), templates); rb_hash_aset(hash_app, rb_str_new2("installation_repository_app"), rb_funcall(installation_repository_app, rb_intern("as_json"), 0)); rb_ary_push(apps, hash_app); app_push(&app_list, current_app_id, current_app_template_id_int, templates); } else { if(!app_template_search(current_app_struct, current_app_template_id_int)) { VALUE app_template = rb_funcall(cApp_template, rb_intern("find"), 1, current_app_template_id); app_push_template(current_app_struct, current_app_template_id_int, rb_funcall(app_template, rb_intern("as_json"), 0)); } } } while(app_list != NULL) app_remove(&app_list); return apps; } void Init_sweat() { rb_mSweat = rb_define_module("Sweat"); rb_define_method(rb_mSweat, "candy", rb_Sweat_candy, 1); }