static VALUE method_set(VALUE self, VALUE path, VALUE data, VALUE version) {
  struct zk_rb_data* zk;

  Check_Type(path, T_STRING);
  Check_Type(data, T_STRING);
  Check_Type(version, T_FIXNUM);
  Data_Get_Struct(rb_iv_get(self, "@data"), struct zk_rb_data, zk);
  
  check_errors(zoo_set(zk->zh, RSTRING(path)->ptr, RSTRING(data)->ptr, RSTRING(data)->len, FIX2INT(version)));

  return Qnil;
}
示例#2
0
VALUE
rb_Node_initialize(int argc, VALUE* argv, VALUE self){
    
    // connect
    if(argc == 3){
        VALUE server_value = argv[0];
        Check_Type(argv[1], T_STRING);
        Check_Type(argv[2], T_FIXNUM);
        
        struct fs_server* server = NULL;
        Data_Get_Struct(server_value, struct fs_server, server);
        
        
        struct fs_node* node = fs_create_node(server);
        
        struct fs_node_addr addr;
        strcpy(addr.addr, StringValueCStr(argv[1]));
        addr.port = FIX2INT(argv[2]);
        
        
        if(fs_server_connect_node(server, node, &addr)){
            
            RDATA(self)->data = node;
            fs_node_set_script_id(node, self);
            rb_funcall(self, rb_intern("server="), 1, server_value);
            
        }else{
            fs_free(node);
            RDATA(node)->data = NULL;
            rb_raise(rb_eRuntimeError, "connect %s:%d fail", addr.addr, addr.port);
        }
        return Qnil;
    }
        
    // accept
    if(argc == 2){
        Check_Type(argv[0], T_DATA);
        Check_Type(argv[1], T_FIXNUM);
        
        VALUE v_server  = argv[0];
        fs_id node_id = FIX2INT(argv[1]);
        
        struct fs_server* server;
        Data_Get_Struct(v_server, struct fs_server, server);
        
        
        struct fs_node* node = fs_server_find_node_by_id(server, node_id);
        
        if(node){
            RDATA(self)->data = node;
            fs_node_set_script_id(node, self);
            rb_funcall(self, rb_intern("server="), 1, v_server);
        }else{
            
            rb_raise(rb_eRuntimeError, "bind node error");
        }
        return Qnil;
    }
    
    rb_raise(rb_eArgError, "#<ArgumentError: wrong number of arguments (%d for %d)>", argc, 3);
    
    return Qnil;
}
示例#3
0
static VALUE t_send_datagram (VALUE self, VALUE signature, VALUE data, VALUE data_length, VALUE address, VALUE port)
{
	int b = evma_send_datagram (NUM2ULONG (signature), StringValuePtr (data), FIX2INT (data_length), StringValuePtr(address), FIX2INT(port));
	return INT2NUM (b);
}
示例#4
0
VALUE string_spec_rb_str2inum(VALUE self, VALUE str, VALUE inum) {
  int num = FIX2INT(inum);
  return rb_str2inum(str, num);
}
示例#5
0
VALUE string_spec_rb_str_resize_RSTRING_LEN(VALUE self, VALUE str, VALUE size) {
  VALUE modified = rb_str_resize(str, FIX2INT(size));
  return INT2FIX(RSTRING_LEN(modified));
}
示例#6
0
VALUE string_spec_rb_str_new(VALUE self, VALUE str, VALUE len) {
  return rb_str_new(RSTRING_PTR(str), FIX2INT(len));
}
示例#7
0
static void svg2bifs_node_start(void *sax_cbck, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
{
	u32 i;
	SVG_SANI_BIFS_Converter *converter = (SVG_SANI_BIFS_Converter *)sax_cbck;
	SVGPropertiesPointers *backup_props;
	char *id_string = NULL;

	u32	tag = gf_svg_get_element_tag(name);
	SVG_Element *elt = (SVG_Element*)gf_node_new(converter->svg_sg, tag);
	if (!gf_sg_get_root_node(converter->svg_sg)) {
		gf_node_register((GF_Node *)elt, NULL);
		gf_sg_set_root_node(converter->svg_sg, (GF_Node *)elt);
	} else {
		gf_node_register((GF_Node *)elt, converter->svg_parent);	
		//gf_node_list_add_child(&((GF_ParentNode*)converter->svg_parent)->children, (GF_Node *)elt);
	}
	converter->svg_parent = (GF_Node *)elt;
	
//	fprintf(stdout, "Converting %s\n", gf_node_get_class_name((GF_Node *)elt));
//	if (converter->bifs_parent) fprintf(stdout, "%s\n", gf_node_get_class_name(converter->bifs_parent));

	for (i=0; i<nb_attributes; i++) {
		GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];
		if (!att->value || !strlen(att->value)) continue;

		if (!stricmp(att->name, "style")) {
			gf_svg_parse_style((GF_Node *)elt, att->value);
		} else if (!stricmp(att->name, "id") || !stricmp(att->name, "xml:id")) {
			gf_svg_parse_element_id((GF_Node *)elt, att->value, 0);
			id_string = att->value;
		} else {
			GF_FieldInfo info;
			if (gf_node_get_field_by_name((GF_Node *)elt, att->name, &info)==GF_OK) {
				gf_svg_parse_attribute((GF_Node *)elt, &info, att->value, 0);
			} else {
				fprintf(stdout, "Skipping attribute %s\n", att->name);
			}
		}
	}

	memset(&converter->all_atts, 0, sizeof(SVGAllAttributes));
	gf_svg_flatten_attributes(elt, &converter->all_atts);
	
	backup_props = gf_malloc(sizeof(SVGPropertiesPointers));
	memcpy(backup_props, &converter->svg_props, sizeof(SVGPropertiesPointers));
	gf_node_set_private((GF_Node *)elt, backup_props);

	gf_svg_apply_inheritance(&converter->all_atts, &converter->svg_props);

	if (!gf_sg_get_root_node(converter->bifs_sg)) {
		if (tag == TAG_SVG_svg) {
			GF_Node *node, *child;

			converter->bifs_sg->usePixelMetrics = 1;
			if (converter->all_atts.width && converter->all_atts.width->type == SVG_NUMBER_VALUE) {
				converter->bifs_sg->width = FIX2INT(converter->all_atts.width->value);
			} else {
				converter->bifs_sg->width = 320;
			}
			if (converter->all_atts.height && converter->all_atts.height->type == SVG_NUMBER_VALUE) {
				converter->bifs_sg->height = FIX2INT(converter->all_atts.height->value);
			} else {
				converter->bifs_sg->height = 200;
			}

			node = gf_node_new(converter->bifs_sg, TAG_MPEG4_OrderedGroup);
			gf_node_register(node, NULL);
			gf_sg_set_root_node(converter->bifs_sg, node);

			/* SVG to BIFS coordinate transformation */
			child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Viewport);
			gf_node_register(child, node);
			gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
			if (converter->all_atts.viewBox) {
				M_Viewport *vp = (M_Viewport*)child;
				vp->size.x = converter->all_atts.viewBox->width;
				vp->size.y = converter->all_atts.viewBox->height;
				vp->position.x = converter->all_atts.viewBox->x+converter->all_atts.viewBox->width/2;
				vp->position.y = -(converter->all_atts.viewBox->y+converter->all_atts.viewBox->height/2);
			} else {
				M_Viewport *vp = (M_Viewport*)child;
				vp->size.x = INT2FIX(converter->bifs_sg->width);
				vp->size.y = INT2FIX(converter->bifs_sg->height);
				vp->position.x = INT2FIX(converter->bifs_sg->width)/2;
				vp->position.y = -INT2FIX(converter->bifs_sg->height)/2;
			}

			child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Background2D);
			gf_node_register(child, node);
			gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
			{
				M_Background2D *b = (M_Background2D *)child;
				b->backColor.red = FIX_ONE;
				b->backColor.green = FIX_ONE;				
				b->backColor.blue = FIX_ONE;
			}

			child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D);
			gf_node_register(child, node);
			gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
			node = child;
			child = NULL;
			{
				M_Transform2D *tr = (M_Transform2D *)node;
				tr->scale.y = -FIX_ONE;
			}
			converter->bifs_parent = node;
		}
	} else {
		GF_Node *node, *child;
		
		node = converter->bifs_parent;

		switch(tag) {
		case TAG_SVG_g:
			{
				if (converter->all_atts.transform) {
					node = add_transform(converter, node);
					converter->bifs_parent = node;
				} else {
					M_Group *g = (M_Group*)gf_node_new(converter->bifs_sg, TAG_MPEG4_Group);
					gf_node_register((GF_Node *)g, node);
					gf_node_list_add_child(&((GF_ParentNode*)node)->children, (GF_Node *)g);
					node = (GF_Node *)g;
					converter->bifs_parent = node;
				}
			}
			break;
		case TAG_SVG_rect:
			{
				Bool is_parent_set = 0;
				if (converter->all_atts.transform) {
					node = add_transform(converter, node);
					converter->bifs_parent = node;
					is_parent_set = 1;
				} 
				if (converter->all_atts.x || converter->all_atts.y) {
					child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D);
					gf_node_register(child, node);
					gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
					node = child;
					child = NULL;
					if (!is_parent_set) {
						converter->bifs_parent = node;
						is_parent_set = 1;
					}
					{
						M_Transform2D *tr = (M_Transform2D *)node;
						if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value + (converter->all_atts.width?converter->all_atts.width->value/2:0);
						if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value + (converter->all_atts.height?converter->all_atts.height->value/2:0);
					}
				} 
				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				if (!is_parent_set) converter->bifs_parent = node;
				{
					M_Shape *shape = (M_Shape *)node;
					shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_Rectangle);
					gf_node_register(shape->geometry, (GF_Node *)shape);
					{
						M_Rectangle *rect = (M_Rectangle *)shape->geometry;
						if (converter->all_atts.width) rect->size.x = converter->all_atts.width->value;
						if (converter->all_atts.height) rect->size.y = converter->all_atts.height->value;					
					}			
					
					shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg);
					gf_node_register(shape->appearance, (GF_Node *)shape);
				}
			}
			break;
		case TAG_SVG_path:
			{
				Bool is_parent_set = 0;
				if (converter->all_atts.transform) {
					node = add_transform(converter, node);
					converter->bifs_parent = node;
					is_parent_set = 1;
				} 
				if (converter->all_atts.x || converter->all_atts.y) {
					child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D);
					gf_node_register(child, node);
					gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
					node = child;
					child = NULL;
					if (!is_parent_set) {
						converter->bifs_parent = node;
						is_parent_set = 1;
					}
					{
						M_Transform2D *tr = (M_Transform2D *)node;
						if (converter->all_atts.x) tr->translation.x = converter->all_atts.x->value;
						if (converter->all_atts.y) tr->translation.y = converter->all_atts.y->value;
					}
				} 
				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				if (!is_parent_set) converter->bifs_parent = node;
				{
					M_Shape *shape = (M_Shape *)node;
					shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_XCurve2D);
					gf_node_register(shape->geometry, (GF_Node *)shape);
					if (converter->all_atts.d) {
						M_Coordinate2D *c2d;
						M_XCurve2D *xc = (M_XCurve2D *)shape->geometry;
						u32 i, j, c;

						xc->point = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D);
						c2d = (M_Coordinate2D *)xc->point;
						gf_node_register(xc->point, (GF_Node *)xc);
						
						gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, converter->all_atts.d->n_points);
						j= 0;
						for (i = 0; i < converter->all_atts.d->n_points; i++) {
							if (converter->all_atts.d->tags[i] != GF_PATH_CLOSE || i == converter->all_atts.d->n_points-1) {
								c2d->point.vals[j] = converter->all_atts.d->points[i];
								j++;
							}
						}
						c2d->point.count = j;

						gf_sg_vrml_mf_alloc(&xc->type, GF_SG_VRML_MFINT32, converter->all_atts.d->n_points);
						c = 0;
						j = 0;
						xc->type.vals[0] = 0;
						for (i = 1; i < converter->all_atts.d->n_points; i++) {
							switch(converter->all_atts.d->tags[i]) {
							case GF_PATH_CURVE_ON:
								if (c < converter->all_atts.d->n_contours &&
									i-1 == converter->all_atts.d->contours[c]) {
									xc->type.vals[j] = 0;
									c++;
								} else {
									xc->type.vals[j] = 1;
								}
								break;
							case GF_PATH_CURVE_CUBIC:
								xc->type.vals[j] = 2;
								i+=2;
								break;
							case GF_PATH_CLOSE:
								xc->type.vals[j] = 6;
								break;
							case GF_PATH_CURVE_CONIC:
								xc->type.vals[j] = 7;
								i++;
								break;
							}
							j++;
						}
						xc->type.count = j;
					}			
					
					shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg);
					gf_node_register(shape->appearance, (GF_Node *)shape);
				}
			}
			break;
		case TAG_SVG_polyline:
			{
				Bool is_parent_set = 0;
				if (converter->all_atts.transform) {
					node = add_transform(converter, node);
					converter->bifs_parent = node;
					is_parent_set = 1;
				} 

				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				if (!is_parent_set) converter->bifs_parent = node;
				{
					M_Shape *shape = (M_Shape *)node;
					shape->geometry = gf_node_new(converter->bifs_sg, TAG_MPEG4_IndexedFaceSet2D);
					gf_node_register(shape->geometry, (GF_Node *)shape);
					if (converter->all_atts.points) {
						M_Coordinate2D *c2d;
						M_IndexedFaceSet2D *ifs = (M_IndexedFaceSet2D *)shape->geometry;
						u32 i;

						ifs->coord = gf_node_new(converter->bifs_sg, TAG_MPEG4_Coordinate2D);
						c2d = (M_Coordinate2D *)ifs->coord;
						gf_node_register(ifs->coord, (GF_Node *)ifs);
						
						gf_sg_vrml_mf_alloc(&c2d->point, GF_SG_VRML_MFVEC2F, gf_list_count(*converter->all_atts.points));
						for (i = 0; i < gf_list_count(*converter->all_atts.points); i++) {
							SVG_Point *p = (SVG_Point *)gf_list_get(*converter->all_atts.points, i);
							c2d->point.vals[i].x = p->x;
							c2d->point.vals[i].y = p->y;
						}						
					}			
					
					shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg);
					gf_node_register(shape->appearance, (GF_Node *)shape);
				}
			}
			break;
		case TAG_SVG_text:
			{
				Bool is_parent_set = 0;
				if (converter->all_atts.transform) {
					node = add_transform(converter, node);
					converter->bifs_parent = node;
					is_parent_set = 1;
				}

				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				{
					M_Transform2D *tr = (M_Transform2D *)child;
					if (converter->all_atts.text_x) tr->translation.x = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_x, 0))->value;
					if (converter->all_atts.text_y) tr->translation.y = ((SVG_Coordinate *)gf_list_get(*converter->all_atts.text_y, 0))->value;
					tr->scale.y = -FIX_ONE;
				}
				node = child;
				child = NULL;
				if (!is_parent_set) {
					converter->bifs_parent = node;
					is_parent_set = 1;
				}

				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				if (!is_parent_set) converter->bifs_parent = node;
				{
					M_FontStyle *fs;
					M_Text *text; 
					M_Shape *shape = (M_Shape *)node;
					text = (M_Text *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Text);
					shape->geometry = (GF_Node *)text;
					converter->bifs_text_node = shape->geometry;
					gf_node_register(shape->geometry, (GF_Node *)shape);
					
					fs = (M_FontStyle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_XFontStyle);
					gf_node_register((GF_Node *)fs, (GF_Node*)text);
					text->fontStyle = (GF_Node *)fs;

					gf_sg_vrml_mf_alloc(&fs->family, GF_SG_VRML_MFSTRING, 1);				
					fs->family.vals[0] = strdup(converter->svg_props.font_family->value);				
					fs->size = converter->svg_props.font_size->value;

					shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg);
					gf_node_register(shape->appearance, (GF_Node *)shape);
				}
			}
			break;
		case TAG_SVG_ellipse:
		case TAG_SVG_circle:
			{
				Bool is_parent_set = 0;
				if (converter->all_atts.transform) {
					node = add_transform(converter, node);
					converter->bifs_parent = node;
					is_parent_set = 1;
				}
				if (converter->all_atts.cx || converter->all_atts.cy) {
					child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D);
					gf_node_register(child, node);
					gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
					{
						M_Transform2D *tr = (M_Transform2D *)child;
						if (converter->all_atts.cx) tr->translation.x = converter->all_atts.cx->value;
						if (converter->all_atts.cy) tr->translation.y = converter->all_atts.cy->value;
					}
					node = child;
					child = NULL;
					if (!is_parent_set) {
						converter->bifs_parent = node;
						is_parent_set = 1;
					}
				} 
				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				if (!is_parent_set) converter->bifs_parent = node;
				{
					M_Shape *shape = (M_Shape *)node;
					if (tag == TAG_SVG_ellipse) {
						M_Ellipse *e = (M_Ellipse *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Ellipse);
						shape->geometry = (GF_Node *)e;
						e->radius.x = converter->all_atts.rx->value;
						e->radius.y = converter->all_atts.ry->value;
					} else {
						M_Circle *c = (M_Circle *)gf_node_new(converter->bifs_sg, TAG_MPEG4_Circle);
						shape->geometry = (GF_Node *)c;
						c->radius = converter->all_atts.r->value;
					}
					gf_node_register(shape->geometry, (GF_Node *)shape);
					
					shape->appearance = create_appearance(&converter->svg_props, converter->bifs_sg);
					gf_node_register(shape->appearance, (GF_Node *)shape);
				}
			}
			break;

		case TAG_SVG_defs:
			{
				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Switch);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				{
					M_Switch *sw = (M_Switch *)node;
					sw->whichChoice = -1;
				}
				converter->bifs_parent = node;
			}
			break;
		case TAG_SVG_solidColor:
			{
				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Shape);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				converter->bifs_parent = node;
			}
			break;
		default:
			{
				fprintf(stdout, "Warning: element %s not supported \n", gf_node_get_class_name((GF_Node *)elt));
				child = gf_node_new(converter->bifs_sg, TAG_MPEG4_Transform2D);
				gf_node_register(child, node);
				gf_node_list_add_child(&((GF_ParentNode*)node)->children, child);
				node = child;
				child = NULL;
				converter->bifs_parent = node;
			}
			break;
		}

		if (id_string) 
			gf_node_set_id(converter->bifs_parent, gf_node_get_id((GF_Node *)elt), gf_node_get_name((GF_Node *)elt));
	}
}
示例#8
0
static void svg_traverse_bitmap(GF_Node *node, void *rs, Bool is_destroy)
{
	Fixed cx, cy, angle;
	/*video stack is just an extension of image stack, type-casting is OK*/
	SVG_video_stack *stack = (SVG_video_stack*)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	DrawableContext *ctx;
	SVGAllAttributes all_atts;


	if (is_destroy) {
		gf_sc_texture_destroy(&stack->txh);
		gf_sg_mfurl_del(stack->txurl);

		drawable_del(stack->graph);
		if (stack->audio) {
			gf_node_unregister(stack->audio, NULL);
		}
		gf_free(stack);
		return;
	} 


	/*TRAVERSE_DRAW is NEVER called in 3D mode*/
	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		SVG_Draw_bitmap(tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_PICK) {
		svg_drawable_pick(node, stack->graph, tr_state);
		return;
	}

	/*flatten attributes and apply animations + inheritance*/
	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!compositor_svg_traverse_base(node, &all_atts, (GF_TraverseState *)rs, &backup_props, &backup_flags))
		return;

	if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
		gf_term_get_mfurl_from_xlink(node, &stack->txurl);
		stack->txh.width = stack->txh.height = 0;
		
		/*remove associated audio if any*/
		if (stack->audio) {
			svg_audio_smil_evaluate_ex(NULL, 0, SMIL_TIMING_EVAL_REMOVE, stack->audio, stack->txh.owner);
			gf_node_unregister(stack->audio, NULL);
			stack->audio = NULL;
		}
		stack->audio_dirty = GF_TRUE;
		
		if (stack->txurl.count) svg_play_texture(stack, &all_atts);
		gf_node_dirty_clear(node, GF_SG_SVG_XLINK_HREF_DIRTY);
	}

	if (gf_node_dirty_get(node)) {
		/*do not clear dirty state until the image is loaded*/
		if (stack->txh.width) {
			gf_node_dirty_clear(node, 0);
			SVG_Build_Bitmap_Graph((SVG_video_stack*)gf_node_get_private(node), tr_state);
		}
		
	} 

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props)) {
			gf_path_get_bounds(stack->graph->path, &tr_state->bounds);
			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			if (svg_video_get_transform_behavior(tr_state, &all_atts, &cx, &cy, &angle)) {
				GF_Matrix2D mx;
				tr_state->bounds.width = INT2FIX(stack->txh.width);
				tr_state->bounds.height = INT2FIX(stack->txh.height);
				tr_state->bounds.x = cx - tr_state->bounds.width/2;
				tr_state->bounds.y = cy + tr_state->bounds.height/2;
				gf_mx2d_init(mx);
				gf_mx2d_add_rotation(&mx, 0, 0, angle);
				gf_mx2d_apply_rect(&mx, &tr_state->bounds);
			} else {
				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
			}

			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
		if (!compositor_svg_is_display_off(tr_state->svg_props) && ( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) {
			GF_Matrix mx_bck;
			Bool restore_mx = GF_FALSE;

			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			ctx = drawable_init_context_svg(stack->graph, tr_state);
			if (!ctx || !ctx->aspect.fill_texture ) return;

			if (svg_video_get_transform_behavior(tr_state, &all_atts, &cx, &cy, &angle)) {
				drawable_reset_path(stack->graph);
				gf_path_add_rect_center(stack->graph->path, cx, cy, INT2FIX(stack->txh.width), INT2FIX(stack->txh.height));

				gf_mx2d_copy(mx_bck, tr_state->transform);
				restore_mx = GF_TRUE;
				
				gf_mx2d_init(tr_state->transform);
				gf_mx2d_add_rotation(&tr_state->transform, cx, cy, angle);
			}

			/*even if set this is not true*/
			ctx->aspect.pen_props.width = 0;
			ctx->flags |= CTX_NO_ANTIALIAS;

			/*if rotation, transparent*/
			ctx->flags &= ~CTX_IS_TRANSPARENT;
			if (ctx->transform.m[1] || ctx->transform.m[3]) {
				ctx->flags |= CTX_IS_TRANSPARENT;
				ctx->flags &= ~CTX_NO_ANTIALIAS;
			}
			else if (ctx->aspect.fill_texture->transparent) 
				ctx->flags |= CTX_IS_TRANSPARENT;
			else if (tr_state->svg_props->opacity && (tr_state->svg_props->opacity->type==SVG_NUMBER_VALUE) && (tr_state->svg_props->opacity->value!=FIX_ONE)) {
				ctx->flags = CTX_IS_TRANSPARENT;
				ctx->aspect.fill_color = GF_COL_ARGB(FIX2INT(0xFF * tr_state->svg_props->opacity->value), 0, 0, 0);
			}

#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d) {
				if (!stack->graph->mesh) {
					stack->graph->mesh = new_mesh();
					mesh_from_path(stack->graph->mesh, stack->graph->path);
				}
				compositor_3d_draw_bitmap(stack->graph, &ctx->aspect, tr_state, 0, 0, FIX_ONE, FIX_ONE);
				ctx->drawable = NULL;
			} else 
#endif
			{
				drawable_finalize_sort(ctx, tr_state, NULL);
			}

			if (restore_mx) gf_mx2d_copy(tr_state->transform, mx_bck);
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	}
	if (stack->audio) svg_traverse_audio_ex(stack->audio, rs, GF_FALSE, tr_state->svg_props);

	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
示例#9
0
static VALUE sa_array_store(VALUE self, VALUE array, VALUE offset, VALUE value) {
  rb_ary_store(array, FIX2INT(offset), value);

  return Qnil;
}
示例#10
0
static VALUE sa_array_entry(VALUE self, VALUE array, VALUE offset) {
  return rb_ary_entry(array, FIX2INT(offset));
}
示例#11
0
文件: blas3.c 项目: Fudge/rb-gsl
static VALUE rb_gsl_blas_zgemm(int argc, VALUE *argv, VALUE obj)
{
  gsl_matrix_complex *A = NULL, *B = NULL, *C = NULL;
  gsl_complex alpha, beta, *pa = &alpha, *pb = &beta;
  CBLAS_TRANSPOSE_t TransA, TransB;
  int flag = 0;
  alpha.dat[0] = 1.0; alpha.dat[1] = 0.0;
  beta.dat[0] = 0.0; beta.dat[1] = 0.0;
  switch (argc) {
  case 2:
    CHECK_MATRIX_COMPLEX(argv[0]);
    CHECK_MATRIX_COMPLEX(argv[1]);
    Data_Get_Struct(argv[0], gsl_matrix_complex, A);
    Data_Get_Struct(argv[1], gsl_matrix_complex, B);
    C = gsl_matrix_complex_calloc(A->size1, B->size2);
    TransA = CblasNoTrans;  TransB = CblasNoTrans;
    flag = 1;
    break;
  case 5:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    CHECK_COMPLEX(argv[2]);
    CHECK_MATRIX_COMPLEX(argv[3]);
    CHECK_MATRIX_COMPLEX(argv[4]);
    TransA = FIX2INT(argv[0]);
    TransB = FIX2INT(argv[1]);
    Data_Get_Struct(argv[2], gsl_complex, pa);
    Data_Get_Struct(argv[3], gsl_matrix_complex, A);
    Data_Get_Struct(argv[4], gsl_matrix_complex, B);
    C = gsl_matrix_complex_calloc(A->size1, B->size2);
    flag = 1;
    break;
  case 6:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    CHECK_COMPLEX(argv[2]);
    CHECK_MATRIX_COMPLEX(argv[3]);
    CHECK_MATRIX_COMPLEX(argv[4]);
    CHECK_COMPLEX(argv[5]);
    TransA = FIX2INT(argv[0]);
    TransB = FIX2INT(argv[1]);
    Data_Get_Struct(argv[2], gsl_complex, pa);
    Data_Get_Struct(argv[3], gsl_matrix_complex, A);
    Data_Get_Struct(argv[4], gsl_matrix_complex, B);
    Data_Get_Struct(argv[5], gsl_complex, pb);
    C = gsl_matrix_complex_calloc(A->size1, B->size2);
    flag = 1;
    break;
  case 7:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    CHECK_COMPLEX(argv[2]);
    CHECK_MATRIX_COMPLEX(argv[3]);
    CHECK_MATRIX_COMPLEX(argv[4]);
    CHECK_COMPLEX(argv[5]);
    CHECK_MATRIX_COMPLEX(argv[6]);
    TransA = FIX2INT(argv[0]);
    TransB = FIX2INT(argv[1]);
    Data_Get_Struct(argv[2], gsl_complex, pa);
    Data_Get_Struct(argv[3], gsl_matrix_complex, A);
    Data_Get_Struct(argv[4], gsl_matrix_complex, B);
    Data_Get_Struct(argv[5], gsl_complex, pb);
    Data_Get_Struct(argv[6], gsl_matrix_complex, C);
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 7)", argc);
    break;
  }
  gsl_blas_zgemm(TransA, TransB, alpha, A, B, beta, C);
  if (flag == 1) return Data_Wrap_Struct(cgsl_matrix_complex, 0, gsl_matrix_complex_free, C);
  else return argv[6];
}
示例#12
0
文件: blas3.c 项目: Fudge/rb-gsl
static VALUE rb_gsl_blas_zhemm(int argc, VALUE *argv, VALUE obj)
{
  gsl_matrix_complex *A = NULL, *B = NULL, *C = NULL;
  gsl_complex alpha, beta, *pa = &alpha, *pb = &beta;
  CBLAS_SIDE_t Side;
  CBLAS_UPLO_t Uplo;
  int flag = 0;
  alpha = gsl_complex_rect(1.0, 0.0);
  beta = gsl_complex_rect(0.0, 0.0);
  switch (argc) {
  case 2:
    CHECK_MATRIX_COMPLEX(argv[0]);
    CHECK_MATRIX_COMPLEX(argv[1]);
    Data_Get_Struct(argv[0], gsl_matrix_complex, A);
    Data_Get_Struct(argv[1], gsl_matrix_complex, B);
    C = gsl_matrix_complex_calloc(A->size1, B->size2);
    Side = CblasLeft;  Uplo = CblasUpper;
    flag = 1;
    break;
  case 5:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    CHECK_COMPLEX(argv[2]);
    CHECK_MATRIX_COMPLEX(argv[3]);
    CHECK_MATRIX_COMPLEX(argv[4]);
    Side = FIX2INT(argv[0]);
    Uplo = FIX2INT(argv[1]);
    Data_Get_Struct(argv[2], gsl_complex, pa);
    Data_Get_Struct(argv[3], gsl_matrix_complex, A);
    Data_Get_Struct(argv[4], gsl_matrix_complex, B);
    C = gsl_matrix_complex_calloc(A->size1, B->size2);
    flag = 1;
    break;
  case 6:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    CHECK_COMPLEX(argv[2]);
    CHECK_MATRIX_COMPLEX(argv[3]);
    CHECK_MATRIX_COMPLEX(argv[4]);
    CHECK_COMPLEX(argv[5]);
    CHECK_MATRIX_COMPLEX(argv[6]);
    Side = FIX2INT(argv[0]);
    Uplo = FIX2INT(argv[1]);
    Data_Get_Struct(argv[2], gsl_complex, pa);
    Data_Get_Struct(argv[3], gsl_matrix_complex, A);
    Data_Get_Struct(argv[4], gsl_matrix_complex, B);
    Data_Get_Struct(argv[5], gsl_complex, pb);
    C = gsl_matrix_complex_calloc(A->size1, B->size2);
    flag = 1;
    break;
  case 7:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    CHECK_COMPLEX(argv[2]);
    CHECK_MATRIX_COMPLEX(argv[3]);
    CHECK_MATRIX_COMPLEX(argv[4]);
    CHECK_COMPLEX(argv[5]);
    CHECK_MATRIX_COMPLEX(argv[6]);
    Side = FIX2INT(argv[0]);
    Uplo = FIX2INT(argv[1]);
    Data_Get_Struct(argv[2], gsl_complex, pa);
    Data_Get_Struct(argv[3], gsl_matrix_complex, A);
    Data_Get_Struct(argv[4], gsl_matrix_complex, B);
    Data_Get_Struct(argv[5], gsl_complex, pb);
    Data_Get_Struct(argv[6], gsl_matrix_complex, C);
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 7)", argc);
    break;
  }
  gsl_blas_zhemm(Side, Uplo, alpha, A, B, beta, C);
  if (flag == 1) return Data_Wrap_Struct(cgsl_matrix_complex, 0, gsl_matrix_complex_free, C);
  else return argv[6];
}
示例#13
0
文件: blas3.c 项目: Fudge/rb-gsl
static VALUE rb_gsl_blas_dgemm(int argc, VALUE *argv, VALUE obj)
{
  gsl_matrix *A = NULL, *B = NULL, *C = NULL;
  double alpha, beta;
  CBLAS_TRANSPOSE_t TransA, TransB;
  int flag = 0;
  switch (argc) {
  case 2:
    CHECK_MATRIX(argv[0]);
    CHECK_MATRIX(argv[1]);
    Data_Get_Struct(argv[0], gsl_matrix, A);
    Data_Get_Struct(argv[1], gsl_matrix, B);
    C = gsl_matrix_calloc(A->size1, B->size2);
    alpha = 1.0;
    beta = 0.0;
    TransA = CblasNoTrans;  TransB = CblasNoTrans;
    flag = 1;
    break;
  case 5:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    Need_Float(argv[2]);
    CHECK_MATRIX(argv[3]);
    CHECK_MATRIX(argv[4]);
    TransA = FIX2INT(argv[0]);
    TransB = FIX2INT(argv[1]);
    alpha = NUM2DBL(argv[2]);
    Data_Get_Struct(argv[3], gsl_matrix, A);
    Data_Get_Struct(argv[4], gsl_matrix, B);
    C = gsl_matrix_calloc(A->size1, B->size2);
    beta = 0.0;
    flag = 1;
    break;
  case 6:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    Need_Float(argv[2]);
    CHECK_MATRIX(argv[3]);
    CHECK_MATRIX(argv[4]);
    Need_Float(argv[5]);
    TransA = FIX2INT(argv[0]);
    TransB = FIX2INT(argv[1]);
    alpha = NUM2DBL(argv[2]);
    Data_Get_Struct(argv[3], gsl_matrix, A);
    Data_Get_Struct(argv[4], gsl_matrix, B);
    beta = NUM2DBL(argv[5]);
    C = gsl_matrix_calloc(A->size1, B->size2);
    flag = 1;
    break;
  case 7:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    Need_Float(argv[2]);
    CHECK_MATRIX(argv[3]);
    CHECK_MATRIX(argv[4]);
    Need_Float(argv[5]);
    CHECK_MATRIX(argv[6]);
    TransA = FIX2INT(argv[0]);
    TransB = FIX2INT(argv[1]);
    alpha = NUM2DBL(argv[2]);
    Data_Get_Struct(argv[3], gsl_matrix, A);
    Data_Get_Struct(argv[4], gsl_matrix, B);
    beta = NUM2DBL(argv[5]);
    Data_Get_Struct(argv[6], gsl_matrix, C);
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2, 5, 6, or 7)", argc);
    break;
  }
  gsl_blas_dgemm(TransA, TransB, alpha, A, B, beta, C);
  if (flag == 1) return Data_Wrap_Struct(cgsl_matrix, 0, gsl_matrix_free, C);
  else return argv[6];
}
示例#14
0
文件: blas3.c 项目: Fudge/rb-gsl
static VALUE rb_gsl_blas_dsymm(int argc, VALUE *argv, VALUE obj)
{
  gsl_matrix *A = NULL, *B = NULL, *C = NULL;
  double alpha, beta;
  CBLAS_SIDE_t Side;
  CBLAS_UPLO_t Uplo;
  int flag = 0;
  switch (argc) {
  case 2:
    CHECK_MATRIX(argv[0]);
    CHECK_MATRIX(argv[1]);
    Data_Get_Struct(argv[0], gsl_matrix, A);
    Data_Get_Struct(argv[1], gsl_matrix, B);
    C = gsl_matrix_calloc(A->size1, B->size2);
    alpha = 1.0;
    beta = 0.0;
    Side = CblasLeft;  Uplo = CblasUpper;
    flag = 1;
    break;
  case 5:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    Need_Float(argv[2]);
    CHECK_MATRIX(argv[3]);
    CHECK_MATRIX(argv[4]);
    Side = FIX2INT(argv[0]);
    Uplo = FIX2INT(argv[1]);
    alpha = NUM2DBL(argv[2]);
    Data_Get_Struct(argv[3], gsl_matrix, A);
    Data_Get_Struct(argv[4], gsl_matrix, B);
    C = gsl_matrix_calloc(A->size1, B->size2);
    beta = 0.0;
    flag = 1;
    break;
  case 6:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    Need_Float(argv[2]);
    CHECK_MATRIX(argv[3]);
    CHECK_MATRIX(argv[4]);
    Need_Float(argv[5]);
    CHECK_MATRIX(argv[6]);
    Side = FIX2INT(argv[0]);
    Uplo = FIX2INT(argv[1]);
    alpha = NUM2DBL(argv[2]);
    Data_Get_Struct(argv[3], gsl_matrix, A);
    Data_Get_Struct(argv[4], gsl_matrix, B);
    beta = NUM2DBL(argv[5]);
    C = gsl_matrix_calloc(A->size1, B->size2);
    flag = 1;
    break;
  case 7:
    CHECK_FIXNUM(argv[0]);
    CHECK_FIXNUM(argv[1]);
    Need_Float(argv[2]);
    CHECK_MATRIX(argv[3]);
    CHECK_MATRIX(argv[4]);
    Need_Float(argv[5]);
    CHECK_MATRIX(argv[6]);
    Side = FIX2INT(argv[0]);
    Uplo = FIX2INT(argv[1]);
    alpha = NUM2DBL(argv[2]);
    Data_Get_Struct(argv[3], gsl_matrix, A);
    Data_Get_Struct(argv[4], gsl_matrix, B);
    beta = NUM2DBL(argv[5]);
    Data_Get_Struct(argv[6], gsl_matrix, C);
    break;
  default:
    rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 7)", argc);
    break;
  }
  gsl_blas_dsymm(Side, Uplo, alpha, A, B, beta, C);
  if (flag == 1) return Data_Wrap_Struct(cgsl_matrix, 0, gsl_matrix_free, C);
  else return argv[6];
}
示例#15
0
static VALUE con_set_digits(VALUE self, VALUE new_value) {
  decContext *self_ptr;
  Data_Get_Struct(self, decContext, self_ptr);
  self_ptr->digits = FIX2INT(new_value);
  return INT2FIX(self_ptr->digits);
}
示例#16
0
static VALUE attr_get_common(int argc, VALUE *argv, VALUE self, enum datatype datatype)
{
    oci8_base_t *base = DATA_PTR(self);
    VALUE attr_type;
    VALUE strict;
    union {
        ub1 ub1val;
        ub2 ub2val;
        ub4 ub4val;
        ub8 ub8val;
        sb1 sb1val;
        sb2 sb2val;
        sb4 sb4val;
        sb8 sb8val;
        boolean booleanval;
        char *charptr;
        ub1 *ub1ptr;
    } v;
    ub4 size = 0;
    sword rv;

    v.ub8val = MAGIC_NUMBER;
    rb_scan_args(argc, argv, "11", &attr_type, &strict);
    if (argc == 1) {
        strict = Qtrue;
    }
    Check_Type(attr_type, T_FIXNUM);
    rv = OCIAttrGet(base->hp.ptr, base->type, &v, &size, FIX2INT(attr_type), oci8_errhp);
    if (!RTEST(strict)) {
        if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 24328) {
			/* ignore ORA-24328: illegal attribute value */
            return Qnil;
        }
    }
    chker2(rv, base);
    switch (datatype) {
        OCINumber onum;
        static VALUE cOraDate = Qnil;
    case DATATYPE_UB1:
        return INT2FIX(v.ub1val);
    case DATATYPE_UB2:
        return INT2FIX(v.ub2val);
    case DATATYPE_UB4:
        return UINT2NUM(v.ub4val);
    case DATATYPE_UB8:
        return ULL2NUM(v.ub8val);
    case DATATYPE_SB1:
        return INT2FIX(v.sb1val);
    case DATATYPE_SB2:
        return INT2FIX(v.sb2val);
    case DATATYPE_SB4:
        return INT2NUM(v.sb4val);
    case DATATYPE_SB8:
        return LL2NUM(v.sb8val);
    case DATATYPE_BOOLEAN:
        return v.booleanval ? Qtrue : Qfalse;
    case DATATYPE_STRING:
        if (size == 0 && !RTEST(strict)) {
            return Qnil;
        }
        return rb_external_str_new_with_enc(v.charptr, size, oci8_encoding);
    case DATATYPE_BINARY:
        return rb_tainted_str_new(v.charptr, size);
    case DATATYPE_INTEGER:
        if (size > sizeof(onum.OCINumberPart) - 1) {
            rb_raise(rb_eRuntimeError, "Too long size %u", size);
        }
        memset(&onum, 0, sizeof(onum));
        onum.OCINumberPart[0] = size;
        memcpy(&onum.OCINumberPart[1], v.ub1ptr, size);
        return oci8_make_integer(&onum, oci8_errhp);
    case DATATYPE_ORADATE:
        if (NIL_P(cOraDate))
            cOraDate = rb_eval_string("OraDate");
        return rb_funcall(cOraDate, oci8_id_new, 6,
                          INT2FIX((v.ub1ptr[0] - 100) * 100 + (v.ub1ptr[1] - 100)),
                          INT2FIX(v.ub1ptr[2]),
                          INT2FIX(v.ub1ptr[3]),
                          INT2FIX(v.ub1ptr[4] - 1),
                          INT2FIX(v.ub1ptr[5] - 1),
                          INT2FIX(v.ub1ptr[6] - 1));
    }
    return Qnil;
}
示例#17
0
/* call-seq: ox_default_options=(opts)
 *
 * Sets the default options for load and dump.
 * @param [Hash] opts options to change
 * @param [Fixnum] :indent number of spaces to indent each element in an XML document
 * @param [Fixnum] :trace trace level where 0 is silent
 * @param [String] :encoding character encoding for the XML file
 * @param [true|false|nil] :with_dtd include DTD in the dump
 * @param [true|false|nil] :with_instruct include instructions in the dump
 * @param [true|false|nil] :with_xml include XML prolog in the dump
 * @param [true|false|nil] :circular support circular references while dumping
 * @param [true|false|nil] :xsd_date use XSD date format instead of decimal format
 * @param [:object|:generic|:limited|nil] :mode load method to use for XML
 * @param [:strict|:tolerant|:auto_define] :effort set the tolerance level for loading
 * @param [true|false|nil] :symbolize_keys symbolize element attribute keys or leave as Strings
 * @param [:skip_none|:skip_return|:skip_white] determines how to handle white space in text
 * @return [nil]
 */
