diff --git a/pglablib/codebuilder/DefaultConfigs.cpp b/pglablib/codebuilder/DefaultConfigs.cpp index da1eba2..227ca22 100644 --- a/pglablib/codebuilder/DefaultConfigs.cpp +++ b/pglablib/codebuilder/DefaultConfigs.cpp @@ -65,6 +65,7 @@ for (auto row: result) { return t; } + std::shared_ptr buildPglabCppLanguageConfig() { auto config = std::make_shared(); diff --git a/pglablib/codebuilder/StringEscapeRule.cpp b/pglablib/codebuilder/StringEscapeRule.cpp new file mode 100644 index 0000000..a483972 --- /dev/null +++ b/pglablib/codebuilder/StringEscapeRule.cpp @@ -0,0 +1,8 @@ +#include "StringEscapeRule.h" + +/** + */ +QString convert(QStringRef in, ConvertToNumericEscape conversion, NumericEscapeFormat format, QString prefix) +{ + return ""; +} diff --git a/pglablib/codebuilder/StringEscapeRule.h b/pglablib/codebuilder/StringEscapeRule.h new file mode 100644 index 0000000..a0ea1f5 --- /dev/null +++ b/pglablib/codebuilder/StringEscapeRule.h @@ -0,0 +1,47 @@ +#ifndef STRINGESCAPERULE_H +#define STRINGESCAPERULE_H + +#include +#include + +enum class ConvertToNumericEscape { + Utf8, ///< Generates upto four escapes for 4 utf8 chars + Utf16, ///< Generates upto four escapes for 2 utf16 chars + Utf32, ///< Generates a single escape for the unicode codepoint +}; + + +enum class NumericEscapeFormat { + Decimal, + HexUpper, + HexLower +}; + +class CharToNumericConversion { +public: + ConvertToNumericEscape m_toNumericEscape; + NumericEscapeFormat m_numericEscapeFormat; + int m_minNumericDigits, m_maxNumericDigits; +}; + +/** The basic method of applying a StringEscapeRule is to find all matches + * in the string for the m_matchRegex. + * + * if m_numericConversion is set then the match is taken out of the string and replaced + * with one or more numerical escapes. + * if no conversion is needed the match is simple prefixed with m_prefixWidth + */ +class StringEscapeRule { +public: + /** Regular expression that finds characters in the string that need replacing. + * Each character to replace should always generate one match. + */ + QString m_matchRegex; + /** As often a simple escape character like \ or a doubling scheme is used this + * field often provides enough flexibility. + */ + QString m_prefixWith; +// boost::optional m_numericConversion; +}; + +#endif // STRINGESCAPERULE_H diff --git a/pglablib/codebuilder/StringLiteralRules.cpp b/pglablib/codebuilder/StringLiteralRules.cpp new file mode 100644 index 0000000..0403e1e --- /dev/null +++ b/pglablib/codebuilder/StringLiteralRules.cpp @@ -0,0 +1,10 @@ +#include "StringLiteralRules.h" +#include + +void StringLiteralRules::OutputString(QTextStream &stream, QString string_literal) +{ + stream << m_stringStart; + + + stream << m_stringEnd; +} diff --git a/pglablib/codebuilder/StringLiteralRules.h b/pglablib/codebuilder/StringLiteralRules.h new file mode 100644 index 0000000..8e02791 --- /dev/null +++ b/pglablib/codebuilder/StringLiteralRules.h @@ -0,0 +1,37 @@ +#ifndef STRINGLITERALRULES_H +#define STRINGLITERALRULES_H + +#include "StringEscapeRule.h" +#include + +class QTextStream; + +class StringLiteralRules { +public: + /** What should be put in front of the string to make it a string literal + * + * For instance a plain char string in C this would just be a double quote " + * But for a C++11 utf8 string literal it would be u8" + */ + QString m_stringStart; + /** Similar to stringStart + */ + QString m_stringEnd; + + /** If true the assumption is that the newlines + * in the source string are not escaped so no line breaking is done. + * However we should still get a multiline string if the source was. + * + * When false the assumption is that we can split the string using stringEnd, + * stringStart and the concatOperator. There is a preference to split on whitespace. + */ + bool m_supportsMultiLine; + QString m_concatOperator; + + std::vector m_escapeRules; + + void OutputString(QTextStream &stream, QString string_literal); +}; + + +#endif // STRINGLITERALRULES_H diff --git a/pglablib/pglablib.pro b/pglablib/pglablib.pro index b355769..bf68c3c 100644 --- a/pglablib/pglablib.pro +++ b/pglablib/pglablib.pro @@ -61,7 +61,9 @@ codebuilder/DefaultConfigs.cpp \ codebuilder/TypeMappings.cpp \ codebuilder/IndentationConfig.cpp \ codebuilder/StructureTemplate.cpp \ - FormatToStream.cpp + FormatToStream.cpp \ + codebuilder/StringLiteralRules.cpp \ + codebuilder/StringEscapeRule.cpp HEADERS += \ Pglablib.h \ @@ -105,7 +107,9 @@ codebuilder/TypeMappings.h \ codebuilder/IndentationConfig.h \ codebuilder/StructureTemplate.h \ FormatToStream.h \ - codebuilder/ResultLoopTemplate.h + codebuilder/ResultLoopTemplate.h \ + codebuilder/StringEscapeRule.h \ + codebuilder/StringLiteralRules.h unix { target.path = /usr/lib diff --git a/tests/pglabtests/pglabtests.pro b/tests/pglabtests/pglabtests.pro index ed131bf..eff3fce 100644 --- a/tests/pglabtests/pglabtests.pro +++ b/tests/pglabtests/pglabtests.pro @@ -27,7 +27,8 @@ SOURCES += main.cpp \ tst_ParamJson.cpp \ tst_CodeBuilder.cpp \ tst_NameManglingRules.cpp \ - tst_TypeMappings.cpp + tst_TypeMappings.cpp \ + tst_Range.cpp win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../core/release/ -lcore else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../core/debug/ -lcore diff --git a/tests/pglabtests/tst_Range.cpp b/tests/pglabtests/tst_Range.cpp new file mode 100644 index 0000000..6048d20 --- /dev/null +++ b/tests/pglabtests/tst_Range.cpp @@ -0,0 +1,107 @@ +#include +#include +#include "PrintTo_Qt.h" + + +template +class Range { +public: + Range(T start, T end, bool incl_start = true, bool incl_end = false) + : m_start(start), m_end(end), m_inclStart(incl_start), m_inclEnd(incl_end) + {} + + bool includes(T v) const + { + // assume chance is small that outcome hangs on the edge cases + // so we start with testing for definitly outside or definitly inside + if (v < m_start || v > m_end) + return false; + if (v > m_start && v < m_end) + return true; + // Now the edge cases + if (m_inclStart && v == m_start) + return true; + if (m_inclEnd && v == m_end) + return true; + + return false; + } + + bool overlap(Range r) const + { + if ( (r.m_start < m_end || (m_incl)) + && r.m_end > m_start) + return true; + + return false; + } +private: + T m_start; + T m_end; + bool m_inclStart; + bool m_inclEnd; +}; + + +TEST(RangeTest, test_int_includes_before) +{ + bool expected = false; + Range r(2, 5, true, false); + bool result = r.includes(1); + + ASSERT_EQ(result, expected); +} + +TEST(RangeTest, test_int_includes_start_excl) +{ + bool expected = false; + Range r(2, 5, false, false); + bool result = r.includes(2); + + ASSERT_EQ(result, expected); +} + +TEST(RangeTest, test_int_includes_start_incl) +{ + bool expected = true; + Range r(2, 5, true, false); + bool result = r.includes(2); + + ASSERT_EQ(result, expected); +} + +TEST(RangeTest, test_int_includes_mid) +{ + bool expected = true; + Range r(2, 5, true, false); + bool result = r.includes(3); + + ASSERT_EQ(result, expected); +} + +TEST(RangeTest, test_int_includes_end_incl) +{ + bool expected = true; + Range r(2, 5, true, true); + bool result = r.includes(5); + + ASSERT_EQ(result, expected); +} + +TEST(RangeTest, test_int_includes_end_excl) +{ + bool expected = false; + Range r(2, 5, true, false); + bool result = r.includes(5); + + ASSERT_EQ(result, expected); +} + +TEST(RangeTest, test_int_includes_after) +{ + bool expected = false; + Range r(2, 5, true, false); + bool result = r.includes(6); + + ASSERT_EQ(result, expected); +}