1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

Add a docs target & worked on documentation. Changed pushString() to

std::string, and added pushUnknown() to conversion destination classes
This commit is contained in:
Bill Robertson 2009-10-17 23:45:02 -04:00
parent 2c3d4e19b6
commit 68c968e109
9 changed files with 1707 additions and 210 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ v8.bundle
*.o
*.log
*~
docs/cpp/html/*

1514
Doxyfile Normal file

File diff suppressed because it is too large Load diff

18
docs/data_conversion.txt Normal file
View file

@ -0,0 +1,18 @@
Short list of types that a receiver should handle:
type expected method
-------------------------------
<null> pushNull
boolean pushBool
int64 pushInt (overloaded on 64-bit int)
double pushDouble
const std::string& pushString
??? pushUndefined
int32 pushInt (overloaded on 32-bit int)
for lack of any better ideas have these functions return true on
success and false on error
--
should add more later.

View file

@ -12,5 +12,13 @@ makefile.print <<EOF
test: all
@echo running spec...
spec -O spec/spec.opts spec/therubyracer_spec.rb
docs/cpp:
mkdir -p docs/cpp
docs: all docs/cpp
@echo Generate C++ docs to docs/cpp/html
doxygen Doxyfile
EOF
end

View file

@ -5,3 +5,6 @@ StringDest::StringDest() {
StringDest::~StringDest(){
}
const std::string StringDest::TRUE("true");
const std::string StringDest::FALSE("false");

View file

@ -4,49 +4,69 @@
#include "v8.h"
#include <string>
/**
* StringDest is a data type conversion destination that converts
* any argument into a string. It should have all methods listed
* in data_conversion.txt so it can be used as a template argument
* for a conversion source class.
*/
class StringDest {
public:
StringDest();
~StringDest();
std::string pushString(const char* value, const char* name=0) {
std::string convertedValue(value);
return convertedValue;
}
public:
StringDest();
~StringDest();
/*
const char* pushInt(int32_t value, const char* name=0) {
char buffer[64];
std::sprintf(buffer, "%d", value);
convertedValue = buffer;
return convertedValue.c_str();
}
*/
std::string pushString(const std::string& value, const char* name=0) {
return value;
}
std::string pushInt(int64_t value, const char* name=0) {
char buffer[64];
std::sprintf(buffer, "%lld", value);
std::string convertedValue(buffer);
return convertedValue;
}
#ifdef FIGURED_OUT_INT_ISSUES
const char* pushInt(int32_t value, const char* name=0) {
char buffer[64];
std::sprintf(buffer, "%d", value);
convertedValue = buffer;
return convertedValue.c_str();
}
#endif
std::string pushDouble(double value, const char* name=0) {
char buffer[64];
std::sprintf(buffer, "%g", value);
std::string convertedValue(buffer);
return convertedValue;
}
std::string pushInt(int64_t value, const char* name=0) {
char buffer[64];
std::sprintf(buffer, "%lld", value);
std::string convertedValue(buffer);
return convertedValue;
}
std::string pushBool(bool value, const char* name=0) {
std::string convertedValue(value ? "true" : "false");
return convertedValue;
}
std::string pushDouble(double value, const char* name=0) {
char buffer[64];
std::sprintf(buffer, "%g", value);
std::string convertedValue(buffer);
return convertedValue;
}
std::string pushNull(const char* name=0) {
return "";
}
std::string pushBool(bool value, const char* name=0) {
std::string convertedValue(value ? TRUE : FALSE);
return convertedValue;
}
std::string pushNull(const char* name=0) {
return ""; // this kind of sucks
}
std::string pushUndefined(const char* name=0) {
return "undefined"; // this too
}
private:
/**
* constant "true" used for pushBool
*/
static const std::string TRUE;
/**
* constant "false" used for pushBool
*/
static const std::string FALSE;
};
#endif

View file

