mirror of
https://github.com/mariiaan/minipp.git
synced 2026-05-14 10:11:17 +02:00
Improve error codes
This commit is contained in:
@@ -41,6 +41,23 @@ namespace minipp
|
|||||||
InvalidDataType = -6,
|
InvalidDataType = -6,
|
||||||
FormatError = -7,
|
FormatError = -7,
|
||||||
ArrayDataTypeInconsistency = -8,
|
ArrayDataTypeInconsistency = -8,
|
||||||
|
BadEscapeSequence = -9,
|
||||||
|
UnknownEscapeSequence = -10,
|
||||||
|
UnescapedStringValue = -11,
|
||||||
|
ValueEmpty = -12,
|
||||||
|
IntegerValueInvalid = -13,
|
||||||
|
IntegerValueOutOfRange = -14,
|
||||||
|
IntegerStyleInvalid = -15,
|
||||||
|
FloatValueInvalid = -16,
|
||||||
|
BooleanValueInvalid = -17,
|
||||||
|
ArrayNotEnclosed = -18,
|
||||||
|
ArrayBracketsInbalanced = -19,
|
||||||
|
InvalidName = -20,
|
||||||
|
SectionExpectedClosingBracket = -21,
|
||||||
|
EmptySectionName = -22,
|
||||||
|
KeyValuePairNotInSection = -23,
|
||||||
|
ExpectedKeyValuePair = -24,
|
||||||
|
KeyEmpty = -25,
|
||||||
|
|
||||||
/* OK Codes */
|
/* OK Codes */
|
||||||
Success = +1,
|
Success = +1,
|
||||||
@@ -72,7 +89,7 @@ namespace minipp
|
|||||||
const std::vector<std::string>& GetComments() const noexcept { return m_comments; }
|
const std::vector<std::string>& GetComments() const noexcept { return m_comments; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<Value> ParseValue(std::string value);
|
static std::unique_ptr<Value> ParseValue(std::string value, EResult* result = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Values
|
class Values
|
||||||
@@ -230,15 +247,19 @@ namespace minipp
|
|||||||
EResult SetValue(const std::string& name, std::unique_ptr<ValueDataType> value, bool allowOverwrite = false) noexcept
|
EResult SetValue(const std::string& name, std::unique_ptr<ValueDataType> value, bool allowOverwrite = false) noexcept
|
||||||
{
|
{
|
||||||
static_assert(std::is_base_of<Value, ValueDataType>::value, "ValueDataType must be a subclass of Value");
|
static_assert(std::is_base_of<Value, ValueDataType>::value, "ValueDataType must be a subclass of Value");
|
||||||
|
bool overwritten = false;
|
||||||
|
|
||||||
if (m_values.find(name) != m_values.end())
|
if (m_values.find(name) != m_values.end())
|
||||||
if (!allowOverwrite)
|
if (!allowOverwrite)
|
||||||
return EResult::KeyAlreadyPresent;
|
return EResult::KeyAlreadyPresent;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
delete m_values[name];
|
delete m_values[name];
|
||||||
|
overwritten = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_values[name] = value.release();
|
m_values[name] = value.release();
|
||||||
return EResult::Success;
|
return overwritten ? EResult::ValueOverwritten : EResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueDataType>
|
template<typename ValueDataType>
|
||||||
@@ -268,7 +289,7 @@ namespace minipp
|
|||||||
static minipp::EResult WriteSection(const Section* section, std::ofstream& ofs, std::string partTreeName) noexcept;
|
static minipp::EResult WriteSection(const Section* section, std::ofstream& ofs, std::string partTreeName) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EResult Parse(const std::string& path) noexcept;
|
EResult Parse(const std::string& path, bool additional = false) noexcept;
|
||||||
EResult Write(const std::string& path) const noexcept;
|
EResult Write(const std::string& path) const noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -312,7 +333,7 @@ namespace minipp
|
|||||||
|
|
||||||
#define PP_COUT_SYNTAX_ERROR(line, msg) PP_COUT("Error in line " << line << ": " << msg)
|
#define PP_COUT_SYNTAX_ERROR(line, msg) PP_COUT("Error in line " << line << ": " << msg)
|
||||||
|
|
||||||
std::unique_ptr<minipp::MiniPPFile::Value> minipp::MiniPPFile::Value::ParseValue(std::string value)
|
std::unique_ptr<minipp::MiniPPFile::Value> minipp::MiniPPFile::Value::ParseValue(std::string value, EResult* result)
|
||||||
{
|
{
|
||||||
char valueFirstChar = value.front();
|
char valueFirstChar = value.front();
|
||||||
char valueLastChar = value.back();
|
char valueLastChar = value.back();
|
||||||
@@ -381,7 +402,7 @@ minipp::EResult minipp::MiniPPFile::Values::StringValue::Parse(const std::string
|
|||||||
if (i + 1 >= str.size())
|
if (i + 1 >= str.size())
|
||||||
{
|
{
|
||||||
PP_COUT("Syntax error: '\\' at end of string");
|
PP_COUT("Syntax error: '\\' at end of string");
|
||||||
return EResult::FormatError;
|
return EResult::BadEscapeSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (str[i + 1])
|
switch (str[i + 1])
|
||||||
@@ -403,12 +424,12 @@ minipp::EResult minipp::MiniPPFile::Values::StringValue::Parse(const std::string
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PP_COUT("Syntax error: Unknown escape sequence '\\" << str[i + 1] << "'");
|
PP_COUT("Syntax error: Unknown escape sequence '\\" << str[i + 1] << "'");
|
||||||
return EResult::FormatError;
|
return EResult::UnknownEscapeSequence;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
else if (str[i] == '"')
|
else if (str[i] == '"')
|
||||||
return EResult::FormatError;
|
return EResult::UnescapedStringValue;
|
||||||
else
|
else
|
||||||
m_value.push_back(str[i]);
|
m_value.push_back(str[i]);
|
||||||
}
|
}
|
||||||
@@ -444,6 +465,7 @@ minipp::EResult minipp::MiniPPFile::Values::StringValue::ToString(std::string& d
|
|||||||
sanitizedValue.insert(i, 1, '\\');
|
sanitizedValue.insert(i, 1, '\\');
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -480,7 +502,7 @@ minipp::EResult minipp::MiniPPFile::Values::IntValue::Parse(const std::string& s
|
|||||||
if (!Tools::IsIntegerDecimal(sanitizedValue))
|
if (!Tools::IsIntegerDecimal(sanitizedValue))
|
||||||
{
|
{
|
||||||
PP_COUT("Invalid decimal integer value: " << sanitizedValue);
|
PP_COUT("Invalid decimal integer value: " << sanitizedValue);
|
||||||
return EResult::FormatError;
|
return EResult::IntegerValueInvalid;
|
||||||
}
|
}
|
||||||
m_value = std::stoll(sanitizedValue);
|
m_value = std::stoll(sanitizedValue);
|
||||||
m_style = EIntStyle::Decimal;
|
m_style = EIntStyle::Decimal;
|
||||||
@@ -489,12 +511,12 @@ minipp::EResult minipp::MiniPPFile::Values::IntValue::Parse(const std::string& s
|
|||||||
catch (const std::invalid_argument&)
|
catch (const std::invalid_argument&)
|
||||||
{
|
{
|
||||||
PP_COUT("Invalid integer value: " << sanitizedValue);
|
PP_COUT("Invalid integer value: " << sanitizedValue);
|
||||||
return EResult::FormatError;
|
return EResult::IntegerValueInvalid;
|
||||||
}
|
}
|
||||||
catch (const std::out_of_range&)
|
catch (const std::out_of_range&)
|
||||||
{
|
{
|
||||||
PP_COUT("Integer value out of range: " << sanitizedValue);
|
PP_COUT("Integer value out of range: " << sanitizedValue);
|
||||||
return EResult::FormatError;
|
return EResult::IntegerValueOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
@@ -534,7 +556,7 @@ minipp::EResult minipp::MiniPPFile::Values::IntValue::ToString(std::string& dest
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
PP_COUT("Invalid integer style.");
|
PP_COUT("Invalid integer style.");
|
||||||
return EResult::FormatError;
|
return EResult::IntegerStyleInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
@@ -549,7 +571,7 @@ minipp::EResult minipp::MiniPPFile::Values::BooleanValue::Parse(const std::strin
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PP_COUT("Invalid boolean value: " << str << " (may only contain lowercase true and false)");
|
PP_COUT("Invalid boolean value: " << str << " (may only contain lowercase true and false)");
|
||||||
return EResult::FormatError;
|
return EResult::BooleanValueInvalid;
|
||||||
}
|
}
|
||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
}
|
}
|
||||||
@@ -561,8 +583,17 @@ minipp::EResult minipp::MiniPPFile::Values::BooleanValue::ToString(std::string&
|
|||||||
}
|
}
|
||||||
|
|
||||||
minipp::EResult minipp::MiniPPFile::Values::FloatValue::Parse(const std::string& str) noexcept
|
minipp::EResult minipp::MiniPPFile::Values::FloatValue::Parse(const std::string& str) noexcept
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
m_value = std::stod(str);
|
m_value = std::stod(str);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
PP_COUT("Invalid float value: " << str);
|
||||||
|
return EResult::FloatValueInvalid;
|
||||||
|
}
|
||||||
|
|
||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +634,7 @@ minipp::EResult minipp::MiniPPFile::Values::ArrayValue::Parse(const std::string&
|
|||||||
if (i + 1 >= str.size())
|
if (i + 1 >= str.size())
|
||||||
{
|
{
|
||||||
PP_COUT("Syntax error: Bad escape sequence: '\\' at end of string");
|
PP_COUT("Syntax error: Bad escape sequence: '\\' at end of string");
|
||||||
return EResult::FormatError;
|
return EResult::BadEscapeSequence;
|
||||||
}
|
}
|
||||||
currentElement += c;
|
currentElement += c;
|
||||||
currentElement += str[i + 1];
|
currentElement += str[i + 1];
|
||||||
@@ -637,7 +668,7 @@ minipp::EResult minipp::MiniPPFile::Values::ArrayValue::Parse(const std::string&
|
|||||||
if (bracketCounter < 0)
|
if (bracketCounter < 0)
|
||||||
{
|
{
|
||||||
PP_COUT("Array brackets are not balanced. (One ] too much or encountered too early)");
|
PP_COUT("Array brackets are not balanced. (One ] too much or encountered too early)");
|
||||||
return EResult::FormatError;
|
return EResult::ArrayBracketsInbalanced;
|
||||||
}
|
}
|
||||||
else if (bracketCounter >= 1)
|
else if (bracketCounter >= 1)
|
||||||
currentElement += c;
|
currentElement += c;
|
||||||
@@ -655,7 +686,7 @@ minipp::EResult minipp::MiniPPFile::Values::ArrayValue::Parse(const std::string&
|
|||||||
if (bracketCounter != 0) // will always be a positive value because negative values are caught earlier
|
if (bracketCounter != 0) // will always be a positive value because negative values are caught earlier
|
||||||
{
|
{
|
||||||
PP_COUT("Array brackets are not balanced. (Missing " << bracketCounter << " closing brackets)");
|
PP_COUT("Array brackets are not balanced. (Missing " << bracketCounter << " closing brackets)");
|
||||||
return EResult::FormatError;
|
return EResult::ArrayBracketsInbalanced;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentElement.empty())
|
if (!currentElement.empty())
|
||||||
@@ -663,11 +694,12 @@ minipp::EResult minipp::MiniPPFile::Values::ArrayValue::Parse(const std::string&
|
|||||||
size_t lastTypeIdHash = 0;
|
size_t lastTypeIdHash = 0;
|
||||||
bool hasTypeHash = false;
|
bool hasTypeHash = false;
|
||||||
|
|
||||||
|
EResult result;
|
||||||
for (auto& elem : elements)
|
for (auto& elem : elements)
|
||||||
{
|
{
|
||||||
auto parsed = ParseValue(elem);
|
auto parsed = ParseValue(elem, &result);
|
||||||
if (parsed == nullptr)
|
if (parsed == nullptr)
|
||||||
return EResult::FormatError;
|
return result;
|
||||||
|
|
||||||
if (!hasTypeHash)
|
if (!hasTypeHash)
|
||||||
{
|
{
|
||||||
@@ -774,7 +806,7 @@ minipp::EResult minipp::MiniPPFile::WriteSection(const Section* section, std::of
|
|||||||
if (!Tools::IsNameValid(pair.first))
|
if (!Tools::IsNameValid(pair.first))
|
||||||
{
|
{
|
||||||
PP_COUT("Invalid name for key: " << pair.first);
|
PP_COUT("Invalid name for key: " << pair.first);
|
||||||
return EResult::FormatError;
|
return EResult::InvalidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& comment : pair.second->m_comments)
|
for (const auto& comment : pair.second->m_comments)
|
||||||
@@ -797,7 +829,7 @@ minipp::EResult minipp::MiniPPFile::WriteSection(const Section* section, std::of
|
|||||||
if (!Tools::IsNameValid(pair.first))
|
if (!Tools::IsNameValid(pair.first))
|
||||||
{
|
{
|
||||||
PP_COUT("Invalid name for section: " << pair.first);
|
PP_COUT("Invalid name for section: " << pair.first);
|
||||||
return EResult::FormatError;
|
return EResult::InvalidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& comment : pair.second->m_comments)
|
for (const auto& comment : pair.second->m_comments)
|
||||||
@@ -812,8 +844,15 @@ minipp::EResult minipp::MiniPPFile::WriteSection(const Section* section, std::of
|
|||||||
return EResult::Success;
|
return EResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
minipp::EResult minipp::MiniPPFile::Parse(const std::string& path) noexcept
|
minipp::EResult minipp::MiniPPFile::Parse(const std::string& path, bool additional) noexcept
|
||||||
{
|
{
|
||||||
|
if (!additional)
|
||||||
|
{
|
||||||
|
m_rootSection.m_comments.clear();
|
||||||
|
m_rootSection.m_values.clear();
|
||||||
|
m_rootSection.m_subSections.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::ifstream ifs;
|
std::ifstream ifs;
|
||||||
ifs.open(path);
|
ifs.open(path);
|
||||||
if (!ifs.is_open())
|
if (!ifs.is_open())
|
||||||
@@ -845,14 +884,14 @@ minipp::EResult minipp::MiniPPFile::Parse(const std::string& path) noexcept
|
|||||||
if (lastChar != ']')
|
if (lastChar != ']')
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected ']' at the end of the line.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected ']' at the end of the line.");
|
||||||
return EResult::FormatError;
|
return EResult::SectionExpectedClosingBracket;
|
||||||
}
|
}
|
||||||
std::string sectionPathStr = currentLine.substr(1, currentLine.size() - 2);
|
std::string sectionPathStr = currentLine.substr(1, currentLine.size() - 2);
|
||||||
Tools::StringTrim(sectionPathStr);
|
Tools::StringTrim(sectionPathStr);
|
||||||
if (sectionPathStr.empty())
|
if (sectionPathStr.empty())
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected section path. Found empty section begin notation.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected section path. Found empty section begin notation.");
|
||||||
return EResult::FormatError;
|
return EResult::EmptySectionName;
|
||||||
}
|
}
|
||||||
// Create section tree
|
// Create section tree
|
||||||
Section* ubSection = &m_rootSection;
|
Section* ubSection = &m_rootSection;
|
||||||
@@ -865,14 +904,14 @@ minipp::EResult minipp::MiniPPFile::Parse(const std::string& path) noexcept
|
|||||||
if (!Tools::IsNameValid(sectionName))
|
if (!Tools::IsNameValid(sectionName))
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Invalid section name. (\"" << sectionName << "\") May only contain [a - z][A - Z][0 - 9] and _.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Invalid section name. (\"" << sectionName << "\") May only contain [a - z][A - Z][0 - 9] and _.");
|
||||||
return EResult::FormatError;
|
return EResult::InvalidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ubSection->SetSubSection(sectionName, std::make_unique<Section>(), false);
|
result = ubSection->SetSubSection(sectionName, std::make_unique<Section>(), false);
|
||||||
if (result == EResult::SectionAlreadyPresent && i == sectionPath.size() - 1)
|
if (result == EResult::SectionAlreadyPresent && i == sectionPath.size() - 1)
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "All (sub-) sections may only be defined once.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "All (sub-) sections may only be defined once.");
|
||||||
return EResult::FormatError;
|
return EResult::SectionAlreadyPresent;
|
||||||
}
|
}
|
||||||
ubSection->GetSubSection(sectionName, &ubSection);
|
ubSection->GetSubSection(sectionName, &ubSection);
|
||||||
}
|
}
|
||||||
@@ -884,14 +923,14 @@ minipp::EResult minipp::MiniPPFile::Parse(const std::string& path) noexcept
|
|||||||
if (currentSection == nullptr)
|
if (currentSection == nullptr)
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected section begin before key-value pair.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected section begin before key-value pair.");
|
||||||
return EResult::FormatError;
|
return EResult::KeyValuePairNotInSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t keyValueDelimiterIndex = Tools::FirstIndexOf(currentLine, '=');
|
int64_t keyValueDelimiterIndex = Tools::FirstIndexOf(currentLine, '=');
|
||||||
if (keyValueDelimiterIndex == -1)
|
if (keyValueDelimiterIndex == -1)
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected '=' in line.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected '=' in line.");
|
||||||
return EResult::FormatError;
|
return EResult::ExpectedKeyValuePair;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto keyValuePair = Tools::SplitInTwo(currentLine, keyValueDelimiterIndex);
|
auto keyValuePair = Tools::SplitInTwo(currentLine, keyValueDelimiterIndex);
|
||||||
@@ -901,24 +940,24 @@ minipp::EResult minipp::MiniPPFile::Parse(const std::string& path) noexcept
|
|||||||
if (keyValuePair.first.empty())
|
if (keyValuePair.first.empty())
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected key in line.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Expected key in line.");
|
||||||
return EResult::FormatError;
|
return EResult::KeyEmpty;
|
||||||
}
|
}
|
||||||
if (!Tools::IsNameValid(keyValuePair.first))
|
if (!Tools::IsNameValid(keyValuePair.first))
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Invalid key name. (\"" << keyValuePair.first << "\") May only contain [a - z][A - Z][0 - 9] and _.");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Invalid key name. (\"" << keyValuePair.first << "\") May only contain [a - z][A - Z][0 - 9] and _.");
|
||||||
return EResult::FormatError;
|
return EResult::InvalidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyValuePair.second.empty())
|
if (keyValuePair.second.empty())
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Empty keys are not allowed");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Empty keys are not allowed");
|
||||||
return EResult::FormatError;
|
return EResult::ValueEmpty;
|
||||||
}
|
}
|
||||||
auto parsedValue = Value::ParseValue(keyValuePair.second);
|
auto parsedValue = Value::ParseValue(keyValuePair.second);
|
||||||
if (parsedValue == nullptr)
|
if (parsedValue == nullptr)
|
||||||
{
|
{
|
||||||
PP_COUT_SYNTAX_ERROR(lineCounter, "Invalid value");
|
PP_COUT_SYNTAX_ERROR(lineCounter, "Invalid value");
|
||||||
return EResult::FormatError;
|
return EResult::InvalidName;
|
||||||
}
|
}
|
||||||
parsedValue->m_comments = commentBuffer;
|
parsedValue->m_comments = commentBuffer;
|
||||||
commentBuffer.clear();
|
commentBuffer.clear();
|
||||||
|
|||||||
2
minipp/simple.mini
Normal file
2
minipp/simple.mini
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[game]
|
||||||
|
what=["test\t\\yeah", "hai"]
|
||||||
@@ -8,7 +8,7 @@ int main()
|
|||||||
EResult result;
|
EResult result;
|
||||||
|
|
||||||
MiniPPFile file;
|
MiniPPFile file;
|
||||||
result = file.Parse("test.mini");
|
result = file.Parse("simple.mini");
|
||||||
|
|
||||||
auto& root = file.GetRoot();
|
auto& root = file.GetRoot();
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ completionPercentage = 50.0f
|
|||||||
is_completed = false
|
is_completed = false
|
||||||
testargs = ["this is a \\\"test\"", "this is\n the next line"]
|
testargs = ["this is a \\\"test\"", "this is\n the next line"]
|
||||||
testTestArg = [["yeah", "new\nline"], ["hallo\ttest\n\\\\"]]
|
testTestArg = [["yeah", "new\nline"], ["hallo\ttest\n\\\\"]]
|
||||||
|
testEmpty = []
|
||||||
|
|
||||||
# This section is about
|
# This section is about
|
||||||
# the settings of a game window
|
# the settings of a game window
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
[game]
|
[game]
|
||||||
|
testEmpty = []
|
||||||
name = "Test Game\nNext Line"
|
name = "Test Game\nNext Line"
|
||||||
testTestArg = [["yeah", "new\nline"], ["hallo\ttest\n\\\\"]]
|
testTestArg = [["yeah", "new\nline"], ["hallo\ttest\n\\\\"]]
|
||||||
completionPercentage = 50.000000
|
completionPercentage = 50.000000
|
||||||
|
|||||||
Reference in New Issue
Block a user