Merge branch 'extradata'

Conflicts:
	src/ass_parser.cpp
This commit is contained in:
Niels Martin Hansen 2014-04-25 17:22:15 +02:00
commit d53c36e67f
72 changed files with 4913 additions and 15 deletions

View File

@ -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

View File

@ -3,6 +3,7 @@ include Makefile.inc
SUBDIRS += \
vendor/lua \
vendor/universalchardet \
vendor/luabins \
libaegisub \
tools \
src \

View File

@ -81,6 +81,9 @@
<ProjectReference Include="..\lua51\lua51.vcxproj">
<Project>{5391a8b1-9c70-4dc4-92ad-d3e34c6b803f}</Project>
</ProjectReference>
<ProjectReference Include="..\luabins\luabins.vcxproj">
<Project>{A7A30702-8162-4E1A-A010-EF51B590C121}</Project>
</ProjectReference>
<ProjectReference Include="..\universalchardet\universalchardet.vcxproj">
<Project>{7b56955d-5162-4698-aa5b-47484edc8783}</Project>
</ProjectReference>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{A7A30702-8162-4E1A-A010-EF51B590C121}</ProjectGuid>
<RootNamespace>luabins</RootNamespace>
</PropertyGroup>
<!-- Aegisub project configuration -->
<PropertyGroup Label="AegisubConfiguration">
<AegisubProjectType>lib</AegisubProjectType>
<SrcDir>..\..\vendor\luabins\src\</SrcDir>
</PropertyGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(MSBuildThisFileDirectory)..\aegisub.props" />
</ImportGroup>
<!-- Project specific configuration -->
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>LUABINS_LUABUILTASCPP;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SrcDir)..\..\lua51\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<!-- Source files -->
<ItemGroup>
<ClCompile Include="$(SrcDir)fwrite.cpp" />
<ClCompile Include="$(SrcDir)load.cpp" />
<ClCompile Include="$(SrcDir)luabins.cpp" />
<ClCompile Include="$(SrcDir)luainternals.cpp" />
<ClCompile Include="$(SrcDir)save.cpp" />
<ClCompile Include="$(SrcDir)savebuffer.cpp" />
<ClCompile Include="$(SrcDir)write.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SrcDir)fwrite.h" />
<ClInclude Include="$(SrcDir)luabins.h" />
<ClInclude Include="$(SrcDir)luaheaders.h" />
<ClInclude Include="$(SrcDir)luainternals.h" />
<ClInclude Include="$(SrcDir)savebuffer.h" />
<ClInclude Include="$(SrcDir)saveload.h" />
<ClInclude Include="$(SrcDir)write.h" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Headers">
<UniqueIdentifier>{0A33FF05-970D-49a7-B722-73E8EA350084}</UniqueIdentifier>
</Filter>
<Filter Include="Source">
<UniqueIdentifier>{2C50401A-5AC6-4630-B633-DFCC190306A8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(SrcDir)fwrite.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)load.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)luabins.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)luainternals.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)save.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)savebuffer.cpp">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="$(SrcDir)write.cpp">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SrcDir)fwrite.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)luabins.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)luaheaders.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)luainternals.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)savebuffer.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)saveload.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)write.h">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -28,7 +28,7 @@ namespace agi { namespace ass {
/// Encode a blob of data, using ASS's nonstandard variant
template<typename RandomAccessRange>
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_t>(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";
}

View File

@ -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

View File

@ -44,6 +44,7 @@
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
#include <boost/spirit/include/karma_generate.hpp>
#include <boost/spirit/include/karma_int.hpp>
@ -120,7 +121,28 @@ void AssDialogue::Parse(std::string const& raw) {
for (int& margin : Margin)
margin = mid(0, boost::lexical_cast<int>(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<std::string::iterator> 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<uint32_t> ids;
while (boost::regex_search(start, end, rematch, idmatcher)) {
auto id = boost::lexical_cast<uint32_t>(rematch.str(1));
ids.push_back(id);
start = rematch.suffix().first;
}
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) {

View File

@ -146,6 +146,8 @@ struct AssDialogueBase {
boost::flyweight<std::string> Actor;
/// Effect name
boost::flyweight<std::string> Effect;
/// IDs of extradata entries for line
boost::flyweight<std::vector<uint32_t>> ExtradataIds;
/// Raw text data
boost::flyweight<std::string> Text;
};
@ -183,3 +185,4 @@ public:
AssDialogue(std::string const& data);
~AssDialogue();
};

View File

@ -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]",
""
};

View File

@ -43,6 +43,7 @@ enum class AssEntryGroup {
FONT,
GRAPHIC,
DIALOGUE,
EXTRADATA,
GROUP_MAX
};

View File

@ -26,6 +26,7 @@
#include <algorithm>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/filesystem/path.hpp>
#include <cassert>
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<AssDialogue> &lst, CompFunc comp, std::set<AssDialo
begin = --end;
}
}
uint32_t AssFile::AddExtradata(std::string const& key, std::string const& value) {
// next_extradata_id must not exist
assert(Extradata.find(next_extradata_id) == Extradata.end());
Extradata[next_extradata_id] = std::make_pair(key, value);
return next_extradata_id++; // return old value, then post-increment
}
std::map<std::string, std::string> AssFile::GetExtradata(std::vector<uint32_t> const& id_list) const {
// If multiple IDs have the same key name, the last ID wins
std::map<std::string, std::string> 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<uint32_t> 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<std::string, uint32_t> 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<uint32_t> 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);
}
}

View File