static VALUE
set_def_opts(VALUE self, VALUE opts) {
    struct _YesNoOpt	ynos[] = {
	{ with_xml_sym, &ox_default_options.with_xml },
	{ with_dtd_sym, &ox_default_options.with_dtd },
	{ with_instruct_sym, &ox_default_options.with_instruct },
	{ xsd_date_sym, &ox_default_options.xsd_date },
	{ circular_sym, &ox_default_options.circular },
	{ symbolize_keys_sym, &ox_default_options.sym_keys },
	{ Qnil, 0 }
    };
    YesNoOpt	o;
    VALUE	v;
    
    Check_Type(opts, T_HASH);

    v = rb_hash_aref(opts, ox_encoding_sym);
    if (Qnil == v) {
	*ox_default_options.encoding = '\0';
    } else {
	Check_Type(v, T_STRING);
	strncpy(ox_default_options.encoding, StringValuePtr(v), sizeof(ox_default_options.encoding) - 1);
#if HAS_ENCODING_SUPPORT
	ox_default_options.rb_enc = rb_enc_find(ox_default_options.encoding);
#elif HAS_PRIVATE_ENCODING
	ox_default_options.rb_enc = rb_str_new2(ox_default_options.encoding);
	rb_gc_register_address(&ox_default_options.rb_enc);
#endif
    }

    v = rb_hash_aref(opts, indent_sym);
    if (Qnil != v) {
	Check_Type(v, T_FIXNUM);
	ox_default_options.indent = FIX2INT(v);
    }

    v = rb_hash_aref(opts, trace_sym);
    if (Qnil != v) {
	Check_Type(v, T_FIXNUM);
	ox_default_options.trace = FIX2INT(v);
    }

    v = rb_hash_aref(opts, mode_sym);
    if (Qnil == v) {
	ox_default_options.mode = NoMode;
    } else if (object_sym == v) {
	ox_default_options.mode = ObjMode;
    } else if (generic_sym == v) {
	ox_default_options.mode = GenMode;
    } else if (limited_sym == v) {
	ox_default_options.mode = LimMode;
    } else {
	rb_raise(ox_parse_error_class, ":mode must be :object, :generic, :limited, or nil.\n");
    }

    v = rb_hash_aref(opts, effort_sym);
    if (Qnil == v) {
	ox_default_options.effort = NoEffort;
    } else if (strict_sym == v) {
	ox_default_options.effort = StrictEffort;
    } else if (tolerant_sym == v) {
	ox_default_options.effort = TolerantEffort;
    } else if (auto_define_sym == v) {
	ox_default_options.effort = AutoEffort;
    } else {
	rb_raise(ox_parse_error_class, ":effort must be :strict, :tolerant, :auto_define, or nil.\n");
    }

    v = rb_hash_aref(opts, skip_sym);
    if (Qnil == v) {
	ox_default_options.skip = NoSkip;
    } else if (skip_none_sym == v) {
	ox_default_options.skip = NoSkip;
    } else if (skip_return_sym == v) {
	ox_default_options.skip = CrSkip;
    } else if (skip_white_sym == v) {
	ox_default_options.skip = SpcSkip;
    } else {
	rb_raise(ox_parse_error_class, ":skip must be :skip_none, :skip_return, :skip_white, or nil.\n");
    }

    for (o = ynos; 0 != o->attr; o++) {
	v = rb_hash_lookup(opts, o->sym);
	if (Qnil == v) {
	    *o->attr = NotSet;
	} else if (Qtrue == v) {
	    *o->attr = Yes;
	} else if (Qfalse == v) {
	    *o->attr = No;
	} else {
	    rb_raise(ox_parse_error_class, "%s must be true or false.\n", rb_id2name(SYM2ID(o->sym)));
	}
    }
    return Qnil;
}
示例#18
0
文件: client.c 项目: brupm/mysql2
static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
  struct nogvl_send_query_args args;
  fd_set fdset;
  int fd, retval;
  int async = 0;
  VALUE opts, defaults, read_timeout;
