@@ -513,7 +513,7 @@ protected: | |||||
{ | { | ||||
if (value.isNotEmpty()) | if (value.isNotEmpty()) | ||||
mo << " VALUE \"" << name << "\", \"" | mo << " VALUE \"" << name << "\", \"" | ||||
<< CodeHelpers::addEscapeChars (value) << "\\0\"" << newLine; | |||||
<< CppTokeniserFunctions::addEscapeChars (value) << "\\0\"" << newLine; | |||||
} | } | ||||
static String getCommaSeparatedVersionNumber (const String& version) | static String getCommaSeparatedVersionNumber (const String& version) | ||||
@@ -435,8 +435,8 @@ private: | |||||
<< newLine | << newLine | ||||
<< "namespace ProjectInfo" << newLine | << "namespace ProjectInfo" << newLine | ||||
<< "{" << newLine | << "{" << newLine | ||||
<< " const char* const projectName = " << CodeHelpers::addEscapeChars (project.getTitle()).quoted() << ";" << newLine | |||||
<< " const char* const versionString = " << CodeHelpers::addEscapeChars (project.getVersionString()).quoted() << ";" << newLine | |||||
<< " const char* const projectName = " << CppTokeniserFunctions::addEscapeChars (project.getTitle()).quoted() << ";" << newLine | |||||
<< " const char* const versionString = " << CppTokeniserFunctions::addEscapeChars (project.getVersionString()).quoted() << ";" << newLine | |||||
<< " const int versionNumber = " << project.getVersionAsHex() << ";" << newLine | << " const int versionNumber = " << project.getVersionAsHex() << ";" << newLine | ||||
<< "}" << newLine | << "}" << newLine | ||||
<< newLine | << newLine | ||||
@@ -128,12 +128,12 @@ namespace | |||||
String valueToStringLiteral (const var& v) | String valueToStringLiteral (const var& v) | ||||
{ | { | ||||
return CodeHelpers::addEscapeChars (v.toString()).quoted(); | |||||
return CppTokeniserFunctions::addEscapeChars (v.toString()).quoted(); | |||||
} | } | ||||
String valueToCharLiteral (const var& v) | String valueToCharLiteral (const var& v) | ||||
{ | { | ||||
return CodeHelpers::addEscapeChars (v.toString().trim().substring (0, 4)).quoted ('\''); | |||||
return CppTokeniserFunctions::addEscapeChars (v.toString().trim().substring (0, 4)).quoted ('\''); | |||||
} | } | ||||
void writePluginCharacteristicsFile (ProjectSaver& projectSaver) | void writePluginCharacteristicsFile (ProjectSaver& projectSaver) | ||||
@@ -212,8 +212,8 @@ namespace | |||||
String createEscapedStringForVersion (ProjectExporter& exporter, const String& text) | String createEscapedStringForVersion (ProjectExporter& exporter, const String& text) | ||||
{ | { | ||||
// (VS10 automatically adds escape characters to the quotes for this definition) | // (VS10 automatically adds escape characters to the quotes for this definition) | ||||
return exporter.getVisualStudioVersion() < 10 ? CodeHelpers::addEscapeChars (text.quoted()) | |||||
: CodeHelpers::addEscapeChars (text).quoted(); | |||||
return exporter.getVisualStudioVersion() < 10 ? CppTokeniserFunctions::addEscapeChars (text.quoted()) | |||||
: CppTokeniserFunctions::addEscapeChars (text).quoted(); | |||||
} | } | ||||
String createRebasedPath (ProjectExporter& exporter, const RelativePath& path) | String createRebasedPath (ProjectExporter& exporter, const RelativePath& path) | ||||
@@ -341,7 +341,7 @@ struct NewProjectWizardClasses | |||||
: "jucer_MainTemplate_NoWindow_cpp") | : "jucer_MainTemplate_NoWindow_cpp") | ||||
.replace ("APPHEADERS", appHeaders, false) | .replace ("APPHEADERS", appHeaders, false) | ||||
.replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) | .replace ("APPCLASSNAME", CodeHelpers::makeValidIdentifier (appTitle + "Application", false, true, false), false) | ||||
.replace ("APPNAME", CodeHelpers::addEscapeChars (appTitle), false) | |||||
.replace ("APPNAME", CppTokeniserFunctions::addEscapeChars (appTitle), false) | |||||
.replace ("CONTENTCOMPCLASS", contentCompName, false) | .replace ("CONTENTCOMPCLASS", contentCompName, false) | ||||
.replace ("ALLOWMORETHANONEINSTANCE", "true", false); | .replace ("ALLOWMORETHANONEINSTANCE", "true", false); | ||||
@@ -102,87 +102,6 @@ namespace CodeHelpers | |||||
return n; | return n; | ||||
} | } | ||||
static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytes, | |||||
const int maxCharsOnLine, const bool breakAtNewLines, | |||||
const bool replaceSingleQuotes, const bool allowStringBreaks) | |||||
{ | |||||
int charsOnLine = 0; | |||||
bool lastWasHexEscapeCode = false; | |||||
for (int i = 0; i < numBytes || numBytes < 0; ++i) | |||||
{ | |||||
const unsigned char c = (unsigned char) utf8[i]; | |||||
bool startNewLine = false; | |||||
switch (c) | |||||
{ | |||||
case '\t': out << "\\t"; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case '\r': out << "\\r"; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case '\n': out << "\\n"; lastWasHexEscapeCode = false; charsOnLine += 2; startNewLine = breakAtNewLines; break; | |||||
case '\\': out << "\\\\"; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case '\"': out << "\\\""; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case 0: | |||||
if (numBytes < 0) | |||||
return; | |||||
out << "\\0"; | |||||
lastWasHexEscapeCode = true; | |||||
charsOnLine += 2; | |||||
break; | |||||
case '\'': | |||||
if (replaceSingleQuotes) | |||||
{ | |||||
out << "\\\'"; | |||||
lastWasHexEscapeCode = false; | |||||
charsOnLine += 2; | |||||
break; | |||||
} | |||||
// deliberate fall-through... | |||||
default: | |||||
if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit) | |||||
&& CharacterFunctions::getHexDigitValue (c) >= 0)) | |||||
{ | |||||
out << (char) c; | |||||
lastWasHexEscapeCode = false; | |||||
++charsOnLine; | |||||
} | |||||
else if (allowStringBreaks && lastWasHexEscapeCode && c >= 32 && c < 127) | |||||
{ | |||||
out << "\"\"" << (char) c; | |||||
lastWasHexEscapeCode = false; | |||||
charsOnLine += 3; | |||||
} | |||||
else | |||||
{ | |||||
out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c); | |||||
lastWasHexEscapeCode = true; | |||||
charsOnLine += 4; | |||||
} | |||||
break; | |||||
} | |||||
if ((startNewLine || (maxCharsOnLine > 0 && charsOnLine >= maxCharsOnLine)) | |||||
&& (numBytes < 0 || i < numBytes - 1)) | |||||
{ | |||||
charsOnLine = 0; | |||||
out << "\"" << newLine << "\""; | |||||
lastWasHexEscapeCode = false; | |||||
} | |||||
} | |||||
} | |||||
String addEscapeChars (const String& s) | |||||
{ | |||||
MemoryOutputStream out; | |||||
writeEscapeChars (out, s.toRawUTF8(), -1, -1, false, true, true); | |||||
return out.toUTF8(); | |||||
} | |||||
String createIncludeStatement (const File& includeFile, const File& targetFile) | String createIncludeStatement (const File& includeFile, const File& targetFile) | ||||
{ | { | ||||
return createIncludeStatement (FileHelpers::unixStylePath (FileHelpers::getRelativePathFrom (includeFile, targetFile.getParentDirectory()))); | return createIncludeStatement (FileHelpers::unixStylePath (FileHelpers::getRelativePathFrom (includeFile, targetFile.getParentDirectory()))); | ||||
@@ -258,7 +177,7 @@ namespace CodeHelpers | |||||
} | } | ||||
for (int i = 0; i < lines.size(); ++i) | for (int i = 0; i < lines.size(); ++i) | ||||
lines.getReference(i) = addEscapeChars (lines.getReference(i)); | |||||
lines.getReference(i) = CppTokeniserFunctions::addEscapeChars (lines.getReference(i)); | |||||
lines.removeEmptyStrings(); | lines.removeEmptyStrings(); | ||||
@@ -424,8 +343,8 @@ namespace CodeHelpers | |||||
else | else | ||||
{ | { | ||||
out << "\""; | out << "\""; | ||||
writeEscapeChars (out, (const char*) data, (int) mb.getSize(), | |||||
maxCharsOnLine, breakAtNewLines, false, allowStringBreaks); | |||||
CppTokeniserFunctions::writeEscapeChars (out, (const char*) data, (int) mb.getSize(), | |||||
maxCharsOnLine, breakAtNewLines, false, allowStringBreaks); | |||||
out << "\";"; | out << "\";"; | ||||
} | } | ||||
} | } | ||||
@@ -31,7 +31,6 @@ namespace CodeHelpers | |||||
{ | { | ||||
String indent (const String& code, const int numSpaces, bool indentFirstLine); | String indent (const String& code, const int numSpaces, bool indentFirstLine); | ||||
String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates); | String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates); | ||||
String addEscapeChars (const String& text); | |||||
String createIncludeStatement (const File& includedFile, const File& targetFile); | String createIncludeStatement (const File& includedFile, const File& targetFile); | ||||
String createIncludeStatement (const String& includePath); | String createIncludeStatement (const String& includePath); | ||||
String makeHeaderGuardName (const File& file); | String makeHeaderGuardName (const File& file); | ||||
@@ -535,6 +535,106 @@ struct CppTokeniserFunctions | |||||
String::CharPointerType t; | String::CharPointerType t; | ||||
int numChars; | int numChars; | ||||
}; | }; | ||||
//============================================================================== | |||||
/** Takes a UTF8 string and writes it to a stream using standard C++ escape sequences for any | |||||
non-ascii bytes. | |||||
Although not strictly a tokenising function, this is still a function that often comes in | |||||
handy when working with C++ code! | |||||
Note that addEscapeChars() is easier to use than this function if you're working with Strings. | |||||
@see addEscapeChars | |||||
*/ | |||||
static void writeEscapeChars (OutputStream& out, const char* utf8, const int numBytesToRead, | |||||
const int maxCharsOnLine, const bool breakAtNewLines, | |||||
const bool replaceSingleQuotes, const bool allowStringBreaks) | |||||
{ | |||||
int charsOnLine = 0; | |||||
bool lastWasHexEscapeCode = false; | |||||
for (int i = 0; i < numBytesToRead || numBytesToRead < 0; ++i) | |||||
{ | |||||
const unsigned char c = (unsigned char) utf8[i]; | |||||
bool startNewLine = false; | |||||
switch (c) | |||||
{ | |||||
case '\t': out << "\\t"; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case '\r': out << "\\r"; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case '\n': out << "\\n"; lastWasHexEscapeCode = false; charsOnLine += 2; startNewLine = breakAtNewLines; break; | |||||
case '\\': out << "\\\\"; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case '\"': out << "\\\""; lastWasHexEscapeCode = false; charsOnLine += 2; break; | |||||
case 0: | |||||
if (numBytesToRead < 0) | |||||
return; | |||||
out << "\\0"; | |||||
lastWasHexEscapeCode = true; | |||||
charsOnLine += 2; | |||||
break; | |||||
case '\'': | |||||
if (replaceSingleQuotes) | |||||
{ | |||||
out << "\\\'"; | |||||
lastWasHexEscapeCode = false; | |||||
charsOnLine += 2; | |||||
break; | |||||
} | |||||
// deliberate fall-through... | |||||
default: | |||||
if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit) | |||||
&& CharacterFunctions::getHexDigitValue (c) >= 0)) | |||||
{ | |||||
out << (char) c; | |||||
lastWasHexEscapeCode = false; | |||||
++charsOnLine; | |||||
} | |||||
else if (allowStringBreaks && lastWasHexEscapeCode && c >= 32 && c < 127) | |||||
{ | |||||
out << "\"\"" << (char) c; | |||||
lastWasHexEscapeCode = false; | |||||
charsOnLine += 3; | |||||
} | |||||
else | |||||
{ | |||||
out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c); | |||||
lastWasHexEscapeCode = true; | |||||
charsOnLine += 4; | |||||
} | |||||
break; | |||||
} | |||||
if ((startNewLine || (maxCharsOnLine > 0 && charsOnLine >= maxCharsOnLine)) | |||||
&& (numBytesToRead < 0 || i < numBytesToRead - 1)) | |||||
{ | |||||
charsOnLine = 0; | |||||
out << "\"" << newLine << "\""; | |||||
lastWasHexEscapeCode = false; | |||||
} | |||||
} | |||||
} | |||||
/** Takes a string and returns a version of it where standard C++ escape sequences have been | |||||
used to replace any non-ascii bytes. | |||||
Although not strictly a tokenising function, this is still a function that often comes in | |||||
handy when working with C++ code! | |||||
@see writeEscapeChars | |||||
*/ | |||||
static String addEscapeChars (StringRef s) | |||||
{ | |||||
MemoryOutputStream out; | |||||
writeEscapeChars (out, s.text, -1, -1, false, true, true); | |||||
return out.toUTF8(); | |||||
} | |||||
}; | }; | ||||