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

document the primitive equivalence classes

This commit is contained in:
Charles Lowell 2015-06-29 19:06:12 +03:00
parent 93ae00ce08
commit d1009c1429
3 changed files with 101 additions and 1 deletions

View file

@ -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<v8::Boolean> 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

View file

@ -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:

View file

@ -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")); //=> <String "5">
*
* 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;
}