Simplify string object printing to reduce code duplication
This commit is contained in:
28
ASTree.cpp
28
ASTree.cpp
@@ -3224,32 +3224,14 @@ bool print_docstring(PycRef<PycObject> obj, int indent, PycModule* mod,
|
|||||||
std::ostream& pyc_output)
|
std::ostream& pyc_output)
|
||||||
{
|
{
|
||||||
// docstrings are translated from the bytecode __doc__ = 'string' to simply '''string'''
|
// docstrings are translated from the bytecode __doc__ = 'string' to simply '''string'''
|
||||||
signed char prefix = -1;
|
auto doc = obj.try_cast<PycString>();
|
||||||
switch (obj.type()) {
|
if (doc != nullptr) {
|
||||||
case PycObject::TYPE_STRING:
|
|
||||||
prefix = mod->strIsUnicode() ? 'b' : 0;
|
|
||||||
break;
|
|
||||||
case PycObject::TYPE_UNICODE:
|
|
||||||
prefix = mod->strIsUnicode() ? 0 : 'u';
|
|
||||||
break;
|
|
||||||
case PycObject::TYPE_INTERNED:
|
|
||||||
case PycObject::TYPE_ASCII:
|
|
||||||
case PycObject::TYPE_ASCII_INTERNED:
|
|
||||||
case PycObject::TYPE_SHORT_ASCII:
|
|
||||||
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
|
||||||
if (mod->majorVer() >= 3)
|
|
||||||
prefix = 0;
|
|
||||||
else
|
|
||||||
prefix = mod->strIsUnicode() ? 'b' : 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (prefix != -1) {
|
|
||||||
start_line(indent, pyc_output);
|
start_line(indent, pyc_output);
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), prefix, true);
|
doc->print(pyc_output, mod, true);
|
||||||
pyc_output << "\n";
|
pyc_output << "\n";
|
||||||
return true;
|
return true;
|
||||||
} else
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decompyle(PycRef<PycCode> code, PycModule* mod, std::ostream& pyc_output)
|
void decompyle(PycRef<PycCode> code, PycModule* mod, std::ostream& pyc_output)
|
||||||
|
12
bytecode.cpp
12
bytecode.cpp
@@ -170,23 +170,13 @@ void print_const(std::ostream& pyc_output, PycRef<PycObject> obj, PycModule* mod
|
|||||||
|
|
||||||
switch (obj->type()) {
|
switch (obj->type()) {
|
||||||
case PycObject::TYPE_STRING:
|
case PycObject::TYPE_STRING:
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0,
|
|
||||||
false, parent_f_string_quote);
|
|
||||||
break;
|
|
||||||
case PycObject::TYPE_UNICODE:
|
case PycObject::TYPE_UNICODE:
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), mod->strIsUnicode() ? 0 : 'u',
|
|
||||||
false, parent_f_string_quote);
|
|
||||||
break;
|
|
||||||
case PycObject::TYPE_INTERNED:
|
case PycObject::TYPE_INTERNED:
|
||||||
case PycObject::TYPE_ASCII:
|
case PycObject::TYPE_ASCII:
|
||||||
case PycObject::TYPE_ASCII_INTERNED:
|
case PycObject::TYPE_ASCII_INTERNED:
|
||||||
case PycObject::TYPE_SHORT_ASCII:
|
case PycObject::TYPE_SHORT_ASCII:
|
||||||
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
||||||
if (mod->majorVer() >= 3)
|
obj.cast<PycString>()->print(pyc_output, mod, false, parent_f_string_quote);
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), 0, false, parent_f_string_quote);
|
|
||||||
else
|
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0,
|
|
||||||
false, parent_f_string_quote);
|
|
||||||
break;
|
break;
|
||||||
case PycObject::TYPE_TUPLE:
|
case PycObject::TYPE_TUPLE:
|
||||||
case PycObject::TYPE_SMALL_TUPLE:
|
case PycObject::TYPE_SMALL_TUPLE:
|
||||||
|
@@ -56,15 +56,35 @@ bool PycString::isEqual(PycRef<PycObject> obj) const
|
|||||||
return isEqual(strObj->m_value);
|
return isEqual(strObj->m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputString(std::ostream &pyc_output, PycRef<PycString> str, char prefix,
|
void PycString::print(std::ostream &pyc_output, PycModule* mod, bool triple,
|
||||||
bool triple, const char* parent_f_string_quote)
|
const char* parent_f_string_quote)
|
||||||
{
|
{
|
||||||
|
char prefix = 0;
|
||||||
|
switch (type()) {
|
||||||
|
case TYPE_STRING:
|
||||||
|
prefix = mod->strIsUnicode() ? 'b' : 0;
|
||||||
|
break;
|
||||||
|
case PycObject::TYPE_UNICODE:
|
||||||
|
prefix = mod->strIsUnicode() ? 0 : 'u';
|
||||||
|
break;
|
||||||
|
case PycObject::TYPE_INTERNED:
|
||||||
|
case PycObject::TYPE_ASCII:
|
||||||
|
case PycObject::TYPE_ASCII_INTERNED:
|
||||||
|
case PycObject::TYPE_SHORT_ASCII:
|
||||||
|
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
||||||
|
if (mod->majorVer() >= 3)
|
||||||
|
prefix = 0;
|
||||||
|
else
|
||||||
|
prefix = mod->strIsUnicode() ? 'b' : 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Invalid string type");
|
||||||
|
}
|
||||||
|
|
||||||
if (prefix != 0)
|
if (prefix != 0)
|
||||||
pyc_output << prefix;
|
pyc_output << prefix;
|
||||||
|
|
||||||
const char* ch = str->value();
|
if (m_value.empty()) {
|
||||||
int len = str->length();
|
|
||||||
if (len == 0) {
|
|
||||||
pyc_output << "''";
|
pyc_output << "''";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -72,20 +92,17 @@ void OutputString(std::ostream &pyc_output, PycRef<PycString> str, char prefix,
|
|||||||
// Determine preferred quote style (Emulate Python's method)
|
// Determine preferred quote style (Emulate Python's method)
|
||||||
bool useQuotes = false;
|
bool useQuotes = false;
|
||||||
if (!parent_f_string_quote) {
|
if (!parent_f_string_quote) {
|
||||||
while (len--) {
|
for (char ch : m_value) {
|
||||||
if (*ch == '\'') {
|
if (ch == '\'') {
|
||||||
useQuotes = true;
|
useQuotes = true;
|
||||||
} else if (*ch == '"') {
|
} else if (ch == '"') {
|
||||||
useQuotes = false;
|
useQuotes = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ch++;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
useQuotes = parent_f_string_quote[0] == '"';
|
useQuotes = parent_f_string_quote[0] == '"';
|
||||||
}
|
}
|
||||||
ch = str->value();
|
|
||||||
len = str->length();
|
|
||||||
|
|
||||||
// Output the string
|
// Output the string
|
||||||
if (!parent_f_string_quote) {
|
if (!parent_f_string_quote) {
|
||||||
@@ -94,42 +111,41 @@ void OutputString(std::ostream &pyc_output, PycRef<PycString> str, char prefix,
|
|||||||
else
|
else
|
||||||
pyc_output << (useQuotes ? '"' : '\'');
|
pyc_output << (useQuotes ? '"' : '\'');
|
||||||
}
|
}
|
||||||
while (len--) {
|
for (char ch : m_value) {
|
||||||
if ((unsigned char)(*ch) < 0x20 || *ch == 0x7F) {
|
if (static_cast<unsigned char>(ch) < 0x20 || ch == 0x7F) {
|
||||||
if (*ch == '\r') {
|
if (ch == '\r') {
|
||||||
pyc_output << "\\r";
|
pyc_output << "\\r";
|
||||||
} else if (*ch == '\n') {
|
} else if (ch == '\n') {
|
||||||
if (triple)
|
if (triple)
|
||||||
pyc_output << '\n';
|
pyc_output << '\n';
|
||||||
else
|
else
|
||||||
pyc_output << "\\n";
|
pyc_output << "\\n";
|
||||||
} else if (*ch == '\t') {
|
} else if (ch == '\t') {
|
||||||
pyc_output << "\\t";
|
pyc_output << "\\t";
|
||||||
} else {
|
} else {
|
||||||
formatted_print(pyc_output, "\\x%02x", (*ch & 0xFF));
|
formatted_print(pyc_output, "\\x%02x", (ch & 0xFF));
|
||||||
}
|
}
|
||||||
} else if ((unsigned char)(*ch) >= 0x80) {
|
} else if (static_cast<unsigned char>(ch) >= 0x80) {
|
||||||
if (str->type() == PycObject::TYPE_UNICODE) {
|
if (type() == TYPE_UNICODE) {
|
||||||
// Unicode stored as UTF-8... Let the stream interpret it
|
// Unicode stored as UTF-8... Let the stream interpret it
|
||||||
pyc_output << *ch;
|
pyc_output << ch;
|
||||||
} else {
|
} else {
|
||||||
formatted_print(pyc_output, "\\x%x", (*ch & 0xFF));
|
formatted_print(pyc_output, "\\x%x", (ch & 0xFF));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!useQuotes && *ch == '\'')
|
if (!useQuotes && ch == '\'')
|
||||||
pyc_output << R"(\')";
|
pyc_output << R"(\')";
|
||||||
else if (useQuotes && *ch == '"')
|
else if (useQuotes && ch == '"')
|
||||||
pyc_output << R"(\")";
|
pyc_output << R"(\")";
|
||||||
else if (*ch == '\\')
|
else if (ch == '\\')
|
||||||
pyc_output << R"(\\)";
|
pyc_output << R"(\\)";
|
||||||
else if (parent_f_string_quote && *ch == '{')
|
else if (parent_f_string_quote && ch == '{')
|
||||||
pyc_output << "{{";
|
pyc_output << "{{";
|
||||||
else if (parent_f_string_quote && *ch == '}')
|
else if (parent_f_string_quote && ch == '}')
|
||||||
pyc_output << "}}";
|
pyc_output << "}}";
|
||||||
else
|
else
|
||||||
pyc_output << *ch;
|
pyc_output << ch;
|
||||||
}
|
}
|
||||||
ch++;
|
|
||||||
}
|
}
|
||||||
if (!parent_f_string_quote) {
|
if (!parent_f_string_quote) {
|
||||||
if (triple)
|
if (triple)
|
||||||
|
@@ -27,11 +27,11 @@ public:
|
|||||||
|
|
||||||
void setValue(std::string str) { m_value = std::move(str); }
|
void setValue(std::string str) { m_value = std::move(str); }
|
||||||
|
|
||||||
|
void print(std::ostream& stream, class PycModule* mod, bool triple = false,
|
||||||
|
const char* parent_f_string_quote = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
void OutputString(std::ostream& stream, PycRef<PycString> str, char prefix,
|
|
||||||
bool triple = false, const char* parent_f_string_quote = nullptr);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
13
pycdas.cpp
13
pycdas.cpp
@@ -153,25 +153,14 @@ void output_object(PycRef<PycObject> obj, PycModule* mod, int indent,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PycObject::TYPE_STRING:
|
case PycObject::TYPE_STRING:
|
||||||
iputs(pyc_output, indent, "");
|
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0);
|
|
||||||
pyc_output << "\n";
|
|
||||||
break;
|
|
||||||
case PycObject::TYPE_UNICODE:
|
case PycObject::TYPE_UNICODE:
|
||||||
iputs(pyc_output, indent, "");
|
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), mod->strIsUnicode() ? 0 : 'u');
|
|
||||||
pyc_output << "\n";
|
|
||||||
break;
|
|
||||||
case PycObject::TYPE_INTERNED:
|
case PycObject::TYPE_INTERNED:
|
||||||
case PycObject::TYPE_ASCII:
|
case PycObject::TYPE_ASCII:
|
||||||
case PycObject::TYPE_ASCII_INTERNED:
|
case PycObject::TYPE_ASCII_INTERNED:
|
||||||
case PycObject::TYPE_SHORT_ASCII:
|
case PycObject::TYPE_SHORT_ASCII:
|
||||||
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
case PycObject::TYPE_SHORT_ASCII_INTERNED:
|
||||||
iputs(pyc_output, indent, "");
|
iputs(pyc_output, indent, "");
|
||||||
if (mod->majorVer() >= 3)
|
obj.cast<PycString>()->print(pyc_output, mod);
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), 0);
|
|
||||||
else
|
|
||||||
OutputString(pyc_output, obj.cast<PycString>(), mod->strIsUnicode() ? 'b' : 0);
|
|
||||||
pyc_output << "\n";
|
pyc_output << "\n";
|
||||||
break;
|
break;
|
||||||
case PycObject::TYPE_TUPLE:
|
case PycObject::TYPE_TUPLE:
|
||||||
|
Reference in New Issue
Block a user