@ -50,6 +50,8 @@ class wxString;
template<typename T>
using EntryList = typename boost::intrusive::make_list<T, boost::intrusive::constant_time_size<false>, boost::intrusive::base_hook<AssEntryListHook>>::type;
using AegisubExtradataMap = std::map<uint32_t, std::pair<std::string, std::string>>;
struct AssFileCommit {
wxString const& message;
int *commit_id;
@ -66,6 +68,9 @@ public:
EntryList<AssStyle> Styles;
EntryList<AssDialogue> Events;
std::vector<AssAttachment> 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<std::string, std::string> GetExtradata(std::vector<uint32_t> 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<AssDialogue>& lst, CompFunc comp = CompStart, std::set<AssDialogue*> const& limit = std::set<AssDialogue*>());
};

View File

@ -19,14 +19,18 @@
#include "ass_file.h"
#include "ass_info.h"
#include "ass_style.h"
#include "string_codec.h"
#include "subtitle_format.h"
#include <libaegisub/ass/uuencode.h>
#include <libaegisub/make_unique.h>
#include <algorithm>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
AssParser::AssParser(AssFile *target, int version)
: target(target)
@ -113,6 +117,33 @@ void AssParser::ParseGraphicsLine(std::string const& data) {
attach = agi::make_unique<AssAttachment>(data, AssEntryGroup::GRAPHIC);
}
void AssParser::ParseExtradataLine(std::string const &data) {
static const boost::regex matcher("Data:[[:space:]]*(\\d+),([^,]+),(.)(.*)");
boost::match_results<std::string::const_iterator> mr;
if (boost::regex_match(data, mr, matcher)) {
auto id = boost::lexical_cast<uint32_t>(mr.str(1));
auto key = inline_string_decode(mr.str(2));
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);
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
@ -144,6 +175,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;

View File

@ -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);

View File

@ -56,6 +56,7 @@
#include <libaegisub/make_unique.h>
#include <algorithm>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/predicate.hpp>
@ -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<AssEntry> et(Automation4::LuaAssFile::LuaToAssEntry(L));
auto st = dynamic_cast<AssStyle*>(et.get());
@ -295,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);
@ -365,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

View File

@ -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<AssEntry> LuaToAssEntry(lua_State *L);
static std::unique_ptr<AssEntry> 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,

View File

@ -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<const AssStyle*>(e)) {
@ -221,7 +230,7 @@ namespace Automation4 {
}
}
std::unique_ptr<AssEntry> LuaAssFile::LuaToAssEntry(lua_State *L)
std::unique_ptr<AssEntry> 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<uint32_t> 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<AssDialogue*>(e.get());
luaL_argcheck(L, dia, 1, "Subtitle line must be a dialogue line");

View File

@ -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) {
@ -71,10 +72,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 = "<not a string>";
return str;
return std::string(str, len);
}
inline std::string get_global_string(lua_State *L, const char *name) {

View File

@ -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;
}

View File

@ -60,6 +60,7 @@ struct SubsController::UndoInfo {
std::vector<AssStyle> styles;
std::vector<AssDialogueBase> events;
std::vector<AssAttachment> attachments;
AegisubExtradataMap extradata;
mutable std::vector<int> 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);
@ -267,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 (...) {

View File

@ -22,10 +22,12 @@
#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"
#include <libaegisub/ass/uuencode.h>
#include <libaegisub/fs.h>
DEFINE_SIMPLE_EXCEPTION(AssParseError, SubtitleFormatParseError, "subtitle_io/parse/ass")
@ -114,6 +116,35 @@ 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 += ",";
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);
}
}
};
}
@ -124,4 +155,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);
}

4
vendor/luabins/AUTHORS vendored Normal file
View File

@ -0,0 +1,4 @@
Luabins authors:
----------------
Alexander Gladysh <agladysh@gmail.com>

51
vendor/luabins/BENCHMARK vendored Normal file
View File

@ -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

32
vendor/luabins/COPYRIGHT vendored Normal file
View File

@ -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)

47
vendor/luabins/HISTORY vendored Normal file
View File

@ -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.

40
vendor/luabins/Makefile vendored Normal file
View File

@ -0,0 +1,40 @@
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

112
vendor/luabins/README.md vendored Normal file
View File

