Bug Summary

File:IccProfLib/IccTagDict.cpp
Warning:line 165, column 55
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-apple-macosx14.0.0 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name IccTagDict.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=osx -analyzer-checker=security.insecureAPI.decodeValueOfObjCType -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -ffp-contract=on -fno-rounding-math -funwind-tables=2 -target-sdk-version=14.0 -fcompatibility-qualified-id-block-type-checking -fvisibility-inlines-hidden-static-local-var -target-cpu penryn -tune-cpu generic -debugger-tuning=lldb -target-linker-version 1015.7 -fprofile-instrument=clang -fcoverage-mapping -fcoverage-compilation-dir=/Users/xss/DemoIccMAX-hoyt-master/build/IccProfLib -resource-dir /usr/local/Cellar/llvm/17.0.3/lib/clang/17 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -D IccProfLib2_EXPORTS -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccProfLib -I /Developer/Headers/FlatCarbon -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/System/Library/Frameworks -internal-isystem /usr/local/Cellar/llvm/17.0.3/bin/../include/c++/v1 -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/local/include -internal-isystem /usr/local/Cellar/llvm/17.0.3/lib/clang/17/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/include -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/Users/xss/DemoIccMAX-hoyt-master/build/IccProfLib -ferror-limit 19 -fsanitize=address -fsanitize-system-ignorelist=/usr/local/Cellar/llvm/17.0.3/lib/clang/17/share/asan_ignorelist.txt -fno-sanitize-memory-param-retval -fsanitize-address-use-after-scope -fsanitize-address-globals-dead-stripping -fno-assume-sane-operator-new -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fmax-type-align=16 -analyzer-output=html -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/folders/l9/sd9kj1px4yq2wc5_lkwhlt6w0000gn/T/scan-build-2023-10-28-102616-57860-1 -x c++ /Users/xss/DemoIccMAX-hoyt-master/IccProfLib/IccTagDict.cpp
1/** @file
2 File: IccTagDictTag.cpp
3
4 Contains: Implementation of prototype dictType Tag
5
6 Version: V1
7
8 Copyright: � see ICC Software License
9*/
10
11/*
12 * The ICC Software License, Version 0.2
13 *
14 *
15 * Copyright (c) 2003-2012 The International Color Consortium. All rights
16 * reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. In the absence of prior written permission, the names "ICC" and "The
31 * International Color Consortium" must not be used to imply that the
32 * ICC organization endorses or promotes products derived from this
33 * software.
34 *
35 *
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This software consists of voluntary contributions made by many
51 * individuals on behalf of the The International Color Consortium.
52 *
53 *
54 * Membership in the ICC is encouraged when this software is used for
55 * commercial purposes.
56 *
57 *
58 * For more information on The International Color Consortium, please
59 * see <http://www.color.org/>.
60 *
61 *
62 */
63
64//////////////////////////////////////////////////////////////////////
65// HISTORY:
66//
67// -Initial implementation by Max Derhak Jun-26-2009
68//
69//////////////////////////////////////////////////////////////////////
70
71#ifdef WIN32
72#pragma warning( disable: 4786) //disable warning in <list.h>
73#endif
74
75#include <stdio.h>
76#include <math.h>
77#include <string.h>
78#include <stdlib.h>
79#include "IccTagDict.h"
80#include "IccUtil.h"
81#include "IccIO.h"
82
83
84//MSVC 6.0 doesn't support std::string correctly so we disable support in this case
85#ifndef ICC_UNSUPPORTED_TAG_DICT
86
87/*=============================================================================
88* CLASS CIccDictEntry
89*=============================================================================*/
90
91/**
92******************************************************************************
93* Name: CIccDictEntry::CIccDictEntry
94*
95* Purpose:
96*
97* Args:
98*
99* Return:
100******************************************************************************/
101CIccDictEntry::CIccDictEntry()
102{
103 m_sName = new std::wstring();
104 m_sValue = new std::wstring();
105 m_pNameLocalized = NULL__null;
106 m_pValueLocalized = NULL__null;
107 m_bValueSet = false;
108}
109
110/**
111******************************************************************************
112* Name: CIccDictEntry::CIccDictEntry
113*
114* Purpose:
115*
116* Args:
117*
118* Return:
119******************************************************************************/
120CIccDictEntry::CIccDictEntry(const CIccDictEntry& IDE)
121{
122 m_sName = new std::wstring();
123 m_sValue = new std::wstring();
124
125 *m_sName = *IDE.m_sName;
126 m_bValueSet = IDE.m_bValueSet;
127 *m_sValue = *IDE.m_sValue;
128
129 if (IDE.m_pNameLocalized) {
130 m_pNameLocalized = (CIccTagMultiLocalizedUnicode*)IDE.m_pNameLocalized->NewCopy();
131 }
132 else
133 m_pNameLocalized = NULL__null;
134
135 if (IDE.m_pValueLocalized) {
136 m_pValueLocalized = (CIccTagMultiLocalizedUnicode*)IDE.m_pValueLocalized->NewCopy();
137 }
138 else
139 m_pValueLocalized = NULL__null;
140}
141
142/**
143******************************************************************************
144* Name: CIccDictEntry::operator=
145*
146* Purpose:
147*
148* Args:
149*
150* Return:
151******************************************************************************/
152CIccDictEntry &CIccDictEntry::operator=(const CIccDictEntry &IDE)
1
Assuming IDE == *this
153{
154 if (m_pNameLocalized)
2
Assuming field 'm_pNameLocalized' is non-null
3
Taking true branch
155 delete m_pNameLocalized;
4
Memory is released
156
157 if (m_pValueLocalized)
5
Assuming field 'm_pValueLocalized' is null
6
Taking false branch
158 delete m_pValueLocalized;
159
160 *m_sName = *IDE.m_sName;
161 m_bValueSet = IDE.m_bValueSet;
162 *m_sValue = *IDE.m_sValue;
163
164 if (IDE.m_pNameLocalized
6.1
Field 'm_pNameLocalized' is non-null
) {
7
Taking true branch
165 m_pNameLocalized = (CIccTagMultiLocalizedUnicode*)IDE.m_pNameLocalized->NewCopy();
8
Use of memory after it is freed
166 }
167 else
168 m_pNameLocalized = NULL__null;
169
170 if (IDE.m_pValueLocalized) {
171 m_pValueLocalized = (CIccTagMultiLocalizedUnicode*)IDE.m_pValueLocalized->NewCopy();
172 }
173 else
174 m_pValueLocalized = NULL__null;
175
176 return *this;
177}
178
179/**
180******************************************************************************
181* Name: CIccDictEntry::~CIccDictEntry
182*
183* Purpose:
184*
185* Args:
186*
187* Return:
188******************************************************************************/
189CIccDictEntry::~CIccDictEntry()
190{
191 delete m_sName;
192 delete m_sValue;
193 delete m_pNameLocalized;
194 delete m_pValueLocalized;
195}
196
197/**
198******************************************************************************
199* Name: CIccDictEntry::Describe
200*
201* Purpose:
202*
203* Args:
204*
205* Return:
206******************************************************************************/
207void CIccDictEntry::Describe(std::string &sDescription)
208{
209 std::string s;
210
211 sDescription += "BEGIN DICT_ENTRY\r\nName=";
212 s.assign(m_sName->begin(), m_sName->end());
213 sDescription += s;
214 sDescription += "\r\nValue=";
215 s.assign(m_sValue->begin(), m_sValue->end());
216 sDescription += s;
217 sDescription += "\r\n";
218
219 if (m_pNameLocalized) {
220 sDescription += "BEGIN NAME_LOCALIZATION\r\n";
221 m_pNameLocalized->Describe(sDescription);
222 sDescription += "END NAME_LOCALIZATION\r\n";
223 }
224 if (m_pValueLocalized) {
225 sDescription += "BEGIN VALUE_LOCALIZATION\r\n";
226 m_pValueLocalized->Describe(sDescription);
227 sDescription += "END VALUE_LOCALIZATION\r\n";
228 }
229 sDescription += "END DICT_ENTRY\r\n";
230}
231
232
233/**
234******************************************************************************
235* Name: CIccDictEntry::PosRecSize
236*
237* Purpose:
238*
239* Args:
240*
241* Return:
242******************************************************************************/
243icUInt32Number CIccDictEntry::PosRecSize()
244{
245 if (m_pValueLocalized)
246 return 32;
247 if (m_pNameLocalized)
248 return 24;
249 return 16;
250}
251
252
253bool CIccDictEntry::SetValue(std::wstring sValue)
254{
255 bool rv = m_bValueSet && !m_sValue->empty();
256
257 *m_sValue = sValue;
258 m_bValueSet = true;
259 return rv;
260}
261
262/**
263******************************************************************************
264* Name: CIccDictEntry::SetNameLocalized
265*
266* Purpose:
267*
268* Args:
269*
270* Return:
271******************************************************************************/
272bool CIccDictEntry::SetNameLocalized(CIccTagMultiLocalizedUnicode *pNameLocalized)
273{
274 bool rv;
275
276 if (m_pNameLocalized) {
277 delete m_pNameLocalized;
278 rv = true;
279 }
280 else
281 rv = false;
282
283 m_pNameLocalized = pNameLocalized;
284
285 return rv;
286}
287
288
289/**
290******************************************************************************
291* Name: CIccDictEntry::SetValueLocalized
292*
293* Purpose:
294*
295* Args:
296*
297* Return:
298******************************************************************************/
299bool CIccDictEntry::SetValueLocalized(CIccTagMultiLocalizedUnicode *pValueLocalized)
300{
301 bool rv;
302
303 if (m_pValueLocalized) {
304 delete m_pValueLocalized;
305 rv = true;
306 }
307 else
308 rv = false;
309
310 m_pValueLocalized = pValueLocalized;
311
312 return rv;
313}
314
315/*=============================================================================
316 * CLASS CIccTagDict
317 *============================================================================*/
318
319/**
320 ******************************************************************************
321 * Name: CIccTagDict::CIccTagDict
322 *
323 * Purpose:
324 *
325 * Args:
326 *
327 * Return:
328 ******************************************************************************/
329CIccTagDict::CIccTagDict()
330{
331 m_bBadAlignment = false;
332
333 m_Dict = new CIccNameValueDict;
334}
335
336/**
337 ******************************************************************************
338 * Name: CIccTagDict::CIccTagDict
339 *
340 * Purpose:
341 *
342 * Args:
343 *
344 * Return:
345 ******************************************************************************/
346CIccTagDict::CIccTagDict(const CIccTagDict &dict)
347{
348 m_bBadAlignment = false;
349 m_Dict = new CIccNameValueDict;
350
351 CIccNameValueDict::iterator i;
352 CIccDictEntryPtr ptr;
353
354 for (i=dict.m_Dict->begin(); i!=dict.m_Dict->end(); i++) {
355 ptr.ptr = new CIccDictEntry(*i->ptr);
356
357 m_Dict->push_back(ptr);
358 }
359}
360
361/**
362 ******************************************************************************
363 * Name: &operator=
364 *
365 * Purpose:
366 *
367 * Args:
368 *
369 * Return:
370 ******************************************************************************/
371CIccTagDict &CIccTagDict::operator=(const CIccTagDict &dict)
372{
373 if (&dict == this)
374 return *this;
375
376 Cleanup();
377
378 CIccNameValueDict::iterator i;
379 CIccDictEntryPtr ptr;
380
381 for (i=dict.m_Dict->begin(); i!=dict.m_Dict->end(); i++) {
382 ptr.ptr = new CIccDictEntry(*i->ptr);
383
384 m_Dict->push_back(ptr);
385 }
386
387 return *this;
388}
389
390/**
391 ******************************************************************************
392 * Name: CIccTagDict::~CIccTagDict
393 *
394 * Purpose:
395 *
396 * Args:
397 *
398 * Return:
399 ******************************************************************************/
400CIccTagDict::~CIccTagDict()
401{
402 Cleanup();
403 delete m_Dict;
404}
405
406
407/**
408******************************************************************************
409* Name: CIccTagDict::MaxPosRecSize;
410*
411* Purpose:
412*
413* Args:
414*
415* Return:
416******************************************************************************/
417icUInt32Number CIccTagDict::MaxPosRecSize()
418{
419
420 icUInt32Number rv = 16;
421
422 CIccNameValueDict::iterator i;
423 CIccDictEntry ptr;
424
425 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
426 if (i->ptr->PosRecSize() > rv)
427 rv = i->ptr->PosRecSize();
428 }
429
430 return rv;
431}
432
433
434/**
435 ******************************************************************************
436 * Name: CIccTagDict::Describe
437 *
438 * Purpose:
439 *
440 * Args:
441 *
442 * Return:
443 ******************************************************************************/
444void CIccTagDict::Describe(std::string &sDescription)
445{
446 icChar buf[128];
447
448 sprintf(buf, "BEGIN DICT_TAG\r\n");
449 sDescription += buf;
450
451 CIccNameValueDict::iterator i;
452 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
453 sDescription += "\r\n";
454
455 i->ptr->Describe(sDescription);
456 }
457
458 sprintf(buf, "\r\nEND DICT_TAG\r\n");
459 sDescription += buf;
460}
461
462typedef struct
463{
464 icPositionNumber posName;
465 icPositionNumber posValue;
466 icPositionNumber posNameLocalized;
467 icPositionNumber posValueLocalized;
468} icDictRecordPos;
469
470
471/**
472 ******************************************************************************
473 * Name: CIccTagDict::Read
474 *
475 * Purpose:
476 *
477 * Args:
478 *
479 * Return:
480 ******************************************************************************/
481bool CIccTagDict::Read(icUInt32Number size, CIccIO *pIO)
482{
483 icTagTypeSignature sig;
484
485 m_tagSize = size;
486
487 icUInt32Number headerSize = sizeof(icTagTypeSignature) +
488 sizeof(icUInt32Number) +
489 sizeof(icUInt32Number) +
490 sizeof(icUInt32Number);
491
492 if (headerSize > size)
493 return false;
494
495 if (!pIO) {
496 return false;
497 }
498
499 Cleanup();
500
501 m_tagStart = pIO->Tell();
502
503 if (!pIO->Read32(&sig))
504 return false;
505
506 if (!pIO->Read32(&m_nReserved))
507 return false;
508
509 icUInt32Number count, reclen, i;
510
511 if (!pIO->Read32(&count))
512 return false;
513
514 if (!pIO->Read32(&reclen))
515 return false;
516
517 if (reclen!=16 && reclen!=24 && reclen!=32)
518 return false;
519
520 if (headerSize + count*reclen > size)
521 return false;
522
523 icDictRecordPos *pos = (icDictRecordPos*)calloc(count, sizeof(icDictRecordPos));
524 if (!pos)
525 return false;
526
527 //Read TagDir
528 for (i=0; i<count; i++) {
529 if (!pIO->Read32(&pos[i].posName.offset) ||
530 !pIO->Read32(&pos[i].posName.size) ||
531 !pIO->Read32(&pos[i].posValue.offset) ||
532 !pIO->Read32(&pos[i].posValue.size)) {
533 free(pos);
534 return false;
535 }
536
537 if (reclen>=24) {
538 if (!pIO->Read32(&pos[i].posNameLocalized.offset) ||
539 !pIO->Read32(&pos[i].posNameLocalized.size)) {
540 free(pos);
541 return false;
542 }
543 if (reclen>=32) {
544 if (!pIO->Read32(&pos[i].posValueLocalized.offset) ||
545 !pIO->Read32(&pos[i].posValueLocalized.size)) {
546 free(pos);
547 return false;
548 }
549 }
550 }
551
552 if ((pos[i].posName.offset & 0x3) ||
553 (pos[i].posValue.offset & 0x3) ||
554 (pos[i].posNameLocalized.offset & 0x3) ||
555 (pos[i].posValueLocalized.offset & 0x3))
556 m_bBadAlignment = true;
557 }
558
559 icUInt32Number bufsize = 128, num;
560 icUnicodeChar *buf = (icUnicodeChar*)malloc(bufsize);
561 CIccDictEntryPtr ptr;
562 std::wstring str;
563
564 for (i=0; i<count; i++) {
565 ptr.ptr = new CIccDictEntry();
566 if (!ptr.ptr)
567 return false;
568
569 //GetName
570 if (pos[i].posName.offset) {
571 if (!pos[i].posName.size) {
572 str.clear();
573 ptr.ptr->SetValue(str);
574 }
575 else {
576 if (pos[i].posName.offset + pos[i].posName.size >size ||
577 !pos[i].posName.size) {
578 free(pos);
579 free(buf);
580 delete ptr.ptr;
581 return false;
582 }
583
584 //Make sure we have buf large enough for the string
585 if (bufsize < pos[i].posName.size) {
586 bufsize = pos[i].posName.size;
587 buf = (icUnicodeChar*)icRealloc(buf, bufsize);
588 if (!buf) {
589 free(pos);
590 delete ptr.ptr;
591 return false;
592 }
593 }
594
595 if (pIO->Seek(m_tagStart+pos[i].posName.offset, icSeekSet)<0) {
596 free(pos);
597 free(buf);
598 delete ptr.ptr;
599 return false;
600 }
601
602 num = pos[i].posName.size / sizeof(icUnicodeChar);
603 if (pIO->Read16(buf, num)!=(icInt32Number)num) {
604 free(pos);
605 free(buf);
606 delete ptr.ptr;
607 return false;
608 }
609 str.assign(&buf[0], &buf[num]);
610 ptr.ptr->GetName() = str;
611 }
612 }
613
614 //GetValue
615 if (pos[i].posValue.offset) {
616 if (!pos[i].posValue.size) {
617 str.clear();
618 ptr.ptr->SetValue(str);
619 }
620 else {
621 if (pos[i].posValue.offset + pos[i].posValue.size >size ||
622 (pos[i].posValue.size&1)) {
623 free(pos);
624 free(buf);
625 delete ptr.ptr;
626 return false;
627 }
628
629 //Make sure we have buf large enough for the string
630 if (bufsize < pos[i].posValue.size) {
631 bufsize = pos[i].posValue.size;
632 buf = (icUnicodeChar*)icRealloc(buf, bufsize);
633 if (!buf) {
634 free(pos);
635 delete ptr.ptr;
636 return false;
637 }
638 }
639
640 if (pIO->Seek(m_tagStart+pos[i].posValue.offset, icSeekSet)<0) {
641 free(pos);
642 free(buf);
643 delete ptr.ptr;
644 return false;
645 }
646
647 num = pos[i].posValue.size / sizeof(icUnicodeChar);
648 if (pIO->Read16(buf, num)!=(icInt32Number)num) {
649 free(pos);
650 free(buf);
651 delete ptr.ptr;
652 return false;
653 }
654 str.assign(&buf[0], &buf[num]);
655 ptr.ptr->SetValue(str);
656 }
657 }
658
659 //Get NameLocalized
660 if (pos[i].posNameLocalized.offset) {
661 if (pos[i].posNameLocalized.offset + pos[i].posNameLocalized.size > size ||
662 pos[i].posNameLocalized.size < sizeof(icSignature)) {
663 free(pos);
664 free(buf);
665 delete ptr.ptr;
666 return false;
667 }
668
669 if (pIO->Seek(m_tagStart+pos[i].posNameLocalized.offset, icSeekSet)<0) {
670 free(pos);
671 free(buf);
672 delete ptr.ptr;
673 return false;
674 }
675
676 icTagTypeSignature textSig = (icTagTypeSignature)0;
677 if (!pIO->Read32(&textSig, 1)) {
678 free(pos);
679 free(buf);
680 delete ptr.ptr;
681 return false;
682 }
683
684 if (textSig != icSigMultiLocalizedUnicodeType) {
685 free(pos);
686 free(buf);
687 delete ptr.ptr;
688 return false;
689 }
690
691 if (pIO->Seek(m_tagStart+pos[i].posNameLocalized.offset, icSeekSet)<0) {
692 free(pos);
693 free(buf);
694 delete ptr.ptr;
695 return false;
696 }
697
698 CIccTagMultiLocalizedUnicode *pTag = new CIccTagMultiLocalizedUnicode();
699
700 if (!pTag || !pTag->Read(pos[i].posNameLocalized.size, pIO)) {
701 free(pos);
702 free(buf);
703 delete ptr.ptr;
704 return false;
705 }
706
707 ptr.ptr->SetNameLocalized(pTag);
708 }
709
710 //Get ValueLocalized
711 if (pos[i].posValueLocalized.offset) {
712 if (pos[i].posValueLocalized.offset + pos[i].posValueLocalized.size > size ||
713 pos[i].posValueLocalized.size < sizeof(icSignature)) {
714 free(pos);
715 free(buf);
716 delete ptr.ptr;
717 return false;
718 }
719
720 if (pIO->Seek(m_tagStart+pos[i].posValueLocalized.offset, icSeekSet)<0) {
721 free(pos);
722 free(buf);
723 delete ptr.ptr;
724 return false;
725 }
726
727 icTagTypeSignature textSig = (icTagTypeSignature)0;
728 if (!pIO->Read32(&textSig, 1)) {
729 free(pos);
730 free(buf);
731 delete ptr.ptr;
732 return false;
733 }
734
735 if (textSig != icSigMultiLocalizedUnicodeType) {
736 free(pos);
737 free(buf);
738 delete ptr.ptr;
739 return false;
740 }
741
742 if (pIO->Seek(m_tagStart+pos[i].posValueLocalized.offset, icSeekSet)<0) {
743 free(pos);
744 free(buf);
745 delete ptr.ptr;
746 return false;
747 }
748
749 CIccTagMultiLocalizedUnicode *pTag = new CIccTagMultiLocalizedUnicode();
750
751 if (!pTag || !pTag->Read(pos[i].posValueLocalized.size, pIO)) {
752 free(pos);
753 free(buf);
754 delete ptr.ptr;
755 return false;
756 }
757
758 ptr.ptr->SetValueLocalized(pTag);
759 }
760
761 m_Dict->push_back(ptr);
762 }
763
764 free(pos);
765 free(buf);
766
767 return true;
768}
769
770/**
771 ******************************************************************************
772 * Name: CIccTagDict::Write
773 *
774 * Purpose:
775 *
776 * Args:
777 *
778 * Return:
779 ******************************************************************************/
780bool CIccTagDict::Write(CIccIO *pIO)
781{
782 icTagTypeSignature sig = GetType();
783
784 if (!pIO)
785 return false;
786
787 m_tagStart = pIO->Tell();
788
789 if (!pIO->Write32(&sig))
790 return false;
791
792 if (!pIO->Write32(&m_nReserved))
793 return false;
794
795 CIccNameValueDict::iterator i, j;
796 icUInt32Number count;
797 icUInt8Number zbuf[32];
798
799 memset(zbuf, 0, 32);
800
801 for (count=0, i=m_Dict->begin(); i!= m_Dict->end(); i++) {
802 if (i->ptr)
803 count++;
804 }
805
806 pIO->Write32(&count);
807
808 icUInt32Number recSize = MaxPosRecSize();
809 pIO->Write32(&recSize);
810
811 icDictRecordPos *pos = (icDictRecordPos*)calloc(count, sizeof(icDictRecordPos));
812 if (!pos)
813 return false;
814
815 icUInt32Number n, dirpos = pIO->Tell();
816
817 //Write Unintialized Dict rec offset array
818 for (i=m_Dict->begin(); i!= m_Dict->end(); i++) {
819 if (i->ptr) {
820 pIO->Write8(zbuf, recSize);
821 }
822 }
823
824 icUnicodeChar c;
825 std::wstring::const_iterator chrptr;
826 //Write Dict records
827 for (n=0, i=m_Dict->begin(); i!= m_Dict->end(); i++) {
828 if (i->ptr) {
829 pos[n].posName.offset = pIO->Tell()-m_tagStart;
830
831 for(chrptr = i->ptr->GetName().begin(); chrptr!=i->ptr->GetName().end(); chrptr++) {
832 c=(icUnicodeChar)*chrptr;
833 pIO->Write16(&c, 1);
834 }
835 pos[n].posName.size = pIO->Tell()-m_tagStart - pos[n].posName.offset;
836 pIO->Align32();
837
838 if (i->ptr->IsValueSet()) {
839 pos[n].posValue.offset = pIO->Tell()-m_tagStart;
840 for(chrptr = i->ptr->ValueBegin(); chrptr!=i->ptr->ValueEnd(); chrptr++) {
841 c=(icUnicodeChar)*chrptr;
842 pIO->Write16(&c, 1);
843 }
844 pos[n].posValue.size = pIO->Tell()-m_tagStart - pos[n].posValue.offset;
845 pIO->Align32();
846 }
847
848 if (recSize>16 && i->ptr->GetNameLocalized()) {
849 pos[n].posNameLocalized.offset = pIO->Tell()-m_tagStart;
850 i->ptr->GetNameLocalized()->Write(pIO);
851 pos[n].posNameLocalized.size = pIO->Tell()-m_tagStart - pos[n].posNameLocalized.offset;
852 pIO->Align32();
853 }
854
855 if (recSize>24 && i->ptr->GetValueLocalized()) {
856 pos[n].posValueLocalized.offset = pIO->Tell()-m_tagStart;
857 i->ptr->GetValueLocalized()->Write(pIO);
858 pos[n].posValueLocalized.size = pIO->Tell()-m_tagStart - pos[n].posValueLocalized.offset;
859 pIO->Align32();
860 }
861 n++;
862 }
863 }
864 icUInt32Number endpos = pIO->Tell();
865
866 pIO->Seek(dirpos, icSeekSet);
867
868 //Write TagDir with offsets and sizes
869 for (n=0, i=m_Dict->begin(); i!= m_Dict->end(); i++) {
870 if (i->ptr) {
871 pIO->Write32(&pos[n].posName.offset);
872 pIO->Write32(&pos[n].posName.size);
873 pIO->Write32(&pos[n].posValue.offset);
874 pIO->Write32(&pos[n].posValue.size);
875 if (recSize>16) {
876 pIO->Write32(&pos[n].posNameLocalized.offset);
877 pIO->Write32(&pos[n].posNameLocalized.size);
878 if (recSize>24) {
879 pIO->Write32(&pos[n].posValueLocalized.offset);
880 pIO->Write32(&pos[n].posValueLocalized.size);
881 }
882 }
883 }
884 n++;
885 }
886 pIO->Seek(endpos, icSeekSet);
887
888 free(pos);
889
890 return true;
891}
892
893
894/**
895 ******************************************************************************
896 * Name: CIccTagDict::Validate
897 *
898 * Purpose:
899 *
900 * Args:
901 *
902 * Return:
903 ******************************************************************************/
904icValidateStatus CIccTagDict::Validate(std::string sigPath, std::string &sReport,
905 const CIccProfile* pProfile /*=NULL*/) const
906{
907 icValidateStatus rv = CIccTag::Validate(sigPath, sReport, pProfile);
908
909 CIccInfo Info;
910 std::string sSigPathName = Info.GetSigPathName(sigPath);
911
912 // Check for duplicate tags
913 if (!AreNamesUnique()) {
914 sReport += icMsgValidateWarning;
915 sReport += sSigPathName;
916 sReport += " - There are duplicate tags.\r\n";
917 rv =icMaxStatus(rv, icValidateWarning);
918 }
919
920 if (!AreNamesNonzero()) {
921 sReport += icMsgValidateWarning;
922 sReport += sSigPathName;
923 sReport += " - There are duplicate tags.\r\n";
924 rv =icMaxStatus(rv, icValidateWarning);
925 }
926
927 // Check for duplicate tags
928 if (m_bBadAlignment) {
929 sReport += icMsgValidateWarning;
930 sReport += sSigPathName;
931 sReport += " - Some Data elements are not aligned correctly\r\n";
932 rv =icMaxStatus(rv, icValidateWarning);
933 }
934
935 return rv;
936}
937
938/**
939 ***************************************************************************
940 * Name: CIccTagDict::Cleanup
941 *
942 * Purpose: Detach from a pending IO object
943 ***************************************************************************
944 */
945void CIccTagDict::Cleanup()
946{
947 CIccNameValueDict::iterator i;
948
949 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
950 if (i->ptr)
951 delete i->ptr;
952 }
953 m_Dict->clear();
954}
955
956/**
957******************************************************************************
958* Name: CIccTagDict::AreNamesUnique
959*
960* Purpose: For each tag it checks to see if any other tags have the same
961* signature.
962*
963*
964* Return:
965* true if all tags have unique signatures, or false if there are duplicate
966* tag signatures.
967*******************************************************************************
968*/
969bool CIccTagDict::AreNamesUnique() const
970{
971 CIccNameValueDict::const_iterator i, j;
972
973 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
974 j=i;
975 for (j++; j!= m_Dict->end(); j++) {
976 if (i->ptr->GetName() == j->ptr->GetName())
977 return false;
978 }
979 }
980
981 return true;
982}
983
984/**
985******************************************************************************
986* Name: CIccTagDict::AreNamesNonzero
987*
988* Purpose: For each tag it checks to see if any other tags have the same
989* signature.
990*
991*
992* Return:
993* true if all tags have unique signatures, or false if there are duplicate
994* tag signatures.
995*******************************************************************************
996*/
997bool CIccTagDict::AreNamesNonzero() const
998{
999 CIccNameValueDict::const_iterator i, j;
1000
1001 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
1002 if (i->ptr->GetName().empty())
1003 return false;
1004 }
1005
1006return true;
1007}
1008
1009
1010/**
1011 ****************************************************************************
1012 * Name: CIccTagDict::Get
1013 *
1014 * Purpose: Get a dictionary entry with a given name
1015 *
1016 * Args:
1017 * sName - name to find in dictionary
1018 *
1019 * Return:
1020 * Pointer to desired dictionary entry, or NULL if not found.
1021 *****************************************************************************
1022 */
1023CIccDictEntry* CIccTagDict::Get(std::wstring sName) const
1024{
1025 CIccNameValueDict::const_iterator i;
1026
1027 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
1028 if (i->ptr->GetName() == sName)
1029 return i->ptr;
1030 }
1031
1032 return NULL__null;
1033}
1034
1035/**
1036****************************************************************************
1037* Name: CIccTagDict::Get
1038*
1039* Purpose: Get a dictionary entry with a given name
1040*
1041* Args:
1042* sName - name to find in dictionary
1043*
1044* Return:
1045* Pointer to desired dictionary entry, or NULL if not found.
1046*****************************************************************************
1047*/
1048CIccDictEntry* CIccTagDict::Get(const icUnicodeChar *szName) const
1049{
1050 std::wstring sName;
1051 while(*szName)
1052 sName += *szName;
1053
1054 return Get(sName);
1055}
1056
1057
1058/**
1059****************************************************************************
1060* Name: CIccTagDict::Get
1061*
1062* Purpose: Get a dictionary entry with a given name
1063*
1064* Args:
1065* sName - name to find in dictionary
1066*
1067* Return:
1068* Pointer to desired dictionary entry, or NULL if not found.
1069*****************************************************************************
1070*/
1071CIccDictEntry* CIccTagDict::Get(const char *szName) const
1072{
1073 std::wstring sName(szName, szName+strlen(szName));
1074
1075 return Get(sName);
1076}
1077
1078/**
1079****************************************************************************
1080* Name: CIccTagDict::GetValue
1081*
1082* Purpose: Get a value associated with a given name
1083*
1084* Args:
1085* sName - name to find in dictionary
1086*
1087* Return:
1088* Pointer to desired dictionary entry, or NULL if not found.
1089*****************************************************************************
1090*/
1091std::wstring CIccTagDict::GetValue(std::wstring sName, bool *bIsSet) const
1092{
1093 CIccDictEntry *de = Get(sName);
1094
1095 if (de) {
1096
1097 if (bIsSet)
1098 *bIsSet = de->IsValueSet();
1099
1100 return de->GetValue();
1101 }
1102
1103 if (bIsSet)
1104 *bIsSet = false;
1105
1106 std::wstring str;
1107 return str;
1108}
1109
1110/**
1111****************************************************************************
1112* Name: CIccTagDict::GetValue
1113*
1114* Purpose: Get a value associated with a given name
1115*
1116* Args:
1117* szName - name to find in dictionary
1118*
1119* Return:
1120* Pointer to desired dictionary entry, or NULL if not found.
1121*****************************************************************************
1122*/
1123std::wstring CIccTagDict::GetValue(const icUnicodeChar *szName, bool *bIsSet) const
1124{
1125 std::wstring sName;
1126 while(*szName)
1127 sName += *szName;
1128
1129 return GetValue(sName, bIsSet);
1130}
1131
1132/**
1133****************************************************************************
1134* Name: CIccTagDict::GetValue
1135*
1136* Purpose: Get a value associated with a given name
1137*
1138* Args:
1139* szName - name to find in dictionary
1140*
1141* Return:
1142* Pointer to desired dictionary entry, or NULL if not found.
1143*****************************************************************************
1144*/
1145std::wstring CIccTagDict::GetValue(const char *szName, bool *bIsSet) const
1146{
1147 std::wstring sName(szName, szName+strlen(szName));
1148
1149 return GetValue(sName, bIsSet);
1150}
1151
1152/**
1153****************************************************************************
1154* Name: CIccTagDict::GetNameLocalized
1155*
1156* Purpose: Get a localized name information associated with a given name
1157*
1158* Args:
1159* sName - name to find in dictionary
1160*
1161* Return:
1162* localized information for name
1163*****************************************************************************
1164*/
1165CIccTagMultiLocalizedUnicode* CIccTagDict::GetNameLocalized(std::wstring sName) const
1166{
1167 CIccDictEntry *de = Get(sName);
1168
1169 if (de)
1170 return de->GetNameLocalized();
1171
1172 return NULL__null;
1173}
1174
1175/**
1176****************************************************************************
1177* Name: CIccTagDict::GetNameLocalized
1178*
1179* Purpose: Get a localized name information associated with a given name
1180*
1181* Args:
1182* sName - name to find in dictionary
1183*
1184* Return:
1185* localized information for name
1186*****************************************************************************
1187*/
1188CIccTagMultiLocalizedUnicode* CIccTagDict::GetNameLocalized(const icUnicodeChar *szName) const
1189{
1190 std::wstring sName;
1191 while(*szName)
1192 sName += *szName;
1193
1194 return GetNameLocalized(sName);
1195}
1196
1197/**
1198****************************************************************************
1199* Name: CIccTagDict::GetNameLocalized
1200*
1201* Purpose: Get a localized name information associated with a given name
1202*
1203* Args:
1204* sName - name to find in dictionary
1205*
1206* Return:
1207* localized information for name
1208*****************************************************************************
1209*/
1210
1211CIccTagMultiLocalizedUnicode* CIccTagDict::GetNameLocalized(const char *szName) const
1212{
1213 std::wstring sName(szName, szName+strlen(szName));
1214
1215 return GetNameLocalized(sName);
1216}
1217
1218
1219/**
1220****************************************************************************
1221* Name: CIccTagDict::GetValueLocalized
1222*
1223* Purpose: Get a localized name information for value associated with a given name
1224*
1225* Args:
1226* sName - name to find in dictionary
1227*
1228* Return:
1229* localized information for name's value
1230*****************************************************************************
1231*/
1232CIccTagMultiLocalizedUnicode* CIccTagDict::GetValueLocalized(std::wstring sName) const
1233{
1234 CIccDictEntry *de = Get(sName);
1235
1236 if (de)
1237 return de->GetValueLocalized();
1238
1239 return NULL__null;
1240}
1241
1242/**
1243****************************************************************************
1244* Name: CIccTagDict::GetValueLocalized
1245*
1246* Purpose: Get a localized name information for value associated with a given name
1247*
1248* Args:
1249* sName - name to find in dictionary
1250*
1251* Return:
1252* localized information for name's value
1253*****************************************************************************
1254*/
1255CIccTagMultiLocalizedUnicode* CIccTagDict::GetValueLocalized(const icUnicodeChar *szName) const
1256{
1257 std::wstring sName;
1258 while(*szName)
1259 sName += *szName;
1260
1261 return GetValueLocalized(sName);
1262}
1263
1264/**
1265****************************************************************************
1266* Name: CIccTagDict::GetValueLocalized
1267*
1268* Purpose: Get a localized name information for value associated with a given name
1269*
1270* Args:
1271* sName - name to find in dictionary
1272*
1273* Return:
1274* localized information for name's value
1275*****************************************************************************
1276*/
1277
1278CIccTagMultiLocalizedUnicode* CIccTagDict::GetValueLocalized(const char *szName) const
1279{
1280 std::wstring sName(szName, szName+strlen(szName));
1281
1282 return GetValueLocalized(sName);
1283}
1284
1285
1286/**
1287******************************************************************************
1288* Name: CIccTagDict::Remove
1289*
1290* Purpose: Remove a name value pair from the dictionary
1291*
1292* Args:
1293* sName = the name to look for in the dictionary
1294*
1295* Return:
1296* true if sName exists and was removed, or false otherwise
1297*******************************************************************************
1298*/
1299bool CIccTagDict::Remove(std::wstring sName)
1300{
1301 CIccNameValueDict::iterator i;
1302
1303 for (i=m_Dict->begin(); i!=m_Dict->end(); i++) {
1304 if (i->ptr->GetName() == sName) {
1305 delete i->ptr;
1306
1307 m_Dict->erase(i);
1308 return true;
1309 }
1310 }
1311
1312 return false;
1313}
1314
1315
1316/**
1317******************************************************************************
1318* Name: CIccTagDict::Remove
1319*
1320* Purpose: Remove a name value pair from the dictionary
1321*
1322* Args:
1323* sName = the name to look for in the dictionary
1324*
1325* Return:
1326* true if sName exists and was remove , or false otherwise
1327*******************************************************************************
1328*/
1329bool CIccTagDict::Remove(const icUnicodeChar *szName)
1330{
1331 std::wstring sName;
1332 while(*szName)
1333 sName += *szName;
1334
1335 return Remove(sName);
1336
1337}
1338
1339
1340/**
1341******************************************************************************
1342* Name: CIccTagDict::Remove
1343*
1344* Purpose: Remove a name value pair from the dictionary
1345*
1346* Args:
1347* sName = the name to look for in the dictionary
1348*
1349* Return:
1350* true if sName exists and was remove , or false otherwise
1351*******************************************************************************
1352*/
1353bool CIccTagDict::Remove(const char *szName)
1354{
1355 std::wstring sName(szName, szName+strlen(szName));
1356
1357 return Remove(sName);
1358}
1359
1360
1361/**
1362******************************************************************************
1363* Name: CIccTagDict::Set
1364*
1365* Purpose: Associate a value with a name in the dictionary
1366*
1367* Args:
1368* sName = the name to look for in the dictionary
1369* sValue = value to associate with sName
1370* bUnset = flag to indicate that value has not been set (no data for value in tag)
1371*
1372* Return:
1373* true if value associate with sName was changed, or false if no change
1374*******************************************************************************
1375*/
1376bool CIccTagDict::Set(std::wstring sName, std::wstring sValue, bool bUnSet)
1377{
1378 CIccDictEntry *de = Get(sName);
1379
1380 if (de) {
1381 if (de->GetValue()==sValue && de->IsValueSet() && !bUnSet)
1382 return false;
1383 }
1384 else {
1385 de = new CIccDictEntry;
1386 de->GetName() = sName;
1387
1388 CIccDictEntryPtr ptr;
1389 ptr.ptr = de;
1390 m_Dict->push_back(ptr);
1391 }
1392
1393 if (sValue.empty() && bUnSet)
1394 de->UnsetValue();
1395 else
1396 de->SetValue(sValue);
1397
1398 return true;
1399}
1400
1401bool CIccTagDict::Set(const icUnicodeChar *szName, const icUnicodeChar *szValue)
1402{
1403 std::wstring sName;
1404 while(*szName)
1405 sName += *szName;
1406
1407 std::wstring sValue;
1408
1409 if (szValue) {
1410 while(*szValue)
1411 sValue += *szValue;
1412
1413 return Set(sName, sValue, false);
1414 }
1415
1416 return Set(sName, sValue, true);
1417}
1418
1419bool CIccTagDict::Set(const char *szName, const char *szValue)
1420{
1421 std::wstring sName(szName, szName+strlen(szName));
1422 std::wstring sValue;
1423
1424 if (szValue) {
1425 sValue.assign(szValue, szValue+strlen(szValue));
1426
1427 return Set(sName, sValue, false);
1428 }
1429
1430 return Set(sName, sValue, true);
1431}
1432
1433bool CIccTagDict::SetNameLocalized(std::wstring sName, CIccTagMultiLocalizedUnicode *pTag)
1434{
1435 CIccDictEntry *de = Get(sName);
1436
1437 if (!de) {
1438 de = new CIccDictEntry;
1439 de->GetName() = sName;
1440
1441 CIccDictEntryPtr ptr;
1442 ptr.ptr = de;
1443 m_Dict->push_back(ptr);
1444 }
1445
1446 return de->SetNameLocalized(pTag);
1447}
1448
1449bool CIccTagDict::SetNameLocalized(const icUnicodeChar *szName, CIccTagMultiLocalizedUnicode *pTag)
1450{
1451 std::wstring sName;
1452 while(*szName)
1453 sName += *szName++;
1454
1455 return SetNameLocalized(sName, pTag);
1456}
1457
1458bool CIccTagDict::SetNameLocalized(const char *szName, CIccTagMultiLocalizedUnicode *pTag)
1459{
1460 std::wstring sName;
1461 while(*szName)
1462 sName += *szName++;
1463
1464 return SetNameLocalized(sName, pTag);
1465}
1466
1467bool CIccTagDict::SetValueLocalized(std::wstring sName, CIccTagMultiLocalizedUnicode *pTag)
1468{
1469 CIccDictEntry *de = Get(sName);
1470
1471 if (!de) {
1472 de = new CIccDictEntry;
1473 de->GetName() = sName;
1474
1475 CIccDictEntryPtr ptr;
1476 ptr.ptr = de;
1477 m_Dict->push_back(ptr);
1478 }
1479
1480 return de->SetValueLocalized(pTag);
1481}
1482
1483bool CIccTagDict::SetValueLocalized(const icUnicodeChar *szName, CIccTagMultiLocalizedUnicode *pTag)
1484{
1485 std::wstring sName;
1486 while(*szName)
1487 sName += *szName++;
1488
1489 return SetValueLocalized(sName, pTag);
1490}
1491
1492bool CIccTagDict::SetValueLocalized(const char *szName, CIccTagMultiLocalizedUnicode *pTag)
1493{
1494 std::wstring sName(szName, szName+strlen(szName));
1495
1496 return SetValueLocalized(sName, pTag);
1497}
1498
1499#endif //ICC_UNSUPPORTED_TAG_DICT