2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 19:08:59 +00:00

Add new QPDFObjectHandle::Integer and QPDFObjectHandle::asInteger

Implement all existing integer accessors in terms of asInteger.
This commit is contained in:
m-holger 2024-03-18 17:22:05 +00:00
parent df852cd695
commit f2fc1d3db8
4 changed files with 222 additions and 73 deletions

View File

@ -23,6 +23,7 @@
#define QPDFOBJECTHANDLE_HH
#include <qpdf/QPDFObjectHandle_core.hh>
#include <qpdf/QPDFObjectHandle_typed.hh>
// See qpdf/QPDFObjectHandle_core.hh for the definition of QPDFObjectHandle.

View File

@ -66,6 +66,8 @@ class QPDFObjectHandle
friend class QPDFParser;
public:
class Typed;
class Integer;
// This class is used by replaceStreamData. It provides an alternative way of associating
// stream data with a stream. See comments on replaceStreamData and newStream for additional
// details.
@ -647,6 +649,8 @@ class QPDFObjectHandle
// return type may be returned. For example, on a system with 32-bit int, a numeric object with
// a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
QPDF_DLL
QPDFObjectHandle::Integer asInteger(bool optional = false);
QPDF_DLL
long long getIntValue();
QPDF_DLL
bool getValueAsInt(long long&);
@ -1367,7 +1371,6 @@ class QPDFObjectHandle
QPDF_Bool* asBool();
QPDF_Dictionary* asDictionary();
QPDF_InlineImage* asInlineImage();
QPDF_Integer* asInteger();
QPDF_Name* asName();
QPDF_Null* asNull();
QPDF_Operator* asOperator();

View File

@ -0,0 +1,138 @@
// Copyright (c) 2005-2024 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.
#ifndef QPDFOBJECTHANDLE_TYPED_HH
#define QPDFOBJECTHANDLE_TYPED_HH
#include <bitset>
class QPDFObjectHandle::Typed
{
public:
operator QPDFObjectHandle() const
{
return oh;
}
QPDF_DLL
operator bool() noexcept
{
return flags.test(fl_valid);
}
QPDF_DLL
operator bool() const noexcept
{
return flags.test(fl_valid);
}
QPDF_DLL
bool
null() const noexcept
{
return flags.test(fl_null);
}
QPDF_DLL
QPDFObjGen
getObjGen() const
{
return oh.getObjGen();
}
// ... and all the other methods applicable to all object types.
protected:
using Flags = std::bitset<3>;
enum flags { fl_valid, fl_null, fl_no_type_check };
Typed() = default;
Typed(QPDFObjectHandle const& oh, Flags flags) :
oh(oh),
flags(flags)
{
}
Typed(QPDFObjectHandle&& oh, Flags flags) :
oh(std::move(oh)),
flags(flags)
{
}
Typed(Typed const&) = default;
Typed(Typed&&) = default;
Typed& operator=(Typed const&) = default;
Typed& operator=(Typed&&) = default;
~Typed() = default;
QPDFObjectHandle oh;
Flags flags{};
};
class QPDFObjectHandle::Integer: public QPDFObjectHandle::Typed
{
friend class QPDFObjectHandle;
public:
QPDF_DLL
operator long long();
QPDF_DLL
operator int();
QPDF_DLL
operator unsigned long long();
QPDF_DLL
operator unsigned int();
QPDF_DLL
long long
value()
{
return *this;
}
template <typename T>
bool
assign_to(T& var)
{
if (flags.test(0)) {
var = *this;
return true;
}
return false;
}
private:
Integer() = default;
Integer(QPDFObjectHandle const& oh, Flags flags) :
QPDFObjectHandle::Typed(oh, flags)
{
}
Integer(QPDFObjectHandle&& oh, QPDF_Integer* ptr, Flags flags) :
QPDFObjectHandle::Typed(std::move(oh), flags)
{
}
};
#endif // QPDFOBJECTHANDLE_TYPED_HH

View File

