1 °³¿ä
LuaCsv.zip
·ç¾Æ¸¦ ÀÌ¿ëÇØ¼ CSV ÆÄÀÏÀ» ´Ù·ç±â À§ÇØ DLLÀ» ¸¸µé¾ú´Ù. ·ç¾Æ¿¡¼ DLL ÆÄÀÏÀ» ·ÎµåÇÏ´Â ¹æ¹ýÀº LuaBinaryExtension ÆäÀÌÁö¸¦ Âü°íÇϱ⠹ٶõ´Ù. Visual C++ CRT ¶óÀ̺귯¸®¸¦ Á¤ÀûÀ¸·Î ¸µÅ©ÇØ ¹ö·È´õ´Ï ÇÏ´Â ÀÏ¿¡ ºñÇØ Å©±â°¡ ²Ï Ä¿Àú¹ö·È´Ù. Â¥Áõ³ª´Â ºÐµéÀº ¾Æ·¡ÀÇ ¼Ò½º¸¦ µû·Î ºôµåÇϽñæ.
2 »ç¿ë¹ý
2.1 ºÒ·¯¿À±â
2.2 ÀúÀåÇϱâ
- ÀúÀå ÇÔ¼ö¿¡ 2Â÷¿ø ¹è¿À» ³Ñ±â¸é µÈ´Ù.
- ¹®ÀÚ¿, ¼ýÀÚ, ºÒ¸° °ª¸¸ ÀúÀåÀÌ °¡´ÉÇÏ´Ù.
- NIL °ªÀº ±×³É ºó ¹®ÀÚ¿·Î ÀúÀåÀÌ µÈ´Ù.
require("LuaCsv")
t = {{1,2},{3,4}}
csv.save_to_file(t, "test.csv") -- ÆÄÀÏ·Î ÀúÀå
print(csv.save_to_string(t)) -- ¹®ÀÚ¿·Î ÀúÀå
2.3 µû¿ÈÇ¥¿Í ºÐ¸®ÀÚ ¼³Á¤
require("LuaCsv")
print(csv.seperator)
print(csv.quote)
print(csv.version)
3 ¼Ò½º
////////////////////////////////////////////////////////////////////////////////
/// \file LuaCsv.cpp
/// \author excel96
/// \date 2007.3.7
////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <fstream>
#include <sstream>
#include <vector>
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
const char* MODULE_NAME = "csv";
const char* MODULE_VERSION = "1.0";
const char DEFAULT_SEPERATOR = ',';
const char DEFAULT_QUOTE = '"';
const char* VERSION_NAME = "version";
const char* SEPERATOR_NAME = "seperator";
const char* QUOTE_NAME = "quote";
typedef std::vector<std::string> ROW;
typedef std::vector<ROW> ROWS;
char get_seperator(lua_State* L)
{
char seperator = DEFAULT_SEPERATOR;
lua_getfield(L, LUA_GLOBALSINDEX, MODULE_NAME);
if (lua_type(L, -1) == LUA_TTABLE)
{
lua_getfield(L, -1, SEPERATOR_NAME);
if (lua_type(L, -1) == LUA_TNUMBER)
seperator = static_cast<char>(lua_tonumber(L, -1));
lua_pop(L, 1);
}
lua_pop(L, 1);
return seperator;
}
char get_quote(lua_State* L)
{
char quote = DEFAULT_QUOTE;
lua_getfield(L, LUA_GLOBALSINDEX, MODULE_NAME);
if (lua_type(L, -1) == LUA_TTABLE)
{
lua_getfield(L, -1, QUOTE_NAME);
if (lua_type(L, -1) == LUA_TNUMBER)
quote = static_cast<char>(lua_tonumber(L, -1));
lua_pop(L, 1);
}
lua_pop(L, 1);
return quote;
}
int load(lua_State* L, std::istream& stream, char seperator, char quote)
{
enum ParseState
{
STATE_NORMAL, // ÀÏ¹Ý »óÅÂ
STATE_QUOTE // µû¿ÈÇ¥ µÚÀÇ »óÅÂ
};
if (!stream.good())
return luaL_error(L, "invalid stream");
ROWS rows;
ROW* row = NULL;
ParseState state = STATE_NORMAL;
std::string text = "";
std::string token = "";
int lineNumber = 0;
while (stream.good())
{
++lineNumber;
std::getline(stream, text);
if (text.empty() || (state == STATE_NORMAL && text[0] == '#'))
continue;
text.append(" ");
const char* cur = text.c_str();
const char* end = cur + text.size();
while (cur < end)
{
if (state == STATE_QUOTE)
{
if (*cur == quote)
{
if (*(cur + 1) == quote)
{
token.append(1, quote);
++cur;
}
else
{
state = STATE_NORMAL;
}
}
else
{
token.append(1, *cur);
}
}
else if (state == STATE_NORMAL)
{
if (row == NULL)
{
rows.push_back(ROW());
row = &(rows.back());
}
if (*cur == seperator)
{
row->push_back(token);
token.clear();
}
else if (*cur == quote)
{
state = STATE_QUOTE;
}
else
{
token.append(1, *cur);
}
}
++cur;
}
if (state == STATE_NORMAL)
{
if (row)
{
row->push_back(token.erase(token.size()-2, 2));
token.clear();
row = NULL;
}
}
else
{
token.erase(token.size()-2, 2);
token.append("\r\n");
}
}
lua_newtable(L);
for (size_t j=0; j<rows.size(); ++j)
{
lua_pushnumber(L, static_cast<int>(j+1));
lua_newtable(L);
const ROW& r = rows[j];
for (size_t i=0; i<r.size(); ++i)
{
lua_pushnumber(L, static_cast<int>(i+1));
lua_pushstring(L, r[i].c_str());
lua_rawset(L, -3);
}
lua_rawset(L, -3);
}
return 1;
}
static void save(lua_State* L, std::ostream& stream, char seperator, char quote)
{
luaL_checktype(L, -1, LUA_TTABLE);
ROWS rows;
int rowCount = 1;
int colCount = 1;
lua_pushnil(L);
while (lua_next(L, -2) != 0)
{
luaL_checktype(L, -1, LUA_TTABLE);
ROW row;
lua_pushnil(L);
while (lua_next(L, -2) != 0)
{
switch (lua_type(L, -1))
{
case LUA_TSTRING:
row.push_back(lua_tostring(L, -1));
break;
case LUA_TNUMBER:
row.push_back(lua_tostring(L, -1));
break;
case LUA_TBOOLEAN:
row.push_back(lua_toboolean(L, -1) ? "true" : "false");
break;
case LUA_TNIL:
row.push_back("nil");
break;
default:
luaL_error(L,
"cannot convert (%s) column to string (row:%d,col:%d)",
lua_typename(L, -1), rows.size() + 1, row.size() + 1
);
break;
}
lua_pop(L, 1);
}
lua_pop(L, 1);
rows.push_back(row);
}
char specialChars[5] = { seperator, quote, '\r', '\n', 0 };
char quoteEscapeString[3] = { quote, quote, 0 };
for (size_t i=0; i<rows.size(); i++)
{
const ROW& row = rows[i];
std::string line;
for (size_t j=0; j<row.size(); j++)
{
const std::string& token = row[j];
if (token.find_first_of(specialChars) == std::string::npos)
{
line.append(token);
}
else
{
line.append(1, quote);
for (size_t k=0; k<token.size(); k++)
{
if (token[k] == quote) line.append(quoteEscapeString);
else line.append(1, token[k]);
}
line.append(1, quote);
}
if (j != row.size() - 1) { line.append(1, seperator); }
}
stream << line << std::endl;
}
}
static int load_from_file(lua_State* L)
{
const char* fileName = luaL_checkstring(L, -1);
std::ifstream file(fileName, std::ios::in);
if (!file)
return luaL_error(L, "cannot open specified file");
char seperator = get_seperator(L);
char quote = get_quote(L);
return load(L, file, seperator, quote);
}
static int load_from_string(lua_State* L)
{
const char* str = luaL_checkstring(L, -1);
char seperator = get_seperator(L);
char quote = get_quote(L);
std::stringstream memory(str);
memory.imbue(std::locale::classic());
return load(L, memory, seperator, quote);
}
static int save_to_file(lua_State* L)
{
luaL_checktype(L, -1, LUA_TSTRING);
luaL_checktype(L, -2, LUA_TTABLE);
std::ofstream file(lua_tostring(L, -1), std::ios::out | std::ios::trunc);
if (!file)
return luaL_error(L, "cannot open specified file");
lua_pop(L, 1);
char seperator = get_seperator(L);
char quote = get_quote(L);
save(L, file, seperator, quote);
return 0;
}
static int save_to_string(lua_State* L)
{
luaL_checktype(L, -2, LUA_TTABLE);
std::stringstream memory;
memory.imbue(std::locale::classic());
char seperator = get_seperator(L);
char quote = get_quote(L);
save(L, memory, seperator, quote);
lua_pushstring(L, memory.str().c_str());
return 1;
}
int __declspec(dllexport) luaopen_LuaCsv(lua_State* L)
{
static const luaL_Reg csvlib[] =
{
{ "load_from_file", load_from_file },
{ "load_from_string", load_from_string },
{ "save_to_file", save_to_file },
{ "save_to_string", save_to_string },
{ NULL, NULL }
};
luaL_register(L, MODULE_NAME, csvlib);
lua_pushnumber(L, DEFAULT_SEPERATOR);
lua_setfield(L, -2, SEPERATOR_NAME);
lua_pushnumber(L, DEFAULT_QUOTE);
lua_setfield(L, -2, QUOTE_NAME);
lua_pushstring(L, MODULE_VERSION);
lua_setfield(L, -2, VERSION_NAME);
return 0;
}
}
#ifdef _DEBUG
#pragma comment(lib, "lualibDebug")
#else
#pragma comment(lib, "lualib")
#endif
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
hModule = hModule;
ul_reason_for_call = ul_reason_for_call;
lpReserved = lpReserved;
return TRUE;
}
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)