@ -5,60 +5,88 @@
#include <stdio.h>
#include <string>
template<class T, class R> class RubyDataSource {
/**
* A RubyValueSource takes a Destination class and a return
* type as a template argument, it converts a Ruby Value to
* the appropriate intermediate type and feed it to an
* instance Destination type.
*
* The destination type should have a default constructor,
* and provide the methods detailed in data_conversion.txt
* \tparam DEST destination type for the converted data
* \tparam RET is the return type of T's methods
*/
template<class DEST, class RET> class RubyValueSource {
T dest;
/**
* An instance of the destination class
*/
DEST dest;
public:
RubyDataSource() {}
~RubyDataSource() {}
public:
RubyValueSource() {}
~RubyValueSource() {}
R push(VALUE& value, const char* name=0) {
switch (TYPE(value)) {
case T_FIXNUM:
return dest.pushInt(FIX2INT(value), name);
case T_FLOAT:
return dest.pushDouble(NUM2DBL(value), name);
case T_STRING:
return dest.pushString(RSTRING(value)->ptr, name);
case T_NIL:
return dest.pushNull(name);
case T_TRUE:
return dest.pushBool(true, name);
case T_FALSE:
return dest.pushBool(false, name);
RET push(VALUE& value, const char* name=0) {
switch (TYPE(value)) {
case T_FIXNUM:
return dest.pushInt(FIX2INT(value), name);
case T_FLOAT:
return dest.pushDouble(NUM2DBL(value), name);
case T_STRING:
return convertString(value, name);
case T_NIL:
return dest.pushNull(name);
case T_TRUE:
return dest.pushBool(true, name);
case T_FALSE:
return dest.pushBool(false, name);
}
return dest.pushUndefined(name);
}
private:
RET convertString(VALUE& value, const char* name=0) {
std::string stringValue(RSTRING(value)->ptr);
return dest.pushString(stringValue, name);
}
return false;
}
};
/**
* A RubyDest class receives on of the types defined in
* data_conversion.txt, and converts it to the appropriate
* Ruby VALUE.
*/
class RubyDest {
public:
RubyDest();
~RubyDest();
public:
RubyDest();
~RubyDest();
VALUE pushString(std::string value, const char* name=0) {
return rb_str_new2(value.c_str());
}
VALUE pushString(const std::string& value, const char* name=0) {
return rb_str_new2(value.c_str());
}
VALUE pushInt(int64_t value, const char* name=0) {
return INT2FIX(value);
}
VALUE pushInt(int64_t value, const char* name=0) {
return INT2FIX(value);
}
VALUE pushDouble(double value, const char* name=0) {
return rb_float_new(value);
}
VALUE pushDouble(double value, const char* name=0) {
return rb_float_new(value);
}
VALUE pushBool(bool value, const char* name=0) {
return value ? Qtrue : Qfalse;
}
VALUE pushNull(const char* name=0) {
return Qnil;
}
VALUE pushBool(bool value, const char* name=0) {
return value ? Qtrue : Qfalse;
}
VALUE pushNull(const char* name=0) {
return Qnil;
}
VALUE pushUndefined(const char* name=0) {
return Qnil;
}
};

View file

@ -1,16 +0,0 @@
Short list of types that a receiver should handle:
type expected method
-------------------------------
<null> pushNull
boolean pushBool
int32 pushInt (overloaded on 32-bit int)
int64 pushInt (overloaded on 64-bit int)
double pushDouble
const char* pushString
for lack of any better ideas have these functions return true on
success and false on error
--
should add more later.

159
v8.cpp
View file

@ -3,16 +3,24 @@
#include "generic_data.h"
#include <stdio.h>
typedef struct v8_context {
v8_context() : context(v8::Context::New()) {}
~v8_context() {
context.Dispose();
}
v8::Persistent<v8::Context> context;
/**
* struct that encapsulates a v8 context. this
* object's lifetime matches the lifetime of
* the ruby v8 context item.
*/
typedef struct v8_context {
v8_context() : context(v8::Context::New()) {}
~v8_context() {
context.Dispose();
}
v8::Persistent<v8::Context> context;
} v8_context;
extern "C" {
void Init_v8();
/**
* ruby init method for the extension
*/
void Init_v8();
}
VALUE v8_allocate(VALUE clazz);
@ -25,12 +33,12 @@ VALUE rb_mModule;
VALUE rb_cV8;
extern "C" {
void Init_v8() {
rb_mModule = rb_define_module("V8");
rb_cV8 = rb_define_class_under(rb_mModule, "Context", rb_cObject);
rb_define_alloc_func(rb_cV8, v8_allocate);
rb_define_method(rb_cV8, "eval", (VALUE(*)(...)) eval, 1);
}
void Init_v8() {
rb_mModule = rb_define_module("V8");
rb_cV8 = rb_define_class_under(rb_mModule, "Context", rb_cObject);
rb_define_alloc_func(rb_cV8, v8_allocate);
rb_define_method(rb_cV8, "eval", (VALUE(*)(...)) eval, 1);
}
}
VALUE v8_allocate(VALUE clazz) {
@ -46,113 +54,26 @@ void v8_free(v8_context *s) {
delete s;
}
/**
* eval a javascript. Currently, return
* types can only be primitive types.
* @param self ruby handle to a v8_context struct
* @param javascript, should be a string
* @return the result of evaluating the script, if
* it can be converted
*/
VALUE eval(VALUE self, VALUE javascript) {
v8_context* s = 0;
Data_Get_Struct(self, struct v8_context, s);
v8::Context::Scope context_scope(s->context);
v8::HandleScope handle_scope;
v8_context* s = 0;
Data_Get_Struct(self, struct v8_context, s);
v8::Context::Scope context_scope(s->context);
v8::HandleScope handle_scope;
RubyDataSource<StringDest, std::string> tostring;
const std::string text(tostring.push(javascript));
v8::Handle<v8::String> source = v8::String::New(text.c_str());
v8::Handle<v8::Script> script = v8::Script::Compile(source);
v8::Handle<v8::Value> local_result = script->Run();
V8HandleSource<RubyDest, VALUE> toValue;
return toValue.push(local_result);
RubyValueSource<StringDest, std::string> tostring;
const std::string text(tostring.push(javascript));
v8::Handle<v8::String> source = v8::String::New(text.c_str());
v8::Handle<v8::Script> script = v8::Script::Compile(source);
v8::Handle<v8::Value> local_result = script->Run();
V8HandleSource<RubyDest, VALUE> toValue;
return toValue.push(local_result);
}
// v8.c: In function Init_v8:
// v8.c:5: error: rb_mV8 undeclared (first use in this function)
// v8.c:5: error: (Each undeclared identifier is reported only once
// v8.c:5: error: for each function it appears in.)
// make: *** [v8.o] Error 1
// #include "glue.h"
//
// VALUE rb_mV8;
// VALUE rb_cContext;
//
//
// VALUE rv8_Context__dealloc(VALUE self) {
// printf("dealloc\n");
// void * context;
// Data_Get_Struct(self, void, context);
// return Qnil;
// }
//
// VALUE rv8_Context__alloc() {
// printf("alloc\n");
// void * context = cpp_v8_Context__new();
// VALUE instance = Data_Wrap_Struct(rb_cContext, -1, rv8_Context__dealloc, context);
// rb_obj_init(instance);
// return instance;
// }
//
// VALUE rv8_Context_pooh(VALUE self) {
// int * i;
// Data_Get_Struct(self, int , i);
// return INT2NUM(*i);
// }
//
// void Init_v8() {
// rb_mV8 = rb_define_module("V8");
// rb_cContext = rb_define_class_under(rb_mV8, "Context", rb_cObject);
// rb_define_alloc_func(rb_cContext, rv8_Context__alloc);
// }
// #include <v8.h>
// #include <stdio.h>
//
//
// using namespace v8;
//
// extern "C" {
// #include "ruby.h"
//
// VALUE rv8;
// VALUE rv8_Context;
//
// VALUE rv8_Context_new(...);
// VALUE rv8_Context_enter(VALUE self);
//
// VALUE rv8_Context__alloc(VALUE klass);
// void rv8_Context_free(VALUE robj);
//
// void Init_rchassis() {
// rv8 = rb_define_module("V8");
// rv8_Context = rb_define_class_under(rv8, "Context", rb_cObject);
// rb_define_alloc_func(rv8_Context, rv8_Context__alloc);
// rb_define_method(rv8_Context, "enter", rv8_Context_enter, 0);
// }
//
// VALUE rv8_Context__alloc(VALUE klass) {
// Persistent<Context> context = Context::New();
// VALUE robj = Data_Wrap_Struct(rv8_Context, -1, rv8_Context_free, &context);
// return robj;
// }
//
// VALUE rv8_Context_enter(VALUE self) {
//
// }
//
// void rv8_Context_free(VALUE robj) {
// Persistent<Context> * context;
// printf("Let my people go!");
// Data_Get_Struct(robj, Persistent<Context> , context);
// printf("Get my people!");
// context->Dispose();
// }
//
// // VALUE rv8_Context_open(...) {
// // HandleScope scopes;
// // Persistent<Context> context = Context::New();
// // Context::Scope scope(context);
// // VALUE result = rb_yield(Qnil);
// // context.Dispose();
// // return result;
// // }
// }