Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp

Issue 1402413004: Add type cast definitions for CPDF_Stream. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include "../../../include/fpdfapi/fpdf_parser.h" 7 #include "../../../include/fpdfapi/fpdf_parser.h"
8 #include "../../../include/fxcrt/fx_string.h" 8 #include "../../../include/fxcrt/fx_string.h"
9 9
10 // static 10 // static
(...skipping 13 matching lines...) Expand all
24 case PDFOBJ_NAME: 24 case PDFOBJ_NAME:
25 delete AsName(); 25 delete AsName();
26 break; 26 break;
27 case PDFOBJ_ARRAY: 27 case PDFOBJ_ARRAY:
28 delete AsArray(); 28 delete AsArray();
29 break; 29 break;
30 case PDFOBJ_DICTIONARY: 30 case PDFOBJ_DICTIONARY:
31 delete AsDictionary(); 31 delete AsDictionary();
32 break; 32 break;
33 case PDFOBJ_STREAM: 33 case PDFOBJ_STREAM:
34 delete (CPDF_Stream*)this; 34 delete AsStream();
35 break; 35 break;
36 default: 36 default:
37 delete this; 37 delete this;
38 } 38 }
39 } 39 }
40 CFX_ByteString CPDF_Object::GetString() const { 40 CFX_ByteString CPDF_Object::GetString() const {
41 switch (m_Type) { 41 switch (m_Type) {
42 case PDFOBJ_BOOLEAN: 42 case PDFOBJ_BOOLEAN:
43 return AsBoolean()->m_bValue ? "true" : "false"; 43 return AsBoolean()->m_bValue ? "true" : "false";
44 case PDFOBJ_NUMBER: 44 case PDFOBJ_NUMBER:
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 return 0; 137 return 0;
138 } 138 }
139 139
140 CPDF_Dictionary* CPDF_Object::GetDict() const { 140 CPDF_Dictionary* CPDF_Object::GetDict() const {
141 switch (m_Type) { 141 switch (m_Type) {
142 case PDFOBJ_DICTIONARY: 142 case PDFOBJ_DICTIONARY:
143 // The method should be made non-const if we want to not be const. 143 // The method should be made non-const if we want to not be const.
144 // See bug #234. 144 // See bug #234.
145 return const_cast<CPDF_Dictionary*>(AsDictionary()); 145 return const_cast<CPDF_Dictionary*>(AsDictionary());
146 case PDFOBJ_STREAM: 146 case PDFOBJ_STREAM:
147 return ((CPDF_Stream*)this)->GetDict(); 147 return AsStream()->GetDict();
148 case PDFOBJ_REFERENCE: { 148 case PDFOBJ_REFERENCE: {
149 CPDF_Reference* pRef = (CPDF_Reference*)this; 149 CPDF_Reference* pRef = (CPDF_Reference*)this;
150 CPDF_IndirectObjects* pIndirect = pRef->GetObjList(); 150 CPDF_IndirectObjects* pIndirect = pRef->GetObjList();
151 if (!pIndirect) 151 if (!pIndirect)
152 return nullptr; 152 return nullptr;
153 CPDF_Object* pObj = pIndirect->GetIndirectObject(pRef->GetRefObjNum()); 153 CPDF_Object* pObj = pIndirect->GetIndirectObject(pRef->GetRefObjNum());
154 if (!pObj || (pObj == this)) 154 if (!pObj || (pObj == this))
155 return nullptr; 155 return nullptr;
156 return pObj->GetDict(); 156 return pObj->GetDict();
157 } 157 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 return AsString()->Identical(pOther->AsString()); 215 return AsString()->Identical(pOther->AsString());
216 case PDFOBJ_NAME: 216 case PDFOBJ_NAME:
217 return AsName()->Identical(pOther->AsName()); 217 return AsName()->Identical(pOther->AsName());
218 case PDFOBJ_ARRAY: 218 case PDFOBJ_ARRAY:
219 return AsArray()->Identical(pOther->AsArray()); 219 return AsArray()->Identical(pOther->AsArray());
220 case PDFOBJ_DICTIONARY: 220 case PDFOBJ_DICTIONARY:
221 return AsDictionary()->Identical(pOther->AsDictionary()); 221 return AsDictionary()->Identical(pOther->AsDictionary());
222 case PDFOBJ_NULL: 222 case PDFOBJ_NULL:
223 return TRUE; 223 return TRUE;
224 case PDFOBJ_STREAM: 224 case PDFOBJ_STREAM:
225 return (((CPDF_Stream*)this)->Identical((CPDF_Stream*)pOther)); 225 return AsStream()->Identical(pOther->AsStream());
226 case PDFOBJ_REFERENCE: 226 case PDFOBJ_REFERENCE:
227 return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther)); 227 return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther));
228 } 228 }
229 return FALSE; 229 return FALSE;
230 } 230 }
231 CPDF_Object* CPDF_Object::GetDirect() const { 231 CPDF_Object* CPDF_Object::GetDirect() const {
232 if (m_Type != PDFOBJ_REFERENCE) { 232 if (m_Type != PDFOBJ_REFERENCE) {
233 return (CPDF_Object*)this; 233 return (CPDF_Object*)this;
234 } 234 }
235 CPDF_Reference* pRef = (CPDF_Reference*)(void*)this; 235 CPDF_Reference* pRef = (CPDF_Reference*)(void*)this;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 CPDF_Object* value; 277 CPDF_Object* value;
278 pThis->m_Map.GetNextAssoc(pos, key, (void*&)value); 278 pThis->m_Map.GetNextAssoc(pos, key, (void*&)value);
279 pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited)); 279 pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited));
280 } 280 }
281 return pCopy; 281 return pCopy;
282 } 282 }
283 case PDFOBJ_NULL: { 283 case PDFOBJ_NULL: {
284 return new CPDF_Null; 284 return new CPDF_Null;
285 } 285 }
286 case PDFOBJ_STREAM: { 286 case PDFOBJ_STREAM: {
287 CPDF_Stream* pThis = (CPDF_Stream*)this; 287 const CPDF_Stream* pThis = AsStream();
288 CPDF_StreamAcc acc; 288 CPDF_StreamAcc acc;
289 acc.LoadAllData(pThis, TRUE); 289 acc.LoadAllData(pThis, TRUE);
290 FX_DWORD streamSize = acc.GetSize(); 290 FX_DWORD streamSize = acc.GetSize();
291 CPDF_Dictionary* pDict = pThis->GetDict(); 291 CPDF_Dictionary* pDict = pThis->GetDict();
292 if (pDict) { 292 if (pDict) {
293 pDict = ToDictionary(pDict->CloneInternal(bDirect, visited)); 293 pDict = ToDictionary(pDict->CloneInternal(bDirect, visited));
294 } 294 }
295 return new CPDF_Stream(acc.DetachData(), streamSize, pDict); 295 return new CPDF_Stream(acc.DetachData(), streamSize, pDict);
296 } 296 }
297 case PDFOBJ_REFERENCE: { 297 case PDFOBJ_REFERENCE: {
(...skipping 14 matching lines...) Expand all
312 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const { 312 CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const {
313 if (m_ObjNum) { 313 if (m_ObjNum) {
314 return new CPDF_Reference(pDoc, m_ObjNum); 314 return new CPDF_Reference(pDoc, m_ObjNum);
315 } 315 }
316 return Clone(); 316 return Clone();
317 } 317 }
318 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const { 318 CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const {
319 if (const CPDF_String* pString = AsString()) 319 if (const CPDF_String* pString = AsString())
320 return PDF_DecodeText(pString->m_String, pCharMap); 320 return PDF_DecodeText(pString->m_String, pCharMap);
321 321
322 if (m_Type == PDFOBJ_STREAM) { 322 if (const CPDF_Stream* pStream = AsStream()) {
323 CPDF_StreamAcc stream; 323 CPDF_StreamAcc stream;
324 stream.LoadAllData((CPDF_Stream*)this, FALSE); 324 stream.LoadAllData(pStream, FALSE);
325 CFX_WideString result = 325 CFX_WideString result =
326 PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap); 326 PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap);
327 return result; 327 return result;
328 } 328 }
329 if (const CPDF_Name* pName = AsName()) 329 if (const CPDF_Name* pName = AsName())
330 return PDF_DecodeText(pName->m_Name, pCharMap); 330 return PDF_DecodeText(pName->m_Name, pCharMap);
331 return CFX_WideString(); 331 return CFX_WideString();
332 } 332 }
333 void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) { 333 void CPDF_Object::SetUnicodeText(const FX_WCHAR* pUnicodes, int len) {
334 if (CPDF_String* pString = AsString()) { 334 if (CPDF_String* pString = AsString()) {
335 pString->m_String = PDF_EncodeText(pUnicodes, len); 335 pString->m_String = PDF_EncodeText(pUnicodes, len);
336 } else if (m_Type == PDFOBJ_STREAM) { 336 } else if (CPDF_Stream* pStream = AsStream()) {
337 CFX_ByteString result = PDF_EncodeText(pUnicodes, len); 337 CFX_ByteString result = PDF_EncodeText(pUnicodes, len);
338 ((CPDF_Stream*)this) 338 pStream->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE,
339 ->SetData((uint8_t*)result.c_str(), result.GetLength(), FALSE, FALSE); 339 FALSE);
340 } 340 }
341 } 341 }
342 342
343 CPDF_Array* CPDF_Object::AsArray() { 343 CPDF_Array* CPDF_Object::AsArray() {
344 return IsArray() ? static_cast<CPDF_Array*>(this) : nullptr; 344 return IsArray() ? static_cast<CPDF_Array*>(this) : nullptr;
345 } 345 }
346 346
347 const CPDF_Array* CPDF_Object::AsArray() const { 347 const CPDF_Array* CPDF_Object::AsArray() const {
348 return IsArray() ? static_cast<const CPDF_Array*>(this) : nullptr; 348 return IsArray() ? static_cast<const CPDF_Array*>(this) : nullptr;
349 } 349 }
(...skipping 23 matching lines...) Expand all
373 } 373 }
374 374
375 CPDF_Number* CPDF_Object::AsNumber() { 375 CPDF_Number* CPDF_Object::AsNumber() {
376 return IsNumber() ? static_cast<CPDF_Number*>(this) : nullptr; 376 return IsNumber() ? static_cast<CPDF_Number*>(this) : nullptr;
377 } 377 }
378 378
379 const CPDF_Number* CPDF_Object::AsNumber() const { 379 const CPDF_Number* CPDF_Object::AsNumber() const {
380 return IsNumber() ? static_cast<const CPDF_Number*>(this) : nullptr; 380 return IsNumber() ? static_cast<const CPDF_Number*>(this) : nullptr;
381 } 381 }
382 382
383 CPDF_Stream* CPDF_Object::AsStream() {
384 return IsStream() ? static_cast<CPDF_Stream*>(this) : nullptr;
385 }
386
387 const CPDF_Stream* CPDF_Object::AsStream() const {
388 return IsStream() ? static_cast<const CPDF_Stream*>(this) : nullptr;
389 }
390
383 CPDF_String* CPDF_Object::AsString() { 391 CPDF_String* CPDF_Object::AsString() {
384 return IsString() ? static_cast<CPDF_String*>(this) : nullptr; 392 return IsString() ? static_cast<CPDF_String*>(this) : nullptr;
385 } 393 }
386 394
387 const CPDF_String* CPDF_Object::AsString() const { 395 const CPDF_String* CPDF_Object::AsString() const {
388 return IsString() ? static_cast<const CPDF_String*>(this) : nullptr; 396 return IsString() ? static_cast<const CPDF_String*>(this) : nullptr;
389 } 397 }
390 398
391 CPDF_Number::CPDF_Number(int value) 399 CPDF_Number::CPDF_Number(int value)
392 : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(value) {} 400 : CPDF_Object(PDFOBJ_NUMBER), m_bInteger(TRUE), m_Integer(value) {}
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 } 488 }
481 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const { 489 FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const {
482 if (i >= (FX_DWORD)m_Objects.GetSize()) { 490 if (i >= (FX_DWORD)m_Objects.GetSize()) {
483 return 0; 491 return 0;
484 } 492 }
485 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); 493 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
486 return p->GetNumber(); 494 return p->GetNumber();
487 } 495 }
488 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const { 496 CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const {
489 CPDF_Object* p = GetElementValue(i); 497 CPDF_Object* p = GetElementValue(i);
490 if (!p) { 498 if (!p)
491 return NULL; 499 return NULL;
492 } 500 if (CPDF_Dictionary* pDict = p->AsDictionary())
493 if (CPDF_Dictionary* pDict = p->AsDictionary()) {
494 return pDict; 501 return pDict;
495 } 502 if (CPDF_Stream* pStream = p->AsStream())
496 if (p->GetType() == PDFOBJ_STREAM) { 503 return pStream->GetDict();
497 return ((CPDF_Stream*)p)->GetDict();
498 }
499 return NULL; 504 return NULL;
500 } 505 }
501 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const { 506 CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const {
502 CPDF_Object* p = GetElementValue(i); 507 return ToStream(GetElementValue(i));
503 if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
504 return NULL;
505 }
506 return (CPDF_Stream*)p;
507 } 508 }
508 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const { 509 CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const {
509 return ToArray(GetElementValue(i)); 510 return ToArray(GetElementValue(i));
510 } 511 }
511 void CPDF_Array::RemoveAt(FX_DWORD i) { 512 void CPDF_Array::RemoveAt(FX_DWORD i) {
512 ASSERT(IsArray()); 513 ASSERT(IsArray());
513 if (i >= (FX_DWORD)m_Objects.GetSize()) { 514 if (i >= (FX_DWORD)m_Objects.GetSize()) {
514 return; 515 return;
515 } 516 }
516 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); 517 CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 FX_BOOL CPDF_Dictionary::GetBoolean(const CFX_ByteStringC& key, 697 FX_BOOL CPDF_Dictionary::GetBoolean(const CFX_ByteStringC& key,
697 FX_BOOL bDefault) const { 698 FX_BOOL bDefault) const {
698 CPDF_Object* p = NULL; 699 CPDF_Object* p = NULL;
699 m_Map.Lookup(key, (void*&)p); 700 m_Map.Lookup(key, (void*&)p);
700 if (ToBoolean(p)) 701 if (ToBoolean(p))
701 return p->GetInteger(); 702 return p->GetInteger();
702 return bDefault; 703 return bDefault;
703 } 704 }
704 CPDF_Dictionary* CPDF_Dictionary::GetDict(const CFX_ByteStringC& key) const { 705 CPDF_Dictionary* CPDF_Dictionary::GetDict(const CFX_ByteStringC& key) const {
705 CPDF_Object* p = GetElementValue(key); 706 CPDF_Object* p = GetElementValue(key);
706 if (!p) { 707 if (!p)
707 return nullptr; 708 return nullptr;
708 } 709 if (CPDF_Dictionary* pDict = p->AsDictionary())
709 if (CPDF_Dictionary* pDict = p->AsDictionary()) {
710 return pDict; 710 return pDict;
711 } 711 if (CPDF_Stream* pStream = p->AsStream())
712 if (p->GetType() == PDFOBJ_STREAM) { 712 return pStream->GetDict();
713 return ((CPDF_Stream*)p)->GetDict();
714 }
715 return nullptr; 713 return nullptr;
716 } 714 }
717 CPDF_Array* CPDF_Dictionary::GetArray(const CFX_ByteStringC& key) const { 715 CPDF_Array* CPDF_Dictionary::GetArray(const CFX_ByteStringC& key) const {
718 return ToArray(GetElementValue(key)); 716 return ToArray(GetElementValue(key));
719 } 717 }
720 CPDF_Stream* CPDF_Dictionary::GetStream(const CFX_ByteStringC& key) const { 718 CPDF_Stream* CPDF_Dictionary::GetStream(const CFX_ByteStringC& key) const {
721 CPDF_Object* p = GetElementValue(key); 719 return ToStream(GetElementValue(key));
722 if (p == NULL || p->GetType() != PDFOBJ_STREAM) {
723 return NULL;
724 }
725 return (CPDF_Stream*)p;
726 } 720 }
727 CFX_FloatRect CPDF_Dictionary::GetRect(const CFX_ByteStringC& key) const { 721 CFX_FloatRect CPDF_Dictionary::GetRect(const CFX_ByteStringC& key) const {
728 CFX_FloatRect rect; 722 CFX_FloatRect rect;
729 CPDF_Array* pArray = GetArray(key); 723 CPDF_Array* pArray = GetArray(key);
730 if (pArray) { 724 if (pArray) {
731 rect = pArray->GetRect(); 725 rect = pArray->GetRect();
732 } 726 }
733 return rect; 727 return rect;
734 } 728 }
735 CFX_AffineMatrix CPDF_Dictionary::GetMatrix(const CFX_ByteStringC& key) const { 729 CFX_AffineMatrix CPDF_Dictionary::GetMatrix(const CFX_ByteStringC& key) const {
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 m_pData = NULL; 1022 m_pData = NULL;
1029 m_dwSize = 0; 1023 m_dwSize = 0;
1030 m_pImageParam = NULL; 1024 m_pImageParam = NULL;
1031 m_pStream = NULL; 1025 m_pStream = NULL;
1032 m_pSrcData = NULL; 1026 m_pSrcData = NULL;
1033 } 1027 }
1034 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, 1028 void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream,
1035 FX_BOOL bRawAccess, 1029 FX_BOOL bRawAccess,
1036 FX_DWORD estimated_size, 1030 FX_DWORD estimated_size,
1037 FX_BOOL bImageAcc) { 1031 FX_BOOL bImageAcc) {
1038 if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) { 1032 if (!pStream)
1039 return; 1033 return;
1040 } 1034
1041 m_pStream = pStream; 1035 m_pStream = pStream;
1042 if (pStream->IsMemoryBased() && 1036 if (pStream->IsMemoryBased() &&
1043 (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) { 1037 (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) {
1044 m_dwSize = pStream->m_dwSize; 1038 m_dwSize = pStream->m_dwSize;
1045 m_pData = (uint8_t*)pStream->m_pDataBuf; 1039 m_pData = (uint8_t*)pStream->m_pDataBuf;
1046 return; 1040 return;
1047 } 1041 }
1048 uint8_t* pSrcData; 1042 uint8_t* pSrcData;
1049 FX_DWORD dwSrcSize = pStream->m_dwSize; 1043 FX_DWORD dwSrcSize = pStream->m_dwSize;
1050 if (dwSrcSize == 0) { 1044 if (dwSrcSize == 0)
1051 return; 1045 return;
1052 } 1046
1053 if (!pStream->IsMemoryBased()) { 1047 if (!pStream->IsMemoryBased()) {
1054 pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize); 1048 pSrcData = m_pSrcData = FX_Alloc(uint8_t, dwSrcSize);
1055 if (!pStream->ReadRawData(0, pSrcData, dwSrcSize)) { 1049 if (!pStream->ReadRawData(0, pSrcData, dwSrcSize))
1056 return; 1050 return;
1057 }
1058 } else { 1051 } else {
1059 pSrcData = pStream->m_pDataBuf; 1052 pSrcData = pStream->m_pDataBuf;
1060 } 1053 }
1061 uint8_t* pDecryptedData; 1054 uint8_t* pDecryptedData;
1062 FX_DWORD dwDecryptedSize; 1055 FX_DWORD dwDecryptedSize;
1063 if (pStream->m_pCryptoHandler) { 1056 if (pStream->m_pCryptoHandler) {
1064 CFX_BinaryBuf dest_buf; 1057 CFX_BinaryBuf dest_buf;
1065 dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize)); 1058 dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize));
1066 void* context = pStream->m_pCryptoHandler->DecryptStart( 1059 void* context = pStream->m_pCryptoHandler->DecryptStart(
1067 pStream->GetObjNum(), pStream->m_GenNum); 1060 pStream->GetObjNum(), pStream->m_GenNum);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 } 1230 }
1238 pObj->m_ObjNum = objnum; 1231 pObj->m_ObjNum = objnum;
1239 m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj); 1232 m_IndirectObjs.SetAt((void*)(uintptr_t)objnum, pObj);
1240 if (m_LastObjNum < objnum) { 1233 if (m_LastObjNum < objnum) {
1241 m_LastObjNum = objnum; 1234 m_LastObjNum = objnum;
1242 } 1235 }
1243 } 1236 }
1244 FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const { 1237 FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const {
1245 return m_LastObjNum; 1238 return m_LastObjNum;
1246 } 1239 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698