AnyMongo
view release on metacpan or search on metacpan
mongo_support.c view on Meta::CPAN
/*
* Copyright 2009 10gen, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mongo_support.h"
#ifdef WIN32
#include <memory.h>
#endif
#include "regcomp.h"
static stackette* check_circular_ref(void *ptr, stackette *stack);
static int isUTF8(const char*, int);
static void serialize_regex(buffer*, const char*, REGEXP*, int is_insert);
static void serialize_regex_flags(buffer*, SV*);
static void append_sv (buffer *buf, const char *key, SV *sv, stackette *stack, int is_insert);
int perl_mongo_inc = 0;
// void
// perl_mongo_call_xs (pTHX_ void (*subaddr) (pTHX_ CV *), CV *cv, SV **mark)
// {
// dSP;
// PUSHMARK (mark);
// (*subaddr) (aTHX_ cv);
// PUTBACK;
// }
SV *
perl_mongo_call_reader (SV *self, const char *reader)
{
dSP;
SV *ret;
I32 count;
ENTER;
SAVETMPS;
PUSHMARK (SP);
XPUSHs (self);
PUTBACK;
count = call_method (reader, G_SCALAR);
SPAGAIN;
if (count != 1) {
croak ("reader didn't return a value");
}
ret = POPs;
SvREFCNT_inc (ret);
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
SV *
perl_mongo_call_method (SV *self, const char *method, int num, ...)
{
dSP;
SV *ret;
I32 count;
va_list args;
ENTER;
SAVETMPS;
PUSHMARK (SP);
XPUSHs (self);
va_start( args, num );
for( ; num > 0; num-- ) {
XPUSHs (va_arg( args, SV* ));
}
va_end( args );
PUTBACK;
count = call_method (method, G_SCALAR);
SPAGAIN;
if (count != 1) {
croak ("method didn't return a value");
}
ret = POPs;
SvREFCNT_inc (ret);
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
SV *
perl_mongo_call_function (const char *func, int num, ...)
{
dSP;
SV *ret;
I32 count;
va_list args;
ENTER;
SAVETMPS;
PUSHMARK (SP);
va_start( args, num );
for( ; num > 0; num-- ) {
XPUSHs (va_arg( args, SV* ));
}
va_end( args );
PUTBACK;
count = call_pv (func, G_SCALAR);
SPAGAIN;
if (count != 1) {
croak ("method didn't return a value");
}
ret = POPs;
SvREFCNT_inc (ret);
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
void
perl_mongo_attach_ptr_to_instance (SV *self, void *ptr)
{
sv_magic (SvRV (self), 0, PERL_MAGIC_ext, (const char *)ptr, 0);
}
void *
perl_mongo_get_ptr_from_instance (SV *self)
{
MAGIC *mg;
if (!self || !SvOK (self) || !SvROK (self)
|| !(mg = mg_find (SvRV (self), PERL_MAGIC_ext))) {
croak ("invalid object");
}
return mg->mg_ptr;
}
SV *
perl_mongo_construct_instance (const char *klass, ...)
{
SV *ret;
va_list ap;
va_start (ap, klass);
ret = perl_mongo_construct_instance_va (klass, ap);
va_end(ap);
return ret;
}
SV *
perl_mongo_construct_instance_va (const char *klass, va_list ap)
{
dSP;
SV *ret;
I32 count;
char *init_arg;
ENTER;
SAVETMPS;
PUSHMARK (SP);
mXPUSHp (klass, strlen (klass));
while ((init_arg = va_arg (ap, char *))) {
mXPUSHp (init_arg, strlen (init_arg));
XPUSHs (va_arg (ap, SV *));
}
PUTBACK;
count = call_method ("new", G_SCALAR);
SPAGAIN;
if (count != 1) {
croak ("constructor didn't return an instance");
}
ret = POPs;
SvREFCNT_inc (ret);
PUTBACK;
FREETMPS;
LEAVE;
return ret;
}
SV *
perl_mongo_construct_instance_with_magic (const char *klass, void *ptr, ...)
{
SV *ret;
va_list ap;
va_start (ap, ptr);
ret = perl_mongo_construct_instance_va (klass, ap);
va_end (ap);
perl_mongo_attach_ptr_to_instance (ret, ptr);
return ret;
}
static SV *bson_to_av (buffer *buf);
void perl_mongo_make_oid(char *twelve, char *twenty4) {
int i;
char *id_str = twelve;
char *movable = twenty4;
for(i=0; i<12; i++) {
int x = *id_str;
if (*id_str < 0) {
x = 256 + *id_str;
}
sprintf(movable, "%02x", x);
movable += 2;
id_str++;
}
twenty4[24] = '\0';
}
static SV *
oid_to_sv (buffer *buf)
{
HV *stash, *id_hv;
char oid_s[25];
perl_mongo_make_oid(buf->pos, oid_s);
id_hv = newHV();
hv_store(id_hv, "value", strlen("value"), newSVpvn(oid_s, 24), 0);
stash = gv_stashpv("AnyMongo::BSON::OID", 0);
return sv_bless(newRV_noinc((SV *)id_hv), stash);
}
static SV *
elem_to_sv (int type, buffer *buf)
{
SV *value = 0;
SV *flag = get_sv("AnyMongo::BSON::utf8_flag_on", 0);
mongo_support.c view on Meta::CPAN
case BSON_SYMBOL:
case BSON_STRING: {
int len = MONGO_32(*((int*)buf->pos));
buf->pos += INT_32;
// this makes a copy of the buffer
// len includes \0
value = newSVpvn(buf->pos, len-1);
if (!flag || !SvIOK(flag) || SvIV(flag) != 0) {
SvUTF8_on(value);
}
buf->pos += len;
break;
}
case BSON_OBJECT: {
value = perl_mongo_bson_to_sv(buf);
break;
}
case BSON_ARRAY: {
value = bson_to_av(buf);
break;
}
case BSON_BINARY: {
int len = MONGO_32(*(int*)buf->pos);
char type;
buf->pos += INT_32;
// we should do something with type
type = *buf->pos++;
if (type == 2) {
int len2 = MONGO_32(*(int*)buf->pos);
if (len2 == len - 4) {
len = len2;
buf->pos += INT_32;
}
}
value = newSVpvn(buf->pos, len);
buf->pos += len;
break;
}
case BSON_BOOL: {
dSP;
char d = *buf->pos++;
int count;
SV *use_bool = get_sv("AnyMongo::BSON::use_boolean", 0);
if (!use_bool) {
value = newSViv(d);
break;
}
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
if (d) {
count = call_pv("boolean::true", G_SCALAR);
}
else {
count = call_pv("boolean::false", G_SCALAR);
}
SPAGAIN;
if (count == 1)
value = newSVsv(POPs);
if (count != 1 || !SvOK(value)) {
value = newSViv(d);
}
PUTBACK;
FREETMPS;
break;
}
case BSON_UNDEF:
case BSON_NULL: {
value = newSV(0);
break;
}
case BSON_INT: {
value = newSViv(MONGO_32(*((int*)buf->pos)));
buf->pos += INT_32;
break;
}
case BSON_LONG: {
#if defined(USE_64_BIT_INT)
value = newSViv(MONGO_64(*((int64_t*)buf->pos)));
#else
value = newSVnv((double)MONGO_64(*((int64_t*)buf->pos)));
#endif
buf->pos += INT_64;
break;
}
case BSON_DATE: {
int64_t ms_i = MONGO_64(*(int64_t*)buf->pos);
SV *datetime, *ms, **heval;
HV *named_params;
buf->pos += INT_64;
ms_i /= 1000;
datetime = sv_2mortal(newSVpv("DateTime", 0));
ms = newSViv(ms_i);
named_params = newHV();
heval = hv_store(named_params, "epoch", strlen("epoch"), ms, 0);
value = perl_mongo_call_function("DateTime::from_epoch", 2, datetime,
sv_2mortal(newRV_inc(sv_2mortal((SV*)named_params))));
break;
}
case BSON_REGEX: {
SV *pattern, *regex, *regex_ref;
HV *stash;
U32 flags = 0;
REGEXP *re;
#if PERL_REVISION==5 && PERL_VERSION<=8
PMOP pm;
STRLEN len;
char *pat;
#endif
pattern = sv_2mortal(newSVpv(buf->pos, 0));
buf->pos += strlen(buf->pos)+1;
while(*(buf->pos) != 0) {
switch(*(buf->pos)) {
case 'l':
flags |= PMf_LOCALE;
break;
case 'm':
flags |= PMf_MULTILINE;
( run in 0.793 second using v1.01-cache-2.11-cpan-437f7b0c052 )