@ -273,12 +273,6 @@ QPDFObjectHandle::asInlineImage()
return dereference() ? obj->as<QPDF_InlineImage>() : nullptr;
}
QPDF_Integer*
QPDFObjectHandle::asInteger()
{
return dereference() ? obj->as<QPDF_Integer>() : nullptr;
}
QPDF_Name*
QPDFObjectHandle::asName()
{
@ -499,110 +493,123 @@ QPDFObjectHandle::getValueAsBool(bool& value)
// Integer accessors
QPDFObjectHandle::Integer
QPDFObjectHandle::asInteger(bool optional)
{
if (isInteger()) {
return {*this, 1U};
}
if (isNull()) {
return {*this, optional ? 3U : 2U};
}
return {*this, 0U};
}
QPDFObjectHandle::Integer::operator long long()
{
if (flags == 1U) {
if (auto ptr = oh.obj ? oh.obj->as<QPDF_Integer>() : nullptr) {
return ptr->getVal();
} else {
throw std::logic_error("object changed");
}
}
if (!flags.test(fl_valid)) {
oh.typeWarning("integer", "returning 0");
}
QTC::TC("qpdf", "QPDFObjectHandle integer returning 0");
return 0;
}
QPDFObjectHandle::Integer::operator int()
{
auto value = operator long long();
if (value < INT_MIN) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN");
oh.warnIfPossible("requested value of integer is too small; returning INT_MIN");
return INT_MIN;
}
if (value > INT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX");
oh.warnIfPossible("requested value of integer is too big; returning INT_MAX");
return INT_MAX;
}
return static_cast<int>(value);
}
QPDFObjectHandle::Integer::operator unsigned long long()
{
auto value = operator long long();
if (value < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning 0");
oh.warnIfPossible("unsigned value request for negative number; returning 0");
return 0;
}
return static_cast<unsigned long long>(value);
}
QPDFObjectHandle::Integer::operator unsigned int()
{
auto value = operator long long();
if (value < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0");
oh.warnIfPossible("unsigned integer value request for negative number; returning 0");
return 0;
}
if (value > UINT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX");
oh.warnIfPossible("requested value of unsigned integer is too big; returning UINT_MAX");
return UINT_MAX;
}
return static_cast<unsigned int>(value);
}
long long
QPDFObjectHandle::getIntValue()
{
auto integer = asInteger();
if (integer) {
return integer->getVal();
} else {
typeWarning("integer", "returning 0");
QTC::TC("qpdf", "QPDFObjectHandle integer returning 0");
return 0;
}
return asInteger();
}
bool
QPDFObjectHandle::getValueAsInt(long long& value)
{
auto integer = asInteger();
if (integer == nullptr) {
return false;
}
value = integer->getVal();
return true;
return asInteger().assign_to(value);
}
int
QPDFObjectHandle::getIntValueAsInt()
{
int result = 0;
long long v = getIntValue();
if (v < INT_MIN) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN");
warnIfPossible("requested value of integer is too small; returning INT_MIN");
result = INT_MIN;
} else if (v > INT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX");
warnIfPossible("requested value of integer is too big; returning INT_MAX");
result = INT_MAX;
} else {
result = static_cast<int>(v);
}
return result;
return asInteger();
}
bool
QPDFObjectHandle::getValueAsInt(int& value)
{
if (!isInteger()) {
return false;
}
value = getIntValueAsInt();
return true;
return asInteger().assign_to(value);
}
unsigned long long
QPDFObjectHandle::getUIntValue()
{
unsigned long long result = 0;
long long v = getIntValue();
if (v < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning 0");
warnIfPossible("unsigned value request for negative number; returning 0");
} else {
result = static_cast<unsigned long long>(v);
}
return result;
return asInteger();
}
bool
QPDFObjectHandle::getValueAsUInt(unsigned long long& value)
{
if (!isInteger()) {
return false;
}
value = getUIntValue();
return true;
return asInteger().assign_to(value);
}
unsigned int
QPDFObjectHandle::getUIntValueAsUInt()
{
unsigned int result = 0;
long long v = getIntValue();
if (v < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0");
warnIfPossible("unsigned integer value request for negative number; returning 0");
result = 0;
} else if (v > UINT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX");
warnIfPossible("requested value of unsigned integer is too big; returning UINT_MAX");
result = UINT_MAX;
} else {
result = static_cast<unsigned int>(v);
}
return result;
return asInteger();
}
bool
QPDFObjectHandle::getValueAsUInt(unsigned int& value)
{
if (!isInteger()) {
return false;
}
value = getUIntValueAsUInt();
return true;
return asInteger().assign_to(value);
}
// Real accessors