summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2015-06-23 13:32:42 +0800
committerDeterminant <ted.sybil@gmail.com>2015-06-23 13:32:42 +0800
commit8f13607cba9d6cf4fc4a213ba5ae4bcd46f7e18d (patch)
tree28a4c503c2b8ab1e687e0ca8a0cd24a1918401b1
parentb5ca62108775505246f752b9782352b45036ef3c (diff)
separate non-Lua part of io code to a dedicated dir; code clean-up
-rw-r--r--nerv/Makefile8
-rw-r--r--nerv/common.h2
-rw-r--r--nerv/io/chunk_file.c345
-rw-r--r--nerv/io/chunk_file.h19
-rw-r--r--nerv/io/init.lua8
-rw-r--r--nerv/lib/io/chunk_file.c239
-rw-r--r--nerv/lib/io/chunk_file.h43
-rw-r--r--nerv/lib/luaT/README.md (renamed from nerv/luaT/README.md)0
-rw-r--r--nerv/lib/luaT/luaT.c (renamed from nerv/luaT/luaT.c)0
-rw-r--r--nerv/lib/luaT/luaT.h (renamed from nerv/luaT/luaT.h)0
-rw-r--r--nerv/matrix/generic/mmatrix.c10
-rw-r--r--nerv/nerv-scm-1.rockspec10
12 files changed, 385 insertions, 299 deletions
diff --git a/nerv/Makefile b/nerv/Makefile
index b69a63e..4008453 100644
--- a/nerv/Makefile
+++ b/nerv/Makefile
@@ -1,7 +1,7 @@
.PHONY: build install clean
SHELL := /bin/bash
BUILD_DIR := $(CURDIR)/build
-OBJS := nerv.o luaT.o common.o \
+OBJS := nerv.o lib/luaT/luaT.o lib/io/chunk_file.o common.o \
matrix/mmatrix.o matrix/cumatrix.o matrix/init.o matrix/cukernel.o \
io/init.o io/chunk_file.o \
examples/oop_example.o
@@ -19,7 +19,7 @@ INCLUDE += $(CUDA_INCLUDE)
LDFLAGS := -L$(CUDA_BASE)/lib64/ -Wl,-rpath=$(CUDA_BASE)/lib64/ -lcudart -lcublas
CFLAGS := -Wall -Wextra -O2
OBJ_DIR := $(BUILD_DIR)/objs
-SUBDIR := matrix io layer examples nn
+SUBDIR := matrix io layer examples nn lib/io lib/luaT
NVCC := $(CUDA_BASE)/bin/nvcc
NVCC_FLAGS := -Xcompiler -fPIC,-Wall,-Wextra
@@ -39,8 +39,8 @@ $(OBJ_DIR)/matrix/cukernel.o: matrix/cukernel.cu
$(NVCC) -c -o $@ $< $(INCLUDE) $(NVCC_FLAGS)
$(LUA_DIR)/%.lua: %.lua
cp $< $@
-$(OBJ_DIR)/luaT.o:
- gcc -c -o $@ luaT/luaT.c $(INCLUDE) -fPIC
+#$(OBJ_DIR)/luaT.o:
+# gcc -c -o $@ luaT/luaT.c $(INCLUDE) -fPIC
$(LIBS): $(OBJS)
gcc -shared -o $@ $(OBJS) $(LDFLAGS)
diff --git a/nerv/common.h b/nerv/common.h
index e21c7a5..6657dc4 100644
--- a/nerv/common.h
+++ b/nerv/common.h
@@ -3,7 +3,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
-#include "luaT/luaT.h"
+#include "lib/luaT/luaT.h"
#include <stdio.h>
#include <stdlib.h>
diff --git a/nerv/io/chunk_file.c b/nerv/io/chunk_file.c
index c0b6b9f..e275d9b 100644
--- a/nerv/io/chunk_file.c
+++ b/nerv/io/chunk_file.c
@@ -5,321 +5,136 @@
#include "chunk_file.h"
#define INVALID_FORMAT_ERROR(fn) \
- nerv_error(L, "Invalid chunk file: %s", fn)
+ nerv_error(L, "invalid chunk file: %s", fn)
#define CHECK_FORMAT(exp, ret, fname) \
do { \
if ((exp) != (ret)) INVALID_FORMAT_ERROR(fn); \
} while (0)
-#define CHECK_FILE_OPEN(pfh) \
- do { \
- if ((pfh)->closed) \
- nerv_error(L, "operations on a closed file"); \
- } while (0)
const char *nerv_chunk_file_tname = "nerv.ChunkFile";
const char *nerv_chunk_file_handle_tname = "nerv.ChunkFileHandle";
const char *nerv_chunk_info_tname = "nerv.ChunkInfo";
const char *nerv_chunk_data_tname = "nerv.ChunkData";
-#define PARAM_HEADER_SIZE 16
-
-enum {
- NORMAL,
- INVALID_FORMAT,
- END_OF_FILE,
- SECTION_OVERFLOW,
- WRITE_ERROR
-};
-
-size_t read_chunk_header_plain(FILE *fp, int *status) {
- static char buff[PARAM_HEADER_SIZE];
- int i;
- size_t size = 0;
- *status = NORMAL;
- if (fread(buff, 1, PARAM_HEADER_SIZE, fp) != PARAM_HEADER_SIZE)
- {
- if (feof(fp)) *status = END_OF_FILE;
- else *status = INVALID_FORMAT;
- }
- for (i = 0; i < PARAM_HEADER_SIZE; i++)
- if (isdigit(buff[i]))
- size = size * 10 + buff[i] - '0';
-/* fprintf(stderr, "header: %lu\n", size); */
- return size;
-}
-
-#define CHECK_WRITE(status) \
- do { \
- if (status == SECTION_OVERFLOW) \
- nerv_error(L, "section overflowed"); \
- else if (status == WRITE_ERROR) \
- nerv_error(L, "error while writing"); \
- } while (0)
-
-void write_chunk_header_plain(FILE *fp, size_t size, int *status) {
- static char buff[PARAM_HEADER_SIZE];
- int i;
- *status = NORMAL;
- for (i = PARAM_HEADER_SIZE - 3; i > 0; i--, size /= 10)
- buff[i] = size % 10 + '0';
- if (size)
- {
- *status = SECTION_OVERFLOW;
- return;
- }
- buff[0] = '[';
- buff[PARAM_HEADER_SIZE - 2] = ']';
- buff[PARAM_HEADER_SIZE - 1] = '\n';
- if (fwrite(buff, 1, PARAM_HEADER_SIZE, fp) != PARAM_HEADER_SIZE)
- {
- *status = WRITE_ERROR;
- return;
- }
-}
-
-ChunkData *get_chunk_data(FILE *fp, ChunkInfo *info) {
- ChunkData *pcd = (ChunkData *)malloc(sizeof(ChunkData));
- pcd->data = (char *)malloc(info->length);
- pcd->fp = fmemopen(pcd->data, info->length, "r");
- assert(fseeko(fp, info->offset, SEEK_SET) == 0);
- if (fread(pcd->data, 1, info->length, fp) != (size_t)info->length)
- return NULL;
- return pcd;
-}
-
-const char *read_chunk_metadata(lua_State *L, FILE *fp, const char *fn) {
-#define LINEBUFF_SIZE 1024
- static char buff[7 + LINEBUFF_SIZE] = "return ";
- CHECK_FORMAT(fgets(buff + 7, LINEBUFF_SIZE, fp), buff + 7, fn);
- /* fprintf(stderr, "metadata: %s\n", buff); */
- return buff;
-}
-
-void write_chunk_metadata(FILE *fp, const char *metadata_str, int *status) {
- size_t size = strlen(metadata_str);
- *status = NORMAL;
- if (fwrite(metadata_str, 1, size, fp) != size ||
- fprintf(fp, "\n") < 0)
+int nerv_lua_chunk_file_new(lua_State *L) {
+ int status;
+ const char *fn = luaL_checkstring(L, 1);
+ ChunkFile *cfp = nerv_chunk_file_create(fn,
+ luaL_checkstring(L, 2),
+ &status);
+ if (status != CF_NORMAL)
{
- *status = WRITE_ERROR;
- return;
+ nerv_error(L, "%s: %s", fn, nerv_chunk_file_errstr(status));
}
- /* fprintf(stderr, "metadata: %s\n", metadata_str); */
-}
-
-
-int nerv_chunk_file_open_write(lua_State *L, const char *fn) {
- FILE *fp = fopen(fn, "w");
- ChunkFileHandle *lfp;
- if (!fp) nerv_error(L, "Error while opening chunk file: %s", fn);
- lfp = (ChunkFileHandle *)malloc(sizeof(ChunkFileHandle));
- lfp->fp = fp;
- lfp->closed = 0;
- luaT_pushudata(L, lfp, nerv_chunk_file_handle_tname);
- lua_setfield(L, -2, "handle");
- luaT_pushmetatable(L, nerv_chunk_file_tname);
- lua_setmetatable(L, -2);
- return 1;
-}
-
-int nerv_chunk_file_open_read(lua_State *L, const char *fn) {
- FILE *fp = fopen(fn, "r");
- int i, status;
- size_t chunk_len;
- off_t offset;
- ChunkFileHandle *lfp;
-
- if (!fp) nerv_error(L, "Error while opening chunk file: %s", fn);
- offset = ftello(fp);
lua_newtable(L);
- /* fprintf(stderr, "%d\n", (int)offset); */
- for (i = 0;; offset += chunk_len, i++)
+ luaT_pushudata(L, cfp, nerv_chunk_file_handle_tname);
+ lua_setfield(L, -2, "handle");
+ if (cfp->status == CF_READ)
{
- ChunkInfo *pci;
- /* fprintf(stderr, "reading chunk %d from %d\n", i, (int)offset); */
- /* skip to the begining of chunk i */
- CHECK_FORMAT(fseeko(fp, offset, SEEK_SET), 0, fn);
- /* read header */
- chunk_len = read_chunk_header_plain(fp, &status);
- if (status == END_OF_FILE) break;
- else if (status == INVALID_FORMAT)
- INVALID_FORMAT_ERROR(fn);
- /* read metadata */
- luaL_loadstring(L, read_chunk_metadata(L, fp, fn));
- CHECK_FORMAT(lua_pcall(L, 0, 1, 0), 0, fn);
- CHECK_FORMAT(lua_istable(L, -1), 1, fn);
- /* stack: obj_table, metadata */
- /* chunk info */
- pci = (ChunkInfo *)malloc(sizeof(ChunkInfo));
- pci->offset = ftello(fp);
- pci->length = chunk_len - (pci->offset - offset);
- /* fprintf(stderr, "%d + %d (skip %lu)\n", (int)pci->offset,
- (int)pci->length, chunk_len); */
- luaT_pushudata(L, pci, nerv_chunk_info_tname);
- lua_setfield(L, -2, "chunk");
- /* stack: obj_table, metadata */
- /* get id */
- lua_getfield(L, -1, "id");
- /* stack: obj_table, metadata, id */
- if (!lua_isstring(L, -1))
- nerv_error(L, "id field in metadata must be a string");
- lua_pushvalue(L, -1);
- /* stack: obj_table, metadata, id, id */
- lua_gettable(L, -4);
- /* stack: obj_table, metadata, id, obj[id] */
- if (!lua_isnil(L, -1))
- nerv_error(L, "conflicting id");
- lua_pop(L, 1);
- /* stack: obj_table, metadata, id */
- lua_pushvalue(L, -2);
- /* stack: obj_table, metadata, id, metadata */
- lua_settable(L, -4);
- /* stack: obj_table, metadata */
- lua_pop(L, 1);
+ ChunkInfo *cip;
+ /* build a table with interpreted metadata in Lua because C API only
+ * provides with linked list with uninterpreted metadata */
+ lua_newtable(L);
+ /* stack: self, metadata_table */
+ for (cip = cfp->info; cip; cip = cip->next)
+ {
+ luaL_loadstring(L, cip->metadata);
+ CHECK_FORMAT(lua_pcall(L, 0, 1, 0), 0, fn);
+ CHECK_FORMAT(lua_istable(L, -1), 1, fn);
+ lua_getfield(L, -1, "id");
+ if (!lua_isstring(L, -1))
+ nerv_error(L, "id field in metadata must be a string");
+ /* stack: ... metadata_table, metadata, id */
+ lua_pushvalue(L, -1);
+ /* stack: ... metadata_table, metadata, id, id */
+ lua_gettable(L, -4);
+ /* stack: ... metadata_table, metadata, id, metadata_table[id] */
+ if (!lua_isnil(L, -1))
+ nerv_error(L, "conflicting id");
+ lua_pop(L, 1);
+ /* stack: ... metadata_table, metadata, id */
+ lua_pushvalue(L, -2);
+ /* stack: ... metadata_table, metadata, id, metadata */
+ lua_settable(L, -4);
+ /* stack: ... metadata_table, metadata */
+ luaT_pushudata(L, cip, nerv_chunk_info_tname);
+ /* stack: ... metadata_table, cip */
+ lua_setfield(L, -2, "_chunk_info");
+ /* stack: ... metadata_table */
+ lua_pop(L, 1);
+ /* stack: ... metadata_table */
+ }
+ lua_setfield(L, -2, "metadata");
+ /* stack: ... */
}
- lua_setfield(L, -2, "metadata");
- lfp = (ChunkFileHandle *)malloc(sizeof(ChunkFileHandle));
- lfp->fp = fp;
- lfp->closed = 0;
- luaT_pushudata(L, lfp, nerv_chunk_file_handle_tname);
- lua_setfield(L, -2, "handle");
luaT_pushmetatable(L, nerv_chunk_file_tname);
lua_setmetatable(L, -2);
return 1;
}
-int nerv_chunk_file_new_(lua_State *L, const char *fn, const char *mode) {
- int rd = 1, bin = 0;
- size_t i, len = strlen(mode);
- for (i = 0; i < len; i++)
- switch (mode[i])
- {
- case 'r': rd = 1; break;
- case 'w': rd = 0; break;
- case 'b': bin = 1; break;
- }
- return rd ? nerv_chunk_file_open_read(L, fn) : \
- nerv_chunk_file_open_write(L, fn);
+static void writer(void *L) {
+ lua_call((lua_State *)L, 2, 0); /* let the write() to write */
}
-int nerv_chunk_file___init(lua_State *L) {
- lua_pushvalue(L, 1);
- return nerv_chunk_file_new_(L, luaL_checkstring(L, 2),
- luaL_checkstring(L, 3));
-}
-
-int nerv_chunk_file_new(lua_State *L) {
- lua_newtable(L);
- return nerv_chunk_file_new_(L, luaL_checkstring(L, 1),
- luaL_checkstring(L, 2));
-}
-
-int nerv_chunk_file_write_chunkdata(lua_State *L) {
- ChunkFileHandle *pfh;
+int nerv_lua_chunk_file_write_chunkdata(lua_State *L) {
int status;
- off_t start;
- size_t size;
- const char *metadata_str = lua_tolstring(L, 2, NULL);
- lua_getfield(L, 1, "handle");
- pfh = luaT_checkudata(L, -1, nerv_chunk_file_handle_tname);
- CHECK_FILE_OPEN(pfh);
- start = ftello(pfh->fp);
- write_chunk_header_plain(pfh->fp, 0, &status); /* fill zeros */
- CHECK_WRITE(status);
- write_chunk_metadata(pfh->fp, metadata_str, &status);
- CHECK_WRITE(status);
- lua_pushvalue(L, 3);
- lua_getfield(L, -1, "write");
+ ChunkFile *cfp = luaT_checkudata(L, 1, nerv_chunk_file_handle_tname);
+ const char *mdstr = lua_tolstring(L, 2, NULL);
+ lua_getfield(L, 3, "write");
if (!lua_isfunction(L, -1))
nerv_error(L, "\"write\" method must be implemented");
- lua_pushvalue(L, -2);
- lua_pushvalue(L, 4); /* pass handle as parameter to write() */
- lua_call(L, 2, 0); /* let the write() to write */
- lua_pop(L, 1);
- size = ftello(pfh->fp) - start;
- fseeko(pfh->fp, start, SEEK_SET);
- /* write the calced size */
- write_chunk_header_plain(pfh->fp, size, &status);
- CHECK_WRITE(status);
- fseeko(pfh->fp, 0, SEEK_END);
+ lua_pushvalue(L, 3); /* lua writer itself */
+ lua_pushvalue(L, 1); /* pass handle as parameter to write() */
+ nerv_chunk_file_write_chunkdata(cfp, mdstr, writer, (void *)L);
return 0;
}
-int nerv_chunk_file_get_chunkdata(lua_State *L) {
- ChunkFileHandle *pfh;
- ChunkInfo *pci;
- ChunkData *pcd;
- const char *id = luaL_checkstring(L, 2);
-
- lua_getfield(L, 1, "handle");
- pfh = luaT_checkudata(L, -1, nerv_chunk_file_handle_tname);
- CHECK_FILE_OPEN(pfh);
- lua_pop(L, 1); /* pop handle */
- lua_getfield(L, 1, "metadata");
- /* now stack: self, k, metadata */
- lua_getfield(L, -1, id);
- /* now stack: self, k, metadata, kth{} */
- if (lua_isnil(L, -1)) /* no chunck with the id */
- return 0;
- lua_getfield(L, -1, "chunk");
- pci = luaT_checkudata(L, -1, nerv_chunk_info_tname);
- if (!(pcd = get_chunk_data(pfh->fp, pci)))
- nerv_error(L, "unexpected end of file");
- luaT_pushudata(L, pcd, nerv_chunk_data_tname);
+int nerv_lua_chunk_file_get_chunkdata(lua_State *L) {
+ int status;
+ ChunkFile *cfp = luaT_checkudata(L, 1, nerv_chunk_file_handle_tname);
+ ChunkInfo *cip = luaT_checkudata(L, 2, nerv_chunk_info_tname);
+ ChunkData *cdp = nerv_chunk_file_get_chunkdata(cfp, cip, &status);
+ if (status != CF_NORMAL)
+ nerv_error(L, "%s", nerv_chunk_file_errstr(status));
+ luaT_pushudata(L, cdp, nerv_chunk_data_tname);
return 1;
}
-int nerv_chunk_file_close(lua_State *L) {
- ChunkFileHandle *pfh;
- lua_getfield(L, 1, "handle");
- pfh = luaT_checkudata(L, -1, nerv_chunk_file_handle_tname);
- CHECK_FILE_OPEN(pfh);
- fclose(pfh->fp);
- pfh->closed = 1;
- return 0;
-}
-
-int nerv_chunk_file_handle_destroy(lua_State *L) {
- ChunkFileHandle *pfh = luaT_checkudata(L, 1,
- nerv_chunk_file_handle_tname);
- if (!pfh->closed) fclose(pfh->fp);
- free(pfh);
+int nerv_lua_chunk_file_close(lua_State *L) {
+ ChunkFile *cfp = luaT_checkudata(L, -1, nerv_chunk_file_handle_tname);
+ nerv_chunk_file_close(cfp);
return 0;
}
-static int nerv_chunk_info_destroy(lua_State *L) {
- ChunkInfo *pci = luaT_checkudata(L, 1, nerv_chunk_info_tname);
- free(pci);
+int nerv_lua_chunk_file_destroy(lua_State *L) {
+ ChunkFile *cfp = luaT_checkudata(L, -1, nerv_chunk_file_handle_tname);
+ nerv_chunk_file_destroy(cfp);
return 0;
}
-static int nerv_chunk_data_destroy(lua_State *L) {
- ChunkData *pcd = luaT_checkudata(L, 1, nerv_chunk_data_tname);
- fclose(pcd->fp);
- free(pcd->data);
- free(pcd);
+static int nerv_lua_chunk_data_destroy(lua_State *L) {
+ ChunkData *cdp = luaT_checkudata(L, 1, nerv_chunk_data_tname);
+ nerv_chunk_data_destroy(cdp);
return 0;
}
static const luaL_Reg nerv_chunk_file_methods[] = {
- {"get_chunkdata", nerv_chunk_file_get_chunkdata},
- {"_write_chunkdata", nerv_chunk_file_write_chunkdata},
- {"close", nerv_chunk_file_close},
- {"__init", nerv_chunk_file___init},
+ {"_get_chunkdata", nerv_lua_chunk_file_get_chunkdata},
+ {"_write_chunkdata", nerv_lua_chunk_file_write_chunkdata},
+ {"_close", nerv_lua_chunk_file_close},
{NULL, NULL}
};
void nerv_chunk_file_init(lua_State *L) {
luaT_newmetatable(L, nerv_chunk_file_tname, NULL,
- nerv_chunk_file_new,
+ nerv_lua_chunk_file_new,
NULL, NULL);
luaL_register(L, NULL, nerv_chunk_file_methods);
lua_pop(L, 1);
luaT_newmetatable(L, nerv_chunk_file_handle_tname, NULL,
- NULL, nerv_chunk_file_handle_destroy, NULL);
+ NULL, nerv_lua_chunk_file_destroy, NULL);
luaT_newmetatable(L, nerv_chunk_info_tname, NULL,
- NULL, nerv_chunk_info_destroy, NULL);
+ NULL, NULL, NULL);
luaT_newmetatable(L, nerv_chunk_data_tname, NULL,
- NULL, nerv_chunk_data_destroy, NULL);
+ NULL, nerv_lua_chunk_data_destroy, NULL);
}
-
diff --git a/nerv/io/chunk_file.h b/nerv/io/chunk_file.h
index 9bae59d..71094a5 100644
--- a/nerv/io/chunk_file.h
+++ b/nerv/io/chunk_file.h
@@ -1,23 +1,10 @@
-#ifndef NERV_LAYER_FILE_H
-#define NERV_LAYER_FILE_H
+#ifndef NERV_LUA_CHUNK_FILE_H
+#define NERV_LUA_CHUNK_FILE_H
+#include "../lib/io/chunk_file.h"
extern const char *nerv_chunk_file_tname;
extern const char *nerv_chunk_file_handle_tname;
extern const char *nerv_chunk_info_tname;
extern const char *nerv_chunk_data_tname;
-typedef struct ChunkFileHandle {
- FILE *fp;
- int closed;
-} ChunkFileHandle;
-
-typedef struct ChunkInfo {
- off_t offset, length;
-} ChunkInfo;
-
-typedef struct ChunkData {
- FILE *fp;
- char *data;
-} ChunkData;
-
#endif
diff --git a/nerv/io/init.lua b/nerv/io/init.lua
index 647ff93..eb2e3e5 100644
--- a/nerv/io/init.lua
+++ b/nerv/io/init.lua
@@ -3,7 +3,7 @@ function nerv.ChunkFile:write_chunkdata(metadata, writer)
nerv.error("metadata should be a Lua table")
return
end
- return self:_write_chunkdata(table.tostring(metadata), writer)
+ return self._write_chunkdata(self.handle, table.tostring(metadata), writer)
end
function nerv.ChunkFile:write_chunk(chunk)
@@ -28,10 +28,14 @@ function nerv.ChunkFile:read_chunk(id, global_conf)
local chunk_type = nerv.get_type(metadata.type)
local chunk = chunk_type(id, global_conf)
chunk:set_info(metadata.info)
- chunk:read(self:get_chunkdata(id))
+ chunk:read(self._get_chunkdata(self.handle, metadata._chunk_info))
return chunk
end
+function nerv.ChunkFile:close()
+ self._close(self.handle)
+end
+
local DataReader = nerv.class("nerv.DataReader")
function DataReader:__init(global_conf, reader_conf)
diff --git a/nerv/lib/io/chunk_file.c b/nerv/lib/io/chunk_file.c
new file mode 100644
index 0000000..a305962
--- /dev/null
+++ b/nerv/lib/io/chunk_file.c
@@ -0,0 +1,239 @@
+#include "../../common.h"
+#include "chunk_file.h"
+#include <stdlib.h>
+#include <string.h>
+#define PARAM_HEADER_SIZE 16
+
+static size_t read_chunk_header_plain(FILE *fp, int *status) {
+ static char buff[PARAM_HEADER_SIZE];
+ int i;
+ size_t size = 0;
+ if (fread(buff, 1, PARAM_HEADER_SIZE, fp) != PARAM_HEADER_SIZE)
+ {
+ if (feof(fp)) *status = CF_END_OF_FILE;
+ else
+ {
+ *status = CF_INVALID_FORMAT;
+ return 0;
+ }
+ }
+ else *status = CF_NORMAL;
+ for (i = 0; i < PARAM_HEADER_SIZE; i++)
+ if (isdigit(buff[i]))
+ size = size * 10 + buff[i] - '0';
+/* fprintf(stderr, "header: %lu\n", size); */
+ return size;
+}
+
+static void write_chunk_header_plain(FILE *fp, size_t size, int *status) {
+ static char buff[PARAM_HEADER_SIZE];
+ int i;
+ for (i = PARAM_HEADER_SIZE - 3; i > 0; i--, size /= 10)
+ buff[i] = size % 10 + '0';
+ if (size)
+ {
+ *status = CF_SECTION_OVERFLOW;
+ return;
+ }
+ buff[0] = '[';
+ buff[PARAM_HEADER_SIZE - 2] = ']';
+ buff[PARAM_HEADER_SIZE - 1] = '\n';
+ if (fwrite(buff, 1, PARAM_HEADER_SIZE, fp) != PARAM_HEADER_SIZE)
+ {
+ *status = CF_WRITE_ERROR;
+ return;
+ }
+ *status = CF_NORMAL;
+}
+
+static ChunkData *get_chunk_data(FILE *fp, ChunkInfo *info) {
+ ChunkData *cdp = (ChunkData *)malloc(sizeof(ChunkData));
+ cdp->data = (char *)malloc(info->length);
+ cdp->fp = fmemopen(cdp->data, info->length, "r");
+ assert(fseeko(fp, info->offset, SEEK_SET) == 0);
+ if (fread(cdp->data, 1, info->length, fp) != (size_t)info->length)
+ return NULL;
+ return cdp;
+}
+
+static const char *read_chunk_metadata(FILE *fp, const char *fn, int *status) {
+#define LINEBUFF_SIZE 1024
+#define LUA_RETURN "return "
+#define LUA_RETURN_LEN (sizeof(LUA_RETURN) - 1)
+ static char buff[LUA_RETURN_LEN + LINEBUFF_SIZE] = LUA_RETURN;
+ *status = fgets(buff + LUA_RETURN_LEN,
+ LINEBUFF_SIZE, fp) == (buff + LUA_RETURN_LEN) ? \
+ CF_NORMAL : CF_INVALID_FORMAT;
+ fprintf(stderr, "metadata: %s\n", buff);
+ return buff;
+}
+
+static void write_chunk_metadata(FILE *fp, const char *mdstr, int *status) {
+ size_t size = strlen(mdstr);
+ if (fwrite(mdstr, 1, size, fp) != size ||
+ fprintf(fp, "\n") < 0)
+ {
+ *status = CF_WRITE_ERROR;
+ return;
+ }
+ /* fprintf(stderr, "metadata: %s\n", metadata_str); */
+ *status = CF_NORMAL;
+}
+
+static ChunkFile *open_write(const char *fn, int *status) {
+ ChunkFile *cfp;
+ FILE *fp = fopen(fn, "w");
+
+ if (!fp)
+ {
+ *status = CF_ERR_OPEN_FILE;
+ return NULL;
+ }
+ cfp = (ChunkFile *)malloc(sizeof(ChunkFile));
+ cfp->fp = fp;
+ cfp->status = CF_WRITE;
+ *status = CF_NORMAL;
+ return cfp;
+}
+
+static ChunkFile *open_read(const char *fn, int *status) {
+ size_t chunk_len;
+ off_t offset;
+ int i;
+ const char *mdstr;
+ ChunkFile *cfp;
+ ChunkInfo *head = NULL;
+ FILE *fp = fopen(fn, "r");
+
+ if (!fp)
+ {
+ *status = CF_ERR_OPEN_FILE;
+ return NULL;
+ }
+ cfp = (ChunkFile *)malloc(sizeof(ChunkFile));
+ cfp->fp = fp;
+ cfp->status = CF_READ;
+ offset = ftello(fp);
+ /* fprintf(stderr, "%d\n", (int)offset); */
+ for (i = 0;; offset += chunk_len, i++)
+ {
+ ChunkInfo *cip;
+ fprintf(stderr, "reading chunk %d from %d\n", i, (int)offset);
+ /* skip to the begining of chunk i */
+ if (fseeko(fp, offset, SEEK_SET) != 0)
+ {
+ *status = CF_INVALID_FORMAT;
+ return NULL;
+ }
+ /* read header */
+ chunk_len = read_chunk_header_plain(fp, status);
+ if (*status == CF_END_OF_FILE) break;
+ if (*status != CF_NORMAL)
+ return NULL;
+ cip = (ChunkInfo *)malloc(sizeof(ChunkInfo));
+ /* read metadata */
+ mdstr = read_chunk_metadata(fp, fn, status);
+ if (*status != CF_NORMAL)
+ return NULL;
+ cip->metadata = strdup(mdstr);
+ cip->offset = ftello(fp);
+ cip->length = chunk_len - (cip->offset - offset);
+ /* fprintf(stderr, "%d + %d (skip %lu)\n", (int)cip->offset,
+ (int)cip->length, chunk_len); */
+ cip->next = head;
+ head = cip;
+ }
+ *status = CF_NORMAL;
+ cfp->info = head;
+ return cfp;
+}
+
+ChunkFile *nerv_chunk_file_create(const char *fn, const char *mode, int *status) {
+ int rd = 1, bin = 0;
+ size_t i, len = strlen(mode);
+ for (i = 0; i < len; i++)
+ switch (mode[i])
+ {
+ case 'r': rd = 1; break;
+ case 'w': rd = 0; break;
+ case 'b': bin = 1; break;
+ }
+ return rd ? open_read(fn, status) : \
+ open_write(fn, status);
+}
+
+int nerv_chunk_file_write_chunkdata(ChunkFile *cfp, const char *mdstr,
+ ChunkDataWriter_t writer, void *writer_arg) {
+ int status;
+ off_t start;
+ size_t size;
+ if (cfp->status != CF_WRITE)
+ return CF_INVALID_OP;
+ start = ftello(cfp->fp);
+ write_chunk_header_plain(cfp->fp, 0, &status); /* fill zeros */
+ if (status != CF_NORMAL) return status;
+ write_chunk_metadata(cfp->fp, mdstr, &status);
+ if (status != CF_NORMAL) return status;
+ writer(writer_arg);
+ size = ftello(cfp->fp) - start;
+ fseeko(cfp->fp, start, SEEK_SET);
+ /* write the calced size */
+ write_chunk_header_plain(cfp->fp, size, &status);
+ if (status != CF_NORMAL) return status;
+ fseeko(cfp->fp, 0, SEEK_END);
+ return CF_NORMAL;
+}
+
+ChunkData *nerv_chunk_file_get_chunkdata(ChunkFile *cfp, ChunkInfo *cip, int *status) {
+ ChunkData *cdp;
+ if (cfp->status != CF_READ)
+ {
+ *status = CF_INVALID_OP;
+ return NULL;
+ }
+ if (!(cdp = get_chunk_data(cfp->fp, cip)))
+ {
+ *status = CF_END_OF_FILE;
+ return NULL;
+ }
+ *status = CF_NORMAL;
+ return cdp;
+}
+
+void nerv_chunk_file_close(ChunkFile *cfp) {
+ if (cfp->status != CF_CLOSED)
+ fclose(cfp->fp);
+ cfp->status = CF_CLOSED;
+}
+
+void nerv_chunk_file_destroy(ChunkFile *cfp) {
+ ChunkInfo *i, *ni;
+ if (cfp->status != CF_CLOSED) fclose(cfp->fp);
+ for (i = cfp->info; i; i = ni)
+ {
+ ni = i->next;
+ free(i->metadata);
+ free(i);
+ }
+ free(cfp);
+}
+
+void nerv_chunk_data_destroy(ChunkData *cdp) {
+ fclose(cdp->fp);
+ free(cdp->data);
+ free(cdp);
+}
+
+const char *nerv_chunk_file_errstr(int status) {
+ switch (status)
+ {
+ case CF_INVALID_FORMAT: return "invalid format";
+ case CF_END_OF_FILE: return "unexpected end of file";
+ case CF_SECTION_OVERFLOW: return "section overflow";
+ case CF_WRITE_ERROR: return "error while writing";
+ case CF_ERR_OPEN_FILE: return "error while opening file";
+ case CF_INVALID_OP: return "invalid operation";
+ default: return "unknown";
+ }
+ return NULL;
+}
diff --git a/nerv/lib/io/chunk_file.h b/nerv/lib/io/chunk_file.h
new file mode 100644
index 0000000..71f0d03
--- /dev/null
+++ b/nerv/lib/io/chunk_file.h
@@ -0,0 +1,43 @@
+#ifndef NERV_CHUNK_FILE_H
+#define NERV_CHUNK_FILE_H
+#include "../../common.h"
+enum {
+ CF_NORMAL,
+ CF_INVALID_FORMAT,
+ CF_END_OF_FILE,
+ CF_SECTION_OVERFLOW,
+ CF_WRITE_ERROR,
+ CF_ERR_OPEN_FILE,
+ CF_INVALID_OP,
+ CF_READ,
+ CF_WRITE,
+ CF_CLOSED
+};
+
+typedef struct ChunkInfo {
+ struct ChunkInfo *next;
+ char *metadata;
+ off_t offset, length;
+} ChunkInfo;
+
+typedef struct ChunkFile {
+ FILE *fp;
+ ChunkInfo *info;
+ int status;
+} ChunkFile;
+
+typedef struct ChunkData {
+ FILE *fp;
+ char *data;
+} ChunkData;
+
+typedef void (*ChunkDataWriter_t)(void *);
+ChunkFile *nerv_chunk_file_create(const char *fn, const char *mode, int *status);
+int nerv_chunk_file_write_chunkdata(ChunkFile *cfp, const char *mdstr,
+ ChunkDataWriter_t writer, void *writer_arg);
+ChunkData *nerv_chunk_file_get_chunkdata(ChunkFile *cfp, ChunkInfo *cip, int *status);
+void nerv_chunk_file_close(ChunkFile *cfp);
+void nerv_chunk_file_destroy(ChunkFile *cfp);
+void nerv_chunk_data_destroy(ChunkData *cdp);
+const char *nerv_chunk_file_errstr(int status);
+#endif
diff --git a/nerv/luaT/README.md b/nerv/lib/luaT/README.md
index 6e9cf0d..6e9cf0d 100644
--- a/nerv/luaT/README.md
+++ b/nerv/lib/luaT/README.md
diff --git a/nerv/luaT/luaT.c b/nerv/lib/luaT/luaT.c
index 7b85ce3..7b85ce3 100644
--- a/nerv/luaT/luaT.c
+++ b/nerv/lib/luaT/luaT.c
diff --git a/nerv/luaT/luaT.h b/nerv/lib/luaT/luaT.h
index 5e8dd2f..5e8dd2f 100644
--- a/nerv/luaT/luaT.h
+++ b/nerv/lib/luaT/luaT.h
diff --git a/nerv/matrix/generic/mmatrix.c b/nerv/matrix/generic/mmatrix.c
index b0f0791..697c9fc 100644
--- a/nerv/matrix/generic/mmatrix.c
+++ b/nerv/matrix/generic/mmatrix.c
@@ -51,11 +51,11 @@ static void host_matrix_(init)(lua_State *L) {
#include "matrix.c"
int nerv_matrix_(load)(lua_State *L) {
- ChunkData *chunk = luaT_checkudata(L, 1, nerv_chunk_data_tname);
+ ChunkData *cdp = luaT_checkudata(L, 1, nerv_chunk_data_tname);
Matrix *self;
int i, j;
long nrow, ncol;
- FILE *fp = chunk->fp;
+ FILE *fp = cdp->fp;
if (fscanf(fp, "%ld %ld", &nrow, &ncol) != 2)
return 0;
self = nerv_matrix_(new_)(L, nrow, ncol);
@@ -74,12 +74,12 @@ int nerv_matrix_(load)(lua_State *L) {
}
int nerv_matrix_(save)(lua_State *L) {
- ChunkFileHandle *chunk = luaT_checkudata(L, 2,
- nerv_chunk_file_handle_tname);
+ ChunkFile *cfp = luaT_checkudata(L, 2,
+ nerv_chunk_file_handle_tname);
Matrix *self = luaT_checkudata(L, 1, nerv_matrix_(tname));
int i, j;
long nrow = self->nrow, ncol = self->ncol;
- FILE *fp = chunk->fp;
+ FILE *fp = cfp->fp;
if (fprintf(fp, "%ld %ld\n", nrow, ncol) < 0)
return 0;
for (i = 0; i < nrow; i++)
diff --git a/nerv/nerv-scm-1.rockspec b/nerv/nerv-scm-1.rockspec
index d14140a..0b7e4cb 100644
--- a/nerv/nerv-scm-1.rockspec
+++ b/nerv/nerv-scm-1.rockspec
@@ -1,21 +1,19 @@
package = "nerv"
version = "scm-1"
source = {
- url = "..." -- We don't have one yet
+ url = "https://github.com/Determinant/nerv.git"
}
description = {
- summary = "An example for the LuaRocks tutorial.",
+ summary = "A Lua-based toolkit dedicated to high-performance deep neural network learning",
detailed = [[
]],
- homepage = "https://github.com/Determinant/nerv", -- We don't have one yet
- license = "BSD" -- or whatever you like
+ homepage = "https://github.com/Determinant/nerv",
+ license = "BSD"
}
dependencies = {
"lua >= 5.1"
- -- If you depend on other rocks, add them here
}
build = {
- -- We'll start here.
type = "make",
build_variables = {
CFLAGS="$(CFLAGS)",
/a> 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899