blob: 665c580daaa351c8c8e8455e47ed854a1dea057b [file] [log] [blame]
/*
* 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();
}