summaryrefslogtreecommitdiff
path: root/cpp/src/slice2cpp/Gen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/slice2cpp/Gen.cpp')
-rw-r--r--cpp/src/slice2cpp/Gen.cpp116
1 files changed, 95 insertions, 21 deletions
diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp
index cd1edb526fc..de179f26d55 100644
--- a/cpp/src/slice2cpp/Gen.cpp
+++ b/cpp/src/slice2cpp/Gen.cpp
@@ -82,20 +82,55 @@ isConstexprType(const TypePtr& type)
}
string
-u32CodePoint(unsigned int value)
+u32CodePoint(unsigned int value, bool cpp11)
{
ostringstream s;
- s << "\\U";
- s << hex;
- s.width(8);
- s.fill('0');
- s << value;
+ //
+ // COMPILERFIX:
+ // With VC++ < 140 characters in the range of 0 to 0x9f cannot be represented
+ // with a universal character name (UCN).
+ //
+ if(!cpp11 && value <= 0x9f)
+ {
+ switch(value)
+ {
+ case 0x22:
+ {
+ s << "\\\"";
+ break;
+ }
+ case 0x5c:
+ {
+ s << "\\\\";
+ break;
+ }
+ default:
+ {
+ s << "\\";
+ s << oct;
+ s.width(3);
+ s.fill('0');
+ s << value;
+ break;
+ }
+ }
+ }
+ //
+ // UCN valid characters
+ //
+ else
+ {
+ s << "\\U";
+ s << hex;
+ s.width(8);
+ s.fill('0');
+ s << value;
+ }
return s.str();
}
-
void
-writeU8Buffer(const vector<unsigned char>& u8buffer, ::IceUtilInternal::Output& out)
+writeU8Buffer(const vector<unsigned char>& u8buffer, ::IceUtilInternal::Output& out, bool cpp11)
{
vector<unsigned int> u32buffer;
IceUtilInternal::ConversionResult result = convertUTF8ToUTF32(u8buffer, u32buffer, IceUtil::lenientConversion);
@@ -116,7 +151,7 @@ writeU8Buffer(const vector<unsigned char>& u8buffer, ::IceUtilInternal::Output&
for(vector<unsigned int>::const_iterator c = u32buffer.begin(); c != u32buffer.end(); ++c)
{
- out << u32CodePoint(*c);
+ out << u32CodePoint(*c, cpp11);
}
}
@@ -167,7 +202,6 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt
// Wide strings or C++11 narrow string
//
vector<unsigned char> u8buffer; // Buffer to convert multibyte characters
-
out << (wide ? "L\"" : "u8\"");
for(size_t i = 0; i < value.size();)
{
@@ -175,10 +209,7 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt
{
if(static_cast<unsigned char>(value[i]) < 128) // Single byte character
{
- //
- // Print as unicode if not in basic source character set
- //
- out << u32CodePoint(static_cast<unsigned int>(value[i]));
+ out << u32CodePoint(static_cast<unsigned char>(value[i]), cpp11);
}
else
{
@@ -192,31 +223,74 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt
//
if(!u8buffer.empty())
{
- writeU8Buffer(u8buffer, out);
+ writeU8Buffer(u8buffer, out, cpp11);
u8buffer.clear();
}
-
+
switch(value[i])
{
+ case '\\':
+ {
+ string s = "\\";
+ size_t j = i + 1;
+ for(; j < value.size(); ++j)
+ {
+ if(value[j] != '\\')
+ {
+ break;
+ }
+ s += "\\";
+ }
+
+ //
+ // An even number of slash \ will escape the backslash and
+ // the codepoint will be interpreted as its charaters
+ //
+ // \\U00000041 - ['\\', 'U', '0', '0', '0', '0', '0', '0', '4', '1']
+ // \\\U00000041 - ['\\', 'A'] (41 is the codepoint for 'A')
+ //
+ if(s.size() % 2 != 0 && (value[j] == 'U' || value[j] == 'u'))
+ {
+ //
+ // Convert codepoint to UTF8 bytes and write the escaped bytes
+ //
+ out << s.substr(0, s.size() - 1);
+
+ size_t sz = value[j] == 'U' ? 8 : 4;
+ string codepoint = value.substr(j + 1, sz);
+ assert(codepoint.size() == sz);
+
+ IceUtil::Int64 v = IceUtilInternal::strToInt64(codepoint.c_str(), 0, 16);
+ out << u32CodePoint(static_cast<unsigned int>(v), cpp11);
+
+ i = j + 1 + sz;
+ }
+ else
+ {
+ out << s;
+ i = j;
+ }
+ continue;
+ }
case '"':
{
out << "\\";
break;
}
}
-
+
out << value[i]; // Print normally if in basic source character set
}
i++;
-
+
}
-
+
//
// Write any pedding characters in the utf8 buffer
//
if(!u8buffer.empty())
{
- writeU8Buffer(u8buffer, out);
+ writeU8Buffer(u8buffer, out, cpp11);
u8buffer.clear();
}
out << "\"";
@@ -323,7 +397,7 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt
break;
}
}
-
+
out << value[i]; // Print normally if in basic source character set
}
++i;