|
|
|
@ -48,36 +48,53 @@ using namespace DFHack;
|
|
|
|
|
|
|
|
|
|
DFHACK_PLUGIN("xlsxreader");
|
|
|
|
|
|
|
|
|
|
typedef void* xlsx_file_handle;
|
|
|
|
|
typedef void* xlsx_sheet_handle;
|
|
|
|
|
struct handle_identity : public compound_identity {
|
|
|
|
|
handle_identity(): compound_identity(0, nullptr, nullptr, "handle") {};
|
|
|
|
|
DFHack::identity_type type() override { return IDTYPE_OPAQUE; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct xlsx_file_handle {
|
|
|
|
|
const xlsxioreader handle;
|
|
|
|
|
xlsx_file_handle(xlsxioreader handle): handle(handle) {}
|
|
|
|
|
static handle_identity _identity;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct xlsx_sheet_handle {
|
|
|
|
|
const xlsxioreadersheet handle;
|
|
|
|
|
xlsx_sheet_handle(xlsxioreadersheet handle): handle(handle) {}
|
|
|
|
|
static handle_identity _identity;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
handle_identity xlsx_file_handle::_identity;
|
|
|
|
|
handle_identity xlsx_sheet_handle::_identity;
|
|
|
|
|
|
|
|
|
|
// returns NULL on error
|
|
|
|
|
xlsx_file_handle open_xlsx_file(std::string filename)
|
|
|
|
|
{
|
|
|
|
|
return xlsxioread_open(filename.c_str());
|
|
|
|
|
xlsx_file_handle* open_xlsx_file(std::string filename) {
|
|
|
|
|
return new xlsx_file_handle(xlsxioread_open(filename.c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void close_xlsx_file(xlsx_file_handle file_handle)
|
|
|
|
|
{
|
|
|
|
|
xlsxioread_close((xlsxioreader)file_handle);
|
|
|
|
|
void close_xlsx_file(xlsx_file_handle *file_handle) {
|
|
|
|
|
CHECK_NULL_POINTER(file_handle);
|
|
|
|
|
xlsxioread_close(file_handle->handle);
|
|
|
|
|
delete(file_handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// returns XLSXIOReaderSheet object or NULL on error
|
|
|
|
|
xlsx_sheet_handle open_sheet(xlsx_file_handle file_handle, std::string sheet_name)
|
|
|
|
|
{
|
|
|
|
|
if (file_handle == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
return xlsxioread_sheet_open((xlsxioreader)file_handle,
|
|
|
|
|
sheet_name.c_str(), XLSXIOREAD_SKIP_NONE);
|
|
|
|
|
xlsx_sheet_handle* open_sheet(xlsx_file_handle *file_handle,
|
|
|
|
|
std::string sheet_name) {
|
|
|
|
|
CHECK_NULL_POINTER(file_handle);
|
|
|
|
|
return new xlsx_sheet_handle(
|
|
|
|
|
xlsxioread_sheet_open(file_handle->handle,
|
|
|
|
|
sheet_name.c_str(), XLSXIOREAD_SKIP_NONE));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void close_sheet(xlsx_sheet_handle sheet_handle)
|
|
|
|
|
{
|
|
|
|
|
xlsxioread_sheet_close((xlsxioreadersheet)sheet_handle);
|
|
|
|
|
void close_sheet(xlsx_sheet_handle *sheet_handle) {
|
|
|
|
|
CHECK_NULL_POINTER(sheet_handle);
|
|
|
|
|
xlsxioread_sheet_close(sheet_handle->handle);
|
|
|
|
|
delete(sheet_handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int list_callback(const XLSXIOCHAR* name, void* cbdata)
|
|
|
|
|
{
|
|
|
|
|
static int list_callback(const XLSXIOCHAR* name, void* cbdata) {
|
|
|
|
|
auto sheetNames = (std::vector<std::string> *)cbdata;
|
|
|
|
|
sheetNames->push_back(name);
|
|
|
|
|
return 0;
|
|
|
|
@ -85,19 +102,16 @@ static int list_callback(const XLSXIOCHAR* name, void* cbdata)
|
|
|
|
|
|
|
|
|
|
// start reading the next row of data; must be called before get_next_cell.
|
|
|
|
|
// returns false if there is no next row to get.
|
|
|
|
|
static bool get_next_row(xlsx_sheet_handle sheet_handle)
|
|
|
|
|
{
|
|
|
|
|
return xlsxioread_sheet_next_row((xlsxioreadersheet)sheet_handle) != 0;
|
|
|
|
|
static bool get_next_row(xlsx_sheet_handle *sheet_handle) {
|
|
|
|
|
return xlsxioread_sheet_next_row(sheet_handle->handle) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fills the value param with the contents of the cell in the next column cell
|
|
|
|
|
// in the current row.
|
|
|
|
|
// returns false if there are no more cells in this row.
|
|
|
|
|
static bool get_next_cell(xlsx_sheet_handle sheet_handle, std::string& value)
|
|
|
|
|
{
|
|
|
|
|
static bool get_next_cell(xlsx_sheet_handle *sheet_handle, std::string& value) {
|
|
|
|
|
char* result;
|
|
|
|
|
if (!xlsxioread_sheet_next_cell_string(
|
|
|
|
|
(xlsxioreadersheet)sheet_handle, &result)) {
|
|
|
|
|
if (!xlsxioread_sheet_next_cell_string(sheet_handle->handle, &result)) {
|
|
|
|
|
value.clear();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -106,44 +120,35 @@ static bool get_next_cell(xlsx_sheet_handle sheet_handle, std::string& value)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// internal function to factor out handle extraction
|
|
|
|
|
static void * get_xlsxreader_handle(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
if (lua_gettop(L) < 1 || lua_isnil(L, 1))
|
|
|
|
|
{
|
|
|
|
|
// internal function to extract a handle from the first stack param
|
|
|
|
|
static void * get_xlsxreader_handle(lua_State *L) {
|
|
|
|
|
if (lua_gettop(L) < 1 || lua_isnil(L, 1)) {
|
|
|
|
|
luaL_error(L, "invalid xlsxreader handle");
|
|
|
|
|
}
|
|
|
|
|
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
|
|
|
|
|
return lua_touserdata(L, 1);
|
|
|
|
|
luaL_checktype(L, 1, LUA_TUSERDATA);
|
|
|
|
|
return LuaWrapper::get_object_ref(L, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// takes a file handle and returns a table-list of sheet names
|
|
|
|
|
int list_sheets(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
xlsxioreader file_handle = (xlsxioreader)get_xlsxreader_handle(L);
|
|
|
|
|
int list_sheets(lua_State *L) {
|
|
|
|
|
auto file_handle = (xlsx_file_handle *)get_xlsxreader_handle(L);
|
|
|
|
|
auto sheetNames = std::vector<std::string>();
|
|
|
|
|
xlsxioread_list_sheets(file_handle, list_callback, &sheetNames);
|
|
|
|
|
xlsxioread_list_sheets(file_handle->handle, list_callback, &sheetNames);
|
|
|
|
|
Lua::PushVector(L, sheetNames, true);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// takes the sheet handle and returns a table-list of strings, or nil if we
|
|
|
|
|
// already processed the last row in the file.
|
|
|
|
|
int get_row(lua_State *L)
|
|
|
|
|
{
|
|
|
|
|
xlsxioreadersheet sheet_handle =
|
|
|
|
|
(xlsxioreadersheet)get_xlsxreader_handle(L);
|
|
|
|
|
int get_row(lua_State *L) {
|
|
|
|
|
auto sheet_handle = (xlsx_sheet_handle *)get_xlsxreader_handle(L);
|
|
|
|
|
bool ok = get_next_row(sheet_handle);
|
|
|
|
|
if (!ok)
|
|
|
|
|
{
|
|
|
|
|
if (!ok) {
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
} else {
|
|
|
|
|
std::string value;
|
|
|
|
|
auto cells = std::vector<std::string>();
|
|
|
|
|
while (get_next_cell(sheet_handle, value))
|
|
|
|
|
{
|
|
|
|
|
while (get_next_cell(sheet_handle, value)) {
|
|
|
|
|
cells.push_back(value);
|
|
|
|
|
}
|
|
|
|
|
Lua::PushVector(L, cells, true);
|
|
|
|
@ -166,12 +171,11 @@ DFHACK_PLUGIN_LUA_COMMANDS{
|
|
|
|
|
DFHACK_LUA_END
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
DFhackCExport command_result plugin_init(color_ostream &, std::vector<PluginCommand> &)
|
|
|
|
|
{
|
|
|
|
|
DFhackCExport command_result plugin_init(color_ostream &,
|
|
|
|
|
std::vector<PluginCommand> &) {
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DFhackCExport command_result plugin_shutdown(color_ostream &)
|
|
|
|
|
{
|
|
|
|
|
DFhackCExport command_result plugin_shutdown(color_ostream &) {
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|