-
Notifications
You must be signed in to change notification settings - Fork 483
/
Copy pathxlsxreader.cpp
154 lines (135 loc) · 4.55 KB
/
xlsxreader.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Wrapper for xlsxio_read library functions.
*/
#define BUILD_XLSXIO_STATIC
#include <xlsxio_read.h>
#include "DataFuncs.h"
#include "Error.h"
#include "LuaTools.h"
#include "PluginManager.h"
#include "PluginLua.h"
#include "PluginStatics.h"
using namespace DFHack;
DFHACK_PLUGIN("xlsxreader");
// returns NULL if the file failed to open
xlsx_file_handle* open_xlsx_file(std::string filename) {
xlsxioreader opaque_file_handle = xlsxioread_open(filename.c_str());
if (!opaque_file_handle) {
return NULL;
}
return new xlsx_file_handle(opaque_file_handle);
}
void close_xlsx_file(xlsx_file_handle *file_handle) {
if (!file_handle) {
return;
}
if (file_handle->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) {
CHECK_NULL_POINTER(file_handle);
CHECK_NULL_POINTER(file_handle->handle);
xlsxioreadersheet opaque_sheet_handle = xlsxioread_sheet_open(
file_handle->handle, sheet_name.c_str(), XLSXIOREAD_SKIP_NONE);
if (!opaque_sheet_handle) {
return NULL;
}
return new xlsx_sheet_handle(opaque_sheet_handle);
}
void close_sheet(xlsx_sheet_handle *sheet_handle) {
if (!sheet_handle) {
return;
}
if (sheet_handle->handle) {
xlsxioread_sheet_close(sheet_handle->handle);
}
delete(sheet_handle);
}
static int list_callback(const XLSXIOCHAR* name, void* cbdata) {
auto sheetNames = (std::vector<std::string> *)cbdata;
sheetNames->push_back(name);
return 0;
}
// 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(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) {
char* result;
if (!xlsxioread_sheet_next_cell_string(sheet_handle->handle, &result)) {
value.clear();
return false;
}
value.assign(result);
free(result);
return true;
}
// 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_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) {
auto file_handle = (xlsx_file_handle *)get_xlsxreader_handle(L);
CHECK_NULL_POINTER(file_handle->handle);
auto sheetNames = std::vector<std::string>();
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, limited to the
// requested number of tokens if specified and > 0, or nil if we already
// processed the last row in the file.
int get_row(lua_State *L) {
auto sheet_handle = (xlsx_sheet_handle *)get_xlsxreader_handle(L);
CHECK_NULL_POINTER(sheet_handle->handle);
lua_Integer max_tokens = luaL_optinteger(L, 2, 0);
bool ok = get_next_row(sheet_handle);
if (!ok) {
lua_pushnil(L);
} else {
std::string value;
auto cells = std::vector<std::string>();
while (get_next_cell(sheet_handle, value)) {
// read all cells in the row, even if we don't need to;
// otherwise xlsxio will return a spurious empty row on
// next call
if (max_tokens <= 0 || int(cells.size()) < max_tokens) {
cells.push_back(value);
}
}
Lua::PushVector(L, cells, true);
}
return 1;
}
DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(open_xlsx_file),
DFHACK_LUA_FUNCTION(close_xlsx_file),
DFHACK_LUA_FUNCTION(open_sheet),
DFHACK_LUA_FUNCTION(close_sheet),
DFHACK_LUA_END
};
DFHACK_PLUGIN_LUA_COMMANDS{
DFHACK_LUA_COMMAND(list_sheets),
DFHACK_LUA_COMMAND(get_row),
DFHACK_LUA_END
};
DFhackCExport command_result plugin_init(color_ostream &,
std::vector<PluginCommand> &) {
return CR_OK;
}
DFhackCExport command_result plugin_shutdown(color_ostream &) {
return CR_OK;
}