Bug Summary

File:IccXML/IccLibXML/IccMpeXml.cpp
Warning:line 614, column 11
Memory allocated by 'new[]' should be deallocated by 'delete[]', not free()

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 IccMpeXml.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/IccXML -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 IccXML2_EXPORTS -I /Users/xss/DemoIccMAX-hoyt-master/build/Cmake/../../IccProfLib -I /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk/usr/include/libxml2 -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/IccXML -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/IccXML/IccLibXML/IccMpeXml.cpp
1/** @file
2 File: IccMpeXml.cpp
3
4 Contains: Implementation of MultiProcessElementType Element XML
5 conversion functionality
6
7 Version: V1
8
9 Copyright: (c) see ICC Software License
10*/
11
12/*
13 * The ICC Software License, Version 0.2
14 *
15 *
16 * Copyright (c) 2003-2012 The International Color Consortium. All rights
17 * reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 *
31 * 3. In the absence of prior written permission, the names "ICC" and "The
32 * International Color Consortium" must not be used to imply that the
33 * ICC organization endorses or promotes products derived from this
34 * software.
35 *
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
41 * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the The International Color Consortium.
53 *
54 *
55 * Membership in the ICC is encouraged when this software is used for
56 * commercial purposes.
57 *
58 *
59 * For more information on The International Color Consortium, please
60 * see <http://www.color.org/>.
61 *
62 *
63 */
64#include "IccTagXml.h"
65#include "IccMpeXml.h"
66#include "IccUtilXml.h"
67#include "IccIoXml.h"
68#include "IccCAM.h"
69
70#include <cstring> /* C strings strcpy, memcpy ... */
71
72#ifdef WIN32
73#include <windows.h>
74#ifdef GetClassName
75#undef GetClassName
76#endif
77#endif
78
79#ifdef USEREFICCMAXNAMESPACE
80namespace refIccMAX {
81#endif
82
83bool CIccMpeXmlUnknown::ToXml(std::string &xml, std::string blanks/* = ""*/)
84{
85 icUInt8Number *m_ptr = m_pData;
86
87 char line[256];
88 char buf[256];
89 char fix[256];
90 sprintf(line, "<UnknownElement Type=\"%s\" InputChannels=\"%d\" OutputChannels=\"%d\"",
91 icFixXml(fix, icGetSigStr(buf, GetType())), NumInputChannels(), NumOutputChannels());
92 xml += blanks + line;
93
94 if (m_nReserved) {
95 sprintf(line, " Reserved=\"%u\"", m_nReserved);
96 xml += buf;
97 }
98 xml += ">\n";
99
100 icXmlDumpHexData(xml, blanks + " ", m_pData, m_nSize);
101
102 xml += blanks + "</UnknownElement>\n";
103 return true;
104}
105
106
107bool CIccMpeXmlUnknown::ParseXml(xmlNode *pNode, std::string &parseStr)
108{
109 SetType((icElemTypeSignature)icXmlStrToSig(icXmlAttrValue(pNode, "type")));
110 SetChannels(atoi(icXmlAttrValue(pNode, "InputChannels")), atoi(icXmlAttrValue(pNode, "OutputChannels")));
111
112 if (pNode->children && pNode->children->type == XML_TEXT_NODE && pNode->children->content) {
113 icUInt32Number nSize = icXmlGetHexDataSize((const char *)pNode->children->content);
114
115 if (!SetDataSize(nSize, false))
116 return false;
117
118 icXmlGetHexData(m_pData, (const char *)pNode->children->content, nSize);
119 }
120 else {
121 SetDataSize(0);
122 }
123 return true;
124}
125
126
127class CIccFormulaCurveSegmentXml : public CIccFormulaCurveSegment
128{
129public:
130 CIccFormulaCurveSegmentXml(icFloatNumber start, icFloatNumber end) : CIccFormulaCurveSegment(start, end) {}
131
132 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
133 bool ParseXml(xmlNode *pNode, std::string &parseStr);
134};
135
136static char* icSegPos(char *buf, icFloatNumber pos)
137{
138 if (pos==icMinFloat32Number-3.402823466e+38F)
139 strcpy(buf, "-infinity");
140 else if (pos==icMaxFloat32Number3.402823466e+38F)
141 strcpy(buf, "+infinity");
142 else
143 sprintf(buf, "%.8" ICFLOATSFX"f", pos);
144
145 return buf;
146}
147
148icFloatNumber icGetSegPos(const char *str)
149{
150 if (!strncmp(str, "-inf", 4)) {
151 return icMinFloat32Number-3.402823466e+38F;
152 }
153 if (!strncmp(str, "+inf", 4)) {
154 return icMaxFloat32Number3.402823466e+38F;
155 }
156
157 return (icFloatNumber)atof(str);
158}
159
160
161bool CIccFormulaCurveSegmentXml::ToXml(std::string &xml, std::string blanks)
162{
163 char buf[256];
164 char line[256];
165
166 sprintf(line, "<FormulaSegment Start=\"%s\"", icSegPos(buf, m_startPoint));
167 xml += blanks + line;
168
169 sprintf(line, " End=\"%s\"",icSegPos(buf, m_endPoint));
170 xml += line;
171
172 sprintf(line, " FunctionType=\"%d\"", m_nFunctionType);
173 xml += line;
174
175 if (m_nReserved) {
176 sprintf(line, " Reserved=\"%d\"", m_nReserved);
177 xml += line;
178 }
179 if (m_nReserved2) {
180 sprintf(line, " Reserved2=\"%d\"", m_nReserved2);
181 xml += line;
182 }
183 xml += ">\n";
184
185 CIccFloatArray::DumpArray(xml, blanks+" ", m_params, m_nParameters, icConvertFloat, 8);
186
187 xml += blanks + "</FormulaSegment>\n";
188
189 return true;
190}
191
192
193bool CIccFormulaCurveSegmentXml::ParseXml(xmlNode *pNode, std::string &parseStr)
194{
195 xmlAttr *funcType = icXmlFindAttr(pNode, "FunctionType");
196
197 if (!funcType) {
198 parseStr += "Bad FunctionType in Formula Segment\n";
199 return false;
200 }
201
202 m_nReserved2 = atoi(icXmlAttrValue(pNode, "Reserved2"));
203 m_nFunctionType = atoi(icXmlAttrValue(funcType));
204
205 switch(m_nFunctionType) {
206 case 0x0000:
207 m_nParameters = 4;
208 break;
209
210 case 0x0001:
211 case 0x0002:
212 case 0x0003:
213 m_nParameters = 5;
214 break;
215
216 default:
217 parseStr += "Unsupported FunctionType value in Formula Segment\n";
218 return false;
219 }
220
221 CIccFloatArray args;
222
223 if (!args.ParseArray(pNode->children))
224 return false;
225
226 if (args.GetSize()>m_nParameters)
227 return false;
228
229 if (m_params) {
230 free(m_params);
231 }
232
233 if (m_nParameters) {
234 m_params = (icFloatNumber*)malloc(m_nParameters * sizeof(icFloatNumber));
235 if (!m_params)
236 return false;
237
238 memcpy(m_params, args.GetBuf(), m_nParameters * sizeof(icFloatNumber));
239 }
240 else
241 m_params = NULL__null;
242
243 return true;
244}
245
246
247class CIccSampledCurveSegmentXml : public CIccSampledCurveSegment
248{
249public:
250 CIccSampledCurveSegmentXml(icFloatNumber start, icFloatNumber end) : CIccSampledCurveSegment(start, end) {}
251
252 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
253 bool ParseXml(xmlNode *pNode, std::string &parseStr);
254};
255
256bool CIccSampledCurveSegmentXml::ToXml(std::string &xml, std::string blanks)
257{
258 char buf[256];
259 char line[256];
260
261 sprintf(line, "<SampledSegment Start=\"%s\"", icSegPos(buf, m_startPoint));
262 xml += blanks + line;
263
264 sprintf(line, " End=\"%s\">\n",icSegPos(buf, m_endPoint));
265 xml += line;
266
267 CIccFloatArray::DumpArray(xml, blanks+" ", m_pSamples, m_nCount, icConvertFloat, 8);
268
269 xml += blanks + "</SampledSegment>\n";
270
271 return true;
272}
273
274
275bool CIccSampledCurveSegmentXml::ParseXml(xmlNode *pNode, std::string &parseStr)
276{
277 const char *filename = icXmlAttrValue(pNode, "Filename");
278
279 // file exists
280 if (filename[0]) {
281 CIccIO *file = IccOpenFileIO(filename, "rb");
282 if (!file){
283 parseStr += "Error! - File '";
284 parseStr += filename;
285 parseStr +="' not found.\n";
286 delete file;
287 return false;
288 }
289
290 const char *format = icXmlAttrValue(pNode, "Format");
291
292 // format is text
293 if (!strcmp(format, "text")) {
294 icUInt32Number num = file->GetLength();
295 char *buf = (char *) new char[num];
296
297 if (!buf) {
298 perror("Memory Error");
299 parseStr += "'";
300 parseStr += filename;
301 parseStr += "' may not be a valid text file.\n";
302 delete buf;
303 delete file;
304 return false;
305 }
306
307 if (file->Read8(buf, num) !=num) {
308 perror("Read-File Error");
309 parseStr += "'";
310 parseStr += filename;
311 parseStr += "' may not be a valid text file.\n";
312 delete buf;
313 delete file;
314 return false;
315 }
316
317 CIccFloatArray data;
318
319 //if (!data.ParseTextArray(buf)) {
320 if (!data.ParseTextArrayNum(buf, num, parseStr)){
321 parseStr += "File '";
322 parseStr += filename;
323 parseStr += "' is not a valid text file.\n";
324 SetSize(0);
325 delete buf;
326 delete file;
327 return false;
328 }
329
330 else {
331 SetSize(data.GetSize());
332 icFloatNumber *src = data.GetBuf();
333 icFloatNumber *dst = m_pSamples;
334
335 icUInt32Number i;
336 for (i=0; i<data.GetSize(); i++) {
337 *dst = *src;
338 dst++;
339 src++;
340 }
341 }
342
343 delete buf;
344 delete file;
345 return true;
346
347 }
348 // format is binary
349 else if (!strcmp(format, "binary")) {
350 const char *order = icXmlAttrValue(pNode, "Endian");
351 bool little_endian = !strcmp(order, "little");
352
353 icUInt16Number storageType = icValueTypeFloat32;
354 xmlAttr *attr = icXmlFindAttr(pNode, "StorageType");
355 if (attr) {
356 storageType = (icUInt16Number)atoi(icXmlAttrValue(attr));
357 }
358
359 if (storageType == icValueTypeUInt8){
360 icUInt32Number num = file->GetLength();
361 icUInt8Number value;
362
363 SetSize(num);
364 icFloatNumber *dst = m_pSamples;
365 icUInt32Number i;
366 for (i=0; i<num; i++) {
367 if (!file->Read8(&value)) {
368 perror("Read-File Error");
369 parseStr += "'";
370 parseStr += filename;
371 parseStr += "' may not be a valid binary file.\n";
372 delete file;
373 return false;
374 }
375 *dst++ = (icFloatNumber)value / 255.0f;
376 }
377 delete file;
378 return true;
379 }
380 else if (storageType == icValueTypeUInt16){
381 icUInt32Number num = file->GetLength() / sizeof(icUInt16Number);
382 icUInt16Number value;
383 icUInt8Number *m_ptr = (icUInt8Number*)&value;
384
385 SetSize(num);
386 icFloatNumber *dst = m_pSamples;
387 icUInt32Number i;
388 for (i=0; i<num; i++) {
389 if (!file->Read16(&value)) { //assumes data is big endian
390 perror("Read-File Error");
391 parseStr += "'";
392 parseStr += filename;
393 parseStr += "' may not be a valid binary file.\n";
394 delete file;
395 return false;
396 }
397#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
398 if (little_endian) {
399#else
400 if (!little_endian) {
401#endif
402 icUInt8Number t = m_ptr[0];
403 m_ptr[0] = m_ptr[1];
404 m_ptr[1] = t;
405 }
406 *dst++ = (icFloatNumber)value / 65535.0f;
407 }
408 delete file;
409 return true;
410 }
411 else if (storageType == icValueTypeFloat16){
412 icUInt32Number num = file->GetLength() / sizeof(icFloat16Number);
413 icFloat16Number value;
414 icUInt8Number *m_ptr = (icUInt8Number*)&value;
415
416 SetSize(num);
417 icFloatNumber *dst = m_pSamples;
418 icUInt32Number i;
419 for (i=0; i<num; i++) {
420 if (!file->Read16(&value)) { //assumes data is big endian
421 perror("Read-File Error");
422 parseStr += "'";
423 parseStr += filename;
424 parseStr += "' may not be a valid binary file.\n";
425 delete file;
426 return false;
427 }
428#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
429 if (little_endian) {
430#else
431 if (!little_endian) {
432#endif
433 icUInt8Number t = m_ptr[0];
434 m_ptr[0] = m_ptr[1];
435 m_ptr[1] = t;
436 }
437 *dst++ = icF16toF(value);
438 }
439 delete file;
440 return true;
441 }
442 else if (storageType == icValueTypeFloat32) {
443 icUInt32Number num = file->GetLength()/sizeof(icFloat32Number);
444 icFloat32Number value;
445 icUInt8Number *m_ptr = (icUInt8Number*)&value;
446
447 SetSize(num);
448 icFloatNumber *dst = m_pSamples;
449
450 icUInt32Number i;
451 for (i=0; i<num; i++) {
452 if (!file->ReadFloat32Float(&value)) { //assumes data is big endian
453 perror("Read-File Error");
454 parseStr += "'";
455 parseStr += filename;
456 parseStr += "' may not be a valid binary file.\n";
457 delete file;
458 return false;
459 }
460#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
461 if (little_endian) {
462#else
463 if (!little_endian) {
464#endif
465 icUInt8Number tmp;
466 tmp = m_ptr[0]; m_ptr[0] = m_ptr[3]; m_ptr[3] = tmp;
467 tmp = m_ptr[1]; m_ptr[1] = m_ptr[2]; m_ptr[2] = tmp;
468 }
469 *dst++ = value;
470 }
471 delete file;
472 return true;
473 }
474 else { //not 8bit/16bit/float
475 delete file;
476 return false;
477 }
478 }
479 }
480 else {
481 CIccFloatArray samples;
482
483 if (!samples.ParseArray(pNode->children)) {
484 return false;
485 }
486
487 if (!SetSize(samples.GetSize())) {
488 return false;
489 }
490
491 memcpy(m_pSamples, samples.GetBuf(), samples.GetSize() * sizeof(icFloatNumber));
492 }
493
494 return true;
495}
496
497
498class CIccSinglSampledeCurveXml : public CIccSingleSampledCurve
499{
500public:
501 CIccSinglSampledeCurveXml(icFloatNumber first=0, icFloatNumber last=0) : CIccSingleSampledCurve(first, last) {}
502
503 bool ToXml(std::string &xml, std::string blanks/* = ""*/);
504 bool ParseXml(xmlNode *pNode, std::string &parseStr);
505};
506
507bool CIccSinglSampledeCurveXml::ToXml(std::string &xml, std::string blanks)
508{
509 char line[256];
510
511 xml += blanks;
512 sprintf(line, "<SingleSampledCurve FirstEntry=\"%.8f\"", m_firstEntry);
513 xml += line;
514
515 sprintf(line, " LastEntry=\"%.8f\"", m_lastEntry);
516 xml += line;
517
518 sprintf(line, " StorageType=\"%u\"", m_storageType);
519 xml += line;
520
521 sprintf(line, " ExtensionType=\"%u\">\n", m_extensionType);
522 xml += line;
523
524 CIccFloatArray::DumpArray(xml, blanks+" ", m_pSamples, m_nCount, icConvertFloat, 8);
525
526 xml += blanks + "</SingleSampledCurve>\n";
527
528 return true;
529}
530
531
532bool CIccSinglSampledeCurveXml::ParseXml(xmlNode *pNode, std::string &parseStr)
533{
534 xmlAttr *attr = icXmlFindAttr(pNode, "FirstEntry");
535
536 if (!attr) {
13
Assuming 'attr' is non-null
14
Taking false branch
537 parseStr += "Bad FirstEntry in Simple Sampled Segment\n";
538 return false;
539 }
540
541 m_firstEntry = (icFloatNumber)atof(icXmlAttrValue(attr));
542
543 attr = icXmlFindAttr(pNode, "LastEntry");
544
545 if (!attr) {
15
Assuming 'attr' is non-null
16
Taking false branch
546 parseStr += "Bad LastEntry in Simple Sampled Segment\n";
547 return false;
548 }
549
550 m_lastEntry = (icFloatNumber)atof(icXmlAttrValue(attr));
551
552 m_storageType = icValueTypeFloat32;
553 attr = icXmlFindAttr(pNode, "StorageType");
554 if (attr) {
17
Assuming 'attr' is non-null
18
Taking true branch
555 m_storageType = (icUInt16Number)atoi(icXmlAttrValue(attr));
556 }
557
558 m_extensionType = icClipSingleSampledCurve;
559 attr = icXmlFindAttr(pNode, "ExtensionType");
560 if (attr) {
19
Assuming 'attr' is null
20
Taking false branch
561 m_extensionType = (icUInt16Number)atoi(icXmlAttrValue(attr));
562 }
563
564 const char *filename = icXmlAttrValue(pNode, "Filename");
565
566 // file exists
567 if (filename[0]) {
21
Assuming the condition is true
22
Taking true branch
568 CIccIO *file = IccOpenFileIO(filename, "rb");
569 if (!file){
23
Assuming 'file' is non-null
24
Taking false branch
570 parseStr += "Error! - File '";
571 parseStr += filename;
572 parseStr +="' not found.\n";
573 delete file;
574 return false;
575 }
576
577 const char *format = icXmlAttrValue(pNode, "Format");
578
579 // format is text
580 if (!strcmp(format, "text")) {
25
Taking true branch
581 icUInt32Number num = file->GetLength();
582 char *buf = (char *) new char[num];
26
Memory is allocated
583
584 if (!buf
26.1
'buf' is non-null
) {
27
Taking false branch
585 perror("Memory Error");
586 parseStr += "'";
587 parseStr += filename;
588 parseStr += "' may not be a valid text file.\n";
589 free(buf);
590 delete file;
591 return false;
592 }
593
594 if (file->Read8(buf, num) !=num) {
28
Assuming the condition is false
29
Taking false branch
595 perror("Read-File Error");
596 parseStr += "'";
597 parseStr += filename;
598 parseStr += "' may not be a valid text file.\n";
599 free(buf);
600 delete file;
601 return false;
602 }
603
604 // lut8type
605 if (m_storageType == icValueTypeUInt8) {
30
Assuming field 'm_storageType' is equal to icValueTypeUInt8
31
Taking true branch
606 CIccUInt8Array data;
607
608 //if (!data.ParseTextArray(buf)) {
609 if (!data.ParseTextArrayNum(buf, num, parseStr)){
32
Assuming the condition is true
33
Taking true branch
610 parseStr += "File '";
611 parseStr += filename;
612 parseStr += "' is not a valid text file.\n";
613 SetSize(0);
614 free(buf);
34
Memory allocated by 'new[]' should be deallocated by 'delete[]', not free()
615 delete file;
616 return false;
617 }
618
619 else {
620 SetSize(data.GetSize());
621 icUInt8Number *src = data.GetBuf();
622 icFloatNumber *dst = m_pSamples;
623
624 icUInt32Number i;
625 for (i=0; i<data.GetSize(); i++) {
626 *dst = (icFloatNumber)(*src) / 255.0f;
627 dst++;
628 src++;
629 }
630
631 //if (i!=256) {
632 //printf("Error! - Input/Output table does not have 256 entries.\n");
633 //SetSize(0);
634 //return false;
635 //}
636 delete file;
637 return true;
638 }
639 }
640
641 //lut16type
642 else if (m_storageType == icValueTypeUInt16) {
643 CIccUInt16Array data;
644
645 //if (!data.ParseTextArray(buf)) {
646 if (!data.ParseTextArrayNum(buf, num, parseStr)){
647 parseStr += "File '";
648 parseStr += filename;
649 parseStr += "' is not a valid text file.\n";
650 SetSize(0);
651 free(buf);
652 delete file;
653 return false;
654 }
655
656 else {
657 SetSize(data.GetSize());
658
659 icUInt16Number *src = data.GetBuf();
660 icFloatNumber *dst = m_pSamples;
661
662 icUInt32Number i;
663 for (i=0; i<data.GetSize(); i++) {
664 *dst = (icFloatNumber)(*src) / 65535.0f;
665 dst++;
666 src++;
667 }
668 }
669 delete file;
670 return true;
671 }
672
673 //float type
674 else if (m_storageType == icValueTypeFloat32){
675 CIccFloatArray data;
676
677 //if (!data.ParseTextArray(buf)) {
678 if (!data.ParseTextArrayNum(buf, num, parseStr)){
679 parseStr += "File '";
680 parseStr += filename;
681 parseStr += "' is not a valid text file.\n";
682 SetSize(0);
683 free(buf);
684 delete file;
685 return false;
686 }
687
688 else {
689 SetSize(data.GetSize());
690 icFloatNumber *src = data.GetBuf();
691 icFloatNumber *dst = m_pSamples;
692
693 icUInt32Number i;
694 for (i=0; i<data.GetSize(); i++) {
695 *dst = *src;
696 dst++;
697 src++;
698 }
699 }
700 delete file;
701 return true;
702 }
703 else {
704 delete file;
705 return false;
706 }
707 }
708 // format is binary
709 else if (!strcmp(format, "binary")) {
710 const char *order = icXmlAttrValue(pNode, "Endian");
711 bool little_endian = !strcmp(order, "little");
712
713 if (m_storageType == icValueTypeUInt8){
714 icUInt32Number num = file->GetLength();
715 icUInt8Number value;
716
717 SetSize(num);
718 icFloatNumber *dst = m_pSamples;
719 icUInt32Number i;
720 for (i=0; i<num; i++) {
721 if (!file->Read8(&value)) {
722 perror("Read-File Error");
723 parseStr += "'";
724 parseStr += filename;
725 parseStr += "' may not be a valid binary file.\n";
726 delete file;
727 return false;
728 }
729 *dst++ = (icFloatNumber)value / 255.0f;
730 }
731 delete file;
732 return true;
733 }
734 else if (m_storageType == icValueTypeUInt16){
735 icUInt32Number num = file->GetLength() / sizeof(icUInt16Number);
736 icUInt16Number value;
737 icUInt8Number *m_ptr = (icUInt8Number*)&value;
738
739 SetSize(num);
740 icFloatNumber *dst = m_pSamples;
741 icUInt32Number i;
742 for (i=0; i<num; i++) {
743 if (!file->Read16(&value)) { //assumes data is big endian
744 perror("Read-File Error");
745 parseStr += "'";
746 parseStr += filename;
747 parseStr += "' may not be a valid binary file.\n";
748 delete file;
749 return false;
750 }
751#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
752 if (little_endian) {
753#else
754 if (!little_endian) {
755#endif
756 icUInt8Number t = m_ptr[0];
757 m_ptr[0] = m_ptr[1];
758 m_ptr[1] = t;
759 }
760 *dst++ = (icFloatNumber)value / 65535.0f;
761 }
762 delete file;
763 return true;
764 }
765 else if (m_storageType == icValueTypeFloat16){
766 icUInt32Number num = file->GetLength() / sizeof(icFloat16Number);
767 icFloat16Number value;
768 icUInt8Number *m_ptr = (icUInt8Number*)&value;
769
770 SetSize(num);
771 icFloatNumber *dst = m_pSamples;
772 icUInt32Number i;
773 for (i=0; i<num; i++) {
774 if (!file->Read16(&value)) { //assumes data is big endian
775 perror("Read-File Error");
776 parseStr += "'";
777 parseStr += filename;
778 parseStr += "' may not be a valid binary file.\n";
779 delete file;
780 return false;
781 }
782#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
783 if (little_endian) {
784#else
785 if (!little_endian) {
786#endif
787 icUInt8Number t = m_ptr[0];
788 m_ptr[0] = m_ptr[1];
789 m_ptr[1] = t;
790 }
791 *dst++ = icF16toF(value);
792 }
793 delete file;
794 return true;
795 }
796 else if (m_storageType == icValueTypeFloat32) {
797 icUInt32Number num = file->GetLength()/sizeof(icFloat32Number);
798 icFloat32Number value;
799 icUInt8Number *m_ptr = (icUInt8Number*)&value;
800
801 SetSize(num);
802 icFloatNumber *dst = m_pSamples;
803
804 icUInt32Number i;
805 for (i=0; i<num; i++) {
806 if (!file->ReadFloat32Float(&value)) {
807 perror("Read-File Error");
808 parseStr += "'";
809 parseStr += filename;
810 parseStr += "' may not be a valid binary file.\n";
811 delete file;
812 return false;
813 }
814#ifdef ICC_BYTE_ORDER_LITTLE_ENDIAN
815 if (little_endian) {
816#else
817 if (!little_endian) {
818#endif
819 icUInt8Number tmp;
820 tmp = m_ptr[0]; m_ptr[0] = m_ptr[3]; m_ptr[3] = tmp;
821 tmp = m_ptr[1]; m_ptr[1] = m_ptr[2]; m_ptr[2] = tmp;
822 }
823 *dst++ = value;
824 }
825 delete file;
826 return true;
827 }
828 else { //not 8bit/16bit/float
829 delete file;
830 return false;
831 }
832 }
833 else {//not text/binary
834 delete file;
835 return false;
836 }
837 }
838 // no file
839 else{
840 CIccFloatArray samples;
841
842 if (!samples.ParseArray(pNode->children)) {
843 return false;
844 }
845
846 if (!SetSize(samples.GetSize())) {
847 return false;
848 }
849
850 memcpy(m_pSamples, samples.GetBuf(), samples.GetSize() * sizeof(icFloatNumber));
851 }
852
853 return true;
854}
855
856
857bool CIccSegmentedCurveXml::ToXml(std::string &xml, std::string blanks)
858{
859 CIccCurveSegmentList::iterator seg;
860 xml += blanks + "<SegmentedCurve>\n";
861 for (seg = m_list->begin(); seg!=m_list->end(); seg++) {
862 CIccCurveSegment* pSeg = *seg;
863 if (pSeg && pSeg->GetType() == icSigFormulaCurveSeg) {
864 if (!((CIccFormulaCurveSegmentXml*)pSeg)->ToXml(xml, blanks+" "))
865 return false;
866 }
867 else if (pSeg && pSeg->GetType() == icSigSampledCurveSeg) {
868 if (!((CIccSampledCurveSegmentXml*)pSeg)->ToXml(xml, blanks+" "))
869 return false;
870 }
871 else
872 return false;
873 }
874 xml += blanks + "</SegmentedCurve>\n";
875 return true;
876}
877
878
879bool CIccSegmentedCurveXml::ParseXml(xmlNode *pNode, std::string &parseStr)
880{
881 m_list->clear();
882 for (pNode=pNode->children; pNode; pNode=pNode->next) {
883 if (pNode->type == XML_ELEMENT_NODE) {
884 icFloatNumber start = icGetSegPos(icXmlAttrValue(pNode, "Start"));
885 icFloatNumber end = icGetSegPos(icXmlAttrValue(pNode, "End"));
886
887 if (!icXmlStrCmp(pNode->name, "FormulaSegment")strcmp((const char *)(pNode->name), (const char*)("FormulaSegment"
))
) {
888 CIccFormulaCurveSegmentXml *pSegXml = new CIccFormulaCurveSegmentXml(start, end);
889
890 if (!pSegXml->ParseXml(pNode, parseStr)) {
891 parseStr += "Unable to parse FormulaSegment\n";
892 delete pSegXml;
893 return false;
894 }
895 m_list->push_back(pSegXml);
896 }
897 else if (!icXmlStrCmp(pNode->name, "SampledSegment")strcmp((const char *)(pNode->name), (const char*)("SampledSegment"
))
) {
898 CIccSampledCurveSegmentXml *pSegXml = new CIccSampledCurveSegmentXml(start, end);
899
900 if (!pSegXml->ParseXml(pNode, parseStr)) {
901 parseStr += "Unable to parse SampledSegment\n";
902 delete pSegXml;
903 return false;
904 }
905 m_list->push_back(pSegXml);
906 }
907 else {
908 parseStr += "Bad Segment Type\n";
909 return false;
910 }
911 }
912 }
913 return true;
914}
915
916
917bool CIccMpeXmlCurveSet::ToXml(std::string &xml, std::string blanks/* = ""*/)
918{
919 char line[256];
920 sprintf(line, "<CurveSetElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
921 xml += blanks + line;
922
923 if (m_nReserved) {
924 sprintf(line, " Reserved=\"%u\"", m_nReserved);
925 xml += line;
926 }
927 xml += ">\n";
928
929 int i;
930
931 for (i=0; i<NumInputChannels(); i++) {
932 CIccCurveSetCurve* curve = m_curve[i];
933 if (curve->GetType() == icSigSingleSampledCurve) {
934 CIccSinglSampledeCurveXml *m_ptr = (CIccSinglSampledeCurveXml*)m_curve[i];
935
936 if (!(m_ptr->ToXml(xml, blanks + " ")))
937 return false;
938 }
939 else if (curve->GetType() == icSigSegmentedCurve) {
940 CIccSegmentedCurveXml *m_ptr = (CIccSegmentedCurveXml*)m_curve[i];
941
942 if (!(m_ptr->ToXml(xml, blanks + " ")))
943 return false;
944 }
945 else
946 return false;
947 }
948
949 xml += blanks + "</CurveSetElement>\n";
950 return true;
951}
952
953
954bool CIccMpeXmlCurveSet::ParseXml(xmlNode *pNode, std::string &parseStr)
955{
956 icUInt16Number nChannels = (icUInt16Number)atoi(icXmlAttrValue(pNode, "InputChannels"));
957
958 if (!nChannels || atoi(icXmlAttrValue(pNode, "OutputChannels")) != nChannels) {
1
Assuming 'nChannels' is not equal to 0
2
Assuming the condition is false
3
Taking false branch
959 parseStr += "Invalid InputChannels or OutputChannels In CurveSetElement\n";
960 return false;
961 }
962
963 SetSize(nChannels);
964 int nIndex = 0;
965 for (pNode = pNode->children, nIndex = 0;
4
Loop condition is true. Entering loop body
966 pNode;
967 pNode=pNode->next) {
968 if (pNode->type == XML_ELEMENT_NODE) {
5
Assuming field 'type' is equal to XML_ELEMENT_NODE
6
Taking true branch
969 if (nIndex >= nChannels) {
7
Assuming 'nIndex' is < 'nChannels'
8
Taking false branch
970 return false;
971 }
972 else if (!strcmp((const char*)pNode->name, "SegmentedCurve")) {
9
Assuming the condition is false
10
Taking false branch
973 CIccSegmentedCurveXml *pCurve = new CIccSegmentedCurveXml();
974
975 if (!pCurve->ParseXml(pNode, parseStr)) {
976 delete pCurve;
977 return false;
978 }
979 if (!SetCurve(nIndex, pCurve))
980 return false;
981 nIndex++;
982 }
983 else if (!strcmp((const char*)pNode->name, "SingleSampledCurve")) {
11
Taking true branch
984 CIccSinglSampledeCurveXml *pCurve = new CIccSinglSampledeCurveXml();
985
986 if (!pCurve->ParseXml(pNode, parseStr)) {
12
Calling 'CIccSinglSampledeCurveXml::ParseXml'
987 delete pCurve;
988 return false;
989 }
990 if (!SetCurve(nIndex, pCurve))
991 return false;
992 nIndex++;
993 }
994 else
995 return false;
996 }
997 }
998
999 if (!pNode && nIndex == nChannels)
1000 return true;
1001
1002 return false;
1003}
1004
1005
1006bool CIccMpeXmlMatrix::ToXml(std::string &xml, std::string blanks/* = ""*/)
1007{
1008 char buf[128];
1009 sprintf(buf, "<MatrixElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1010 xml += blanks + buf;
1011
1012 if (m_nReserved) {
1013 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1014 xml += buf;
1015 }
1016 xml += ">\n";
1017
1018 int i, j, n;
1019
1020 if (m_pMatrix) {
1021 xml += blanks + " <MatrixData>\n";
1022
1023 for (n=0, j=0; j<NumOutputChannels(); j++) {
1024 xml += blanks + " ";
1025 for (i=0; i<NumInputChannels(); i++, n++) {
1026 sprintf(buf, " %.8f", m_pMatrix[n]);
1027 xml += buf;
1028 }
1029 xml += "\n";
1030 }
1031 xml += blanks + " </MatrixData>\n";
1032 }
1033
1034 if (m_pConstants) {
1035 for (i = 0; i < NumOutputChannels(); i++) {
1036 if (icNotZero(m_pConstants[i])((m_pConstants[i])>1.0e-8 || (m_pConstants[i])<-1.0e-8))
1037 break;
1038 }
1039 if (i < NumOutputChannels()) {
1040 xml += blanks + " <ConstantData>\n";
1041
1042 xml += blanks + " ";
1043 for (i = 0; i < NumOutputChannels(); i++) {
1044 sprintf(buf, " %.8f", m_pConstants[i]);
1045 xml += buf;
1046 }
1047 xml += "\n";
1048
1049 xml += blanks + " </ConstantData>\n";
1050 }
1051 }
1052
1053 xml += blanks + "</MatrixElement>\n";
1054
1055 return true;
1056}
1057
1058
1059bool CIccMpeXmlMatrix::ParseXml(xmlNode *pNode, std::string &parseStr)
1060{
1061 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1062 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1063 if (!nInputChannels || !nOutputChannels) {
1064 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1065 return false;
1066 }
1067
1068 xmlNode *pData;
1069
1070 pData = icXmlFindNode(pNode->children, "MatrixData");
1071 if (pData) {
1072 SetSize(nInputChannels, nOutputChannels);
1073
1074 if (!CIccFloatArray::ParseArray(m_pMatrix, m_nInputChannels*m_nOutputChannels, pData->children))
1075 return false;
1076
1077 const char *invert = icXmlAttrValue(pData, "InvertMatrix", "false");
1078 if (!stricmpstrcasecmp(invert, "true")) {
1079 if (m_nInputChannels != m_nOutputChannels) {
1080 parseStr += "Inversion of MatrixData requires square matrix\n";
1081 return false;
1082 }
1083 IIccMatrixInverter *pInverter = IccGetDefaultMatrixInverter();
1084 if (!pInverter || !pInverter->Invert(m_pMatrix, m_nOutputChannels, m_nInputChannels)) {
1085 parseStr += "Unable to invert matrix!\n";
1086 return false;
1087 }
1088 }
1089 }
1090 else { //Having no MatrixData implies having a matrix full of zeros which is represented by m_pMatrix set to NULL
1091 SetSize(0, nOutputChannels); //Initialize with m_pMatrix set to NULL
1092 m_nInputChannels = nInputChannels; //Fix m_nInputChannels
1093 }
1094
1095 pData = icXmlFindNode(pNode->children, "ConstantData");
1096 if (pData) {
1097 if (!CIccFloatArray::ParseArray(m_pConstants, m_nOutputChannels, pData->children))
1098 return false;
1099 }
1100 return true;
1101}
1102
1103bool CIccMpeXmlEmissionMatrix::ToXml(std::string &xml, std::string blanks/* = ""*/)
1104{
1105 char buf[128];
1106 sprintf(buf, "<EmissionMatrixElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1107 xml += blanks + buf;
1108
1109 if (m_nReserved) {
1110 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1111 xml += buf;
1112 }
1113 xml += ">\n";
1114
1115 sprintf(buf, " <Wavelengths start=\"%.8f\" end=\"%.8f\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
1116 xml += blanks + buf;
1117
1118 int i, j, n;
1119
1120 if (m_pWhite) {
1121 xml += blanks + " <WhiteData>\n";
1122
1123 xml += blanks + " ";
1124 for (i=0; i<(int)m_Range.steps; i++) {
1125 sprintf(buf, " %.8f", m_pWhite[i]);
1126 xml += buf;
1127 }
1128 xml += "\n";
1129
1130 xml += blanks + " </WhiteData>\n";
1131 }
1132
1133 if (m_pMatrix) {
1134 xml += blanks + " <MatrixData>\n";
1135
1136 for (n=0, j=0; j<numVectors(); j++) {
1137 xml += blanks + " ";
1138 for (i=0; i<(int)m_Range.steps; i++, n++) {
1139 sprintf(buf, " %.8f", m_pMatrix[n]);
1140 xml += buf;
1141 }
1142 xml += "\n";
1143 }
1144 xml += blanks + " </MatrixData>\n";
1145 }
1146
1147 if (m_pOffset) {
1148 xml += blanks + " <OffsetData>\n";
1149
1150 xml += blanks + " ";
1151 for (i=0; i<(int)m_Range.steps; i++) {
1152 sprintf(buf, " %.8f", m_pOffset[i]);
1153 xml += buf;
1154 }
1155 xml += "\n";
1156
1157 xml += blanks + " </OffsetData>\n";
1158 }
1159
1160 xml += blanks + "</EmissionMatrixElement>\n";
1161
1162 return true;
1163}
1164
1165
1166bool CIccMpeXmlEmissionMatrix::ParseXml(xmlNode *pNode, std::string &parseStr)
1167{
1168 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1169 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1170
1171 if (!nInputChannels || !nOutputChannels) {
1172 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1173 return false;
1174 }
1175
1176 xmlNode *pData;
1177
1178 pData = icXmlFindNode(pNode->children, "Wavelengths");
1179 if (pData) {
1180 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
1181 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
1182 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
1183
1184 if (!nSteps) {
1185 parseStr += "Invalid Spectral Range\n";
1186 return false;
1187 }
1188 m_Range.start = icFtoF16(dStart);
1189 m_Range.end = icFtoF16(dEnd);
1190 m_Range.steps = nSteps;
1191 }
1192
1193 SetSize(nInputChannels, nOutputChannels, m_Range);
1194 if (!m_pWhite || !m_pMatrix || !m_pOffset) {
1195 parseStr += "Unable to SetSize\n";
1196 return false;
1197 }
1198
1199 pData = icXmlFindNode(pNode->children, "WhiteData");
1200 if (pData) {
1201
1202 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
1203 return false;
1204 }
1205 else {
1206 parseStr += "Missing MatrixData";
1207 }
1208
1209 pData = icXmlFindNode(pNode->children, "MatrixData");
1210 if (pData) {
1211
1212 if (!CIccFloatArray::ParseArray(m_pMatrix, numVectors()*(int)m_Range.steps, pData->children))
1213 return false;
1214 }
1215 else {
1216 parseStr += "Missing MatrixData";
1217 }
1218
1219 pData = icXmlFindNode(pNode->children, "OffsetData");
1220 if (pData) {
1221 if (!CIccFloatArray::ParseArray(m_pOffset, m_Range.steps, pData->children))
1222 return false;
1223 }
1224 else {
1225 memset(m_pOffset, 0, (int)m_Range.steps*sizeof(icFloatNumber));
1226 }
1227 return true;
1228}
1229
1230bool CIccMpeXmlInvEmissionMatrix::ToXml(std::string &xml, std::string blanks/* = ""*/)
1231{
1232 char buf[128];
1233 sprintf(buf, "<InvEmissionMatrixElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1234 xml += blanks + buf;
1235
1236 if (m_nReserved) {
1237 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1238 xml += buf;
1239 }
1240 xml += ">\n";
1241
1242 sprintf(buf, " <Wavelengths start=\"%.8f\" end=\"%.8f\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
1243 xml += blanks + buf;
1244
1245 int i, j, n;
1246
1247 if (m_pWhite) {
1248 xml += blanks + " <WhiteData>\n";
1249
1250 xml += blanks + " ";
1251 for (i=0; i<(int)m_Range.steps; i++) {
1252 sprintf(buf, " %.8f", m_pWhite[i]);
1253 xml += buf;
1254 }
1255 xml += "\n";
1256
1257 xml += blanks + " </WhiteData>\n";
1258 }
1259
1260 if (m_pMatrix) {
1261 xml += blanks + " <MatrixData>\n";
1262
1263 for (n=0, j=0; j<numVectors(); j++) {
1264 xml += blanks + " ";
1265 for (i=0; i<(int)m_Range.steps; i++, n++) {
1266 sprintf(buf, " %.8f", m_pMatrix[n]);
1267 xml += buf;
1268 }
1269 xml += "\n";
1270 }
1271 xml += blanks + " </MatrixData>\n";
1272 }
1273
1274 if (m_pOffset) {
1275 xml += blanks + " <OffsetData>\n";
1276
1277 xml += blanks + " ";
1278 for (i=0; i<(int)m_Range.steps; i++) {
1279 sprintf(buf, " %.8f", m_pOffset[i]);
1280 xml += buf;
1281 }
1282 xml += "\n";
1283
1284 xml += blanks + " </OffsetData>\n";
1285 }
1286
1287 xml += blanks + "</InvEmissionMatrixElement>\n";
1288
1289 return true;
1290}
1291
1292
1293bool CIccMpeXmlInvEmissionMatrix::ParseXml(xmlNode *pNode, std::string &parseStr)
1294{
1295 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1296 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1297
1298 if (!nInputChannels || !nOutputChannels) {
1299 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1300 return false;
1301 }
1302
1303 xmlNode *pData;
1304
1305 pData = icXmlFindNode(pNode->children, "Wavelengths");
1306 if (pData) {
1307 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
1308 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
1309 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
1310
1311 if (!nSteps) {
1312 parseStr += "Invalid Spectral Range\n";
1313 return false;
1314 }
1315 m_Range.start = icFtoF16(dStart);
1316 m_Range.end = icFtoF16(dEnd);
1317 m_Range.steps = nSteps;
1318 }
1319
1320 SetSize(nInputChannels, nOutputChannels, m_Range);
1321 if (!m_pWhite || !m_pMatrix || !m_pOffset) {
1322 parseStr += "Unable to SetSize\n";
1323 return false;
1324 }
1325
1326 pData = icXmlFindNode(pNode->children, "WhiteData");
1327 if (pData) {
1328
1329 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
1330 return false;
1331 }
1332 else {
1333 parseStr += "Missing White Data";
1334 }
1335
1336 pData = icXmlFindNode(pNode->children, "MatrixData");
1337 if (pData) {
1338
1339 if (!CIccFloatArray::ParseArray(m_pMatrix, numVectors()*(int)m_Range.steps, pData->children))
1340 return false;
1341 }
1342 else {
1343 parseStr += "Missing Matrix Data";
1344 }
1345
1346 pData = icXmlFindNode(pNode->children, "OffsetData");
1347 if (pData) {
1348 if (!CIccFloatArray::ParseArray(m_pOffset, m_Range.steps, pData->children))
1349 return false;
1350 }
1351 else {
1352 memset(m_pOffset, 0, (int)m_Range.steps*sizeof(icFloatNumber));
1353 }
1354 return true;
1355}
1356
1357bool CIccMpeXmlTintArray::ToXml(std::string &xml, std::string blanks/* = ""*/)
1358{
1359 char buf[128], line[128];
1360 sprintf(buf, "<TintArrayElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1361 xml += blanks + buf;
1362
1363 if (m_nReserved) {
1364 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
1365 xml += buf;
1366 }
1367 xml += ">\n";
1368
1369 IIccExtensionTag *pTagEx;
1370 if (m_Array && (pTagEx=m_Array->GetExtension()) && !strcmp(pTagEx->GetExtClassName(), "CIccTagXml")) {
1371 CIccTagXml *pTagXml = (CIccTagXml*)pTagEx;
1372 const icChar* tagSig = icGetTagSigTypeName(m_Array->GetType());
1373
1374 sprintf(line, " <%s>\n", tagSig); //parent node is the tag type
1375 xml += line;
1376
1377 //convert the rest of the tag to xml
1378 if (!pTagXml->ToXml(xml, " ")) {
1379 printf("Unable to output tag with type %s\n", icGetSigStr(buf, m_Array->GetType()));
1380 return false;
1381 }
1382 sprintf(line, " </%s>\n", tagSig);
1383 xml += line;
1384 }
1385
1386 xml += blanks + "</TintArrayElement>\n";
1387
1388 return true;
1389}
1390
1391
1392bool CIccMpeXmlTintArray::ParseXml(xmlNode *pNode, std::string &parseStr)
1393{
1394 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1395 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1396 if (!nInputChannels || !nOutputChannels) {
1397 parseStr += "Invalid InputChannels or OutputChannels In MatrixElement\n";
1398 return false;
1399 }
1400 m_nInputChannels = nInputChannels;
1401 m_nOutputChannels = nOutputChannels;
1402
1403 for (pNode = pNode->children; pNode && pNode->type != XML_ELEMENT_NODE; pNode = pNode->next);
1404 if (pNode) {
1405 CIccTag *pTag = NULL__null;
1406 icSignature sigTag = (icSignature)0;
1407
1408 // get the tag signature
1409 std::string nodeName = (icChar*) pNode->name;
1410 icTagTypeSignature sigType = icGetTypeNameTagSig (nodeName.c_str());
1411
1412 if (sigType==icSigUnknownType((icTagTypeSignature) 0x3f3f3f3f)){
1413 xmlAttr *attr = icXmlFindAttr(pNode, "type");
1414 sigType = (icTagTypeSignature)icGetSigVal((icChar*) icXmlAttrValue(attr));
1415 }
1416
1417 CIccInfo info;
1418
1419 // create a tag based on the signature
1420 pTag = CIccTag::Create(sigType);
1421
1422 if (!pTag && !pTag->IsNumArrayType()) {
1423 parseStr+= "Invalid data type for Tint Array!\n";
1424 delete pTag;
1425 return false;
1426 }
1427
1428 IIccExtensionTag *pExt;
1429
1430 if (pTag && (pExt = pTag->GetExtension()) && !strcmp(pExt->GetExtClassName(), "CIccTagXml")) {
1431 CIccTagXml* pXmlTag = (CIccTagXml*)pExt;
1432 xmlAttr *attr;
1433
1434 if (pXmlTag->ParseXml(pNode->children, parseStr)) {
1435 if ((attr=icXmlFindAttr(pNode, "reserved"))) {
1436 sscanf(icXmlAttrValue(attr), "%u", &pTag->m_nReserved);
1437 }
1438 m_Array = (CIccTagNumArray*)pTag;
1439 }
1440 else {
1441 parseStr += "Unable to Parse \"";
1442 parseStr += info.GetTagTypeSigName(sigType);
1443 parseStr += "\" (";
1444 parseStr += nodeName;
1445 parseStr += ") Tint Tag\n";
1446 delete pTag;
1447 return false;
1448 }
1449 }
1450 else {
1451 parseStr += "Invalid tag extension for \"";
1452 parseStr += info.GetTagTypeSigName(sigType);
1453 parseStr += "\" (";
1454 parseStr += nodeName;
1455 parseStr += ") Tint Tag\n";
1456 if (pTag)
1457 delete pTag;
1458 return false;
1459 }
1460 }
1461 else {
1462 parseStr += "Tint Array missing tint values\n";
1463 return false;
1464 }
1465 return true;
1466}
1467
1468
1469extern CIccCLUT *icCLutFromXml(xmlNode *pNode, int nIn, int nOut, icConvertType nType, std::string &parseStr);
1470
1471bool CIccMpeXmlCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
1472{
1473 char attrs[256];
1474
1475 if (m_nReserved) {
1476 sprintf(attrs, " InputChannels=\"%d\" OutputChannels=\"%d\" Reserved=\"%u\"", NumInputChannels(), NumOutputChannels(), m_nReserved);
1477 }
1478 else {
1479 sprintf(attrs, " InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1480 }
1481
1482 return icCLUTToXml(xml, m_pCLUT, icConvertFloat, blanks, true, attrs, "CLutElement");
1483}
1484
1485bool CIccMpeXmlCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
1486{
1487 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1488 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1489
1490 if (!m_nInputChannels || !m_nOutputChannels) {
1491 parseStr += "Invalid InputChannels or OutputChannels In CLutElement\n";
1492 return false;
1493 }
1494
1495 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_nOutputChannels, icConvertFloat, parseStr);
1496 if (pCLut) {
1497 SetCLUT(pCLut);
1498 if (m_pCLUT)
1499 return true;
1500 }
1501
1502 return false;
1503}
1504
1505bool CIccMpeXmlExtCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
1506{
1507 char attrs[256];
1508 std::string reserved;
1509
1510 if (m_nReserved) {
1511 sprintf(attrs, " Reserved=\"%u\"", m_nReserved);
1512 reserved = attrs;
1513 }
1514
1515 if (m_nReserved2) {
1516 sprintf(attrs, " Reserved2=\"%u\"", m_nReserved2);
1517 reserved += attrs;
1518 }
1519
1520 sprintf(attrs, " InputChannels=\"%d\" OutputChannels=\"%d\"%s StorageType=\"%d\"", NumInputChannels(), NumOutputChannels(), reserved.c_str(), m_storageType);
1521
1522 return icCLUTToXml(xml, m_pCLUT, icConvertFloat, blanks, true, attrs, "ExtCLutElement");
1523}
1524
1525bool CIccMpeXmlExtCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
1526{
1527 m_storageType = (icUInt16Number)atoi(icXmlAttrValue(pNode, "StorageType", "0"));
1528 m_nReserved2 = atoi(icXmlAttrValue(pNode, "Reserved2", "0"));
1529
1530 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1531 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1532
1533 if (!m_nInputChannels || !m_nOutputChannels) {
1534 parseStr += "Invalid InputChannels or OutputChannels In ExtCLutElement\n";
1535 return false;
1536 }
1537
1538 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_nOutputChannels, icConvertFloat, parseStr);
1539 if (pCLut) {
1540 SetCLUT(pCLut);
1541 if (m_pCLUT)
1542 return true;
1543 }
1544
1545 return false;
1546}
1547
1548bool CIccMpeXmlBAcs::ToXml(std::string &xml, std::string blanks/* = ""*/)
1549{
1550 char line[256];
1551 char buf[256], fix[256];
1552
1553 sprintf(line, "<BAcsElement InputChannels=\"%d\" OutputChannels=\"%d\" Signature=\"%s\"", NumInputChannels(), NumOutputChannels(),
1554 icFixXml(fix, icGetSigStr(buf, m_signature)));
1555 xml += blanks + line;
1556
1557 if (m_nReserved) {
1558 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1559 xml += line;
1560 }
1561
1562 if (m_pData && m_nDataSize) {
1563 icUInt8Number *m_ptr = m_pData;
1564
1565 xml += ">\n";
1566
1567 icXmlDumpHexData(xml, blanks+" ", m_pData, m_nDataSize);
1568
1569 xml += blanks + "</BAcsElement>\n";
1570 }
1571 else {
1572 xml += "/>\n";
1573 }
1574
1575 return true;
1576}
1577
1578
1579bool CIccMpeXmlBAcs::ParseXml(xmlNode *pNode, std::string &parseStr)
1580{
1581 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1582 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1583
1584 if (!m_nInputChannels || !m_nOutputChannels) {
1585 parseStr += "Invalid InputChannels or OutputChannels In BAcsElement\n";
1586 return false;
1587 }
1588
1589 m_signature = icXmlStrToSig(icXmlAttrValue(pNode, "Signature"));
1590
1591 if (pNode->children && pNode->children->type == XML_TEXT_NODE && pNode->children->content) {
1592 icUInt32Number nSize = icXmlGetHexDataSize((const char*)pNode->children->content);
1593
1594 if (nSize) {
1595 if (!AllocData(nSize))
1596 return false;
1597 icXmlGetHexData(m_pData, (const char *)pNode->children->content, nSize);
1598 }
1599 }
1600 return true;
1601}
1602
1603
1604bool CIccMpeXmlEAcs::ToXml(std::string &xml, std::string blanks/* = ""*/)
1605{
1606 char line[256];
1607 char buf[256], fix[256];
1608
1609 sprintf(line, "<EAcsElement InputChannels=\"%d\" OutputChannels=\"%d\" Signature=\"%s\"", NumInputChannels(), NumOutputChannels(),
1610 icFixXml(fix, icGetSigStr(buf, m_signature)));
1611 xml += blanks + line;
1612
1613 if (m_nReserved) {
1614 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1615 xml += line;
1616 }
1617
1618 if (m_pData && m_nDataSize) {
1619 icUInt8Number *m_ptr = m_pData;
1620
1621 xml += ">\n";
1622 icXmlDumpHexData(xml, blanks+" ", m_pData, m_nDataSize);
1623 xml += blanks + "</EAcsElement>\n";
1624 }
1625 else {
1626 xml += "/>\n";
1627 }
1628
1629 return true;
1630}
1631
1632
1633bool CIccMpeXmlEAcs::ParseXml(xmlNode *pNode, std::string &parseStr)
1634{
1635 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1636 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1637
1638 if (!m_nInputChannels || !m_nOutputChannels) {
1639 parseStr += "Invalid InputChannels or OutputChannels In EAcsElement\n";
1640 return false;
1641 }
1642
1643 m_signature = icXmlStrToSig(icXmlAttrValue(pNode, "Signature"));
1644
1645 if (pNode->children && pNode->children->type == XML_TEXT_NODE && pNode->children->content) {
1646 icUInt32Number nSize = icXmlGetHexDataSize((const char*)pNode->children->content);
1647
1648 if (nSize) {
1649 if (!AllocData(nSize))
1650 return false;
1651 icXmlGetHexData(m_pData, (const char *)pNode->children->content, nSize);
1652 }
1653 }
1654 return true;
1655}
1656
1657static bool icXmlDumpColorAppearanceParams(std::string &xml, std::string blanks, CIccCamConverter *pCam)
1658{
1659 char line[256];
1660 icFloatNumber xyz[3];
1661
1662 xml += blanks + "<ColorAppearanceParams>\n";
1663
1664 pCam->GetParameter_WhitePoint(&xyz[0]);
1665 sprintf(line, " <XYZNumber X=\"%.8f\" Y=\"%.8f\" Z=\"%.8f\"/>", xyz[0], xyz[1], xyz[2]);
1666
1667 xml += blanks + " <WhitePoint>\n";
1668 xml += blanks + line;
1669 xml += blanks + " </WhitePoint>\n";
1670
1671 sprintf(line, " <Luminance>%f</Luminance>\n", pCam->GetParameter_La());
1672 xml += blanks + line;
1673
1674 sprintf(line, " <BackgroundLuminance>%.8f</BackgroundLuminance>\n", pCam->GetParameter_Yb());
1675 xml += blanks + line;
1676
1677 sprintf(line, " <ImpactSurround>%f</ImpactSurround>\n", pCam->GetParameter_C());
1678 xml += blanks + line;
1679
1680 sprintf(line, " <ChromaticInductionFactor>%f</ChromaticInductionFactor>\n", pCam->GetParameter_Nc());
1681 xml += blanks + line;
1682
1683 sprintf(line, " <AdaptationFactor>%f</AdaptationFactor>\n", pCam->GetParameter_F());
1684 xml += blanks + line;
1685
1686 xml += "</ColorAppearanceParams>\n";
1687
1688 return true;
1689}
1690
1691static bool icXmlParseColorAppearanceParams(xmlNode *pNode, std::string &parseStr, CIccCamConverter *pCam)
1692{
1693 xmlNode *pChild = icXmlFindNode(pNode, "WhitePoint");
1694 if (!pChild) {
1695 parseStr += "Unable to find CAM Whitepoint\n";
1696 return false;
1697 }
1698
1699 xmlNode *xyzNode = icXmlFindNode(pChild->children, "XYZNumber");
1700
1701 if (!xyzNode) {
1702 parseStr += "Unable to find valid CAM WhitePoint XYZ\n";
1703 return false;
1704 }
1705
1706 xmlAttr *x = icXmlFindAttr(xyzNode, "X");
1707 xmlAttr *y = icXmlFindAttr(xyzNode, "Y");
1708 xmlAttr *z = icXmlFindAttr(xyzNode, "Z");
1709
1710 icFloatNumber xyz[3];
1711 if (x && y && z) {
1712 xyz[0] = (icFloatNumber)atof(icXmlAttrValue(x));
1713 xyz[1] = (icFloatNumber)atof(icXmlAttrValue(y));
1714 xyz[2] = (icFloatNumber)atof(icXmlAttrValue(z));
1715 }
1716 else {
1717 parseStr += "Invalid CAM WhitePoint XYZNumber\n";
1718 return false;
1719 }
1720 pCam->SetParameter_WhitePoint(&xyz[0]);
1721
1722 pChild = icXmlFindNode(pNode, "Luminance");
1723 if (!pChild || !pChild->children || !pChild->children->content) {
1724 parseStr += "Invalid CAM Luminance\n";
1725 return false;
1726 }
1727 pCam->SetParameter_La((icFloatNumber)atof((const char*)pChild->children->content));
1728
1729 pChild = icXmlFindNode(pNode, "BackgroundLuminance");
1730 if (!pChild || !pChild->children || !pChild->children->content) {
1731 parseStr += "Invalid CAM Luminance\n";
1732 return false;
1733 }
1734 pCam->SetParameter_Yb((icFloatNumber)atof((const char*)pChild->children->content));
1735
1736 pChild = icXmlFindNode(pNode, "ImpactSurround");
1737 if (!pChild || !pChild->children || !pChild->children->content) {
1738 parseStr += "Invalid CAM ImpactSurround\n";
1739 return false;
1740 }
1741 pCam->SetParameter_C((icFloatNumber)atof((const char*)pChild->children->content));
1742
1743 pChild = icXmlFindNode(pNode, "ChromaticInductionFactor");
1744 if (!pChild || !pChild->children || !pChild->children->content) {
1745 parseStr += "Invalid CAM ChromaticInductionFactor\n";
1746 return false;
1747 }
1748 pCam->SetParameter_Nc((icFloatNumber)atof((const char*)pChild->children->content));
1749
1750 pChild = icXmlFindNode(pNode, "AdaptationFactor");
1751 if (!pChild || !pChild->children || !pChild->children->content) {
1752 parseStr += "Invalid CAM AdaptationFactor\n";
1753 return false;
1754 }
1755 pCam->SetParameter_F((icFloatNumber)atof((const char*)pChild->children->content));
1756
1757 return true;
1758}
1759
1760bool CIccMpeXmlJabToXYZ::ToXml(std::string &xml, std::string blanks/* = ""*/)
1761{
1762 char line[256];
1763
1764 sprintf(line, "<JabToXYZElement InputChannels=\"%d\" OutputChannels=\"%d\"" , NumInputChannels(), NumOutputChannels());
1765 xml += blanks + line;
1766
1767 if (m_nReserved) {
1768 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1769 xml += line;
1770 }
1771 xml += ">\n";
1772
1773 if (m_pCAM) {
1774 icXmlDumpColorAppearanceParams(xml, blanks+" ", m_pCAM);
1775 xml += blanks + "</JabToXYZElement>\n";
1776 }
1777
1778 return true;
1779}
1780
1781
1782bool CIccMpeXmlJabToXYZ::ParseXml(xmlNode *pNode, std::string &parseStr)
1783{
1784 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1785 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1786
1787 if (m_nInputChannels!=3 || m_nOutputChannels!=3) {
1788 parseStr += "Invalid InputChannels or OutputChannels In JabToXYZElement\n";
1789 return false;
1790 }
1791 xmlNode *pChild = icXmlFindNode(pNode->children, "ColorAppearanceParams");
1792
1793 if (pChild) {
1794 CIccCamConverter *pCAM = new CIccCamConverter();
1795
1796 if (!icXmlParseColorAppearanceParams(pChild->children, parseStr, pCAM)) {
1797 delete pCAM;
1798 return false;
1799 }
1800
1801 SetCAM(pCAM);
1802 }
1803 else {
1804 parseStr += "Unable to find ColorAppearanceParams\n";
1805 return false;
1806 }
1807
1808 return true;
1809}
1810
1811bool CIccMpeXmlXYZToJab::ToXml(std::string &xml, std::string blanks/* = ""*/)
1812{
1813 char line[256];
1814
1815 sprintf(line, "<XYZToJabElement InputChannels=\"%d\" OutputChannels=\"%d\"" , NumInputChannels(), NumOutputChannels());
1816 xml += blanks + line;
1817
1818 if (m_nReserved) {
1819 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1820 xml += line;
1821 }
1822 xml += ">\n";
1823
1824 if (m_pCAM) {
1825 icXmlDumpColorAppearanceParams(xml, blanks+" ", m_pCAM);
1826 xml += blanks + "</XYZToJabElement>\n";
1827 }
1828
1829 return true;
1830}
1831
1832
1833bool CIccMpeXmlXYZToJab::ParseXml(xmlNode *pNode, std::string &parseStr)
1834{
1835 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
1836 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
1837
1838 if (m_nInputChannels!=3 || m_nOutputChannels!=3) {
1839 parseStr += "Invalid InputChannels or OutputChannels In XYZToJabElement\n";
1840 return false;
1841 }
1842 xmlNode *pChild = icXmlFindNode(pNode->children, "ColorAppearanceParams");
1843
1844 if (pChild) {
1845 CIccCamConverter *pCAM = new CIccCamConverter();
1846
1847 if (!icXmlParseColorAppearanceParams(pChild->children, parseStr, pCAM)) {
1848 delete pCAM;
1849 return false;
1850 }
1851
1852 SetCAM(pCAM);
1853 }
1854 else {
1855 parseStr += "Unable to find ColorAppearanceParams\n";
1856 return false;
1857 }
1858
1859 return true;
1860}
1861
1862
1863bool CIccMpeXmlCalculator::ToXml(std::string &xml, std::string blanks/* = ""*/)
1864{
1865 char line[256];
1866 std::string blanks2 = blanks + " ";
1867
1868 sprintf(line, "<CalculatorElement InputChannels=\"%d\" OutputChannels=\"%d\"", NumInputChannels(), NumOutputChannels());
1869 xml += blanks + line;
1870
1871 if (m_nReserved) {
1872 sprintf(line, " Reserved=\"%u\"", m_nReserved);
1873 xml += line;
1874 }
1875 xml += ">\n";
1876
1877 int i;
1878
1879 if (m_SubElem && m_nSubElem) {
1880 xml += blanks2 + "<SubElements>\n";
1881 for (i=0; i<(int)m_nSubElem; i++) {
1882 if (m_SubElem[i]) {
1883 IIccExtensionMpe *pExt = m_SubElem[i]->GetExtension();
1884 if (pExt && !strcmp(pExt->GetExtClassName(), "CIccMpeXml")) {
1885 CIccMpeXml *pMpe = (CIccMpeXml*)pExt;
1886 pMpe->ToXml(xml, blanks2+" ");
1887 }
1888 else {
1889 return false;
1890 }
1891 }
1892 else {
1893 return false;
1894 }
1895 }
1896 xml += blanks2 + "</SubElements>\n";
1897 }
1898
1899 if (m_calcFunc) {
1900 std::string desc;
1901
1902 xml += blanks2 + "<MainFunction>\n";
1903
1904 m_calcFunc->Describe(desc, (int)blanks2.size()+2);
1905 xml += desc;
1906
1907 xml+= blanks2 + "</MainFunction>\n";
1908 }
1909
1910 xml += blanks + "</CalculatorElement>\n";
1911 return true;
1912}
1913
1914bool CIccMpeXmlCalculator::validNameChar(char c, bool bFirst)
1915{
1916 if (bFirst && !((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_')))
1917 return false;
1918 else if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '_')))
1919 return false;
1920
1921 return true;
1922}
1923
1924bool CIccMpeXmlCalculator::validName(const char *szName)
1925{
1926 const char *ptr;
1927 if (!szName || !*szName) {
1928 return false;
1929 }
1930
1931 for (ptr = szName; *ptr; ptr++) {
1932 if (!validNameChar(*ptr, ptr == szName))
1933 return false;
1934 }
1935
1936 return true;
1937}
1938
1939bool CIccMpeXmlCalculator::ParseImport(xmlNode *pNode, std::string importPath, std::string &parseStr)
1940{
1941 xmlNode *pChild, *pNext;
1942 xmlAttr *attr;
1943
1944 pChild = icXmlFindNode(pNode->children, "Imports");
1945 if (pChild) {
1946 for (pNext = pChild->children; pNext; pNext = pNext->next) {
1947 if (pNext->type == XML_ELEMENT_NODE) {
1948 if (!strcmp((icChar*)pNext->name, "Import")) {
1949 if ((attr = icXmlFindAttr(pNext, "Filename"))) {
1950 std::string file = icXmlAttrValue(attr);
1951 xmlDoc *doc = NULL__null;
1952 xmlNode *root_element = NULL__null;
1953
1954 std::string look = "*";
1955 look += file;
1956 look += "*";
1957
1958 if (strstr(importPath.c_str(), look.c_str())) {
1959 //Already imported this file
1960 continue;
1961 }
1962
1963 /*parse the file and get the DOM */
1964 doc = xmlReadFile(file.c_str(), NULL__null, 0);
1965
1966 if (doc == NULL__null) {
1967 parseStr += "Unable to import '";
1968 parseStr += file;
1969 parseStr += '\n';
1970 return false;
1971 }
1972
1973 /*Get the root element node */
1974 root_element = xmlDocGetRootElement(doc);
1975 if (strcmp((icChar*)root_element->name, "IccCalcImport")) {
1976 parseStr += "Invalid calc element import file '" + file + "'\n";
1977 return false;
1978 }
1979
1980 bool rv = ParseImport(root_element, importPath+file+"*", parseStr);
1981
1982 xmlFreeDoc(doc);
1983 }
1984 else {
1985 parseStr += "Missing import file specifier\n";
1986 return false;
1987 }
1988 }
1989 else {
1990 parseStr += "Invalid import specifier\n";
1991 return false;
1992 }
1993 }
1994 }
1995 }
1996
1997 pChild = icXmlFindNode(pNode->children, "Variables");
1998 if (pChild) {
1999 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2000 if (pNext->type == XML_ELEMENT_NODE) {
2001 if (!strcmp((icChar*)pNext->name, "Declare")) {
2002 if ((attr = icXmlFindAttr(pNext, "Name"))) {
2003 std::string name = icXmlAttrValue(attr);
2004 if (!validName(name.c_str())) {
2005 parseStr += "Invalid calc element variable name '" + name + "'\n'";
2006 return false;
2007 }
2008
2009 TempDeclVarMap::iterator v = m_declVarMap.find(name);
2010 if (v != m_declVarMap.end()) {
2011 parseStr += "Calc element variable '" + name + "' was previously declared\n";
2012 return false;
2013 }
2014 int offset = -1;
2015 icUInt16Number size = 1;
2016
2017 if ((attr = icXmlFindAttr(pNext, "Position"))) {
2018 offset = atoi(icXmlAttrValue(attr));
2019 if (offset && importPath != "*") {
2020 parseStr += "Position cannot be specified for imported variables";
2021 return false;
2022 }
2023 }
2024 if ((attr = icXmlFindAttr(pNext, "Size"))) {
2025 size = (icUInt16Number)atoi(icXmlAttrValue(attr));
2026 }
2027 if (size < 1) size = 1;
2028
2029 CIccTempDeclVar var = CIccTempDeclVar(name, offset, size);
2030 if (pNext->children && pNext->children->content) {
2031 CIccFuncTokenizer parse((icChar*)pNext->children->content);
2032 offset = 0;
2033
2034 while (parse.GetNext()) {
2035 icUInt16Number extra = 0;
2036 std::string member = parse.GetName();
2037 if (!validName(member.c_str())) {
2038 parseStr += "Invalid member name '" + member + "' for calc element variable '" + name + "'\n";
2039 return false;
2040 }
2041 size = 0; extra = 0;
2042 parse.GetIndex(size, extra, 1, 0);
2043 size++;
2044 if (size < 1)
2045 size = 1;
2046
2047 var.m_members.push_back(CIccTempVar(member, offset, size));
2048 offset += size;
2049 }
2050 if (var.m_size < offset)
2051 var.m_size = offset;
2052 }
2053 m_declVarMap[name] = var;
2054 }
2055 else {
2056 parseStr += "Missing calc element variable name definition\n";
2057 return false;
2058 }
2059 }
2060 else {
2061 parseStr += "Invalid calc element variable declaration\n";
2062 return false;
2063 }
2064 }
2065 }
2066 }
2067
2068 pChild = icXmlFindNode(pNode->children, "Macros");
2069 if (pChild) {
2070 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2071 if (pNext->type == XML_ELEMENT_NODE) {
2072 if (!strcmp((icChar*)pNext->name, "Macro")) {
2073 if ((attr = icXmlFindAttr(pNext, "Name"))) {
2074 std::string name = icXmlAttrValue(attr);
2075 if (!validName(name.c_str())) {
2076 parseStr += "Invalid Macro name '" + name + "'\n'";
2077 return false;
2078 }
2079 if (!pNext->children || !pNext->children->content || !pNext->children->content[0]) {
2080 parseStr += "Missing content for macro '" + name + "'\n'";
2081 return false;
2082 }
2083 MacroMap::iterator m = m_macroMap.find(name);
2084 if (m != m_macroMap.end()) {
2085 if (!strcmp(m->second.c_str(), (icChar*)pNext->children->content))
2086 continue;
2087 parseStr += "Calc Element macro '" + name + "' was previously defined differently\n";
2088 return false;
2089 }
2090 m_macroMap[name] = (icChar*)(pNext->children->content);
2091
2092 if ((attr = icXmlFindAttr(pNext, "Local"))) {
2093 icUInt16Number offset, size;
2094 CIccTempDeclVar var = CIccTempDeclVar(name, 0, 0);
2095 std::string locals = icXmlAttrValue(attr);
2096 CIccFuncTokenizer parse(locals.c_str());
2097 offset = 0;
2098
2099 while (parse.GetNext()) {
2100 icUInt16Number extra = 0;
2101 std::string member = parse.GetName();
2102 if (!validName(member.c_str())) {
2103 parseStr += "Invalid local name '" + member + "' for calc element macro '" + name + "'\n";
2104 return false;
2105 }
2106 size = 0; extra = 0;
2107 parse.GetIndex(size, extra, 1, 0);
2108 size++;
2109 if (size < 1)
2110 size = 1;
2111
2112 var.m_members.push_back(CIccTempVar(member, offset, size));
2113 offset += size;
2114 }
2115 if (var.m_size < offset)
2116 var.m_size = offset;
2117
2118 m_macroLocalMap[name] = var;
2119 }
2120 }
2121 else {
2122 parseStr += "Missing macro name\n";
2123 return false;
2124 }
2125 }
2126 else {
2127 parseStr += "Invalid macro declaration\n";
2128 return false;
2129 }
2130 }
2131 }
2132 }
2133
2134 pChild = icXmlFindNode(pNode->children, "SubElements");
2135 if (pChild) {
2136 for (pNext = pChild->children; pNext; pNext = pNext->next) {
2137 if (pNext->type == XML_ELEMENT_NODE) {
2138 std::string name;
2139
2140 if ((attr = icXmlFindAttr(pNext, "Name"))) {
2141 name = icXmlAttrValue(attr);
2142 if (!validName(name.c_str())) {
2143 parseStr += "Invalid SubElement name '" + name + "'\n'";
2144 return false;
2145 }
2146 }
2147 if (name.empty()) {
2148 if (importPath != "*") {
2149 parseStr += "Imported Calc SubElments must be named.";
2150 return false;
2151 }
2152 }
2153 else {
2154 MpePtrMap::iterator se = m_mpeMap.find(name);
2155 if (se != m_mpeMap.end()) {
2156 parseStr += "Duplicate declaration of SubElement '" + name + "'\n";
2157 return false;
2158 }
2159 }
2160
2161 CIccMultiProcessElement *pMpe = CIccTagXmlMultiProcessElement::CreateElement((const icChar*)pNext->name);
2162
2163 if (!pMpe) {
2164 parseStr += std::string("Unknown Sub-Element Type (") + (const icChar*)pNext->name + ")\n";
2165 return false;
2166 }
2167
2168 if (!strcmp(pMpe->GetClassName(), "CIccMpeXmlCalculator")) {
2169 CIccMpeXmlCalculator *pSubCalc = (CIccMpeXmlCalculator*)pMpe;
2170 pSubCalc->m_sImport = importPath;
2171 }
2172
2173 xmlAttr *attr;
2174 IIccExtensionMpe *pExt = pMpe->GetExtension();
2175
2176 if (pExt) {
2177 if (!strcmp(pExt->GetExtClassName(), "CIccMpeXml")) {
2178 CIccMpeXml* pXmlMpe = (CIccMpeXml*)pExt;
2179
2180 if (pXmlMpe->ParseXml(pNext, parseStr)) {
2181 if ((attr = icXmlFindAttr(pNode, "Reserved"))) {
2182 sscanf(icXmlAttrValue(attr), "%u", &pMpe->m_nReserved);
2183 }
2184
2185 if (name.empty()) {
2186 m_mpeList.push_back(CIccMpePtr(pMpe, m_nNextMpe));
2187 m_nNextMpe++;
2188 }
2189 else {
2190 m_mpeMap[name] = CIccMpePtr(pMpe);
2191 }
2192 }
2193 else {
2194 char str[100];
2195 sprintf(str, " starting on line %d", pNext->line);
2196 parseStr += std::string("Unable to parse element of type ") + pMpe->GetClassName() + str + "\n";
2197 delete pMpe;
2198 return false;
2199 }
2200 }
2201 else {
2202 parseStr += std::string("Element ") + pMpe->GetClassName() + "isn't of type CIccMpeXml\n";
2203 delete pMpe;
2204 return false;
2205 }
2206 }
2207 else {
2208 parseStr += std::string("Element ") + pMpe->GetClassName() + "isn't of type CIccMpeXml\n";
2209 delete pMpe;
2210 return false;
2211 }
2212 }
2213 }
2214 }
2215 return true;
2216}
2217
2218bool CIccMpeXmlCalculator::ValidMacroCalls(const char *szMacroText, std::string macroStack, std::string &parseStr) const
2219{
2220 const char *ptr;
2221 for (ptr = strstr(szMacroText, "call{"); ptr; ptr = strstr(ptr, "call{")) {
2222 CIccFuncTokenizer parse(ptr, true);
2223 parse.GetNext();
2224
2225 std::string name = parse.GetReference();
2226 MacroMap::const_iterator m = m_macroMap.find(name);
2227 if (m == m_macroMap.end()) {
2228 parseStr += "Call to undefined macro '" + name + "'\n";
2229 return false;
2230 }
2231 std::string sm = "*";
2232 sm += name + "*";
2233 if (strstr(macroStack.c_str(), sm.c_str())) {
2234 parseStr += "Macro recursion detected in call to '" + name + "'\n";
2235 return false;
2236 }
2237 if (!ValidMacroCalls(m->second.c_str(), macroStack + name + "*", parseStr)) {
2238 return false;
2239 }
2240 ptr++;
2241 }
2242 return true;
2243}
2244
2245bool CIccMpeXmlCalculator::ValidateMacroCalls(std::string &parseStr) const
2246{
2247 MacroMap::const_iterator m;
2248
2249 for (m = m_macroMap.begin(); m != m_macroMap.end(); m++) {
2250 if (!ValidMacroCalls(m->second.c_str(), "*", parseStr)) {
2251 return false;
2252 }
2253 }
2254 return true;
2255}
2256
2257bool CIccMpeXmlCalculator::Flatten(std::string &flatStr, std::string macroName, const char *szFunc, std::string &parseStr, icUInt32Number nLocalsOffset)
2258{
2259 CIccFuncTokenizer parse(szFunc, true);
2260
2261 while (parse.GetNext()) {
2262 std::string token = parse.GetLast();
2263 const char *tok = token.c_str();
2264 if (!strncmp(tok, "call{", 5) ||
2265 tok[0] == '#') {
2266 std::string nameiter;
2267 std::string name;
2268
2269 if (tok[0] == '#')
2270 nameiter = token.substr(1);
2271 else
2272 nameiter = parse.GetReference();
2273
2274 const char *ptr;
2275 for (ptr = nameiter.c_str(); *ptr && *ptr != '[' && *ptr != '('; ptr++) name += *ptr;
2276 int iter = 1;
2277// if (*ptr) {
2278// iter = atoi(ptr + 1);
2279// if (iter < 1)
2280// iter = 1;
2281// else if (iter>1024)
2282// iter = 1024;
2283// }
2284
2285 MacroMap::iterator m = m_macroMap.find(name.c_str());
2286 if (m != m_macroMap.end()) {
2287 icUInt16Number nLocalsSize = 0;
2288 TempDeclVarMap::iterator locals = m_macroLocalMap.find(macroName);
2289 if (locals != m_macroLocalMap.end()) {
2290 nLocalsSize = locals->second.m_size;
2291 }
2292
2293 int i;
2294 for (i = 0; i < iter; i++) {
2295 Flatten(flatStr, name, m->second.c_str(), parseStr, nLocalsOffset+nLocalsSize);
2296 }
2297 }
2298 else {
2299 parseStr += "Call to undefined macro '" + name + "'\n";
2300 return false;
2301 }
2302 }
2303 else if (!strncmp(tok, "in{", 3) ||
2304 !strncmp(tok, "out{", 4)) {
2305 std::string op = parse.GetName();
2306 std::string ref = parse.GetReference();
2307 std::string refroot;
2308 for (const char *ptr = ref.c_str(); *ptr && *ptr != ',' && *ptr != '(' && *ptr != '['; ptr++) refroot += *ptr;
2309
2310 ChanVarMap *pMap;
2311 int nChan;
2312 if (op == "in") {
2313 pMap = &m_inputMap;
2314 nChan = m_nInputChannels;
2315 }
2316 else {
2317 pMap = &m_outputMap;
2318 nChan = m_nOutputChannels;
2319 }
2320
2321 ChanVarMap::iterator ci = pMap->find(refroot);
2322 if (ci == pMap->end()) {
2323 parseStr += "Invalid '" + op + "' operation channel reference '" + refroot + "'\n";
2324 return false;
2325 }
2326 if (refroot != ref) {
2327 std::string select = ref.substr(refroot.size());
2328 int offset = 0;
2329 int size = 1;
2330
2331 if (select[0] == '[' || select[1] == '(') {
2332 const char *ptr;
2333 offset = atoi(select.c_str() + 1);
2334 for (ptr = select.c_str() + 1; *ptr && *ptr != ')' && *ptr != ']'; ptr++);
2335 select = ptr + 1;
2336 }
2337
2338 if (select[0]==',')
2339 size = atoi(select.c_str() + 1);
2340
2341 if (size < 0 || offset<0 || ci->second.first + offset + size > m_nInputChannels) {
2342 parseStr += "Invalid '" + op + "' operation channel offset or size '" + refroot + "'\n";
2343 return false;
2344 }
2345 char index[80];
2346 sprintf(index, "(%d,%d)", ci->second.first+offset, size);
2347 flatStr += op + index + " ";
2348 }
2349 else if (ci->second.second>1) {
2350 char index[80];
2351 sprintf(index, "(%d,%d)", ci->second.first, ci->second.second);
2352 flatStr += op + index + " ";
2353 }
2354 else {
2355 char index[80];
2356 sprintf(index, "(%d)", ci->second.first);
2357 flatStr += op + index + " ";
2358 }
2359 }
2360 else if (!strncmp(tok, "tget{", 5) ||
2361 !strncmp(tok, "tput{", 5) ||
2362 !strncmp(tok, "tsav{", 5)) {
2363 std::string op = parse.GetName();
2364 std::string ref = parse.GetReference();
2365 std::string refroot;
2366 for (const char *ptr = ref.c_str(); *ptr && *ptr != '[' && *ptr != '('; ptr++) refroot += *ptr;
2367
2368 if (macroName.size() && refroot.size() && refroot[0] == '@') {
2369 std::string localName = refroot.substr(1);
2370 TempDeclVarMap::iterator locals = m_macroLocalMap.find(macroName);
2371 if (locals == m_macroLocalMap.end()) {
2372 parseStr += "Reference to undeclared local variable '" + localName + "' in macro '" + macroName + "'\n";
2373 return false;
2374 }
2375
2376 unsigned long nLocalOffset = 0;
2377 unsigned long nLocalSize = 0;
2378 TempVarList::iterator m = locals->second.m_members.begin();
2379 for (; m != locals->second.m_members.end(); m++) {
2380 if (localName == m->m_name) {
2381 nLocalOffset = m->m_pos;
2382 nLocalSize = m->m_size;
2383 break;
2384 }
2385 }
2386 if (m == locals->second.m_members.end()) {
2387 parseStr += "Reference to undeclared local variable '" + localName + "' in macro '" + macroName + "'\n";
2388 return false;
2389 }
2390 int voffset, vsize;
2391
2392 if (ref != refroot) {
2393 CIccFuncTokenizer p2(ref.c_str());
2394 p2.GetNext();
2395 icUInt16Number _voffset = 0, _vsize = 1;
2396 p2.GetIndex(_voffset, _vsize, 0, 1);
2397 voffset = _voffset;
2398 vsize = _vsize + 1;
2399 }
2400 else {
2401 voffset = 0;
2402 vsize = (int)nLocalSize;
2403 }
2404
2405 if (voffset + vsize > (int)nLocalSize) {
2406 parseStr += "Out of bounds indexing of local '" + refroot + "' in macro '" + macroName + "'\n";
2407 return false;
2408 }
2409
2410 if (nLocalsOffset + nLocalOffset + voffset + vsize > 65536) {
2411 parseStr += "Temporary variable addressing out of bounds\n";
2412 return false;
2413 }
2414 char idx[80];
2415 if (vsize == 1) {
2416 sprintf(idx, "[%lu]", nLocalsOffset + nLocalOffset + voffset);
2417 }
2418 else {
2419 sprintf(idx, "[%lu,%d]", nLocalsOffset + nLocalOffset + voffset, vsize);
2420 }
2421 flatStr += "l";
2422 flatStr += op.substr(1);
2423 flatStr += idx;
2424 flatStr += " ";
2425 }
2426 else {
2427 TempVarMap::iterator var = m_varMap.find(refroot);
2428 if (var == m_varMap.end()) {
2429 std::string root;
2430 for (const char *ptr = refroot.c_str(); *ptr && *ptr != '.'; ptr++) root += *ptr;
2431
2432 TempVarMap::iterator rootVar = m_varMap.find(root);
2433 if (refroot != root && rootVar == m_varMap.end()) {
2434 parseStr += "Reference to undeclared variable '" + ref + "'\n";
2435 return false;
2436 }
2437
2438 TempDeclVarMap::iterator decl = m_declVarMap.find(root);
2439 if (decl == m_declVarMap.end()) {
2440 parseStr += "Reference to undeclared variable '" + ref + "'\n";
2441 return false;
2442 }
2443
2444 if (decl->second.m_pos < 0) {
2445 m_varMap[root] = CIccTempVar(root, m_nNextVar, decl->second.m_size);
2446 decl->second.m_pos = m_nNextVar;
2447
2448 if (strchr(refroot.c_str(), '.')) {
2449 TempVarList::iterator m = decl->second.m_members.begin();
2450 for (; m != decl->second.m_members.end(); m++) {
2451 std::string vm = root + "." + m->m_name;
2452 m_varMap[vm] = CIccTempVar(vm, m_nNextVar + m->m_pos, m->m_size);
2453 }
2454 }
2455
2456 if (m_nNextVar + decl->second.m_size > 65536) {
2457 parseStr += "Temporary variable addressing out of bounds\n";
2458 return false;
2459 }
2460 m_nNextVar += decl->second.m_size;
2461 }
2462 else {
2463 m_varMap[root] = CIccTempVar(root, decl->second.m_pos, decl->second.m_size);
2464
2465 if (strchr(refroot.c_str(), '.')) {
2466 TempVarList::iterator m = decl->second.m_members.begin();
2467 for (; m != decl->second.m_members.end(); m++) {
2468 std::string vm = root + "." + m->m_name;
2469 m_varMap[vm] = CIccTempVar(vm, decl->second.m_pos + m->m_pos, m->m_size);
2470 }
2471 }
2472 if (decl->second.m_pos + decl->second.m_size > 65536) {
2473 parseStr += "Temporary variable addressing out of bounds\n";
2474 return false;
2475 }
2476 }
2477
2478 var = m_varMap.find(refroot);
2479 if (var == m_varMap.end()) {
2480 parseStr += "Reference to undeclared variable '" + refroot + "'\n";
2481 return false;
2482 }
2483 }
2484 int voffset, vsize;
2485
2486 if (ref != refroot) {
2487 CIccFuncTokenizer p2(ref.c_str());
2488 p2.GetNext();
2489 icUInt16Number _voffset = 0, _vsize = 1;
2490 p2.GetIndex(_voffset, _vsize, 0, 1);
2491 voffset = _voffset;
2492 vsize = _vsize + 1;
2493 }
2494 else {
2495 voffset = 0;
2496 vsize = var->second.m_size;
2497 }
2498
2499 if (voffset + vsize > var->second.m_size) {
2500 parseStr += "Out of bounds indexing of '" + refroot + "'\n";
2501 return false;
2502 }
2503 if (var->second.m_pos + voffset + vsize > 65536) {
2504 parseStr += "Temporary variable addressing out of bounds\n";
2505 return false;
2506 }
2507 char idx[80];
2508 if (vsize == 1) {
2509 sprintf(idx, "[%d]", var->second.m_pos + voffset);
2510 }
2511 else {
2512 sprintf(idx, "[%d,%d]", var->second.m_pos + voffset, vsize);
2513 }
2514 flatStr += op + idx + " ";
2515 }
2516 }
2517 else if (!strncmp(tok, "elem{", 5) ||
2518 !strncmp(tok, "curv{", 5) ||
2519 !strncmp(tok, "clut{", 5) ||
2520 !strncmp(tok, "mtx{", 4) ||
2521 !strncmp(tok, "fJab{", 5) ||
2522 !strncmp(tok, "tJab{", 5) ||
2523 !strncmp(tok, "calc{", 5) ||
2524 !strncmp(tok, "tint{", 5)) {
2525 std::string op = parse.GetName();
2526 std::string ref = parse.GetReference();
2527 MpePtrMap::iterator e = m_mpeMap.find(ref);
2528 if (e == m_mpeMap.end()) {
2529 parseStr += "Unknown sub element reference to " + token + "\n";
2530 return false;
2531 }
2532 if (e->second.m_nIndex<0) {
2533 if (e->second.m_ptr) {
2534 m_mpeList.push_back(CIccMpePtr(e->second.m_ptr, m_nNextMpe));
2535 e->second.m_ptr = NULL__null;
2536 e->second.m_nIndex = m_nNextMpe;
2537 m_nNextMpe++;
2538 }
2539 else {
2540 parseStr += "Invalid sub-element reference: " + token + "\n";
2541 return false;
2542 }
2543 }
2544 char idx[80];
2545 sprintf(idx, "(%d)", e->second.m_nIndex);
2546 flatStr += op + idx + " ";
2547 }
2548 else {
2549 flatStr += tok;
2550 flatStr += " ";
2551 }
2552 }
2553
2554 return true;
2555}
2556
2557bool CIccMpeXmlCalculator::UpdateLocals(std::string &func, std::string sFunc, std::string &parseStr, int nLocalsOffset)
2558{
2559 func.clear();
2560 CIccFuncTokenizer parse(sFunc.c_str(), true);
2561
2562 while (parse.GetNext()) {
2563 std::string token = parse.GetLast();
2564 const char *tok = token.c_str();
2565
2566 if (!strncmp(tok, "lget[", 5) ||
2567 !strncmp(tok, "lput[", 5) ||
2568 !strncmp(tok, "lsav[", 5)) {
2569 std::string op = parse.GetName();
2570 int voffset, vsize;
2571
2572 CIccFuncTokenizer p2(tok+4);
2573 icUInt16Number _voffset = 0, _vsize = 1;
2574 p2.GetIndex(_voffset, _vsize, 0, 1);
2575 voffset = _voffset + nLocalsOffset;
2576 vsize = _vsize + 1;
2577
2578 if (voffset + vsize > 65535) {
2579 parseStr += "Local variable out of bounds - too many variables.\n";
2580 return false;
2581 }
2582
2583 char idx[80];
2584 if (vsize == 1) {
2585 sprintf(idx, "[%d]", voffset);
2586 }
2587 else {
2588 sprintf(idx, "[%d,%d]", voffset, vsize);
2589 }
2590 func +="t";
2591 func += op.substr(1);
2592 func += idx;
2593 func += " ";
2594 }
2595 else {
2596 func += tok;
2597 func += " ";
2598 }
2599 }
2600
2601 return true;
2602}
2603void CIccMpeXmlCalculator::clean()
2604{
2605 m_sImport = "*";
2606 m_declVarMap.clear();
2607 m_varMap.clear();
2608 m_macroMap.clear();
2609
2610 MpePtrList::iterator ml;
2611 for (ml = m_mpeList.begin(); ml != m_mpeList.end(); ml++) {
2612 if (ml->m_ptr)
2613 delete ml->m_ptr;
2614 }
2615 m_mpeList.clear();
2616
2617 MpePtrMap::iterator mm;
2618 for (mm = m_mpeMap.begin(); mm != m_mpeMap.end(); mm++) {
2619 if (mm->second.m_ptr)
2620 delete mm->second.m_ptr;
2621 }
2622 m_mpeMap.clear();
2623 m_nNextVar = 0;
2624 m_nNextMpe = 0;
2625}
2626
2627bool CIccMpeXmlCalculator::ParseChanMap(ChanVarMap& chanMap, const char *szNames, int nChannels)
2628{
2629 chanMap.clear();
2630
2631 if (!szNames)
2632 return false;
2633
2634 int i;
2635 const char *ptr;
2636 std::string name;
2637 IndexSizePair isp;
2638 int size = 1;
2639
2640 for (i = 0, ptr = szNames; *ptr && i < nChannels; ptr++) {
2641 bool bFirst = name.empty();
2642 if (*ptr == ' ') {
2643 if (!bFirst) {
2644 isp.first = i;
2645 isp.second = size;
2646 chanMap[name] = isp;
2647 name.clear();
2648 i += size;
2649 size = 1;
2650 }
2651 }
2652 else if (*ptr == '[' || *ptr == '(') {
2653 size = atoi(ptr + 1);
2654 if (size<0 || i + size>nChannels)
2655 return 0;
2656
2657 for (; *ptr && *ptr != ']' && *ptr != ')'; ptr++);
2658 if (!*ptr)
2659 ptr--;
2660 }
2661 else if (validNameChar(*ptr, bFirst)) {
2662 name += *ptr;
2663 }
2664 else {
2665 return false;
2666 }
2667 }
2668
2669 if (!name.empty() && i < nChannels) {
2670 isp.first = i;
2671 isp.second = size;
2672 chanMap[name] = isp;
2673 }
2674
2675 return true;
2676}
2677
2678bool CIccMpeXmlCalculator::ParseXml(xmlNode *pNode, std::string &parseStr)
2679{
2680 xmlNode *pChild;
2681
2682 SetSize(atoi(icXmlAttrValue(pNode, "InputChannels")),
2683 atoi(icXmlAttrValue(pNode, "OutputChannels")));
2684
2685 clean();
2686
2687 if (!ParseChanMap(m_inputMap, icXmlAttrValue(pNode, "InputNames"), m_nInputChannels)) {
2688 parseStr += "Invalid name for InputChannels";
2689 return false;
2690 }
2691
2692 if (!ParseChanMap(m_outputMap, icXmlAttrValue(pNode, "OutputNames"), m_nOutputChannels)) {
2693 parseStr += "Invalid name for InputChannels";
2694 return false;
2695 }
2696
2697 if (!ParseImport(pNode, "*", parseStr))
2698 return false;
2699
2700 if (!ValidateMacroCalls(parseStr)) {
2701 return false;
2702 }
2703
2704 pChild = icXmlFindNode(pNode->children, "MainFunction");
2705 if (pChild && pNode->children && pChild->children->content) {
2706 char *content = (char*)pChild->children->content;
2707 std::string flatFunc;
2708
2709 //Move new variables to after allocated variables
2710 TempDeclVarMap::iterator declVar;
2711 for (declVar = m_declVarMap.begin(); declVar != m_declVarMap.end(); declVar++) {
2712 if (declVar->second.m_pos >= 0) {
2713 int next = declVar->second.m_pos + declVar->second.m_size;
2714 if (next > m_nNextVar)
2715 m_nNextVar = next;
2716 }
2717 }
2718
2719 if (!Flatten(flatFunc, "", content, parseStr, 0)) {
2720 return false;
2721 }
2722
2723 if (m_macroLocalMap.size()) {
2724 std::string localFunc;
2725 if (!UpdateLocals(localFunc, flatFunc, parseStr, m_nNextVar)) {
2726 return false;
2727 }
2728 flatFunc = localFunc;
2729 }
2730 //copy MPE subelmeents used by Main Function to returned object
2731 int n;
2732 MpePtrList::iterator m;
2733 for (m = m_mpeList.begin(), n = 0; m != m_mpeList.end(); m++, n++) {
2734 this->SetSubElem(n, m->m_ptr);
2735 m->m_ptr = NULL__null;
2736 }
2737
2738#if 0
2739 FILE *ff = fopen("flatfunc.txt", "wb");
2740 fwrite(flatFunc.c_str(), flatFunc.size(), 1, ff);
2741 fclose(ff);
2742#endif
2743
2744 icFuncParseStatus stat = SetCalcFunc(flatFunc.c_str(), parseStr);
2745 if (stat!=icFuncParseNoError) {
2746 char buf[65];
2747 int len = icIntMin(64, (int)strlen(flatFunc.c_str()));
2748 strncpy(buf, flatFunc.c_str(), len);
2749 buf[len]=0;
2750
2751 switch(stat) {
2752 case icFuncParseSyntaxError:
2753 parseStr += "Syntax Error occurred while parsing Main Calculator Function from \"";
2754 break;
2755 case icFuncParseInvalidOperation:
2756 parseStr += "Invalid Operation found while parsing Main Calculator Function from \"";
2757 break;
2758 case icFuncParseStackUnderflow:
2759 parseStr += "Stack underflow detected while parsing Main Calculator Function from \"";
2760 break;
2761 case icFuncParseInvalidChannel:
2762 parseStr += "Invalid Channel detected while parsing Main Calculator Function from \"";
2763 break;
2764 default:
2765 parseStr += "Unable to parse Main Calculator Function from \"";
2766 }
2767 parseStr += buf;
2768 parseStr += "\"\r\n";
2769 return false;
2770 }
2771 }
2772 clean();
2773
2774 return true;
2775}
2776
2777
2778bool CIccMpeXmlEmissionCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
2779{
2780 char buf[256];
2781 std::string reserved;
2782
2783 xml += blanks + "<EmissionCLutElement";
2784
2785 if (m_nReserved) {
2786 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
2787 xml += buf;
2788 }
2789
2790 sprintf(buf, " InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\" StorageType=\"%d\">\n", NumInputChannels(), NumOutputChannels(), m_flags, m_nStorageType);
2791 xml += buf;
2792
2793 sprintf(buf, " <Wavelengths start=\"%.8f\" end=\"%.8f\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
2794 xml += blanks + buf;
2795
2796 int i;
2797
2798 if (m_pWhite) {
2799 xml += blanks + " <WhiteData>\n";
2800
2801 xml += blanks + " ";
2802 for (i=0; i<(int)m_Range.steps; i++) {
2803 sprintf(buf, " %.8f", m_pWhite[i]);
2804 xml += buf;
2805 }
2806 xml += "\n";
2807
2808 xml += blanks + " </WhiteData>\n";
2809 }
2810
2811 if (!icCLUTDataToXml(xml, m_pCLUT, icConvertFloat, blanks, true))
2812 return false;
2813
2814 xml += blanks + "</EmissionCLutElement>\n";
2815
2816 return true;
2817}
2818
2819bool CIccMpeXmlEmissionCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
2820{
2821 m_nStorageType = (icUInt16Number)atoi(icXmlAttrValue(pNode, "StorageType", "0"));
2822
2823 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
2824 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
2825 m_flags = atoi(icXmlAttrValue(pNode, "Flags", 0));
2826
2827 if (!m_nInputChannels || !m_nOutputChannels) {
2828 parseStr += "Invalid InputChannels or OutputChannels In CLutElement\n";
2829 return false;
2830 }
2831
2832 xmlNode *pData;
2833
2834 pData = icXmlFindNode(pNode->children, "Wavelengths");
2835 if (pData) {
2836 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
2837 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
2838 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
2839
2840 if (dStart >= dEnd ||!nSteps) {
2841 parseStr += "Invalid Spectral Range\n";
2842 return false;
2843 }
2844 m_Range.start = icFtoF16(dStart);
2845 m_Range.end = icFtoF16(dEnd);
2846 m_Range.steps = nSteps;
2847 }
2848 else {
2849 parseStr += "Missing Spectral Range\n";
2850 return false;
2851 }
2852
2853 if (m_pWhite)
2854 free(m_pWhite);
2855
2856 m_pWhite = (icFloatNumber *)malloc(m_Range.steps*sizeof(icFloatNumber));
2857 if (!m_pWhite) {
2858 parseStr += "White buffer memory error\n";
2859 return false;
2860 }
2861
2862 pData = icXmlFindNode(pNode->children, "WhiteData");
2863 if (pData) {
2864
2865 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
2866 return false;
2867 }
2868 else {
2869 parseStr += "Missing White Data";
2870 }
2871
2872 if (m_pCLUT) {
2873 delete m_pCLUT;
2874 m_pCLUT = NULL__null;
2875 }
2876
2877 if (m_pApplyCLUT) {
2878 delete m_pApplyCLUT;
2879 m_pApplyCLUT = NULL__null;
2880 }
2881
2882 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_Range.steps, icConvertFloat, parseStr);
2883 if (pCLut) {
2884 m_pCLUT = pCLut;
2885 return true;
2886 }
2887
2888 return false;
2889}
2890
2891bool CIccMpeXmlReflectanceCLUT::ToXml(std::string &xml, std::string blanks/* = ""*/)
2892{
2893 char buf[256];
2894 std::string reserved;
2895
2896 xml += blanks + "<ReflectanceCLutElem";
2897
2898 if (m_nReserved) {
2899 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
2900 xml += buf;
2901 }
2902
2903 sprintf(buf, " InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\">\n", NumInputChannels(), NumOutputChannels(), m_flags);
2904 xml += buf;
2905
2906 sprintf(buf, " <Wavelengths start=\"%.8f\" end=\"%.8f\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
2907 xml += buf;
2908
2909 int i;
2910
2911 if (m_pWhite) {
2912 xml += blanks + " <WhiteData>\n";
2913
2914 xml += blanks + " ";
2915 for (i=0; i<(int)m_Range.steps; i++) {
2916 sprintf(buf, " %.8f", m_pWhite[i]);
2917 xml += buf;
2918 }
2919 xml += "\n";
2920
2921 xml += blanks + " </WhiteData>\n";
2922 }
2923
2924 if (!icCLUTDataToXml(xml, m_pCLUT, icConvertFloat, blanks, true))
2925 return false;
2926
2927 xml += blanks + "</ReflectanceCLutElem>\n";
2928
2929 return true;
2930}
2931
2932bool CIccMpeXmlReflectanceCLUT::ParseXml(xmlNode *pNode, std::string &parseStr)
2933{
2934 m_nStorageType = (icUInt16Number)atoi(icXmlAttrValue(pNode, "StorageType", "0"));
2935
2936 m_nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
2937 m_nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
2938 m_flags = atoi(icXmlAttrValue(pNode, "Flags", 0));
2939
2940 if (!m_nInputChannels || !m_nOutputChannels) {
2941 parseStr += "Invalid InputChannels or OutputChannels In CLutElement\n";
2942 return false;
2943 }
2944
2945 xmlNode *pData;
2946
2947 pData = icXmlFindNode(pNode->children, "Wavelengths");
2948 if (pData) {
2949 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
2950 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
2951 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
2952
2953 if (dStart >= dEnd ||!nSteps) {
2954 parseStr += "Invalid Spectral Range\n";
2955 return false;
2956 }
2957 m_Range.start = icFtoF16(dStart);
2958 m_Range.end = icFtoF16(dEnd);
2959 m_Range.steps = nSteps;
2960 }
2961 else {
2962 parseStr += "Missing Spectral Range\n";
2963 return false;
2964 }
2965
2966 if (m_pWhite)
2967 free(m_pWhite);
2968
2969 m_pWhite = (icFloatNumber *)malloc(m_Range.steps*sizeof(icFloatNumber));
2970 if (!m_pWhite) {
2971 parseStr += "White buffer memory error\n";
2972 return false;
2973 }
2974
2975 pData = icXmlFindNode(pNode->children, "WhiteData");
2976 if (pData) {
2977
2978 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
2979 return false;
2980 }
2981 else {
2982 parseStr += "Missing WhiteData";
2983 }
2984
2985 if (m_pCLUT) {
2986 delete m_pCLUT;
2987 m_pCLUT = NULL__null;
2988 }
2989
2990 if (m_pApplyCLUT) {
2991 delete m_pApplyCLUT;
2992 m_pApplyCLUT = NULL__null;
2993 }
2994
2995 CIccCLUT *pCLut = icCLutFromXml(pNode, m_nInputChannels, m_Range.steps, icConvertFloat, parseStr);
2996 if (pCLut) {
2997 m_pCLUT = pCLut;
2998 return true;
2999 }
3000
3001 return false;
3002}
3003
3004bool CIccMpeXmlEmissionObserver::ParseXml(xmlNode *pNode, std::string &parseStr)
3005{
3006 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
3007 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
3008 m_flags = atoi(icXmlAttrValue(pNode, "Flags"));
3009
3010 if (!nInputChannels || !nOutputChannels) {
3011 parseStr += "Invalid InputChannels or OutputChannels In EmissionObserverElement\n";
3012 return false;
3013 }
3014
3015 xmlNode *pData;
3016
3017 pData = icXmlFindNode(pNode->children, "Wavelengths");
3018 if (pData) {
3019 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
3020 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
3021 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
3022
3023 if (dStart >= dEnd || nSteps != nInputChannels) {
3024 parseStr += "Invalid Spectral Range\n";
3025 return false;
3026 }
3027 m_Range.start = icFtoF16(dStart);
3028 m_Range.end = icFtoF16(dEnd);
3029 m_Range.steps = nSteps;
3030 }
3031
3032 SetSize(nInputChannels, nOutputChannels, m_Range);
3033 if (!m_pWhite) {
3034 parseStr += "Unable to SetSize\n";
3035 return false;
3036 }
3037
3038 pData = icXmlFindNode(pNode->children, "WhiteData");
3039 if (pData) {
3040
3041 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
3042 return false;
3043 }
3044 else {
3045 parseStr += "Missing White Data";
3046 }
3047
3048 return true;
3049}
3050
3051bool CIccMpeXmlEmissionObserver::ToXml(std::string &xml, std::string blanks/* = ""*/)
3052{
3053 char buf[128];
3054 sprintf(buf, "<EmissionObserverElement InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\"", NumInputChannels(), NumOutputChannels(), m_flags);
3055 xml += blanks + buf;
3056
3057 if (m_nReserved) {
3058 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
3059 xml += buf;
3060 }
3061 xml += ">\n";
3062
3063 sprintf(buf, " <Wavelengths start=\"%.8f\" end=\"%.8f\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
3064 xml += buf;
3065
3066 int i;
3067
3068 if (m_pWhite) {
3069 xml += blanks + " <WhiteData>\n";
3070
3071 xml += blanks + " ";
3072 for (i=0; i<(int)m_Range.steps; i++) {
3073 sprintf(buf, " %.8f", m_pWhite[i]);
3074 xml += buf;
3075 }
3076 xml += "\n";
3077
3078 xml += blanks + " </WhiteData>\n";
3079 }
3080
3081 xml += blanks + "</EmissionObserverElement>\n";
3082
3083 return true;
3084}
3085
3086bool CIccMpeXmlReflectanceObserver::ParseXml(xmlNode *pNode, std::string &parseStr)
3087{
3088 icUInt16Number nInputChannels = atoi(icXmlAttrValue(pNode, "InputChannels"));
3089 icUInt16Number nOutputChannels = atoi(icXmlAttrValue(pNode, "OutputChannels"));
3090 m_flags = atoi(icXmlAttrValue(pNode, "Flags"));
3091
3092 if (!nInputChannels || !nOutputChannels) {
3093 parseStr += "Invalid InputChannels or OutputChannels In ReflectanceObserverElement\n";
3094 return false;
3095 }
3096
3097 xmlNode *pData;
3098
3099 pData = icXmlFindNode(pNode->children, "Wavelengths");
3100 if (pData) {
3101 icFloatNumber dStart = (icFloatNumber)atof(icXmlAttrValue(pData, "start"));
3102 icFloatNumber dEnd = (icFloatNumber)atof(icXmlAttrValue(pData, "end"));
3103 icUInt16Number nSteps = atoi(icXmlAttrValue(pData, "steps"));
3104
3105 if (dStart >= dEnd || nSteps != nInputChannels) {
3106 parseStr += "Invalid Spectral Range\n";
3107 return false;
3108 }
3109 m_Range.start = icFtoF16(dStart);
3110 m_Range.end = icFtoF16(dEnd);
3111 m_Range.steps = nSteps;
3112 }
3113
3114 SetSize(nInputChannels, nOutputChannels, m_Range);
3115 if (!m_pWhite) {
3116 parseStr += "Unable to SetSize\n";
3117 return false;
3118 }
3119
3120 pData = icXmlFindNode(pNode->children, "WhiteData");
3121 if (pData) {
3122
3123 if (!CIccFloatArray::ParseArray(m_pWhite, m_Range.steps, pData->children))
3124 return false;
3125 }
3126 else {
3127 parseStr += "Missing White Data";
3128 }
3129
3130 return true;
3131}
3132
3133bool CIccMpeXmlReflectanceObserver::ToXml(std::string &xml, std::string blanks/* = ""*/)
3134{
3135 char buf[128];
3136 sprintf(buf, "<ReflectanceObserverElement InputChannels=\"%d\" OutputChannels=\"%d\" Flags=\"%d\"", NumInputChannels(), NumOutputChannels(), m_flags);
3137 xml += blanks + buf;
3138
3139 if (m_nReserved) {
3140 sprintf(buf, " Reserved=\"%u\"", m_nReserved);
3141 xml += buf;
3142 }
3143 xml += ">\n";
3144
3145 sprintf(buf, " <Wavelengths start=\"%.8f\" end=\"%.8f\" steps=\"%d\"/>\n", icF16toF(m_Range.start), icF16toF(m_Range.end), m_Range.steps);
3146 xml += buf;
3147
3148 int i;
3149
3150 if (m_pWhite) {
3151 xml += blanks + " <WhiteData>\n";
3152
3153 xml += blanks + " ";
3154 for (i=0; i<(int)m_Range.steps; i++) {
3155 sprintf(buf, " %.8f", m_pWhite[i]);
3156 xml += buf;
3157 }
3158 xml += "\n";
3159
3160 xml += blanks + " </WhiteData>\n";
3161 }
3162
3163 xml += blanks + "</ReflectanceObserverElement>\n";
3164
3165 return true;
3166}
3167
3168#ifdef USEREFICCMAXNAMESPACE
3169}
3170#endif