/* * Copyright 2001-2004 Brandon Long * All Rights Reserved. * * ClearSilver Templating System * * This code is made available under the terms of the ClearSilver License. * http://www.clearsilver.net/license.hdf * */ #include <ruby.h> #include <version.h> #include "ClearSilver.h" #include "neo_ruby.h" VALUE mNeotonic; static VALUE cHdf; VALUE eHdfError; static ID id_to_s; #define Srb_raise(val) rb_raise(eHdfError, "%s/%d %s",__FILE__,__LINE__,RSTRING(val)->ptr) VALUE r_neo_error (NEOERR *err) { STRING str; VALUE errstr; string_init (&str); nerr_error_string (err, &str); errstr = rb_str_new2(str.buf); /* if (nerr_match(err, NERR_PARSE)) { } else { } */ string_clear (&str); return errstr; } static void h_free2(t_hdfh *hdfh) { #ifdef DEBUG fprintf(stderr,"freeing hdf 0x%x\n",hdfh); #endif hdf_destroy(&(hdfh->hdf)); free(hdfh); } static void h_free(t_hdfh *hdfh) { #ifdef DEBUG fprintf(stderr,"freeing hdf holder 0x%x of 0x%x\n",hdfh,hdfh->parent); #endif free(hdfh); } static void h_mark(t_hdfh *hdfh) { /* Only mark the array if this is the top node, only the original node should set up the marker. */ #ifdef DEBUG fprintf(stderr,"marking 0x%x\n",hdfh); #endif if ( ! NIL_P(hdfh->top) ) rb_gc_mark(hdfh->top); else fprintf(stderr,"mark top 0x%x\n",hdfh); } static VALUE h_init (VALUE self) { return self; } VALUE h_new(VALUE class) { t_hdfh *hdfh; NEOERR *err; VALUE obj; obj=Data_Make_Struct(class,t_hdfh,0,h_free2,hdfh); err = hdf_init (&(hdfh->hdf)); if (err) Srb_raise(r_neo_error(err)); #ifdef DEBUG fprintf(stderr,"allocated 0x%x\n",(void *)hdfh); #endif hdfh->top=Qnil; rb_obj_call_init(obj, 0, NULL); return obj; } static VALUE h_get_attr (VALUE self, VALUE oName) { t_hdfh *hdfh; char *name; HDF_ATTR *attr; VALUE k,v; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); name = STR2CSTR(oName); rv = rb_hash_new(); attr = hdf_get_attr(hdfh->hdf, name); while ( attr != NULL ) { k=rb_str_new2(attr->key); v=rb_str_new2(attr->value); rb_hash_aset(rv, k, v); attr = attr->next; } return rv; } static VALUE h_set_attr(VALUE self, VALUE oName, VALUE oKey, VALUE oValue) { t_hdfh *hdfh; char *name, *key, *value; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); name = STR2CSTR(oName); key = STR2CSTR(oKey); if ( NIL_P(oValue) ) value = NULL; else value = STR2CSTR(oValue); err = hdf_set_attr(hdfh->hdf, name, key, value); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_set_value (VALUE self, VALUE oName, VALUE oValue) { t_hdfh *hdfh; char *name, *value; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); if ( TYPE(oName) == T_STRING ) name=STR2CSTR(oName); else name=STR2CSTR(rb_funcall(oName,id_to_s,0)); if ( TYPE(oValue) == T_STRING ) value=STR2CSTR(oValue); else value=STR2CSTR(rb_funcall(oValue,id_to_s,0)); err = hdf_set_value (hdfh->hdf, name, value); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_get_int_value (VALUE self, VALUE oName, VALUE oDefault) { t_hdfh *hdfh; char *name; int r, d = 0; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); name=STR2CSTR(oName); d=NUM2INT(oDefault); r = hdf_get_int_value (hdfh->hdf, name, d); rv = INT2NUM(r); return rv; } static VALUE h_get_value (VALUE self, VALUE oName, VALUE oDefault) { t_hdfh *hdfh; char *name; char *r, *d = NULL; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); name=STR2CSTR(oName); d=STR2CSTR(oDefault); r = hdf_get_value (hdfh->hdf, name, d); rv = rb_str_new2(r); return rv; } static VALUE h_get_child (VALUE self, VALUE oName) { t_hdfh *hdfh,*hdfh_new; HDF *r; VALUE rv; char *name; Data_Get_Struct(self, t_hdfh, hdfh); name=STR2CSTR(oName); r = hdf_get_child (hdfh->hdf, name); if (r == NULL) { return Qnil; } rv=Data_Make_Struct(cHdf,t_hdfh,h_mark,h_free,hdfh_new); hdfh_new->top=self; hdfh_new->hdf=r; hdfh_new->parent=hdfh; return rv; } static VALUE h_get_obj (VALUE self, VALUE oName) { t_hdfh *hdfh,*hdfh_new; HDF *r; VALUE rv; char *name; Data_Get_Struct(self, t_hdfh, hdfh); name=STR2CSTR(oName); r = hdf_get_obj (hdfh->hdf, name); if (r == NULL) { return Qnil; } rv=Data_Make_Struct(cHdf,t_hdfh,h_mark,h_free,hdfh_new); hdfh_new->top=self; hdfh_new->hdf=r; hdfh_new->parent=hdfh; return rv; } static VALUE h_get_node (VALUE self, VALUE oName) { t_hdfh *hdfh,*hdfh_new; HDF *r; VALUE rv; char *name; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); name=STR2CSTR(oName); err = hdf_get_node (hdfh->hdf, name, &r); if (err) Srb_raise(r_neo_error(err)); rv=Data_Make_Struct(cHdf,t_hdfh,h_mark,h_free,hdfh_new); hdfh_new->top=self; hdfh_new->hdf=r; hdfh_new->parent=hdfh; return rv; } static VALUE h_obj_child (VALUE self) { t_hdfh *hdfh,*hdfh_new; HDF *r = NULL; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); r = hdf_obj_child (hdfh->hdf); if (r == NULL) { return Qnil; } rv=Data_Make_Struct(cHdf,t_hdfh,h_mark,h_free,hdfh_new); hdfh_new->top=self; hdfh_new->hdf=r; hdfh_new->parent=hdfh; return rv; } static VALUE h_obj_next (VALUE self) { t_hdfh *hdfh,*hdfh_new; HDF *r = NULL; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); r = hdf_obj_next (hdfh->hdf); if (r == NULL) { return Qnil; } rv=Data_Make_Struct(cHdf,t_hdfh,h_mark,h_free,hdfh_new); hdfh_new->top=self; hdfh_new->hdf=r; hdfh_new->parent=hdfh; return rv; } static VALUE h_obj_top (VALUE self) { t_hdfh *hdfh,*hdfh_new; HDF *r = NULL; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); r = hdf_obj_top (hdfh->hdf); if (r == NULL) { return Qnil; } rv=Data_Make_Struct(cHdf,t_hdfh,h_mark,h_free,hdfh_new); hdfh_new->top=self; hdfh_new->hdf=r; hdfh_new->parent=hdfh; return rv; } static VALUE h_obj_name (VALUE self) { t_hdfh *hdfh; VALUE rv; char *r; Data_Get_Struct(self, t_hdfh, hdfh); r = hdf_obj_name (hdfh->hdf); if (r == NULL) { return Qnil; } rv = rb_str_new2(r); return rv; } static VALUE h_obj_attr (VALUE self) { t_hdfh *hdfh; HDF_ATTR *attr; VALUE k,v; VALUE rv; Data_Get_Struct(self, t_hdfh, hdfh); rv = rb_hash_new(); attr = hdf_obj_attr(hdfh->hdf); while ( attr != NULL ) { k=rb_str_new2(attr->key); v=rb_str_new2(attr->value); rb_hash_aset(rv, k, v); attr = attr->next; } return rv; } static VALUE h_obj_value (VALUE self) { t_hdfh *hdfh; VALUE rv; char *r; Data_Get_Struct(self, t_hdfh, hdfh); r = hdf_obj_value (hdfh->hdf); if (r == NULL) { return Qnil; } rv = rb_str_new2(r); return rv; } static VALUE h_read_file (VALUE self, VALUE oPath) { t_hdfh *hdfh; char *path; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); path=STR2CSTR(oPath); err = hdf_read_file (hdfh->hdf, path); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_write_file (VALUE self, VALUE oPath) { t_hdfh *hdfh; char *path; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); path=STR2CSTR(oPath); err = hdf_write_file (hdfh->hdf, path); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_write_file_atomic (VALUE self, VALUE oPath) { t_hdfh *hdfh; char *path; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); path=STR2CSTR(oPath); err = hdf_write_file_atomic (hdfh->hdf, path); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_remove_tree (VALUE self, VALUE oName) { t_hdfh *hdfh; char *name; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); name = STR2CSTR(oName); err = hdf_remove_tree (hdfh->hdf, name); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_dump (VALUE self) { t_hdfh *hdfh; VALUE rv; NEOERR *err; STRING str; string_init (&str); Data_Get_Struct(self, t_hdfh, hdfh); err = hdf_dump_str (hdfh->hdf, NULL, 0, &str); if (err) Srb_raise(r_neo_error(err)); if (str.len==0) return Qnil; rv = rb_str_new2(str.buf); string_clear (&str); return rv; } static VALUE h_write_string (VALUE self) { t_hdfh *hdfh; VALUE rv; NEOERR *err; char *s = NULL; Data_Get_Struct(self, t_hdfh, hdfh); err = hdf_write_string (hdfh->hdf, &s); if (err) Srb_raise(r_neo_error(err)); rv = rb_str_new2(s); if (s) free(s); return rv; } static VALUE h_read_string (VALUE self, VALUE oString, VALUE oIgnore) { t_hdfh *hdfh; NEOERR *err; char *s = NULL; int ignore = 0; Data_Get_Struct(self, t_hdfh, hdfh); s = STR2CSTR(oString); ignore = NUM2INT(oIgnore); err = hdf_read_string_ignore (hdfh->hdf, s, ignore); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_copy (VALUE self, VALUE oName, VALUE oHdfSrc) { t_hdfh *hdfh, *hdfh_src; char *name; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); Data_Get_Struct(oHdfSrc, t_hdfh, hdfh_src); name = STR2CSTR(oName); if (hdfh_src == NULL) rb_raise(eHdfError, "second argument must be an Hdf object"); err = hdf_copy (hdfh->hdf, name, hdfh_src->hdf); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_set_symlink (VALUE self, VALUE oSrc, VALUE oDest) { t_hdfh *hdfh; char *src; char *dest; NEOERR *err; Data_Get_Struct(self, t_hdfh, hdfh); src = STR2CSTR(oSrc); dest = STR2CSTR(oDest); err = hdf_set_symlink (hdfh->hdf, src, dest); if (err) Srb_raise(r_neo_error(err)); return self; } static VALUE h_escape (VALUE self, VALUE oString, VALUE oEsc_char, VALUE oEsc) { VALUE rv; char *s; char *escape; char *esc_char; long buflen; char *ret = NULL; NEOERR *err; s = rb_str2cstr(oString,&buflen); esc_char = STR2CSTR(oEsc_char); escape = STR2CSTR(oEsc); err = neos_escape((UINT8*)s, buflen, esc_char[0], escape, &ret); if (err) Srb_raise(r_neo_error(err)); rv = rb_str_new2(ret); free(ret); return rv; } static VALUE h_unescape (VALUE self, VALUE oString, VALUE oEsc_char) { VALUE rv; char *s; char *copy; char *esc_char; long buflen; s = rb_str2cstr(oString,&buflen); esc_char = STR2CSTR(oEsc_char); /* This should be changed to use memory from the gc */ copy = strdup(s); if (copy == NULL) rb_raise(rb_eNoMemError, "out of memory"); neos_unescape((UINT8*)copy, buflen, esc_char[0]); rv = rb_str_new2(copy); free(copy); return rv; } void Init_cs(); void Init_hdf() { id_to_s=rb_intern("to_s"); mNeotonic = rb_define_module("Neo"); cHdf = rb_define_class_under(mNeotonic, "Hdf", rb_cObject); rb_define_singleton_method(cHdf, "new", h_new, 0); rb_define_method(cHdf, "initialize", h_init, 0); rb_define_method(cHdf, "get_attr", h_get_attr, 1); rb_define_method(cHdf, "set_attr", h_set_attr, 3); rb_define_method(cHdf, "set_value", h_set_value, 2); rb_define_method(cHdf, "put", h_set_value, 2); rb_define_method(cHdf, "get_int_value", h_get_int_value, 2); rb_define_method(cHdf, "get_value", h_get_value, 2); rb_define_method(cHdf, "get_child", h_get_child, 1); rb_define_method(cHdf, "get_obj", h_get_obj, 1); rb_define_method(cHdf, "get_node", h_get_node, 1); rb_define_method(cHdf, "obj_child", h_obj_child, 0); rb_define_method(cHdf, "obj_next", h_obj_next, 0); rb_define_method(cHdf, "obj_top", h_obj_top, 0); rb_define_method(cHdf, "obj_name", h_obj_name, 0); rb_define_method(cHdf, "obj_attr", h_obj_attr, 0); rb_define_method(cHdf, "obj_value", h_obj_value, 0); rb_define_method(cHdf, "read_file", h_read_file, 1); rb_define_method(cHdf, "write_file", h_write_file, 1); rb_define_method(cHdf, "write_file_atomic", h_write_file_atomic, 1); rb_define_method(cHdf, "remove_tree", h_remove_tree, 1); rb_define_method(cHdf, "dump", h_dump, 0); rb_define_method(cHdf, "write_string", h_write_string, 0); rb_define_method(cHdf, "read_string", h_read_string, 2); rb_define_method(cHdf, "copy", h_copy, 2); rb_define_method(cHdf, "set_symlink", h_set_symlink, 2); rb_define_singleton_method(cHdf, "escape", h_escape, 3); rb_define_singleton_method(cHdf, "unescape", h_unescape, 3); eHdfError = rb_define_class_under(mNeotonic, "HdfError", #if RUBY_VERSION_MINOR >= 6 rb_eStandardError); #else rb_eException); #endif Init_cs(); }