Skip to content

Commit

Permalink
* Finish GridFS support
Browse files Browse the repository at this point in the history
* Expand BSON type support


git-svn-id: http://luamongo.googlecode.com/svn/branches/gridfs@28 17e306f6-9439-11de-a13a-71b910e68cc8
  • Loading branch information
nrich@ii.net committed Jul 25, 2010
1 parent c09155b commit 41c68de
Show file tree
Hide file tree
Showing 7 changed files with 375 additions and 42 deletions.
4 changes: 3 additions & 1 deletion Makefile
Expand Up @@ -8,7 +8,7 @@ OUTLIB=mongo.so

LDFLAGS= $(LIBS)

OBJS = main.o mongo_bsontypes.o mongo_connection.o mongo_cursor.o mongo_gridfile.o mongo_gridfs.o mongo_query.o utils.o
OBJS = main.o mongo_bsontypes.o mongo_connection.o mongo_cursor.o mongo_gridfile.o mongo_gridfs.o mongo_gridfschunk.o mongo_query.o utils.o

all: luamongo

Expand Down Expand Up @@ -36,6 +36,8 @@ mongo_gridfile.o: mongo_gridfile.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
mongo_gridfs.o: mongo_gridfs.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
mongo_gridfschunk.o: mongo_gridfschunk.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
mongo_query.o: mongo_query.cpp common.h utils.h
$(CC) -c -o $@ $< $(CFLAGS)
mongo_bsontypes.o: mongo_bsontypes.cpp common.h
Expand Down
12 changes: 10 additions & 2 deletions common.h
Expand Up @@ -4,17 +4,25 @@
#define LUAMONGO_QUERY "mongo.Query"
#define LUAMONGO_GRIDFS "mongo.GridFS"
#define LUAMONGO_GRIDFILE "mongo.GridFile"
#define LUAMONGO_GRIDFSCHUNK "mongo.GridFSChunk"

#define LUAMONGO_ERR_CONNECTION_FAILED "Connection failed: %s"
#define LUAMONGO_ERR_GRIDFS_FAILED "GridFS failed: %s"
#define LUAMONGO_ERR_GRIDFSCHUNK_FAILED "GridFSChunk failed: %s"
#define LUAMONGO_ERR_QUERY_FAILED "Query failed: %s"
#define LUAMONGO_ERR_INSERT_FAILED "Insert failed: %s"
#define LUAMONGO_ERR_CONNECT_FAILED "Connection to %s failed: %s"
#define LUAMONGO_ERR_COUNT_FAILED "Count failed: %s"
#define LUAMONGO_ERR_REMOVE_FAILED "Remove failed: %s"
#define LUAMONGO_ERR_UPDATE_FAILED "Update failed: %s"
#define LUAMONGO_UNSUPPORTED_BSON_TYPE "Unsupported BSON type"
#define LUAMONGO_UNSUPPORTED_BSON_TYPE "Unsupported BSON type `%s'"
#define LUAMONGO_UNSUPPORTED_LUA_TYPE "Unsupported Lua type `%s'"
#define LUAMONGO_REQUIRES_JSON_OR_TABLE "JSON string or Lua table required"
#define LUAMONGO_NOT_IMPLEMENTED "Not implemented: %s.%s"
#define LUAMONGO_ERR_CALLING "Errori calling %s.%s: %s"
#define LUAMONGO_ERR_CALLING "Error calling %s.%s: %s"

#if defined(MONGO_1_5)
#define CHUNK GridFSChunk
#else
#define CHUNK Chunk
#endif
2 changes: 2 additions & 0 deletions main.cpp
Expand Up @@ -42,6 +42,7 @@ extern int mongo_cursor_register(lua_State *L);
extern int mongo_query_register(lua_State *L);
extern int mongo_gridfs_register(lua_State *L);
extern int mongo_gridfile_register(lua_State *L);
extern int mongo_gridfschunk_register(lua_State *L);