@ -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`.

11
vendor/luabins/TODO vendored Normal file
View File

@ -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

106
vendor/luabins/etc/benchmark.lua vendored Normal file
View File

@ -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

30
vendor/luabins/etc/checkfmt.lua vendored Normal file
View File

@ -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 <out_filename>")
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")

90
vendor/luabins/etc/dataset.lua vendored Normal file
View File

@ -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 <out_filename>")
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

39
vendor/luabins/etc/tolua.lua vendored Normal file
View File

@ -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 <out_filename>")
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

16
vendor/luabins/etc/toluabins.lua vendored Normal file
View File

@ -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 <out_filename>")
io.write(
luabins.save(
assert(loadfile(filename))()
)
)
io:flush()

0
vendor/luabins/include/.keepme vendored Normal file
View File

0
vendor/luabins/lib/.keepme vendored Normal file
View File

0
vendor/luabins/obj/.keepme vendored Normal file
View File

View File

@ -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"
}

View File

@ -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/"
}
}
}
}

View File

@ -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/"
}
}
}
}

View File

@ -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/"
}
}
}
}

View File

@ -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/"
}
}
}
}

View File

@ -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/"
}
}
}
}

49
vendor/luabins/src/fwrite.cpp vendored Normal file
View File

@ -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);
}

37
vendor/luabins/src/fwrite.h vendored Normal file
View File

@ -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_ */

367
vendor/luabins/src/load.cpp vendored Normal file
View File

@ -0,0 +1,367 @@
/*
* load.c
* Luabins load code
* See copyright notice in luabins.h
*/
#include <string.h>
#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;
}

104
vendor/luabins/src/luabins.cpp vendored Normal file
View File

@ -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

69
vendor/luabins/src/luabins.h vendored Normal file
View File

@ -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_ */

14
vendor/luabins/src/luaheaders.h vendored Normal file
View File

@ -0,0 +1,14 @@
#ifndef LUABINS_LUAHEADERS_H_INCLUDED_
#define LUABINS_LUAHEADERS_H_INCLUDED_
#if defined (__cplusplus) && !defined (LUABINS_LUABUILTASCPP)
extern "C" {
#endif
#include <lua.h>
#include <lauxlib.h>
#if defined (__cplusplus) && !defined (LUABINS_LUABUILTASCPP)
}
#endif
#endif /* LUABINS_LUAHEADERS_H_INCLUDED_ */

54
vendor/luabins/src/luainternals.cpp vendored Normal file
View File

@ -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 <lua.h>
#include <lauxlib.h>
#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
*/

53
vendor/luabins/src/luainternals.h vendored Normal file
View File

@ -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_ */

32
vendor/luabins/src/lualess.c vendored Normal file
View File

@ -0,0 +1,32 @@
/*
* lualess.h
* Lua-related definitions for lua-less builds (based on Lua manual)
* See copyright notice in luabins.h
*/
#include <stdlib.h>
/*
* 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);
}
}

33
vendor/luabins/src/lualess.h vendored Normal file
View File

@ -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 <stddef.h> /* 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_ */

236
vendor/luabins/src/save.cpp vendored Normal file
View File

@ -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;
}

252
vendor/luabins/src/savebuffer.cpp vendored Normal file
View File

@ -0,0 +1,252 @@
/*
* savebuffer.c
* Luabins save buffer
* See copyright notice in luabins.h
*/
#include <string.h> /* 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;
}
}

91
vendor/luabins/src/savebuffer.h vendored Normal file
View File

@ -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_ */

114
vendor/luabins/src/saveload.h vendored Normal file
View File

@ -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_ */

75
vendor/luabins/src/write.cpp vendored Normal file
View File

@ -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;
}

44
vendor/luabins/src/write.h vendored Normal file
View File

@ -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_ */

38
vendor/luabins/test/large_data.lua vendored Normal file
View File

@ -0,0 +1,38 @@
return true,nil,907.8738621938385904286406002938747406005859375,true,-10.074422490352031189786430331878364086151123046875,nil,0.5328851083912351516147509755683131515979766845703125,true,true,0.5577272826608863365294155300944112241268157958984375,0.77317682130875853285800758385448716580867767333984375,4203,"üΤ½Ð¤ZkL‰+¼$Ö½xßG\000TøKówÚj=h \"÷ð›ÚÁ@5,<2C>¾WIã.[\rN[bF§V¾<56>Áüéâáÿ|ÙѽþJÍV”±„ êhõ1\rì{ï \\îÙÈí×ëá¥AuVÆcYûËN,Û›l¨ ç˜C‡1O³'\
ÌL\
#kRºD-UaþjıáÛ)b'4…:P ¦h_a¬Œ·&µy§Lùkj«LØ|ámX Ï?Uº<55>b`÷ÁÁ¤Nx²t.+{%‡æÑÓ¿Mµ,¥Àü%ÿRß<52>´@‡v+ÄzÞ8©\
T$0Û ®ÊNd÷ô$ó#³ú::p<f4Dm`<EFBFBD><EFBFBD>LZÏ°RÄÔFÞøŒØ«æ÷OL,šfá\\ë`ú{áFÖ±÷(uÌnTÄû-p@Vz<EFBFBD>£§5Aûžæw˜bYß9\
×a£ÐÔØNA/ÉÐÓpf²aPHéªðÉäú FzCO«ãP2³ûc<EFBFBD>+¯osFX6\"1ÂH¬_û²BL6uÞêpBrÜ ú7±iªøÂÉ/äË`§\r­s`¶T—+3<>œvóxörº§Üe ž.σú0*F98ÐdÏR\000EFxÈ<ëäÈç„gÃî¡ 'Ù¥÷>tI>º<>·ƒÌ£°kí5ÒŠ½Ò2ÒÁÓÜè­ßëö)*±ºâ4††:7ñ'mÄ+÷‚>UqÙD¶þò8","/àÂëIqO€cwí(¢åªáìÿRÆ—|‰µógäûpž[ÚÍ*‡0¢uXEZ&Gx\rŠ-™? \000$qéÚÌÄášïiÊÞ#Ö9'ý<>)vŽB†pX<> |­f‡^*høÑë°æ‚êk7õúz{êl{»è(LO°ªz¢”ëe@L†ZBò\r³\000øNlt U<>V¤M\000f£³Q óíU¶t°øfC0SQãSI2¿¾;[‘¹¨’×5Ša?~N”4ÂE,)‰\\|Ú@Ï$r<>⮣=?\\æÒ4õ¿VG=¥Üqh\"<EFBFBD>«ú\r†:ܪ¬kŒZÊšl°m¡¦u`ý½<C3BD>¢™ »­œg§©í↘<E280A0>ò$êï…oŸòFhqC%æ¿ñ{ÌŽâs8ÐV¾hå±<C3A5>д}U#H4c°¥¦Öµ<C396>Ó~Ÿ\rôEÄj-Oµ» j8uŽU½Â¸nh_EìÛñkìx᤽¦ÂÓ^x<>âÈôp²3×!œ6fº#A«<41>.=âƵñˆ‰P\000ÏâáÃSÿv‡×—$\rþÞ1?ŠÀnÇÈ~©<>3½ëÖºú¸~M¸õÕ<C3B5>Œù<C592>ŠØÎÊb<C38A>9*X·Ôçëoþ¨Z~7”^ï‰3- êkgz¤Ò[f¹GÕ¸ï0ÍnFÞ¥Ú<•coyœ0¢… •)g…!Ì×Ù¼¦*N…Ï(Áe0yÍ©oÄ£yYÍÁSâï»Û÷bFçÕo¨:ûÙ´\000§]\"Â<EFBFBD>|<7C>¥=⽬ÛÞ¤=äë%ºZÎõU§©UNse)6õ¥Åã¨YªÞˆ«lA&ðE·ÅšÌkõDa\
ý~²V<EFBFBD>]\\|¾yŽÎÓZn'ÂX¸ÌU6«¸ÜÁ®R<C2AE>= \"¥}1¤ý(À¿€yÕ¯\
<EFBFBD>g抨¼JfIl˜,é^<EFBFBD>Ç_Üwj^Þ^ùrÎÙÿU`kíŒTëâq0îx÷NUn¸³M\
œ¬ ºï÷ºDW&1ä{7Ï]QA<EFBFBD>?¹ŽóGÂAQ_íU nʳ[ðå?kÈmQV­ Û<σÜÔ;þ*»\
:*\rÝiõ©`߸)M\
û[7/*º ;<EFBFBD>H9ºCô.Qù ºïÏcO®&ù÷;T.k~é",0.72726119576360159779682135194889269769191741943359375,0.7488742800191390269759494913159869611263275146484375,{},{},-5936,-126,nil,nil,-37.53135836568259264822700060904026031494140625,nil,false,nil,nil,nil,{},nil,9692,{},nil,nil,nil,nil,1906,nil,-2262,nil,{},false,-6092,nil,false,321.657733579938167167711071670055389404296875,846.6585411041315865077194757759571075439453125,{},1554,nil,nil,nil,{},"ÄAõý®N×<EFBFBD>xaHÂ80»Q¿KŒ<EFBFBD>.9Iö×8ï5<EFBFBD>V\r,ÎnL0@œ ËHVÞWMj¥qºBÇÈo6¼­gAõ*<EFBFBD>Ž¬\r+»ö[½ÅC07þsþÆãüŸBdá7ŽcÆ:pñöŠèúú½U¸HûyRùìQÀÏæ½o(!P`¯´&ê$à¯\000Ú©½0bK^žXkï:ÖÕ©ÿ÷ú_§®Óœr<EFBFBD>M,Z}Ž`ÉíàhEKX^.40-+*ŒÒÙd¬¯Ö/L#[¦¡êk×èÔ4,|ºZ°ëˆÜ¯ï'œ×êË#'Ê°Òéºïw4ÿªÀš=Ó6½8Ì(|:Ô˜$<EFBFBD>+}¤¯&ã»ôe0´ÿnˆ6ƒF8»`½<EFBFBD>'¿!¯ëŸSšÆn~<7E>‰sçº(ç)±¬÷Uh\
%R¸ÀÚpýyØ@2»©v³Ÿe®L\\´g»Ú\rÂl2æõ&'ÍéãXY #ùqÒEÎ×ù6Ó7 fù¿Ó+ݹ!“àI`É,¹\\†Æ€€8SÅ*¿=½“u]ùoÌú†¼<E280A0>gî13¨<33>ºn:§a\000¯ŒÀìISb§MÑÄ )L/;9cãÇRÕWù7X¨Ã\r´¹ÉyÓ67t_„}<7D>¿¶ò¢}õSg—NØ-[D%ýîˆÑ$ÀF„EÃy§÷œK}‹Õ<##P~YuŽVc(ˆØn 1 \"«&Ê£<gî¹óÄöç ffdÛõ»? ãÇåRÔ„ô&0ñÓWXÂK†anÈÔw£É2âÖª¼h~¿íså<1D>Öñæ/³÷{:ÿÜ©¤}‰HG¼+ÓÕÚ<T™)ÈFWV7>…ë6\000&5ÝÏGMÑË”Žö²bÌ<62>ž &Ç","@üE~1´ƒXê`'2ãt® ¥¼õqIpZ{h¼®;àð8Úz` ^Õ\¤²#ä,µU1lðíŸ(1¸ó¬ÿ\
í̵ÉgNìL{¢¢ÓòÀ<EFBFBD>é§ØÊõâõŽÐ¦œ»o \\PþòÒz |8~èsÊh#oÉ7*9;4Œ¹~@g»úÇwIåõZÍiï˜Ò4AÜll§ «4Y@³š§3U¢EŽéÐyØiKë<EFBFBD><EFBFBD>Ç\
ùݲæóÉŽqÌã, ;Ôµb>\000<EFBFBD>æò˜!{E¢åÉ÷ö2!`çžèÑ{væbýÙúTy2ÕOw\\nB(Ï*¬m~éˆeK>E¤¿×,Q¬|É8ì¦>[èg*%<EFBFBD>­øÌ36×ÈÑ®õ#[qíd%P­d«ËÕ©àmÎrî|j»°¡ÍiŸ6_Ãаö×ÕG9òÈÅå6X%ÂàÀd®HÎN~-ýÁÕNZÐAuÕ :º@ÎeßÕFŸ9õçCf4Tw2~¬Ìa}\r×R\rWà½Àõ_.ùG6=­k$<EFBFBD>¨£¤ToÒ|Ü$î1ëÏQ©<EFBFBD>F®ïu¨7¬ååw\
´­Yt^F;j-*œùíÃ4qy©°mvŸ\"•L{ hÚPº/@WI:E Ãy}<#—íy•ç ! ¡m„«Ö_ûØu¶µ\rRïR^³ÌÜððsÝi `Q<15>Z¶ïßaÅ?\\ž´§i ùYsX\r@5þ0©Üš²<ëǽF~­%ßrd<O¹ƒp³Üã ê#AèTêÅîœÙd¿ âlEÂߪÿñÃOªG¿]#£",false,"÷•¼ 2¾ã}yêI<Êô;»¸fÿJÃ#î-1µØ)ÑmåÚŸ£¾6!¯ ìÖ\000(‘¸³÷¸þ»Ûìè\r¢À6s.MÍÀ âϳîÛ ÄÛÈU”{MLz (fò6²m{áŠÉ®JÖ²,¥fß[Î5ðJ=ÄŒf+~œ31 ¯“yÀÞOs õÙ&ußÑ®;Âø¾ÿ½JeèÈù Ì ŸEÌ~•?ŠŠ°ÿø¶Ñ§ò“Ÿ°’]úøEÂùa»-Ç¥s“#Ó­’ì^’å÷,·Š‰±Ït|10^÷'ÒŠKÚ]ømIW\000.ld»t[ç+æqÝh@RäqfÐyŽ¢Ù}aÒêª)ëÙO”\
«|6íù.fÞŸèEoaÓe¬<EFBFBD>Æ~zq¨eJ>µßI`\\ñIëwúÉ☩Ž(p ¢áµ+ó½ =g½±)@.ÒÆs´_Bˆ<EFBFBD>O+n3šøñ¦6\¾Dç<EFBFBD>Ý(¿°ï3eOP¨×ÝøLü6æõ'Œ+7šUYdoAôLi´ýXçb§7\
<EFBFBD>aÿ¸HõàÕ!p@¤Ü\
(tN&Ì5tmó--Œ\r®$sï<”mG-–»{¼ˆ±EüÙï¡pe…²“ µAÄ(0UeÅìòYgnï [ì>5ÜߥAd­Ô@tÍ8õ³ŽZxRk«nÙÁ^ùK8S'ùi|¦=”æ²aiêWy²•Ë¹\000w(Ú9‡ÔWÒ ªú$£d¡J¢51T—š?î·¸ L„ZLû&4 ú‹Ü5Ö+Ù;Ì#ÝT1™ïpˆ¦))ò­ƒ>¨_hëfžÂwý^Ûað\rûß}ƒ…§­wT0¶ý6ÚEzB1ááósXñÑôÍ3äÚ.ÄX±Iÿ^ÁT<C381>wQÅ“+",nil,nil,false,{},"ºïLpØPhÍË{,I¬*á®,ãC#Œ ÞÝ÷Ø=²ÈŠ\"çcsPt@<1B>»GÙhq»<16>žYÀ+cŸBA—~Iã lËlßà6qÛ~KCïZ<>¥³NÑíX„.ÖÎà:ÞLù-9/ž®êX<C3AA>ð²+•fyg}gzÕ멬º»Œô™ÙHÃ¥]q<>€h:γ}L÷\" ÎÁ\\[µö4ÄŠ;\rMàk¾p!Íð‰X»ƒ¤Ö{ÇÝ•žyñTo%ú`&GA±²Ó¡<Û¨•—+9n§ê<‡?¬­îPôÄÈ£\000£L•;wÏ©ÐõâgàïËœxr«÷`ûTýÌ ÍÀìbûd2¥„šfjz…YšQöá #<23>xšß”;¬U(QŒBöE<> ý¥Nÿ·¡Á5>ԭسB`—;pèȲßÙ÷oP§{N¯!œ¯Ø®PšãŽng\"Ôzƒl¶ôU¦4Yž¤ªEøõ@”¤´&",0.13656971796256012208203856062027625739574432373046875,"E<>eÉù½Ndô&žIF>†+ã nØT•[wNF½Û«†ÔÇD\"c©¥X¬Ë÷õŽ4™¹9(ð<>½L ’Âç>I»<06>Þi7ƒÂãO¹ÙaGú&4)ÂçbÇóõŠÚ3Ó9at£˜øe|GV©gd£hŠ×¡™zamùëH-¾Þg S\
¹Kp5<EFBFBD><÷ðß_z·òQl³Úž\"F]­}T¸6 )l3¸øo°èOc~Xnž H¸ªkþl¬†Áe½aŽ)”F!ö\
RmYì²w¾ÀCh+Bp˜îöYS³ºáÝO(ÿS\
¥&wÿ/d±§ïpg2ØuI+d@·ô?Ò<EFBFBD>ÂÑââÛˆSˆ8·9ߧªFÚƒÙO̳\rkÉÔ¦;©Ä²Õ<EFBFBD>É50³é_î<EFBFBD>x~<EFBFBD>BƒdJ\
×óŒ¥<EFBFBD>ðmY%ži4QSÑA¦$ïü§Sò^oæë\
Œ>`vdþßP3-!<EFBFBD>/øp+ ÄÃ#2y=]/!œ<EFBFBD>ŽwšÞªÇ\000 <EFBFBD>Oò{5·?ÈÛrAê¯FHßhäo\000åýxÜ#GÜCã^xQ­Mvä¿·ÎNgû¾»àa¨tFŒÒÙ#ç²,5(õàßdßõ³Fðq®Ñ-Ž2ÄÛ9Øh ±m/ \\ÎHlÃ)K(AÛN2Mýz7?{¦è´?Q}ÒzÈúƒ\
ÖÒ<$Ï@žZwÞwŠWlÛî<EFBFBD>S÷ aI3Äæ.-)émÇD妼)<ei<EFBFBD>] ñ¦&%k S³ý*˜}ð·îíàÊ/¬'8<EFBFBD>Î_Ã9kìip¹“òp+<k©,\"üàÇËîHi¼§,öCâ}´œ¦ <ãwå™})z\
ºA/bîì\
â^Åa¬º<EFBFBD>äÍ­}K×ÅáÓûX6^G\"ibˆÀÊ$Ô,ÐŽ™¹,~‡ÙüÒ±鞎AÔí‰÷Wëý߬È€ôÔŽ<>: çÅXçIñÔÒé+½æ é£äø1r3>‡HGn\reífm\
Mü!æMFÌX°{LP¾Æ<EFBFBD>EÖ´<¢©­Ð`ªñé<EFBFBD>?0]˜áÙ\000{øLI ÕØ®ë¨UTõÿFß<EFBFBD>ìñÅl¾j{vQßÇ6ŽÍ7yu¼ÊÉWäYÝôFûå ÎÑú±ÁU?Ž<EFBFBD>¹","̱±ñŽ¥7ŠC¢Ý&«ß!Êâ Ñq­Šu÷SCP ÛÑÍ<EFBFBD>vH¼Þ6TÈçuX\"wj—ílhºüÞ¿àÒ¾^µH•¹<E280A2>] öù5ÇNÚ¹(Ç&#pB9PJ ©ÁW>{ôœ;­ÞŠ?¸Dg€jùŽiEȺ<C388>ÔÉ9!x.§DXU#â”Û'ü[’õ^ _¤è4½ãnSæeû”6£ØŽøûqŒ×˜ˆ2*~JÝ63÷kðÚÙDÞÀ©ø»=.^½W.ãéÆlñë®<ÈäoÀO`š(¤yéMr¤¡¡^Z´Œ><3E>S«ºDh€_LïœPºÅô4®B¦SÍGWo¦²#2ðÁ…œ{É2äJ09±Í‰k~ @ÀF“<46>Žêý4œ!g<>âì)^¶\\B\000ís:Ÿ@Ä ÒB«ò§<C3B2><E282AC>µ.®¼‘æï¿B2À0¥úÏå¾Ú¸\000†Ë",0.4478582876957293290587358569609932601451873779296875,9428,nil,nil,1244.468268439391749780043028295040130615234375,"`ÒÖO<18>RH'L\r óÅ yñ¢ê×;“a+ó4Åcìf{ùqn¿~èP<C3A8>ÙT0Ã]ô[™‡½Äzñƾ¹áƒÒDp8¿jª.)(z¶ðÏæ³,ÛÅb̊ݾQw2Jw<4A>ƒ7ù-f#V|ž\rmmô!šÏ0`1ýë»=ª3pÊ}çY\000S.„w…oƒ‡<C692>VÁ~ˆ¾i—z§B® +þe,¹Z¢1à¤FsÊú£èPefÙ#Ðpžw²L<C2B2>¾x<C2BE>$¤«ÞÿNßòVR<08>ov3?çÑ·™FXÔ}:€\\9ÎkÀÂkÆâ·pëUZ˲š²„QL¢—¥9l#sì­ºëÆ{­1B<31>é²z>2Õ\
åo½\
X¯EÅÓ¹±Rgl=-çê_)zIÜõÊô:P^ûZjS\
°Ý/Ñ6mÿX_HÒ¨%È04Â(ÍÈw¢4U\rÿß6òßTJ><EFBFBD>æÂå÷ § Y(Ñ<]&I]«)žèèF,HêB?b_§´a Ý2Ü;Y&˜O+£XŒžËâ|\"ß*<2A>†2ˆ:“(ÆS+ë${ÈÓ+TqÅæ<¨bJÊBtLȧÔ\000o-[D¨r {ž`ídG* ªt×ìé#µ<>ø¸ËõÔËøDë%Ÿ0Î=J±ž8åb\"<EFBFBD>×ù{À0Qé ¾éÕ)¢÷´BBfáz{ÆÜžU³˜ÑtµÆËëãÖªÍÚ­¢P¨ûë=k̸畅èH¹½Ó¼„ž¨guR5O\000×RPNUjÀ6D§ÉÙ-±\"Jkß'd½ÏË3\"\"ØÕrX$È°ˆùô0ÂÍ]sð¨ßÐÇ4„Õ\000·÷:Ù<10>24UôäÞîÙ°§l$—aßœ×<>Sòwd©™Ôž~²ŒWÁ=þ.aDeý o™N6&ÓïKS—ôíl“k Ãá]¿XS$Ut“ïöâ% ù<>!DÕ¹9Â%Í.Díñ&J³5 ‰-aþÁQõ¤w‡­pε݈¼Íò©¿ósNý~Ø+à×í1Ì©S>[\rÏ8•¾ØBz¦5$fNÙ<>WvA8M.j¿mý-È\
üŸ»Úâ5ZçgrÀzÈPÈ÷ºáÎN´ü¾ø^´óAêtZD[ÁÆ>3A þ?ë´\r:i\
Q'k†·^È¡Ó\"å.äJªÚ~ëáõßAá”OýYm%\\ج7tµ\
š9{6ƒ&ò","èfdîqKJ6^<EFBFBD>ªŒB®Å½åIãöJõèNýºæ )ê\\c§(ïÕµ2{ïiÄÓ_ÉG^Çò­\"˜§4ôµ—œúYÄê/z³õ ¹à|ȪÃ'qÅç6·<36>j¬DH?\\\r)‡F?}R\\62ØÿÜœ&Na@mIv%ØáÒä\\@(†Ì°Ì -hdQ@d.Ý‹|?Ëê‰Ba$áüÜI$bÕ/!N‰g ÊÌΧWKç#5pfDÑŠ&Q“#-ÜG<C39C>ñ¿ œ‡®gT|«ÇöÎýf4B8¿h‰R·.ÓG ð3ЙÃ7í@G˜=g£œGÛ[¯e­;Ü\000j0ªC9—ƒ€/‹½",1268,false,"Ž‡¢<¾Ò\"Ò<>\rFŽP\000U_½ìïÆ[®Nþê¼ãÞµk^™y¥'É$M<>%¢üâ<C3BC>쯳]][HKõ÷dªcÂCÜgk¥Œ¸C±[@”ê,•šßó÷áN@ófŒè]ð“Á³×<C2B3>BB¨û†ZVÆîAó„ÛÓwӴƧ- <>#LDúé_=,8²b<C2B2>yPÐlÕ¬?M€ó”›@4+ÌÅN\
Ij.r¾áÔMZ%ÆúÊGJù[ßœÀ<EFBFBD>ãXƒNÞ±Àœêíº´µÓ¹ü³XýHô\\ëÝÏo`MÞê¥-ÞG","ßд7Îü,àˆËfšŒÇ¸ÙÙÄ 7wY)Zùú1È ]¨æs-M¹Æî]Xmgñž¸4²<EFBFBD>CäUOBþa(q<EFBFBD>uIŠGÜx¤5æ '<EFBFBD>@b$u±¹ù <jdwùÚ÷Be>ÝâTÃî{*˜ jû1àâ™\
ê£\r«g^<EFBFBD>¾Œn:G!x[E>c5L<EFBFBD>Sû<EFBFBD>˜IÆÖ\000ŒŽH®<EFBFBD>À°£KÀbŠ#Ö34)È0ÇIÉÎâijöùݤžT-º í*´\000*\rñVãÀéÆTS0êI)Çí³eBáâÎ<\ràð\r%Ú72ô)×ér<EFBFBD>=ÆÎ(÷ïý«U@Œu\"[±/;¢=`|u“pžH‡<48>åÅU´íe¬ÝbW2¢ä¨Å?Yõ{ü3Üx¨oéFŒ1ΓqË€Öw^9Î<39>ܳ9¡ò—n<E28094>ÊJrºð¹F!‡b8Ó›ª{úäIŠÀýÄbïVù^æĨí6cÞð©\000w 8à<.Š·(o³/þwîÎM´Oõ¢†Y€v€î¹<>ðö¯{®Øê°Œ¯ª<>Ò5뇅á) <>=+oMåñ=Ü¡¸Šy¢:»é\
fÜœrd!,Ž9®ËdJV&°°*±ë0:Ó\\{#\
¿±Cm}¨òšìJûÊt¬µ¥Šßíçö^·rðÚ}¯Ài§ž\\B?2õ¦L9h}ðˆùm7.ü,ó>¸>©ÌqŸs½ú÷w<EFBFBD>§g¡ÕO&£´ŸáŽÞšø©Ø¡vI@é`ãþè[Ž<EFBFBD>Â¥0õW˜ 68îň½À`_6ªŸ ±\000°è_>x\"䨺Ù\000Ur\r«ûQ„äm¸<6D>\rØA\rÜòõ<0n^îma$ù JϤYQ‰Æ\
","ZâÀLØü}F[]stáâÚï¹%¾]~æEþþ¿¥Ô¼\"´wŠ5ìk…F>lÆêÖ<C3AA>0ñ€JðÚF¯k¢5ƒW­\rŒ™y¥À¬],rùI{G;ü‘+ÖØÛVóGø(ÊOÖØÜoR<6F>Ž.ì? åVê`<60>%\\/Q3,‰út<C3BA>#>Ðù­ii.ø|\\ä»ýÉè*¯\r†Þ^¹åBàÿÄ>•ýUBf¾q^;ÎCöÌ ´6¶Á½• w{¬º[«]?VÄþÈ#9f/br7©îÙg„úßÿ¦™[Qº;-{„ÜyLÿ³ãeãFØ]<36><30>×bè({£d¨»à,˜Yy—\r]ýð£Õ W8A£i\
0@m¼Îx®¾8¨¥8{9Ó&qÊÚúŒuÏRG\000ÅXý\000¥$Ë 6ô]w 'R(!mµ5ñ+D2LDø¤Mõ¤l‰J<E280B0>UkÆZ_#ÑhJ$lG¡ƒr¥Ç¤ò œ—Z†VpñËQ@<40>ºÁL÷S“˜Ö>žª1«GÈÙËõŠ\"f|?1̀ψ <0B>ÔãhºnÚY `Ó 9×Õ/bø•Þ7Ǭ¸' Æ qbÅà<ùH\"Y,“óÂUúX41 à궮ÞׯqÍj\\ðÃxVlÁröKÖ5Iìã' Yœ0¿\rE<EFBFBD>x¢~<“‡»¬IÔ?°9!\r2©Ãñ· /«ýkÇ™þNT«˜×I{ížuïØüjȦ.º]7:<3A>ã8ùªÑ÷ù&£Omi˜èV7^EôBy½è¨xFß²ÓÃêÌn¼Ägâgù2Õb˾¸þAŒÏ)4GoúC×äE¡Ô­„<¦¶‚ÐÁ…íÀ—ÿ#Ï+WkÞCöÂ6þÜÒåTá§ÙÏgpÎh“ž“ëµ.VÆ\rš¼û\"S¾Xo½5AΕ°Âo*ßN“sì'^¡VµhcO$_rxËçÛ¾Zß-Ù \r(œ€Ãß·}åDÜW¼ú#¤Ö$Ì@‹Ú ¸´)ÅÜÆFñŠ%©¤»È!  þ÷ÉømÎ?:N€Å( ~ÝÊD¹<44>Š«°T¿ká óØa¦]œõÞb~àûI$µÚ®`õ_µ´ÊÒÖüuÚðMøRôVîê4P³1üU¹ÖÌcÐ<63>Ÿ",7463,7066,"Î/Ϲd §€ë«›·k9>PC­Ý#<·û†*î@Ž¦`È»I§³ä_ÃP˜^èE ÆiH~dg<04>VDeGÅÅ€ÍY(<28>>‡EŽ<08>øÏöAMZ©Rêÿ—dÞÎ*îOøGwy…þ¿'”úöŠ<Cåå•Ïä,ØI ¦sùök@måÆl¥ÛŠ«Ü²@רÊë¯ù<C2AF>Ý®X'¹ÿš²õócë¹Ï<C2B9>”Z<q |H´G\\ ÷U!w3ÏÏZ‰Ïô;Åú.(æè÷w}R´î^17y“³pèÕ祷v.‡jjLe˜tL<74>lÄþ¾xíª$0#¸ä” º|¼_32Ž»<C5BD>ø|Oè§<>ÿÄ7#õ[ÛÙï|”k9óŸkZ {b \rÞ\\ Çp2oý135U)<29>1­—ìæR\ræ[ˆIh'Ķï5é^3ip»ù¡¾zOVf5áòˆîÙäw\"L\rIÄ9F®—zÉ)ã9åÝÛ¤W*ú¾`Û°èʉÌA¬Oö*/qÂÇëŒñÎÅÖ¬¡zËuÂ+Prüá\\¨ú¬Ÿ$ÁΕ„•<E2809E>†PÖ]üwØ\000CMÂn<EFBFBD>¸2dÛ^Âzƒ„HÞšdëïÁçg™çªçª…ß<E280A6>>Tì`¯ý¤<C3BD>˜½ñƒ­³kMSÀ4ýÙ¹Üv÷îxLÚØbA¼þð¹¢}Q`oÕ\"@#p“ã¥<C3A3>½^m4V[¬¢6…xAhû¦æMU\"xb9èö<1D>†ÚìôCP»æ‡Aìÿðh~—NËŸ¤íµF “Íæ€Áöıª™ò—™uˆó P¾¿õ¬tücBo¬V,ÒLñäþœ~ñ3[Ükœ`ÆsÂtä7;dèˆŬñKx%càá};¾èUZIk¼ÞàHäÄ€úÿäâ‡:¯,ú‡R^g3Ü¢òÄøL¸Ëò˜Ö\\“Ñ\\x³ä²bòß]z1»ád—„W\\|£k<C2A3>[6ôJYPÞ*­@„çžþZà~òdÕNàyºpÕñóÉ;LvÇoTXx”Ü`3Ûy<C39B>»øÍÎ\000Fˆqzdäµ°þÏ'Å?{¸ûCÖ“ÐO±X²ž¦#º ‡žÖ8œ¦_båÛ€<C39B>ë|¶/RJÿäÕO-nHÌk†5ó$ +Á²‹$˜f¥5R!ì<>t6<74>X Ñî9?6T¢ŒŠ•±—ÁsJL—â"

BIN
vendor/luabins/test/large_data.luabins vendored Normal file

Binary file not shown.

25
vendor/luabins/test/test.c vendored Normal file
View File

@ -0,0 +1,25 @@
/*
* test.c
* Luabins test suite
* See copyright notice in luabins.h
*/
#include <stdio.h>
#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;
}

25
vendor/luabins/test/test.h vendored Normal file
View File

@ -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_ */

813
vendor/luabins/test/test.lua vendored Normal file
View File

@ -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")

311
vendor/luabins/test/test_api.c vendored Normal file
View File

@ -0,0 +1,311 @@
/*
* test_api.c
* Luabins API tests
* See copyright notice in luabins.h
*/
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#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");
}

112
vendor/luabins/test/test_fwrite_api.c vendored Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

499
vendor/luabins/test/test_savebuffer.c vendored Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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();
}

130
vendor/luabins/test/test_write_api.c vendored Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 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();
}

17
vendor/luabins/test/util.c vendored Normal file
View File

@ -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");
}

14
vendor/luabins/test/util.h vendored Normal file
View File

@ -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 <stdio.h>
void fprintbuf(FILE * out, const unsigned char * b, size_t len);
#endif /* LUABINS_TEST_UTIL_H_INCLUDED_ */

175
vendor/luabins/test/write_tests.inc vendored Normal file
View File

@ -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)();

0
vendor/luabins/tmp/.keepme vendored Normal file
View File