diff --git a/ext/v8/bool.h b/ext/v8/bool.h index 6119558..c431cec 100644 --- a/ext/v8/bool.h +++ b/ext/v8/bool.h @@ -1,19 +1,59 @@ +// -*- mode: c++ -*- #ifndef RR_BOOL #define RR_BOOL namespace rr { + /** + * Seemlessly convert between Ruby booleans and C/C++. + * + * The `Bool` equivalence lets you plop in a Ruby boolean anywhere + * you might need a C++ boolean, and, by the same token, drop in a + * C/C++ boolean anywhere you might need a Ruby boolean. E.g. + * + * // Ruby -> C/C++ + * if (Bool(Qtrue)) { + * //always executed + * } + * + * // C/C++ -> Ruby + * if (RTEST(Bool(true))) { + * //always executed + * } + */ class Bool : public Equiv { public: + /** + * Construct a Bool from a Ruby VALUE + */ Bool(VALUE val) : Equiv(val) {} + + /** + * Constructo a Bool from a C/C++ boo. It is immediately + * converted into the corresponding; + */ Bool(bool b) : Equiv(b ? Qtrue : Qfalse) {} + + /** + * Construct a Bool from JavaScript. + */ Bool(v8::Handle b) : Equiv(b->Value() ? Qtrue : Qfalse) {} + /** + * Coerce this into a native C/C++ bool. Since it is stored as a + * Ruby VALUE, this is just a simple RTEST. + * + * bool b = Bool(true); // true + * b = Bool(false); // false + * b = Bool(Qtrue); // true + * b = Bool(Qfalse); // false + * b = Bool(Qnil); // false + * b = Bool(rb_cObject); // true + */ inline operator bool() { return RTEST(value); } }; - } #endif diff --git a/ext/v8/equiv.h b/ext/v8/equiv.h index c35455a..d7a9f30 100644 --- a/ext/v8/equiv.h +++ b/ext/v8/equiv.h @@ -1,11 +1,43 @@ +// -*- mode: c++ -*- #ifndef RR_EQUIV #define RR_EQUIV namespace rr { + /** + * Defines an equivalence between a primitive Ruby and C/C++ types so + * that they can be used inter-changeably. In other words: given a + * Ruby `VALUE` it can convert it to a C/C++ type, and given a C/C++ + * type, it can convert it to a Ruby type. For example, the Boolean + * equivalence class defines the relationship between Ruby booleans + * and C/++ booleans, and can be used to place a Ruby VALUE anywhere + * you might need a C/C++ boolean such as an "if" statement: + * + * if (rr::Bool(Qnil)) { // + * throw "not going to happen!"; + * } + * + * This is the superclass of all equivalences classes, + * and is not meant to be instantiated. + * + * Internally, `Equiv`s are always stored as a Ruby `VALUE`, and so + * part of the job of the subclass is to have an appropriate + * constructor that converts the C/C++ type to a `VALUE` + */ class Equiv { public: + /** + * Constructs an `Equiv` from a Ruby VALUE. It's up to the + * subclass to determine what it can be converted to. + */ Equiv(VALUE val) : value(val) {} + + /** + * Converts this `Equiv` into a Ruby `VALUE`. This, of course, is + * just the value of the internal storage. In the Boolean example: + * + * VALUE val = Bool(Qnil); //=> Qnil; + */ inline operator VALUE() { return value; } protected: diff --git a/ext/v8/uint32.h b/ext/v8/uint32.h index c25986b..727776b 100644 --- a/ext/v8/uint32.h +++ b/ext/v8/uint32.h @@ -1,13 +1,41 @@ +// -*- mode: c++ -*- #ifndef RR_UINT32 #define RR_UINT32 namespace rr { + /** + * Converts between Ruby `Number` and the C/C++ `uint32_t`. + * + * This allows you to easily pass in `uint32_t` values whenever a + * Ruby VALUE is expected (such as a method call) E.g. + * + * uint_32_t myInt = 5; + * rb_funcall(UInt32(myInt), rb_intern("to_s")); //=> + * + * It also converts a Ruby `VALUE` into its corresponding + * `uint32_t`: + * + * uint_32_t myInt = UInt32(rb_eval_string("5")); //=> 5 + * + * Like all `Equiv`s, it stores itself internally as a Ruby `VALUE` + */ class UInt32 : public Equiv { public: + /** + * Construct a UInt32 from a Ruby `VALUE` + */ UInt32(VALUE val) : Equiv(val) {} + + /** + * Construct a UInt32 from a `uint32_t` by converting it into its + * corresponding `VALUE`. + */ UInt32(uint32_t ui) : Equiv(UINT2NUM(ui)) {} + /** + * Coerce the Ruby `VALUE` into a `uint32_t`. + */ inline operator uint32_t() { return RTEST(value) ? NUM2UINT(value) : 0; }