/*
*
Expand All @@ -59,6 +60,7 @@ LM_EXPORT int luaopen_mongo(lua_State *L) {

mongo_gridfs_register(L);
mongo_gridfile_register(L);
mongo_gridfschunk_register(L);

/*
* push the created table to the top of the stack
Expand Down
212 changes: 190 additions & 22 deletions mongo_bsontypes.cpp
Expand Up @@ -15,28 +15,8 @@ extern "C" {

using namespace mongo;

// TODO:
// all of this should be in Lua so it can get JIT wins
// bind the bson typeids
// each type could have its cached metatable (from registry)

// all these types are represented as tables
// the metatable entry __bsontype dictates the type
// the t[1] represents the object itself, with some types using other fields

namespace {
// pushes onto the stack a new table with the bsontype metatable set up
void push_bsontype_table(lua_State* L, mongo::BSONType bsontype)
{
lua_newtable(L);
lua_newtable(L);
lua_pushstring(L, "__bsontype");
lua_pushinteger(L, bsontype);
lua_settable(L, -3);
lua_setmetatable(L, -2);
}
} // anonynous namespace

void push_bsontype_table(lua_State* L, mongo::BSONType bsontype);
extern const char *bson_name(int type);

static int bson_type_Date(lua_State *L) {
push_bsontype_table(L, mongo::Date);
Expand Down Expand Up @@ -74,13 +54,201 @@ static int bson_type_Symbol(lua_State *L) {
return 1;
}

static int integer_value(lua_State *L) {
int n = lua_gettop(L);
int returncount = 1;

lua_rawgeti(L, 1, 1);

if (n > 1) {
lua_pushinteger(L, luaL_checkint(L, 2));
lua_rawseti(L, 1, 1);
returncount = 0;
} else {
lua_pushinteger(L, luaL_checkint(L, -1));
}

return returncount;
}

static int number_value(lua_State *L) {
int n = lua_gettop(L);
int returncount = 1;

lua_rawgeti(L, 1, 1);

if (n > 1) {
lua_pushnumber(L, luaL_checknumber(L, 2));
lua_rawseti(L, 1, 1);
returncount = 0;
} else {
lua_pushnumber(L, luaL_checknumber(L, -1));
}

return returncount;
}

static int string_value(lua_State *L) {
int n = lua_gettop(L);
int returncount = 1;

lua_rawgeti(L, 1, 1);

if (n > 1) {
lua_pushstring(L, luaL_checkstring(L, 2));
lua_rawseti(L, 1, 1);
returncount = 0;
} else {
lua_pushstring(L, luaL_checkstring(L, -1));
}

return returncount;
}

static int stringpair_value(lua_State *L) {
int n = lua_gettop(L);
int returncount = 2;

lua_rawgeti(L, 1, 1);
lua_rawgeti(L, 1, 2);

if (n > 1) {
lua_pushstring(L, luaL_checkstring(L, 2));
lua_rawseti(L, 1, 1);
lua_pushstring(L, luaL_checkstring(L, 3));
lua_rawseti(L, 1, 2);
returncount = 0;
} else {
lua_pushstring(L, luaL_checkstring(L, -2));
lua_pushstring(L, luaL_checkstring(L, -2));
}

return returncount;
}

static int generic_tostring(lua_State *L) {
lua_rawgeti(L, 1, 1);

//lua_pushstring(L, lua_tostring(L, -1));
lua_pushstring(L, luaL_optstring(L, -1, "nil"));

return 1;
}

static int date_tostring(lua_State *L) {
char datestr[64];

lua_rawgeti(L, 1, 1);

time_t t = (time_t)(lua_tonumber(L, -1)/1000);

#if defined(_WIN32)
ctime_s(datestr, 64, &t);
#else
ctime_r(&t,datestr);
#endif

datestr[24] = 0; // don't want the \n

lua_pushstring(L, datestr);

return 1;
}

static int regex_tostring(lua_State *L) {
lua_rawgeti(L, 1, 1);
lua_rawgeti(L, 1, 2);

lua_pushfstring(L, "/%s/%s", lua_tostring(L, -2), lua_tostring(L, -1));

return 1;
}


// TODO:
// all of this should be in Lua so it can get JIT wins
// bind the bson typeids
// each type could have its cached metatable (from registry)

// all these types are represented as tables
// the metatable entry __bsontype dictates the type
// the t[1] represents the object itself, with some types using other fields

void push_bsontype_table(lua_State* L, mongo::BSONType bsontype) {
lua_newtable(L);
lua_newtable(L);

lua_pushstring(L, "__bsontype");
lua_pushinteger(L, bsontype);
lua_settable(L, -3);

lua_pushstring(L, "__call");
switch(bsontype) {
case mongo::NumberInt:
lua_pushcfunction(L, integer_value);
break;
case mongo::Date:
case mongo::Timestamp:
lua_pushcfunction(L, number_value);
break;
case mongo::Symbol:
lua_pushcfunction(L, string_value);
break;
case mongo::RegEx:
lua_pushcfunction(L, stringpair_value);
break;
}
lua_settable(L, -3);

lua_pushstring(L, "__tostring");
switch(bsontype) {
case mongo::NumberInt:
case mongo::Timestamp:
case mongo::Symbol:
lua_pushcfunction(L, generic_tostring);
break;
case mongo::Date:
lua_pushcfunction(L, date_tostring);
break;
case mongo::RegEx:
lua_pushcfunction(L, regex_tostring);
break;
}
lua_settable(L, -3);

lua_setmetatable(L, -2);
}

/*
* typename = mongo.type(obj)
*/
static int bson_type_name(lua_State *L) {
if (lua_istable(L, 1)) {
int bsontype_found = luaL_getmetafield(L, 1, "__bsontype");

if (bsontype_found) {
int bson_type = lua_tointeger(L, -1);
lua_pop(L, 1);

lua_pushfstring(L, "%s.%s", LUAMONGO_ROOT, bson_name(bson_type));
} else {
lua_pushstring(L, luaL_typename(L, 1));
}
} else {
lua_pushstring(L, luaL_typename(L, 1));
}

return 1;
}

int mongo_bsontypes_register(lua_State *L) {
static const luaL_Reg bsontype_methods[] = {
{"Date", bson_type_Date},
{"Timestamp", bson_type_Timestamp},
{"RegEx", bson_type_RegEx},
{"NumberInt", bson_type_NumberInt},
{"Symbol", bson_type_Symbol},
{"type", bson_type_name},
{NULL, NULL}
};

Expand Down

0 comments on commit 41c68de

Please sign in to comment.