#ifdef HAVE_RUBY_ENCODING_H
  rb_encoding *conn_enc;
#endif
  struct timeval tv;
  struct timeval* tvp;
  long int sec;
  VALUE result;
  GET_CLIENT(self);

  REQUIRE_OPEN_DB(wrapper);
  args.mysql = wrapper->client;

  // see if this connection is still waiting on a result from a previous query
  if (wrapper->active == 0) {
    // mark this connection active
    wrapper->active = 1;
  } else {
    rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
  }

  defaults = rb_iv_get(self, "@query_options");
  if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
    opts = rb_funcall(defaults, intern_merge, 1, opts);
    rb_iv_set(self, "@query_options", opts);

    if (rb_hash_aref(opts, sym_async) == Qtrue) {
      async = 1;
    }
  } else {
    opts = defaults;
  }

  Check_Type(args.sql, T_STRING);
#ifdef HAVE_RUBY_ENCODING_H
  conn_enc = rb_to_encoding(wrapper->encoding);
  // ensure the string is in the encoding the connection is expecting
  args.sql = rb_str_export_to_enc(args.sql, conn_enc);
#endif

  if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) {
    // an error occurred, we're not active anymore
    MARK_CONN_INACTIVE(self);
    return rb_raise_mysql2_error(wrapper);
  }

  read_timeout = rb_iv_get(self, "@read_timeout");

  tvp = NULL;
  if (!NIL_P(read_timeout)) {
    Check_Type(read_timeout, T_FIXNUM);
    tvp = &tv;
    sec = FIX2INT(read_timeout);
    // TODO: support partial seconds?
    // also, this check is here for sanity, we also check up in Ruby
    if (sec >= 0) {
      tvp->tv_sec = sec;
    } else {
      rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec);
    }
    tvp->tv_usec = 0;
  }

  if (!async) {
    // the below code is largely from do_mysql
    // http://github.com/datamapper/do
    fd = wrapper->client->net.fd;
    for(;;) {
      int fd_set_fd = fd;

#ifdef _WIN32
      WSAPROTOCOL_INFO wsa_pi;
      // dupicate the SOCKET from libmysql
      int r = WSADuplicateSocket(fd, GetCurrentProcessId(), &wsa_pi);
      SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
      // create the CRT fd so ruby can get back to the SOCKET
      fd_set_fd = _open_osfhandle(s, O_RDWR|O_BINARY);
#endif

      FD_ZERO(&fdset);
      FD_SET(fd_set_fd, &fdset);

      retval = rb_thread_select(fd_set_fd + 1, &fdset, NULL, NULL, tvp);

#ifdef _WIN32
      // cleanup the CRT fd
      _close(fd_set_fd);
      // cleanup the duplicated SOCKET
      closesocket(s);
#endif

      if (retval == 0) {
        rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
      }

      if (retval < 0) {
        rb_sys_fail(0);
      }

      if (retval > 0) {
        break;
      }
    }

    result = rb_mysql_client_async_result(self);

    return result;
  } else {
    return Qnil;
  }
}
示例#19
0
/**
 * This method creates a database parameter buffer to be used in creating a
 * database connection.
 *
 * @param  user      A reference to a string containing the user name to be used
 *                   in making the connection.
 * @param  password  A reference to a string containing the password to be used
 *                   in making the connection.
 * @param  options   A hash of the options to be used in making the connection
 *                   to the database.
 * @param  length    A pointer to a short integer that will be set to the
 *                   length of the buffer.
 *
 * @return  A pointer to an array of characters containing the database
 *          parameter buffer.
 *
 */
