From 8076fb2791efd1054802c970b92bcf06c6fd16ec Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Tue, 22 Apr 2014 19:21:00 +0200 Subject: [PATCH 01/13] Basic storage and loading/saving for extradata --- src/ass_dialogue.cpp | 34 ++++++++++++++++++++- src/ass_dialogue.h | 3 ++ src/ass_entry.cpp | 2 ++ src/ass_entry.h | 1 + src/ass_file.cpp | 60 +++++++++++++++++++++++++++++++++++++ src/ass_file.h | 20 ++++++++++++- src/ass_parser.cpp | 20 +++++++++++++ src/ass_parser.h | 1 + src/subtitle_format_ass.cpp | 20 +++++++++++++ 9 files changed, 159 insertions(+), 2 deletions(-) diff --git a/src/ass_dialogue.cpp b/src/ass_dialogue.cpp index 38577ca75..73c272cfd 100644 --- a/src/ass_dialogue.cpp +++ b/src/ass_dialogue.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -120,7 +121,28 @@ void AssDialogue::Parse(std::string const& raw) { for (int& margin : Margin) margin = mid(0, boost::lexical_cast(tkn.next_str()), 9999); Effect = tkn.next_str_trim(); - Text = std::string(tkn.next_tok().begin(), str.end()); + + std::string text{tkn.next_tok().begin(), str.end()}; + + static const boost::regex extradata_test("^\\{(=\\d+)+\\}"); + boost::match_results rematch; + if (boost::regex_search(text.begin(), text.end(), rematch, extradata_test)) { + std::string extradata_str = rematch.str(0); + text = rematch.suffix().str(); + + static const boost::regex idmatcher("=(\\d+)"); + auto start = extradata_str.begin(); + auto end = extradata_str.end(); + std::vector ids; + while (boost::regex_search(start, end, rematch, idmatcher)) { + auto id = boost::lexical_cast(rematch.str(1)); + ids.push_back(id); + start = rematch.suffix().second; + } + ExtradataIds = ids; + } + + Text = text; } void append_int(std::string &str, int v) { @@ -156,6 +178,16 @@ std::string AssDialogue::GetData(bool ssa) const { for (auto margin : Margin) append_int(str, margin); append_unsafe_str(str, Effect); + + if (ExtradataIds.get().size() > 0) { + str += "{"; + for (auto id : ExtradataIds.get()) { + str += "="; + boost::spirit::karma::generate(back_inserter(str), boost::spirit::karma::int_, id); + } + str += "}"; + } + str += Text.get(); if (str.find('\n') != str.npos || str.find('\r') != str.npos) { diff --git a/src/ass_dialogue.h b/src/ass_dialogue.h index 2a1dd28b0..affa6809a 100644 --- a/src/ass_dialogue.h +++ b/src/ass_dialogue.h @@ -146,6 +146,8 @@ struct AssDialogueBase { boost::flyweight Actor; /// Effect name boost::flyweight Effect; + /// IDs of extradata entries for line + boost::flyweight> ExtradataIds; /// Raw text data boost::flyweight Text; }; @@ -183,3 +185,4 @@ public: AssDialogue(std::string const& data); ~AssDialogue(); }; + diff --git a/src/ass_entry.cpp b/src/ass_entry.cpp index 30ec7f8dc..bdf486b0f 100644 --- a/src/ass_entry.cpp +++ b/src/ass_entry.cpp @@ -28,6 +28,7 @@ std::string const& AssEntry::GroupHeader(bool ssa) const { "[Fonts]", "[Graphics]", "[Events]", + "[Aegisub Extradata]", "" }; @@ -37,6 +38,7 @@ std::string const& AssEntry::GroupHeader(bool ssa) const { "[Fonts]", "[Graphics]", "[Events]", + "[Aegisub Extradata]", "" }; diff --git a/src/ass_entry.h b/src/ass_entry.h index f03d10336..9556ef18a 100644 --- a/src/ass_entry.h +++ b/src/ass_entry.h @@ -43,6 +43,7 @@ enum class AssEntryGroup { FONT, GRAPHIC, DIALOGUE, + EXTRADATA, GROUP_MAX }; diff --git a/src/ass_file.cpp b/src/ass_file.cpp index 8ceafe5d1..9d07b6220 100644 --- a/src/ass_file.cpp +++ b/src/ass_file.cpp @@ -26,6 +26,7 @@ #include #include #include +#include AssFile::AssFile() { } @@ -54,6 +55,8 @@ void AssFile::LoadDefault(bool include_dialogue_line) { AssFile::AssFile(const AssFile &from) : Info(from.Info) , Attachments(from.Attachments) +, Extradata(from.Extradata) +, next_extradata_id(from.next_extradata_id) { Styles.clone_from(from.Styles, [](AssStyle const& e) { return new AssStyle(e); }, @@ -68,6 +71,8 @@ void AssFile::swap(AssFile& from) throw() { Styles.swap(from.Styles); Events.swap(from.Events); Attachments.swap(from.Attachments); + Extradata.swap(from.Extradata); + std::swap(next_extradata_id, from.next_extradata_id); } AssFile& AssFile::operator=(AssFile from) { @@ -229,3 +234,58 @@ void AssFile::Sort(EntryList &lst, CompFunc comp, std::set AssFile::GetExtradata(std::vector const& id_list) const { + // If multiple IDs have the same key name, the last ID wins + std::map result; + for (auto id : id_list) { + auto it = Extradata.find(id); + if (it != Extradata.end()) + result[it->second.first] = it->second.second; + } + return result; +} + +void AssFile::CleanExtradata() { + // Collect all IDs existing in the database + // Then remove all IDs found to be in use from this list + // Remaining is then all garbage IDs + std::vector ids; + for (auto& it : Extradata) { + ids.push_back(it.first); + } + + // For each line, find which IDs it actually uses and remove them from the unused-list + for (auto& line : Events) { + // Find the ID for each unique key in the line + std::map key_ids; + for (auto id : line.ExtradataIds.get()) { + auto ed_it = Extradata.find(id); + if (ed_it == Extradata.end()) + continue; + key_ids[ed_it->second.first] = id; + } + // Update the line's ID list to only contain the actual ID for any duplicate keys + // Also mark found IDs as used in the cleaning list + std::vector new_ids; + for (auto& keyid : key_ids) { + new_ids.push_back(keyid.second); + ids.erase(std::remove(ids.begin(), ids.end(), keyid.second)); + } + line.ExtradataIds = new_ids; + } + + // The ids list should contain only unused IDs now + for (auto id : ids) { + Extradata.erase(id); + } +} + diff --git a/src/ass_file.h b/src/ass_file.h index 7ed814e5e..9c1bd9ae8 100644 --- a/src/ass_file.h +++ b/src/ass_file.h @@ -50,6 +50,8 @@ class wxString; template using EntryList = typename boost::intrusive::make_list, boost::intrusive::base_hook>::type; +using AegisubExtradataMap = std::map>; + struct AssFileCommit { wxString const& message; int *commit_id; @@ -66,6 +68,9 @@ public: EntryList Styles; EntryList Events; std::vector Attachments; + AegisubExtradataMap Extradata; + + uint32_t next_extradata_id = 0; AssFile(); AssFile(const AssFile &from); @@ -102,6 +107,16 @@ public: int GetUIStateAsInt(std::string const& key) const; void SaveUIState(std::string const& key, std::string const& value); + /// @brief Add a new extradata entry + /// @param key Class identifier/owner for the extradata + /// @param value Data for the extradata + /// @return ID of the created entry + uint32_t AddExtradata(std::string const& key, std::string const& value); + /// Fetch all extradata entries from a list of IDs + std::map GetExtradata(std::vector const& id_list) const; + /// Remove unreferenced extradata entries + void CleanExtradata(); + /// Type of changes made in a commit enum CommitType { /// Potentially the entire file has been changed; any saved information @@ -129,7 +144,9 @@ public: COMMIT_DIAG_TIME = 0x40, /// The text of existing dialogue lines have changed COMMIT_DIAG_TEXT = 0x80, - COMMIT_DIAG_FULL = COMMIT_DIAG_META | COMMIT_DIAG_TIME | COMMIT_DIAG_TEXT + COMMIT_DIAG_FULL = COMMIT_DIAG_META | COMMIT_DIAG_TIME | COMMIT_DIAG_TEXT, + /// Extradata entries were added/modified/removed + COMMIT_EXTRADATA = 0x100, }; DEFINE_SIGNAL_ADDERS(AnnounceCommit, AddCommitListener) @@ -168,3 +185,4 @@ public: /// @param limit If non-empty, only lines in this set are sorted static void Sort(EntryList& lst, CompFunc comp = CompStart, std::set const& limit = std::set()); }; + diff --git a/src/ass_parser.cpp b/src/ass_parser.cpp index 1099cc7a7..478704eb5 100644 --- a/src/ass_parser.cpp +++ b/src/ass_parser.cpp @@ -19,12 +19,15 @@ #include "ass_file.h" #include "ass_info.h" #include "ass_style.h" +#include "string_codec.h" #include "subtitle_format.h" #include #include #include #include +#include +#include AssParser::AssParser(AssFile *target, int version) : target(target) @@ -111,6 +114,21 @@ void AssParser::ParseGraphicsLine(std::string const& data) { attach.reset(new AssAttachment(data, AssEntryGroup::GRAPHIC)); } +void AssParser::ParseExtradataLine(std::string const &data) { + static const boost::regex matcher("Data:[[:space:]]*(\\d+),([^,]+),(.*)"); + boost::match_results mr; + + if (boost::regex_match(data, mr, matcher)) { + auto id = boost::lexical_cast(mr.str(1)); + auto key = inline_string_decode(mr.str(2)); + auto value = inline_string_decode(mr.str(3)); + + // ensure next_extradata_id is always at least 1 more than the largest existing id + target->next_extradata_id = std::max(id+1, target->next_extradata_id); + target->Extradata[id] = std::make_pair(key, value); + } +} + void AssParser::AddLine(std::string const& data) { // Special-case for attachments since a line could theoretically be both a // valid attachment data line and a valid section header, and if an @@ -142,6 +160,8 @@ void AssParser::AddLine(std::string const& data) { state = &AssParser::ParseGraphicsLine; else if (low == "[fonts]") state = &AssParser::ParseFontLine; + else if (low == "[aegisub extradata]") + state = &AssParser::ParseExtradataLine; else state = &AssParser::UnknownLine; return; diff --git a/src/ass_parser.h b/src/ass_parser.h index b97bba766..c51c20204 100644 --- a/src/ass_parser.h +++ b/src/ass_parser.h @@ -31,6 +31,7 @@ class AssParser { void ParseScriptInfoLine(std::string const& data); void ParseFontLine(std::string const& data); void ParseGraphicsLine(std::string const& data); + void ParseExtradataLine(std::string const &data); void UnknownLine(std::string const&) { } public: AssParser(AssFile *target, int version); diff --git a/src/subtitle_format_ass.cpp b/src/subtitle_format_ass.cpp index 3fdc30e39..3d5972a36 100644 --- a/src/subtitle_format_ass.cpp +++ b/src/subtitle_format_ass.cpp @@ -22,6 +22,7 @@ #include "ass_file.h" #include "ass_style.h" #include "ass_parser.h" +#include "string_codec.h" #include "text_file_reader.h" #include "text_file_writer.h" #include "version.h" @@ -114,6 +115,24 @@ struct Writer { file.WriteLineToFile(ssa ? line.GetSSAText() : line.GetEntryData()); } } + + void WriteExtradata(AegisubExtradataMap const& extradata) { + if (extradata.size() == 0) + return; + + group = AssEntryGroup::EXTRADATA; + file.WriteLineToFile(""); + file.WriteLineToFile("[Aegisub Extradata]"); + for (auto const& edi : extradata) { + std::string line = "Data: "; + line += std::to_string(edi.first); + line += ","; + line += inline_string_encode(edi.second.first); + line += ","; + line += inline_string_encode(edi.second.second); + file.WriteLineToFile(line); + } + } }; } @@ -124,4 +143,5 @@ void AssSubtitleFormat::WriteFile(const AssFile *src, agi::fs::path const& filen writer.Write(src->Styles); writer.Write(src->Attachments); writer.Write(src->Events); + writer.WriteExtradata(src->Extradata); } From 040b467090c6a4acda74860ea02574724a210a03 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Wed, 23 Apr 2014 16:54:41 +0200 Subject: [PATCH 02/13] Add undo support for extradata --- src/subs_controller.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/subs_controller.cpp b/src/subs_controller.cpp index 4f3aae793..314354443 100644 --- a/src/subs_controller.cpp +++ b/src/subs_controller.cpp @@ -60,6 +60,7 @@ struct SubsController::UndoInfo { std::vector styles; std::vector events; std::vector attachments; + AegisubExtradataMap extradata; mutable std::vector selection; int active_line_id = 0; @@ -69,6 +70,7 @@ struct SubsController::UndoInfo { : undo_description(d) , commit_id(commit_id) , attachments(c->ass->Attachments) + , extradata(c->ass->Extradata) { script_info.reserve(c->ass->Info.size()); for (auto const& info : c->ass->Info) @@ -108,6 +110,7 @@ struct SubsController::UndoInfo { if (binary_search(begin(selection), end(selection), copy->Id)) new_sel.insert(copy); } + c->ass->Extradata = extradata; c->ass->Commit("", AssFile::COMMIT_NEW); c->selectionController->SetSelectionAndActive(std::move(new_sel), active_line); From 159dfcde3931a885127310af8c64c1e6179d119a Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Wed, 23 Apr 2014 21:50:26 +0200 Subject: [PATCH 03/13] Add extradata reading/writing to Auto4 Lua --- src/auto4_lua.cpp | 12 ++++++++++++ src/auto4_lua.h | 2 +- src/auto4_lua_assfile.cpp | 32 +++++++++++++++++++++++++++----- src/auto4_lua_utils.h | 5 +++-- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/auto4_lua.cpp b/src/auto4_lua.cpp index 194c110dc..26d2768f2 100644 --- a/src/auto4_lua.cpp +++ b/src/auto4_lua.cpp @@ -56,6 +56,7 @@ #include #include +#include #include #include #include @@ -274,6 +275,17 @@ namespace { luaL_argcheck(L, lua_istable(L, 1), 1, ""); luaL_argcheck(L, lua_isstring(L, 2), 2, ""); + // have to check that it looks like a style table before actually converting + // if it's a dialogue table then an active AssFile object is required + { + lua_getfield(L, 1, "class"); + std::string actual_class{lua_tostring(L, -1)}; + boost::to_lower(actual_class); + if (actual_class != "style") + return luaL_error(L, "Not a style entry"); + lua_pop(L, 1); + } + lua_pushvalue(L, 1); std::unique_ptr et(Automation4::LuaAssFile::LuaToAssEntry(L)); auto st = dynamic_cast(et.get()); diff --git a/src/auto4_lua.h b/src/auto4_lua.h index 9695c3ad9..e2b2a7369 100644 --- a/src/auto4_lua.h +++ b/src/auto4_lua.h @@ -124,7 +124,7 @@ namespace Automation4 { /// makes a Lua representation of AssEntry and places on the top of the stack void AssEntryToLua(lua_State *L, size_t idx); /// assumes a Lua representation of AssEntry on the top of the stack, and creates an AssEntry object of it - static std::unique_ptr LuaToAssEntry(lua_State *L); + static std::unique_ptr LuaToAssEntry(lua_State *L, AssFile *ass=0); /// @brief Signal that the script using this file is now done running /// @param set_undo If there's any uncommitted changes to the file, diff --git a/src/auto4_lua_assfile.cpp b/src/auto4_lua_assfile.cpp index b21bbcfdf..f397568b6 100644 --- a/src/auto4_lua_assfile.cpp +++ b/src/auto4_lua_assfile.cpp @@ -173,6 +173,15 @@ namespace Automation4 { set_field(L, "text", dia->Text); + // create extradata table + lua_newtable(L); + for (auto const& ed : ass->GetExtradata(dia->ExtradataIds)) { + push_value(L, ed.first); + push_value(L, ed.second); + lua_settable(L, -3); + } + lua_setfield(L, -2, "extra"); + set_field(L, "class", "dialogue"); } else if (auto sty = dynamic_cast(e)) { @@ -221,7 +230,7 @@ namespace Automation4 { } } - std::unique_ptr LuaAssFile::LuaToAssEntry(lua_State *L) + std::unique_ptr LuaAssFile::LuaToAssEntry(lua_State *L, AssFile *ass) { // assume an assentry table is on the top of the stack // convert it to a real AssEntry object, and pop the table from the stack @@ -271,6 +280,7 @@ namespace Automation4 { sty->UpdateData(); } else if (lclass == "dialogue") { + assert(ass != 0); // since we need AssFile::AddExtradata auto dia = new AssDialogue; result.reset(dia); @@ -285,6 +295,18 @@ namespace Automation4 { dia->Margin[2] = get_int_field(L, "margin_t", "dialogue"); dia->Effect = get_string_field(L, "effect", "dialogue"); dia->Text = get_string_field(L, "text", "dialogue"); + + lua_getfield(L, -1, "extra"); + std::vector new_ids; + lua_pushnil(L); + while (lua_next(L, -2)) { + auto key = get_string_or_default(L, -2); + auto value = get_string_or_default(L, -1); + new_ids.push_back(ass->AddExtradata(key, value)); + lua_pop(L, 1); + } + lua_pop(L, 1); + dia->ExtradataIds = new_ids; } else { luaL_error(L, "Found line with unknown class: %s", lclass.c_str()); @@ -422,7 +444,7 @@ namespace Automation4 { // insert CheckBounds(n); - auto e = LuaToAssEntry(L); + auto e = LuaToAssEntry(L, ass); modification_type |= modification_mask(e.get()); QueueLineForDeletion(n - 1); AssignLine(n - 1, std::move(e)); @@ -511,7 +533,7 @@ namespace Automation4 { for (int i = 1; i <= n; i++) { lua_pushvalue(L, i); - auto e = LuaToAssEntry(L); + auto e = LuaToAssEntry(L, ass); modification_type |= modification_mask(e.get()); if (lines.empty()) { @@ -555,7 +577,7 @@ namespace Automation4 { new_entries.reserve(n - 1); for (int i = 2; i <= n; i++) { lua_pushvalue(L, i); - auto e = LuaToAssEntry(L); + auto e = LuaToAssEntry(L, ass); modification_type |= modification_mask(e.get()); InsertLine(new_entries, i - 2, std::move(e)); lua_pop(L, 1); @@ -594,7 +616,7 @@ namespace Automation4 { int LuaAssFile::LuaParseKaraokeData(lua_State *L) { - auto e = LuaToAssEntry(L); + auto e = LuaToAssEntry(L, ass); auto dia = dynamic_cast(e.get()); luaL_argcheck(L, dia, 1, "Subtitle line must be a dialogue line"); diff --git a/src/auto4_lua_utils.h b/src/auto4_lua_utils.h index a9e9c9a92..9639121c6 100644 --- a/src/auto4_lua_utils.h +++ b/src/auto4_lua_utils.h @@ -71,10 +71,11 @@ inline wxString check_wxstring(lua_State *L, int idx) { } inline std::string get_string_or_default(lua_State *L, int idx) { - const char *str = lua_tostring(L, idx); + size_t len = 0; + const char *str = lua_tolstring(L, idx, &len); if (!str) str = ""; - return str; + return std::string(str, len); } inline std::string get_global_string(lua_State *L, const char *name) { From cf81e9138337712623f3bbe99cedf0c2fc335fa9 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Wed, 23 Apr 2014 22:00:38 +0200 Subject: [PATCH 04/13] Perform extradata garbage collection on save --- src/subs_controller.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/subs_controller.cpp b/src/subs_controller.cpp index 314354443..de1f8a954 100644 --- a/src/subs_controller.cpp +++ b/src/subs_controller.cpp @@ -270,6 +270,8 @@ void SubsController::Save(agi::fs::path const& filename, std::string const& enco FileSave(); + context->ass->CleanExtradata(); + writer->WriteFile(context->ass.get(), filename, 0, encoding); } catch (...) { From b4801ef1bb94b87261a8fc5a73be87ae68d21426 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 24 Apr 2014 18:09:45 +0200 Subject: [PATCH 05/13] Import luabins 831869cdc8c5e7579804e6472a2dc6cbe0b2672b --- vendor/luabins/AUTHORS | 4 + vendor/luabins/BENCHMARK | 51 ++ vendor/luabins/COPYRIGHT | 32 + vendor/luabins/HISTORY | 47 + vendor/luabins/Makefile | 469 ++++++++++ vendor/luabins/README.md | 112 +++ vendor/luabins/TODO | 11 + vendor/luabins/etc/Makefile.luabins.template | 242 ++++++ vendor/luabins/etc/benchmark.lua | 106 +++ vendor/luabins/etc/checkfmt.lua | 30 + vendor/luabins/etc/dataset.lua | 90 ++ vendor/luabins/etc/genmakefile.sh | 2 + vendor/luabins/etc/tolua.lua | 39 + vendor/luabins/etc/toluabins.lua | 16 + vendor/luabins/include/.keepme | 0 vendor/luabins/lib/.keepme | 0 vendor/luabins/obj/.keepme | 0 .../luabins/rockspec/luabins-0.1.1-1.rockspec | 19 + .../luabins/rockspec/luabins-0.1.1-2.rockspec | 32 + .../luabins/rockspec/luabins-0.2-1.rockspec | 35 + .../luabins/rockspec/luabins-0.3-1.rockspec | 35 + .../luabins/rockspec/luabins-scm-1.rockspec | 32 + .../luabins/rockspec/luabins-scm-2.rockspec | 35 + vendor/luabins/src/fwrite.c | 49 ++ vendor/luabins/src/fwrite.h | 37 + vendor/luabins/src/load.c | 367 ++++++++ vendor/luabins/src/luabins.c | 104 +++ vendor/luabins/src/luabins.h | 69 ++ vendor/luabins/src/luaheaders.h | 14 + vendor/luabins/src/luainternals.c | 54 ++ vendor/luabins/src/luainternals.h | 53 ++ vendor/luabins/src/lualess.c | 32 + vendor/luabins/src/lualess.h | 33 + vendor/luabins/src/save.c | 236 +++++ vendor/luabins/src/savebuffer.c | 252 ++++++ vendor/luabins/src/savebuffer.h | 91 ++ vendor/luabins/src/saveload.h | 114 +++ vendor/luabins/src/write.c | 75 ++ vendor/luabins/src/write.h | 44 + vendor/luabins/test/large_data.lua | 38 + vendor/luabins/test/large_data.luabins | Bin 0 -> 9590 bytes vendor/luabins/test/test.c | 25 + vendor/luabins/test/test.h | 25 + vendor/luabins/test/test.lua | 813 ++++++++++++++++++ vendor/luabins/test/test_api.c | 311 +++++++ vendor/luabins/test/test_fwrite_api.c | 112 +++ vendor/luabins/test/test_savebuffer.c | 499 +++++++++++ vendor/luabins/test/test_write_api.c | 130 +++ vendor/luabins/test/util.c | 17 + vendor/luabins/test/util.h | 14 + vendor/luabins/test/write_tests.inc | 175 ++++ vendor/luabins/tmp/.keepme | 0 52 files changed, 5222 insertions(+) create mode 100644 vendor/luabins/AUTHORS create mode 100644 vendor/luabins/BENCHMARK create mode 100644 vendor/luabins/COPYRIGHT create mode 100644 vendor/luabins/HISTORY create mode 100644 vendor/luabins/Makefile create mode 100644 vendor/luabins/README.md create mode 100644 vendor/luabins/TODO create mode 100644 vendor/luabins/etc/Makefile.luabins.template create mode 100644 vendor/luabins/etc/benchmark.lua create mode 100644 vendor/luabins/etc/checkfmt.lua create mode 100644 vendor/luabins/etc/dataset.lua create mode 100755 vendor/luabins/etc/genmakefile.sh create mode 100644 vendor/luabins/etc/tolua.lua create mode 100644 vendor/luabins/etc/toluabins.lua create mode 100644 vendor/luabins/include/.keepme create mode 100644 vendor/luabins/lib/.keepme create mode 100644 vendor/luabins/obj/.keepme create mode 100644 vendor/luabins/rockspec/luabins-0.1.1-1.rockspec create mode 100644 vendor/luabins/rockspec/luabins-0.1.1-2.rockspec create mode 100644 vendor/luabins/rockspec/luabins-0.2-1.rockspec create mode 100644 vendor/luabins/rockspec/luabins-0.3-1.rockspec create mode 100644 vendor/luabins/rockspec/luabins-scm-1.rockspec create mode 100644 vendor/luabins/rockspec/luabins-scm-2.rockspec create mode 100644 vendor/luabins/src/fwrite.c create mode 100644 vendor/luabins/src/fwrite.h create mode 100644 vendor/luabins/src/load.c create mode 100644 vendor/luabins/src/luabins.c create mode 100644 vendor/luabins/src/luabins.h create mode 100644 vendor/luabins/src/luaheaders.h create mode 100644 vendor/luabins/src/luainternals.c create mode 100644 vendor/luabins/src/luainternals.h create mode 100644 vendor/luabins/src/lualess.c create mode 100644 vendor/luabins/src/lualess.h create mode 100644 vendor/luabins/src/save.c create mode 100644 vendor/luabins/src/savebuffer.c create mode 100644 vendor/luabins/src/savebuffer.h create mode 100644 vendor/luabins/src/saveload.h create mode 100644 vendor/luabins/src/write.c create mode 100644 vendor/luabins/src/write.h create mode 100644 vendor/luabins/test/large_data.lua create mode 100644 vendor/luabins/test/large_data.luabins create mode 100644 vendor/luabins/test/test.c create mode 100644 vendor/luabins/test/test.h create mode 100644 vendor/luabins/test/test.lua create mode 100644 vendor/luabins/test/test_api.c create mode 100644 vendor/luabins/test/test_fwrite_api.c create mode 100644 vendor/luabins/test/test_savebuffer.c create mode 100644 vendor/luabins/test/test_write_api.c create mode 100644 vendor/luabins/test/util.c create mode 100644 vendor/luabins/test/util.h create mode 100644 vendor/luabins/test/write_tests.inc create mode 100644 vendor/luabins/tmp/.keepme diff --git a/vendor/luabins/AUTHORS b/vendor/luabins/AUTHORS new file mode 100644 index 000000000..c5bde58ea --- /dev/null +++ b/vendor/luabins/AUTHORS @@ -0,0 +1,4 @@ +Luabins authors: +---------------- + +Alexander Gladysh diff --git a/vendor/luabins/BENCHMARK b/vendor/luabins/BENCHMARK new file mode 100644 index 000000000..b74356c44 --- /dev/null +++ b/vendor/luabins/BENCHMARK @@ -0,0 +1,51 @@ +Luabins 0.2 benchmark (see etc/benchmark.lua) results on + + MacBook Pro 2.4 GHz Intel Core Duo 2.66 MB DDR2 SDRAM + OS X 10.6.2 + GCC 4.2.1 (Apple Inc. build 5646) (dot 1) + Lua 5.1.4 from MacPorts + Luabins built with default Makefile configuration + +Note that the data used in benchmark is quite trivial. You're advised +to find out if Luabins is "fast enough" for you by yourself. + +Lua +------------------------------------------------------------------- + name | rel | abs s / iter = us (1e-6 s) / iter +------------------------------------------------------------------- + luabins_save | 1.0000 | 4.21 / 1000000 = 4.210000 us + luabins_load | 1.2043 | 5.07 / 1000000 = 5.070000 us + loadstring | 4.7435 | 19.97 / 1000000 = 19.970000 us + concat | 10.6413 | 44.80 / 1000000 = 44.800000 us + +=================================================================== + +Luabins 0.1 benchmark (see etc/benchmark.lua) results on + + MacBook Pro 2.4 GHz Intel Core Duo 2.66 MB DDR2 SDRAM + OS X 10.5.6 + GCC 4.0.1 (Apple Inc. build 5490) + Lua 5.1.4 from MacPorts + LuaJIT 1.1.3 built from sources with default configuration + Luabins built with default configuration + +Note that the data used in benchmark is quite trivial. You're advised +to find out if Luabins is "fast enough" for you by yourself. + +Lua +------------------------------------------------------------------- + name | rel | abs s / iter = us (1e-6 s) / iter +------------------------------------------------------------------- + luabins_load | 1.0000 | 6.34 / 1000000 = 6.340000 us + luabins_save | 1.7256 | 10.94 / 1000000 = 10.940000 us + loadstring | 3.6530 | 23.16 / 1000000 = 23.160000 us + concat | 10.0741 | 63.87 / 1000000 = 63.870000 us + +LuaJIT -O +------------------------------------------------------------------- + name | rel | abs s / iter = us (1e-6 s) / iter +------------------------------------------------------------------- + luabins_load | 1.0000 | 5.40 / 1000000 = 5.400000 us + luabins_save | 1.6111 | 8.70 / 1000000 = 8.700000 us + concat | 6.6630 | 35.98 / 1000000 = 35.980000 us + loadstring | 23.6370 | 127.64 / 1000000 = 127.640000 us diff --git a/vendor/luabins/COPYRIGHT b/vendor/luabins/COPYRIGHT new file mode 100644 index 000000000..da6420e4b --- /dev/null +++ b/vendor/luabins/COPYRIGHT @@ -0,0 +1,32 @@ +Luabins License +--------------- + +Luabins is licensed under the terms of the MIT license reproduced below. +This means that luabins is free software and can be used for both academic +and commercial purposes at absolutely no cost. + +=============================================================================== + +Copyright (C) 2009-2010 Luabins authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/vendor/luabins/HISTORY b/vendor/luabins/HISTORY new file mode 100644 index 000000000..f235214ea --- /dev/null +++ b/vendor/luabins/HISTORY @@ -0,0 +1,47 @@ +v0.3 +==== + +Format unification for x86 and x86_64. Bug fixes. + +WARNING: Format is not compatible with 0.2 and below. + Only data saved on x86_64 is affected, though. + Data, saved on x86, should load fine. + +New features: + +-- Format change: unified save format for x86 vs. x86_64. +-- API to save data to FILE * stream without Lua (see fwrite.h). + +Bug fixes: + +-- Load: fixed bug in readbyte, now it checks if we have data before read. +-- Load: fixed Lua C stack overflow bug on large data. + +Misc: + +-- Better module information. + Replaced luabins.VERSION with _VERSION, _DESCRIPTION and _COPYRIGHT. +-- Added some CLI tools, useful for Luabins development (see etc/). +-- Some code cleanup. + +v0.2 +==== + +Lua-less saving. + +-- New, 2x faster luabins.save() (see BENCHMARK). +-- API to save data manually, without Lua (see write.h). +-- Added Luarocks rockspecs (see rockspec/). +-- Fixed Makefile for Ubuntu. + +v0.1.1 +====== + +Bugfix release. + +-- Fixed handling of array holes in Lua tables. + +v0.1 +==== + +Initial release. diff --git a/vendor/luabins/Makefile b/vendor/luabins/Makefile new file mode 100644 index 000000000..386738da1 --- /dev/null +++ b/vendor/luabins/Makefile @@ -0,0 +1,469 @@ +## CONFIGURATION ############################################################## + +ifeq ($(shell uname),Darwin) + LUA_DIR := /usr/local + LUA_LIBDIR := $(LUA_DIR)/lib/lua/5.1 + LUA_INCDIR := $(LUA_DIR)/include + LUALIB := lua +else + # Assuming Ubuntu + LUA_LIBDIR := /usr/lib + LUA_INCDIR := /usr/include/lua5.1 + LUALIB := lua5.1 +endif + +PROJECTNAME := luabins + +SONAME := $(PROJECTNAME).so +ANAME := lib$(PROJECTNAME).a +HNAME := $(PROJECTNAME).h +TESTNAME := $(PROJECTNAME)-test +TESTLUA := test.lua + +LUA := lua +CP := cp +RM := rm -f +RMDIR := rm -df +MKDIR := mkdir -p +CC := gcc +LD := gcc +AR := ar rcu +RANLIB := ranlib +ECHO := @echo +TOUCH := touch + +# Needed for tests only +CXX := g++ +LDXX := g++ + +OBJDIR := ./obj +TMPDIR := ./tmp +INCDIR := ./include +LIBDIR := ./lib + +HFILE := $(INCDIR)/$(HNAME) + +CFLAGS += -O2 -Wall -I$(LUA_INCDIR) +LDFLAGS += -L$(LUA_LIBDIR) + +# Tested on OS X and Ubuntu +SOFLAGS := +ifeq ($(shell uname),Darwin) + SOFLAGS += -dynamiclib -undefined dynamic_lookup +else + CFLAGS += -fPIC + SOFLAGS += -shared + LDFLAGS += -ldl + RMDIR := rm -rf +endif + +CFLAGS += $(MYCFLAGS) +LDFLAGS += $(MYLDFLAGS) + +## MAIN TARGETS ############################################################### + +all: $(LIBDIR)/$(SONAME) $(LIBDIR)/$(ANAME) $(HFILE) + +clean: cleanlibs cleantest + $(RM) $(HFILE) + +install: $(LIBDIR)/$(SONAME) + # Note header and static library are not copied anywhere + $(CP) $(LIBDIR)/$(SONAME) $(LUA_LIBDIR)/$(SONAME) + +$(HFILE): + $(CP) src/$(HNAME) $(HFILE) + +## GENERATED RELEASE TARGETS ################################################## + +cleanlibs: cleanobjects + $(RM) $(LIBDIR)/$(SONAME) + $(RM) $(LIBDIR)/$(ANAME) + +$(LIBDIR)/$(SONAME): $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o + $(MKDIR) $(LIBDIR) + $(LD) -o $@ $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o $(LDFLAGS) $(SOFLAGS) + +$(LIBDIR)/$(ANAME): $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o + $(MKDIR) $(LIBDIR) + $(AR) $@ $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o + $(RANLIB) $@ + +# objects: + +cleanobjects: + $(RM) $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o + +$(OBJDIR)/fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ + src/saveload.h + $(CC) $(CFLAGS) -o $@ -c src/fwrite.c + +$(OBJDIR)/load.o: src/load.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/luainternals.h + $(CC) $(CFLAGS) -o $@ -c src/load.c + +$(OBJDIR)/luabins.o: src/luabins.c src/luaheaders.h src/luabins.h + $(CC) $(CFLAGS) -o $@ -c src/luabins.c + +$(OBJDIR)/luainternals.o: src/luainternals.c src/luainternals.h + $(CC) $(CFLAGS) -o $@ -c src/luainternals.c + +$(OBJDIR)/lualess.o: src/lualess.c + $(CC) $(CFLAGS) -o $@ -c src/lualess.c + +$(OBJDIR)/save.o: src/save.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/savebuffer.h src/write.h + $(CC) $(CFLAGS) -o $@ -c src/save.c + +$(OBJDIR)/savebuffer.o: src/savebuffer.c src/luaheaders.h \ + src/saveload.h src/savebuffer.h + $(CC) $(CFLAGS) -o $@ -c src/savebuffer.c + +$(OBJDIR)/write.o: src/write.c src/luaheaders.h src/write.h \ + src/saveload.h src/savebuffer.h + $(CC) $(CFLAGS) -o $@ -c src/write.c + +## TEST TARGETS ############################################################### + +test: testc89 testc99 testc++98 + $(ECHO) "===== TESTS PASSED =====" + +resettest: resettestc89 resettestc99 resettestc++98 + +cleantest: cleantestc89 cleantestc99 cleantestc++98 + +## GENERATED TEST TARGETS ##################################################### + +## ----- Begin c89 ----- + +testc89: lua-testsc89 c-testsc89 + +lua-testsc89: $(TMPDIR)/c89/.luatestspassed + +c-testsc89: $(TMPDIR)/c89/.ctestspassed + +$(TMPDIR)/c89/.luatestspassed: $(TMPDIR)/c89/$(SONAME) test/$(TESTLUA) + $(ECHO) "===== Running Lua tests for c89 =====" + @$(LUA) \ + -e "package.cpath='$(TMPDIR)/c89/$(SONAME);'..package.cpath" \ + test/$(TESTLUA) + $(TOUCH) $(TMPDIR)/c89/.luatestspassed + $(ECHO) "===== Lua tests for c89 PASSED =====" + +$(TMPDIR)/c89/.ctestspassed: $(TMPDIR)/c89/$(TESTNAME) test/$(TESTLUA) + $(ECHO) "===== Running C tests for c89 =====" + $(TMPDIR)/c89/$(TESTNAME) + $(TOUCH) $(TMPDIR)/c89/.ctestspassed + $(ECHO) "===== C tests for c89 PASSED =====" + +$(TMPDIR)/c89/$(TESTNAME): $(OBJDIR)/c89-test.o $(OBJDIR)/c89-test_api.o $(OBJDIR)/c89-test_fwrite_api.o $(OBJDIR)/c89-test_savebuffer.o $(OBJDIR)/c89-test_write_api.o $(OBJDIR)/c89-util.o $(TMPDIR)/c89/$(ANAME) + $(MKDIR) $(TMPDIR)/c89 + $(LD) -o $@ $(OBJDIR)/c89-test.o $(OBJDIR)/c89-test_api.o $(OBJDIR)/c89-test_fwrite_api.o $(OBJDIR)/c89-test_savebuffer.o $(OBJDIR)/c89-test_write_api.o $(OBJDIR)/c89-util.o $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L$(TMPDIR)/c89 + +resettestc89: + $(RM) $(TMPDIR)/c89/.luatestspassed + $(RM) $(TMPDIR)/c89/.ctestspassed + +cleantestc89: cleanlibsc89 resettestc89 \ + cleantestobjectsc89 + $(RM) $(TMPDIR)/c89/$(TESTNAME) + $(RMDIR) $(TMPDIR)/c89 + +# testobjectsc89: + +cleantestobjectsc89: + $(RM) $(OBJDIR)/c89-test.o $(OBJDIR)/c89-test_api.o $(OBJDIR)/c89-test_fwrite_api.o $(OBJDIR)/c89-test_savebuffer.o $(OBJDIR)/c89-test_write_api.o $(OBJDIR)/c89-util.o + +$(OBJDIR)/c89-test.o: test/test.c test/test.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test.c + +$(OBJDIR)/c89-test_api.o: test/test_api.c src/luabins.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_api.c + +$(OBJDIR)/c89-test_fwrite_api.o: test/test_fwrite_api.c src/lualess.h \ + src/fwrite.h src/saveload.h test/test.h test/util.h \ + test/write_tests.inc + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_fwrite_api.c + +$(OBJDIR)/c89-test_savebuffer.o: test/test_savebuffer.c src/lualess.h \ + src/savebuffer.h test/test.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_savebuffer.c + +$(OBJDIR)/c89-test_write_api.o: test/test_write_api.c src/lualess.h \ + src/write.h src/saveload.h src/savebuffer.h test/test.h test/util.h \ + test/write_tests.inc + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_write_api.c + +$(OBJDIR)/c89-util.o: test/util.c test/util.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/util.c + +cleanlibsc89: cleanobjectsc89 + $(RM) $(TMPDIR)/c89/$(SONAME) + $(RM) $(TMPDIR)/c89/$(ANAME) + +$(TMPDIR)/c89/$(SONAME): $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o + $(MKDIR) $(TMPDIR)/c89 + $(LD) -o $@ $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o $(LDFLAGS) $(SOFLAGS) + +$(TMPDIR)/c89/$(ANAME): $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o + $(MKDIR) $(TMPDIR)/c89 + $(AR) $@ $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o + $(RANLIB) $@ + +# objectsc89: + +cleanobjectsc89: + $(RM) $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o + +$(OBJDIR)/c89-fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ + src/saveload.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/fwrite.c + +$(OBJDIR)/c89-load.o: src/load.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/luainternals.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/load.c + +$(OBJDIR)/c89-luabins.o: src/luabins.c src/luaheaders.h src/luabins.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/luabins.c + +$(OBJDIR)/c89-luainternals.o: src/luainternals.c src/luainternals.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/luainternals.c + +$(OBJDIR)/c89-lualess.o: src/lualess.c + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/lualess.c + +$(OBJDIR)/c89-save.o: src/save.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/savebuffer.h src/write.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/save.c + +$(OBJDIR)/c89-savebuffer.o: src/savebuffer.c src/luaheaders.h \ + src/saveload.h src/savebuffer.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/savebuffer.c + +$(OBJDIR)/c89-write.o: src/write.c src/luaheaders.h src/write.h \ + src/saveload.h src/savebuffer.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/write.c + +## ----- Begin c99 ----- + +testc99: lua-testsc99 c-testsc99 + +lua-testsc99: $(TMPDIR)/c99/.luatestspassed + +c-testsc99: $(TMPDIR)/c99/.ctestspassed + +$(TMPDIR)/c99/.luatestspassed: $(TMPDIR)/c99/$(SONAME) test/$(TESTLUA) + $(ECHO) "===== Running Lua tests for c99 =====" + @$(LUA) \ + -e "package.cpath='$(TMPDIR)/c99/$(SONAME);'..package.cpath" \ + test/$(TESTLUA) + $(TOUCH) $(TMPDIR)/c99/.luatestspassed + $(ECHO) "===== Lua tests for c99 PASSED =====" + +$(TMPDIR)/c99/.ctestspassed: $(TMPDIR)/c99/$(TESTNAME) test/$(TESTLUA) + $(ECHO) "===== Running C tests for c99 =====" + $(TMPDIR)/c99/$(TESTNAME) + $(TOUCH) $(TMPDIR)/c99/.ctestspassed + $(ECHO) "===== C tests for c99 PASSED =====" + +$(TMPDIR)/c99/$(TESTNAME): $(OBJDIR)/c99-test.o $(OBJDIR)/c99-test_api.o $(OBJDIR)/c99-test_fwrite_api.o $(OBJDIR)/c99-test_savebuffer.o $(OBJDIR)/c99-test_write_api.o $(OBJDIR)/c99-util.o $(TMPDIR)/c99/$(ANAME) + $(MKDIR) $(TMPDIR)/c99 + $(LD) -o $@ $(OBJDIR)/c99-test.o $(OBJDIR)/c99-test_api.o $(OBJDIR)/c99-test_fwrite_api.o $(OBJDIR)/c99-test_savebuffer.o $(OBJDIR)/c99-test_write_api.o $(OBJDIR)/c99-util.o $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L$(TMPDIR)/c99 + +resettestc99: + $(RM) $(TMPDIR)/c99/.luatestspassed + $(RM) $(TMPDIR)/c99/.ctestspassed + +cleantestc99: cleanlibsc99 resettestc99 \ + cleantestobjectsc99 + $(RM) $(TMPDIR)/c99/$(TESTNAME) + $(RMDIR) $(TMPDIR)/c99 + +# testobjectsc99: + +cleantestobjectsc99: + $(RM) $(OBJDIR)/c99-test.o $(OBJDIR)/c99-test_api.o $(OBJDIR)/c99-test_fwrite_api.o $(OBJDIR)/c99-test_savebuffer.o $(OBJDIR)/c99-test_write_api.o $(OBJDIR)/c99-util.o + +$(OBJDIR)/c99-test.o: test/test.c test/test.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test.c + +$(OBJDIR)/c99-test_api.o: test/test_api.c src/luabins.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_api.c + +$(OBJDIR)/c99-test_fwrite_api.o: test/test_fwrite_api.c src/lualess.h \ + src/fwrite.h src/saveload.h test/test.h test/util.h \ + test/write_tests.inc + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_fwrite_api.c + +$(OBJDIR)/c99-test_savebuffer.o: test/test_savebuffer.c src/lualess.h \ + src/savebuffer.h test/test.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_savebuffer.c + +$(OBJDIR)/c99-test_write_api.o: test/test_write_api.c src/lualess.h \ + src/write.h src/saveload.h src/savebuffer.h test/test.h test/util.h \ + test/write_tests.inc + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_write_api.c + +$(OBJDIR)/c99-util.o: test/util.c test/util.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/util.c + +cleanlibsc99: cleanobjectsc99 + $(RM) $(TMPDIR)/c99/$(SONAME) + $(RM) $(TMPDIR)/c99/$(ANAME) + +$(TMPDIR)/c99/$(SONAME): $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o + $(MKDIR) $(TMPDIR)/c99 + $(LD) -o $@ $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o $(LDFLAGS) $(SOFLAGS) + +$(TMPDIR)/c99/$(ANAME): $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o + $(MKDIR) $(TMPDIR)/c99 + $(AR) $@ $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o + $(RANLIB) $@ + +# objectsc99: + +cleanobjectsc99: + $(RM) $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o + +$(OBJDIR)/c99-fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ + src/saveload.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/fwrite.c + +$(OBJDIR)/c99-load.o: src/load.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/luainternals.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/load.c + +$(OBJDIR)/c99-luabins.o: src/luabins.c src/luaheaders.h src/luabins.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/luabins.c + +$(OBJDIR)/c99-luainternals.o: src/luainternals.c src/luainternals.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/luainternals.c + +$(OBJDIR)/c99-lualess.o: src/lualess.c + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/lualess.c + +$(OBJDIR)/c99-save.o: src/save.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/savebuffer.h src/write.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/save.c + +$(OBJDIR)/c99-savebuffer.o: src/savebuffer.c src/luaheaders.h \ + src/saveload.h src/savebuffer.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/savebuffer.c + +$(OBJDIR)/c99-write.o: src/write.c src/luaheaders.h src/write.h \ + src/saveload.h src/savebuffer.h + $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/write.c + +## ----- Begin c++98 ----- + +testc++98: lua-testsc++98 c-testsc++98 + +lua-testsc++98: $(TMPDIR)/c++98/.luatestspassed + +c-testsc++98: $(TMPDIR)/c++98/.ctestspassed + +$(TMPDIR)/c++98/.luatestspassed: $(TMPDIR)/c++98/$(SONAME) test/$(TESTLUA) + $(ECHO) "===== Running Lua tests for c++98 =====" + @$(LUA) \ + -e "package.cpath='$(TMPDIR)/c++98/$(SONAME);'..package.cpath" \ + test/$(TESTLUA) + $(TOUCH) $(TMPDIR)/c++98/.luatestspassed + $(ECHO) "===== Lua tests for c++98 PASSED =====" + +$(TMPDIR)/c++98/.ctestspassed: $(TMPDIR)/c++98/$(TESTNAME) test/$(TESTLUA) + $(ECHO) "===== Running C tests for c++98 =====" + $(TMPDIR)/c++98/$(TESTNAME) + $(TOUCH) $(TMPDIR)/c++98/.ctestspassed + $(ECHO) "===== C tests for c++98 PASSED =====" + +$(TMPDIR)/c++98/$(TESTNAME): $(OBJDIR)/c++98-test.o $(OBJDIR)/c++98-test_api.o $(OBJDIR)/c++98-test_fwrite_api.o $(OBJDIR)/c++98-test_savebuffer.o $(OBJDIR)/c++98-test_write_api.o $(OBJDIR)/c++98-util.o $(TMPDIR)/c++98/$(ANAME) + $(MKDIR) $(TMPDIR)/c++98 + $(LDXX) -o $@ $(OBJDIR)/c++98-test.o $(OBJDIR)/c++98-test_api.o $(OBJDIR)/c++98-test_fwrite_api.o $(OBJDIR)/c++98-test_savebuffer.o $(OBJDIR)/c++98-test_write_api.o $(OBJDIR)/c++98-util.o $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L$(TMPDIR)/c++98 + +resettestc++98: + $(RM) $(TMPDIR)/c++98/.luatestspassed + $(RM) $(TMPDIR)/c++98/.ctestspassed + +cleantestc++98: cleanlibsc++98 resettestc++98 \ + cleantestobjectsc++98 + $(RM) $(TMPDIR)/c++98/$(TESTNAME) + $(RMDIR) $(TMPDIR)/c++98 + +# testobjectsc++98: + +cleantestobjectsc++98: + $(RM) $(OBJDIR)/c++98-test.o $(OBJDIR)/c++98-test_api.o $(OBJDIR)/c++98-test_fwrite_api.o $(OBJDIR)/c++98-test_savebuffer.o $(OBJDIR)/c++98-test_write_api.o $(OBJDIR)/c++98-util.o + +$(OBJDIR)/c++98-test.o: test/test.c test/test.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test.c + +$(OBJDIR)/c++98-test_api.o: test/test_api.c src/luabins.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_api.c + +$(OBJDIR)/c++98-test_fwrite_api.o: test/test_fwrite_api.c src/lualess.h \ + src/fwrite.h src/saveload.h test/test.h test/util.h \ + test/write_tests.inc + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_fwrite_api.c + +$(OBJDIR)/c++98-test_savebuffer.o: test/test_savebuffer.c src/lualess.h \ + src/savebuffer.h test/test.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_savebuffer.c + +$(OBJDIR)/c++98-test_write_api.o: test/test_write_api.c src/lualess.h \ + src/write.h src/saveload.h src/savebuffer.h test/test.h test/util.h \ + test/write_tests.inc + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_write_api.c + +$(OBJDIR)/c++98-util.o: test/util.c test/util.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/util.c + +cleanlibsc++98: cleanobjectsc++98 + $(RM) $(TMPDIR)/c++98/$(SONAME) + $(RM) $(TMPDIR)/c++98/$(ANAME) + +$(TMPDIR)/c++98/$(SONAME): $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o + $(MKDIR) $(TMPDIR)/c++98 + $(LDXX) -o $@ $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o $(LDFLAGS) $(SOFLAGS) + +$(TMPDIR)/c++98/$(ANAME): $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o + $(MKDIR) $(TMPDIR)/c++98 + $(AR) $@ $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o + $(RANLIB) $@ + +# objectsc++98: + +cleanobjectsc++98: + $(RM) $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o + +$(OBJDIR)/c++98-fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ + src/saveload.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/fwrite.c + +$(OBJDIR)/c++98-load.o: src/load.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/luainternals.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/load.c + +$(OBJDIR)/c++98-luabins.o: src/luabins.c src/luaheaders.h src/luabins.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/luabins.c + +$(OBJDIR)/c++98-luainternals.o: src/luainternals.c src/luainternals.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/luainternals.c + +$(OBJDIR)/c++98-lualess.o: src/lualess.c + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/lualess.c + +$(OBJDIR)/c++98-save.o: src/save.c src/luaheaders.h src/luabins.h \ + src/saveload.h src/savebuffer.h src/write.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/save.c + +$(OBJDIR)/c++98-savebuffer.o: src/savebuffer.c src/luaheaders.h \ + src/saveload.h src/savebuffer.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/savebuffer.c + +$(OBJDIR)/c++98-write.o: src/write.c src/luaheaders.h src/write.h \ + src/saveload.h src/savebuffer.h + $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/write.c + +## END OF GENERATED TARGETS ################################################### + +.PHONY: all clean install cleanlibs cleanobjects test resettest cleantest testc89 lua-testsc89 c-testsc89 resettestc89 cleantestc89 cleantestobjectsc89 cleanlibsc89 cleanobjectsc89 testc99 lua-testsc99 c-testsc99 resettestc99 cleantestc99 cleantestobjectsc99 cleanlibsc99 cleanobjectsc99 testc++98 lua-testsc++98 c-testsc++98 resettestc++98 cleantestc++98 cleantestobjectsc++98 cleanlibsc++98 cleanobjectsc++98 diff --git a/vendor/luabins/README.md b/vendor/luabins/README.md new file mode 100644 index 000000000..02b3b17b0 --- /dev/null +++ b/vendor/luabins/README.md @@ -0,0 +1,112 @@ +luabins — Lua Binary Serialization Library +========================================== + +Allows to save tuples of primitive Lua types into binary chunks +and to load saved data back. + +On serialization +---------------- + +### Luabins works with + + * `nil` + * `boolean` + * `number` + * `string` + * `table` (see below) + +### Luabins refuses to save + + * `function` + * `thread` + * `userdata` + +Luabins intentionally does not save or check any meta-information +(versions, endianness etc.) along with data. If needed, it is to be handled +elsewhere. + +### Table serialization + +1. Metatatables are ignored. +2. Table nesting depth should be no more than `LUABINS_MAXTABLENESTING`. +3. On table save references are not honored. Each encountered reference + becomes independent object on load: + + local t = { 42 } + { t, t } + + becomes + + { { 42 }, { 42 } } + + that is, three separate tables instead of two. + +Lua API +------- + + * `luabins.save(...)` + + Saves arguments into a binary string. + + * On success returns that string. + * On failure returns nil and error message. + + Example: + + local str = assert(luabins.save(1, "two", { "three", 4 })) + + * `luabins.load(string)` + + Loads a list of values from a binary string. + + * On success returns true and loaded values. + * On failure returns nil and error message. + + Example: + + If you do not know in advance what data is stored inside a binary string, + you may put results into a table: + + local values = { luabins.load(data) } + assert(values[1], values[2]) + + If you know how to handle stored values (for example you're sure they were + generated following some established protocol), you may want to use + something like this function to check `luabins.load()` result: + + function eat_true(t, ...) + assert(t, ...) + return ... + end + + my_value_handler(eat_true(luabins.load(data))) + +C API +----- + + * `int luabins_save(lua_State * L, int index_from, int index_to)` + + Save Lua values from given state at given stack index range. + Lua value is left untouched. Note that empty range is not an error. + You may save from 0 to `LUABINS_MAXTUPLE` values. + Note only real non-negative indices work. + + * On success returns 0, pushes saved data as a string on the top of stack. + * On failure returns non-zero, pushes error message on the top + of the stack. + + * `int luabins_load(lua_State * L, const unsigned char * data, + size_t len, int *count)` + + Load Lua values from given byte chunk. + + * On success returns 0, pushes loaded values on stack. + Sets count to the number of values pushed. + Note that to have zero loaded items is a valid scenario. + * On failure returns non-zero, pushes error message on the top + of the stack. + +Luabins is still an experimental volatile software. +Please see source code for more documentation. + +See the copyright information in the file named `COPYRIGHT`. diff --git a/vendor/luabins/TODO b/vendor/luabins/TODO new file mode 100644 index 000000000..71c317f13 --- /dev/null +++ b/vendor/luabins/TODO @@ -0,0 +1,11 @@ +-- Add key-value size-less table format (see luatexts) +-- Add utf-8 char-length string format (see luatexts) +-- Add autotest targets for LuaJIT and LuaJIT 2 x86, x86_64, both for Lua and C. +-- Test on Lua with custom allocator. +-- Use Makefile in rockspec? +-- Enhance "corrupt data" message on load. Need more info on what is wrong. + Ensure every case is covered with tests. +-- Autocompact integers (especially strings -- most of them do not need size_t!) +-- Better cover new exponential growth strategy corner-cases with tests. +-- Shouldn't write and fwrite have common codebase? +-- Document write.h and fwrite.h diff --git a/vendor/luabins/etc/Makefile.luabins.template b/vendor/luabins/etc/Makefile.luabins.template new file mode 100644 index 000000000..77b76e80d --- /dev/null +++ b/vendor/luabins/etc/Makefile.luabins.template @@ -0,0 +1,242 @@ +@{define:projectname:luabins} +@{define:test-dir:test/} +@{define:source-dir:src/} +@{define:sharedlib:$(LIBDIR)/$(SONAME)} +@{define:staticlib:$(LIBDIR)/$(ANAME)} +@{define-table:release-info: + {suffix=""; + libdir="$(LIBDIR)";objprefix="$(OBJDIR)/"; + cflags=""; + CC="$(CC)"; + LD="$(LD)"; + }; +} +@{define-table:std-info: + {suffix="c89"; + libdir="$(TMPDIR)/c89";objprefix="$(OBJDIR)/c89-"; + cflags="-Werror -Wall -Wextra -pedantic -x c -std=c89"; + CC="$(CC)"; + LD="$(LD)"; + }; + {suffix="c99"; + libdir="$(TMPDIR)/c99";objprefix="$(OBJDIR)/c99-"; + cflags="-Werror -Wall -Wextra -pedantic -x c -std=c99"; + CC="$(CC)"; + LD="$(LD)"; + }; + {suffix="c++98"; + libdir="$(TMPDIR)/c++98";objprefix="$(OBJDIR)/c++98-"; + cflags="-Werror -Wall -Wextra -pedantic -x c++ -std=c++98"; + CC="$(CXX)"; + LD="$(LDXX)"; + }; +} +@{define-dep:dep-objects:dep-template::@{source-dir}} +@{define-dep:test-dep-objects:test-dep-template:-I@{source-dir}:@{test-dir}} + +## CONFIGURATION ############################################################## + +ifeq ($(shell uname),Darwin) + LUA_DIR := /usr/local + LUA_LIBDIR := $(LUA_DIR)/lib/lua/5.1 + LUA_INCDIR := $(LUA_DIR)/include + LUALIB := lua +else + # Assuming Ubuntu + LUA_LIBDIR := /usr/lib + LUA_INCDIR := /usr/include/lua5.1 + LUALIB := lua5.1 +endif + +PROJECTNAME := @{projectname} + +SONAME := $(PROJECTNAME).so +ANAME := lib$(PROJECTNAME).a +HNAME := $(PROJECTNAME).h +TESTNAME := $(PROJECTNAME)-test +TESTLUA := test.lua + +LUA := lua +CP := cp +RM := rm -f +RMDIR := rm -df +MKDIR := mkdir -p +CC := gcc +LD := gcc +AR := ar rcu +RANLIB := ranlib +ECHO := @echo +TOUCH := touch + +# Needed for tests only +CXX := g++ +LDXX := g++ + +OBJDIR := ./obj +TMPDIR := ./tmp +INCDIR := ./include +LIBDIR := ./lib + +HFILE := $(INCDIR)/$(HNAME) + +CFLAGS += -O2 -Wall -I$(LUA_INCDIR) +LDFLAGS += -L$(LUA_LIBDIR) + +# Tested on OS X and Ubuntu +SOFLAGS := +ifeq ($(shell uname),Darwin) + SOFLAGS += -dynamiclib -undefined dynamic_lookup +else + CFLAGS += -fPIC + SOFLAGS += -shared + LDFLAGS += -ldl + RMDIR := rm -rf +endif + +CFLAGS += $(MYCFLAGS) +LDFLAGS += $(MYLDFLAGS) + +## MAIN TARGETS ############################################################### + +@{define-table:.PHONY:} + +@{insert:.PHONY:all} +all: @{sharedlib} @{staticlib} $(HFILE) + +@{insert:.PHONY:clean} +clean: cleanlibs cleantest + $(RM) $(HFILE) + +@{insert:.PHONY:install} +install: @{sharedlib} + # Note header and static library are not copied anywhere + $(CP) @{sharedlib} $(LUA_LIBDIR)/$(SONAME) + +$(HFILE): + $(CP) src/$(HNAME) $(HFILE) + +@{--:-------------------------------------------------------------------------} + +@{define:objects-macro: + +@{insert:.PHONY:clean%objects@{suffix}} +clean%objects@{suffix}: + $(RM) % + +% + +} + +@{define:lib-targets: + +@{define-fill:objects:@{fill-template:@{dep-objects}:}} + +@{insert:.PHONY:cleanlibs@{suffix}} +cleanlibs@{suffix}: cleanobjects@{suffix} + $(RM) @{sharedlib} + $(RM) @{staticlib} + +@{sharedlib}: @{objects} + $(MKDIR) @{libdir} + @{LD} -o $@ @{objects} $(LDFLAGS) $(SOFLAGS) + +@{staticlib}: @{objects} + $(MKDIR) @{libdir} + $(AR) $@ @{objects} + $(RANLIB) $@ + +@{--: note implicit objprefix parameter } +# objects@{suffix}: +@{fill-macro:objects-macro:%<>: + prefix="", + objects=@{lua-escape:@{objects}}; + dep=@{lua-escape:@{fill-template:dep-template:}}; +} + +} + +@{define:std-targets: + +## ----- Begin @{suffix} ----- + +@{define-fill:cflags-orig:@{cflags}} +@{define-fill:cflags:@{cflags} -I@{source-dir}} + +@{define-fill:sharedlib:@{libdir}/$(SONAME)} +@{define-fill:staticlib:@{libdir}/$(ANAME)} +@{define-fill:objects:@{fill-template:@{test-dep-objects}:}} + +@{insert:.PHONY:test@{suffix}} +test@{suffix}: lua-tests@{suffix} c-tests@{suffix} + +@{insert:.PHONY:lua-tests@{suffix}} +lua-tests@{suffix}: @{libdir}/.luatestspassed + +@{insert:.PHONY:c-tests@{suffix}} +c-tests@{suffix}: @{libdir}/.ctestspassed + +@{libdir}/.luatestspassed: @{sharedlib} test/$(TESTLUA) + $(ECHO) "===== Running Lua tests for @{suffix} =====" + @$(LUA) \ + -e "package.cpath='@{sharedlib};'..package.cpath" \ + test/$(TESTLUA) + $(TOUCH) @{libdir}/.luatestspassed + $(ECHO) "===== Lua tests for @{suffix} PASSED =====" + +@{libdir}/.ctestspassed: @{libdir}/$(TESTNAME) test/$(TESTLUA) + $(ECHO) "===== Running C tests for @{suffix} =====" + @{libdir}/$(TESTNAME) + $(TOUCH) @{libdir}/.ctestspassed + $(ECHO) "===== C tests for @{suffix} PASSED =====" + +@{libdir}/$(TESTNAME): @{objects} @{staticlib} + $(MKDIR) @{libdir} + @{LD} -o $@ @{objects} $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L@{libdir} + +@{insert:.PHONY:resettest@{suffix}} +resettest@{suffix}: + $(RM) @{libdir}/.luatestspassed + $(RM) @{libdir}/.ctestspassed + +@{insert:.PHONY:cleantest@{suffix}} +cleantest@{suffix}: cleanlibs@{suffix} resettest@{suffix} \ + cleantestobjects@{suffix} + $(RM) @{libdir}/$(TESTNAME) + $(RMDIR) @{libdir} + +@{--: Note implicit objprefix parameter } +# testobjects@{suffix}: +@{fill-macro:objects-macro:%<>: + prefix="test", + objects=@{lua-escape:@{objects}}; + dep=@{lua-escape:@{fill-template:test-dep-template:}}; +} + +@{--: Libraries must use original cflags } +@{fill-template:lib-targets:cflags=@{lua-escape:@{cflags-orig}}} + +} + +## GENERATED RELEASE TARGETS ################################################## + +@{map-template:release-info:lib-targets} + +## TEST TARGETS ############################################################### + +@{insert:.PHONY:test} +test:@{map-template:std-info: test@{suffix}} + $(ECHO) "===== TESTS PASSED =====" + +@{insert:.PHONY:resettest} +resettest:@{map-template:std-info: resettest@{suffix}} + +@{insert:.PHONY:cleantest} +cleantest:@{map-template:std-info: cleantest@{suffix}} + +## GENERATED TEST TARGETS ##################################################### + +@{map-template:std-info:std-targets} + +## END OF GENERATED TARGETS ################################################### + +.PHONY: @{concat:.PHONY: } diff --git a/vendor/luabins/etc/benchmark.lua b/vendor/luabins/etc/benchmark.lua new file mode 100644 index 000000000..7ed8c4d58 --- /dev/null +++ b/vendor/luabins/etc/benchmark.lua @@ -0,0 +1,106 @@ +-- This benchmark is compatible with luamarca benchmarking system +-- http://github.com/agladysh/luamarca + +package.cpath = "./?.so;"..package.cpath + +local luabins = require("luabins") + +local table_concat = table.concat +local loadstring, assert = loadstring, assert +local pairs, type, tostring = pairs, type, tostring +local luabins_save, luabins_load = luabins.save, luabins.load + +local lua = ([[return { + true, false, 42, "string", + [{ + true, false, 42, "string", + [true] = true, [false] = false, [42] = 42, string = "string" + }] = + { + true, false, 42, "string", + [true] = true, [false] = false, [42] = 42, string = "string" + } +}]]):gsub("[%s\n]+", "") -- Remove spaces for compactness + +local data = assert(loadstring(lua))() +local saved = assert(luabins_save(data)) + +-- Imagine we know exact data structure. +-- We still impose some overhead on table.concat() related +-- stuff, since it is more realistic scenario. +-- Still looks a bit silly. +local concat = function(data) + local buf = {} + local function cat(v) buf[#buf + 1] = tostring(v) return cat end + + -- Find table key + local tablekey, tableval + for k, v in pairs(data) do + if type(k) == "table" then + tablekey, tableval = k, v + break + end + end + + cat 'return{' + + cat (data[1]) ',' + cat (data[2]) ',' + cat (data[3]) ',' + cat '"' (data[4]) '",' + + cat '[{' + + cat (tablekey[1]) ',' + cat (tablekey[2]) ',' + cat (tablekey[3]) ',' + cat '"' (tablekey[4]) '",' + + cat '[' (true) ']=' (tablekey[true]) ',' + cat '[' (false) ']=' (tablekey[false]) ',' + cat '[' (42) ']=' (tablekey[42]) ',' + cat 'string' '=' '"' (tablekey["string"]) '"' + + cat '}]=' + + cat '{' + + cat (tablekey[1]) ',' + cat (tablekey[2]) ',' + cat (tablekey[3]) ',' + cat '"' (tablekey[4]) '",' + + cat '[' (true) ']=' (tablekey[true]) ',' + cat '[' (false) ']=' (tablekey[false]) ',' + cat '[' (42) ']=' (tablekey[42]) ',' + cat 'string' '=' '"' (tablekey["string"]) '"' + + cat '}' + + cat '}' + + return table_concat(buf, '') +end + +-- Sanity check +assert(concat(data) == lua) + +local bench = {} + +bench.concat = function() + assert(concat(data)) +end + +bench.loadstring = function() + assert(loadstring(lua))() +end + +bench.luabins_save = function() + assert(luabins_save(data)) +end + +bench.luabins_load = function() + assert(luabins_load(saved)) +end + +return bench diff --git a/vendor/luabins/etc/checkfmt.lua b/vendor/luabins/etc/checkfmt.lua new file mode 100644 index 000000000..c1bf35320 --- /dev/null +++ b/vendor/luabins/etc/checkfmt.lua @@ -0,0 +1,30 @@ +--- Luabins format checker + +package.cpath = "./lib/?.so;"..package.cpath + +local luabins = require("luabins") + +local luabins_save, luabins_load = luabins.save, luabins.load + +local filename = select(1, ...) +assert(filename, "Usage: lua checkfmt.lua ") + +local file +if filename == "-" then + file = io.stdin +else + file = assert(io.open(filename, "r")) +end + +assert( + luabins_load( + file:read("*a") + ) + ) + +if file ~= io.stdin then + file:close() +end +file = nil + +print("OK") diff --git a/vendor/luabins/etc/dataset.lua b/vendor/luabins/etc/dataset.lua new file mode 100644 index 000000000..f6bceacae --- /dev/null +++ b/vendor/luabins/etc/dataset.lua @@ -0,0 +1,90 @@ +-- Random Luabins dataset generator + +package.cpath = "./lib/?.so;"..package.cpath + +local luabins = require("luabins") + +local luabins_save, luabins_load = luabins.save, luabins.load + +math.randomseed(123456) + +-- TODO: Generalize. Copy-paste from test.lua +local function gen_random_dataset(num, nesting) + num = num or math.random(0, 128) + nesting = nesting or 1 + + local gen_str = function() + local t = {} + local n = math.random(0, 1024) + for i = 1, n do + t[i] = string.char(math.random(0, 255)) + end + return table.concat(t) + end + + local gen_bool = function() return math.random() >= 0.5 end + + local gen_nil = function() return nil end + + local generators = + { + gen_nil; + gen_nil; + gen_nil; + gen_bool; + gen_bool; + gen_bool; + function() return math.random() end; + function() return math.random(-10000, 10000) end; + function() return math.random() * math.random(-10000, 10000) end; + gen_str; + gen_str; + gen_str; + function() + if nesting >= 24 then + return nil + end + + local t = {} + local n = math.random(0, 24 - nesting) + for i = 1, n do + local k = gen_random_dataset(1, nesting + 1) + if k == nil then + k = "(nil)" + end + t[ k ] = gen_random_dataset( + 1, + nesting + 1 + ) + end + + return t + end; + } + + local t = {} + for i = 1, num do + local n = math.random(1, #generators) + t[i] = generators[n]() + end + return unpack(t, 0, num) +end + +local saved = assert(luabins_save(gen_random_dataset())) + +local filename = select(1, ...) +assert(filename, "Usage: lua dataset.lua ") + +local file +if filename == "-" then + file = io.stdout +else + file = assert(io.open(filename, "w")) +end + +file:write(saved) + +if file ~= io.stdout then + file:close() +end +file = nil diff --git a/vendor/luabins/etc/genmakefile.sh b/vendor/luabins/etc/genmakefile.sh new file mode 100755 index 000000000..45244e442 --- /dev/null +++ b/vendor/luabins/etc/genmakefile.sh @@ -0,0 +1,2 @@ +#! /bin/bash +lua ~/projects/genmakefile/src/genmakefile.lua Makefile diff --git a/vendor/luabins/etc/tolua.lua b/vendor/luabins/etc/tolua.lua new file mode 100644 index 000000000..f70990547 --- /dev/null +++ b/vendor/luabins/etc/tolua.lua @@ -0,0 +1,39 @@ +-- Luabins to Lua converter +-- Requires lua-nucleo (http://github.com/lua-nucleo/lua-nucleo/) + +package.cpath = "./lib/?.so;"..package.cpath + +local luabins = require 'luabins' + +dofile('lua-nucleo/strict.lua') +dofile('lua-nucleo/import.lua') + +local tserialize = import 'lua-nucleo/tserialize.lua' { 'tserialize' } + +local filename = select(1, ...) +assert(filename, "Usage: lua tolua.lua ") + +local file +if filename == "-" then + file = io.stdin +else + file = assert(io.open(filename, "r")) +end + +io.write( + tserialize( + assert( + luabins.load( + file:read("*a") + ) + ) + ) + ) + +io:flush() + +if file ~= io.stdin then + file:close() +end +file = nil + diff --git a/vendor/luabins/etc/toluabins.lua b/vendor/luabins/etc/toluabins.lua new file mode 100644 index 000000000..9880c73b7 --- /dev/null +++ b/vendor/luabins/etc/toluabins.lua @@ -0,0 +1,16 @@ +-- Lua to Luabins converter + +package.cpath = "./lib/?.so;"..package.cpath + +local luabins = require 'luabins' + +local filename = select(1, ...) +assert(filename, "Usage: lua toluabins.lua ") + +io.write( + luabins.save( + assert(loadfile(filename))() + ) + ) + +io:flush() diff --git a/vendor/luabins/include/.keepme b/vendor/luabins/include/.keepme new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/luabins/lib/.keepme b/vendor/luabins/lib/.keepme new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/luabins/obj/.keepme b/vendor/luabins/obj/.keepme new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/luabins/rockspec/luabins-0.1.1-1.rockspec b/vendor/luabins/rockspec/luabins-0.1.1-1.rockspec new file mode 100644 index 000000000..2fce4970f --- /dev/null +++ b/vendor/luabins/rockspec/luabins-0.1.1-1.rockspec @@ -0,0 +1,19 @@ +package = "luabins" +version = "0.1.1-1" +source = { + url = "http://cloud.github.com/downloads/agladysh/luabins/luabins-0.1.1.tar.gz" +} +description = { + summary = "Trivial Lua Binary Serialization Library", + detailed = [[ + Luabins allows to save tuples of primitive Lua types into binary chunks and to load saved data back. + ]], + homepage = "http://github.com/agladysh/luabins", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "make" +} diff --git a/vendor/luabins/rockspec/luabins-0.1.1-2.rockspec b/vendor/luabins/rockspec/luabins-0.1.1-2.rockspec new file mode 100644 index 000000000..bacadd8a2 --- /dev/null +++ b/vendor/luabins/rockspec/luabins-0.1.1-2.rockspec @@ -0,0 +1,32 @@ +package = "luabins" +version = "0.1.1-2" +source = { + url = "http://cloud.github.com/downloads/agladysh/luabins/luabins-0.1.1.tar.gz" +} +description = { + summary = "Trivial Lua Binary Serialization Library", + detailed = [[ + Luabins allows to save tuples of primitive Lua types into binary chunks and to load saved data back. + ]], + homepage = "http://github.com/agladysh/luabins", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + luabins = { + sources = { + "src/load.c", + "src/luabins.c", + "src/luainternals.c", + "src/save.c" + }, + incdirs = { + "src/" + } + } + } +} diff --git a/vendor/luabins/rockspec/luabins-0.2-1.rockspec b/vendor/luabins/rockspec/luabins-0.2-1.rockspec new file mode 100644 index 000000000..f91848e98 --- /dev/null +++ b/vendor/luabins/rockspec/luabins-0.2-1.rockspec @@ -0,0 +1,35 @@ +package = "luabins" +version = "0.2-1" +source = { + url = "http://cloud.github.com/downloads/agladysh/luabins/luabins-0.2.tar.gz" +} +description = { + summary = "Trivial Lua Binary Serialization Library", + detailed = [[ + Luabins allows to save tuples of primitive Lua types into binary chunks and to load saved data back. + ]], + homepage = "http://github.com/agladysh/luabins", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + luabins = { + sources = { + "src/load.c", + "src/luabins.c", + "src/luainternals.c", + "src/lualess.c", + "src/save.c", + "src/savebuffer.c", + "src/write.c" + }, + incdirs = { + "src/" + } + } + } +} diff --git a/vendor/luabins/rockspec/luabins-0.3-1.rockspec b/vendor/luabins/rockspec/luabins-0.3-1.rockspec new file mode 100644 index 000000000..d97beef77 --- /dev/null +++ b/vendor/luabins/rockspec/luabins-0.3-1.rockspec @@ -0,0 +1,35 @@ +package = "luabins" +version = "0.3-1" +source = { + url = "http://cloud.github.com/downloads/agladysh/luabins/luabins-0.3.tar.gz" +} +description = { + summary = "Trivial Lua Binary Serialization Library", + detailed = [[ + Luabins allows to save tuples of primitive Lua types into binary chunks and to load saved data back. + ]], + homepage = "http://github.com/agladysh/luabins", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + luabins = { + sources = { + "src/load.c", + "src/luabins.c", + "src/luainternals.c", + "src/lualess.c", + "src/save.c", + "src/savebuffer.c", + "src/write.c" + }, + incdirs = { + "src/" + } + } + } +} diff --git a/vendor/luabins/rockspec/luabins-scm-1.rockspec b/vendor/luabins/rockspec/luabins-scm-1.rockspec new file mode 100644 index 000000000..44d15f874 --- /dev/null +++ b/vendor/luabins/rockspec/luabins-scm-1.rockspec @@ -0,0 +1,32 @@ +package = "luabins" +version = "scm-1" +source = { + url = "git://github.com/agladysh/luabins.git" +} +description = { + summary = "Trivial Lua Binary Serialization Library", + detailed = [[ + Luabins allows to save tuples of primitive Lua types into binary chunks and to load saved data back. + ]], + homepage = "http://github.com/agladysh/luabins", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + luabins = { + sources = { + "src/load.c", + "src/luabins.c", + "src/luainternals.c", + "src/save.c" + }, + incdirs = { + "src/" + } + } + } +} diff --git a/vendor/luabins/rockspec/luabins-scm-2.rockspec b/vendor/luabins/rockspec/luabins-scm-2.rockspec new file mode 100644 index 000000000..f1b5e3a30 --- /dev/null +++ b/vendor/luabins/rockspec/luabins-scm-2.rockspec @@ -0,0 +1,35 @@ +package = "luabins" +version = "scm-2" +source = { + url = "git://github.com/agladysh/luabins.git" +} +description = { + summary = "Trivial Lua Binary Serialization Library", + detailed = [[ + Luabins allows to save tuples of primitive Lua types into binary chunks and to load saved data back. + ]], + homepage = "http://github.com/agladysh/luabins", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + luabins = { + sources = { + "src/load.c", + "src/luabins.c", + "src/luainternals.c", + "src/lualess.c", + "src/save.c", + "src/savebuffer.c", + "src/write.c" + }, + incdirs = { + "src/" + } + } + } +} diff --git a/vendor/luabins/src/fwrite.c b/vendor/luabins/src/fwrite.c new file mode 100644 index 000000000..99591e7f2 --- /dev/null +++ b/vendor/luabins/src/fwrite.c @@ -0,0 +1,49 @@ +/* +* fwrite.c +* Luabins Lua-less write API using FILE * as buffer +* See copyright notice in luabins.h +*/ + +#include "luaheaders.h" + +#include "fwrite.h" + +/* TODO: Note that stream errors are ignored. Handle them better? */ + +void lbs_fwriteTableHeader( + FILE * f, + int array_size, + int hash_size + ) +{ + fputc(LUABINS_CTABLE, f); + fwrite( + (const unsigned char *)&array_size, + LUABINS_LINT, + 1, + f + ); + fwrite( + (const unsigned char *)&hash_size, + LUABINS_LINT, + 1, + f + ); +} + +void lbs_fwriteNumber(FILE * f, lua_Number value) +{ + fputc(LUABINS_CNUMBER, f); + fwrite((const unsigned char *)&value, LUABINS_LNUMBER, 1, f); +} + +void lbs_fwriteString( + FILE * f, + const char * value, + size_t length + ) +{ + fputc(LUABINS_CSTRING, f); + fwrite((const unsigned char *)&length, LUABINS_LSIZET, 1, f); + fwrite((const unsigned char *)value, length, 1, f); +} diff --git a/vendor/luabins/src/fwrite.h b/vendor/luabins/src/fwrite.h new file mode 100644 index 000000000..ea27cbcd4 --- /dev/null +++ b/vendor/luabins/src/fwrite.h @@ -0,0 +1,37 @@ +/* +* fwrite.h +* Luabins Lua-less write API using FILE * as buffer +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_FWRITE_H_INCLUDED_ +#define LUABINS_FWRITE_H_INCLUDED_ + +#include "saveload.h" + +#define lbs_fwriteTupleSize(f, tuple_size) \ + fputc((int)(tuple_size), (f)) + +void lbs_fwriteTableHeader( + FILE * f, + int array_size, + int hash_size + ); + +#define lbs_fwriteNil(f) \ + fputc(LUABINS_CNIL, (f)) + +#define lbs_fwriteBoolean(f, value) \ + fputc(((value) == 0) ? LUABINS_CFALSE : LUABINS_CTRUE, (f)) + +void lbs_fwriteNumber(FILE * f, lua_Number value); + +#define lbs_fwriteInteger lbs_fwriteNumber + +void lbs_fwriteString( + FILE * f, + const char * value, + size_t length + ); + +#endif /* LUABINS_FWRITE_H_INCLUDED_ */ diff --git a/vendor/luabins/src/load.c b/vendor/luabins/src/load.c new file mode 100644 index 000000000..0c7dcba38 --- /dev/null +++ b/vendor/luabins/src/load.c @@ -0,0 +1,367 @@ +/* +* load.c +* Luabins load code +* See copyright notice in luabins.h +*/ + +#include + +#include "luaheaders.h" + +#include "luabins.h" +#include "saveload.h" +#include "luainternals.h" + +#if 0 + #define XSPAM(a) printf a +#else + #define XSPAM(a) (void)0 +#endif + +#if 0 + #define SPAM(a) printf a +#else + #define SPAM(a) (void)0 +#endif + +typedef struct lbs_LoadState +{ + const unsigned char * pos; + size_t unread; +} lbs_LoadState; + +static void lbsLS_init( + lbs_LoadState * ls, + const unsigned char * data, + size_t len + ) +{ + ls->pos = (len > 0) ? data : NULL; + ls->unread = len; +} + +#define lbsLS_good(ls) \ + ((ls)->pos != NULL) + +#define lbsLS_unread(ls) \ + ((ls)->unread) + +static unsigned char lbsLS_readbyte(lbs_LoadState * ls) +{ + if (lbsLS_good(ls)) + { + if (lbsLS_unread(ls) > 0) + { + const unsigned char b = *ls->pos; + ++ls->pos; + --ls->unread; + return b; + } + else + { + ls->unread = 0; + ls->pos = NULL; + } + } + return 0; +} + +static const unsigned char * lbsLS_eat(lbs_LoadState * ls, size_t len) +{ + const unsigned char * result = NULL; + if (lbsLS_good(ls)) + { + if (lbsLS_unread(ls) >= len) + { + XSPAM(("* eat: len %u\n", (int)len)); + result = ls->pos; + ls->pos += len; + ls->unread -= len; + XSPAM(("* eat: done len %u\n", (int)len)); + } + else + { + ls->unread = 0; + ls->pos = NULL; + } + } + return result; +} + +static int lbsLS_readbytes( + lbs_LoadState * ls, + unsigned char * buf, + size_t len + ) +{ + const unsigned char * pos = lbsLS_eat(ls, len); + if (pos != NULL) + { + memcpy(buf, pos, len); + return LUABINS_ESUCCESS; + } + SPAM(("load: Failed to read %lu bytes\n", (unsigned long)len)); + return LUABINS_EBADDATA; +} + +static int load_value(lua_State * L, lbs_LoadState * ls); + +static int load_table(lua_State * L, lbs_LoadState * ls) +{ + int array_size = 0; + int hash_size = 0; + unsigned int total_size = 0; + + int result = lbsLS_readbytes(ls, (unsigned char *)&array_size, LUABINS_LINT); + if (result == LUABINS_ESUCCESS) + { + result = lbsLS_readbytes(ls, (unsigned char *)&hash_size, LUABINS_LINT); + } + + if (result == LUABINS_ESUCCESS) + { + total_size = array_size + hash_size; +/* + SPAM(( + "LT SIZE CHECK\n" + "* array_size %d limit 0 .. %d\n" + "* hash_size %d limit >0\n" + "* hash_size bytes %d, limit %d\n" + "* unread %u limit >min_size %u (total_size %u)\n", + array_size, MAXASIZE, + hash_size, + ceillog2((unsigned int)hash_size), MAXBITS, + (unsigned int)lbsLS_unread(ls), + (unsigned int)luabins_min_table_data_size(total_size), + (unsigned int)total_size + )); +*/ + if ( + array_size < 0 || array_size > MAXASIZE || + hash_size < 0 || + (hash_size > 0 && ceillog2((unsigned int)hash_size) > MAXBITS) || + lbsLS_unread(ls) < luabins_min_table_data_size(total_size) + ) + { + result = LUABINS_EBADSIZE; + } + } + + if (result == LUABINS_ESUCCESS) + { + unsigned int i = 0; + + XSPAM(( + "* load: creating table a:%d + h:%d = %d\n", + array_size, hash_size, total_size + )); + + lua_createtable(L, array_size, hash_size); + + for (i = 0; i < total_size; ++i) + { + int key_type = LUA_TNONE; + + result = load_value(L, ls); /* Load key. */ + if (result != LUABINS_ESUCCESS) + { + break; + } + + /* Table key can't be nil or NaN */ + key_type = lua_type(L, -1); + if (key_type == LUA_TNIL) + { + /* Corrupt data? */ + SPAM(("load: nil as key detected\n")); + result = LUABINS_EBADDATA; + break; + } + + if (key_type == LUA_TNUMBER) + { + lua_Number key = lua_tonumber(L, -1); + if (luai_numisnan(key)) + { + /* Corrupt data? */ + SPAM(("load: NaN as key detected\n")); + result = LUABINS_EBADDATA; + break; + } + } + + result = load_value(L, ls); /* Load value. */ + if (result != LUABINS_ESUCCESS) + { + break; + } + + lua_rawset(L, -3); + } + } + + return result; +} + +static int load_value(lua_State * L, lbs_LoadState * ls) +{ + int result = LUABINS_ESUCCESS; + unsigned char type = lbsLS_readbyte(ls); + if (!lbsLS_good(ls)) + { + SPAM(("load: Failed to read value type byte\n")); + return LUABINS_EBADDATA; + } + + XSPAM(("* load: begin load_value\n")); + + luaL_checkstack(L, 1, "load_value"); + + switch (type) + { + case LUABINS_CNIL: + XSPAM(("* load: nil\n")); + lua_pushnil(L); + break; + + case LUABINS_CFALSE: + XSPAM(("* load: false\n")); + lua_pushboolean(L, 0); + break; + + case LUABINS_CTRUE: + XSPAM(("* load: true\n")); + lua_pushboolean(L, 1); + break; + + case LUABINS_CNUMBER: + { + lua_Number value; + + XSPAM(("* load: number\n")); + + result = lbsLS_readbytes(ls, (unsigned char *)&value, LUABINS_LNUMBER); + if (result == LUABINS_ESUCCESS) + { + lua_pushnumber(L, value); + } + } + break; + + case LUABINS_CSTRING: + { + size_t len = 0; + + XSPAM(("* load: string\n")); + + result = lbsLS_readbytes(ls, (unsigned char *)&len, LUABINS_LSIZET); + if (result == LUABINS_ESUCCESS) + { + const unsigned char * pos = lbsLS_eat(ls, len); + + XSPAM(("* load: string size %u\n", (int)len)); + + if (pos != NULL) + { + lua_pushlstring(L, (const char *)pos, len); + } + else + { + result = LUABINS_EBADSIZE; + } + } + } + break; + + case LUABINS_CTABLE: + XSPAM(("* load: table\n")); + result = load_table(L, ls); + break; + + default: + SPAM(("load: Unknown type char 0x%02X found\n", type)); + result = LUABINS_EBADDATA; + break; + } + + XSPAM(("* load: end load_value\n")); + + return result; +} + +int luabins_load( + lua_State * L, + const unsigned char * data, + size_t len, + int * count + ) +{ + lbs_LoadState ls; + int result = LUABINS_ESUCCESS; + unsigned char num_items = 0; + int base = 0; + int i = 0; + + base = lua_gettop(L); + + lbsLS_init(&ls, data, len); + num_items = lbsLS_readbyte(&ls); + if (!lbsLS_good(&ls)) + { + SPAM(("load: failed to read num_items byte\n")); + result = LUABINS_EBADDATA; + } + else if (num_items > LUABINS_MAXTUPLE) + { + SPAM(("load: tuple too large: %d\n", (int)num_items)); + result = LUABINS_EBADSIZE; + } + else + { + XSPAM(("* load: tuple size %d\n", (int)num_items)); + for ( + i = 0; + i < num_items && result == LUABINS_ESUCCESS; + ++i + ) + { + XSPAM(("* load: loading tuple item %d\n", i)); + result = load_value(L, &ls); + } + } + + if (result == LUABINS_ESUCCESS && lbsLS_unread(&ls) > 0) + { + SPAM(("load: %lu chars left at tail\n", lbsLS_unread(&ls))); + result = LUABINS_ETAILEFT; + } + + if (result == LUABINS_ESUCCESS) + { + *count = num_items; + } + else + { + lua_settop(L, base); /* Discard intermediate results */ + switch (result) + { + case LUABINS_EBADDATA: + lua_pushliteral(L, "can't load: corrupt data"); + break; + + case LUABINS_EBADSIZE: + lua_pushliteral(L, "can't load: corrupt data, bad size"); + break; + + case LUABINS_ETAILEFT: + lua_pushliteral(L, "can't load: extra data at end"); + break; + + default: /* Should not happen */ + lua_pushliteral(L, "load failed"); + break; + } + } + + return result; +} diff --git a/vendor/luabins/src/luabins.c b/vendor/luabins/src/luabins.c new file mode 100644 index 000000000..60668213f --- /dev/null +++ b/vendor/luabins/src/luabins.c @@ -0,0 +1,104 @@ +/* +* luabins.c +* Luabins Lua module code +* See copyright notice in luabins.h +*/ + +#include "luaheaders.h" + +#include "luabins.h" +#include "saveload.h" + +/* +* On success returns data string. +* On failure returns nil and error message. +*/ +static int l_save(lua_State * L) +{ + int error = luabins_save(L, 1, lua_gettop(L)); + if (error == 0) + { + return 1; + } + + lua_pushnil(L); + lua_replace(L, -3); /* Put nil before error message on stack */ + return 2; +} + +/* +* On success returns true and loaded data tuple. +* On failure returns nil and error message. +*/ +static int l_load(lua_State * L) +{ + int count = 0; + int error = 0; + size_t len = 0; + const unsigned char * data = (const unsigned char *)luaL_checklstring( + L, 1, &len + ); + + lua_pushboolean(L, 1); + + error = luabins_load(L, data, len, &count); + if (error == 0) + { + return count + 1; + } + + lua_pushnil(L); + lua_replace(L, -3); /* Put nil before error message on stack */ + + return 2; +} + +/* luabins Lua module API */ +static const struct luaL_reg R[] = +{ + { "save", l_save }, + { "load", l_load }, + { NULL, NULL } +}; + +#ifdef __cplusplus +extern "C" { +#endif + +LUALIB_API int luaopen_luabins(lua_State * L) +{ + /* + * Compile-time checks for size constants. + * Consult PORTABILITY WARNING in saveload.h before changing constants. + */ + + /* int is too small on your platform, fix LUABINS_LINT */ + luabins_static_assert(sizeof(int) >= LUABINS_LINT); + /* size_t is too small on your platform, fix LUABINS_LSIZET */ + luabins_static_assert(sizeof(size_t) >= LUABINS_LSIZET); + /* unexpected lua_Number size, fix LUABINS_LNUMBER */ + luabins_static_assert(sizeof(lua_Number) == LUABINS_LNUMBER); + + /* + * Register module + */ + luaL_register(L, "luabins", R); + + /* + * Register module information + */ + lua_pushliteral(L, LUABINS_VERSION); + lua_setfield(L, -2, "_VERSION"); + + lua_pushliteral(L, LUABINS_COPYRIGHT); + lua_setfield(L, -2, "_COPYRIGHT"); + + lua_pushliteral(L, LUABINS_DESCRIPTION); + lua_setfield(L, -2, "_DESCRIPTION"); + + return 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/vendor/luabins/src/luabins.h b/vendor/luabins/src/luabins.h new file mode 100644 index 000000000..e9e777773 --- /dev/null +++ b/vendor/luabins/src/luabins.h @@ -0,0 +1,69 @@ +/* +* luabins.h +* luabins -- Lua Binary Serialization Module +* See copyright notice at the end of this file. +*/ + +#ifndef LUABINS_H_INCLUDED_ +#define LUABINS_H_INCLUDED_ + +#define LUABINS_VERSION "Luabins 0.3" +#define LUABINS_COPYRIGHT "Copyright (C) 2009-2010, Luabins authors" +#define LUABINS_DESCRIPTION "Trivial Lua Binary Serialization Library" + +/* Define LUABINS_LUABUILTASCPP if your Lua is built as C++ */ + +/* Can't be more than 255 */ +#define LUABINS_MAXTUPLE (250) + +#define LUABINS_MAXTABLENESTING (250) + +/* +* Save Lua values from given state at given stack index range. +* Lua value is left untouched. Note that empty range is not an error. +* You may save from 0 to LUABINS_MAXTUPLE values. +* Returns 0 on success, pushes saved data as a string on the top of stack. +* Returns non-zero on failure, pushes error message on the top +* of the stack. +*/ +int luabins_save(lua_State * L, int index_from, int index_to); + +/* +* Load Lua values from given byte chunk. +* Returns 0 on success, pushes loaded values on stack. +* Sets count to the number of values pushed. +* Note that to have zero loaded items is a valid scenario. +* Returns non-zero on failure, pushes error message on the top +* of the stack. +*/ +int luabins_load( + lua_State * L, + const unsigned char * data, + size_t len, + int * count + ); + +/****************************************************************************** +* Copyright (C) 2009-2010 Luabins authors. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +#endif /* LUABINS_H_INCLUDED_ */ diff --git a/vendor/luabins/src/luaheaders.h b/vendor/luabins/src/luaheaders.h new file mode 100644 index 000000000..5d1b4079b --- /dev/null +++ b/vendor/luabins/src/luaheaders.h @@ -0,0 +1,14 @@ +#ifndef LUABINS_LUAHEADERS_H_INCLUDED_ +#define LUABINS_LUAHEADERS_H_INCLUDED_ + +#if defined (__cplusplus) && !defined (LUABINS_LUABUILTASCPP) +extern "C" { +#endif + +#include +#include +#if defined (__cplusplus) && !defined (LUABINS_LUABUILTASCPP) +} +#endif + +#endif /* LUABINS_LUAHEADERS_H_INCLUDED_ */ diff --git a/vendor/luabins/src/luainternals.c b/vendor/luabins/src/luainternals.c new file mode 100644 index 000000000..60d76edfe --- /dev/null +++ b/vendor/luabins/src/luainternals.c @@ -0,0 +1,54 @@ +/* +* luainternals.c +* Code quoted from MIT-licensed Lua 5.1.4 internals +* See copyright notice in lua.h +*/ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "luainternals.h" + +/* +* BEGIN COPY-PASTE FROM Lua 5.1.4 llimits.h +*/ + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + +/* +* END COPY-PASTE FROM Lua 5.1.4 llimits.h +*/ + +/* +* BEGIN COPY-PASTE FROM Lua 5.1.4 lobject.c +*/ + +int luaO_log2 (unsigned int x) { + static const lu_byte log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = -1; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; + +} + +/* +* END COPY-PASTE FROM Lua 5.1.4 lobject.c +*/ diff --git a/vendor/luabins/src/luainternals.h b/vendor/luabins/src/luainternals.h new file mode 100644 index 000000000..373b7e09f --- /dev/null +++ b/vendor/luabins/src/luainternals.h @@ -0,0 +1,53 @@ +/* +* luainternals.h +* Code quoted from MIT-licensed Lua 5.1.4 internals +* See copyright notice in lua.h +*/ + +#ifndef LUABINS_LUAINTERNALS_H_INCLUDED_ +#define LUABINS_LUAINTERNALS_H_INCLUDED_ + +/* +* BEGIN COPY-PASTE FROM Lua 5.1.4 luaconf.h +* WARNING: If your Lua config differs, fix this! +*/ + +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) + +/* +* END COPY-PASTE FROM Lua 5.1.4 luaconf.h +*/ + +/* +* BEGIN COPY-PASTE FROM Lua 5.1.4 lobject.h +*/ + +int luaO_log2 (unsigned int x); + +#define ceillog2(x) (luaO_log2((x)-1) + 1) + +/* +* END COPY-PASTE FROM Lua 5.1.4 lobject.h +*/ + +/* +* BEGIN COPY-PASTE FROM Lua 5.1.4 ltable.c +*/ + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT > 26 +#define MAXBITS 26 +#else +#define MAXBITS (LUAI_BITSINT-2) +#endif + +#define MAXASIZE (1 << MAXBITS) + +/* +* END COPY-PASTE FROM Lua 5.1.4 ltable.c +*/ + +#endif /* LUABINS_LUAINTERNALS_H_INCLUDED_ */ diff --git a/vendor/luabins/src/lualess.c b/vendor/luabins/src/lualess.c new file mode 100644 index 000000000..fefc0a135 --- /dev/null +++ b/vendor/luabins/src/lualess.c @@ -0,0 +1,32 @@ +/* +* lualess.h +* Lua-related definitions for lua-less builds (based on Lua manual) +* See copyright notice in luabins.h +*/ + +#include + +/* +* lua_Alloc-compatible allocator to use in Lua-less applications +* with lbs_SaveBuffer. Based on sample code from Lua 5.1 manual. +*/ +void * lbs_simplealloc( + void * ud, + void * ptr, + size_t osize, + size_t nsize + ) +{ + (void) ud; + (void) osize; /* not used */ + + if (nsize == 0) + { + free(ptr); + return NULL; + } + else + { + return realloc(ptr, nsize); + } +} diff --git a/vendor/luabins/src/lualess.h b/vendor/luabins/src/lualess.h new file mode 100644 index 000000000..1e2a57f31 --- /dev/null +++ b/vendor/luabins/src/lualess.h @@ -0,0 +1,33 @@ +/* +* lualess.h +* Lua-related definitions for lua-less builds (based on Lua manual) +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_LUALESS_H_INCLUDED_ +#define LUABINS_LUALESS_H_INCLUDED_ + +#include /* ptrdiff_t */ + +/* WARNING: Change these if your luaconf.h has different settings */ +typedef double lua_Number; +typedef ptrdiff_t lua_Integer; + +typedef void * (*lua_Alloc) (void *ud, + void *ptr, + size_t osize, + size_t nsize) + ; + +/* +* lua_Alloc-compatible allocator to use in Lua-less applications +* with lbs_SaveBuffer. Based on sample code from Lua 5.1 manual. +*/ +void * lbs_simplealloc( + void * ud, + void * ptr, + size_t osize, + size_t nsize + ); + +#endif /* LUABINS_LUALESS_H_INCLUDED_ */ diff --git a/vendor/luabins/src/save.c b/vendor/luabins/src/save.c new file mode 100644 index 000000000..bf9b23e51 --- /dev/null +++ b/vendor/luabins/src/save.c @@ -0,0 +1,236 @@ +/* +* save.c +* Luabins save code +* See copyright notice in luabins.h +*/ + +#include "luaheaders.h" + +#include "luabins.h" +#include "saveload.h" +#include "savebuffer.h" +#include "write.h" + +/* TODO: Test this with custom allocator! */ + +#if 0 + #define SPAM(a) printf a +#else + #define SPAM(a) (void)0 +#endif + +static int save_value( + lua_State * L, + luabins_SaveBuffer * sb, + int index, + int nesting + ); + +/* Returns 0 on success, non-zero on failure */ +static int save_table( + lua_State * L, + luabins_SaveBuffer * sb, + int index, + int nesting + ) +{ + int result = LUABINS_ESUCCESS; + int header_pos = 0; + int total_size = 0; + + if (nesting > LUABINS_MAXTABLENESTING) + { + return LUABINS_ETOODEEP; + } + + /* TODO: Hauling stack for key and value removal + may get too heavy for larger tables. Think out a better way. + */ + + header_pos = lbsSB_length(sb); + result = lbs_writeTableHeader(sb, 0, 0); + + result = lbsSB_grow(sb, LUABINS_LINT + LUABINS_LINT); + if (result == LUABINS_ESUCCESS) + { + lua_checkstack(L, 2); /* Key and value */ + lua_pushnil(L); /* key for lua_next() */ + } + + while (result == LUABINS_ESUCCESS && lua_next(L, index) != 0) + { + int value_pos = lua_gettop(L); /* We need absolute values */ + int key_pos = value_pos - 1; + + /* Save key. */ + result = save_value(L, sb, key_pos, nesting); + + /* Save value. */ + if (result == LUABINS_ESUCCESS) + { + result = save_value(L, sb, value_pos, nesting); + } + + if (result == LUABINS_ESUCCESS) + { + /* Remove value from stack, leave key for the next iteration. */ + lua_pop(L, 1); + ++total_size; + } + } + + if (result == LUABINS_ESUCCESS) + { + /* + Note that if array has holes, lua_objlen() may report + larger than actual array size. So we need to adjust. + + TODO: Note inelegant downsize from size_t to int. + Handle integer overflow here. + */ + int array_size = luabins_min(total_size, (int)lua_objlen(L, index)); + int hash_size = luabins_max(0, total_size - array_size); + + result = lbs_writeTableHeaderAt(sb, header_pos, array_size, hash_size); + } + + return result; +} + +/* Returns 0 on success, non-zero on failure */ +static int save_value( + lua_State * L, + luabins_SaveBuffer * sb, + int index, + int nesting + ) +{ + int result = LUABINS_ESUCCESS; + + switch (lua_type(L, index)) + { + case LUA_TNIL: + result = lbs_writeNil(sb); + break; + + case LUA_TBOOLEAN: + result = lbs_writeBoolean(sb, lua_toboolean(L, index)); + break; + + case LUA_TNUMBER: + result = lbs_writeNumber(sb, lua_tonumber(L, index)); + break; + + case LUA_TSTRING: + { + size_t len = 0; + const char * buf = lua_tolstring(L, index, &len); + + result = lbs_writeString(sb, buf, len); + } + break; + + case LUA_TTABLE: + result = save_table(L, sb, index, nesting + 1); + break; + + case LUA_TNONE: + case LUA_TFUNCTION: + case LUA_TTHREAD: + case LUA_TUSERDATA: + default: + result = LUABINS_EBADTYPE; + } + + return result; +} + +int luabins_save(lua_State * L, int index_from, int index_to) +{ + unsigned char num_to_save = 0; + int index = index_from; + int base = lua_gettop(L); + luabins_SaveBuffer sb; + + /* + * TODO: If lua_error() would happen below, would leak the buffer. + */ + + if (index_to - index_from > LUABINS_MAXTUPLE) + { + lua_pushliteral(L, "can't save that many items"); + return LUABINS_EFAILURE; + } + + /* Allowing to call luabins_save(L, 1, lua_gettop(L)) + from C function, called from Lua with no arguments + (when lua_gettop() would return 0) + */ + if (index_to < index_from) + { + index_from = 0; + index_to = 0; + num_to_save = 0; + } + else + { + if ( + index_from < 0 || index_from > base || + index_to < 0 || index_to > base + ) + { + lua_pushliteral(L, "can't save: inexistant indices"); + return LUABINS_EFAILURE; + } + + num_to_save = index_to - index_from + 1; + } + + { + void * alloc_ud = NULL; + lua_Alloc alloc_fn = lua_getallocf(L, &alloc_ud); + lbsSB_init(&sb, alloc_fn, alloc_ud); + } + + lbs_writeTupleSize(&sb, num_to_save); + for ( ; index <= index_to; ++index) + { + int result = 0; + + result = save_value(L, &sb, index, 0); + if (result != LUABINS_ESUCCESS) + { + switch (result) + { + case LUABINS_EBADTYPE: + lua_pushliteral(L, "can't save: unsupported type detected"); + break; + + case LUABINS_ETOODEEP: + lua_pushliteral(L, "can't save: nesting is too deep"); + break; + + case LUABINS_ETOOLONG: + lua_pushliteral(L, "can't save: not enough memory"); + break; + + default: /* Should not happen */ + lua_pushliteral(L, "save failed"); + break; + } + + lbsSB_destroy(&sb); + + return result; + } + } + + { + size_t len = 0UL; + const unsigned char * buf = lbsSB_buffer(&sb, &len); + lua_pushlstring(L, (const char *)buf, len); + lbsSB_destroy(&sb); + } + + return LUABINS_ESUCCESS; +} diff --git a/vendor/luabins/src/savebuffer.c b/vendor/luabins/src/savebuffer.c new file mode 100644 index 000000000..27ab236cc --- /dev/null +++ b/vendor/luabins/src/savebuffer.c @@ -0,0 +1,252 @@ +/* +* savebuffer.c +* Luabins save buffer +* See copyright notice in luabins.h +*/ + +#include /* memcpy() */ + +#include "luaheaders.h" + +#include "saveload.h" +#include "savebuffer.h" + +#if 0 + #define SPAM(a) printf a +#else + #define SPAM(a) (void)0 +#endif + +/* Minimum allocation size */ +#define LUABINS_SAVEMINALLOC (256) + +/* TODO: Test this with custom allocator! */ + +void lbsSB_init( + luabins_SaveBuffer * sb, + lua_Alloc alloc_fn, + void * alloc_ud + ) +{ + sb->alloc_fn = alloc_fn; + sb->alloc_ud = alloc_ud; + + sb->buffer = NULL; + sb->buf_size = 0UL; + + sb->end = 0UL; +} + +/* +* Ensures that there is at least delta size available in buffer. +* New size is aligned by blockSize increments +* Returns non-zero if resize failed. +* If you pre-sized the buffer, subsequent writes up to the new size +* are guaranteed to not fail. +*/ +int lbsSB_grow(luabins_SaveBuffer * sb, size_t delta) +{ + size_t needed_size = sb->end + delta; + + if (needed_size > sb->buf_size) + { + /* + * Growth factor x1.5 + * Discussion on possible values: + * http://stackoverflow.com/questions/2269063/buffer-growth-strategy + */ + + /* TODO: Handle size_t overflow? */ + + size_t new_size = 0; + + size_t add_size = sb->buf_size / 2; + if (add_size < LUABINS_SAVEMINALLOC) + { + add_size = LUABINS_SAVEMINALLOC; + } + + new_size = sb->buf_size + add_size; + +/* + SPAM(( + "trying %lu + %lu = %lu (needed %lu)\n", + sb->buf_size, + add_size, + new_size, + needed_size + )); +*/ + + while (new_size < needed_size) + { + SPAM(("...+%lu not enough, growing more\n", add_size)); + /* Grow exponentially as needed */ + add_size += new_size / 2; + new_size += add_size; + } + + SPAM(( + "growing from %lu to %lu (needed %lu)\n", + sb->buf_size, + new_size, + needed_size + )); + + sb->buffer = (unsigned char *)sb->alloc_fn( + sb->alloc_ud, + sb->buffer, + sb->buf_size, + new_size + ); + if (sb->buffer == NULL) + { + /* TODO: We probably should free the buffer here */ + sb->buf_size = 0UL; + sb->end = 0; + return LUABINS_ETOOLONG; + } + + sb->buf_size = new_size; + } + + return LUABINS_ESUCCESS; +} + +/* +* Returns non-zero if write failed. +* Allocates buffer as needed. +*/ +int lbsSB_write( + luabins_SaveBuffer * sb, + const unsigned char * bytes, + size_t length + ) +{ + int result = lbsSB_grow(sb, length); + if (result != LUABINS_ESUCCESS) + { + return result; + } + + memcpy(&sb->buffer[sb->end], bytes, length); + sb->end += length; + + return LUABINS_ESUCCESS; +} + +/* +* Returns non-zero if write failed. +* Allocates buffer as needed. +* Convenience function. +*/ +int lbsSB_writechar( + luabins_SaveBuffer * sb, + const unsigned char byte + ) +{ + /* TODO: Shouldn't this be a macro? */ + int result = lbsSB_grow(sb, 1); + if (result != LUABINS_ESUCCESS) + { + return result; + } + + sb->buffer[sb->end] = byte; + sb->end++; + + return LUABINS_ESUCCESS; +} + +/* +* If offset is greater than total length, data is appended to the end. +* Returns non-zero if write failed. +* Allocates buffer as needed. +*/ +int lbsSB_overwrite( + luabins_SaveBuffer * sb, + size_t offset, + const unsigned char * bytes, + size_t length + ) +{ + if (offset > sb->end) + { + offset = sb->end; + } + + if (offset + length > sb->end) + { + int result = lbsSB_grow(sb, length); + if (result != LUABINS_ESUCCESS) + { + return result; + } + + sb->end = offset + length; + } + + memcpy(&sb->buffer[offset], bytes, length); + + return LUABINS_ESUCCESS; +} + +/* +* If offset is greater than total length, data is appended to the end. +* Returns non-zero if write failed. +* Allocates buffer as needed. +* Convenience function. +*/ +int lbsSB_overwritechar( + luabins_SaveBuffer * sb, + size_t offset, + unsigned char byte + ) +{ + if (offset > sb->end) + { + offset = sb->end; + } + + if (offset + 1 > sb->end) + { + int result = lbsSB_grow(sb, 1); + if (result != LUABINS_ESUCCESS) + { + return result; + } + + sb->end = offset + 1; + } + + sb->buffer[offset] = byte; + + return LUABINS_ESUCCESS; +} + +/* +* Returns a pointer to the internal buffer with data. +* Note that buffer is NOT zero-terminated. +* Buffer is valid until next operation with the given sb. +*/ +const unsigned char * lbsSB_buffer(luabins_SaveBuffer * sb, size_t * length) +{ + if (length != NULL) + { + *length = sb->end; + } + return sb->buffer; +} + +void lbsSB_destroy(luabins_SaveBuffer * sb) +{ + if (sb->buffer != NULL) + { + /* Ignoring errors */ + SPAM(("dealloc size %lu\n", sb->buf_size)); + sb->alloc_fn(sb->alloc_ud, sb->buffer, sb->buf_size, 0UL); + sb->buffer = NULL; + sb->buf_size = 0UL; + sb->end = 0UL; + } +} diff --git a/vendor/luabins/src/savebuffer.h b/vendor/luabins/src/savebuffer.h new file mode 100644 index 000000000..7207c3819 --- /dev/null +++ b/vendor/luabins/src/savebuffer.h @@ -0,0 +1,91 @@ +/* +* savebuffer.h +* Luabins save buffer +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_SAVEBUFFER_H_INCLUDED_ +#define LUABINS_SAVEBUFFER_H_INCLUDED_ + +typedef struct luabins_SaveBuffer +{ + lua_Alloc alloc_fn; + void * alloc_ud; + + unsigned char * buffer; + size_t buf_size; + size_t end; + +} luabins_SaveBuffer; + +void lbsSB_init( + luabins_SaveBuffer * sb, + lua_Alloc alloc_fn, + void * alloc_ud + ); + +/* +* Ensures that there is at least delta size available in buffer. +* New size is aligned by blockSize increments. +* Returns non-zero if resize failed. +* If you pre-sized the buffer, subsequent writes up to the new size +* are guaranteed to not fail. +*/ +int lbsSB_grow(luabins_SaveBuffer * sb, size_t delta); + +/* +* Returns non-zero if write failed. +* Allocates buffer as needed. +*/ +int lbsSB_write( + luabins_SaveBuffer * sb, + const unsigned char * bytes, + size_t length + ); + +/* +* Returns non-zero if write failed. +* Allocates buffer as needed. +* Convenience function. +*/ +int lbsSB_writechar( + luabins_SaveBuffer * sb, + unsigned char byte + ); + +#define lbsSB_length(sb) ( (sb)->end ) + +/* +* If offset is greater than total length, data is appended to the end. +* Returns non-zero if write failed. +* Allocates buffer as needed. +*/ +int lbsSB_overwrite( + luabins_SaveBuffer * sb, + size_t offset, + const unsigned char * bytes, + size_t length + ); + +/* +* If offset is greater than total length, data is appended to the end. +* Returns non-zero if write failed. +* Allocates buffer as needed. +* Convenience function. +*/ +int lbsSB_overwritechar( + luabins_SaveBuffer * sb, + size_t offset, + unsigned char byte + ); + +/* +* Returns a pointer to the internal buffer with data. +* Note that buffer is NOT zero-terminated. +* Buffer is valid until next operation with the given sb. +*/ +const unsigned char * lbsSB_buffer(luabins_SaveBuffer * sb, size_t * length); + +void lbsSB_destroy(luabins_SaveBuffer * sb); + +#endif /* LUABINS_SAVEBUFFER_H_INCLUDED_ */ diff --git a/vendor/luabins/src/saveload.h b/vendor/luabins/src/saveload.h new file mode 100644 index 000000000..117e209ff --- /dev/null +++ b/vendor/luabins/src/saveload.h @@ -0,0 +1,114 @@ +/* +* saveload.h +* Luabins internal constants and helper macros +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_SAVELOAD_H_INCLUDED_ +#define LUABINS_SAVELOAD_H_INCLUDED_ + +/* Find minimum of two values */ +#define luabins_min(a, b) \ + ( ((a) < (b)) ? (a) : (b) ) + +/* Find maximum of two values */ +#define luabins_max(a, b) \ + ( ((a) > (b)) ? (a) : (b) ) + +/* Find minimum of three values */ +#define luabins_min3(a, b, c) \ + ( ((a) < (b)) ? luabins_min((a), (c)) : luabins_min((b), (c)) ) + +/* Preprocessor concatenation */ +#define LUABINS_CAT(a, b) a##b + +/* Static assert helper macro */ +#define luabins_static_assert_line(pred, line) \ + typedef char LUABINS_CAT( \ + static_assertion_failed_at_line_, \ + line \ + )[2 * !!(pred) - 1] + +/* Static (compile-time) assert */ +#define luabins_static_assert(pred) \ + luabins_static_assert_line(pred, __LINE__) + +/* Internal error codes */ +#define LUABINS_ESUCCESS (0) +#define LUABINS_EFAILURE (1) +#define LUABINS_EBADTYPE (2) +#define LUABINS_ETOODEEP (3) +#define LUABINS_ENOSTACK (4) +#define LUABINS_EBADDATA (5) +#define LUABINS_ETAILEFT (6) +#define LUABINS_EBADSIZE (7) +#define LUABINS_ETOOLONG (8) + +/* Type bytes */ +#define LUABINS_CNIL '-' /* 0x2D (45) */ +#define LUABINS_CFALSE '0' /* 0x30 (48) */ +#define LUABINS_CTRUE '1' /* 0x31 (49) */ +#define LUABINS_CNUMBER 'N' /* 0x4E (78) */ +#define LUABINS_CSTRING 'S' /* 0x53 (83) */ +#define LUABINS_CTABLE 'T' /* 0x54 (84) */ + +/* +* PORTABILITY WARNING! +* You have to ensure manually that length constants below are the same +* for both code that does the save and code that does the load. +* Also these constants must be actual or code below would break. +* Beware of endianness and lua_Number actual type as well. +* Note also that luabins does not check for overflow on save, +* if your integer does not fit, it would be truncated. +*/ +#define LUABINS_LINT (4) +#define LUABINS_LSIZET (4) +#define LUABINS_LNUMBER (8) + +/* +* Derived lengths +* +* WARNING: Change these if format is changed! +*/ + +/* One type byte */ +#define LUABINS_LTYPEBYTE (1) + +/* Minimal table: type, array size, hash size, no data */ +#define LUABINS_LMINTABLE (LUABINS_LTYPEBYTE + LUABINS_LINT + LUABINS_LINT) + +/* Minimal number: type, number value */ +#define LUABINS_LMINNUMBER (LUABINS_LTYPEBYTE + LUABINS_LNUMBER) + +/* Minimal string: type, length, no data */ +#define LUABINS_LMINSTRING (LUABINS_LTYPEBYTE + LUABINS_LSIZET) + +/* Minimum large (non-boolean non-nil) value length */ +#define LUABINS_LMINLARGEVALUE \ + ( luabins_min3(LUABINS_LMINTABLE, LUABINS_LMINSTRING, LUABINS_LMINSTRING) ) + +/* +* Lower limit on total table data size is determined as follows: +* -- All entries are always key and value. +* -- Minimum value size is one byte for nil and boolean, +* but that is two keys maximum (nil can'be the key). +* -- All the rest of key types are mimimum of LUABINS_MINLARGEVALUELEN +* bytes (type byte plus data bytes). +* -- All values in the table may be booleans. +* +* WARNING: Change this if format is changed! +* +* Note this formula does NOT take in account +* table header (type byte and array/hash sizes). +*/ +#define luabins_min_table_data_size(total_size) \ + ( \ + (total_size > 2) \ + ? ( \ + 2 * (LUABINS_LTYPEBYTE + LUABINS_LTYPEBYTE) \ + + (total_size - 2) * (LUABINS_LMINLARGEVALUE + LUABINS_LTYPEBYTE) \ + ) \ + : (total_size * (LUABINS_LTYPEBYTE + LUABINS_LTYPEBYTE)) \ + ) + +#endif /* LUABINS_SAVELOAD_H_INCLUDED_ */ diff --git a/vendor/luabins/src/write.c b/vendor/luabins/src/write.c new file mode 100644 index 000000000..996267ee4 --- /dev/null +++ b/vendor/luabins/src/write.c @@ -0,0 +1,75 @@ +/* +* write.c +* Luabins Lua-less write API +* See copyright notice in luabins.h +*/ + +#include "luaheaders.h" + +#include "write.h" + +int lbs_writeTableHeaderAt( + luabins_SaveBuffer * sb, + size_t offset, /* Pass LUABINS_APPEND to append to the end of buffer */ + int array_size, + int hash_size + ) +{ + int result = lbsSB_grow(sb, 1 + LUABINS_LINT + LUABINS_LINT); + if (result == LUABINS_ESUCCESS) + { + /* + * We have to reset offset here in case it was beyond the buffer. + * Otherwise sequental overwrites may break. + */ + + size_t length = lbsSB_length(sb); + if (offset > length) + { + offset = length; + } + + lbsSB_overwritechar(sb, offset, LUABINS_CTABLE); + lbsSB_overwrite( + sb, + offset + 1, + (const unsigned char *)&array_size, + LUABINS_LINT + ); + lbsSB_overwrite( + sb, + offset + 1 + LUABINS_LINT, + (const unsigned char *)&hash_size, + LUABINS_LINT + ); + } + + return result; +} + +int lbs_writeNumber(luabins_SaveBuffer * sb, lua_Number value) +{ + int result = lbsSB_grow(sb, 1 + LUABINS_LNUMBER); + if (result == LUABINS_ESUCCESS) + { + lbsSB_writechar(sb, LUABINS_CNUMBER); + lbsSB_write(sb, (const unsigned char *)&value, LUABINS_LNUMBER); + } + return result; +} + +int lbs_writeString( + luabins_SaveBuffer * sb, + const char * value, + size_t length + ) +{ + int result = lbsSB_grow(sb, 1 + LUABINS_LSIZET + length); + if (result == LUABINS_ESUCCESS) + { + lbsSB_writechar(sb, LUABINS_CSTRING); + lbsSB_write(sb, (const unsigned char *)&length, LUABINS_LSIZET); + lbsSB_write(sb, (const unsigned char *)value, length); + } + return result; +} diff --git a/vendor/luabins/src/write.h b/vendor/luabins/src/write.h new file mode 100644 index 000000000..deb3e4996 --- /dev/null +++ b/vendor/luabins/src/write.h @@ -0,0 +1,44 @@ +/* +* write.h +* Luabins Lua-less write API +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_WRITE_H_INCLUDED_ +#define LUABINS_WRITE_H_INCLUDED_ + +#include "saveload.h" +#include "savebuffer.h" + +#define LUABINS_APPEND ((size_t)-1) + +#define lbs_writeTupleSize(sb, tuple_size) \ + lbsSB_writechar((sb), (tuple_size)) + +int lbs_writeTableHeaderAt( + luabins_SaveBuffer * sb, + size_t offset, /* Pass LUABINS_APPEND to append to the end of buffer */ + int array_size, + int hash_size + ); + +#define lbs_writeTableHeader(sb, array_size, hash_size) \ + lbs_writeTableHeaderAt((sb), LUABINS_APPEND, (array_size), (hash_size)) + +#define lbs_writeNil(sb) \ + lbsSB_writechar((sb), LUABINS_CNIL) + +#define lbs_writeBoolean(sb, value) \ + lbsSB_writechar((sb), ((value) == 0) ? LUABINS_CFALSE : LUABINS_CTRUE) + +int lbs_writeNumber(luabins_SaveBuffer * sb, lua_Number value); + +#define lbs_writeInteger lbs_writeNumber + +int lbs_writeString( + luabins_SaveBuffer * sb, + const char * value, + size_t length + ); + +#endif /* LUABINS_WRITE_H_INCLUDED_ */ diff --git a/vendor/luabins/test/large_data.lua b/vendor/luabins/test/large_data.lua new file mode 100644 index 000000000..29e212c95 --- /dev/null +++ b/vendor/luabins/test/large_data.lua @@ -0,0 +1,38 @@ +return true,nil,907.8738621938385904286406002938747406005859375,true,-10.074422490352031189786430331878364086151123046875,nil,0.5328851083912351516147509755683131515979766845703125,true,true,0.5577272826608863365294155300944112241268157958984375,0.77317682130875853285800758385448716580867767333984375,4203,"ΤФZkL+$ֽxG\000TKwj=h \"@5,WI.[\rN[bFV|ѽJV h1L\r{ \\AuVcYN,ۛl C1O'\ +L\ +#kRD-UajmД)b'4:P h_a&yLkjL|mX ?Ub`Nxt.+{%ӿM,%Rߏ@v+z8\ +T$0 Nd$#F::ptI>̣k52譂)*4:7'm+>UqD8","/IqOcw(R|gpž[*0uXEZ&Gx\r-? \000$qiʑ#9')vBpX |f^*hëk7z{l{(LOze@L†ZB7\r\000Nlt UVM\000fQ UtfC0SQSI2;[5a?~N4E,)\\|@$r⮣=?\\4VG=qh\"\r:ܪkZʚlmu` g↘$oFhqC%{̎s8Vh屍д}U#H4cֵ~\rEj-O j8uU¸nh_Ekx᤽^xp3!6f#A.=ƵP\000Svח$\r1?n~3ֺ~MՏb9*XoZ~7^3-kgz[fGո0nFޥ6\000&5GM˔b̍ &","@E~1X`'2t qIpZ{h;8z` ^\rޤ#,U1l퀟(1\ +̵gNL{o \\Pz |8~sh#o7*9;4~@gwIZi4All4Y@3UEyiK띍\ +ݲəq,;Եb>\000M܍!{E2!`焞{vbTy2Ow\\nnB(*m~eK>E,Q|8>[g*%36Ѯ#[qd%Pdթmr|j͇i6_ÒаG96X%dHN~-ՖNZAu :@eF9Cf4Tw2~a}\rR\rW_.G6=k$To|$1QFu7w\ +Yt^F;j-*É4qyVmv\"L{ hP/@WI:E y}<#y ! m_u\rRR^si `QZa?\\i YsX\r@50ܚ<ǽF~%rd<Op #ATd lEߪOG]#",false," 2}yI<;fJ#-1)mڟ6!¯ \000(\r6s.M ϳ۠U{MLz (f6m{ɮJֲ,f[5J=Čf+~31 yOs &uѮ;Je E~?ѧ򓟰]Ea-ǥs#ӭ^d,t|10^'ҊK]mIW\000.ldt[+qh@Rqfy}a)ٖO\ +|6.fޟEoae~zqeJ>I`\\IwDᘩ(p + =gQ)K@.s_BO+n36\rD(3eOPL6'+7UYdoALiXb7\ +aH!p@lɤ\ +(tN&5tmu--\r$s5ߥAd@t͂8ZxRkn^K8S'i|=aiWy˹\000w(9W $dJ51T?LZL&4 5+;#T1p))>d_hf’w^a\r}wT06EzB1sX3.XI^TwQœ+",nil,nil,false,{},"LpPh{,I*,C# =Ȋ\"csPt@GhqY+cBA~I ll6q~KCZNX.:L-9/X+fyg}gz멬Hå]qh:γ}L\"\\[4Ċ;\rMkp!X{yTo%`&GAӡ<ۨ+9nKÖԭسB`;pȲoP{N!خPng\"zlU4YE@B&",0.13656971796256012208203856062027625739574432373046875,"EeNd&IF>+nT[wNF۫D\"cX49(L >Ii7OaG&4)b3Ӗ9ate|GVgdhגzamH-g S\ +Kp5<_zQl\"F]}T6)l3oOc~Xn Hklea)F!\ +RmYwCh+BpYSO(S\ +&w/dpg2ؓuI+d@?ҏۈS89ߧFڃO\rkYǦ;IJLꍆ50_x~BdJ\ +󌛥bmY%i4QSA_$S^o\ +N>`vdߙP3-!uԁ/p+Ó#2y=]/!wު\000 O{5?rAFHho\000x#GC^xQMv俷oNggatF#,5(dFq-2đ9h m/ \\Hl)K(AN2Mz7?x{?Q}z\ +<$@ZwwWlSaI3.G-)mD妼p)vHGn\refm\ +M!MFX{hLPƏEִ<`?0]\000{LI Q먄UTFߏlj{vQ67yuWYF RʄU?I","̗7C&!ʑ quSCP ͐vHV6TuX\"#wjlh޿Ҿ^H]5Nڹ(&#pB9PJ W>{;ފ?DgjiEȺ9!x.DXU#'[^ _4nSe6؎qט2*~J63kD=.^W.lSDh_LP4BSGWo#2{2J09͉k~@F4!g)^\\B\000s:@ B򧐀.B20ڸ\000",0.4478582876957293290587358569609932601451873779296875,9428,nil,nil,1244.468268439391749780043028295040130615234375,"`ORH'L\r y×;a+4Ccf{qn~PT0][zƾDp8j.)(z,b̊ݾQw2Jw7-f#V|\rmm!0`1=3p}Y\000S.woV~izB +e,Z1FsPef#pwLx$NVR Lov3?ѷFX}:\\9kkpUZ˲QL9l#s{1Bz>2\ +oi\ + XEӹRgl=-_)zIʒ:P^ZjS\ +j/6mX_HҨ%04(mw4U\r6TJ>w D Y(<]&I])F,HB?b_a2;Y&O+X|\"*2:(S+${+Tq[\r8Bz5$fNٝWvA8M.jm-\ +5ZgrzPN^AtZD[>3A ?\r:i\ +Q'k^ȡ\".J~AOYm%\\ج7t\ +9{6&","fdqKJ6^BŽIJN )\\cD(յ2{i_G^\"4Y/z |Ȫ'q6jDH?\\\r)F?}R\\62ܜ&Na@mIv%\\@(̰ -hdQ@d.݋|?Ba$I$b/!NgΧWK#5pfDъ&Q#-G gT|f4B8hR.G 3Й7@G=gG[e;c\000j0C9/",1268,false,"<¾\"ҍE\rFP%\000U_[Nk^y'$M%]][HKdcCgkC[@,N@f]םBBZVAwӴ-#LD_=,8byPlլ?M@4+N\ +Ij.rMZ%GJ[ߔhXNޱӹXH\\o`MsՓ-G","д7,fǸٖ 7wY)Z1 ]s-MƓ]Xmgiڸ4CUOBa(quIGx5 'f@b$u <jdwBe>T{* j1\ +F\rg^JiȀn:G!x[E>c5LSIև\000HKb#34)0IΓijݤT-*\000D*\rVTS0I)eB<\r\r%72)r=(U@u\"[/;=`|upHUebW2?Y{3xoF1qˀw^9ΐܳ9nJrF!b8{IbV^Ĩ6c\000w 8<.(o/w΋MOYv{갌5뇅) :=+oM=ܡy:\ +fܜrd!S,9dJV&*0m:\\p{#\ +Cm}Jt^r}i\\Bu?2L9h}m7.T,>i>qswgO&ޚءvI@`[¥0W 68`_6 \000_>x\"䨺\000Ur\rQ„m\rA\r<0n^ma$ JϤYQ\ +","ZL}F[]st%]~EYԼ\"w5kF>lƛց0JFk5W\ry],rI{G;+VG(OoR.?V`%\\/Q3,t#>ii.|\\*\r^B>UBfq^;C 6 w{[_]?V#9f/br7g[Q;-{yLeF] 60ȍb({d,Yy\r] W8Ai\ +0@miΑx88{9&quRG\000X\000$ 6]w 'R(!m5+D2LDMlJUkZ_#hJ$lGrǤ Z;VpQ@LS>1G\"f|?1̀ψ hnY ` 9/b7Ǭ4' qb<H\"Y,UX41 uׯqj\\xVlrK5I' Y0\rEx~<I?U9!\r2 /kǙNT)I{uؖjȦ.]7:8&OmiV7^EByxF߲ngg2b˾A)4GoCEԭ<#+WkC6Tgph.V\r\"SXo5Ao*Ns'^VhcO$_rx(Z- \r(߷}DW#$@ )F%! m?:N(~DTk *a]b~I$ڮ`_ҖuMRV4P1UcЁ.",7463,7066,"/Ϲd Q뫛k9>PC#<*@`ȻI_P^E iH~dgVDeGY(>EGAMZRd*OGwy'T`f㛯񃭳kMS4ٹvxLbA}Q`o\"@#p㥐^m4V[6xAhMU\"xb9CPAh~N˟PF u PtcBoV,L~3g[k`st7;dŬKx%c};UZIkHĀ:,R^g3ܢL\\\\xb]z1dW\\|k[6JYP*Vݑ@Z~dNyp;LvoTXx`3y\000Fqzd䵰'?{C֓БOX# 8_bۀ|/RJO-nHk5$ +$f5R!t6X 9?6TsJL" \ No newline at end of file diff --git a/vendor/luabins/test/large_data.luabins b/vendor/luabins/test/large_data.luabins new file mode 100644 index 0000000000000000000000000000000000000000..edbba9f8bd1bcd56e92281d63e92bdce55656680 GIT binary patch literal 9590 zcmYkgV|XQ8%r0EJ-Nn?lZJX2X+V0fuw4K_vjp@|3ZDVTN=C1M0cb;>-?^!?Al`F~0 z`jgzr9VJ#q;G5vDiVuTm5mq3VylEpI6-6&2a2$^e-3)nGn3WYcUAMn?w6ZG+n$EH?9RR97E?0veh>u;fsjeG=sC&f~i`?fTg+Vl5&w>4`)OA@jtf}50I14H9%o4;3kiSkq zzVNz6)Vm^B9lcClKHn`8b=4R~`=R|d0c2RuBCsumKTgLK4`U@zByONaNS>5OAVPY{Fz0BNurpHZ5An;1_m|h1sZ|+VklK2VUa1H} zKYCJ>XMj$~G~d-bH+uEjm0GHMqH&$HR~vj|bPN>H@Qf=cN#PWI!^%B!OE=Np=0#XG z_AmImU@-~40u*H)`#bMw4p(nXtR$0mT7ENj@R}#(DUPLBv9A=&me}z2Bg|$jo`}B2 z!C6X+h>Hw@wO^(Z#_+9POrFbi>&#K?=LQnQD|ek$`E&mm^TC8s$v5OGXE>u~wKRJ6 zfb3uQ?tza#+ewYlV+gN*FL0L-z?_04abR0VFIKho0GweN9+hVpUW zQrivEKLrZGsynS>Ni=`n@u+%0f`Ku^!R_>)W6C-y`u}jdq{%-l-@W)!8OBWW{ua@6 zZ*lPEIMl7X20KL;#**)I6JEELC)SSy~yyDGsv%z)1F8EjZ;>(y~WBd=In?unb9 zd~PO^CEp*aBX*a_eSzEn_6)RjfmhGbC{zF=GB0RQhQGg5Z+5ADHWz16Ro+*XW$WqY z|E8PJR+_jB;EXgD_5~($^h+|(M(BC3iOf*^jN7X&5ERxsn&SY$^=L>77Hv3LlI0{+ zydsD4ZIoBqMC$;?Gi___{uH|!eRSpIX8;g8su`2j<6&>D(Sv8jW^ zn#VO(y{o^~-qKK#@M8Ve<|4s;x3H@i&_8eB9_P0=`rt@Z&%R8W&1K$BE?N=CBnSuC z8*aJ{k5B@`o!Q$RQ2qK9wwy+R{JF&{9NB9>GU{6v$DW1Vb&kE%{@UuR&iQ}cyYFRiwcla#T!SuyM3uwG*zG4j3{+(`OdN;sG^PM&vM9;GsQ**{6!V zM||C}{$v6pb-d_M%J;U~2v(v`ghkdL?;TepxYtDtQMtZVD0pyA*{(AUQZFe}2f{j= z(Q<)`hO+icwIR!4w!$k2Y*R(4ZU6+5Ekl{mlPESI3F9n;58rx?0DV2fLs)N>+-{H9 z>6G~p9s4M1pGSgzt=36(F29P_4LIyR)MSiml^8)1GPEKeKi0wzn%*9NkEq2OgaC`9 zNWapoZ=G`HvSFdN=?tgX1~K14feSDrh8u3y23yJ}1~0)so2OU5)QxN|qt&3#_wbxp zuH2u1>h`S-3JBSiP$Wd{*H7&dnpCU@UfeVK%AzsCZ6UFMd+B~rWy4E#KO|Ip$ngf< zn?qq60>G%9vPKo+x&Yox&<5%P|0i7s0v{bR)TR}vzszX6l~w`4?+sIzo0+a1i9b$; zw;fXafl2uVsr`E9hhjB>$2--_6TcdhjqfSYIm%wLP4ZY67<*a6I`VidtoDD9{onOJ z!hcxL($f2%;BVN=$OwcBhmV0A6zgSVVPs_dA6LfzT(0^>{#W(S{-1UiVgax1}?|B z8xza)^ROgzDEEAaj1FMpmBj!&E~E2Y!*b?mATvzc%VV>INcW3m1V&{8kS1g_wlo!* ztwV~O+Qmjj9a6bEt1Lu8bOEuI$n+h!kC2Xwx?NF2;w;>s&Y#2kDeu3>;m36V0zTISTc7E!rIZY5O(o6+uv$8%OdNYB^?arrXr!2lo=|mz36L>A07kgB5c_G9Z_Y!8WMh+RmmO z6Wg*89)X&vsHaZ%wGy?F$X}f1B&U~OxDw~N^UPm*=IJ-vNRxJCjm8+-^g@UI{drV} zVCi}UyOLb>UmOT0vtC0xV=Q2Lt%~W(MK2D3dY#>maxh@Eq!|~oev4) zmTr%j8=k!QzBbCx3wrl)G}yC{iHNCxP?N_xxlD6H)o^+6=o-rV;}2H zCS!6*s76#X|0OPp$h)L(AZufg)|nAC+rA4_HGEQ0C&)=QDbZ2K3)`|2qnbZ;=LVN& z&C>|UU=a;@tFS&RgZzM@Nj;3!_U6+6Hx0HQ4r}XuCC(SZB^vf*)0hSDLf$JsA7UQm zt~W06v;+-eWgHZ|2a5d*Q=Hx500pn76#RJ?HV5vRlz`;TL*$Ek;+#BgNuK2}#!bh| z&yf<{mh3BH;otF!HsU6G2-2Cdx=x=%=MdenwZ$yStKiTUX~-;LSI?Iu#Epdjoc{G# zvHE_V6ElMFvRR)IadbbH5$iO$kAVixkO#>hvCw291g5YN^X(|?E}hiN@0%n}e)D1I z*i+bJS`-_p(Q$C@$*k9}Ba@HSS0XhJwv5C@MK?WM`+Zaxdoh|Bx=K5A-_vlj?;%2x zg^4}O49b<>V{j=v7sW!lCl+)V-_j@(1FD`U*}2e{M`x=+y-xV$JG!h44gJvwyAm83<9+P~9lS}ijT^kqat{pf>T zOa{ za|u@2Bv9m(78I&EK+kz^P$XZmp3f+k#Yt6PyOwfS9v))5Av6+KX}b^@NM-O_Gty<_ zzFZDOa5#CC;nr$=rr7=ZO_n0>1#h{g1cBMkETSpPCy6xR;UhqvcIlB4c#KF2|Hm%4 zV#)Ar#kCo(30dV@#h_twsQ?{ zc>#-R#lQS~!cXahXY1Zi^?~#_lNA_$;O}USGXIhrAirW{ZCat7wL4t*84?*8hM zGdmdtCwM`eMEor|>6;=P8Hro__1rvLa+mbGHc|ieS+f7dxC5GTq{umm9B#fU@xmbS z5Ysdo_KBe-GNLYU#>JbJCD7oBdM@(&n*Ot$tR@(ft!amg?lJw5)25|}%7Ig$`CpIN ze8^QF0Cmc*wBH9snC6C^8x0A?!ebQa?V;E+ zpKpt~0Lb@5-4eLR@tZU~wb$%sib|!+o6ivP?_5V9>S%iIOk#CyQwPxpd8@_`tz(lC zZUjF}hydfSRvFOFA}O|`i0xS620{jn3y^A(Gs49#={_*k^&pjzF&Y`7n!@=yK_J;q znlZJ*t24Y#@||e)`j4Yo2y9|~QeKnjAPtMU+0a1cowkKN)-{Rlg%Ib)c9E!Q)dIGN z%Tyo_s3BIzT?N*r!hW^S;Dzuzk193xirhJ%^Gjmg614j z`71?%=^wd#PFA(FOyR4R);#%O9r?FFDh~M9s0~=oCHhtVN%BnyHP(!4$M9lW+PkVC zp;BnmO@N{0xp{7XqT7c-*1GWx^4qpgP)JFYn;J{=2N(XDq^B6`?(V&_*6r-W6#Ky% z)1X$J?3Y2GTAZ8mP!c^OBg_9x9IAfcU|{Xn@{U9+N|tC-6Zl>XvXykZ)eQUM3{qd6HUYSmEDK8ov_`;-y!C5TKD}f zehs4&Q`7*Q#lFPQ3T9fGM&IGvlE-^tH|H~7foKas)YP50^PHa&6-M)D&o?AUZWl1|-3z`|&C1QjlM zjcgL6smgSEs+}bllJ5%`) zec%r~c@DaJ=5{iFr8*5jIa=%yRWjbK2Jr)~2>8{4_NR|iXrXGQK@7tvjokpI||@;2C7w{Gjev%%PoIST0HY3=&B$#1(sJqyh>&k}VK= z^$Dw%|D$)3F=k^g1YN)^)4&Hvs$5yARH0D%{XF{>wG>@9pj6j-Md-qa1lfxMgEmr@r$;dq@a*cgH zmDkv%ApP0QTbfv-%)+$5GIBZbPlhLyvE9qL3}g3}1&Jy`+jmFKq_`-7r<-j<&z3uU zWn1EgHQZb>DShxNAGKDlJX%}!)@O&>6Ggxe7zkf2`&>ks)^eLqINQq5KC>?4SlVPM zQpiUH6&O2hxQlwXsP0~IOL{TK^s7g0)rR)nO+}h7Rbqr9Dz`6Y)4GytM+>%E8Fc(at@}de7-N^4(-mv zylHV6NRwHaK!^8^Q!Ft2jm>Cd@C{pipR2=6OFYeu6P8xBfAT_B~ z>t&fqET5#*Jsc+qSZX8?$PX;5`fF5vdm1myqMyFI3g-1Jk0Oh>xT1Ve4Gn%?8l0l8 z2KtiPjtfD(Ai5nQvhB9^g8ikuJ;D_`#qHtRi877~HKuu>z4;*Zc8G+lG9ElV`$}Bb zr!E{D(*`L!s%r5MJ15iX>TY9;xFaIP^EXkbDz-_-6ZS}EovI>TpH#(_NY=q;r{aG> z;eyL_ZfWdCa6ze!9=m2}k&#d1x}jUAUD{fjh%X^a-i zQLSi~NVW7gl)om;8Y#7T5zh5U}l(B%<2;4>yhGmJ}0l0#szE<#CV^ z?}v~)5&*Z5`DbtgY5YmX^!FU#;v;xNxIZq;yRY{YVIaY5WKjOOGT-nqzjb`PYP zGb~1|ALoD$!E$!Tai3#tFd|i^V7Cx(%tVKvuy{g^KHuXJf)gb(^HuV{j=662@^RhnF%*RrTVFuH_ML_bG>Lo}Tn@nD7rXHBY)b}_ zlve7351+pt@3ak0Z@X}zZq z+akiDLzh)A0+LpZ}HzQ$U&l`no zn=T-fEu1fj24@&rm6-mV!V7zJo?gvq=t!W{L~dNnMSiqo0g~^701U!`_#ag*{fXq2 zYjkNUO@~zOvV3t$-W31bIssakc$PS){LM0rE+|)*%Y%7nLKe6D;?+yYqKtV;h}eA! z39(3<5B=0ACT70t={3BOtKN`4>(T@xle5_-qBiZCnP4Xa4&w=Arqw z2mjr%w#Vs@qjPNWvll81$8%I^^r?Nfc^cUGj@|u?YtVQvdgh`dq1)GtKP<#93L6an zDSY0D%x8t5Obuxh+F~&JXP)ek=^#t4e9iZK7Xq{`x|^(s|DkP1skc&z!R^w7ke12o z#T7(_3XXmU1*?kn4^2Kp4|N^N?mxy+(eeRm zry*S8W3HAs>q-d-8DTwS+NdxoVILJeF1D4gjch8Qv51}QFUpnOIl==xJrSDF$=XRo zMj}g7Wf4=R%_wi-iL(eXfHB3cAKd$fEQJZ?A~Pu@Fv22ld~&)(^ZPM5r=z*VY$TO( z5;^0Bbo?!04+aTJc38EAnm3?gKnm>5CIB!~zKXX*qf9t%zNg^z&5C4{pv0?cF{oOco zWSDa?lKaR~u}XfF3t;MoT^H9x#KXGPz|S+(PRRW&oF*HC438q}F$#qo%KZ1exC`)_ z27P^ST^V$o@1Q5s@*n-;8x}T2(XHZjx+2ME3@Mr0_fNY(k$dy#6aAZ{zJ}!-d@-@o zw@@98;VaSm;PrX8`NrXIC5(CTQ3>So60fI*f(&px^(Jv1N`Gw^D}@#O?=h0IL^$Xt zhk!T;vJlpxOh3DK7Zh|TiH2Xtp{3h_zZMzH*GvxotIYt>nM_bDcX@UqXJ6Xx8bBKeJwkSTmM|Ewbmq#`WW#8bw#mH zV;ZM8SAW?^=?(Wn&Lc!>^Rjpm6AD+%y0#ZscmZf@Q@5A3CowZ2;>|s^fh#Y%bR_FH z)*aNn41}`+scYm43)oNtx$_*WQUC5}d%k8^X;KJxaCF@)0!g7CobrGi)s(j!|8!Vc z+~K7#u;^Hs>iFK;0)p?oCXwW6OY9u9qbwt`W7A1{$yU}Wk1v~r5xHuN?Rl33bZCuW z5~p;?c()q+y{E%!sw`)+v?G@dW@5XL_`GQ8?u1Su$1TtZ9hePU(mu8ilCYo&d2c<*8+90oY_6_$^hf}F&)@gjK zB&P}gB{u`!>G+KX-amJVY4&mBaXLHb_-+5&DKYrLvg&T6A^ zYoN+=<~Yy8LUw5p`N{(X=^YdfZv{90v_^X5^TBkSBAAD5WdAfJRgGnc<*lADCBl&d zXi(Ln)Y8?Rv)C>2&Ff)1&Uht~BlOgX+xe76rQT&;;L5#?yHqw6;YMy>9zPni{JdH7 zsfp?(fU_#e)f0`-k#c`lJ!xgumEvhcKzdroA)V3$pGf zr}leK(LyH~9(JQ!B>aEmg z`1yh@>m|+qoi{RJoui^|{Wt?_?MjWr;4G;ORhJCYr zsTDl^KzOdx7?#nPWs?&cuL9H3jva<{ZI3i${g0c1MMQ8-Odin!D+Cr1I~=Q%&glgA z>TXmxo>I(|A{ZVoG~RhCr*GqH#IN|#7{RVHDzMUELt1bjU_?np6cZ#|&=2}<@YE_a zq;^f5xAagFZ1NJ%g$kfT+X%UMb(>)wL-JWmIf?|^1nECPKZ`~R?~t<7bQ1Z8@k2En zZwV)qMRMAs`sANflhT)uVTE2KxESD_|Ak!0rH!mLyNGvSEw3y}MkS?%^~+Bk?% zM)UBz%Ztn=&na8nBbBYG90Szw!-!5MLpuUQFEV7>_zX$+5dG?}S{$q-J7>+9)my}_ zrwPk7PT!`i^=<~-2{mkqarnrMBzm2hJw#I|nWHEMC|aO(wcqAqYOv(L|$X zXgQ=EzP*Ys9{?o(EK~&x6gQ*61^(>|x$I5*0wGNsq8P9H7m=EYbM3d*cIWEx_A6bE4tJY&fxQj@)4SBypWL&JD4camx z^4)oprD$5KHUb$oHIC1vF1@?1-6%Y(JZM~-{rkTb zOWh^%pOD!hq8j$EN~f7;+Du9Mv6cUIJ^%BHtQLR`uMmooc-1DkK+79ZDBYDvEC8a| zXtV=Pwxr>}a6l;?!r(*_ao9@6*VFJqEl?G?JHBEP=_$=+_5%SsdjR*#uI{Ec6Qb7FhFlFX|VMP|P*!ktrM#S!L*tTdr zvSOoNWVv)4qFdl9;bSZgPcQq~&Qk++{6s6qj+Z~(o{AdgoV$17SE~nZ zWb(+eXoI{`)oGq%wEMh=o9l&|bg$h;>$NB25tE{oxQdT--fr-zm*|9C=9 zxc1X4{rraizN=UITKSuzZ#pG7B>**4X-WUxZ3RqRq2E4-GpLo#6m#96-!mv!1{ZEC z6W8?oy6@N`o%yW!3I-7wU^^#wQb|q)0MmY z+KP#2=jTmZzK^nz!y*cq2)Sd@eo=gvfgOj2Ze>1K2(-H>l;vCTkpiqb8K%1l@5v)! zOz7Ih13+A<<0wq@;w$jR(l-q_@w@P{iBRbZS_&y?>d3$EaS*+(JmW4c!!;b@o + +#include "test.h" + +int main() +{ +#ifdef __cplusplus + printf("luabins C API test compiled as C++\n"); +#else + printf("luabins C API test compiled as plain C\n"); +#endif /* __cplusplus */ + + test_savebuffer(); + test_write_api(); + test_fwrite_api(); + test_api(); + + return 0; +} diff --git a/vendor/luabins/test/test.h b/vendor/luabins/test/test.h new file mode 100644 index 000000000..3cb43e0fb --- /dev/null +++ b/vendor/luabins/test/test.h @@ -0,0 +1,25 @@ +/* +* test.h +* Luabins test basics +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_TEST_H_INCLUDED_ +#define LUABINS_TEST_H_INCLUDED_ + +#define STRINGIZE(s) #s + +#define TEST(name, body) \ + static void name() \ + { \ + printf("---> BEGIN %s\n", STRINGIZE(name)); \ + body \ + printf("---> OK\n"); \ + } + +void test_savebuffer(); +void test_write_api(); +void test_fwrite_api(); +void test_api(); + +#endif /* LUABINS_TEST_H_INCLUDED_ */ diff --git a/vendor/luabins/test/test.lua b/vendor/luabins/test/test.lua new file mode 100644 index 000000000..a5a42e976 --- /dev/null +++ b/vendor/luabins/test/test.lua @@ -0,0 +1,813 @@ +-- ---------------------------------------------------------------------------- +-- test.lua +-- Luabins test suite +-- See copyright notice in luabins.h +-- ---------------------------------------------------------------------------- + +package.cpath = "./?.so;"..package.cpath + +local randomseed = 1235134892 +--local randomseed = os.time() + +print("===== BEGIN LUABINS TEST SUITE (seed " .. randomseed .. ") =====") +math.randomseed(randomseed) + +-- ---------------------------------------------------------------------------- +-- Utility functions +-- ---------------------------------------------------------------------------- + +local invariant = function(v) + return function() + return v + end +end + +local escape_string = function(str) + return str:gsub( + "[^0-9A-Za-z_%- :]", + function(c) + return ("%%%02X"):format(c:byte()) + end + ) +end + +local ensure_equals = function(msg, actual, expected) + if actual ~= expected then + error( + msg..":\n actual: `"..escape_string(tostring(actual)) + .."`\nexpected: `"..escape_string(tostring(expected)).."'" + ) + end +end + +local ensure_equals_permute +do + -- Based on MIT-licensed + -- http://snippets.luacode.org/sputnik.lua?p=snippets/ \ + -- Iterator_over_Permutations_of_a_Table_62 + -- Which is based on PiL + local function permgen(a, n, fn) + if n == 0 then + fn(a) + else + for i = 1, n do + -- put i-th element as the last one + a[n], a[i] = a[i], a[n] + + -- generate all permutations of the other elements + permgen(a, n - 1, fn) + + -- restore i-th element + a[n], a[i] = a[i], a[n] + end + end + end + + --- an iterator over all permutations of the elements of a list. + -- Please note that the same list is returned each time, + -- so do not keep references! + -- @param a list-like table + -- @return an iterator which provides the next permutation as a list + local function permute_iter(a, n) + local n = n or #a + local co = coroutine.create(function() permgen(a, n, coroutine.yield) end) + return function() -- iterator + local code, res = coroutine.resume(co) + return res + end + end + + ensure_equals_permute = function( + msg, + actual, + expected_prefix, + expected_body, + expected_suffix, + expected_body_size + ) + expected_body_size = expected_body_size or #expected_body + + local expected + for t in permute_iter(expected_body, expected_body_size) do + expected = expected_prefix .. table.concat(t) .. expected_suffix + if actual == expected then + return actual + end + end + + error( + msg..":\nactual: `"..escape_string(tostring(actual)) + .."`\nexpected one of permutations: `" + ..escape_string(tostring(expected)).."'" + ) + end +end + +local function deepequals(lhs, rhs) + if type(lhs) ~= "table" or type(rhs) ~= "table" then + return lhs == rhs + end + + local checked_keys = {} + + for k, v in pairs(lhs) do + checked_keys[k] = true + if not deepequals(v, rhs[k]) then + return false + end + end + + for k, v in pairs(rhs) do + if not checked_keys[k] then + return false -- extra key + end + end + + return true +end + +local nargs = function(...) + return select("#", ...), ... +end + +local pack = function(...) + return select("#", ...), { ... } +end + +local eat_true = function(t, ...) + if t == nil then + error("failed: " .. (...)) + end + return ... +end + +-- ---------------------------------------------------------------------------- +-- Test helper functions +-- ---------------------------------------------------------------------------- + +local luabins_local = require 'luabins' +assert(luabins_local == luabins) + +assert(type(luabins.save) == "function") +assert(type(luabins.load) == "function") + +local check_load_fn_ok = function(eq, saved, ...) + local expected = { nargs(...) } + local loaded = { nargs(eat_true(luabins.load(saved))) } + + ensure_equals("num arguments match", loaded[1], expected[1]) + for i = 2, expected[1] do + assert(eq(loaded[i], expected[i])) + end + + return saved +end + +local check_load_ok = function(saved, ...) + return check_load_fn_ok(deepequals, saved, ...) +end + +local check_fn_ok = function(eq, ...) + local saved = assert(luabins.save(...)) + + assert(type(saved) == "string") + + print("saved length", #saved, "(display truncated to 70 chars)") + print(escape_string(saved):sub(1, 70)) + + return check_load_fn_ok(eq, saved, ...) +end + +local check_ok = function(...) + print("check_ok") + return check_fn_ok(deepequals, ...) +end + +local check_fail_save = function(msg, ...) + print("check_fail_save") + local res, err = luabins.save(...) + ensure_equals("result", res, nil) + ensure_equals("error message", err, msg) +-- print("/check_fail_save") +end + +local check_fail_load = function(msg, v) + print("check_fail_load") + local res, err = luabins.load(v) + ensure_equals("result", res, nil) + ensure_equals("error message", err, msg) +-- print("/check_fail_load") +end + +print("===== BEGIN LARGE DATA OK =====") + +-- Based on actual bug. +-- This dataset triggered Lua C data stack overflow. +-- (Note that bug is not triggered if check_ok is used) +-- Update data with +-- $ lua etc/toluabins.lua test/large_data.lua>test/large_data.luabins +-- WARNING: Keep this test above other tests, so Lua stack is small. +assert( + luabins.load( + assert(io.open("test/large_data.luabins", "r"):read("*a")) + ) + ) + +print("===== LARGE DATA OK =====") + +-- ---------------------------------------------------------------------------- +-- Basic tests +-- ---------------------------------------------------------------------------- + +print("===== BEGIN BASIC TESTS =====") + +print("---> basic corrupt data tests") + +check_fail_load("can't load: corrupt data", "") +check_fail_load("can't load: corrupt data", "bad data") + +print("---> basic extra data tests") +do + local s + + s = check_ok() + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(nil) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(true) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(false) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(42) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(math.pi) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(1/0) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok(-1/0) + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok("Luabins") + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok({ }) + + check_fail_load("can't load: extra data at end", s .. "-") + + s = check_ok({ a = 1, 2 }) + check_fail_load("can't load: extra data at end", s .. "-") +end + +print("---> basic type tests") + +-- This is the way to detect NaN +check_fn_ok(function(lhs, rhs) return lhs ~= lhs and rhs ~= rhs end, 0/0) + +check_ok("") + +check_ok("Embedded\0Zero") + +check_ok(("longstring"):rep(1024000)) + +check_fail_save("can't save: unsupported type detected", function() end) +check_fail_save( + "can't save: unsupported type detected", + coroutine.create(function() end) + ) +check_fail_save("can't save: unsupported type detected", newproxy()) + +print("---> basic table tests") + +check_ok({ 1 }) +check_ok({ a = 1 }) +check_ok({ a = 1, 2, [42] = true, [math.pi] = math.huge }) +check_ok({ { } }) +check_ok({ a = {}, b = { c = 7 } }) +check_ok({ 1, 2, 3 }) +check_ok({ [1] = 1, [1.5] = 2, [2] = 3 }) +check_ok({ 1, nil, 3 }) +check_ok({ 1, nil, 3, [{ 1, nil, 3 }] = { 1, nil, 3 } }) + +print("---> basic tuple tests") + +check_ok(nil, nil) + +do + local s = check_ok(nil, false, true, 42, "Embedded\0Zero", { { [{3}] = 54 } }) + check_fail_load("can't load: extra data at end", s .. "-") + + check_ok(check_ok(s)) -- Save data string couple of times more +end + +print("---> basic table tuple tests") + +check_ok({ a = {}, b = { c = 7 } }, nil, { { } }, 42) + +check_ok({ ["1"] = "str", [1] = "num" }) + +check_ok({ [true] = true }) +check_ok({ [true] = true, [false] = false, 1 }) + +print("---> basic fail save tests") + +check_fail_save( + "can't save: unsupported type detected", + { { function() end } } + ) + +check_fail_save( + "can't save: unsupported type detected", + nil, false, true, 42, "Embedded\0Zero", function() end, + { { [{3}] = 54 } } + ) + +print("---> recursive table test") + +local t = {}; t[1] = t +check_fail_save("can't save: nesting is too deep", t) + +print("---> metatable test") + +check_ok(setmetatable({}, {__index = function(t, k) return k end})) + +print("===== BASIC TESTS OK =====") + +print("===== BEGIN FORMAT SANITY TESTS =====") + +-- Format sanity checks for LJ2 compatibility tests. +-- These tests are intended to help debugging actual problems +-- of test suite, and are not feature complete. +-- What is not checked here, checked in the rest of suite. + +do + do + local saved = check_ok(1) + local expected = + "\001".."N" + .. "\000\000\000\000\000\000\240\063" -- Note number is a double + + ensure_equals( + "1 as number", + expected, + saved + ) + end + + do + local saved = check_ok({ [true] = 1 }) + local expected = + "\001".."T" + .. "\000\000\000\000".."\001\000\000\000" + .. "1" + .. "N\000\000\000\000\000\000\240\063" -- Note number is a double + + ensure_equals( + "1 as value", + expected, + saved + ) + end + + do + local saved = check_ok({ [1] = true }) + local expected = + "\001".."T" + .. "\001\000\000\000".."\000\000\000\000" + .. "N\000\000\000\000\000\000\240\063" -- Note number is a double + .. "1" + + ensure_equals( + "1 as key", + expected, + saved + ) + end +end + +print("===== FORMAT SANITY TESTS OK =====") + +print("===== BEGIN AUTOCOLLAPSE TESTS =====") + +-- Note: those are ad-hoc tests, tuned for old implementation +-- which generated save data on Lua stack. +-- These tests are kept here for performance comparisons. + +local LUABINS_CONCATTHRESHOLD = 1024 + +local gen_t = function(size) + -- two per numeric entry, three per string entry, + -- two entries per key-value pair + local actual_size = math.ceil(size / (2 + 3)) + print("generating table of "..actual_size.." pairs") + local t = {} + for i = 1, actual_size do + t[i] = "a"..i + end + return t +end + +-- Test table value autocollapse +check_ok(gen_t(LUABINS_CONCATTHRESHOLD - 100)) -- underflow, no autocollapse +check_ok(gen_t(LUABINS_CONCATTHRESHOLD)) -- autocollapse, no extra elements +check_ok(gen_t(LUABINS_CONCATTHRESHOLD + 100)) -- autocollapse, extra elements + +-- Test table key autocollapse +check_ok({ [gen_t(LUABINS_CONCATTHRESHOLD - 4)] = true }) + +-- Test multiarg autocollapse +check_ok( + 1, + gen_t(LUABINS_CONCATTHRESHOLD - 5), + 2, + gen_t(LUABINS_CONCATTHRESHOLD - 5), + 3 + ) + +print("===== AUTOCOLLAPSE TESTS OK =====") + +print("===== BEGIN MIN TABLE SIZE TESTS =====") + +do + -- one small key + do + local data = { [true] = true } + local saved = check_ok(data) + ensure_equals( + "format sanity check", + "\001".."T".."\000\000\000\000".."\001\000\000\000".."11", + saved + ) + check_fail_load( + "can't load: corrupt data, bad size", + saved:sub(1, #saved - 1) + ) + + -- As long as array and hash size sum is correct + -- (and both are within limits), load is successful. + -- If values are swapped, we get some performance hit. + check_load_ok( + "\001".."T".."\001\000\000\000".."\000\000\000\000".."11", + data + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T".."\001\000\000\000".."\001\000\000\000".."11" + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T".."\000\000\000\000".."\002\000\000\000".."11" + ) + + check_fail_load( + "can't load: extra data at end", + "\001".."T".."\000\000\000\000".."\000\000\000\000".."11" + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T".."\255\255\255\255".."\255\255\255\255".."11" + ) + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T".."\000\255\255\255".."\000\255\255\255".."11" + ) + check_fail_load( + "can't load: corrupt data, bad size", + "\255".."T".."\000\000\000\000".."\000\000\000\000" + ) + end + + -- two small keys + do + local data = { [true] = true, [false] = false } + local saved = check_ok({ [true] = true, [false] = false }) + ensure_equals_permute( + "format sanity check", + saved, + "\001" .. "T" .. "\000\000\000\000" .. "\002\000\000\000", + { + "0" .. "0"; + "1" .. "1"; + }, + "" + ) + check_fail_load( + "can't load: corrupt data, bad size", + saved:sub(1, #saved - 1) + ) + + -- See above about swapped array and hash sizes + check_load_ok( + "\001".."T".."\001\000\000\000".."\001\000\000\000".."1100", + data + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T".."\000\000\000\000".."\003\000\000\000".."0011" + ) + end + + -- two small and one large key + do + local saved = check_ok({ [true] = true, [false] = false, [1] = true }) + ensure_equals_permute( + "format sanity check", + saved, + "\001" .. "T" .. "\001\000\000\000" .. "\002\000\000\000", + { + "0" .. "0"; + "1" .. "1"; + -- Note number is a double + "N\000\000\000\000\000\000\240\063" .. "1"; + }, + "" + ) + + check_fail_load( + "can't load: corrupt data", + saved:sub(1, #saved - 1) + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T" + .. "\002\000\000\000".."\002\000\000\000" + .. "0011" + .. "N\000\000\000\000\000\000\240\063" + .. "1" + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T" + .. "\001\000\000\000".."\003\000\000\000" + .. "0011" + .. "N\000\000\000\000\000\000\240\063" + .. "1" + ) + end + + -- two small and two large keys + do + local saved = check_ok( + { [true] = true, [false] = false, [1] = true, [42] = true } + ) + local expected = + "\001".."T" + .. "\001\000\000\000".."\003\000\000\000" + .. "0011" + ensure_equals_permute( + "format sanity check", + saved, + "\001" .. "T" .. "\001\000\000\000" .. "\003\000\000\000", + { + "0" .. "0"; + "1" .. "1"; + "N\000\000\000\000\000\000\069\064" .. "1"; + "N\000\000\000\000\000\000\240\063" .. "1"; + }, + "" + ) + + check_fail_load( + "can't load: corrupt data", + saved:sub(1, #saved - 1) + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T" + .. "\001\000\000\000".."\005\000\000\000" + .. "0011" + .. "N\000\000\000\000\000\000\069\064" + .. "1" + .. "N\000\000\000\000\000\000\240\063" + .. "1" + ) + + check_fail_load( + "can't load: corrupt data, bad size", + "\001".."T" + .. "\003\000\000\000".."\003\000\000\000" + .. "0011" + .. "N\000\000\000\000\000\000\069\064" + .. "1" + .. "N\000\000\000\000\000\000\240\063" + .. "1" + ) + end +end + +print("===== MIN TABLE SIZE TESTS OK =====") + +print("===== BEGIN LOAD TRUNCATION TESTS =====") + +local function gen_random_dataset(num, nesting) + num = num or math.random(0, 128) + nesting = nesting or 1 + + local gen_str = function() + local t = {} + local n = math.random(0, 1024) + for i = 1, n do + t[i] = string.char(math.random(0, 255)) + end + return table.concat(t) + end + + local gen_bool = function() return math.random() >= 0.5 end + + local gen_nil = function() return nil end + + local generators = + { + gen_nil; + gen_nil; + gen_nil; + gen_bool; + gen_bool; + gen_bool; + function() return math.random() end; + function() return math.random(-10000, 10000) end; + function() return math.random() * math.random(-10000, 10000) end; + gen_str; + gen_str; + gen_str; + function() + if nesting >= 24 then + return nil + end + + local t = {} + local n = math.random(0, 24 - nesting) + for i = 1, n do + local k = gen_random_dataset(1, nesting + 1) + if k == nil then + k = "(nil)" + end + t[ k ] = gen_random_dataset( + 1, + nesting + 1 + ) + end + + return t + end; + } + + local t = {} + for i = 1, num do + local n = math.random(1, #generators) + t[i] = generators[n]() + end + return unpack(t, 0, num) +end + +local random_dataset_num, random_dataset_data = pack(gen_random_dataset()) +local random_dataset_saved = check_ok( + unpack(random_dataset_data, 0, random_dataset_num) + ) + +local num_tries = 100 +local errors = {} +for i = 1, num_tries do + local to = math.random(1, #random_dataset_saved - 1) + local new_data = random_dataset_saved:sub(1, to) + + local res, err = luabins.load(new_data) + ensure_equals("truncated data must not be loaded", res, nil) + errors[err] = (errors[err] or 0) + 1 +end + +print("truncation errors encountered:") +for err, n in pairs(errors) do + print(err, n) +end + +print("===== BASIC LOAD TRUNCATION OK =====") + +print("===== BEGIN LOAD MUTATION TESTS =====") + +local function mutate_string(str, num, override) + num = num or math.random(1, 8) + + if num < 1 then + return str + end + + local mutators = + { + -- truncate at end + function(str) + local pos = math.random(1, #str) + return str:sub(1, pos) + end; + -- truncate at beginning + function(str) + local pos = math.random(1, #str) + return str:sub(-pos) + end; + -- cut out the middle + function(str) + local from = math.random(1, #str) + local to = math.random(from, #str) + return str:sub(1, from) .. str:sub(to) + end; + -- swap two halves + function(str) + local pos = math.random(1, #str) + return str:sub(pos + 1, #str) .. str:sub(1, pos) + end; + -- swap two characters + function(str) + local pa, pb = math.random(1, #str), math.random(1, #str) + local a, b = str:sub(pa, pa), str:sub(pb, pb) + return + str:sub(1, pa - 1) .. + a .. + str:sub(pa + 1, pb - 1) .. + b .. + str:sub(pb + 1, #str) + end; + -- replace one character + function(str) + local pos = math.random(1, #str) + return + str:sub(1, pos - 1) .. + string.char(math.random(0, 255)) .. + str:sub(pos + 1, #str) + end; + -- increase one character + function(str) + local pos = math.random(1, #str) + local b = str:byte(pos, pos) + 1 + if b > 255 then + b = 0 + end + return + str:sub(1, pos - 1) .. + string.char(b) .. + str:sub(pos + 1, #str) + end; + -- decrease one character + function(str) + local pos = math.random(1, #str) + local b = str:byte(pos, pos) - 1 + if b < 0 then + b = 255 + end + return + str:sub(1, pos - 1) .. + string.char(b) .. + str:sub(pos + 1, #str) + end; + } + + local n = override or math.random(1, #mutators) + + str = mutators[n](str) + + return mutate_string(str, num - 1, override) +end + +local num_tries = 100000 +local num_successes = 0 +local errors = {} +for i = 1, num_tries do + local new_data = mutate_string(random_dataset_saved) + + local res, err = luabins.load(new_data) + if res == nil then + errors[err] = (errors[err] or 0) + 1 + else + num_successes = num_successes + 1 + end +end + +if num_successes == 0 then + print("no mutated strings loaded successfully") +else + -- This is ok, since we may corrupt data, not format. + -- If it is an issue for user, he must append checksum to data, + -- as usual. + print("mutated strings loaded successfully: "..num_successes) +end + +print("mutation errors encountered:") +for err, n in pairs(errors) do + print(err, n) +end + +print("===== BASIC LOAD MUTATION OK =====") + +print("OK") diff --git a/vendor/luabins/test/test_api.c b/vendor/luabins/test/test_api.c new file mode 100644 index 000000000..75a1bda45 --- /dev/null +++ b/vendor/luabins/test/test_api.c @@ -0,0 +1,311 @@ +/* +* test_api.c +* Luabins API tests +* See copyright notice in luabins.h +*/ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include +#include + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#include "luabins.h" + +#define STACKGUARD "-- stack ends here --" + +/* Note this one does not dump values to protect from embedded zeroes. */ +static int dump_lua_stack(lua_State * L, int base) +{ + int top = lua_gettop(L); + + if (top == 0) + { + lua_pushliteral(L, "-- stack is empty --"); + } + else + { + int pos = 0; + luaL_Buffer b; + + luaL_buffinit(L, &b); + + for (pos = top; pos > 0; --pos) + { + luaL_addstring(&b, (pos != base) ? "[" : "{"); + lua_pushinteger(L, pos); + luaL_addvalue(&b); + luaL_addstring(&b, (pos != base) ? "] - " : "} -"); + luaL_addstring(&b, luaL_typename(L, pos)); + luaL_addstring(&b, "\n"); + } + + luaL_pushresult(&b); + } + + if (lua_gettop(L) != top + 1) + { + return luaL_error(L, "dumpstack not balanced %d %d", top, lua_gettop(L)); + } + + return 1; +} + +static void fatal(lua_State * L, const char * msg) +{ + dump_lua_stack(L, 0); + fprintf(stderr, "%s\nSTACK\n%s", msg, lua_tostring(L, -1)); + lua_pop(L, 1); + fflush(stderr); + exit(1); +} + +static void check(lua_State * L, int base, int extra) +{ + int top = lua_gettop(L); + if (top != base + extra) + { + fatal(L, "stack unbalanced"); + } + + lua_pushliteral(L, STACKGUARD); + if (lua_rawequal(L, -1, base) == 0) + { + fatal(L, "stack guard corrupted"); + } + lua_pop(L, 1); +} + +static void checkerr(lua_State * L, int base, const char * err) +{ + int top = lua_gettop(L); + if (top != base + 1) + { + fatal(L, "stack unbalanced on error"); + } + + lua_pushliteral(L, STACKGUARD); + if (lua_rawequal(L, -1, base) == 0) + { + fatal(L, "stack guard corrupted"); + } + lua_pop(L, 1); + + lua_pushstring(L, err); + if (lua_rawequal(L, -1, -2) == 0) + { + fprintf(stderr, "actual: '%s'\n", lua_tostring(L, -2)); + fprintf(stderr, "expected: '%s'\n", err); + fatal(L, "error message mismatch"); + } + lua_pop(L, 2); /* Pops error message as well */ +} + +static int push_testdataset(lua_State * L) +{ + int base = lua_gettop(L); + + lua_pushnil(L); + lua_pushboolean(L, 0); + lua_pushboolean(L, 1); + lua_pushinteger(L, 42); + lua_pushliteral(L, "luabins"); + + lua_newtable(L); + + if (lua_gettop(L) - base != 6) + { + fatal(L, "push_dataset broken"); + } + + return 6; +} + +static void check_testdataset_on_top(lua_State * L) +{ + int base = lua_gettop(L); + + /* TODO: Check table contents */ + if (!lua_istable(L, -1)) + { + fatal(L, "dataset (-1) is not table"); + } + + lua_pushliteral(L, "luabins"); + if (!lua_rawequal(L, -1, -2 - 1)) + { + fatal(L, "dataset (-2) value mismatch"); + } + lua_pop(L, 1); + + lua_pushinteger(L, 42); + if (!lua_rawequal(L, -1, -3 - 1)) + { + fatal(L, "dataset (-3) value mismatch"); + } + lua_pop(L, 1); + + lua_pushboolean(L, 1); + if (!lua_rawequal(L, -1, -4 - 1)) + { + fatal(L, "dataset (-4) value mismatch"); + } + lua_pop(L, 1); + + lua_pushboolean(L, 0); + if (!lua_rawequal(L, -1, -5 - 1)) + { + fatal(L, "dataset (-5) value mismatch"); + } + lua_pop(L, 1); + + lua_pushnil(L); + if (!lua_rawequal(L, -1, -6 - 1)) + { + fatal(L, "dataset (-6) value mismatch"); + } + lua_pop(L, 1); + + if (lua_gettop(L) != base) + { + fatal(L, "check_dataset_on_top broken"); + } +} + +void test_api() +{ + int base = 0; + int count = 0; + const unsigned char * str; + size_t length = 0; + + lua_State * L = lua_open(); + luaL_openlibs(L); + + printf("---> BEGIN test_api\n"); + + /* Push stack check value */ + lua_pushliteral(L, STACKGUARD); + base = lua_gettop(L); + + /* Sanity check */ + check(L, base, 0); + + /* Save error: inexistant index */ + if (luabins_save(L, lua_gettop(L) + 1, lua_gettop(L) + 1) == 0) + { + fatal(L, "save should fail"); + } + + checkerr(L, base, "can't save: inexistant indices"); + + if (luabins_save(L, -1, -1) == 0) + { + fatal(L, "save should fail"); + } + + checkerr(L, base, "can't save: inexistant indices"); + + /* Assuming other save errors to be tested in test.lua */ + + /* Trigger load error */ + + if (luabins_load(L, (const unsigned char *)"", 0, &count) == 0) + { + fatal(L, "load should fail"); + } + + checkerr(L, base, "can't load: corrupt data"); + + /* Assuming other load errors to be tested in test.lua */ + + /* Do empty save */ + if (luabins_save(L, base, base - 1) != 0) + { + fatal(L, "empty save failed"); + } + check(L, base, 1); + + str = (const unsigned char *)lua_tolstring(L, -1, &length); + if (str == NULL || length == 0) + { + fatal(L, "bad empty save string"); + } + + /* Load empty save */ + + if (luabins_load(L, str, length, &count) != 0) + { + fatal(L, "empty load failed"); + } + + if (count != 0) + { + fatal(L, "bad empty load count"); + } + + /* Pop saved data string */ + check(L, base, 1); + lua_pop(L, 1); + check(L, base, 0); + + { + /* Save test dataset */ + + int num_items = push_testdataset(L); + check(L, base, num_items); + + if (luabins_save(L, base + 1, base + num_items) != 0) + { + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + fatal(L, "test dataset save failed"); + } + + check(L, base, num_items + 1); + + /* Load test dataset */ + + str = (const unsigned char *)lua_tolstring(L, -1, &length); + if (str == NULL || length == 0) + { + fatal(L, "bad empty save string"); + } + + if (luabins_load(L, str, length, &count) != 0) + { + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + fatal(L, "test dataset load failed"); + } + + if (count != num_items) + { + fatal(L, "wrong test dataset load count"); + } + + check(L, base, num_items + 1 + num_items); + + check_testdataset_on_top(L); /* Check loaded data */ + + lua_pop(L, 1 + num_items); + + check_testdataset_on_top(L); /* Check original data intact */ + + lua_pop(L, num_items); + + check(L, base, 0); + + /* Assuming further tests are done in test.lua */ + } + + lua_close(L); + + printf("---> OK\n"); +} diff --git a/vendor/luabins/test/test_fwrite_api.c b/vendor/luabins/test/test_fwrite_api.c new file mode 100644 index 000000000..68123ef82 --- /dev/null +++ b/vendor/luabins/test/test_fwrite_api.c @@ -0,0 +1,112 @@ +/* +* test_fwrite_api.c +* Luabins Lua-less fwrite API tests +* See copyright notice in luabins.h +*/ + +/* +* WARNING: This suite is format-specific. Change it when format changes. +*/ + +#include +#include +#include + +#include "lualess.h" +#include "fwrite.h" + +#include "test.h" +#include "util.h" + +/******************************************************************************/ + +/* +* Note it is different from test_savebuffer variant. +* We're interested in higher level stuff here. +*/ +static void check_buffer( + FILE * f, + const char * expected_buf_c, + size_t expected_length + ) +{ + const unsigned char * expected_buf = (unsigned char *)expected_buf_c; + unsigned char * actual_buf = NULL; + size_t actual_length = ftell(f); + size_t actually_read = 0; + + fseek(f, 0, SEEK_SET); + + actual_buf = (unsigned char *)malloc(actual_length); + actually_read = fread(actual_buf, actual_length, 1, f); + if (actually_read != 1ul) + { + fprintf( + stderr, + "fread count error: got %lu, expected %lu\n", + actually_read, 1ul + ); + + free(actual_buf); + fclose(f); + exit(1); + } + + fseek(f, actual_length, SEEK_SET); + + if (actual_length != expected_length) + { + fprintf( + stderr, + "length mismatch: got %lu, expected %lu\n", + actual_length, expected_length + ); + fprintf(stderr, "actual:\n"); + fprintbuf(stderr, actual_buf, actual_length); + fprintf(stderr, "expected:\n"); + fprintbuf(stderr, expected_buf, expected_length); + + free(actual_buf); + fclose(f); + exit(1); + } + + if (memcmp(actual_buf, expected_buf, expected_length) != 0) + { + fprintf(stderr, "buffer mismatch\n"); + fprintf(stderr, "actual:\n"); + fprintbuf(stderr, actual_buf, actual_length); + fprintf(stderr, "expected:\n"); + fprintbuf(stderr, expected_buf, expected_length); + + free(actual_buf); + fclose(f); + exit(1); + } + + free(actual_buf); +} + +/******************************************************************************/ + +#define CAT(a, b) a ## b + +#define TEST_NAME(x) CAT(test_fwrite, x) +#define CALL_NAME(x) CAT(lbs_fwrite, x) +#define BUFFER_NAME (f) +#define INIT_BUFFER \ + FILE * f = tmpfile(); + +#define DESTROY_BUFFER \ + fclose(f); + +#define CHECK_BUFFER check_buffer + +#include "write_tests.inc" + +/******************************************************************************/ + +void test_fwrite_api() +{ + RUN_GENERATED_TESTS; +} diff --git a/vendor/luabins/test/test_savebuffer.c b/vendor/luabins/test/test_savebuffer.c new file mode 100644 index 000000000..877ee5c4c --- /dev/null +++ b/vendor/luabins/test/test_savebuffer.c @@ -0,0 +1,499 @@ +/* +* test_savebuffer.c +* Luabins SaveBuffer tests +* See copyright notice in luabins.h +*/ + +/* +* TODO: Tests are tuned for old fixed-increment memory allocation strategy. +* Test for exponential growth corner-cases specifically. +*/ + +#include +#include +#include + +#include "lualess.h" +#include "savebuffer.h" + +#include "test.h" + +/******************************************************************************/ + +static size_t NOT_CHANGED = (size_t)-1; +static void * NOT_CHANGED_PTR = NULL; + +static size_t DUMMY = (size_t)-42; +static void * DUMMY_PTR = NULL; + +static void * g_last_ud = NULL; +static size_t g_last_osize = 0; + +static void reset_alloc_globals() +{ + g_last_ud = NOT_CHANGED_PTR; + g_last_osize = NOT_CHANGED; +} + +static void init_globals() +{ + NOT_CHANGED_PTR = (void *)&NOT_CHANGED; + DUMMY_PTR = (void *)&DUMMY; + + reset_alloc_globals(); +} + +static void * dummy_alloc( + void * ud, + void * ptr, + size_t osize, + size_t nsize + ) +{ + g_last_ud = ud; + g_last_osize = osize; + + if (nsize == 0) + { + free(ptr); + return NULL; + } + else + { + return realloc(ptr, nsize); + } +} + +/******************************************************************************/ + +static void check_alloc(void * expected_ud, size_t expected_osize) +{ + if (g_last_ud != expected_ud) + { + fprintf( + stderr, + "userdata mismatch in allocator: got %p, expected %p\n", + g_last_ud, expected_ud + ); + exit(1); + } + + if (g_last_osize != expected_osize) + { + fprintf( + stderr, + "old size mismatch in allocator: got %lu, expected %lu\n", + g_last_osize, expected_osize + ); + exit(1); + } + + reset_alloc_globals(); +} + +static void check_buffer( + luabins_SaveBuffer * sb, + const char * expected_buf_c, + size_t expected_length, + void * expected_ud, + size_t expected_osize + ) +{ + const unsigned char * expected_buf = (const unsigned char *)expected_buf_c; + + { + size_t actual_length = lbsSB_length(sb); + if (actual_length != expected_length) + { + fprintf( + stderr, + "lbsSB_length mismatch in allocator: got %lu, expected %lu\n", + actual_length, expected_length + ); + exit(1); + } + } + + { + size_t actual_length = (size_t)-1; + const unsigned char * actual_buf = lbsSB_buffer(sb, &actual_length); + if (actual_length != expected_length) + { + fprintf( + stderr, + "lsbSB_buffer length mismatch in allocator: got %lu, expected %lu\n", + actual_length, expected_length + ); + exit(1); + } + + if (memcmp(actual_buf, expected_buf, expected_length) != 0) + { + fprintf( + stderr, + "lsbSB_buffer buf mismatch in allocator\n" + ); + exit(1); + } + } + + check_alloc(expected_ud, expected_osize); +} + +/******************************************************************************/ + +TEST (test_init_destroy, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + check_buffer(&sb, "", 0, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(NOT_CHANGED_PTR, NOT_CHANGED); +}) + +TEST (test_grow_zero, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_grow(&sb, 0); + check_buffer(&sb, "", 0, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(NOT_CHANGED_PTR, NOT_CHANGED); +}) + +TEST (test_grow_bufsiz, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_grow(&sb, 1024); + check_buffer(&sb, "", 0, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 1344); +}) + +TEST (test_grow_one, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_grow(&sb, 1); + check_buffer(&sb, "", 0, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_grow_one_grow_one_noop, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_grow(&sb, 1); + check_buffer(&sb, "", 0, DUMMY_PTR, 0); + + lbsSB_grow(&sb, 1); + check_buffer(&sb, "", 0, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_grow_one_grow_bufsiz_noop, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_grow(&sb, 1); + check_buffer(&sb, "", 0, DUMMY_PTR, 0); + + lbsSB_grow(&sb, 255); + check_buffer(&sb, "", 0, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_grow_one_grow_bufsiz_one, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_grow(&sb, 1); + check_buffer(&sb, "", 0, DUMMY_PTR, 0); + + lbsSB_grow(&sb, 257); + check_buffer(&sb, "", 0, DUMMY_PTR, 256); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 512); +}) + +/******************************************************************************/ + +TEST (test_write_empty, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"", 0); + check_buffer(&sb, "", 0, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(NOT_CHANGED_PTR, NOT_CHANGED); +}) + +TEST (test_write, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"42", 3); + check_buffer(&sb, "42", 3, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_write_embedded_zero, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"4\02", 4); + check_buffer(&sb, "4\02", 4, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_write_write_smallsiz, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"01234567", 8); + check_buffer(&sb, "01234567", 8, DUMMY_PTR, 0); + + lbsSB_write(&sb, (unsigned char*)"01234567", 8); + check_buffer(&sb, "0123456701234567", 8 + 8, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_write(&sb, (unsigned char*)"0123", 4); + check_buffer( + &sb, + "01234567012345670123", + 8 + 8 + 4, + NOT_CHANGED_PTR, + NOT_CHANGED + ); + + lbsSB_write(&sb, (unsigned char*)"0123456789ABCDEF", 16); + check_buffer( + &sb, + "012345670123456701230123456789ABCDEF", + 8 + 8 + 4 + 16, + NOT_CHANGED_PTR, + NOT_CHANGED + ); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +/******************************************************************************/ + +TEST (test_writechar, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_writechar(&sb, 'A'); + check_buffer(&sb, "A", 1, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_writechar_zero, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_writechar(&sb, '\0'); + check_buffer(&sb, "\0", 1, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_write_writechar_smallsiz, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"01234567", 8); + check_buffer(&sb, "01234567", 8, DUMMY_PTR, 0); + + lbsSB_writechar(&sb, 'A'); + check_buffer(&sb, "01234567A", 8 + 1, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +/******************************************************************************/ + +TEST (test_overwrite_empty, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_overwrite(&sb, 0, (unsigned char*)"42", 3); + check_buffer(&sb, "42", 3, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_overwrite_inplace, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"ABCD", 4); + check_buffer(&sb, "ABCD", 4, DUMMY_PTR, 0); + + lbsSB_overwrite(&sb, 1, (unsigned char*)"42", 2); + check_buffer(&sb, "A42D", 4, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_overwrite_overflow, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"ABCD", 4); + check_buffer(&sb, "ABCD", 4, DUMMY_PTR, 0); + + lbsSB_overwrite(&sb, 3, (unsigned char*)"42", 2); + check_buffer(&sb, "ABC42", 5, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_overwrite_overflow_grows, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"012345", 6); + check_buffer(&sb, "012345", 6, DUMMY_PTR, 0); + + lbsSB_overwrite(&sb, 4, (unsigned char*)"ABCDEF", 6); + check_buffer(&sb, "0123ABCDEF", 10, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_overwrite_large_offset_appends, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"012345", 6); + check_buffer(&sb, "012345", 6, DUMMY_PTR, 0); + + lbsSB_overwrite(&sb, 100, (unsigned char*)"ABCDEF", 6); + check_buffer(&sb, "012345ABCDEF", 12, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +/******************************************************************************/ + +TEST (test_overwritechar_empty_buffer, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_overwritechar(&sb, 0, 'A'); + check_buffer(&sb, "A", 1, DUMMY_PTR, 0); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_overwritechar_inplace, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"ABCD", 4); + check_buffer(&sb, "ABCD", 4, DUMMY_PTR, 0); + + lbsSB_overwritechar(&sb, 1, '!'); + check_buffer(&sb, "A!CD", 4, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +TEST (test_overwritechar_large_offset_appends, +{ + luabins_SaveBuffer sb; + lbsSB_init(&sb, dummy_alloc, DUMMY_PTR); + + lbsSB_write(&sb, (unsigned char*)"01234567", 8); + check_buffer(&sb, "01234567", 8, DUMMY_PTR, 0); + + lbsSB_overwritechar(&sb, 100, '!'); + check_buffer(&sb, "01234567!", 9, NOT_CHANGED_PTR, NOT_CHANGED); + + lbsSB_destroy(&sb); + check_alloc(DUMMY_PTR, 256); +}) + +/******************************************************************************/ + +void test_savebuffer() +{ + init_globals(); + + test_init_destroy(); + test_grow_zero(); + test_grow_bufsiz(); + test_grow_one(); + test_grow_one_grow_one_noop(); + test_grow_one_grow_bufsiz_noop(); + test_grow_one_grow_bufsiz_one(); + + test_write_empty(); + test_write(); + test_write_embedded_zero(); + test_write_write_smallsiz(); + + test_writechar(); + test_writechar_zero(); + test_write_writechar_smallsiz(); + + test_overwrite_empty(); + test_overwrite_inplace(); + test_overwrite_overflow(); + test_overwrite_overflow_grows(); + test_overwrite_large_offset_appends(); + + test_overwritechar_empty_buffer(); + test_overwritechar_inplace(); + test_overwritechar_large_offset_appends(); +} diff --git a/vendor/luabins/test/test_write_api.c b/vendor/luabins/test/test_write_api.c new file mode 100644 index 000000000..18bef2381 --- /dev/null +++ b/vendor/luabins/test/test_write_api.c @@ -0,0 +1,130 @@ +/* +* test_write_api.c +* Luabins Lua-less write API tests +* See copyright notice in luabins.h +*/ + +/* +* WARNING: This suite is format-specific. Change it when format changes. +*/ + +#include +#include +#include + +/* Should be included first */ +#include "lualess.h" +#include "write.h" + +#include "test.h" +#include "util.h" + +/******************************************************************************/ + +/* +* Note it is different from test_savebuffer variant. +* We're interested in higher level stuff here. +*/ +static void check_buffer( + luabins_SaveBuffer * sb, + const char * expected_buf_c, + size_t expected_length + ) +{ + const unsigned char * expected_buf = (const unsigned char *)expected_buf_c; + + size_t actual_length = (size_t)-1; + const unsigned char * actual_buf = lbsSB_buffer(sb, &actual_length); + if (actual_length != expected_length) + { + fprintf( + stderr, + "lsbSB_buffer length mismatch: got %lu, expected %lu\n", + actual_length, expected_length + ); + fprintf(stderr, "actual:\n"); + fprintbuf(stderr, actual_buf, actual_length); + fprintf(stderr, "expected:\n"); + fprintbuf(stderr, expected_buf, expected_length); + exit(1); + } + + if (memcmp(actual_buf, expected_buf, expected_length) != 0) + { + fprintf(stderr, "lsbSB_buffer buffer mismatch\n"); + fprintf(stderr, "actual:\n"); + fprintbuf(stderr, actual_buf, actual_length); + fprintf(stderr, "expected:\n"); + fprintbuf(stderr, expected_buf, expected_length); + + exit(1); + } +} + +/******************************************************************************/ + +#define CAT(a, b) a ## b + +#define TEST_NAME(x) CAT(test_write, x) +#define CALL_NAME(x) CAT(lbs_write, x) +#define BUFFER_NAME (&sb) +#define INIT_BUFFER \ + luabins_SaveBuffer sb; \ + lbsSB_init(BUFFER_NAME, lbs_simplealloc, NULL); + +#define DESTROY_BUFFER \ + lbsSB_destroy(BUFFER_NAME); + +#define CHECK_BUFFER check_buffer + +#include "write_tests.inc" + +/******************************************************************************/ + +TEST (test_writeTableHeaderAt, +{ + INIT_BUFFER; + + { + unsigned char tuple_size = 0x01; + int array_size = 0x00; + int hash_size = 0x00; + int table_header_pos = 0; + + lbs_writeTupleSize(BUFFER_NAME, tuple_size); + table_header_pos = lbsSB_length(BUFFER_NAME); + lbs_writeTableHeader(BUFFER_NAME, array_size, hash_size); + + CHECK_BUFFER( + &sb, + "\x01" "T" "\x00\x00\x00\x00" "\x00\x00\x00\x00", + 1 + 1 + 4 + 4 + ); + + array_size = 0xAB; + hash_size = 0xCD; + + lbs_writeTableHeaderAt( + BUFFER_NAME, + table_header_pos, + array_size, + hash_size + ); + CHECK_BUFFER( + BUFFER_NAME, + "\x01" "T" "\xAB\x00\x00\x00" "\xCD\x00\x00\x00", + 1 + 1 + 4 + 4 + ); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +void test_write_api() +{ + RUN_GENERATED_TESTS; + + test_writeTableHeaderAt(); +} diff --git a/vendor/luabins/test/util.c b/vendor/luabins/test/util.c new file mode 100644 index 000000000..84b4ac6b7 --- /dev/null +++ b/vendor/luabins/test/util.c @@ -0,0 +1,17 @@ +/* +* util.c +* Luabins test utilities +* See copyright notice in luabins.h +*/ + +#include "util.h" + +void fprintbuf(FILE * out, const unsigned char * b, size_t len) +{ + size_t i = 0; + for (i = 0; i < len; ++i) + { + fprintf(out, "%02X ", b[i]); + } + fprintf(out, "\n"); +} diff --git a/vendor/luabins/test/util.h b/vendor/luabins/test/util.h new file mode 100644 index 000000000..b5e7121ab --- /dev/null +++ b/vendor/luabins/test/util.h @@ -0,0 +1,14 @@ +/* +* util.h +* Luabins test utilities +* See copyright notice in luabins.h +*/ + +#ifndef LUABINS_TEST_UTIL_H_INCLUDED_ +#define LUABINS_TEST_UTIL_H_INCLUDED_ + +#include + +void fprintbuf(FILE * out, const unsigned char * b, size_t len); + +#endif /* LUABINS_TEST_UTIL_H_INCLUDED_ */ diff --git a/vendor/luabins/test/write_tests.inc b/vendor/luabins/test/write_tests.inc new file mode 100644 index 000000000..f3c215675 --- /dev/null +++ b/vendor/luabins/test/write_tests.inc @@ -0,0 +1,175 @@ +/* +* write_tests.inc +* Luabins Lua-less write API +* See copyright notice in luabins.h +*/ + +/* Note this file intentionally does not have include guards */ + +/* +* Depends on following symbols: +* -- TEST_NAME +* -- CALL_NAME +* -- BUFFER_NAME +* -- INIT_BUFFER +* -- DESTROY_BUFFER +* -- CHECK_BUFFER +* +* Defines symbols +* -- RUN_GENERATED_TESTS +*/ + +TEST (TEST_NAME(TupleSize), +{ + INIT_BUFFER; + + { + unsigned char tuple_size = 0xAB; + + CALL_NAME(TupleSize)(BUFFER_NAME, tuple_size); + CHECK_BUFFER(BUFFER_NAME, "\xAB", 1); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +TEST (TEST_NAME(TableHeader), +{ + INIT_BUFFER; + + { + int array_size = 0xAB; + int hash_size = 0xCD; + + CALL_NAME(TableHeader)(BUFFER_NAME, array_size, hash_size); + CHECK_BUFFER( + BUFFER_NAME, + "T" "\xAB\x00\x00\x00" "\xCD\x00\x00\x00", + 1 + 4 + 4 + ); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +TEST (TEST_NAME(Nil), +{ + INIT_BUFFER; + + { + CALL_NAME(Nil)(BUFFER_NAME); + CHECK_BUFFER(BUFFER_NAME, "-", 1); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +TEST (TEST_NAME(Boolean), +{ + INIT_BUFFER; + + { + CALL_NAME(Boolean)(BUFFER_NAME, 1); + CHECK_BUFFER(BUFFER_NAME, "1", 1); + + CALL_NAME(Boolean)(BUFFER_NAME, 0); + CHECK_BUFFER(BUFFER_NAME, "10", 1 + 1); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +TEST (TEST_NAME(Number), +{ + INIT_BUFFER; + + { + /* Note number is a double */ + CALL_NAME(Number)(BUFFER_NAME, 1.0); + CHECK_BUFFER(BUFFER_NAME, "N" "\x00\x00\x00\x00\x00\x00\xF0\x3F", 1 + 8); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +TEST (TEST_NAME(Integer), +{ + INIT_BUFFER; + + { + /* Note integer is alsow written as a double */ + CALL_NAME(Integer)(BUFFER_NAME, 1); + CHECK_BUFFER(BUFFER_NAME, "N" "\x00\x00\x00\x00\x00\x00\xF0\x3F", 1 + 8); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +TEST (TEST_NAME(StringEmpty), +{ + INIT_BUFFER; + + { + CALL_NAME(String)(BUFFER_NAME, "", 0); + CHECK_BUFFER(BUFFER_NAME, "S" "\x00\x00\x00\x00", 1 + 4); + } + + DESTROY_BUFFER; +}) + +TEST (TEST_NAME(StringSimple), +{ + INIT_BUFFER; + + { + CALL_NAME(String)(BUFFER_NAME, "Luabins", 7); + CHECK_BUFFER( + BUFFER_NAME, + "S" "\x07\x00\x00\x00" "Luabins", + 1 + 4 + 7 + ); + } + + DESTROY_BUFFER; +}) + +TEST (TEST_NAME(StringEmbeddedZero), +{ + INIT_BUFFER; + + { + CALL_NAME(String)(BUFFER_NAME, "Embedded\0Zero", 13); + CHECK_BUFFER( + BUFFER_NAME, + "S" "\x0D\x00\x00\x00" "Embedded\0Zero", + 1 + 4 + 13 + ); + } + + DESTROY_BUFFER; +}) + +/******************************************************************************/ + +#define RUN_GENERATED_TESTS \ + TEST_NAME(TupleSize)(); \ + TEST_NAME(TableHeader)(); \ + TEST_NAME(Nil)(); \ + TEST_NAME(Boolean)(); \ + TEST_NAME(Number)(); \ + TEST_NAME(Integer)(); \ + TEST_NAME(StringEmpty)(); \ + TEST_NAME(StringSimple)(); \ + TEST_NAME(StringEmbeddedZero)(); diff --git a/vendor/luabins/tmp/.keepme b/vendor/luabins/tmp/.keepme new file mode 100644 index 000000000..e69de29bb From 057a223b389efa869a3fd76ee7a7c678bd805727 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 24 Apr 2014 22:16:30 +0200 Subject: [PATCH 06/13] Integrate luabins into Aegisub's build system Make it build as C++ so it links properly against the C++-built version of Lua used in Aegisub too. --- Makefile | 1 + vendor/luabins/Makefile | 509 ++---------------- vendor/luabins/etc/Makefile.luabins.template | 242 --------- vendor/luabins/etc/genmakefile.sh | 2 - vendor/luabins/src/{fwrite.c => fwrite.cpp} | 0 vendor/luabins/src/{load.c => load.cpp} | 0 vendor/luabins/src/{luabins.c => luabins.cpp} | 0 .../src/{luainternals.c => luainternals.cpp} | 0 vendor/luabins/src/{save.c => save.cpp} | 0 .../src/{savebuffer.c => savebuffer.cpp} | 0 vendor/luabins/src/{write.c => write.cpp} | 0 11 files changed, 41 insertions(+), 713 deletions(-) delete mode 100644 vendor/luabins/etc/Makefile.luabins.template delete mode 100755 vendor/luabins/etc/genmakefile.sh rename vendor/luabins/src/{fwrite.c => fwrite.cpp} (100%) rename vendor/luabins/src/{load.c => load.cpp} (100%) rename vendor/luabins/src/{luabins.c => luabins.cpp} (100%) rename vendor/luabins/src/{luainternals.c => luainternals.cpp} (100%) rename vendor/luabins/src/{save.c => save.cpp} (100%) rename vendor/luabins/src/{savebuffer.c => savebuffer.cpp} (100%) rename vendor/luabins/src/{write.c => write.cpp} (100%) diff --git a/Makefile b/Makefile index 828f49666..e4fa04a6b 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ include Makefile.inc SUBDIRS += \ vendor/lua \ vendor/universalchardet \ + vendor/luabins \ libaegisub \ tools \ src \ diff --git a/vendor/luabins/Makefile b/vendor/luabins/Makefile index 386738da1..6713d3759 100644 --- a/vendor/luabins/Makefile +++ b/vendor/luabins/Makefile @@ -1,469 +1,40 @@ -## CONFIGURATION ############################################################## - -ifeq ($(shell uname),Darwin) - LUA_DIR := /usr/local - LUA_LIBDIR := $(LUA_DIR)/lib/lua/5.1 - LUA_INCDIR := $(LUA_DIR)/include - LUALIB := lua -else - # Assuming Ubuntu - LUA_LIBDIR := /usr/lib - LUA_INCDIR := /usr/include/lua5.1 - LUALIB := lua5.1 -endif - -PROJECTNAME := luabins - -SONAME := $(PROJECTNAME).so -ANAME := lib$(PROJECTNAME).a -HNAME := $(PROJECTNAME).h -TESTNAME := $(PROJECTNAME)-test -TESTLUA := test.lua - -LUA := lua -CP := cp -RM := rm -f -RMDIR := rm -df -MKDIR := mkdir -p -CC := gcc -LD := gcc -AR := ar rcu -RANLIB := ranlib -ECHO := @echo -TOUCH := touch - -# Needed for tests only -CXX := g++ -LDXX := g++ - -OBJDIR := ./obj -TMPDIR := ./tmp -INCDIR := ./include -LIBDIR := ./lib - -HFILE := $(INCDIR)/$(HNAME) - -CFLAGS += -O2 -Wall -I$(LUA_INCDIR) -LDFLAGS += -L$(LUA_LIBDIR) - -# Tested on OS X and Ubuntu -SOFLAGS := -ifeq ($(shell uname),Darwin) - SOFLAGS += -dynamiclib -undefined dynamic_lookup -else - CFLAGS += -fPIC - SOFLAGS += -shared - LDFLAGS += -ldl - RMDIR := rm -rf -endif - -CFLAGS += $(MYCFLAGS) -LDFLAGS += $(MYLDFLAGS) - -## MAIN TARGETS ############################################################### - -all: $(LIBDIR)/$(SONAME) $(LIBDIR)/$(ANAME) $(HFILE) - -clean: cleanlibs cleantest - $(RM) $(HFILE) - -install: $(LIBDIR)/$(SONAME) - # Note header and static library are not copied anywhere - $(CP) $(LIBDIR)/$(SONAME) $(LUA_LIBDIR)/$(SONAME) - -$(HFILE): - $(CP) src/$(HNAME) $(HFILE) - -## GENERATED RELEASE TARGETS ################################################## - -cleanlibs: cleanobjects - $(RM) $(LIBDIR)/$(SONAME) - $(RM) $(LIBDIR)/$(ANAME) - -$(LIBDIR)/$(SONAME): $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o - $(MKDIR) $(LIBDIR) - $(LD) -o $@ $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o $(LDFLAGS) $(SOFLAGS) - -$(LIBDIR)/$(ANAME): $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o - $(MKDIR) $(LIBDIR) - $(AR) $@ $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o - $(RANLIB) $@ - -# objects: - -cleanobjects: - $(RM) $(OBJDIR)/fwrite.o $(OBJDIR)/load.o $(OBJDIR)/luabins.o $(OBJDIR)/luainternals.o $(OBJDIR)/lualess.o $(OBJDIR)/save.o $(OBJDIR)/savebuffer.o $(OBJDIR)/write.o - -$(OBJDIR)/fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ - src/saveload.h - $(CC) $(CFLAGS) -o $@ -c src/fwrite.c - -$(OBJDIR)/load.o: src/load.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/luainternals.h - $(CC) $(CFLAGS) -o $@ -c src/load.c - -$(OBJDIR)/luabins.o: src/luabins.c src/luaheaders.h src/luabins.h - $(CC) $(CFLAGS) -o $@ -c src/luabins.c - -$(OBJDIR)/luainternals.o: src/luainternals.c src/luainternals.h - $(CC) $(CFLAGS) -o $@ -c src/luainternals.c - -$(OBJDIR)/lualess.o: src/lualess.c - $(CC) $(CFLAGS) -o $@ -c src/lualess.c - -$(OBJDIR)/save.o: src/save.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/savebuffer.h src/write.h - $(CC) $(CFLAGS) -o $@ -c src/save.c - -$(OBJDIR)/savebuffer.o: src/savebuffer.c src/luaheaders.h \ - src/saveload.h src/savebuffer.h - $(CC) $(CFLAGS) -o $@ -c src/savebuffer.c - -$(OBJDIR)/write.o: src/write.c src/luaheaders.h src/write.h \ - src/saveload.h src/savebuffer.h - $(CC) $(CFLAGS) -o $@ -c src/write.c - -## TEST TARGETS ############################################################### - -test: testc89 testc99 testc++98 - $(ECHO) "===== TESTS PASSED =====" - -resettest: resettestc89 resettestc99 resettestc++98 - -cleantest: cleantestc89 cleantestc99 cleantestc++98 - -## GENERATED TEST TARGETS ##################################################### - -## ----- Begin c89 ----- - -testc89: lua-testsc89 c-testsc89 - -lua-testsc89: $(TMPDIR)/c89/.luatestspassed - -c-testsc89: $(TMPDIR)/c89/.ctestspassed - -$(TMPDIR)/c89/.luatestspassed: $(TMPDIR)/c89/$(SONAME) test/$(TESTLUA) - $(ECHO) "===== Running Lua tests for c89 =====" - @$(LUA) \ - -e "package.cpath='$(TMPDIR)/c89/$(SONAME);'..package.cpath" \ - test/$(TESTLUA) - $(TOUCH) $(TMPDIR)/c89/.luatestspassed - $(ECHO) "===== Lua tests for c89 PASSED =====" - -$(TMPDIR)/c89/.ctestspassed: $(TMPDIR)/c89/$(TESTNAME) test/$(TESTLUA) - $(ECHO) "===== Running C tests for c89 =====" - $(TMPDIR)/c89/$(TESTNAME) - $(TOUCH) $(TMPDIR)/c89/.ctestspassed - $(ECHO) "===== C tests for c89 PASSED =====" - -$(TMPDIR)/c89/$(TESTNAME): $(OBJDIR)/c89-test.o $(OBJDIR)/c89-test_api.o $(OBJDIR)/c89-test_fwrite_api.o $(OBJDIR)/c89-test_savebuffer.o $(OBJDIR)/c89-test_write_api.o $(OBJDIR)/c89-util.o $(TMPDIR)/c89/$(ANAME) - $(MKDIR) $(TMPDIR)/c89 - $(LD) -o $@ $(OBJDIR)/c89-test.o $(OBJDIR)/c89-test_api.o $(OBJDIR)/c89-test_fwrite_api.o $(OBJDIR)/c89-test_savebuffer.o $(OBJDIR)/c89-test_write_api.o $(OBJDIR)/c89-util.o $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L$(TMPDIR)/c89 - -resettestc89: - $(RM) $(TMPDIR)/c89/.luatestspassed - $(RM) $(TMPDIR)/c89/.ctestspassed - -cleantestc89: cleanlibsc89 resettestc89 \ - cleantestobjectsc89 - $(RM) $(TMPDIR)/c89/$(TESTNAME) - $(RMDIR) $(TMPDIR)/c89 - -# testobjectsc89: - -cleantestobjectsc89: - $(RM) $(OBJDIR)/c89-test.o $(OBJDIR)/c89-test_api.o $(OBJDIR)/c89-test_fwrite_api.o $(OBJDIR)/c89-test_savebuffer.o $(OBJDIR)/c89-test_write_api.o $(OBJDIR)/c89-util.o - -$(OBJDIR)/c89-test.o: test/test.c test/test.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test.c - -$(OBJDIR)/c89-test_api.o: test/test_api.c src/luabins.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_api.c - -$(OBJDIR)/c89-test_fwrite_api.o: test/test_fwrite_api.c src/lualess.h \ - src/fwrite.h src/saveload.h test/test.h test/util.h \ - test/write_tests.inc - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_fwrite_api.c - -$(OBJDIR)/c89-test_savebuffer.o: test/test_savebuffer.c src/lualess.h \ - src/savebuffer.h test/test.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_savebuffer.c - -$(OBJDIR)/c89-test_write_api.o: test/test_write_api.c src/lualess.h \ - src/write.h src/saveload.h src/savebuffer.h test/test.h test/util.h \ - test/write_tests.inc - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/test_write_api.c - -$(OBJDIR)/c89-util.o: test/util.c test/util.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -Isrc/ -o $@ -c test/util.c - -cleanlibsc89: cleanobjectsc89 - $(RM) $(TMPDIR)/c89/$(SONAME) - $(RM) $(TMPDIR)/c89/$(ANAME) - -$(TMPDIR)/c89/$(SONAME): $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o - $(MKDIR) $(TMPDIR)/c89 - $(LD) -o $@ $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o $(LDFLAGS) $(SOFLAGS) - -$(TMPDIR)/c89/$(ANAME): $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o - $(MKDIR) $(TMPDIR)/c89 - $(AR) $@ $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o - $(RANLIB) $@ - -# objectsc89: - -cleanobjectsc89: - $(RM) $(OBJDIR)/c89-fwrite.o $(OBJDIR)/c89-load.o $(OBJDIR)/c89-luabins.o $(OBJDIR)/c89-luainternals.o $(OBJDIR)/c89-lualess.o $(OBJDIR)/c89-save.o $(OBJDIR)/c89-savebuffer.o $(OBJDIR)/c89-write.o - -$(OBJDIR)/c89-fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ - src/saveload.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/fwrite.c - -$(OBJDIR)/c89-load.o: src/load.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/luainternals.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/load.c - -$(OBJDIR)/c89-luabins.o: src/luabins.c src/luaheaders.h src/luabins.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/luabins.c - -$(OBJDIR)/c89-luainternals.o: src/luainternals.c src/luainternals.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/luainternals.c - -$(OBJDIR)/c89-lualess.o: src/lualess.c - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/lualess.c - -$(OBJDIR)/c89-save.o: src/save.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/savebuffer.h src/write.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/save.c - -$(OBJDIR)/c89-savebuffer.o: src/savebuffer.c src/luaheaders.h \ - src/saveload.h src/savebuffer.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/savebuffer.c - -$(OBJDIR)/c89-write.o: src/write.c src/luaheaders.h src/write.h \ - src/saveload.h src/savebuffer.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c89 -o $@ -c src/write.c - -## ----- Begin c99 ----- - -testc99: lua-testsc99 c-testsc99 - -lua-testsc99: $(TMPDIR)/c99/.luatestspassed - -c-testsc99: $(TMPDIR)/c99/.ctestspassed - -$(TMPDIR)/c99/.luatestspassed: $(TMPDIR)/c99/$(SONAME) test/$(TESTLUA) - $(ECHO) "===== Running Lua tests for c99 =====" - @$(LUA) \ - -e "package.cpath='$(TMPDIR)/c99/$(SONAME);'..package.cpath" \ - test/$(TESTLUA) - $(TOUCH) $(TMPDIR)/c99/.luatestspassed - $(ECHO) "===== Lua tests for c99 PASSED =====" - -$(TMPDIR)/c99/.ctestspassed: $(TMPDIR)/c99/$(TESTNAME) test/$(TESTLUA) - $(ECHO) "===== Running C tests for c99 =====" - $(TMPDIR)/c99/$(TESTNAME) - $(TOUCH) $(TMPDIR)/c99/.ctestspassed - $(ECHO) "===== C tests for c99 PASSED =====" - -$(TMPDIR)/c99/$(TESTNAME): $(OBJDIR)/c99-test.o $(OBJDIR)/c99-test_api.o $(OBJDIR)/c99-test_fwrite_api.o $(OBJDIR)/c99-test_savebuffer.o $(OBJDIR)/c99-test_write_api.o $(OBJDIR)/c99-util.o $(TMPDIR)/c99/$(ANAME) - $(MKDIR) $(TMPDIR)/c99 - $(LD) -o $@ $(OBJDIR)/c99-test.o $(OBJDIR)/c99-test_api.o $(OBJDIR)/c99-test_fwrite_api.o $(OBJDIR)/c99-test_savebuffer.o $(OBJDIR)/c99-test_write_api.o $(OBJDIR)/c99-util.o $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L$(TMPDIR)/c99 - -resettestc99: - $(RM) $(TMPDIR)/c99/.luatestspassed - $(RM) $(TMPDIR)/c99/.ctestspassed - -cleantestc99: cleanlibsc99 resettestc99 \ - cleantestobjectsc99 - $(RM) $(TMPDIR)/c99/$(TESTNAME) - $(RMDIR) $(TMPDIR)/c99 - -# testobjectsc99: - -cleantestobjectsc99: - $(RM) $(OBJDIR)/c99-test.o $(OBJDIR)/c99-test_api.o $(OBJDIR)/c99-test_fwrite_api.o $(OBJDIR)/c99-test_savebuffer.o $(OBJDIR)/c99-test_write_api.o $(OBJDIR)/c99-util.o - -$(OBJDIR)/c99-test.o: test/test.c test/test.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test.c - -$(OBJDIR)/c99-test_api.o: test/test_api.c src/luabins.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_api.c - -$(OBJDIR)/c99-test_fwrite_api.o: test/test_fwrite_api.c src/lualess.h \ - src/fwrite.h src/saveload.h test/test.h test/util.h \ - test/write_tests.inc - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_fwrite_api.c - -$(OBJDIR)/c99-test_savebuffer.o: test/test_savebuffer.c src/lualess.h \ - src/savebuffer.h test/test.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_savebuffer.c - -$(OBJDIR)/c99-test_write_api.o: test/test_write_api.c src/lualess.h \ - src/write.h src/saveload.h src/savebuffer.h test/test.h test/util.h \ - test/write_tests.inc - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/test_write_api.c - -$(OBJDIR)/c99-util.o: test/util.c test/util.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -Isrc/ -o $@ -c test/util.c - -cleanlibsc99: cleanobjectsc99 - $(RM) $(TMPDIR)/c99/$(SONAME) - $(RM) $(TMPDIR)/c99/$(ANAME) - -$(TMPDIR)/c99/$(SONAME): $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o - $(MKDIR) $(TMPDIR)/c99 - $(LD) -o $@ $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o $(LDFLAGS) $(SOFLAGS) - -$(TMPDIR)/c99/$(ANAME): $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o - $(MKDIR) $(TMPDIR)/c99 - $(AR) $@ $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o - $(RANLIB) $@ - -# objectsc99: - -cleanobjectsc99: - $(RM) $(OBJDIR)/c99-fwrite.o $(OBJDIR)/c99-load.o $(OBJDIR)/c99-luabins.o $(OBJDIR)/c99-luainternals.o $(OBJDIR)/c99-lualess.o $(OBJDIR)/c99-save.o $(OBJDIR)/c99-savebuffer.o $(OBJDIR)/c99-write.o - -$(OBJDIR)/c99-fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ - src/saveload.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/fwrite.c - -$(OBJDIR)/c99-load.o: src/load.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/luainternals.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/load.c - -$(OBJDIR)/c99-luabins.o: src/luabins.c src/luaheaders.h src/luabins.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/luabins.c - -$(OBJDIR)/c99-luainternals.o: src/luainternals.c src/luainternals.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/luainternals.c - -$(OBJDIR)/c99-lualess.o: src/lualess.c - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/lualess.c - -$(OBJDIR)/c99-save.o: src/save.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/savebuffer.h src/write.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/save.c - -$(OBJDIR)/c99-savebuffer.o: src/savebuffer.c src/luaheaders.h \ - src/saveload.h src/savebuffer.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/savebuffer.c - -$(OBJDIR)/c99-write.o: src/write.c src/luaheaders.h src/write.h \ - src/saveload.h src/savebuffer.h - $(CC) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c -std=c99 -o $@ -c src/write.c - -## ----- Begin c++98 ----- - -testc++98: lua-testsc++98 c-testsc++98 - -lua-testsc++98: $(TMPDIR)/c++98/.luatestspassed - -c-testsc++98: $(TMPDIR)/c++98/.ctestspassed - -$(TMPDIR)/c++98/.luatestspassed: $(TMPDIR)/c++98/$(SONAME) test/$(TESTLUA) - $(ECHO) "===== Running Lua tests for c++98 =====" - @$(LUA) \ - -e "package.cpath='$(TMPDIR)/c++98/$(SONAME);'..package.cpath" \ - test/$(TESTLUA) - $(TOUCH) $(TMPDIR)/c++98/.luatestspassed - $(ECHO) "===== Lua tests for c++98 PASSED =====" - -$(TMPDIR)/c++98/.ctestspassed: $(TMPDIR)/c++98/$(TESTNAME) test/$(TESTLUA) - $(ECHO) "===== Running C tests for c++98 =====" - $(TMPDIR)/c++98/$(TESTNAME) - $(TOUCH) $(TMPDIR)/c++98/.ctestspassed - $(ECHO) "===== C tests for c++98 PASSED =====" - -$(TMPDIR)/c++98/$(TESTNAME): $(OBJDIR)/c++98-test.o $(OBJDIR)/c++98-test_api.o $(OBJDIR)/c++98-test_fwrite_api.o $(OBJDIR)/c++98-test_savebuffer.o $(OBJDIR)/c++98-test_write_api.o $(OBJDIR)/c++98-util.o $(TMPDIR)/c++98/$(ANAME) - $(MKDIR) $(TMPDIR)/c++98 - $(LDXX) -o $@ $(OBJDIR)/c++98-test.o $(OBJDIR)/c++98-test_api.o $(OBJDIR)/c++98-test_fwrite_api.o $(OBJDIR)/c++98-test_savebuffer.o $(OBJDIR)/c++98-test_write_api.o $(OBJDIR)/c++98-util.o $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L$(TMPDIR)/c++98 - -resettestc++98: - $(RM) $(TMPDIR)/c++98/.luatestspassed - $(RM) $(TMPDIR)/c++98/.ctestspassed - -cleantestc++98: cleanlibsc++98 resettestc++98 \ - cleantestobjectsc++98 - $(RM) $(TMPDIR)/c++98/$(TESTNAME) - $(RMDIR) $(TMPDIR)/c++98 - -# testobjectsc++98: - -cleantestobjectsc++98: - $(RM) $(OBJDIR)/c++98-test.o $(OBJDIR)/c++98-test_api.o $(OBJDIR)/c++98-test_fwrite_api.o $(OBJDIR)/c++98-test_savebuffer.o $(OBJDIR)/c++98-test_write_api.o $(OBJDIR)/c++98-util.o - -$(OBJDIR)/c++98-test.o: test/test.c test/test.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test.c - -$(OBJDIR)/c++98-test_api.o: test/test_api.c src/luabins.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_api.c - -$(OBJDIR)/c++98-test_fwrite_api.o: test/test_fwrite_api.c src/lualess.h \ - src/fwrite.h src/saveload.h test/test.h test/util.h \ - test/write_tests.inc - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_fwrite_api.c - -$(OBJDIR)/c++98-test_savebuffer.o: test/test_savebuffer.c src/lualess.h \ - src/savebuffer.h test/test.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_savebuffer.c - -$(OBJDIR)/c++98-test_write_api.o: test/test_write_api.c src/lualess.h \ - src/write.h src/saveload.h src/savebuffer.h test/test.h test/util.h \ - test/write_tests.inc - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/test_write_api.c - -$(OBJDIR)/c++98-util.o: test/util.c test/util.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -Isrc/ -o $@ -c test/util.c - -cleanlibsc++98: cleanobjectsc++98 - $(RM) $(TMPDIR)/c++98/$(SONAME) - $(RM) $(TMPDIR)/c++98/$(ANAME) - -$(TMPDIR)/c++98/$(SONAME): $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o - $(MKDIR) $(TMPDIR)/c++98 - $(LDXX) -o $@ $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o $(LDFLAGS) $(SOFLAGS) - -$(TMPDIR)/c++98/$(ANAME): $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o - $(MKDIR) $(TMPDIR)/c++98 - $(AR) $@ $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o - $(RANLIB) $@ - -# objectsc++98: - -cleanobjectsc++98: - $(RM) $(OBJDIR)/c++98-fwrite.o $(OBJDIR)/c++98-load.o $(OBJDIR)/c++98-luabins.o $(OBJDIR)/c++98-luainternals.o $(OBJDIR)/c++98-lualess.o $(OBJDIR)/c++98-save.o $(OBJDIR)/c++98-savebuffer.o $(OBJDIR)/c++98-write.o - -$(OBJDIR)/c++98-fwrite.o: src/fwrite.c src/luaheaders.h src/fwrite.h \ - src/saveload.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/fwrite.c - -$(OBJDIR)/c++98-load.o: src/load.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/luainternals.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/load.c - -$(OBJDIR)/c++98-luabins.o: src/luabins.c src/luaheaders.h src/luabins.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/luabins.c - -$(OBJDIR)/c++98-luainternals.o: src/luainternals.c src/luainternals.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/luainternals.c - -$(OBJDIR)/c++98-lualess.o: src/lualess.c - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/lualess.c - -$(OBJDIR)/c++98-save.o: src/save.c src/luaheaders.h src/luabins.h \ - src/saveload.h src/savebuffer.h src/write.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/save.c - -$(OBJDIR)/c++98-savebuffer.o: src/savebuffer.c src/luaheaders.h \ - src/saveload.h src/savebuffer.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/savebuffer.c - -$(OBJDIR)/c++98-write.o: src/write.c src/luaheaders.h src/write.h \ - src/saveload.h src/savebuffer.h - $(CXX) $(CFLAGS) -Werror -Wall -Wextra -pedantic -x c++ -std=c++98 -o $@ -c src/write.c - -## END OF GENERATED TARGETS ################################################### - -.PHONY: all clean install cleanlibs cleanobjects test resettest cleantest testc89 lua-testsc89 c-testsc89 resettestc89 cleantestc89 cleantestobjectsc89 cleanlibsc89 cleanobjectsc89 testc99 lua-testsc99 c-testsc99 resettestc99 cleantestc99 cleantestobjectsc99 cleanlibsc99 cleanobjectsc99 testc++98 lua-testsc++98 c-testsc++98 resettestc++98 cleantestc++98 cleantestobjectsc++98 cleanlibsc++98 cleanobjectsc++98 +include ../../Makefile.inc + +LIB = libluabins.a + +CXXFLAGS += -I../lua/src -DLUABINS_LUABUILTASCPP + +SRC = \ + src/fwrite.cpp \ + src/load.cpp \ + src/luabins.cpp \ + src/luainternals.cpp \ + src/save.cpp \ + src/savebuffer.cpp \ + src/write.cpp + +HEADER = \ + src/fwrite.h \ + src/luabins.h \ + src/luaheaders.h \ + src/luainternals.h \ + src/savebuffer.h \ + src/saveload.h \ + src/write.h + +EXTRA_DIST = \ + src/lualess.c \ + src/lualess.h \ + etc/benchmark.lua \ + etc/checkfmt.lua \ + etc/dataset.lua \ + etc/tolua.lua \ + etc/toluabins.lua \ + AUTHORS \ + COPYRIGHT \ + HISTORY \ + README.md \ + TODO + +include ../../Makefile.target +-include src/*.d diff --git a/vendor/luabins/etc/Makefile.luabins.template b/vendor/luabins/etc/Makefile.luabins.template deleted file mode 100644 index 77b76e80d..000000000 --- a/vendor/luabins/etc/Makefile.luabins.template +++ /dev/null @@ -1,242 +0,0 @@ -@{define:projectname:luabins} -@{define:test-dir:test/} -@{define:source-dir:src/} -@{define:sharedlib:$(LIBDIR)/$(SONAME)} -@{define:staticlib:$(LIBDIR)/$(ANAME)} -@{define-table:release-info: - {suffix=""; - libdir="$(LIBDIR)";objprefix="$(OBJDIR)/"; - cflags=""; - CC="$(CC)"; - LD="$(LD)"; - }; -} -@{define-table:std-info: - {suffix="c89"; - libdir="$(TMPDIR)/c89";objprefix="$(OBJDIR)/c89-"; - cflags="-Werror -Wall -Wextra -pedantic -x c -std=c89"; - CC="$(CC)"; - LD="$(LD)"; - }; - {suffix="c99"; - libdir="$(TMPDIR)/c99";objprefix="$(OBJDIR)/c99-"; - cflags="-Werror -Wall -Wextra -pedantic -x c -std=c99"; - CC="$(CC)"; - LD="$(LD)"; - }; - {suffix="c++98"; - libdir="$(TMPDIR)/c++98";objprefix="$(OBJDIR)/c++98-"; - cflags="-Werror -Wall -Wextra -pedantic -x c++ -std=c++98"; - CC="$(CXX)"; - LD="$(LDXX)"; - }; -} -@{define-dep:dep-objects:dep-template::@{source-dir}} -@{define-dep:test-dep-objects:test-dep-template:-I@{source-dir}:@{test-dir}} - -## CONFIGURATION ############################################################## - -ifeq ($(shell uname),Darwin) - LUA_DIR := /usr/local - LUA_LIBDIR := $(LUA_DIR)/lib/lua/5.1 - LUA_INCDIR := $(LUA_DIR)/include - LUALIB := lua -else - # Assuming Ubuntu - LUA_LIBDIR := /usr/lib - LUA_INCDIR := /usr/include/lua5.1 - LUALIB := lua5.1 -endif - -PROJECTNAME := @{projectname} - -SONAME := $(PROJECTNAME).so -ANAME := lib$(PROJECTNAME).a -HNAME := $(PROJECTNAME).h -TESTNAME := $(PROJECTNAME)-test -TESTLUA := test.lua - -LUA := lua -CP := cp -RM := rm -f -RMDIR := rm -df -MKDIR := mkdir -p -CC := gcc -LD := gcc -AR := ar rcu -RANLIB := ranlib -ECHO := @echo -TOUCH := touch - -# Needed for tests only -CXX := g++ -LDXX := g++ - -OBJDIR := ./obj -TMPDIR := ./tmp -INCDIR := ./include -LIBDIR := ./lib - -HFILE := $(INCDIR)/$(HNAME) - -CFLAGS += -O2 -Wall -I$(LUA_INCDIR) -LDFLAGS += -L$(LUA_LIBDIR) - -# Tested on OS X and Ubuntu -SOFLAGS := -ifeq ($(shell uname),Darwin) - SOFLAGS += -dynamiclib -undefined dynamic_lookup -else - CFLAGS += -fPIC - SOFLAGS += -shared - LDFLAGS += -ldl - RMDIR := rm -rf -endif - -CFLAGS += $(MYCFLAGS) -LDFLAGS += $(MYLDFLAGS) - -## MAIN TARGETS ############################################################### - -@{define-table:.PHONY:} - -@{insert:.PHONY:all} -all: @{sharedlib} @{staticlib} $(HFILE) - -@{insert:.PHONY:clean} -clean: cleanlibs cleantest - $(RM) $(HFILE) - -@{insert:.PHONY:install} -install: @{sharedlib} - # Note header and static library are not copied anywhere - $(CP) @{sharedlib} $(LUA_LIBDIR)/$(SONAME) - -$(HFILE): - $(CP) src/$(HNAME) $(HFILE) - -@{--:-------------------------------------------------------------------------} - -@{define:objects-macro: - -@{insert:.PHONY:clean%objects@{suffix}} -clean%objects@{suffix}: - $(RM) % - -% - -} - -@{define:lib-targets: - -@{define-fill:objects:@{fill-template:@{dep-objects}:}} - -@{insert:.PHONY:cleanlibs@{suffix}} -cleanlibs@{suffix}: cleanobjects@{suffix} - $(RM) @{sharedlib} - $(RM) @{staticlib} - -@{sharedlib}: @{objects} - $(MKDIR) @{libdir} - @{LD} -o $@ @{objects} $(LDFLAGS) $(SOFLAGS) - -@{staticlib}: @{objects} - $(MKDIR) @{libdir} - $(AR) $@ @{objects} - $(RANLIB) $@ - -@{--: note implicit objprefix parameter } -# objects@{suffix}: -@{fill-macro:objects-macro:%<>: - prefix="", - objects=@{lua-escape:@{objects}}; - dep=@{lua-escape:@{fill-template:dep-template:}}; -} - -} - -@{define:std-targets: - -## ----- Begin @{suffix} ----- - -@{define-fill:cflags-orig:@{cflags}} -@{define-fill:cflags:@{cflags} -I@{source-dir}} - -@{define-fill:sharedlib:@{libdir}/$(SONAME)} -@{define-fill:staticlib:@{libdir}/$(ANAME)} -@{define-fill:objects:@{fill-template:@{test-dep-objects}:}} - -@{insert:.PHONY:test@{suffix}} -test@{suffix}: lua-tests@{suffix} c-tests@{suffix} - -@{insert:.PHONY:lua-tests@{suffix}} -lua-tests@{suffix}: @{libdir}/.luatestspassed - -@{insert:.PHONY:c-tests@{suffix}} -c-tests@{suffix}: @{libdir}/.ctestspassed - -@{libdir}/.luatestspassed: @{sharedlib} test/$(TESTLUA) - $(ECHO) "===== Running Lua tests for @{suffix} =====" - @$(LUA) \ - -e "package.cpath='@{sharedlib};'..package.cpath" \ - test/$(TESTLUA) - $(TOUCH) @{libdir}/.luatestspassed - $(ECHO) "===== Lua tests for @{suffix} PASSED =====" - -@{libdir}/.ctestspassed: @{libdir}/$(TESTNAME) test/$(TESTLUA) - $(ECHO) "===== Running C tests for @{suffix} =====" - @{libdir}/$(TESTNAME) - $(TOUCH) @{libdir}/.ctestspassed - $(ECHO) "===== C tests for @{suffix} PASSED =====" - -@{libdir}/$(TESTNAME): @{objects} @{staticlib} - $(MKDIR) @{libdir} - @{LD} -o $@ @{objects} $(LDFLAGS) -lm -l$(LUALIB) -l$(PROJECTNAME) -L@{libdir} - -@{insert:.PHONY:resettest@{suffix}} -resettest@{suffix}: - $(RM) @{libdir}/.luatestspassed - $(RM) @{libdir}/.ctestspassed - -@{insert:.PHONY:cleantest@{suffix}} -cleantest@{suffix}: cleanlibs@{suffix} resettest@{suffix} \ - cleantestobjects@{suffix} - $(RM) @{libdir}/$(TESTNAME) - $(RMDIR) @{libdir} - -@{--: Note implicit objprefix parameter } -# testobjects@{suffix}: -@{fill-macro:objects-macro:%<>: - prefix="test", - objects=@{lua-escape:@{objects}}; - dep=@{lua-escape:@{fill-template:test-dep-template:}}; -} - -@{--: Libraries must use original cflags } -@{fill-template:lib-targets:cflags=@{lua-escape:@{cflags-orig}}} - -} - -## GENERATED RELEASE TARGETS ################################################## - -@{map-template:release-info:lib-targets} - -## TEST TARGETS ############################################################### - -@{insert:.PHONY:test} -test:@{map-template:std-info: test@{suffix}} - $(ECHO) "===== TESTS PASSED =====" - -@{insert:.PHONY:resettest} -resettest:@{map-template:std-info: resettest@{suffix}} - -@{insert:.PHONY:cleantest} -cleantest:@{map-template:std-info: cleantest@{suffix}} - -## GENERATED TEST TARGETS ##################################################### - -@{map-template:std-info:std-targets} - -## END OF GENERATED TARGETS ################################################### - -.PHONY: @{concat:.PHONY: } diff --git a/vendor/luabins/etc/genmakefile.sh b/vendor/luabins/etc/genmakefile.sh deleted file mode 100755 index 45244e442..000000000 --- a/vendor/luabins/etc/genmakefile.sh +++ /dev/null @@ -1,2 +0,0 @@ -#! /bin/bash -lua ~/projects/genmakefile/src/genmakefile.lua Makefile diff --git a/vendor/luabins/src/fwrite.c b/vendor/luabins/src/fwrite.cpp similarity index 100% rename from vendor/luabins/src/fwrite.c rename to vendor/luabins/src/fwrite.cpp diff --git a/vendor/luabins/src/load.c b/vendor/luabins/src/load.cpp similarity index 100% rename from vendor/luabins/src/load.c rename to vendor/luabins/src/load.cpp diff --git a/vendor/luabins/src/luabins.c b/vendor/luabins/src/luabins.cpp similarity index 100% rename from vendor/luabins/src/luabins.c rename to vendor/luabins/src/luabins.cpp diff --git a/vendor/luabins/src/luainternals.c b/vendor/luabins/src/luainternals.cpp similarity index 100% rename from vendor/luabins/src/luainternals.c rename to vendor/luabins/src/luainternals.cpp diff --git a/vendor/luabins/src/save.c b/vendor/luabins/src/save.cpp similarity index 100% rename from vendor/luabins/src/save.c rename to vendor/luabins/src/save.cpp diff --git a/vendor/luabins/src/savebuffer.c b/vendor/luabins/src/savebuffer.cpp similarity index 100% rename from vendor/luabins/src/savebuffer.c rename to vendor/luabins/src/savebuffer.cpp diff --git a/vendor/luabins/src/write.c b/vendor/luabins/src/write.cpp similarity index 100% rename from vendor/luabins/src/write.c rename to vendor/luabins/src/write.cpp From 18f55eaebf5cb6b4ccb4d85d5961d6a858bd4ab6 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 24 Apr 2014 22:57:23 +0200 Subject: [PATCH 07/13] Load luabins library into Auto4 Lua environment --- src/Makefile | 1 + src/auto4_lua.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/Makefile b/src/Makefile index 919c55abc..77f91e1b6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,6 +14,7 @@ LIBS := -L../libaegisub -laegisub $(LIBS) LIBS += $(LIBS_GL) $(LIBS_PTHREAD) $(LIBS_WX) $(LIBS_FREETYPE) LIBS += $(LIBS_FONTCONFIG) $(LIBS_FFTW3) $(LIBS_UCHARDET) $(LIBS_BOOST) LIBS += $(LIBS_ICU) $(LIBS_LUA) +LIBS += ../vendor/luabins/libluabins.a ifeq (yes, $(BUILD_DARWIN)) SRC += osx_utils.mm retina_helper.mm diff --git a/src/auto4_lua.cpp b/src/auto4_lua.cpp index 26d2768f2..7ddb363dc 100644 --- a/src/auto4_lua.cpp +++ b/src/auto4_lua.cpp @@ -307,6 +307,9 @@ namespace { int luaopen_lpeg (lua_State *L); +// Forward-declaration for luabins library (not in any public header) +extern "C" int luaopen_luabins(lua_State * L); + namespace Automation4 { int regex_init(lua_State *L); @@ -377,6 +380,7 @@ namespace Automation4 { push_value(L, luaopen_package); lua_call(L, 0, 0); push_value(L, luaopen_string); lua_call(L, 0, 0); push_value(L, luaopen_table); lua_call(L, 0, 0); + push_value(L, luaopen_luabins); lua_call(L, 0, 0); _stackcheck.check_stack(0); // dofile and loadfile are replaced with include From 3f08b1d057fbebacaa182c60b239f29b9c7b4f4f Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 24 Apr 2014 23:49:36 +0200 Subject: [PATCH 08/13] Use lua_pushlstring() so strings with embedded NULs also work --- src/auto4_lua_utils.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/auto4_lua_utils.h b/src/auto4_lua_utils.h index 9639121c6..594eec419 100644 --- a/src/auto4_lua_utils.h +++ b/src/auto4_lua_utils.h @@ -40,11 +40,12 @@ inline void push_value(lua_State *L, wxString const& value) { } inline void push_value(lua_State *L, agi::fs::path const& value) { - lua_pushstring(L, value.string().c_str()); + std::string strval = value.string(); + lua_pushlstring(L, strval.c_str(), strval.size()); } inline void push_value(lua_State *L, std::string const& value) { - lua_pushstring(L, value.c_str()); + lua_pushlstring(L, value.c_str(), value.size()); } inline void push_value(lua_State *L, lua_CFunction value) { From b2768b7abd3fb4e450a976a3bd3c50b910ffe585 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 24 Apr 2014 23:54:42 +0200 Subject: [PATCH 09/13] Work around boost::format bug See https://svn.boost.org/trac/boost/ticket/9360 It seems that the %X specifier is ignored if the input value is a char type and the char is instead output verbatim and not in its integer value. Casting it to an int works around this. --- src/string_codec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/string_codec.cpp b/src/string_codec.cpp index 5e48d214a..6e19c7fbb 100644 --- a/src/string_codec.cpp +++ b/src/string_codec.cpp @@ -45,7 +45,7 @@ std::string inline_string_encode(const std::string &input) { auto format = boost::format("#%02X"); for (char c : input) { if (c <= 0x1F || c == 0x23 || c == 0x2C || c == 0x3A || c == 0x7C) - output += str(format % c); + output += str(format % (int)(unsigned char)c); else output += c; } From 7839e8c983d79a7f6665c697c1d0ede6d1486ee9 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Fri, 25 Apr 2014 00:05:32 +0200 Subject: [PATCH 10/13] Fix bug in extradata id list reading --- src/ass_dialogue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ass_dialogue.cpp b/src/ass_dialogue.cpp index 73c272cfd..5a3b9c100 100644 --- a/src/ass_dialogue.cpp +++ b/src/ass_dialogue.cpp @@ -137,7 +137,7 @@ void AssDialogue::Parse(std::string const& raw) { while (boost::regex_search(start, end, rematch, idmatcher)) { auto id = boost::lexical_cast(rematch.str(1)); ids.push_back(id); - start = rematch.suffix().second; + start = rematch.suffix().first; } ExtradataIds = ids; } From bcd41bd986f8434b419276bd6f50c77c45b73f98 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Fri, 25 Apr 2014 15:08:54 +0200 Subject: [PATCH 11/13] Windows build system for luabins (untested) --- build/Aegisub/Aegisub.vcxproj | 3 ++ build/luabins/luabins.vcxproj | 44 +++++++++++++++++++++ build/luabins/luabins.vcxproj.filters | 57 +++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 build/luabins/luabins.vcxproj create mode 100644 build/luabins/luabins.vcxproj.filters diff --git a/build/Aegisub/Aegisub.vcxproj b/build/Aegisub/Aegisub.vcxproj index b1bac423c..56aa2e069 100644 --- a/build/Aegisub/Aegisub.vcxproj +++ b/build/Aegisub/Aegisub.vcxproj @@ -81,6 +81,9 @@ {5391a8b1-9c70-4dc4-92ad-d3e34c6b803f} + + {A7A30702-8162-4E1A-A010-EF51B590C121} + {7b56955d-5162-4698-aa5b-47484edc8783} diff --git a/build/luabins/luabins.vcxproj b/build/luabins/luabins.vcxproj new file mode 100644 index 000000000..c0e7f4093 --- /dev/null +++ b/build/luabins/luabins.vcxproj @@ -0,0 +1,44 @@ + + + + {A7A30702-8162-4E1A-A010-EF51B590C121} + luabins + + + + + lib + ..\..\vendor\luabins\src\ + + + + + + + + + LUABINS_LUABUILTASCPP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + $(SrcDir)..\..\lua51\src;%(AdditionalIncludeDirectories) + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/luabins/luabins.vcxproj.filters b/build/luabins/luabins.vcxproj.filters new file mode 100644 index 000000000..7a9b51b8e --- /dev/null +++ b/build/luabins/luabins.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {0A33FF05-970D-49a7-B722-73E8EA350084} + + + {2C50401A-5AC6-4630-B633-DFCC190306A8} + + + + + Source + + + Source + + + Source + + + Source + + + Source + + + Source + + + Source + + + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + From f278c35f3f27c107e4c49c36c2a195cdf1bbe252 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Fri, 25 Apr 2014 16:04:08 +0200 Subject: [PATCH 12/13] Dynamically use either inline_string escaping or uuencoding for extradata Since luabins generates binary data which grows up to 3x by escaping, it's more efficient to uuencode that instead. A marker is placed as the first character of the value field, either 'e' for inline_string escaped text, or 'u' for uuencoded binary data. The key is always inline_string escaped, as it will typically be human readable. --- libaegisub/include/libaegisub/ass/uuencode.h | 4 ++-- src/ass_parser.cpp | 18 ++++++++++++++++-- src/subtitle_format_ass.cpp | 14 +++++++++++++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libaegisub/include/libaegisub/ass/uuencode.h b/libaegisub/include/libaegisub/ass/uuencode.h index fbc957c3d..b6b30e442 100644 --- a/libaegisub/include/libaegisub/ass/uuencode.h +++ b/libaegisub/include/libaegisub/ass/uuencode.h @@ -28,7 +28,7 @@ namespace agi { namespace ass { /// Encode a blob of data, using ASS's nonstandard variant template -std::string UUEncode(RandomAccessRange const& data) { +std::string UUEncode(RandomAccessRange const& data, bool insert_linebreaks=true) { using std::begin; using std::end; @@ -51,7 +51,7 @@ std::string UUEncode(RandomAccessRange const& data) { for (size_t i = 0; i < std::min(size - pos + 1, 4u); ++i) { ret += dst[i] + 33; - if (++written == 80 && pos + 3 < size) { + if (insert_linebreaks && ++written == 80 && pos + 3 < size) { written = 0; ret += "\r\n"; } diff --git a/src/ass_parser.cpp b/src/ass_parser.cpp index 478704eb5..4e2e9061b 100644 --- a/src/ass_parser.cpp +++ b/src/ass_parser.cpp @@ -22,6 +22,8 @@ #include "string_codec.h" #include "subtitle_format.h" +#include + #include #include #include @@ -115,13 +117,25 @@ void AssParser::ParseGraphicsLine(std::string const& data) { } void AssParser::ParseExtradataLine(std::string const &data) { - static const boost::regex matcher("Data:[[:space:]]*(\\d+),([^,]+),(.*)"); + static const boost::regex matcher("Data:[[:space:]]*(\\d+),([^,]+),(.)(.*)"); boost::match_results mr; if (boost::regex_match(data, mr, matcher)) { auto id = boost::lexical_cast(mr.str(1)); auto key = inline_string_decode(mr.str(2)); - auto value = inline_string_decode(mr.str(3)); + auto valuetype = mr.str(3); + auto value = mr.str(4); + if (valuetype == "e") { + // escaped/inline_string encoded + value = inline_string_decode(value); + } else if (valuetype == "u") { + // ass uuencoded + auto valuedata = agi::ass::UUDecode(value); + value = std::string(valuedata.begin(), valuedata.end()); + } else { + // unknown, error? + value = ""; + } // ensure next_extradata_id is always at least 1 more than the largest existing id target->next_extradata_id = std::max(id+1, target->next_extradata_id); diff --git a/src/subtitle_format_ass.cpp b/src/subtitle_format_ass.cpp index 3d5972a36..c5d1800df 100644 --- a/src/subtitle_format_ass.cpp +++ b/src/subtitle_format_ass.cpp @@ -27,6 +27,7 @@ #include "text_file_writer.h" #include "version.h" +#include #include DEFINE_SIMPLE_EXCEPTION(AssParseError, SubtitleFormatParseError, "subtitle_io/parse/ass") @@ -129,7 +130,18 @@ struct Writer { line += ","; line += inline_string_encode(edi.second.first); line += ","; - line += inline_string_encode(edi.second.second); + std::string encoded_data = inline_string_encode(edi.second.second); + if (4*edi.second.second.size() < 3*encoded_data.size()) { + // the inline_string encoding grew the data by more than uuencoding would + // so base64 encode it instead + line += "u"; // marker for uuencoding + encoded_data = agi::ass::UUEncode(edi.second.second, false); + printf("did uuencoding, original size=%lu, encoded size=%lu\n", edi.second.second.size(), encoded_data.size()); + line += encoded_data; + } else { + line += "e"; // marker for inline_string encoding (escaping) + line += encoded_data; + } file.WriteLineToFile(line); } } From 5a930cfee398a7c43626b007469f2db606048784 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Fri, 25 Apr 2014 17:19:39 +0200 Subject: [PATCH 13/13] Forgot to add the luabins project to MSVS solution file --- Aegisub.sln | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Aegisub.sln b/Aegisub.sln index 22c2ce5f3..8a6d6112b 100644 --- a/Aegisub.sln +++ b/Aegisub.sln @@ -28,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libresrc", "build\libresrc\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua51", "build\lua51\lua51.vcxproj", "{5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luabins", "build\luabins\luabins.vcxproj", "{A7A30702-8162-4E1A-A010-EF51B590C121}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "respack", "build\respack\respack.vcxproj", "{08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}" ProjectSection(ProjectDependencies) = postProject {FB8E8D19-A4D6-4181-943C-282075F49B41} = {FB8E8D19-A4D6-4181-943C-282075F49B41} @@ -223,6 +225,20 @@ Global {5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}.Release|x64.Build.0 = Release|x64 {5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}.Release-MinDep|Win32.ActiveCfg = Release|Win32 {5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}.Release-MinDep|x64.ActiveCfg = Release|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|Win32.ActiveCfg = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|Win32.Build.0 = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|x64.ActiveCfg = Debug|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|x64.Build.0 = Debug|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-MinDep|Win32.ActiveCfg = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-MinDep|x64.ActiveCfg = Debug|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-Tests|Win32.ActiveCfg = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-Tests|x64.ActiveCfg = Debug|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|Win32.ActiveCfg = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|Win32.Build.0 = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|x64.ActiveCfg = Release|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|x64.Build.0 = Release|x64 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release-MinDep|Win32.ActiveCfg = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release-MinDep|x64.ActiveCfg = Release|x64 {08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}.Debug|Win32.ActiveCfg = Debug|Win32 {08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}.Debug|Win32.Build.0 = Debug|Win32 {08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}.Debug|x64.ActiveCfg = Debug|x64