2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-31 02:48:31 +00:00

In QPDFParser::parseRemainder eliminate most temporary variables

This commit is contained in:
m-holger 2023-10-31 11:57:34 +00:00
parent 4c8836d520
commit 1548b8d8be
2 changed files with 68 additions and 63 deletions

View File

@ -113,11 +113,11 @@ QPDFParser::parse(bool& empty, bool content_stream)
case QPDFTokenizer::tt_string:
if (decrypter) {
std::string s{tokenizer.getValue()};
decrypter->decryptString(s);
return withDescription<QPDF_String>(s);
std::string s{tokenizer.getValue()};
decrypter->decryptString(s);
return withDescription<QPDF_String>(s);
} else {
return withDescription<QPDF_String>(tokenizer.getValue());
return withDescription<QPDF_String>(tokenizer.getValue());
}
default:
@ -134,20 +134,10 @@ QPDFParser::parseRemainder(bool content_stream)
// effect of reading the object and changing the file pointer. If you do this, it will cause a
// logic error to be thrown from QPDF::inParse().
const static ObjectPtr null_oh = QPDF_Null::create();
ObjectPtr object;
bool set_offset = false;
bool b_contents = false;
bool is_null = false;
bad_count = 0;
bool b_contents = false;
while (true) {
bool indirect_ref = false;
is_null = false;
object = nullptr;
set_offset = false;
if (!tokenizer.nextToken(*input, object_description)) {
warn(tokenizer.getErrorMessage());
}
@ -169,8 +159,8 @@ QPDFParser::parseRemainder(bool content_stream)
if (tooManyBadTokens()) {
return {QPDF_Null::create()};
}
is_null = true;
break;
addNull();
continue;
case QPDFTokenizer::tt_brace_open:
case QPDFTokenizer::tt_brace_close:
@ -179,32 +169,32 @@ QPDFParser::parseRemainder(bool content_stream)
if (tooManyBadTokens()) {
return {QPDF_Null::create()};
}
is_null = true;
break;
addNull();
continue;
case QPDFTokenizer::tt_array_close:
if (frame->state == st_array) {
object = QPDF_Array::create(std::move(frame->olist), frame->null_count > 100);
auto object = QPDF_Array::create(std::move(frame->olist), frame->null_count > 100);
setDescription(object, frame->offset - 1);
// The `offset` points to the next of "[". Set the rewind offset to point to the
// beginning of "[". This has been explicitly tested with whitespace surrounding the
// array start delimiter. getLastOffset points to the array end token and therefore
// can't be used here.
set_offset = true;
if (stack.size() <= 1) {
return object;
}
stack.pop_back();
frame = &stack.back();
add(std::move(object));
} else {
QTC::TC("qpdf", "QPDFParser bad array close in parseRemainder");
warn("treating unexpected array close token as null");
if (tooManyBadTokens()) {
return {QPDF_Null::create()};
}
is_null = true;
addNull();
}
break;
continue;
case QPDFTokenizer::tt_dict_close:
if (frame->state == st_dictionary) {
@ -267,7 +257,7 @@ QPDFParser::parseRemainder(bool content_stream)
dict["/Contents"] = QPDFObjectHandle::newString(frame->contents_string);
dict["/Contents"].setParsedOffset(frame->contents_offset);
}
object = QPDF_Dictionary::create(std::move(dict));
auto object = QPDF_Dictionary::create(std::move(dict));
setDescription(object, frame->offset - 2);
// The `offset` points to the next of "<<". Set the rewind offset to point to the
// beginning of "<<". This has been explicitly tested with whitespace surrounding
@ -276,18 +266,18 @@ QPDFParser::parseRemainder(bool content_stream)
if (stack.size() <= 1) {
return object;
}
set_offset = true;
stack.pop_back();
frame = &stack.back();
add(std::move(object));
} else {
QTC::TC("qpdf", "QPDFParser bad dictionary close in parseRemainder");
warn("unexpected dictionary close token");
if (tooManyBadTokens()) {
return {QPDF_Null::create()};
}
is_null = true;
addNull();
}
break;
continue;
case QPDFTokenizer::tt_array_open:
case QPDFTokenizer::tt_dict_open:
@ -306,26 +296,25 @@ QPDFParser::parseRemainder(bool content_stream)
}
case QPDFTokenizer::tt_bool:
object = QPDF_Bool::create((tokenizer.getValue() == "true"));
break;
addScalar<QPDF_Bool>(tokenizer.getValue() == "true");
continue;
case QPDFTokenizer::tt_null:
is_null = true;
++frame->null_count;
break;
addNull();
continue;
case QPDFTokenizer::tt_integer:
object = QPDF_Integer::create(QUtil::string_to_ll(tokenizer.getValue().c_str()));
break;
addScalar<QPDF_Integer>(QUtil::string_to_ll(tokenizer.getValue().c_str()));
continue;
case QPDFTokenizer::tt_real:
object = QPDF_Real::create(tokenizer.getValue());
break;
addScalar<QPDF_Real>(tokenizer.getValue());
continue;
case QPDFTokenizer::tt_name:
{
auto const& name = tokenizer.getValue();
object = QPDF_Name::create(name);
addScalar<QPDF_Name>(name);
if (name == "/Contents") {
b_contents = true;
@ -333,14 +322,14 @@ QPDFParser::parseRemainder(bool content_stream)
b_contents = false;
}
}
break;
continue;
case QPDFTokenizer::tt_word:
{
auto const& value = tokenizer.getValue();
auto size = frame->olist.size();
if (content_stream) {
object = QPDF_Operator::create(value);
addScalar<QPDF_Operator>(value);
} else if (
value == "R" && size >= 2 && frame->olist.back() &&
frame->olist.back()->getTypeCode() == ::ot_integer &&
@ -359,24 +348,25 @@ QPDFParser::parseRemainder(bool content_stream)
// This action has the desirable side effect of causing dangling references
// (references to indirect objects that don't appear in the PDF) in any
// parsed object to appear in the object cache.
object = context->getObject(ref_og).obj;
indirect_ref = true;
frame->olist.pop_back();
frame->olist.pop_back();
add(std::move(context->getObject(ref_og).obj));
} else {
QTC::TC("qpdf", "QPDFParser indirect with 0 objid");
is_null = true;
frame->olist.pop_back();
frame->olist.pop_back();
addNull();
}
frame->olist.pop_back();
frame->olist.pop_back();
} else {
QTC::TC("qpdf", "QPDFParser treat word as string in parseRemainder");
warn("unknown token while reading object; treating as string");
if (tooManyBadTokens()) {
return {QPDF_Null::create()};
}
object = QPDF_String::create(value);
addScalar<QPDF_String>(value);
}
}
break;
continue;
case QPDFTokenizer::tt_string:
{
@ -389,37 +379,48 @@ QPDFParser::parseRemainder(bool content_stream)
}
std::string s{val};
decrypter->decryptString(s);
object = QPDF_String::create(s);
addScalar<QPDF_String>(s);
} else {
object = QPDF_String::create(val);
addScalar<QPDF_String>(val);
}
}
break;
continue;
default:
warn("treating unknown token type as null while reading object");
if (tooManyBadTokens()) {
return {QPDF_Null::create()};
}
is_null = true;
break;
addNull();
}
if (object == nullptr && !is_null) {
throw std::logic_error("QPDFParser:parseInternal: unexpected uninitialized object");
}
if (is_null) {
object = null_oh;
// No need to set description for direct nulls - they probably will become implicit.
} else if (!indirect_ref && !set_offset) {
setDescription(object, input->getLastOffset());
}
frame->olist.push_back(object);
}
return {}; // unreachable
}
void
QPDFParser::add(std::shared_ptr<QPDFObject>&& obj)
{
frame->olist.emplace_back(std::move(obj));
}
void
QPDFParser::addNull()
{
const static ObjectPtr null_obj = QPDF_Null::create();
frame->olist.emplace_back(null_obj);
++frame->null_count;
}
template <typename T, typename... Args>
void
QPDFParser::addScalar(Args&&... args)
{
auto obj = T::create(args...);
obj->setDescription(context, description, input->getLastOffset());
add(std::move(obj));
}
template <typename T, typename... Args>
QPDFObjectHandle
QPDFParser::withDescription(Args&&... args)

View File

@ -51,6 +51,10 @@ class QPDFParser
};
QPDFObjectHandle parseRemainder(bool content_stream);
void add(std::shared_ptr<QPDFObject>&& obj);
void addNull();
template <typename T, typename... Args>
void addScalar(Args&&... args);
bool tooManyBadTokens();
void warn(qpdf_offset_t offset, std::string const& msg) const;
void warn(std::string const& msg) const;