summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorWei Li <weili@chromium.org>2016-01-29 17:30:25 -0800
committerWei Li <weili@chromium.org>2016-01-29 17:30:25 -0800
commitdf1ab41e000069dda7bf21527308f3bf41e126ca (patch)
tree12926f62e7f0c512dcf8b2a5047d97c633358698 /core/src
parent6902db5cbaf0afb8f2cb4df325e1a4e7d6acd53f (diff)
downloadpdfium-df1ab41e000069dda7bf21527308f3bf41e126ca.tar.xz
Refactor CPDF_Object and its subclasses.
Mainly use virtual functions to replace functions with switch statements. Also remove a few unused functions and make some format changes. BUG=pdfium:63 R=thestig@chromium.org Review URL: https://codereview.chromium.org/1634373003 .
Diffstat (limited to 'core/src')
-rw-r--r--core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp2
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp594
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp535
3 files changed, 506 insertions, 625 deletions
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp
index 9296cd6158..3791f5fec0 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp
@@ -49,7 +49,7 @@ CPDF_Image* CPDF_Image::Clone() {
return m_pDocument->GetPageData()->GetImage(m_pStream);
CPDF_Image* pImage = new CPDF_Image(m_pDocument);
- pImage->LoadImageF(ToStream(m_pStream->CPDF_Object::Clone()), m_bInline);
+ pImage->LoadImageF(ToStream(m_pStream->Clone()), m_bInline);
if (m_bInline)
pImage->SetInlineDict(ToDictionary(m_pInlineDict->Clone(TRUE)));
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
index 6b512949ae..813c18a4c5 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp
@@ -12,382 +12,38 @@
#include "core/include/fxcrt/fx_string.h"
#include "third_party/base/stl_util.h"
-namespace {
-
-const FX_DWORD kBlockSize = 1024;
-
-} // namespace
-
void CPDF_Object::Release() {
if (m_ObjNum) {
return;
}
Destroy();
}
-void CPDF_Object::Destroy() {
- switch (m_Type) {
- case STRING:
- delete AsString();
- break;
- case NAME:
- delete AsName();
- break;
- case ARRAY:
- delete AsArray();
- break;
- case DICTIONARY:
- delete AsDictionary();
- break;
- case STREAM:
- delete AsStream();
- break;
- default:
- delete this;
- }
-}
-
-const CPDF_Object* CPDF_Object::GetBasicObject() const {
- const CPDF_Reference* pRef = AsReference();
- if (!pRef) {
- // This is not an indirect reference.
- return this;
- }
- if (!pRef->m_pObjList)
- return nullptr;
- return pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum());
-}
-
-CFX_ByteString CPDF_Object::GetString() const {
- const CPDF_Object* obj = GetBasicObject();
- if (obj) {
- switch (obj->GetType()) {
- case BOOLEAN:
- return obj->AsBoolean()->GetString();
- case NUMBER:
- return obj->AsNumber()->GetString();
- case STRING:
- return obj->AsString()->GetString();
- case NAME:
- return obj->AsName()->GetString();
- default:
- break;
- }
- }
- return CFX_ByteString();
-}
-
-CFX_ByteStringC CPDF_Object::GetConstString() const {
- const CPDF_Object* obj = GetBasicObject();
- if (obj) {
- FX_DWORD type = obj->GetType();
- if (type == STRING) {
- CFX_ByteString str = obj->AsString()->GetString();
- return CFX_ByteStringC(str);
- }
- if (type == NAME) {
- CFX_ByteString name = obj->AsName()->GetString();
- return CFX_ByteStringC(name);
- }
- }
- return CFX_ByteStringC();
-}
-
-FX_FLOAT CPDF_Object::GetNumber() const {
- const CPDF_Object* obj = GetBasicObject();
- if (obj && obj->GetType() == NUMBER)
- return obj->AsNumber()->GetNumber();
- return 0;
-}
-
-FX_FLOAT CPDF_Object::GetNumber16() const {
- return GetNumber();
-}
-
-int CPDF_Object::GetInteger() const {
- const CPDF_Object* obj = GetBasicObject();
- if (obj) {
- FX_DWORD type = obj->GetType();
- if (type == BOOLEAN)
- return obj->AsBoolean()->GetValue();
- if (type == NUMBER)
- return obj->AsNumber()->GetInteger();
- }
- return 0;
-}
-
-CPDF_Dictionary* CPDF_Object::GetDict() const {
- const CPDF_Object* obj = GetBasicObject();
- if (obj) {
- FX_DWORD type = obj->GetType();
- if (type == DICTIONARY) {
- // The method should be made non-const if we want to not be const.
- // See bug #234.
- return const_cast<CPDF_Dictionary*>(obj->AsDictionary());
- }
- if (type == STREAM)
- return obj->AsStream()->GetDict();
- }
- return nullptr;
-}
-
-CPDF_Array* CPDF_Object::GetArray() const {
- // The method should be made non-const if we want to not be const.
- // See bug #234.
- return const_cast<CPDF_Array*>(AsArray());
-}
-
-void CPDF_Object::SetString(const CFX_ByteString& str) {
- switch (m_Type) {
- case BOOLEAN:
- AsBoolean()->m_bValue = (str == "true");
- return;
- case NUMBER:
- AsNumber()->SetString(str);
- return;
- case STRING:
- AsString()->m_String = str;
- return;
- case NAME:
- AsName()->m_Name = str;
- return;
- default:
- break;
- }
- ASSERT(FALSE);
-}
-FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const {
- if (this == pOther)
- return TRUE;
- if (!pOther)
- return FALSE;
- if (pOther->m_Type != m_Type) {
- if (IsReference() && GetDirect())
- return GetDirect()->IsIdentical(pOther);
- if (pOther->IsReference())
- return IsIdentical(pOther->GetDirect());
- return FALSE;
- }
- switch (m_Type) {
- case BOOLEAN:
- return AsBoolean()->Identical(pOther->AsBoolean());
- case NUMBER:
- return AsNumber()->Identical(pOther->AsNumber());
- case STRING:
- return AsString()->Identical(pOther->AsString());
- case NAME:
- return AsName()->Identical(pOther->AsName());
- case ARRAY:
- return AsArray()->Identical(pOther->AsArray());
- case DICTIONARY:
- return AsDictionary()->Identical(pOther->AsDictionary());
- case NULLOBJ:
- return TRUE;
- case STREAM:
- return AsStream()->Identical(pOther->AsStream());
- case REFERENCE:
- return AsReference()->Identical(pOther->AsReference());
- }
- return FALSE;
-}
-
-CPDF_Object* CPDF_Object::GetDirect() const {
- const CPDF_Reference* pRef = AsReference();
- if (!pRef)
- return const_cast<CPDF_Object*>(this);
- if (!pRef->m_pObjList)
- return nullptr;
- return pRef->m_pObjList->GetIndirectObject(pRef->GetRefObjNum());
-}
-
-CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const {
- std::set<FX_DWORD> visited;
- return CloneInternal(bDirect, &visited);
-}
-CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect,
- std::set<FX_DWORD>* visited) const {
- switch (m_Type) {
- case BOOLEAN:
- return new CPDF_Boolean(AsBoolean()->m_bValue);
- case NUMBER: {
- const CPDF_Number* pThis = AsNumber();
- return new CPDF_Number(pThis->m_bInteger ? pThis->m_Integer
- : pThis->m_Float);
- }
- case STRING: {
- const CPDF_String* pString = AsString();
- return new CPDF_String(pString->m_String, pString->IsHex());
- }
- case NAME:
- return new CPDF_Name(AsName()->m_Name);
- case ARRAY: {
- CPDF_Array* pCopy = new CPDF_Array();
- const CPDF_Array* pThis = AsArray();
- int n = pThis->GetCount();
- for (int i = 0; i < n; i++) {
- CPDF_Object* value = pThis->m_Objects.GetAt(i);
- pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited));
- }
- return pCopy;
- }
- case DICTIONARY: {
- CPDF_Dictionary* pCopy = new CPDF_Dictionary();
- const CPDF_Dictionary* pThis = AsDictionary();
- for (const auto& it : *pThis) {
- pCopy->m_Map.insert(std::make_pair(
- it.first, it.second->CloneInternal(bDirect, visited)));
- }
- return pCopy;
- }
- case NULLOBJ: {
- return new CPDF_Null;
- }
- case STREAM: {
- const CPDF_Stream* pThis = AsStream();
- CPDF_StreamAcc acc;
- acc.LoadAllData(pThis, TRUE);
- FX_DWORD streamSize = acc.GetSize();
- CPDF_Dictionary* pDict = pThis->GetDict();
- if (pDict) {
- pDict = ToDictionary(pDict->CloneInternal(bDirect, visited));
- }
- return new CPDF_Stream(acc.DetachData(), streamSize, pDict);
- }
- case REFERENCE: {
- const CPDF_Reference* pRef = AsReference();
- FX_DWORD obj_num = pRef->GetRefObjNum();
- if (bDirect && !pdfium::ContainsKey(*visited, obj_num)) {
- visited->insert(obj_num);
- auto* pDirect = pRef->GetDirect();
- return pDirect ? pDirect->CloneInternal(TRUE, visited) : nullptr;
- }
- return new CPDF_Reference(pRef->m_pObjList, obj_num);
- }
- }
- return NULL;
-}
-CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjectHolder* pDoc) const {
- if (m_ObjNum) {
- return new CPDF_Reference(pDoc, m_ObjNum);
- }
- return Clone();
-}
-CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const {
- if (const CPDF_String* pString = AsString())
- return PDF_DecodeText(pString->m_String, pCharMap);
-
- if (const CPDF_Stream* pStream = AsStream()) {
- CPDF_StreamAcc stream;
- stream.LoadAllData(pStream, FALSE);
- CFX_WideString result =
- PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
- return result;
- }
- if (const CPDF_Name* pName = AsName())
- return PDF_DecodeText(pName->m_Name, pCharMap);
- return CFX_WideString();
-}
-void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) {
- if (CPDF_String* pString = AsString()) {
- pString->m_String = PDF_EncodeText(pUnicodes, len);
- } else if (CPDF_Stream* pStream = AsStream()) {
- CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
- pStream->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE,
- FALSE);
- }
-}
-
-CPDF_Array* CPDF_Object::AsArray() {
- return IsArray() ? static_cast<CPDF_Array*>(this) : nullptr;
-}
-
-const CPDF_Array* CPDF_Object::AsArray() const {
- return IsArray() ? static_cast<const CPDF_Array*>(this) : nullptr;
-}
-CPDF_Boolean* CPDF_Object::AsBoolean() {
- return IsBoolean() ? static_cast<CPDF_Boolean*>(this) : nullptr;
-}
-
-const CPDF_Boolean* CPDF_Object::AsBoolean() const {
- return IsBoolean() ? static_cast<const CPDF_Boolean*>(this) : nullptr;
-}
-
-CPDF_Dictionary* CPDF_Object::AsDictionary() {
- return IsDictionary() ? static_cast<CPDF_Dictionary*>(this) : nullptr;
-}
-
-const CPDF_Dictionary* CPDF_Object::AsDictionary() const {
- return IsDictionary() ? static_cast<const CPDF_Dictionary*>(this) : nullptr;
-}
-
-CPDF_Name* CPDF_Object::AsName() {
- return IsName() ? static_cast<CPDF_Name*>(this) : nullptr;
-}
-
-const CPDF_Name* CPDF_Object::AsName() const {
- return IsName() ? static_cast<const CPDF_Name*>(this) : nullptr;
-}
-
-CPDF_Number* CPDF_Object::AsNumber() {
- return IsNumber() ? static_cast<CPDF_Number*>(this) : nullptr;
-}
-
-const CPDF_Number* CPDF_Object::AsNumber() const {
- return IsNumber() ? static_cast<const CPDF_Number*>(this) : nullptr;
-}
-
-CPDF_Reference* CPDF_Object::AsReference() {
- return IsReference() ? static_cast<CPDF_Reference*>(this) : nullptr;
-}
-
-const CPDF_Reference* CPDF_Object::AsReference() const {
- return IsReference() ? static_cast<const CPDF_Reference*>(this) : nullptr;
+CPDF_Number::CPDF_Number(const CFX_ByteStringC& str) {
+ FX_atonum(str, m_bInteger, &m_Integer);
}
-CPDF_Stream* CPDF_Object::AsStream() {
- return IsStream() ? static_cast<CPDF_Stream*>(this) : nullptr;
+void CPDF_Number::SetString(const CFX_ByteString& str) {
+ FX_atonum(str, m_bInteger, &m_Integer);
}
-const CPDF_Stream* CPDF_Object::AsStream() const {
- return IsStream() ? static_cast<const CPDF_Stream*>(this) : nullptr;
+CFX_ByteString CPDF_Number::GetString() const {
+ return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED)
+ : CFX_ByteString::FormatFloat(m_Float);
}
-CPDF_String* CPDF_Object::AsString() {
- return IsString() ? static_cast<CPDF_String*>(this) : nullptr;
+CPDF_String::CPDF_String(const CFX_WideString& str) : m_bHex(FALSE) {
+ m_String = PDF_EncodeText(str);
}
-const CPDF_String* CPDF_Object::AsString() const {
- return IsString() ? static_cast<const CPDF_String*>(this) : nullptr;
+CFX_WideString CPDF_String::GetUnicodeText(CFX_CharMap* pCharMap) const {
+ return PDF_DecodeText(m_String, pCharMap);
}
-CPDF_Number::CPDF_Number(int value)
- : CPDF_Object(NUMBER), m_bInteger(TRUE), m_Integer(value) {}
-
-CPDF_Number::CPDF_Number(FX_FLOAT value)
- : CPDF_Object(NUMBER), m_bInteger(FALSE), m_Float(value) {}
-
-CPDF_Number::CPDF_Number(const CFX_ByteStringC& str) : CPDF_Object(NUMBER) {
- FX_atonum(str, m_bInteger, &m_Integer);
+CFX_WideString CPDF_Name::GetUnicodeText(CFX_CharMap* pCharMap) const {
+ return PDF_DecodeText(m_Name, pCharMap);
}
-void CPDF_Number::SetString(const CFX_ByteStringC& str) {
- FX_atonum(str, m_bInteger, &m_Integer);
-}
-FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const {
- return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer;
-}
-CFX_ByteString CPDF_Number::GetString() const {
- return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED)
- : CFX_ByteString::FormatFloat(m_Float);
-}
-void CPDF_Number::SetNumber(FX_FLOAT value) {
- m_bInteger = FALSE;
- m_Float = value;
-}
-CPDF_String::CPDF_String(const CFX_WideString& str)
- : CPDF_Object(STRING), m_bHex(FALSE) {
- m_String = PDF_EncodeText(str);
-}
CPDF_Array::~CPDF_Array() {
int size = m_Objects.GetSize();
CPDF_Object** pList = m_Objects.GetData();
@@ -396,6 +52,16 @@ CPDF_Array::~CPDF_Array() {
pList[i]->Release();
}
}
+
+CPDF_Object* CPDF_Array::Clone(FX_BOOL bDirect) const {
+ CPDF_Array* pCopy = new CPDF_Array();
+ for (int i = 0; i < GetCount(); i++) {
+ CPDF_Object* value = m_Objects.GetAt(i);
+ pCopy->m_Objects.Add(value->Clone(bDirect));
+ }
+ return pCopy;
+}
+
CFX_FloatRect CPDF_Array::GetRect() {
CFX_FloatRect rect;
if (!IsArray() || m_Objects.GetSize() != 4)
@@ -407,6 +73,7 @@ CFX_FloatRect CPDF_Array::GetRect() {
rect.top = GetNumberAt(3);
return rect;
}
+
CFX_Matrix CPDF_Array::GetMatrix() {
CFX_Matrix matrix;
if (!IsArray() || m_Objects.GetSize() != 6)
@@ -416,36 +83,43 @@ CFX_Matrix CPDF_Array::GetMatrix() {
GetNumberAt(4), GetNumberAt(5));
return matrix;
}
+
CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const {
if (i >= (FX_DWORD)m_Objects.GetSize())
return nullptr;
return m_Objects.GetAt(i);
}
+
CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const {
if (i >= (FX_DWORD)m_Objects.GetSize())
return nullptr;
return m_Objects.GetAt(i)->GetDirect();
}
+
CFX_ByteString CPDF_Array::GetStringAt(FX_DWORD i) const {
if (i >= (FX_DWORD)m_Objects.GetSize())
return CFX_ByteString();
return m_Objects.GetAt(i)->GetString();
}
+
CFX_ByteStringC CPDF_Array::GetConstStringAt(FX_DWORD i) const {
if (i >= (FX_DWORD)m_Objects.GetSize())
return CFX_ByteStringC();
return m_Objects.GetAt(i)->GetConstString();
}
+
int CPDF_Array::GetIntegerAt(FX_DWORD i) const {
if (i >= (FX_DWORD)m_Objects.GetSize())
return 0;
return m_Objects.GetAt(i)->GetInteger();
}
+
FX_FLOAT CPDF_Array::GetNumberAt(FX_DWORD i) const {
if (i >= (FX_DWORD)m_Objects.GetSize())
return 0;
return m_Objects.GetAt(i)->GetNumber();
}
+
CPDF_Dictionary* CPDF_Array::GetDictAt(FX_DWORD i) const {
CPDF_Object* p = GetElementValue(i);
if (!p)
@@ -456,12 +130,15 @@ CPDF_Dictionary* CPDF_Array::GetDictAt(FX_DWORD i) const {
return pStream->GetDict();
return NULL;
}
+
CPDF_Stream* CPDF_Array::GetStreamAt(FX_DWORD i) const {
return ToStream(GetElementValue(i));
}
+
CPDF_Array* CPDF_Array::GetArrayAt(FX_DWORD i) const {
return ToArray(GetElementValue(i));
}
+
void CPDF_Array::RemoveAt(FX_DWORD i, int nCount) {
if (i >= (FX_DWORD)m_Objects.GetSize())
return;
@@ -475,6 +152,7 @@ void CPDF_Array::RemoveAt(FX_DWORD i, int nCount) {
}
m_Objects.RemoveAt(i, nCount);
}
+
void CPDF_Array::SetAt(FX_DWORD i,
CPDF_Object* pObj,
CPDF_IndirectObjectHolder* pObjs) {
@@ -490,6 +168,7 @@ void CPDF_Array::SetAt(FX_DWORD i,
}
m_Objects.SetAt(i, pObj);
}
+
void CPDF_Array::InsertAt(FX_DWORD index,
CPDF_Object* pObj,
CPDF_IndirectObjectHolder* pObjs) {
@@ -499,6 +178,7 @@ void CPDF_Array::InsertAt(FX_DWORD index,
}
m_Objects.InsertAt(index, pObj);
}
+
void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) {
if (pObj->GetObjNum()) {
ASSERT(pObjs);
@@ -506,44 +186,47 @@ void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjectHolder* pObjs) {
}
m_Objects.Add(pObj);
}
+
void CPDF_Array::AddName(const CFX_ByteString& str) {
ASSERT(IsArray());
Add(new CPDF_Name(str));
}
+
void CPDF_Array::AddString(const CFX_ByteString& str) {
ASSERT(IsArray());
Add(new CPDF_String(str, FALSE));
}
+
void CPDF_Array::AddInteger(int i) {
ASSERT(IsArray());
Add(new CPDF_Number(i));
}
+
void CPDF_Array::AddNumber(FX_FLOAT f) {
ASSERT(IsArray());
- CPDF_Number* pNumber = new CPDF_Number;
- pNumber->SetNumber(f);
+ CPDF_Number* pNumber = new CPDF_Number(f);
Add(pNumber);
}
+
void CPDF_Array::AddReference(CPDF_IndirectObjectHolder* pDoc,
FX_DWORD objnum) {
ASSERT(IsArray());
Add(new CPDF_Reference(pDoc, objnum));
}
-FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const {
- if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) {
- return FALSE;
- }
- for (int i = 0; i < m_Objects.GetSize(); i++) {
- if (!m_Objects[i]->IsIdentical(pOther->m_Objects[i]))
- return FALSE;
- }
- return TRUE;
-}
+
CPDF_Dictionary::~CPDF_Dictionary() {
for (const auto& it : m_Map) {
it.second->Release();
}
}
+
+CPDF_Object* CPDF_Dictionary::Clone(FX_BOOL bDirect) const {
+ CPDF_Dictionary* pCopy = new CPDF_Dictionary();
+ for (const auto& it : *this)
+ pCopy->m_Map.insert(std::make_pair(it.first, it.second->Clone(bDirect)));
+ return pCopy;
+}
+
CPDF_Object* CPDF_Dictionary::GetElement(const CFX_ByteStringC& key) const {
auto it = m_Map.find(key);
if (it == m_Map.end())
@@ -555,6 +238,7 @@ CPDF_Object* CPDF_Dictionary::GetElementValue(
CPDF_Object* p = GetElement(key);
return p ? p->GetDirect() : nullptr;
}
+
CFX_ByteString CPDF_Dictionary::GetStringBy(const CFX_ByteStringC& key) const {
CPDF_Object* p = GetElement(key);
if (p) {
@@ -562,6 +246,7 @@ CFX_ByteString CPDF_Dictionary::GetStringBy(const CFX_ByteStringC& key) const {
}
return CFX_ByteString();
}
+
CFX_ByteStringC CPDF_Dictionary::GetConstStringBy(
const CFX_ByteStringC& key) const {
CPDF_Object* p = GetElement(key);
@@ -570,6 +255,7 @@ CFX_ByteStringC CPDF_Dictionary::GetConstStringBy(
}
return CFX_ByteStringC();
}
+
CFX_WideString CPDF_Dictionary::GetUnicodeTextBy(const CFX_ByteStringC& key,
CFX_CharMap* pCharMap) const {
CPDF_Object* p = GetElement(key);
@@ -577,6 +263,7 @@ CFX_WideString CPDF_Dictionary::GetUnicodeTextBy(const CFX_ByteStringC& key,
p = pRef->GetDirect();
return p ? p->GetUnicodeText(pCharMap) : CFX_WideString();
}
+
CFX_ByteString CPDF_Dictionary::GetStringBy(const CFX_ByteStringC& key,
const CFX_ByteStringC& def) const {
CPDF_Object* p = GetElement(key);
@@ -585,6 +272,7 @@ CFX_ByteString CPDF_Dictionary::GetStringBy(const CFX_ByteStringC& key,
}
return CFX_ByteString(def);
}
+
CFX_ByteStringC CPDF_Dictionary::GetConstStringBy(
const CFX_ByteStringC& key,
const CFX_ByteStringC& def) const {
@@ -594,6 +282,7 @@ CFX_ByteStringC CPDF_Dictionary::GetConstStringBy(
}
return CFX_ByteStringC(def);
}
+
int CPDF_Dictionary::GetIntegerBy(const CFX_ByteStringC& key) const {
CPDF_Object* p = GetElement(key);
if (p) {
@@ -601,6 +290,7 @@ int CPDF_Dictionary::GetIntegerBy(const CFX_ByteStringC& key) const {
}
return 0;
}
+
int CPDF_Dictionary::GetIntegerBy(const CFX_ByteStringC& key, int def) const {
CPDF_Object* p = GetElement(key);
if (p) {
@@ -608,6 +298,7 @@ int CPDF_Dictionary::GetIntegerBy(const CFX_ByteStringC& key, int def) const {
}
return def;
}
+
FX_FLOAT CPDF_Dictionary::GetNumberBy(const CFX_ByteStringC& key) const {
CPDF_Object* p = GetElement(key);
if (p) {
@@ -615,6 +306,7 @@ FX_FLOAT CPDF_Dictionary::GetNumberBy(const CFX_ByteStringC& key) const {
}
return 0;
}
+
FX_BOOL CPDF_Dictionary::GetBooleanBy(const CFX_ByteStringC& key,
FX_BOOL bDefault) const {
CPDF_Object* p = GetElement(key);
@@ -622,6 +314,7 @@ FX_BOOL CPDF_Dictionary::GetBooleanBy(const CFX_ByteStringC& key,
return p->GetInteger();
return bDefault;
}
+
CPDF_Dictionary* CPDF_Dictionary::GetDictBy(const CFX_ByteStringC& key) const {
CPDF_Object* p = GetElementValue(key);
if (!p)
@@ -632,12 +325,15 @@ CPDF_Dictionary* CPDF_Dictionary::GetDictBy(const CFX_ByteStringC& key) const {
return pStream->GetDict();
return nullptr;
}
+
CPDF_Array* CPDF_Dictionary::GetArrayBy(const CFX_ByteStringC& key) const {
return ToArray(GetElementValue(key));
}
+
CPDF_Stream* CPDF_Dictionary::GetStreamBy(const CFX_ByteStringC& key) const {
return ToStream(GetElementValue(key));
}
+
CFX_FloatRect CPDF_Dictionary::GetRectBy(const CFX_ByteStringC& key) const {
CFX_FloatRect rect;
CPDF_Array* pArray = GetArrayBy(key);
@@ -645,6 +341,7 @@ CFX_FloatRect CPDF_Dictionary::GetRectBy(const CFX_ByteStringC& key) const {
rect = pArray->GetRect();
return rect;
}
+
CFX_Matrix CPDF_Dictionary::GetMatrixBy(const CFX_ByteStringC& key) const {
CFX_Matrix matrix;
CPDF_Array* pArray = GetArrayBy(key);
@@ -652,6 +349,7 @@ CFX_Matrix CPDF_Dictionary::GetMatrixBy(const CFX_ByteStringC& key) const {
matrix = pArray->GetMatrix();
return matrix;
}
+
FX_BOOL CPDF_Dictionary::KeyExist(const CFX_ByteStringC& key) const {
return pdfium::ContainsKey(m_Map, key);
}
@@ -677,8 +375,8 @@ void CPDF_Dictionary::SetAt(const CFX_ByteStringC& key, CPDF_Object* pObj) {
else
m_Map.erase(it);
}
+
void CPDF_Dictionary::RemoveAt(const CFX_ByteStringC& key) {
- ASSERT(m_Type == DICTIONARY);
auto it = m_Map.find(key);
if (it == m_Map.end())
return;
@@ -686,9 +384,9 @@ void CPDF_Dictionary::RemoveAt(const CFX_ByteStringC& key) {
it->second->Release();
m_Map.erase(it);
}
+
void CPDF_Dictionary::ReplaceKey(const CFX_ByteStringC& oldkey,
const CFX_ByteStringC& newkey) {
- ASSERT(m_Type == DICTIONARY);
auto old_it = m_Map.find(oldkey);
if (old_it == m_Map.end())
return;
@@ -707,49 +405,42 @@ void CPDF_Dictionary::ReplaceKey(const CFX_ByteStringC& oldkey,
}
m_Map.erase(old_it);
}
-FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const {
- if (!pOther) {
- return FALSE;
- }
- if (m_Map.size() != pOther->m_Map.size()) {
- return FALSE;
- }
- for (const auto& it : m_Map) {
- const CFX_ByteString& key = it.first;
- if (!it.second->IsIdentical(pOther->GetElement(key)))
- return FALSE;
- }
- return TRUE;
-}
+
void CPDF_Dictionary::SetAtInteger(const CFX_ByteStringC& key, int i) {
SetAt(key, new CPDF_Number(i));
}
+
void CPDF_Dictionary::SetAtName(const CFX_ByteStringC& key,
const CFX_ByteString& name) {
SetAt(key, new CPDF_Name(name));
}
+
void CPDF_Dictionary::SetAtString(const CFX_ByteStringC& key,
const CFX_ByteString& str) {
SetAt(key, new CPDF_String(str, FALSE));
}
+
void CPDF_Dictionary::SetAtReference(const CFX_ByteStringC& key,
CPDF_IndirectObjectHolder* pDoc,
FX_DWORD objnum) {
SetAt(key, new CPDF_Reference(pDoc, objnum));
}
+
void CPDF_Dictionary::AddReference(const CFX_ByteStringC& key,
CPDF_IndirectObjectHolder* pDoc,
FX_DWORD objnum) {
SetAt(key, new CPDF_Reference(pDoc, objnum));
}
+
void CPDF_Dictionary::SetAtNumber(const CFX_ByteStringC& key, FX_FLOAT f) {
- CPDF_Number* pNumber = new CPDF_Number;
- pNumber->SetNumber(f);
+ CPDF_Number* pNumber = new CPDF_Number(f);
SetAt(key, pNumber);
}
+
void CPDF_Dictionary::SetAtBoolean(const CFX_ByteStringC& key, FX_BOOL bValue) {
SetAt(key, new CPDF_Boolean(bValue));
}
+
void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key,
const CFX_FloatRect& rect) {
CPDF_Array* pArray = new CPDF_Array;
@@ -759,6 +450,7 @@ void CPDF_Dictionary::SetAtRect(const CFX_ByteStringC& key,
pArray->AddNumber(rect.top);
SetAt(key, pArray);
}
+
void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key,
const CFX_Matrix& matrix) {
CPDF_Array* pArray = new CPDF_Array;
@@ -770,9 +462,9 @@ void CPDF_Dictionary::SetAtMatrix(const CFX_ByteStringC& key,
pArray->AddNumber(matrix.f);
SetAt(key, pArray);
}
+
CPDF_Stream::CPDF_Stream(uint8_t* pData, FX_DWORD size, CPDF_Dictionary* pDict)
- : CPDF_Object(STREAM),
- m_pDict(pDict),
+ : m_pDict(pDict),
m_dwSize(size),
m_GenNum(kMemoryBasedGenNum),
m_pDataBuf(pData) {}
@@ -812,6 +504,18 @@ void CPDF_Stream::InitStream(uint8_t* pData,
m_pDict->SetAtInteger("Length", size);
}
}
+
+CPDF_Object* CPDF_Stream::Clone(FX_BOOL bDirect) const {
+ CPDF_StreamAcc acc;
+ acc.LoadAllData(this, TRUE);
+ FX_DWORD streamSize = acc.GetSize();
+ CPDF_Dictionary* pDict = GetDict();
+ if (pDict) {
+ pDict = ToDictionary(pDict->Clone(bDirect));
+ }
+ return new CPDF_Stream(acc.DetachData(), streamSize, pDict);
+}
+
void CPDF_Stream::SetData(const uint8_t* pData,
FX_DWORD size,
FX_BOOL bCompressed,
@@ -821,7 +525,7 @@ void CPDF_Stream::SetData(const uint8_t* pData,
m_GenNum = kMemoryBasedGenNum;
if (bKeepBuf) {
- m_pDataBuf = (uint8_t*)pData;
+ m_pDataBuf = const_cast<uint8_t*>(pData);
} else {
m_pDataBuf = FX_Alloc(uint8_t, size);
if (pData) {
@@ -837,6 +541,7 @@ void CPDF_Stream::SetData(const uint8_t* pData,
m_pDict->RemoveAt("DecodeParms");
}
}
+
FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset,
uint8_t* buf,
FX_DWORD size) const {
@@ -857,72 +562,10 @@ void CPDF_Stream::InitStreamFromFile(IFX_FileRead* pFile,
}
}
-FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const {
- if (!m_pDict)
- return !pOther->m_pDict;
-
- if (!m_pDict->Identical(pOther->m_pDict))
- return FALSE;
-
- if (m_dwSize != pOther->m_dwSize)
- return FALSE;
-
- if (!IsMemoryBased() && !pOther->IsMemoryBased()) {
- if (m_pFile == pOther->m_pFile && !m_pFile)
- return TRUE;
-
- if (!m_pFile || !pOther->m_pFile)
- return FALSE;
-
- uint8_t srcBuf[kBlockSize];
- uint8_t destBuf[kBlockSize];
- FX_DWORD size = m_dwSize;
- if (m_pFile == pOther->m_pFile)
- return TRUE;
-
- FX_DWORD offset = 0;
- while (size > 0) {
- FX_DWORD actualSize = std::min(size, kBlockSize);
- m_pFile->ReadBlock(srcBuf, offset, actualSize);
- pOther->m_pFile->ReadBlock(destBuf, offset, actualSize);
- if (FXSYS_memcmp(srcBuf, destBuf, actualSize) != 0)
- return FALSE;
-
- size -= actualSize;
- offset += actualSize;
- }
- return TRUE;
- }
-
- if (!IsMemoryBased() || !pOther->IsMemoryBased()) {
- IFX_FileRead* pFile = nullptr;
- uint8_t* pBuf = nullptr;
- if (!pOther->IsMemoryBased()) {
- pFile = pOther->m_pFile;
- pBuf = m_pDataBuf;
- } else if (!IsMemoryBased()) {
- pFile = m_pFile;
- pBuf = pOther->m_pDataBuf;
- }
- if (!pBuf)
- return FALSE;
-
- uint8_t srcBuf[kBlockSize];
- FX_DWORD size = m_dwSize;
- FX_DWORD offset = 0;
- while (size > 0) {
- FX_DWORD actualSize = std::min(size, kBlockSize);
- pFile->ReadBlock(srcBuf, offset, actualSize);
- if (FXSYS_memcmp(srcBuf, pBuf, actualSize) != 0)
- return FALSE;
-
- pBuf += actualSize;
- size -= actualSize;
- offset += actualSize;
- }
- return TRUE;
- }
- return FXSYS_memcmp(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0;
+CFX_WideString CPDF_Stream::GetUnicodeText(CFX_CharMap* pCharMap) const {
+ CPDF_StreamAcc stream;
+ stream.LoadAllData(this, FALSE);
+ return PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
}
CPDF_StreamAcc::CPDF_StreamAcc() {
@@ -943,12 +586,12 @@ void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
m_pStream = pStream;
if (pStream->IsMemoryBased() &&
(!pStream->GetDict()->KeyExist("Filter") || bRawAccess)) {
- m_dwSize = pStream->m_dwSize;
- m_pData = (uint8_t*)pStream->m_pDataBuf;
+ m_dwSize = pStream->GetRawSize();
+ m_pData = pStream->GetRawData();
return;
}
uint8_t* pSrcData;
- FX_DWORD dwSrcSize = pStream->m_dwSize;
+ FX_DWORD dwSrcSize = pStream->GetRawSize();
if (dwSrcSize == 0)
return;
@@ -957,7 +600,7 @@ void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
if (!pStream->ReadRawData(0, pSrcData, dwSrcSize))
return;
} else {
- pSrcData = pStream->m_pDataBuf;
+ pSrcData = pStream->GetRawData();
}
uint8_t* pDecryptedData = pSrcData;
FX_DWORD dwDecryptedSize = dwSrcSize;
@@ -973,21 +616,23 @@ void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
m_dwSize = dwDecryptedSize;
}
}
- if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) {
+ if (pSrcData != pStream->GetRawData() && pSrcData != m_pData) {
FX_Free(pSrcData);
}
if (pDecryptedData != pSrcData && pDecryptedData != m_pData) {
FX_Free(pDecryptedData);
}
m_pSrcData = NULL;
- m_bNewBuf = m_pData != pStream->m_pDataBuf;
+ m_bNewBuf = m_pData != pStream->GetRawData();
}
+
CPDF_StreamAcc::~CPDF_StreamAcc() {
if (m_bNewBuf) {
FX_Free(m_pData);
}
FX_Free(m_pSrcData);
}
+
const uint8_t* CPDF_StreamAcc::GetData() const {
if (m_bNewBuf) {
return m_pData;
@@ -995,8 +640,9 @@ const uint8_t* CPDF_StreamAcc::GetData() const {
if (!m_pStream) {
return NULL;
}
- return m_pStream->m_pDataBuf;
+ return m_pStream->GetRawData();
}
+
FX_DWORD CPDF_StreamAcc::GetSize() const {
if (m_bNewBuf) {
return m_dwSize;
@@ -1004,8 +650,9 @@ FX_DWORD CPDF_StreamAcc::GetSize() const {
if (!m_pStream) {
return 0;
}
- return m_pStream->m_dwSize;
+ return m_pStream->GetRawSize();
}
+
uint8_t* CPDF_StreamAcc::DetachData() {
if (m_bNewBuf) {
uint8_t* p = m_pData;
@@ -1017,20 +664,36 @@ uint8_t* CPDF_StreamAcc::DetachData() {
FXSYS_memcpy(p, m_pData, m_dwSize);
return p;
}
+
+CPDF_Object* CPDF_Reference::Clone(FX_BOOL bDirect) const {
+ if (bDirect) {
+ auto* pDirect = GetDirect();
+ return pDirect ? pDirect->Clone(TRUE) : nullptr;
+ }
+ return new CPDF_Reference(m_pObjList, m_RefObjNum);
+}
+
void CPDF_Reference::SetRef(CPDF_IndirectObjectHolder* pDoc, FX_DWORD objnum) {
m_pObjList = pDoc;
m_RefObjNum = objnum;
}
+
+CPDF_Object* CPDF_Reference::GetDirect() const {
+ return m_pObjList ? m_pObjList->GetIndirectObject(m_RefObjNum) : nullptr;
+}
+
CPDF_IndirectObjectHolder::CPDF_IndirectObjectHolder(CPDF_Parser* pParser)
: m_pParser(pParser), m_LastObjNum(0) {
if (pParser)
m_LastObjNum = m_pParser->GetLastObjNum();
}
+
CPDF_IndirectObjectHolder::~CPDF_IndirectObjectHolder() {
for (const auto& pair : m_IndirectObjs) {
pair.second->Destroy();
}
}
+
CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(FX_DWORD objnum) {
if (objnum == 0)
return nullptr;
@@ -1054,6 +717,7 @@ CPDF_Object* CPDF_IndirectObjectHolder::GetIndirectObject(FX_DWORD objnum) {
m_IndirectObjs[objnum] = pObj;
return pObj;
}
+
FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) {
if (pObj->m_ObjNum) {
return pObj->m_ObjNum;
@@ -1063,6 +727,7 @@ FX_DWORD CPDF_IndirectObjectHolder::AddIndirectObject(CPDF_Object* pObj) {
pObj->m_ObjNum = m_LastObjNum;
return m_LastObjNum;
}
+
void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) {
auto it = m_IndirectObjs.find(objnum);
if (it == m_IndirectObjs.end() || it->second->GetObjNum() == -1)
@@ -1070,6 +735,7 @@ void CPDF_IndirectObjectHolder::ReleaseIndirectObject(FX_DWORD objnum) {
it->second->Destroy();
m_IndirectObjs.erase(it);
}
+
FX_BOOL CPDF_IndirectObjectHolder::InsertIndirectObject(FX_DWORD objnum,
CPDF_Object* pObj) {
if (!objnum || !pObj)
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp
index 10cfecf042..9de31c8673 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects_unittest.cpp
@@ -1,160 +1,375 @@
-// Copyright 2016 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "core/include/fpdfapi/fpdf_objects.h"
-
-#include <memory>
-#include <vector>
-
-#include "core/include/fxcrt/fx_basic.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class PDFObjectsTest : public testing::Test {
- public:
- void SetUp() override {
- // Initialize different kinds of objects.
- // Boolean objects.
- CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false);
- CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true);
- // Number objects.
- CPDF_Number* number_int_obj = new CPDF_Number(1245);
- CPDF_Number* number_float_obj = new CPDF_Number(9.00345f);
- // String objects.
- CPDF_String* str_reg_obj = new CPDF_String(L"A simple test");
- CPDF_String* str_spec_obj = new CPDF_String(L"\t\n");
- // Name object.
- CPDF_Name* name_obj = new CPDF_Name("space");
- // Array object.
- CPDF_Array* array_obj = new CPDF_Array;
- array_obj->InsertAt(0, new CPDF_Number(8902));
- array_obj->InsertAt(1, new CPDF_Name("address"));
- // Dictionary object.
- m_DictObj = new CPDF_Dictionary;
- m_DictObj->SetAt("bool", new CPDF_Boolean(false));
- m_DictObj->SetAt("num", new CPDF_Number(0.23f));
- // Stream object.
- const char content[] = "abcdefghijklmnopqrstuvwxyz";
- size_t buf_len = FX_ArraySize(content);
- uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len));
- memcpy(buf, content, buf_len);
- m_StreamDictObj = new CPDF_Dictionary;
- m_StreamDictObj->SetAt("key1", new CPDF_String(L" test dict"));
- m_StreamDictObj->SetAt("key2", new CPDF_Number(-1));
- CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj);
- // Null Object.
- CPDF_Null* null_obj = new CPDF_Null;
- // All direct objects.
- CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj,
- number_float_obj, str_reg_obj, str_spec_obj,
- name_obj, array_obj, m_DictObj,
- stream_obj, null_obj};
- for (int i = 0; i < FX_ArraySize(objs); ++i)
- m_DirectObjs.emplace_back(objs[i]);
-
- // Indirect references to indirect objects.
- m_ObjHolder.reset(new CPDF_IndirectObjectHolder(nullptr));
- CPDF_Object* referred_objs[] = {
- boolean_true_obj, number_int_obj, str_spec_obj, name_obj,
- array_obj, m_DictObj, stream_obj};
- for (int i = 0; i < FX_ArraySize(referred_objs); ++i) {
- m_ObjHolder->AddIndirectObject(referred_objs[i]);
- m_RefObjs.emplace_back(
- new CPDF_Reference(m_ObjHolder.get(), referred_objs[i]->GetObjNum()));
- }
- }
-
- protected:
- using ScopedObj = std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>>;
-
- // m_ObjHolder needs to be declared first and destructed last since it also
- // refers to some objects in m_DirectObjs.
- std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder;
- std::vector<ScopedObj> m_DirectObjs;
- std::vector<ScopedObj> m_RefObjs;
- CPDF_Dictionary* m_DictObj;
- CPDF_Dictionary* m_StreamDictObj;
-};
-
-TEST_F(PDFObjectsTest, GetString) {
- const char* direct_obj_results[] = {
- "false", "true", "1245", "9.00345", "A simple test", "\t\n", "space",
- "", "", "", ""};
- // Check for direct objects.
- for (int i = 0; i < m_DirectObjs.size(); ++i)
- EXPECT_STREQ(m_DirectObjs[i]->GetString().c_str(), direct_obj_results[i]);
-
- // Check indirect references.
- const char* indirect_obj_results[] = {"true", "1245", "\t\n", "space",
- "", "", ""};
- for (int i = 0; i < m_RefObjs.size(); ++i) {
- EXPECT_STREQ(m_RefObjs[i]->GetString().c_str(), indirect_obj_results[i]);
- }
-}
-
-TEST_F(PDFObjectsTest, GetConstString) {
- const char* direct_obj_results[] = {
- nullptr, nullptr, nullptr, nullptr, "A simple test", "\t\n",
- "space", nullptr, nullptr, nullptr, nullptr};
- // Check for direct objects.
- for (int i = 0; i < m_DirectObjs.size(); ++i) {
- if (!direct_obj_results[i]) {
- EXPECT_EQ(m_DirectObjs[i]->GetConstString().GetCStr(),
- direct_obj_results[i]);
- } else {
- EXPECT_STREQ(m_DirectObjs[i]->GetConstString().GetCStr(),
- direct_obj_results[i]);
- }
- }
- // Check indirect references.
- const char* indirect_obj_results[] = {nullptr, nullptr, "\t\n", "space",
- nullptr, nullptr, nullptr};
- for (int i = 0; i < m_RefObjs.size(); ++i) {
- if (!indirect_obj_results[i])
- EXPECT_EQ(m_RefObjs[i]->GetConstString().GetCStr(), nullptr);
- else {
- EXPECT_STREQ(m_RefObjs[i]->GetConstString().GetCStr(),
- indirect_obj_results[i]);
- }
- }
-}
-
-TEST_F(PDFObjectsTest, GetNumber) {
- const FX_FLOAT direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0,
- 0, 0, 0, 0, 0};
- // Check for direct objects.
- for (int i = 0; i < m_DirectObjs.size(); ++i)
- EXPECT_EQ(m_DirectObjs[i]->GetNumber(), direct_obj_results[i]);
-
- // Check indirect references.
- const FX_FLOAT indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0};
- for (int i = 0; i < m_RefObjs.size(); ++i)
- EXPECT_EQ(m_RefObjs[i]->GetNumber(), indirect_obj_results[i]);
-}
-
-TEST_F(PDFObjectsTest, GetInteger) {
- const int direct_obj_results[] = {0, 1, 1245, 9, 0, 0, 0, 0, 0, 0, 0};
- // Check for direct objects.
- for (int i = 0; i < m_DirectObjs.size(); ++i)
- EXPECT_EQ(m_DirectObjs[i]->GetInteger(), direct_obj_results[i]);
-
- // Check indirect references.
- const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0};
- for (int i = 0; i < m_RefObjs.size(); ++i)
- EXPECT_EQ(m_RefObjs[i]->GetInteger(), indirect_obj_results[i]);
-}
-
-TEST_F(PDFObjectsTest, GetDict) {
- const CPDF_Dictionary* direct_obj_results[] = {
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr};
- // Check for direct objects.
- for (int i = 0; i < m_DirectObjs.size(); ++i)
- EXPECT_EQ(m_DirectObjs[i]->GetDict(), direct_obj_results[i]);
-
- // Check indirect references.
- const CPDF_Dictionary* indirect_obj_results[] = {
- nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj};
- for (int i = 0; i < m_RefObjs.size(); ++i)
- EXPECT_EQ(m_RefObjs[i]->GetDict(), indirect_obj_results[i]);
-}
+// Copyright 2016 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/include/fpdfapi/fpdf_objects.h"
+
+#include <memory>
+#include <vector>
+
+#include "core/include/fxcrt/fx_basic.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class PDFObjectsTest : public testing::Test {
+ public:
+ void SetUp() override {
+ // Initialize different kinds of objects.
+ // Boolean objects.
+ CPDF_Boolean* boolean_false_obj = new CPDF_Boolean(false);
+ CPDF_Boolean* boolean_true_obj = new CPDF_Boolean(true);
+ // Number objects.
+ CPDF_Number* number_int_obj = new CPDF_Number(1245);
+ CPDF_Number* number_float_obj = new CPDF_Number(9.00345f);
+ // String objects.
+ CPDF_String* str_reg_obj = new CPDF_String(L"A simple test");
+ CPDF_String* str_spec_obj = new CPDF_String(L"\t\n");
+ // Name object.
+ CPDF_Name* name_obj = new CPDF_Name("space");
+ // Array object.
+ m_ArrayObj = new CPDF_Array;
+ m_ArrayObj->InsertAt(0, new CPDF_Number(8902));
+ m_ArrayObj->InsertAt(1, new CPDF_Name("address"));
+ // Dictionary object.
+ m_DictObj = new CPDF_Dictionary;
+ m_DictObj->SetAt("bool", new CPDF_Boolean(false));
+ m_DictObj->SetAt("num", new CPDF_Number(0.23f));
+ // Stream object.
+ const char content[] = "abcdefghijklmnopqrstuvwxyz";
+ size_t buf_len = FX_ArraySize(content);
+ uint8_t* buf = reinterpret_cast<uint8_t*>(malloc(buf_len));
+ memcpy(buf, content, buf_len);
+ m_StreamDictObj = new CPDF_Dictionary;
+ m_StreamDictObj->SetAt("key1", new CPDF_String(L" test dict"));
+ m_StreamDictObj->SetAt("key2", new CPDF_Number(-1));
+ CPDF_Stream* stream_obj = new CPDF_Stream(buf, buf_len, m_StreamDictObj);
+ // Null Object.
+ CPDF_Null* null_obj = new CPDF_Null;
+ // All direct objects.
+ CPDF_Object* objs[] = {boolean_false_obj, boolean_true_obj, number_int_obj,
+ number_float_obj, str_reg_obj, str_spec_obj,
+ name_obj, m_ArrayObj, m_DictObj,
+ stream_obj, null_obj};
+ m_DirectObjTypes = {
+ CPDF_Object::BOOLEAN, CPDF_Object::BOOLEAN, CPDF_Object::NUMBER,
+ CPDF_Object::NUMBER, CPDF_Object::STRING, CPDF_Object::STRING,
+ CPDF_Object::NAME, CPDF_Object::ARRAY, CPDF_Object::DICTIONARY,
+ CPDF_Object::STREAM, CPDF_Object::NULLOBJ};
+ for (size_t i = 0; i < FX_ArraySize(objs); ++i)
+ m_DirectObjs.emplace_back(objs[i]);
+
+ // Indirect references to indirect objects.
+ m_ObjHolder.reset(new CPDF_IndirectObjectHolder(nullptr));
+ m_IndirectObjs = {boolean_true_obj, number_int_obj, str_spec_obj, name_obj,
+ m_ArrayObj, m_DictObj, stream_obj};
+ for (size_t i = 0; i < m_IndirectObjs.size(); ++i) {
+ m_ObjHolder->AddIndirectObject(m_IndirectObjs[i]);
+ m_RefObjs.emplace_back(new CPDF_Reference(
+ m_ObjHolder.get(), m_IndirectObjs[i]->GetObjNum()));
+ }
+ }
+
+ bool Equal(CPDF_Object* obj1, CPDF_Object* obj2) {
+ if (obj1 == obj2)
+ return true;
+ if (!obj1 || !obj2 || obj1->GetType() != obj2->GetType())
+ return false;
+ switch (obj1->GetType()) {
+ case CPDF_Object::BOOLEAN:
+ return obj1->GetInteger() == obj2->GetInteger();
+ case CPDF_Object::NUMBER:
+ return obj1->AsNumber()->IsInteger() == obj2->AsNumber()->IsInteger() &&
+ obj1->GetInteger() == obj2->GetInteger();
+ case CPDF_Object::STRING:
+ case CPDF_Object::NAME:
+ return obj1->GetString() == obj2->GetString();
+ case CPDF_Object::ARRAY: {
+ const CPDF_Array* array1 = obj1->AsArray();
+ const CPDF_Array* array2 = obj2->AsArray();
+ if (array1->GetCount() != array2->GetCount())
+ return false;
+ for (size_t i = 0; i < array1->GetCount(); ++i) {
+ if (!Equal(array1->GetElement(i), array2->GetElement(i)))
+ return false;
+ }
+ return true;
+ }
+ case CPDF_Object::DICTIONARY: {
+ const CPDF_Dictionary* dict1 = obj1->AsDictionary();
+ const CPDF_Dictionary* dict2 = obj2->AsDictionary();
+ if (dict1->GetCount() != dict2->GetCount())
+ return false;
+ for (CPDF_Dictionary::const_iterator it = dict1->begin();
+ it != dict1->end(); ++it) {
+ if (!Equal(it->second, dict2->GetElement(it->first)))
+ return false;
+ }
+ return true;
+ }
+ case CPDF_Object::NULLOBJ:
+ return true;
+ case CPDF_Object::STREAM: {
+ const CPDF_Stream* stream1 = obj1->AsStream();
+ const CPDF_Stream* stream2 = obj2->AsStream();
+ if (!stream1->GetDict() && !stream2->GetDict())
+ return true;
+ // Compare dictionaries.
+ if (!Equal(stream1->GetDict(), stream2->GetDict()))
+ return false;
+ // Compare sizes.
+ if (stream1->GetRawSize() != stream2->GetRawSize())
+ return false;
+ // Compare contents.
+ // Since this function is used for testing Clone(), only memory based
+ // streams need to be handled.
+ if (!stream1->IsMemoryBased() || !stream2->IsMemoryBased())
+ return false;
+ return FXSYS_memcmp(stream1->GetRawData(), stream2->GetRawData(),
+ stream1->GetRawSize()) == 0;
+ }
+ case CPDF_Object::REFERENCE:
+ return obj1->AsReference()->GetRefObjNum() ==
+ obj2->AsReference()->GetRefObjNum();
+ }
+ return false;
+ }
+
+ protected:
+ using ScopedObj = std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>>;
+
+ // m_ObjHolder needs to be declared first and destructed last since it also
+ // refers to some objects in m_DirectObjs.
+ std::unique_ptr<CPDF_IndirectObjectHolder> m_ObjHolder;
+ std::vector<ScopedObj> m_DirectObjs;
+ std::vector<int> m_DirectObjTypes;
+ std::vector<ScopedObj> m_RefObjs;
+ CPDF_Dictionary* m_DictObj;
+ CPDF_Dictionary* m_StreamDictObj;
+ CPDF_Array* m_ArrayObj;
+ std::vector<CPDF_Object*> m_IndirectObjs;
+};
+
+TEST_F(PDFObjectsTest, GetString) {
+ const char* direct_obj_results[] = {
+ "false", "true", "1245", "9.00345", "A simple test", "\t\n", "space",
+ "", "", "", ""};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_STREQ(m_DirectObjs[i]->GetString().c_str(), direct_obj_results[i]);
+
+ // Check indirect references.
+ const char* indirect_obj_results[] = {"true", "1245", "\t\n", "space",
+ "", "", ""};
+ for (size_t i = 0; i < m_RefObjs.size(); ++i) {
+ EXPECT_STREQ(m_RefObjs[i]->GetString().c_str(), indirect_obj_results[i]);
+ }
+}
+
+TEST_F(PDFObjectsTest, GetConstString) {
+ const char* direct_obj_results[] = {
+ nullptr, nullptr, nullptr, nullptr, "A simple test", "\t\n",
+ "space", nullptr, nullptr, nullptr, nullptr};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
+ if (!direct_obj_results[i]) {
+ EXPECT_EQ(m_DirectObjs[i]->GetConstString().GetCStr(),
+ direct_obj_results[i]);
+ } else {
+ EXPECT_STREQ(m_DirectObjs[i]->GetConstString().GetCStr(),
+ direct_obj_results[i]);
+ }
+ }
+ // Check indirect references.
+ const char* indirect_obj_results[] = {nullptr, nullptr, "\t\n", "space",
+ nullptr, nullptr, nullptr};
+ for (size_t i = 0; i < m_RefObjs.size(); ++i) {
+ if (!indirect_obj_results[i]) {
+ EXPECT_EQ(m_RefObjs[i]->GetConstString().GetCStr(), nullptr);
+ } else {
+ EXPECT_STREQ(m_RefObjs[i]->GetConstString().GetCStr(),
+ indirect_obj_results[i]);
+ }
+ }
+}
+
+TEST_F(PDFObjectsTest, GetUnicodeText) {
+ const wchar_t* direct_obj_results[] = {
+ L"", L"", L"", L"", L"A simple test",
+ L"\t\n", L"space", L"", L"", L"abcdefghijklmnopqrstuvwxyz",
+ L""};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_STREQ(m_DirectObjs[i]->GetUnicodeText().c_str(),
+ direct_obj_results[i]);
+
+ // Check indirect references.
+ for (const auto& it : m_RefObjs)
+ EXPECT_STREQ(it->GetUnicodeText().c_str(), L"");
+}
+
+TEST_F(PDFObjectsTest, GetNumber) {
+ const FX_FLOAT direct_obj_results[] = {0, 0, 1245, 9.00345f, 0, 0,
+ 0, 0, 0, 0, 0};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_EQ(m_DirectObjs[i]->GetNumber(), direct_obj_results[i]);
+
+ // Check indirect references.
+ const FX_FLOAT indirect_obj_results[] = {0, 1245, 0, 0, 0, 0, 0};
+ for (size_t i = 0; i < m_RefObjs.size(); ++i)
+ EXPECT_EQ(m_RefObjs[i]->GetNumber(), indirect_obj_results[i]);
+}
+
+TEST_F(PDFObjectsTest, GetInteger) {
+ const int direct_obj_results[] = {0, 1, 1245, 9, 0, 0, 0, 0, 0, 0, 0};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_EQ(m_DirectObjs[i]->GetInteger(), direct_obj_results[i]);
+
+ // Check indirect references.
+ const int indirect_obj_results[] = {1, 1245, 0, 0, 0, 0, 0};
+ for (size_t i = 0; i < m_RefObjs.size(); ++i)
+ EXPECT_EQ(m_RefObjs[i]->GetInteger(), indirect_obj_results[i]);
+}
+
+TEST_F(PDFObjectsTest, GetDict) {
+ const CPDF_Dictionary* direct_obj_results[] = {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, m_DictObj, m_StreamDictObj, nullptr};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_EQ(m_DirectObjs[i]->GetDict(), direct_obj_results[i]);
+
+ // Check indirect references.
+ const CPDF_Dictionary* indirect_obj_results[] = {
+ nullptr, nullptr, nullptr, nullptr, nullptr, m_DictObj, m_StreamDictObj};
+ for (size_t i = 0; i < m_RefObjs.size(); ++i)
+ EXPECT_EQ(m_RefObjs[i]->GetDict(), indirect_obj_results[i]);
+}
+
+TEST_F(PDFObjectsTest, GetArray) {
+ const CPDF_Array* direct_obj_results[] = {
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, m_ArrayObj, nullptr, nullptr, nullptr};
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_EQ(m_DirectObjs[i]->GetArray(), direct_obj_results[i]);
+
+ // Check indirect references.
+ for (const auto& it : m_RefObjs)
+ EXPECT_EQ(it->GetArray(), nullptr);
+}
+
+TEST_F(PDFObjectsTest, Clone) {
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
+ ScopedObj obj(m_DirectObjs[i]->Clone());
+ EXPECT_TRUE(Equal(m_DirectObjs[i].get(), obj.get()));
+ }
+
+ // Check indirect references.
+ for (const auto& it : m_RefObjs) {
+ ScopedObj obj(it->Clone());
+ EXPECT_TRUE(Equal(it.get(), obj.get()));
+ }
+}
+
+TEST_F(PDFObjectsTest, GetType) {
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_EQ(m_DirectObjs[i]->GetType(), m_DirectObjTypes[i]);
+
+ // Check indirect references.
+ for (const auto& it : m_RefObjs)
+ EXPECT_EQ(it->GetType(), CPDF_Object::REFERENCE);
+}
+
+TEST_F(PDFObjectsTest, GetDirect) {
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i)
+ EXPECT_EQ(m_DirectObjs[i]->GetDirect(), m_DirectObjs[i].get());
+
+ // Check indirect references.
+ for (size_t i = 0; i < m_RefObjs.size(); ++i)
+ EXPECT_EQ(m_RefObjs[i]->GetDirect(), m_IndirectObjs[i]);
+}
+
+TEST_F(PDFObjectsTest, SetString) {
+ // Check for direct objects.
+ const char* const set_values[] = {"true", "fake", "3.125f", "097",
+ "changed", "", "NewName"};
+ const char* expected[] = {"true", "false", "3.125", "97",
+ "changed", "", "NewName"};
+ for (size_t i = 0; i < FX_ArraySize(set_values); ++i) {
+ m_DirectObjs[i]->SetString(set_values[i]);
+ EXPECT_STREQ(m_DirectObjs[i]->GetString().c_str(), expected[i]);
+ }
+}
+
+TEST_F(PDFObjectsTest, IsTypeAndAsType) {
+ // Check for direct objects.
+ for (size_t i = 0; i < m_DirectObjs.size(); ++i) {
+ if (m_DirectObjTypes[i] == CPDF_Object::ARRAY) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsArray());
+ EXPECT_EQ(m_DirectObjs[i]->AsArray(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsArray());
+ EXPECT_EQ(m_DirectObjs[i]->AsArray(), nullptr);
+ }
+
+ if (m_DirectObjTypes[i] == CPDF_Object::BOOLEAN) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsBoolean());
+ EXPECT_EQ(m_DirectObjs[i]->AsBoolean(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsBoolean());
+ EXPECT_EQ(m_DirectObjs[i]->AsBoolean(), nullptr);
+ }
+
+ if (m_DirectObjTypes[i] == CPDF_Object::NAME) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsName());
+ EXPECT_EQ(m_DirectObjs[i]->AsName(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsName());
+ EXPECT_EQ(m_DirectObjs[i]->AsName(), nullptr);
+ }
+
+ if (m_DirectObjTypes[i] == CPDF_Object::NUMBER) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsNumber());
+ EXPECT_EQ(m_DirectObjs[i]->AsNumber(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsNumber());
+ EXPECT_EQ(m_DirectObjs[i]->AsNumber(), nullptr);
+ }
+
+ if (m_DirectObjTypes[i] == CPDF_Object::STRING) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsString());
+ EXPECT_EQ(m_DirectObjs[i]->AsString(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsString());
+ EXPECT_EQ(m_DirectObjs[i]->AsString(), nullptr);
+ }
+
+ if (m_DirectObjTypes[i] == CPDF_Object::DICTIONARY) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsDictionary());
+ EXPECT_EQ(m_DirectObjs[i]->AsDictionary(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsDictionary());
+ EXPECT_EQ(m_DirectObjs[i]->AsDictionary(), nullptr);
+ }
+
+ if (m_DirectObjTypes[i] == CPDF_Object::STREAM) {
+ EXPECT_TRUE(m_DirectObjs[i]->IsStream());
+ EXPECT_EQ(m_DirectObjs[i]->AsStream(), m_DirectObjs[i].get());
+ } else {
+ EXPECT_FALSE(m_DirectObjs[i]->IsStream());
+ EXPECT_EQ(m_DirectObjs[i]->AsStream(), nullptr);
+ }
+
+ EXPECT_FALSE(m_DirectObjs[i]->IsReference());
+ EXPECT_EQ(m_DirectObjs[i]->AsReference(), nullptr);
+ }
+ // Check indirect references.
+ for (size_t i = 0; i < m_RefObjs.size(); ++i) {
+ EXPECT_TRUE(m_RefObjs[i]->IsReference());
+ EXPECT_EQ(m_RefObjs[i]->AsReference(), m_RefObjs[i].get());
+ }
+}