Merge branch 'extradata'
Conflicts: src/ass_parser.cpp
This commit is contained in:
commit
d53c36e67f
72 changed files with 4913 additions and 15 deletions
16
Aegisub.sln
16
Aegisub.sln
|
@ -28,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libresrc", "build\libresrc\
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua51", "build\lua51\lua51.vcxproj", "{5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luabins", "build\luabins\luabins.vcxproj", "{A7A30702-8162-4E1A-A010-EF51B590C121}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "respack", "build\respack\respack.vcxproj", "{08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{FB8E8D19-A4D6-4181-943C-282075F49B41} = {FB8E8D19-A4D6-4181-943C-282075F49B41}
|
||||
|
@ -223,6 +225,20 @@ Global
|
|||
{5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}.Release|x64.Build.0 = Release|x64
|
||||
{5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}.Release-MinDep|Win32.ActiveCfg = Release|Win32
|
||||
{5391A8B1-9C70-4DC4-92AD-D3E34C6B803F}.Release-MinDep|x64.ActiveCfg = Release|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|x64.Build.0 = Debug|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-MinDep|Win32.ActiveCfg = Debug|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-MinDep|x64.ActiveCfg = Debug|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-Tests|Win32.ActiveCfg = Debug|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug-Tests|x64.ActiveCfg = Debug|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|Win32.Build.0 = Release|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|x64.Build.0 = Release|x64
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release-MinDep|Win32.ActiveCfg = Release|Win32
|
||||
{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release-MinDep|x64.ActiveCfg = Release|x64
|
||||
{08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{08AF2BCC-FCDD-4F0E-8B41-59A6E634F2E8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
|
|
1
Makefile
1
Makefile
|
@ -3,6 +3,7 @@ include Makefile.inc
|
|||
SUBDIRS += \
|
||||
vendor/lua \
|
||||
vendor/universalchardet \
|
||||
vendor/luabins \
|
||||
libaegisub \
|
||||
tools \
|
||||
src \
|
||||
|
|
|
@ -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>
|
||||
|
|
44
build/luabins/luabins.vcxproj
Normal file
44
build/luabins/luabins.vcxproj
Normal 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>
|
57
build/luabins/luabins.vcxproj.filters
Normal file
57
build/luabins/luabins.vcxproj.filters
Normal 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>
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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]",
|
||||
""
|
||||
};
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ enum class AssEntryGroup {
|
|||
FONT,
|
||||
GRAPHIC,
|
||||
DIALOGUE,
|
||||
EXTRADATA,
|
||||
GROUP_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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*>());
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 (...) {
|
||||
|
|
|
@ -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
4
vendor/luabins/AUTHORS
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
Luabins authors:
|
||||
----------------
|
||||
|
||||
Alexander Gladysh <agladysh@gmail.com>
|
51
vendor/luabins/BENCHMARK
vendored
Normal file
51
vendor/luabins/BENCHMARK
vendored
Normal 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
32
vendor/luabins/COPYRIGHT
vendored
Normal 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
47
vendor/luabins/HISTORY
vendored
Normal 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
40
vendor/luabins/Makefile
vendored
Normal 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
112
vendor/luabins/README.md
vendored
Normal 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
11
vendor/luabins/TODO
vendored
Normal 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
106
vendor/luabins/etc/benchmark.lua
vendored
Normal 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
30
vendor/luabins/etc/checkfmt.lua
vendored
Normal 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
90
vendor/luabins/etc/dataset.lua
vendored
Normal 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
39
vendor/luabins/etc/tolua.lua
vendored
Normal 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
16
vendor/luabins/etc/toluabins.lua
vendored
Normal 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
0
vendor/luabins/include/.keepme
vendored
Normal file
0
vendor/luabins/lib/.keepme
vendored
Normal file
0
vendor/luabins/lib/.keepme
vendored
Normal file
0
vendor/luabins/obj/.keepme
vendored
Normal file
0
vendor/luabins/obj/.keepme
vendored
Normal file
19
vendor/luabins/rockspec/luabins-0.1.1-1.rockspec
vendored
Normal file
19
vendor/luabins/rockspec/luabins-0.1.1-1.rockspec
vendored
Normal 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"
|
||||
}
|
32
vendor/luabins/rockspec/luabins-0.1.1-2.rockspec
vendored
Normal file
32
vendor/luabins/rockspec/luabins-0.1.1-2.rockspec
vendored
Normal 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/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
vendor/luabins/rockspec/luabins-0.2-1.rockspec
vendored
Normal file
35
vendor/luabins/rockspec/luabins-0.2-1.rockspec
vendored
Normal 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/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
vendor/luabins/rockspec/luabins-0.3-1.rockspec
vendored
Normal file
35
vendor/luabins/rockspec/luabins-0.3-1.rockspec
vendored
Normal 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/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
vendor/luabins/rockspec/luabins-scm-1.rockspec
vendored
Normal file
32
vendor/luabins/rockspec/luabins-scm-1.rockspec
vendored
Normal 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/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
vendor/luabins/rockspec/luabins-scm-2.rockspec
vendored
Normal file
35
vendor/luabins/rockspec/luabins-scm-2.rockspec
vendored
Normal 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
49
vendor/luabins/src/fwrite.cpp
vendored
Normal 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
37
vendor/luabins/src/fwrite.h
vendored
Normal 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
367
vendor/luabins/src/load.cpp
vendored
Normal 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
104
vendor/luabins/src/luabins.cpp
vendored
Normal 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
69
vendor/luabins/src/luabins.h
vendored
Normal 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
14
vendor/luabins/src/luaheaders.h
vendored
Normal 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
54
vendor/luabins/src/luainternals.cpp
vendored
Normal 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
53
vendor/luabins/src/luainternals.h
vendored
Normal 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
32
vendor/luabins/src/lualess.c
vendored
Normal 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
33
vendor/luabins/src/lualess.h
vendored
Normal 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
236
vendor/luabins/src/save.cpp
vendored
Normal 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
252
vendor/luabins/src/savebuffer.cpp
vendored
Normal 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
91
vendor/luabins/src/savebuffer.h
vendored
Normal 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
114
vendor/luabins/src/saveload.h
vendored
Normal 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
75
vendor/luabins/src/write.cpp
vendored
Normal 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
44
vendor/luabins/src/write.h
vendored
Normal 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
38
vendor/luabins/test/large_data.lua
vendored
Normal 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õ1Lï‘\rì{ï\\îÙÈí–×ëá¥AuVÆcYûËN,Û›l¨ ç˜C‡1O³'\
|
||||
”ÌL\
|
||||
#†kRºD-Ua™þj€—€Ä±ámД•Û)b'4…:P¦h_a¬Œ·&µy§Lùkj«LØ|ámXÏ?Uº<55>b`÷ÁÁ¤Nx²t.+{%‡æÑÓ¿Mµ,¥Àü%ÿRß<52>´@‡v+ÄzÞ8©\
|
||||
T$0Û®ÊNd÷ô$ó#Fú³ú::p<f4¶Dm`OÂ…<EFBFBD><EFBFBD>€LZÏ°RÄÔFÞøŒØ«‡æ÷OL,‘šfá\\ë`ú{áFÖ±÷(uÌnTÄû-p‚@Vz<EFBFBD>£§•5Aûžæw˜bYß9\
|
||||
×a€£ÐÔgÌØNA/ÉÐÓpf²aPH—éªðÉäú FzCO«ãP„2’³ûc‡kÉ<EFBFBD>+¯osFX6\"1ÂH¬_û²BL6uÞêpBrÜú7±iªøÂÉ/äË`§\rs`¶T—+3<>œvóx‚örº§Üe ž.σú0*=Ø‚F98›ÐdÏR\000EFxÈ<ë‚äÈç„gTê…Ãî¡ 'Ù¥÷>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ò’7ì\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…Ï(Áe‹0yÍ©oÄ£yYÍÁSâï»Û÷bFçÕo¨:ûÙ´\000§]\"Â<EFBFBD>|<7C>¥=⽬ÛÞ¤=äë%ºZÎõU§©UNse)6õ¥Å›ã¨YªÞˆ«l–A&ðE·ÅšÌkõDa›\
|
||||
ý~²V<EFBFBD>]\\_å|Rž¾yŽÎ•Ó…Zn‹'}öÂX¸ÌU6«¸ÜÁ”®R<C2AE>= \"¥}1¤ý(À¿€y‹Õ¯\
|
||||
<EFBFBD>g抨›¼JfI‡†l˜,é^<EFBFBD>†NÔÇ_Üwj^ÞQè^ù„r¶ÎÙÿU`kíŒTëâq0îx÷NUn¸³M\
|
||||
œ¬ ºï÷ºDW&1ä{7Ï]QA<EFBFBD>?¹…ŽóGÂAQ_íUnʳ[ðå?kÈmQVÛ<σÜÔ;þ*»\
|
||||
:*\rÝiõ©`߸)M\
|
||||
û[7/*º;<EFBFBD>H9ºCô.QùºïÏcO®yü&ù÷;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…GÂ@™‚‹œËHVÞWM¶j…¥qºBÇÈo–6¼gAõ*<EFBFBD>Ž¬\r+»öpÕ[½‹Å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æõ¶&'ÍéãX’Y#ùqÒEÎ×ù6’Ó7 fù¿Ó+ݹ!“àI`É,¹\\†Æ€€8SÅ*¿=½“u]ùoÌ›ú†¼<E280A0>gî13¨<33>ºn:§a\000¯ŒÀìISb§MÑÄl¾ )L/;9cãÇRÕWù7X¨Ã•\rl÷´¹ÉyÓ67t_„}<7D>¿¶ò¢}õSg—NØ-[D%ýîˆÑ$ÀF„EÃy§÷œK}‹Õ<##P~YuŽVc(ˆØn1 \"«&Ê£<gî¹óÄöçffdÛõ»?ãÇåRÔ„ô&0ñÓWXÂK†anÈÔw£É2âÖª¼h~¿íså<1D>Öñæ/³÷{:ÿÜ©¤}‰HG¼+ÓÕÚ<T™)ÈFWV7>…ë6\000&5ÝÏG‚MÑË”Žö²bÌ<62>ž &Ç","@üE~‚1´ƒXê`'2ãt® “¥¼õqI“’pZ{h¼®;–àð8Úz`^Õ\rÞ¤²›™#ä,µU‡1lð퀟(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>\000MÜ<EFBFBD>æ‡ò˜!{E¢¶å†É÷‡ö—‹2!`ç„žèÑ{væbýÙúTy2™’ÕOw\\nãnB(Ï*¬m~éˆeK…>E¤’¿×,Q¬|É•8ì¦>[èg*—%’<EFBFBD>øÌ36×ÈÑ®õ#[qíd%Pd«–ËÕ©àmÎrî|j»°¡Í‡iŸ6_Òаö×ÕG…9òÈÅå6“X%ÂàÀ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©°Vþ•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“#Ó’ì^’ådŒ÷,·Š‰±‚Ït|10‚^÷'ÒŠKÚ]ømIW\000.ld»t[ç+æqÝh@Räq‚fÐyŽ¢Ù}aÒêª)ëÙ–O”\
|
||||
«|6‘íù.fÞŸèEoaÓe¬<EFBFBD>Æ~zq¨eJ>µßI`\\ñI”ëwúÉâ†DᘩŽ(p¢áµ+ó½=g½±Qú)KÄ@.ÒÆs´_Bˆ<EFBFBD>O+n3šøñ¦6\ró¾Dç<EFBFBD>Ý(¿°ï3eOP¨×ÝøLü6æõ'Œ+7šUYdoAôLi´ýXçb§7\
|
||||
<EFBFBD>aÿ¸HõàÕ!p@lɤÜ\
|
||||
™(tN&Ì5‰tm“ó‚–uä–--Œ\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ˆ¦))òƒ>¨dÝ_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§KÖê<‡?¬X¦îPôÄÈ£\000£L•;wÏ©ÐõâgàïËœxr«÷`ûTýÌ ÍÀìbûd2¥„šfjz…YšQöá #<23>xšß”;¬U(QŒBöE<>w¯ý¥Nÿ·¡Á5>ÔسB`—;pèȲßÙ÷oP§{N¯!œ¯Ø®PšãŽn‘g\"Ôzƒl¶ôU¦4Yž¤ªEøõ@”¤Bô´&",0.13656971796256012208203856062027625739574432373046875,"E<>eÉù½N›d‚ô&ž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̳\r‰kÉÔYǦ;©‚IJÕLê<EFBFBD>†É50³é_€î<EFBFBD>x~<EFBFBD>Bƒd›J\
|
||||
×󌛥bç<EFBFBD>ðmY%ži4QS”ÑA¦_º$ïü§S—ò^oæë\
|
||||
ŒNò>`vdþß™P3-!uÔ<EFBFBD>/øp+ ÄÓ#2y=]/!œ<EFBFBD>—ŽwšÞªÇ\000 ›<EFBFBD>O”ò{5·?ÈÛrAê¯FHßhäo\000åýx€Ü#GÜCã^’xQMvä¿·ÎoþNgû¾gà»àa—¨tFŒÒÙ#ç²,5(õàßdßõ³Fðq®Ñ-Ž2Ä‘Û9Øh±m/™ \\ÎHlÃ)K(AÛN2Mýz‹7?xõ{„¦è´?Q}ÒzÈúƒ\
|
||||
ÖÒ<$Ï@žZwÞwŠWlÛî<EFBFBD>S÷ aI3Äæ.Gð-)émÇD妼pý)vÙ<ei<EFBFBD>] ñ¦&%kS³ýYÍ*‚¶˜Iú}ð·îíàdÆÊ/¬'8<EFBFBD>Î_Ã9kìip¹“òp+<k©,\"—üàÇËîHi¼§,öCâ}´œ¦<ãwå™})›z\
|
||||
ºA…/bîì\
|
||||
â^Å›a¬ºmè<EFBFBD>äÍ}K×ÅáÓûX6^G\"ibˆÀÊ$Ô,ÐŽ™¹,~‡ÙüÒ±—’鞎AÔí‰÷Wëý߬ȀôÔŽ<>:çÅXçIñÔÒé+½æi®é£äø1r3>‡HGn\reífm\
|
||||
M¶ü!‰æMFÌX°{hšL“P¾Æ<EFBFBD>EÖ´<¢‚©Ð`ªñé<EFBFBD>?0]˜áÙ\000{øLIÕØQä®ë¨„•UTõÿFß<EFBFBD>…ìñÅl¾j{vQßÇ6ŽÍ7yu¼ÊÉWäYÝôFûåRÊ„ÎÑú±ÁU?Ž<EFBFBD>¹IÈ","Ì—±±ñŽ¥7‰ŠC¢Ý&«ß!Ê‘â ÑqŠu÷SCP ÛÑÍ<EFBFBD>vH¼ÞVã‰6TÈçu™X\"#Î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«ºD–h€_LïœPºÅô4®B¦SÍGWo¦²#2ðÁ…œ{É2äJ‘09±Í‰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+ó4CÇÅcìf{ùqn¿~èP<C3A8>ÙT0Ã]ô[™‡½Äzñƾ¹áƒÒDp8¿jª.)(z¶ðÏæ³,ÛÅb̊ݾQ›w2Jw<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 L©<08>ov3?çÑ·™FX–Ô}:€\\9ÎkÀÂkÆâ·pëUZ˲š²„QL¢—¥9l#sìºëÆ{1B<31>é²z>2Õ\
|
||||
åo½iÀ\
|
||||
X¯EÅÓ¹±Rgl=-çê_)zIÜõ‡Ê’ô:P^ûZjS\
|
||||
°ÝjÊ/Ñ6mÿX_HÒ¨%È04’Â(͇Èmòw¢4U\rÿ…ß6òßTJ><EFBFBD>æÂå÷wØ Dë§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$—gÜ ›aßœ×<>Sòwd©™Ôž~²ŒWÁ=þ.a–Deý 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ý-È\
|
||||
üŸ»Úâ5€ZçgrÀ‡zÈPÈ÷ºá¶ÎN´ü¾ø^´óAêtZD[Á¶Æ>3A„ þ?ë´\r:i\
|
||||
Q'k†·^È¡Ó\"å.ä›JªÚ~ëáõßAá”OýYm%\\ج7tµ\
|
||||
—š9{6ƒ&ò","èf•dîq‰KJ6^<EFBFBD>ªŒB®Å½åIãöJõèNýº”æ )ê„\\c§DÁ(ïÕµ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;Ücü\000j0€ªC9—ƒ€/‹½",1268,false,"Ž‡¢<¾Ò\"Ò<>Eã\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ù[ß”œÀhÙ<EFBFBD>ãXƒNÞ±Àœ“•êíº´µÓ¹ü³XýHô\\ëÝÏo`MÞê¥sÕ“-ÞG","ßд7Îü,àˆËfšŒÇ¸ÙÙ–Ä ™7wY)Zùú1È]¨æs-M¹Æ“î]Xmgñ€žiÚ¸“4²<EFBFBD>CäUOBþa(q<EFBFBD>u€IŠGÜx¤5æ'f©<EFBFBD>@b$u±¹ù <jdwùÚ÷Be>ÝâTÃî{*˜jû1àâ™\
|
||||
ê£Fï\r«g†^Jë<EFBFBD>iÈ€¾Œn:¶G!x[›E>c5L<EFBFBD>S•û<EFBFBD>€˜IÆÖ‡\000ŒŽH®<EFBFBD>À°£KÀbŠ#—Ö34)È0ÇIÉΓâ”ij•öùݤ‰žT-º í*´\000Dé*\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Þð©\000w8’à<.Š·(o³/þw‘î΋M´Oõ¢†Y€v€î¹<>ðö¯{®Øê°Œ¯ª<>Ò5뇅á):ª<>=+oMåñ=Ü¡¸Šy¢:»é\
|
||||
f‡Üœrd!SŽ,Ž9®ËdJV&°°*±ë0mÕ:Ó\\pÏ{’#\
|
||||
¿±Cm}¨‹–òšìJûÊt¬µ¥Šßíçö^·rðÚ}¯‹Ài§ž\\B‹uŒ†?2õ¦L€†9h}—ðˆùm7….TŽ—ü,ó>¸iË>©Ì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[’]s€táâ™Úï¹%¾]~æEþþYü¿¥Ô¼\"´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ÄþÈ#9–f/br7©îÙg„úßÿ¦™[Qº;-{„ÜyLÿ³ãeãFØ]‚ 6é<36>0È<30>×bè({£d¨»à,˜Yy—\r]ýð£ÕW8A£i\
|
||||
0@miè¼Î‘x®¾8¨•¥8{9Ó&qÊÚúŒ„uÏRG\000ÅXý\000“¥$Ë 6ô]w 'R(!mµ5ñ+D2LDø¤Mõ¤l‰J<E280B0>UkÆZ_#ÑhJ$‘l‘G¡ƒr¥Ç¤òœ—Z’;ƆVpñËQ@<40>º‹ÁL÷S“˜Ö>žª1«GÈÙËõŠ\"f|?1̀ψ<0B>Ôãh›ºnÚY`Ó 9×Õ/bø•Þ7Ǭ¸–4Ã' ÆqbÅà<ùH\"Y,“óÂUúX41 à궮Þué‘ׯqÍj\\ðÃxVlÁröK’Ö5Iìã'Yœ0¿\rE<EFBFBD>x¢~<›“‡»¬IÔ?°Uú9!\r’2©Ãñ· /«ýkÇ™þNT«˜)Ê×I{ížuïØ–üjȦ.º]7:<3A>ã8ùªÑ÷ù&£‘Omi˜èV7^EôBy½è¨xFß²ÓÃêÌn¼Ägâgù2Õb˾¸þAŒÏ)4GoúC×äE¡Ô„<¦¶‚ÐÁ…íÀ—ÿ#Ï+W›kÞ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 ÂQƧ€ë«›·k9>PCÝ#<·û†*î@Ž¦`È»I§³ä_ÃP˜^èEÆiH~dg<04>VDeGÅÅ€ÍY(<28>>‡EŽGí<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óŸk‚Z {b\rÞ\\ Çp2oý135U)<29>1€—ìæ‹‹R\ræ[ˆIh–'Ķï5é^3’ip»ù¡¾zOVf5áòˆîÙäw\"L\rIÄ9F®—zÉ)ã9åÝÛ¤W*ú¾`Û°èʉÌA¬Oö*/qÂÇëŒñÎÅÖ¬¡zËuÂ+Prüá\\¨ú¬Ÿ$ÁΕ„•<E2809E>†PÖ]üwØ\000CMÂn<EFBFBD>5ƒ¸2dÛ^Âzƒ„HÞšdëïÁçg™çªçª…ß<E280A6>>Tì`f㛯ý¤<C3BD>˜½ñƒ³kMSÀ4ýÙ¹Üv÷îxLÚØbA¼þð¹¢}Q`oÕ\"@#p“ã¥<C3A3>½^m4V[¬¢6…xAhû¦æMU\"xb9èö<1D>†ÚìôCP»æ‡Aìÿ‚ðh~—NËŸ¤íµPîF“Íæ€Áöıª™ò—™uˆó P¾¿õ¬tücBo¬V,ÒLñäþœ~ñ3g¼[Ükœ`ÆsÂt‹ä7;dèˆŬñKx%càá};¾èUZIk¼ÞàHäÄ€úÿäâ‡:¯,ú‡R^g3Ü¢òÄøL¸Ëò˜Ö\\“Ñ\\x³ä²bòß]z1»ád—„W\\|£k<C2A3>[6‚ôJYPÞ*VÝ‘@„çžþ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
BIN
vendor/luabins/test/large_data.luabins
vendored
Normal file
Binary file not shown.
25
vendor/luabins/test/test.c
vendored
Normal file
25
vendor/luabins/test/test.c
vendored
Normal 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
25
vendor/luabins/test/test.h
vendored
Normal 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
813
vendor/luabins/test/test.lua
vendored
Normal 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
311
vendor/luabins/test/test_api.c
vendored
Normal 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
112
vendor/luabins/test/test_fwrite_api.c
vendored
Normal 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
499
vendor/luabins/test/test_savebuffer.c
vendored
Normal 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
130
vendor/luabins/test/test_write_api.c
vendored
Normal 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
17
vendor/luabins/test/util.c
vendored
Normal 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
14
vendor/luabins/test/util.h
vendored
Normal 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
175
vendor/luabins/test/write_tests.inc
vendored
Normal 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
0
vendor/luabins/tmp/.keepme
vendored
Normal file
Loading…
Reference in a new issue