char *createDPB(VALUE user, VALUE password, VALUE options, short *length) {
  char *dpb = NULL;
  VALUE keys;
  VALUE entry;
  int i;
  short type;

  /* Determine the dpb length and allocate it. */
  *length = 1;
  if(user != Qnil) {
    *length += strlen(StringValuePtr(user)) + 2;
  }
  if(password != Qnil) {
    *length += strlen(StringValuePtr(password)) + 2;
  }
  if(options != Qnil) {
    keys = rb_funcall(options, rb_intern("keys"), 0);

    for(i = 0; i < RARRAY_LEN(keys); i++) {
      type = FIX2INT(rb_ary_entry(keys, i));

      switch (type) {
      case isc_dpb_sql_role_name:
      case isc_dpb_lc_messages:
      case isc_dpb_lc_ctype:
      case isc_dpb_reserved:
      {
        entry = rb_hash_aref(options, INT2FIX(type));
        *length += strlen(StringValuePtr(entry)) + 2;
        break;
      }
      default:
      {
        *length += 3;
      }
      }
    }
  }
  dpb = ALLOC_N(char, *length);

  /* Populate the buffer. */
  if(dpb != NULL) {
    char *ptr = NULL;
    int size = 0;

    /* Fill out the DPB. */
    memset(dpb, 0, *length);
    dpb[0] = isc_dpb_version1;
    ptr    = &dpb[1];

    if(user != Qnil) {
      char *username = StringValuePtr(user);

      size   = strlen(username);
      *ptr++ = isc_dpb_user_name;
      *ptr++ = (char)size;
      memcpy(ptr, username, size);
      ptr    = ptr + size;
    }

    if(password != Qnil) {
      char *userpwd  = StringValuePtr(password);

      size   = strlen(userpwd);
      *ptr++ = isc_dpb_password;
      *ptr++ = (char)size;
      memcpy(ptr, userpwd, size);
      ptr    = ptr + size;
    }

    if(options != Qnil) {
      for(i = 0; i < RARRAY_LEN(keys); i++) {
        type = FIX2INT(rb_ary_entry(keys, i));
        entry = rb_hash_aref(options, INT2FIX(type));

        switch (type) {
        case isc_dpb_sql_role_name:
        case isc_dpb_lc_messages:
        case isc_dpb_lc_ctype:
        case isc_dpb_reserved:
        {
          char *text = StringValuePtr(entry);

          size   = strlen(text);
          *ptr++ = type;
          *ptr++ = (char)size;
          memcpy(ptr, text, size);
          ptr    = ptr + size;
          break;
        }
        default:
        {
          short value;
          switch (TYPE(entry)) {
          case T_FIXNUM: value = FIX2INT(entry);
          case T_NIL: value = 0;
          case T_FALSE: value = 0;
          case T_TRUE: value = 1;
          case T_UNDEF: value = 0;
          case T_FLOAT: value = NUM2INT(entry);
          case T_BIGNUM: value = NUM2INT(entry);
          default: value = 0;
          }

          *ptr++ = type;
          *ptr++ = (char)1;
          *ptr++ = value;
        }
        }
      }
    }
  } else {
    /* Generate an error. */
    rb_raise(rb_eNoMemError,
             "Memory allocation failure creating database DPB.");
  }

  return(dpb);
}
示例#20
0
static void write_container(int ttype, VALUE field_info, VALUE value, VALUE protocol) {
  int sz, i;

  if (ttype == TTYPE_MAP) {
    VALUE keys;
    VALUE key;
    VALUE val;

    Check_Type(value, T_HASH);

    VALUE key_info = rb_hash_aref(field_info, key_sym);
    VALUE keytype_value = rb_hash_aref(key_info, type_sym);
    int keytype = FIX2INT(keytype_value);

    VALUE value_info = rb_hash_aref(field_info, value_sym);
    VALUE valuetype_value = rb_hash_aref(value_info, type_sym);
    int valuetype = FIX2INT(valuetype_value);

    keys = rb_funcall(value, keys_method_id, 0);

    sz = RARRAY_LEN(keys);

    mt->write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz));

    for (i = 0; i < sz; i++) {
      key = rb_ary_entry(keys, i);
      val = rb_hash_aref(value, key);

      if (IS_CONTAINER(keytype)) {
        write_container(keytype, key_info, key, protocol);
      } else {
        write_anything(keytype, key, protocol, key_info);
      }

      if (IS_CONTAINER(valuetype)) {
        write_container(valuetype, value_info, val, protocol);
      } else {
        write_anything(valuetype, val, protocol, value_info);
      }
    }

    mt->write_map_end(protocol);
  } else if (ttype == TTYPE_LIST) {
    Check_Type(value, T_ARRAY);

    sz = RARRAY_LEN(value);

    VALUE element_type_info = rb_hash_aref(field_info, element_sym);
    VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
    int element_type = FIX2INT(element_type_value);

    mt->write_list_begin(protocol, element_type_value, INT2FIX(sz));
    for (i = 0; i < sz; ++i) {
      VALUE val = rb_ary_entry(value, i);
      if (IS_CONTAINER(element_type)) {
        write_container(element_type, element_type_info, val, protocol);
      } else {
        write_anything(element_type, val, protocol, element_type_info);
      }
    }
    mt->write_list_end(protocol);
  } else if (ttype == TTYPE_SET) {
    VALUE items;

    if (TYPE(value) == T_ARRAY) {
      items = value;
    } else {        
      if (rb_cSet == CLASS_OF(value)) {
        items = rb_funcall(value, entries_method_id, 0);
      } else {
        Check_Type(value, T_HASH);
        items = rb_funcall(value, keys_method_id, 0);
      }
    }

    sz = RARRAY_LEN(items);

    VALUE element_type_info = rb_hash_aref(field_info, element_sym);
    VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
    int element_type = FIX2INT(element_type_value);

    mt->write_set_begin(protocol, element_type_value, INT2FIX(sz));

    for (i = 0; i < sz; i++) {
      VALUE val = rb_ary_entry(items, i);
      if (IS_CONTAINER(element_type)) {
        write_container(element_type, element_type_info, val, protocol);
      } else {
        write_anything(element_type, val, protocol, element_type_info);
      }
    }

    mt->write_set_end(protocol);
  } else {
    rb_raise(rb_eNotImpError, "can't write container of type: %d", ttype);
  }
}
示例#21
0
VALUE string_spec_rb_cstr2inum(VALUE self, VALUE str, VALUE inum) {
  int num = FIX2INT(inum);
  return rb_cstr2inum(RSTRING_PTR(str), num);
}
示例#22
0
static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
  VALUE result = Qnil;

  if (ttype == TTYPE_BOOL) {
    result = mt->read_bool(protocol);
  } else if (ttype == TTYPE_BYTE) {
    result = mt->read_byte(protocol);
  } else if (ttype == TTYPE_I16) {
    result = mt->read_i16(protocol);
  } else if (ttype == TTYPE_I32) {
    result = mt->read_i32(protocol);
  } else if (ttype == TTYPE_I64) {
    result = mt->read_i64(protocol);
  } else if (ttype == TTYPE_STRING) {
    result = mt->read_string(protocol);
  } else if (ttype == TTYPE_DOUBLE) {
    result = mt->read_double(protocol);
  } else if (ttype == TTYPE_STRUCT) {
    VALUE klass = rb_hash_aref(field_info, class_sym);
    result = rb_class_new_instance(0, NULL, klass);

    if (rb_obj_is_kind_of(result, thrift_union_class)) {
      rb_thrift_union_read(result, protocol);
    } else {
      rb_thrift_struct_read(result, protocol);
    }
  } else if (ttype == TTYPE_MAP) {
    int i;

    VALUE map_header = mt->read_map_begin(protocol);
    int key_ttype = FIX2INT(rb_ary_entry(map_header, 0));
    int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
    int num_entries = FIX2INT(rb_ary_entry(map_header, 2));

    VALUE key_info = rb_hash_aref(field_info, key_sym);
    VALUE value_info = rb_hash_aref(field_info, value_sym);

    result = rb_hash_new();

    for (i = 0; i < num_entries; ++i) {
      VALUE key, val;

      key = read_anything(protocol, key_ttype, key_info);
      val = read_anything(protocol, value_ttype, value_info);

      rb_hash_aset(result, key, val);
    }

    mt->read_map_end(protocol);
  } else if (ttype == TTYPE_LIST) {
    int i;

    VALUE list_header = mt->read_list_begin(protocol);
    int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
    int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
    result = rb_ary_new2(num_elements);

    for (i = 0; i < num_elements; ++i) {
      rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
    }

    mt->read_list_end(protocol);
  } else if (ttype == TTYPE_SET) {
    VALUE items;
    int i;

    VALUE set_header = mt->read_set_begin(protocol);
    int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
    int num_elements = FIX2INT(rb_ary_entry(set_header, 1));
    items = rb_ary_new2(num_elements);

    for (i = 0; i < num_elements; ++i) {
      rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
    }

    mt->read_set_end(protocol);

    result = rb_class_new_instance(1, &items, rb_cSet);
  } else {
    rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype);
  }

  return result;
}
示例#23
0
VALUE string_spec_rb_str_resize(VALUE self, VALUE str, VALUE size) {
  return rb_str_resize(str, FIX2INT(size));
}
示例#24
0
static VALUE rb_gsl_sf_hydrogenicR(VALUE obj, VALUE n, VALUE l, 
				   VALUE Z, VALUE r)
{
  return rb_float_new(gsl_sf_hydrogenicR(FIX2INT(n), FIX2INT(l),
					   NUM2DBL(Z), NUM2DBL(r)));
}
示例#25
0
VALUE string_spec_rb_str_substr(VALUE self, VALUE str, VALUE beg, VALUE len) {
  return rb_str_substr(str, FIX2INT(beg), FIX2INT(len));
}
示例#26
0
static VALUE t_set_max_timer_count (VALUE self UNUSED, VALUE ct)
{
	evma_set_max_timer_count (FIX2INT (ct));
	return Qnil;
}
示例#27
0
static VALUE t_send_data (VALUE self, VALUE signature, VALUE data, VALUE data_length)
{
	int b = evma_send_data_to_connection (NUM2ULONG (signature), StringValuePtr (data), FIX2INT (data_length));
	return INT2NUM (b);
}
示例#28
0
static VALUE t_set_simultaneous_accept_count (VALUE self UNUSED, VALUE ct)
{
	evma_set_simultaneous_accept_count (FIX2INT (ct));
	return Qnil;
}
示例#29
0
static VALUE t_set_timer_quantum (VALUE self, VALUE interval)
{
  evma_set_timer_quantum (FIX2INT (interval));
  return Qnil;
}
示例#30
0
static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow_id) {
    buffer_t buffer = (buffer_t)NUM2LL(rb_ary_entry(extra, 0));
    VALUE check_keys = rb_ary_entry(extra, 1);

    if (TYPE(key) == T_SYMBOL) {
        // TODO better way to do this... ?
        key = rb_str_new2(rb_id2name(SYM2ID(key)));
    }

    if (TYPE(key) != T_STRING) {
        buffer_free(buffer);
        rb_raise(rb_eTypeError, "keys must be strings or symbols");
    }

    if (!allow_id && strcmp("_id", RSTRING_PTR(key)) == 0) {
        return ST_CONTINUE;
    }

    if (check_keys == Qtrue) {
        int i;
        if (RSTRING_LEN(key) > 0 && RSTRING_PTR(key)[0] == '$') {
            buffer_free(buffer);
            rb_raise(InvalidName, "key must not start with '$'");
        }
        for (i = 0; i < RSTRING_LEN(key); i++) {
            if (RSTRING_PTR(key)[i] == '.') {
                buffer_free(buffer);
                rb_raise(InvalidName, "key must not contain '.'");
            }
        }
    }

    switch(TYPE(value)) {
    case T_BIGNUM:
    case T_FIXNUM:
        {
            if (rb_funcall(value, rb_intern(">"), 1, LL2NUM(9223372036854775807LL)) == Qtrue ||
                rb_funcall(value, rb_intern("<"), 1, LL2NUM(-9223372036854775808ULL)) == Qtrue) {
                buffer_free(buffer);
                rb_raise(rb_eRangeError, "MongoDB can only handle 8-byte ints");
            }
            if (rb_funcall(value, rb_intern(">"), 1, INT2NUM(2147483647L)) == Qtrue ||
                rb_funcall(value, rb_intern("<"), 1, INT2NUM(-2147483648L)) == Qtrue) {
                long long ll_value;
                write_name_and_type(buffer, key, 0x12);
                ll_value = NUM2LL(value);
                SAFE_WRITE(buffer, (char*)&ll_value, 8);
            } else {
                int int_value;
                write_name_and_type(buffer, key, 0x10);
                int_value = NUM2LL(value);
                SAFE_WRITE(buffer, (char*)&int_value, 4);
            }
            break;
        }
    case T_TRUE:
        {
            write_name_and_type(buffer, key, 0x08);
            SAFE_WRITE(buffer, &one, 1);
            break;
        }
    case T_FALSE:
        {
            write_name_and_type(buffer, key, 0x08);
            SAFE_WRITE(buffer, &zero, 1);
            break;
        }
    case T_FLOAT:
        {
            double d = NUM2DBL(value);
            write_name_and_type(buffer, key, 0x01);
            SAFE_WRITE(buffer, (char*)&d, 8);
            break;
        }
    case T_NIL:
        {
            write_name_and_type(buffer, key, 0x0A);
            break;
        }
    case T_HASH:
        {
            write_name_and_type(buffer, key, 0x03);
            write_doc(buffer, value, check_keys);
            break;
        }
    case T_ARRAY:
        {
            buffer_position length_location, start_position, obj_length;
            int items, i;
            VALUE* values;

            write_name_and_type(buffer, key, 0x04);
            start_position = buffer_get_position(buffer);

            // save space for length
            length_location = buffer_save_space(buffer, 4);
            if (length_location == -1) {
                rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
            }

            items = RARRAY_LEN(value);
            values = RARRAY_PTR(value);
            for(i = 0; i < items; i++) {
                char* name;
                VALUE key;
                INT2STRING(&name, i);
                key = rb_str_new2(name);
                write_element(key, values[i], pack_extra(buffer, check_keys));
                free(name);
            }

            // write null byte and fill in length
            SAFE_WRITE(buffer, &zero, 1);
            obj_length = buffer_get_position(buffer) - start_position;
            SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
            break;
        }
    case T_STRING:
        {
            if (strcmp(rb_class2name(RBASIC(value)->klass),
                  "Mongo::Code") == 0) {
                buffer_position length_location, start_position, total_length;
                int length;
                write_name_and_type(buffer, key, 0x0F);

                start_position = buffer_get_position(buffer);
                length_location = buffer_save_space(buffer, 4);
                if (length_location == -1) {
                    rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
                }

                length = RSTRING_LEN(value) + 1;
                SAFE_WRITE(buffer, (char*)&length, 4);
                SAFE_WRITE(buffer, RSTRING_PTR(value), length - 1);
                SAFE_WRITE(buffer, &zero, 1);
                write_doc(buffer, rb_funcall(value, rb_intern("scope"), 0), Qfalse);

                total_length = buffer_get_position(buffer) - start_position;
                SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&total_length, 4);
                break;
            } else {
                int length;
                write_name_and_type(buffer, key, 0x02);
                value = TO_UTF8(value);
                length = RSTRING_LEN(value) + 1;
                SAFE_WRITE(buffer, (char*)&length, 4);
                write_utf8(buffer, value, 0);
                SAFE_WRITE(buffer, &zero, 1);
                break;
            }
        }
    case T_SYMBOL:
        {
            const char* str_value = rb_id2name(SYM2ID(value));
            int length = strlen(str_value) + 1;
            write_name_and_type(buffer, key, 0x0E);
            SAFE_WRITE(buffer, (char*)&length, 4);
            SAFE_WRITE(buffer, str_value, length);
            break;
        }
    case T_OBJECT:
        {
            // TODO there has to be a better way to do these checks...
            const char* cls = rb_class2name(RBASIC(value)->klass);
            if (strcmp(cls, "Mongo::Binary") == 0 ||
                strcmp(cls, "ByteBuffer") == 0) {
                const char subtype = strcmp(cls, "ByteBuffer") ?
                    (const char)FIX2INT(rb_funcall(value, rb_intern("subtype"), 0)) : 2;
                VALUE string_data = rb_funcall(value, rb_intern("to_s"), 0);
                int length = RSTRING_LEN(string_data);
                write_name_and_type(buffer, key, 0x05);
                if (subtype == 2) {
                    const int other_length = length + 4;
                    SAFE_WRITE(buffer, (const char*)&other_length, 4);
                    SAFE_WRITE(buffer, &subtype, 1);
                }
                SAFE_WRITE(buffer, (const char*)&length, 4);
                if (subtype != 2) {
                    SAFE_WRITE(buffer, &subtype, 1);
                }
                SAFE_WRITE(buffer, RSTRING_PTR(string_data), length);
                break;
            }
            if (strcmp(cls, "Mongo::ObjectID") == 0) {
                VALUE as_array = rb_funcall(value, rb_intern("to_a"), 0);
                int i;
                write_name_and_type(buffer, key, 0x07);
                for (i = 0; i < 12; i++) {
                    char byte = (char)FIX2INT(RARRAY_PTR(as_array)[i]);
                    SAFE_WRITE(buffer, &byte, 1);
                }
                break;
            }
            if (strcmp(cls, "Mongo::DBRef") == 0) {
                buffer_position length_location, start_position, obj_length;
                VALUE ns, oid;
                write_name_and_type(buffer, key, 0x03);

                start_position = buffer_get_position(buffer);

                // save space for length
                length_location = buffer_save_space(buffer, 4);
                if (length_location == -1) {
                    rb_raise(rb_eNoMemError, "failed to allocate memory in buffer.c");
                }

                ns = rb_funcall(value, rb_intern("namespace"), 0);
                write_element(rb_str_new2("$ref"), ns, pack_extra(buffer, Qfalse));
                oid = rb_funcall(value, rb_intern("object_id"), 0);
                write_element(rb_str_new2("$id"), oid, pack_extra(buffer, Qfalse));

                // write null byte and fill in length
                SAFE_WRITE(buffer, &zero, 1);
                obj_length = buffer_get_position(buffer) - start_position;
                SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
                break;
            }
            if (strcmp(cls, "Mongo::MaxKey") == 0) {
                write_name_and_type(buffer, key, 0x7f);
                break;
            }
            if (strcmp(cls, "Mongo::MinKey") == 0) {
                write_name_and_type(buffer, key, 0xff);
                break;
            }
            if (strcmp(cls, "DateTime") == 0 || strcmp(cls, "Date") == 0 || strcmp(cls, "ActiveSupport::TimeWithZone") == 0) {
                buffer_free(buffer);
                rb_raise(InvalidDocument, "%s is not currently supported; use a UTC Time instance instead.", cls);
                break;
            }
            if(strcmp(cls, "Complex") == 0 || strcmp(cls, "Rational") == 0 || strcmp(cls, "BigDecimal") == 0) {
                buffer_free(buffer);
                rb_raise(InvalidDocument, "Cannot serialize the Numeric type %s as BSON; only Bignum, Fixnum, and Float are supported.", cls);
                break;
            }
            buffer_free(buffer);
            rb_raise(InvalidDocument, "Cannot serialize an object of class %s into BSON.", cls);
            break;
        }
    case T_DATA:
        {
            const char* cls = rb_class2name(RBASIC(value)->klass);
            if (strcmp(cls, "Time") == 0) {
                double t = NUM2DBL(rb_funcall(value, rb_intern("to_f"), 0));
                long long time_since_epoch = (long long)round(t * 1000);
                write_name_and_type(buffer, key, 0x09);
                SAFE_WRITE(buffer, (const char*)&time_since_epoch, 8);
                break;
            }
            if(strcmp(cls, "BigDecimal") == 0) {
                buffer_free(buffer);
                rb_raise(InvalidDocument, "Cannot serialize the Numeric type %s as BSON; only Bignum, Fixnum, and Float are supported.", cls);
                break;
            }
            buffer_free(buffer);
            rb_raise(InvalidDocument, "Cannot serialize an object of class %s into BSON.", cls);
            break;
        }
    case T_REGEXP:
        {
            VALUE pattern = RREGEXP_SRC(value);
            long flags = RREGEXP(value)->ptr->options;
            VALUE has_extra;

            write_name_and_type(buffer, key, 0x0B);

            pattern = TO_UTF8(pattern);
            write_utf8(buffer, pattern, 1);
            SAFE_WRITE(buffer, &zero, 1);

            if (flags & IGNORECASE) {
                char ignorecase = 'i';
                SAFE_WRITE(buffer, &ignorecase, 1);
            }
            if (flags & MULTILINE) {
                char multiline = 'm';
                SAFE_WRITE(buffer, &multiline, 1);
            }
            if (flags & EXTENDED) {
                char extended = 'x';
                SAFE_WRITE(buffer, &extended, 1);
            }

            has_extra = rb_funcall(value, rb_intern("respond_to?"), 1, rb_str_new2("extra_options_str"));
            if (TYPE(has_extra) == T_TRUE) {
                VALUE extra = rb_funcall(value, rb_intern("extra_options_str"), 0);
                buffer_position old_position = buffer_get_position(buffer);
                SAFE_WRITE(buffer, RSTRING_PTR(extra), RSTRING_LEN(extra));
                qsort(buffer_get_buffer(buffer) + old_position, RSTRING_LEN(extra), sizeof(char), cmp_char);
            }
            SAFE_WRITE(buffer, &zero, 1);

            break;
        }
    default:
        {
            const char* cls = rb_class2name(RBASIC(value)->klass);
            buffer_free(buffer);
            rb_raise(InvalidDocument, "Cannot serialize an object of class %s (type %d) into BSON.", cls, TYPE(value));
            break;
        }
    }
    return ST_CONTINUE;
}