Skip to content

Commit

Permalink
Merge pull request #151 from getaroom/objectid_from_string
Browse files Browse the repository at this point in the history
C extension support for BSON::ObjectId.from_string and BSON::ObjectID.legal?
  • Loading branch information
Brandon Black committed Jan 22, 2013
2 parents 8952e34 + f13c026 commit f4f8c78
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions ext/cbson/cbson.c
Expand Up @@ -93,6 +93,7 @@ static VALUE OrderedHash;
static VALUE InvalidKeyName;
static VALUE InvalidStringEncoding;
static VALUE InvalidDocument;
static VALUE InvalidObjectId;
static VALUE DigestMD5;
static VALUE RB_HASH;

Expand Down Expand Up @@ -924,6 +925,64 @@ static VALUE method_deserialize(VALUE self, VALUE bson) {
return elements_to_hash(buffer, remaining);
}

static int legal_objectid_str(VALUE str) {
int i;

if (TYPE(str) != T_STRING) {
return 0;
}

if (RSTRING_LEN(str) != 24) {
return 0;
}

for(i = 0; i < 24; i++) {
char c = RSTRING_PTR(str)[i];

if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) {
return 0;
}
}

return 1;
}

static VALUE objectid_legal(VALUE self, VALUE str)
{
if (legal_objectid_str(str))
return Qtrue;
return Qfalse;
}

static char hexbyte( char hex ) {
if (hex >= '0' && hex <= '9')
return (hex - '0');
else if (hex >= 'A' && hex <= 'F')
return (hex - 'A' + 10);
else if (hex >= 'a' && hex <= 'f')
return (hex - 'a' + 10);
else
return 0x0;
}

static VALUE objectid_from_string(VALUE self, VALUE str)
{
VALUE oid;
int i;

if (!legal_objectid_str(str)) {
rb_raise(InvalidObjectId, "illegal ObjectId format: %s", RSTRING_PTR(str));
}

oid = rb_ary_new2(12);

for(i = 0; i < 12; i++) {
rb_ary_store(oid, i, INT2FIX( (unsigned)(hexbyte( RSTRING_PTR(str)[2*i] ) << 4 ) | hexbyte( RSTRING_PTR(str)[2*i + 1] )));
}

return rb_class_new_instance(1, &oid, ObjectId);
}

static VALUE objectid_generate(int argc, VALUE* args, VALUE self)
{
VALUE oid;
Expand Down Expand Up @@ -1002,6 +1061,7 @@ void Init_cbson() {
InvalidKeyName = rb_const_get(bson, rb_intern("InvalidKeyName"));
InvalidStringEncoding = rb_const_get(bson, rb_intern("InvalidStringEncoding"));
InvalidDocument = rb_const_get(bson, rb_intern("InvalidDocument"));
InvalidObjectId = rb_const_get(bson, rb_intern("InvalidObjectId"));
rb_require("bson/ordered_hash");
OrderedHash = rb_const_get(bson, rb_intern("OrderedHash"));
RB_HASH = rb_const_get(bson, rb_intern("Hash"));
Expand All @@ -1018,6 +1078,8 @@ void Init_cbson() {
Digest = rb_const_get(rb_cObject, rb_intern("Digest"));
DigestMD5 = rb_const_get(Digest, rb_intern("MD5"));

rb_define_singleton_method(ObjectId, "legal?", objectid_legal, 1);
rb_define_singleton_method(ObjectId, "from_string", objectid_from_string, 1);
rb_define_method(ObjectId, "generate", objectid_generate, -1);

if (gethostname(hostname, MAX_HOSTNAME_LENGTH) != 0) {
Expand Down

0 comments on commit f4f8c78

Please sign in to comment.