1 /** @file
2     File:       IccUtilXml.cpp
3 
4     Contains:   Implementation of XML conversion utilities
5 
6     Version:    V1
7 
8     Copyright:  � see ICC Software License
9 */
10 
11 /*
12  * The ICC Software License, Version 0.2
13  *
14  *
15  * Copyright (c) 2003-2010 The International Color Consortium. All rights
16  * reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  *
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  *
25  * 2. Redistributions in binary form must reproduce the above copyright
26  *    notice, this list of conditions and the following disclaimer in
27  *    the documentation and/or other materials provided with the
28  *    distribution.
29  *
30  * 3. In the absence of prior written permission, the names "ICC" and "The
31  *    International Color Consortium" must not be used to imply that the
32  *    ICC organization endorses or promotes products derived from this
33  *    software.
34  *
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40  * ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the The International Color Consortium.
52  *
53  *
54  * Membership in the ICC is encouraged when this software is used for
55  * commercial purposes.
56  *
57  *
58  * For more information on The International Color Consortium, please
59  * see <http://www.color.org/>.
60  *
61  *
62  */
63 
64 #include "IccUtilXml.h"
65 #include "IccConvertUTF.h"
66 #include <time.h>
67 
68 #if defined(WIN32) || defined(WIN64)
69 #include <windows.h>
70 #ifdef GetClassName
71 #undef GetClassName
72 #endif
73 #endif
74 #include <cstring> /* C strings strcpy, memcpy ... */
75 
76 const icTagSigType tagSignatureMap[] ={
77 	{ icSigChromaticityType			  , "chromaticityType"},
78 	{ icSigColorantOrderType		  , "colorantOrderType"},
79 	{ icSigColorantTableType          , "colorantTableType"},
80 	{ icSigCurveType                  , "curveType"},
81 	{ icSigDataType                   , "dataType"},
82 	{ icSigDateTimeType               , "dateTimeType"},
83   { icSigDictType                   , "dictType"},
84 	{ icSigLut16Type                  , "lut16Type"},
85 	{ icSigLut8Type                   , "lut8Type"},
86 	{ icSigLutAtoBType                , "lutAtoBType"},
87 	{ icSigLutBtoAType                , "lutBtoAType"},
88 	{ icSigMeasurementType            , "measurementType"},
89 	{ icSigMultiLocalizedUnicodeType  , "multiLocalizedUnicodeType"},
90 	{ icSigMultiProcessElementType    , "multiProcessElementType"},
91 	{ icSigNamedColor2Type            , "namedColor2Type"},
92 	{ icSigParametricCurveType        , "parametricCurveType"},
93 	{ icSigProfileSequenceDescType    , "profileSequenceDescType"},
94 	{ icSigProfileSequceIdType        , "profileSequenceIdentifierType"},
95 	{ icSigResponseCurveSet16Type     , "responseCurveSet16Type"},
96 	{ icSigS15Fixed16ArrayType        , "s15Fixed16ArrayType"},
97 	{ icSigSignatureType              , "signatureType"},
98 	{ icSigTextType                   , "textType"},
99 	{ icSigTextDescriptionType        , "textDescriptionType"},
100 	{ icSigU16Fixed16ArrayType        , "uInt16Type"},
101 	{ icSigUInt16ArrayType            , "uInt16Type"},
102 	{ icSigUInt32ArrayType            , "uInt32ArrayType"},
103 	{ icSigUInt64ArrayType            , "uInt64Type"},
104 	{ icSigUInt8ArrayType             , "uInt8Type"},
105 	{ icSigViewingConditionsType      , "viewingConditionsType"},
106 	{ icSigXYZType                    , "XYZType"},
107 	{ icSigXYZArrayType               , "XYZType"},
108 	{ icSigUnknownType				  , "PrivateType"}
109 };
110 #define tagSignatureMapSize (sizeof(tagSignatureMap)/sizeof(tagSignatureMap[0]))
111 
112 
113 
114 
icFixXml(std::string & buf,const char * szStr)115 const char *icFixXml(std::string &buf, const char *szStr)
116 {
117   buf = "";
118   while (*szStr) {
119     switch (*szStr) {
120     case '\'':
121       buf += "&apos;";
122       break;
123     case '&':
124       buf += "&amp;";
125       break;
126     case '\"':
127       buf += "&quot;";
128       break;
129     case '<':
130       buf += "&lt;";
131       break;
132     case '>':
133       buf += "&gt;";
134       break;
135     default:
136       buf += *szStr;
137     }
138     szStr++;
139   }
140 
141   return buf.c_str();
142 }
143 
icFixXml(char * szDest,const char * szStr)144 const char *icFixXml(char *szDest, const char *szStr)
145 {
146   char *ptr = szDest;
147 
148   while (*szStr) {
149     switch (*szStr) {
150     case '\'':
151       strcpy(ptr, "&apos;");
152       ptr += 6;
153       break;
154     case '&':
155       strcpy(ptr, "&amp;");
156       ptr += 5;
157       break;
158     case '\"':
159       strcpy(ptr, "&quot;");
160       ptr += 6;
161       break;
162     case '<':
163       strcpy(ptr, "&lt;");
164       ptr += 4;
165       break;
166     case '>':
167       strcpy(ptr, "&gt;");
168       ptr += 4;
169       break;
170     default:
171       *ptr++ = *szStr;
172     }
173     szStr++;
174   }
175   *ptr = '\0';
176 
177   return szDest;
178 }
179 
icAnsiToUtf8(std::string & buf,const char * szSrc)180 const char *icAnsiToUtf8(std::string &buf, const char *szSrc)
181 {
182 #if defined(WIN32) || defined(WIN64)
183   size_t len = strlen(szSrc)+1;
184   wchar_t *szUnicodeBuf = (wchar_t*)malloc(len*sizeof(icUInt16Number)*2);
185   char *szBuf = (char*)malloc(len*2);
186 
187   size_t n;
188 
189   n=MultiByteToWideChar(CP_ACP, 0, szSrc, (int)len-1, szUnicodeBuf, (int)len*2);
190   szUnicodeBuf[n] = '\0';
191 
192   n = WideCharToMultiByte(CP_UTF8, 0, (const wchar_t*)szUnicodeBuf, (int)n, szBuf, (int)len*2, 0, NULL);
193   szBuf[n] = '\0';
194 
195   buf = szBuf;
196 
197   free(szBuf);
198   free(szUnicodeBuf);
199 #else
200   buf = szSrc;
201 #endif
202   return buf.c_str();
203 }
204 
icUtf8ToAnsi(std::string & buf,const char * szSrc)205 const char *icUtf8ToAnsi(std::string &buf, const char *szSrc)
206 {
207 #if defined(WIN32) || defined(WIN64)
208   size_t len = strlen(szSrc)+1;
209   wchar_t *szUnicodeBuf = (wchar_t*)malloc(len*sizeof(icUInt16Number)*2);
210   char *szBuf = (char*)malloc(len*2);
211 
212   size_t n;
213 
214   n=MultiByteToWideChar(CP_UTF8, 0, szSrc, (int)len-1, szUnicodeBuf, (int)len*2);
215   szUnicodeBuf[n] = '\0';
216 
217   n = WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)szUnicodeBuf, (int)n, szBuf, (int)len*2, "?", NULL);
218   szBuf[n] = '\0';
219 
220   buf = szBuf;
221 
222   free(szBuf);
223   free(szUnicodeBuf);
224 #else
225   buf = szSrc;
226 #endif
227   return buf.c_str();
228 }
229 
230 class CIccDumpXmlCLUT : public IIccCLUTExec
231 {
232 public:
CIccDumpXmlCLUT(std::string * xml,icConvertType nType,std::string blanks,icUInt16Number nSamples,icUInt8Number nPixelsPerRow)233   CIccDumpXmlCLUT(std::string *xml, icConvertType nType, std::string blanks, icUInt16Number nSamples, icUInt8Number nPixelsPerRow)
234   {
235     m_xml = xml;
236     m_nType = nType;
237     m_blanks = blanks;
238     m_nSamples = nSamples;
239     m_nPixelsPerRow = nPixelsPerRow;
240     m_nCurPixel = 0;
241   }
242 
PixelOp(icFloatNumber * pGridAdr,icFloatNumber * pData)243   virtual void PixelOp(icFloatNumber* pGridAdr, icFloatNumber* pData)
244   {
245     int i;
246     char buf[128];
247 
248     if (!(m_nCurPixel % m_nPixelsPerRow))
249       *m_xml += m_blanks;
250 
251     switch(m_nType) {
252       case icConvert8Bit:
253         for (i=0; i<m_nSamples; i++) {
254           sprintf(buf, " %3d", (icUInt8Number)(pData[i]*255.0 + 0.5));
255           *m_xml += buf;
256         }
257         break;
258       case icConvert16Bit:
259         for (i=0; i<m_nSamples; i++) {
260           sprintf(buf, " %5d", (icUInt16Number)(pData[i]*65535.0 + 0.5));
261           *m_xml += buf;
262         }
263         break;
264       case icConvertFloat:
265       default:
266         for (i=0; i<m_nSamples; i++) {
267           sprintf(buf, " %13.8f", pData[i]);
268           *m_xml += buf;
269         }
270         break;
271     }
272     m_nCurPixel++;
273     if (!(m_nCurPixel % m_nPixelsPerRow)) {
274       *m_xml += "\n";
275     }
276   }
277 
Finish()278   void Finish()
279   {
280     if (m_nCurPixel % m_nPixelsPerRow) {
281       *m_xml += "\n";
282     }
283   }
284 
285   std::string *m_xml;
286   icConvertType m_nType;
287   std::string m_blanks;
288   icUInt16Number m_nSamples;
289   icUInt8Number m_nPixelsPerRow;
290   icUInt32Number m_nCurPixel;
291 };
292 
293 
icCLUTToXml(std::string & xml,CIccCLUT * pCLUT,icConvertType nType,std::string blanks,bool bSaveGridPoints,const char * szExtraAttrs,const char * szName)294 bool icCLUTToXml(std::string &xml, CIccCLUT *pCLUT, icConvertType nType, std::string blanks,
295                  bool bSaveGridPoints/*=false*/, const char *szExtraAttrs/*=""*/, const char *szName/*="CLUT"*/)
296 {
297   char buf[128];
298   if (nType == icConvertVariable) {
299     nType = pCLUT->GetPrecision()==1 ? icConvert8Bit : icConvert16Bit;
300   }
301 
302   xml += blanks + "<" + szName;
303 
304   if (!bSaveGridPoints) {
305     sprintf(buf, " GridGranularity=\"%d\"", pCLUT->GridPoint(0));
306     xml += buf;
307   }
308 
309    if (szExtraAttrs && *szExtraAttrs) {
310     xml += szExtraAttrs;
311   }
312   xml += ">\n";
313 
314   if (bSaveGridPoints) {
315     xml += blanks + "  <GridPoints>";
316     int i;
317 
318     for (i=0; i<pCLUT->GetInputDim(); i++) {
319       if (i)
320         sprintf(buf, " %d", pCLUT->GridPoint(i));
321       else
322         sprintf(buf, "%d", pCLUT->GridPoint(i));
323       xml += buf;
324     }
325     xml += "</GridPoints>\n";
326   }
327 
328   int nPixelsPerRow = pCLUT->GridPoint(0);
329 
330   // if the CLUT has no GridPoints, profile is invalid
331   if (nPixelsPerRow == 0) {
332     printf("\nError! - CLUT Table not found.\n");
333 	  return false;
334   }
335 
336   CIccDumpXmlCLUT dumper(&xml, nType, blanks + "   ", pCLUT->GetOutputChannels(), nPixelsPerRow);
337 
338   xml += blanks + "  <TableData>\n";
339   pCLUT->Iterate(&dumper);
340 
341   dumper.Finish();
342 
343   xml += blanks + "  </TableData>\n";
344 
345   xml += blanks + "</" + szName + ">\n";
346   return true;
347 }
348 
icXmlStrToFloat(const xmlChar * szStr)349 icFloatNumber icXmlStrToFloat(const xmlChar *szStr)
350 {
351   float f=0.0;
352   sscanf((const char*)szStr, "%f", &f);
353 
354   return (icFloatNumber)f;
355 }
356 
icXmlStrToSig(const char * szStr)357 icSignature icXmlStrToSig(const char *szStr)
358 {
359   return icGetSigVal(szStr);
360 }
361 
icXmlAttrValue(xmlAttr * attr,const char * szDefault)362 const char *icXmlAttrValue(xmlAttr *attr, const char *szDefault)
363 {
364   if (attr && attr->children && attr->children->type == XML_TEXT_NODE && attr->children->content)
365     return (const char*)attr->children->content;
366 
367   return szDefault;
368 }
369 
icXmlAttrValue(xmlNode * pNode,const char * szName,const char * szDefault)370 const char *icXmlAttrValue(xmlNode *pNode, const char *szName, const char *szDefault)
371 {
372   xmlAttr *attr = icXmlFindAttr(pNode, szName);
373   if (attr) {
374     return icXmlAttrValue(attr, szDefault);
375   }
376   return szDefault;
377 }
378 
icXmlGetChildSigVal(xmlNode * pNode)379 icUInt32Number icXmlGetChildSigVal(xmlNode *pNode)
380 {
381   if (!pNode || !pNode->children || !pNode->children->content)
382     return 0;
383 
384   return icGetSigVal((const char*)pNode->children->content);
385 }
386 
hexValue(char c)387 static int hexValue(char c)
388 {
389   if (c>='0' && c<='9')
390     return c-'0';
391   if (c>='A' && c<='F')
392     return c-'A'+10;
393   if (c>='a' && c<='f')
394     return c-'a'+10;
395   return -1;
396 }
397 
398 
icXmlGetHexData(void * pBuf,const char * szText,icUInt32Number nBufSize)399 icUInt32Number icXmlGetHexData(void *pBuf, const char *szText, icUInt32Number nBufSize)
400 {
401   unsigned char *pDest = (unsigned char*)pBuf;
402   icUInt32Number rv =0;
403 
404   while(*szText && rv<nBufSize) {
405     int c1=hexValue(szText[0]);
406     int c2=hexValue(szText[1]);
407     if (c1>=0 && c2>=0) {
408       *pDest = c1*16+ c2;
409       pDest++;
410       szText +=2;
411       rv++;
412     }
413     else {
414       szText++;
415     }
416   }
417   return rv;
418 }
419 
icXmlGetHexDataSize(const char * szText)420 icUInt32Number icXmlGetHexDataSize(const char *szText)
421 {
422   icUInt32Number rv =0;
423 
424   while(*szText) {
425     int c1=hexValue(szText[0]);
426     int c2=hexValue(szText[1]);
427     if (c1>=0 && c2>=0) {
428       szText +=2;
429       rv++;
430     }
431     else {
432       szText++;
433     }
434   }
435   return rv;
436 }
437 
icXmlDumpHexData(std::string & xml,std::string blanks,void * pBuf,icUInt32Number nBufSize)438 icUInt32Number icXmlDumpHexData(std::string &xml, std::string blanks, void *pBuf, icUInt32Number nBufSize)
439 {
440   icUInt8Number *ptr = (icUInt8Number *)pBuf;
441   char buf[15];
442   icUInt32Number i;
443 
444   for (i=0; i<nBufSize; i++, ptr++) {
445     if (!(i%32)) {
446       if (i)
447         xml += "\n";
448       xml += blanks;
449     }
450     sprintf(buf, "%02x", *ptr);
451     xml += buf;
452   }
453   if (i) {
454     xml += "\n";
455   }
456   return i;
457 }
458 
icXmlFindAttr(xmlNode * pNode,const char * szAttrName)459 xmlAttr *icXmlFindAttr(xmlNode *pNode, const char *szAttrName)
460 {
461   if (!pNode) return NULL;
462 
463   xmlAttr *attr;
464 
465   for (attr = pNode->properties; attr; attr = attr->next) {
466     if (attr->type != XML_ATTRIBUTE_NODE)
467       continue;
468 
469     if (!icXmlStrCmp(attr->name, szAttrName)) {
470       return attr;
471     }
472   }
473 
474   return NULL;
475 }
476 
icXmlFindNode(xmlNode * pNode,const char * szNodeName)477 xmlNode *icXmlFindNode(xmlNode *pNode, const char *szNodeName)
478 {
479   if (!pNode) return NULL;
480 
481   for (; pNode; pNode = pNode->next) {
482     if (pNode->type != XML_ELEMENT_NODE)
483       continue;
484 
485     if (!icXmlStrCmp(pNode->name, szNodeName)) {
486       return pNode;
487     }
488   }
489 
490   return NULL;
491 }
492 
icXmlNodeCount(xmlNode * pNode,const char * szNodeName)493 icUInt32Number icXmlNodeCount(xmlNode *pNode, const char *szNodeName)
494 {
495   icUInt32Number rv = 0;
496   for (; pNode; pNode = pNode->next) {
497     if (pNode->type == XML_ELEMENT_NODE &&
498         !icXmlStrCmp(pNode->name, szNodeName)) {
499       rv++;
500     }
501   }
502   return rv;
503 }
504 
505 template <class T, icTagTypeSignature Tsig>
CIccXmlArrayType()506 CIccXmlArrayType<T, Tsig>::CIccXmlArrayType()
507 {
508   m_pBuf = NULL;
509   m_nSize = 0;
510 }
511 
512 template <class T, icTagTypeSignature Tsig>
~CIccXmlArrayType()513 CIccXmlArrayType<T, Tsig>::~CIccXmlArrayType()
514 {
515   if (m_pBuf) {
516     free(m_pBuf);
517   }
518 }
519 
520 template <class T, icTagTypeSignature Tsig>
ParseArray(xmlNode * pNode)521 bool CIccXmlArrayType<T, Tsig>::ParseArray(xmlNode *pNode)
522 {
523   const char *scanType = (Tsig == icSigFloatArrayType ? "f" : "n");
524   icUInt32Number n = icXmlNodeCount(pNode, scanType);
525 
526   if (n) {
527     if (!SetSize(n))
528       return false;
529     return ParseArray(m_pBuf, m_nSize, pNode);
530   }
531 
532   for ( ;pNode && pNode->type!= XML_TEXT_NODE; pNode=pNode->next);
533 
534   if (!pNode || !pNode->content)
535     return false;
536 
537   n = ParseTextCount((const char*)pNode->content);
538 
539   if (!n || !SetSize(n))
540     return false;
541 
542   return ParseArray(m_pBuf, m_nSize, pNode);
543 }
544 
545 template <class T, icTagTypeSignature Tsig>
ParseTextArray(const char * szText)546 bool CIccXmlArrayType<T, Tsig>::ParseTextArray(const char *szText)
547 {
548   icUInt32Number n = ParseTextCount(szText);
549 
550   if (n) {
551     if (!SetSize(n))
552       return false;
553 
554     return ParseText(m_pBuf, m_nSize, szText)==m_nSize;
555   }
556 
557   return false;
558 }
559 
560 template <class T, icTagTypeSignature Tsig>
ParseTextArrayNum(const char * szText,icUInt32Number num,std::string & parseStr)561 bool CIccXmlArrayType<T, Tsig>::ParseTextArrayNum(const char *szText, icUInt32Number num, std::string &parseStr)
562 {
563   icUInt32Number n = ParseTextCountNum(szText, num, parseStr);
564   if (n) {
565     if (!SetSize(n))
566       return false;
567     return ParseText(m_pBuf, m_nSize, szText)==m_nSize;
568   }
569 
570   return false;
571 }
572 
573 template <class T, icTagTypeSignature Tsig>
DumpArray(std::string & xml,std::string blanks,T * buf,icUInt32Number nBufSize,icConvertType nType,icUInt8Number nColumns)574 bool CIccXmlArrayType<T, Tsig>::DumpArray(std::string &xml, std::string blanks, T *buf, icUInt32Number nBufSize,
575                                           icConvertType nType,  icUInt8Number nColumns)
576 {
577   char str[40];
578 
579   if (!nColumns) nColumns = 1;
580   icUInt32Number i;
581 
582   for (i=0; i<nBufSize; i++) {
583     if (!(i%nColumns)) {
584       xml += blanks;
585     }
586     else {
587       xml += " ";
588     }
589 
590     switch (Tsig) {
591       case icSigUInt8ArrayType:
592         switch (nType) {
593           case icConvert8Bit:
594           default:
595             sprintf(str, "%u", buf[i]);
596             break;
597 
598           case icConvert16Bit:
599             sprintf(str, "%u", (icUInt16Number)((icFloatNumber)buf[i] * 65535.0 / 255.0 + 0.5));
600             break;
601 
602           case icConvertFloat:
603             sprintf(str, "%.8f", (icFloatNumber)buf[i] / 255.0);
604             break;
605         }
606         break;
607 
608       case icSigUInt16ArrayType:
609         switch (nType) {
610           case icConvert8Bit:
611             sprintf(str, "%u", (icUInt16Number)((icFloatNumber)buf[i] * 255.0 / 65535.0 + 0.5));
612             break;
613 
614           case icConvert16Bit:
615           default:
616             sprintf(str, "%u", buf[i]);
617             break;
618 
619           case icConvertFloat:
620             sprintf(str, "%.8f", (icFloatNumber)buf[i] / 65535.0);
621             break;
622         }
623         break;
624 
625       case icSigUInt32ArrayType:
626         sprintf(str, "%u", buf[i]);
627         break;
628 
629       case icSigFloatArrayType:
630         switch (nType) {
631           case icConvert8Bit:
632             sprintf(str, "%u", (icUInt8Number)(buf[i] * 255.0 + 0.5));
633             break;
634 
635           case icConvert16Bit:
636             sprintf(str, "%u", (icUInt16Number)(buf[i] * 65535.0 + 0.5));
637             break;
638 
639           case icConvertFloat:
640           default:
641             sprintf(str, "%.8f", buf[i]);
642         }
643         break;
644     }
645     xml += str;
646     if (i%nColumns == nColumns-1) {
647       xml += "\n";
648     }
649   }
650 
651   if (i%nColumns) {
652     xml += "\n";
653   }
654 
655   return true;
656 }
657 
658 // for multi-platform support
659 // replaced "_inline" with "inline"
icIsNumChar(char c)660 static inline bool icIsNumChar(char c)
661 {
662   if ((c>='0' && c<='9') || c=='.' || c=='+' || c=='-' || c=='e')
663     return true;
664   return false;
665 }
666 
667 // function used when checking contents of a file
668 // count the number of entries.
669 template <class T, icTagTypeSignature Tsig>
ParseTextCountNum(const char * szText,icUInt32Number num,std::string & parseStr)670 icUInt32Number CIccXmlArrayType<T, Tsig>::ParseTextCountNum(const char *szText, icUInt32Number num, std::string &parseStr)
671 {
672   icUInt32Number n = 0;
673   bool bInNum = false;
674   //icUInt32Number count = 1;
675 
676   //while (*szText) {
677   for (icUInt32Number i=0; i<num; i++) {
678 	  if (icIsNumChar(*szText)) {
679 		  if (!bInNum) {
680 			  bInNum = true;
681 		  }
682 	  }
683 	  // an invalid character is encountered (not digit and not space)
684 	  else if (!isspace(*szText) && i <= num ){
685 		  char line[100];
686 		  sprintf(line, "Data '%c' in position %d is not a number. ", *szText, i);
687 		  parseStr += line;
688 		  return false;
689 	  }
690 	  else if (bInNum) { //char is a space
691 		  n++;
692 		  bInNum = false;
693 	  }
694 	  szText++;
695 	  //count++;
696   }
697   if (bInNum) {
698     n++;
699   }
700 
701   return n;
702 }
703 
704 template <class T, icTagTypeSignature Tsig>
ParseTextCount(const char * szText)705 icUInt32Number CIccXmlArrayType<T, Tsig>::ParseTextCount(const char *szText)
706 {
707   icUInt32Number n = 0;
708   bool bInNum = false;
709 
710   while (*szText) {
711     if (icIsNumChar(*szText)) {
712       if (!bInNum) {
713         bInNum = true;
714       }
715     }
716     else if (bInNum) {
717       n++;
718       bInNum = false;
719     }
720     szText++;
721   }
722   if (bInNum) {
723     n++;
724   }
725 
726   return n;
727 }
728 
729 template <class T, icTagTypeSignature Tsig>
ParseText(T * pBuf,icUInt32Number nSize,const char * szText)730 icUInt32Number CIccXmlArrayType<T, Tsig>::ParseText(T* pBuf, icUInt32Number nSize, const char *szText)
731 {
732   icUInt32Number n = 0, b;
733   bool bInNum = false;
734   char num[256];
735 
736   while (*szText && n<nSize) {
737 	if (icIsNumChar(*szText)) {
738       if (!bInNum) {
739         bInNum = true;
740         b=0;
741       }
742       num[b] = *szText;
743 
744       if (b+2<sizeof(num))
745         b++;
746     }
747     else if (bInNum) {
748       num[b] = 0;
749       pBuf[n] = (T)atof(num);
750       n++;
751       bInNum = false;
752     }
753     szText++;
754   }
755   if (bInNum) {
756     num[b] = 0;
757     pBuf[n] = (T)atof(num);
758     n++;
759   }
760 
761   return n;
762 }
763 
764 template <class T, icTagTypeSignature Tsig>
ParseArray(T * pBuf,icUInt32Number nSize,xmlNode * pNode)765 bool CIccXmlArrayType<T, Tsig>::ParseArray(T* pBuf, icUInt32Number nSize, xmlNode *pNode)
766 {
767   icUInt32Number n;
768   if (Tsig==icSigFloatArrayType) {
769     n = icXmlNodeCount(pNode, "f");
770 
771     if (!n) {
772       if (pNode->type!=XML_TEXT_NODE || !pNode->content)
773         return false;
774 
775       n = ParseTextCount((const char*)pNode->content);
776       if (!n || n>nSize)
777         return false;
778 
779       ParseText(pBuf, n, (const char*)pNode->content);
780     }
781     else {
782       if (n>nSize)
783         return false;
784 
785       icUInt32Number i;
786       for (i=0; i<nSize && pNode; pNode = pNode->next) {
787         if (pNode->type == XML_ELEMENT_NODE &&
788           !icXmlStrCmp(pNode->name, "f") &&
789           pNode->children &&
790           pNode->children->content) {
791             float f;
792             sscanf((const char *)(pNode->children->content), "%f", &f);
793             pBuf[i] = (T)f;
794             i++;
795         }
796       }
797     }
798   }
799   else {
800     n = icXmlNodeCount(pNode, "n");
801 
802     if (!n) {
803       if (pNode->type!=XML_TEXT_NODE || !pNode->content)
804         return false;
805 
806       n = ParseTextCount((const char *)pNode->content);
807       if (!n || n>nSize)
808         return false;
809 
810       n = ParseText(pBuf, n, (const char *)pNode->content);
811     }
812     else {
813       if (n>nSize)
814         return false;
815 
816       icUInt32Number i;
817       for (i=0; i<nSize && pNode; pNode = pNode->next) {
818         if (pNode->type == XML_ELEMENT_NODE &&
819           !icXmlStrCmp(pNode->name, "n") &&
820           pNode->children &&
821           pNode->children->content) {
822             pBuf[i] = (T)atol((const char *)(pNode->children->content));
823             i++;
824         }
825       }
826     }
827   }
828   return nSize==n;
829 }
830 
831 
832 template <class T, icTagTypeSignature Tsig>
SetSize(icUInt32Number nSize)833 bool CIccXmlArrayType<T, Tsig>::SetSize(icUInt32Number nSize)
834 {
835   if (m_pBuf) {
836     free(m_pBuf);
837   }
838   m_pBuf = (T*)malloc(nSize * sizeof(T));
839   if (!m_pBuf) {
840     m_nSize = 0;
841     return false;
842   }
843   m_nSize = nSize;
844 
845   return true;
846 }
847 
848 //Make sure typedef classes get built
849 template class CIccXmlArrayType<icUInt8Number, icSigUInt8ArrayType>;
850 template class CIccXmlArrayType<icUInt16Number, icSigUInt16ArrayType>;
851 template class CIccXmlArrayType<icUInt32Number, icSigUInt32ArrayType>;
852 template class CIccXmlArrayType<icFloatNumber, icSigFloatArrayType>;
853 
854 
icGetRenderingIntentValue(icChar * szRenderingIntent)855 const icRenderingIntent icGetRenderingIntentValue (icChar *szRenderingIntent)
856 {
857   if (szRenderingIntent == "Perceptual")
858 	  return icPerceptual;
859   else if (szRenderingIntent == "Media-relative colorimetric")
860 	  return icRelativeColorimetric;
861   else if (szRenderingIntent == "Saturation")
862 	  return icSaturation;
863   else if (szRenderingIntent == "ICC-absolute colorimetric")
864 	  return icAbsoluteColorimetric;
865 
866   return icPerceptual;
867 }
868 
icGetTagSigTypeName(icTagTypeSignature tagSig)869 const icChar* icGetTagSigTypeName(icTagTypeSignature tagSig)
870 {
871   //loop through the list of all tag signatures
872   for (int i=0; i<tagSignatureMapSize; i++) {
873 	if ( tagSignatureMap[i].tagSig == tagSig )
874 		return tagSignatureMap[i].szTagType;
875   }
876 
877   // if  the tag signature is not found, it is a custom type.
878   return "PrivateType";
879 }
880 
icGetTypeNameTagSig(const icChar * szTagType)881 const icTagTypeSignature icGetTypeNameTagSig(const icChar* szTagType)
882 {
883   //loop through the list of all tag signatures
884   for (int i=0; i<tagSignatureMapSize; i++) {
885    if (!strcmp((const char*)tagSignatureMap[i].szTagType, szTagType))
886 	 return tagSignatureMap[i].tagSig;
887   }
888 
889    // if  the tag signature is not found, it is a custom type.
890   return icSigUnknownType;
891 }
892 
icGetNamedStandardObserverValue(const icChar * str)893 icStandardObserver icGetNamedStandardObserverValue(const icChar* str)
894 {
895   if (!strcmp(str, "Unknown observer"))
896 	  return icStdObsUnknown;
897 
898   if (!strcmp(str, "CIE 1931 standard colorimetric observer"))
899 	  return icStdObs1931TwoDegrees;
900 
901   if (!strcmp(str, "CIE 1964 standard colorimetric observer"))
902 	  return icStdObs1964TenDegrees;
903 
904   return icStdObsUnknown;
905 }
906 
907 
icGeNamedtMeasurementGeometryValue(const icChar * str)908 icMeasurementGeometry icGeNamedtMeasurementGeometryValue(const icChar* str)
909 {
910   if (!strcmp(str, "Geometry Unknown"))
911   	return icGeometryUnknown;
912 
913   if (!strcmp(str, "Geometry 0-45 or 45-0"))
914 	  return icGeometry045or450;
915 
916   if (!strcmp(str, "Geometry 0-d or d-0"))
917 	  return icGeometry0dord0;
918 
919   if (!strcmp(str, "Max Geometry"))
920 	  return icMaxEnumGeometry;
921 
922   return icGeometryUnknown;
923 }
924 
icGetNamedMeasurementFlareValue(const icChar * str)925 icMeasurementFlare icGetNamedMeasurementFlareValue(const icChar * str)
926 {
927   if (!strcmp(str, "Flare 0"))
928 	  return icFlare0;
929 
930   if (!strcmp(str, "Flare 100"))
931 	  return icFlare100;
932 
933   if (!strcmp(str, "Max Flare"))
934 	  return icMaxEnumFlare;
935 
936   return icFlare0;
937 }
938 
icGetIlluminantValue(const icChar * str)939 icIlluminant icGetIlluminantValue(const icChar* str)
940 {
941   if (!strcmp(str, "Illuminant Unknown"))
942 	  return icIlluminantUnknown;
943 
944   if (!strcmp(str, "Illuminant D50"))
945 	  return icIlluminantD50;
946 
947   if (!strcmp(str, "Illuminant D65"))
948 	  return icIlluminantD65;
949 
950   if (!strcmp(str, "Illuminant D93"))
951 	  return icIlluminantD93;
952 
953   if (!strcmp(str, "Illuminant F2"))
954 	  return icIlluminantF2;
955 
956   if (!strcmp(str, "Illuminant D55"))
957 	  return icIlluminantD55;
958 
959   if (!strcmp(str, "Illuminant A"))
960 	  return icIlluminantA;
961 
962   if (!strcmp(str, "Illuminant EquiPowerE"))
963 	  return icIlluminantEquiPowerE;
964 
965   if (!strcmp(str, "Illuminant F8"))
966 	  return icIlluminantF8;
967 
968   return icIlluminantUnknown;
969 }
970 
icGetStandardObserverName(icStandardObserver str)971 const icChar* icGetStandardObserverName(icStandardObserver str)
972 {
973   switch (str) {
974   case icStdObsUnknown:
975     return "Unknown Observer";
976 
977   case icStdObs1931TwoDegrees:
978     return "CIE 1931 standard colorimetric observer";
979 
980   case icStdObs1964TenDegrees:
981     return "CIE 1964 standard colorimetric observer";
982 
983   default:
984     return "Unknown Observer";
985   }
986 }
987 
icGetDateTimeValue(const icChar * str)988 icDateTimeNumber icGetDateTimeValue(const icChar* str)
989 {
990 	icDateTimeNumber dateTime;
991 
992 	if (!stricmp(str, "Now")) {
993 	  struct tm *newtime;
994     time_t long_time;
995 
996     time( &long_time );                /* Get time as long integer. */
997     newtime = gmtime( &long_time );
998 
999     dateTime.year = newtime->tm_year+1900;
1000     dateTime.month = newtime->tm_mon+1;
1001     dateTime.day = newtime->tm_mday;
1002     dateTime.hours = newtime->tm_hour;
1003     dateTime.minutes = newtime->tm_min;
1004     dateTime.seconds = newtime->tm_sec;
1005 
1006 	}
1007 	else {
1008 		unsigned int day=0, month=0, year=0, hours=0, minutes=0, seconds=0;
1009 
1010 		sscanf(str, "%d-%02d-%02dT%02d:%02d:%02d", &year, &month, &day, &hours, &minutes, &seconds);
1011 
1012 		dateTime.year = year;
1013 		dateTime.month = month;
1014 		dateTime.day = day;
1015 		dateTime.hours = hours;
1016 		dateTime.minutes = minutes;
1017 		dateTime.seconds = seconds;
1018 	}
1019 
1020 	return dateTime;
1021 }
1022 
icGetChildText(xmlNode * pNode)1023 const icChar *icGetChildText(xmlNode *pNode)
1024 {
1025   if (pNode && pNode->children && pNode->content)
1026     return (const char*)pNode->content;
1027   return "";
1028 }
1029 
icGetDeviceAttrValue(xmlNode * pNode)1030 icUInt64Number icGetDeviceAttrValue(xmlNode *pNode)
1031 {
1032 	icUInt64Number devAttr = 0;
1033 	xmlAttr *attr = icXmlFindAttr(pNode, "ReflectiveOrTransparency");
1034   if (attr && !strcmp(icXmlAttrValue(attr), "transparency")) {
1035     devAttr |= icTransparency;
1036   }
1037 
1038 	attr = icXmlFindAttr(pNode, "GlossyOrMatte");
1039   if (attr && !strcmp(icXmlAttrValue(attr), "matte")) {
1040     devAttr |= icMatte;
1041 	}
1042 
1043 	attr = icXmlFindAttr(pNode, "MediaPolarity");
1044   if (attr && !strcmp(icXmlAttrValue(attr), "negative")) {
1045     devAttr |= icMediaNegative;
1046   }
1047 
1048 	attr = icXmlFindAttr(pNode, "MediaColour");
1049   if (attr && !strcmp(icXmlAttrValue(attr), "blackAndWhite")) {
1050 		devAttr |= icMediaBlackAndWhite;
1051 	}
1052 
1053   attr = icXmlFindAttr(pNode, "VendorSpecific");
1054   if (attr) {
1055     icUInt64Number vendor;
1056     sscanf(icXmlAttrValue(attr), "%I64x", &vendor);
1057     devAttr |= vendor;
1058   }
1059 
1060 	return devAttr;
1061 }
1062 
icGetColorantValue(const icChar * str)1063 icColorantEncoding icGetColorantValue(const icChar* str)
1064 {
1065 	if (!strcmp(str, "ITU-R BT.709"))
1066 		return icColorantITU;
1067 
1068 	if (!strcmp(str, "SMPTE RP145-1994"))
1069 		return icColorantSMPTE;
1070 
1071 	if (!strcmp(str, "EBU Tech.3213-E"))
1072 		return icColorantEBU;
1073 
1074 	if (!strcmp(str, "P22"))
1075 		return icColorantP22;
1076 
1077   return icColorantUnknown;
1078 }
1079 
icGetMeasurementValue(const icChar * str)1080 icMeasurementUnitSig icGetMeasurementValue(const icChar* str)
1081 {
1082 	if (!strcmp(str, "Status A"))
1083 		return icSigStatusA;
1084 
1085 	if (!strcmp(str, "Status E"))
1086 		return icSigStatusE;
1087 
1088 	if (!strcmp(str, "Status I"))
1089 		return icSigStatusI;
1090 
1091 	if (!strcmp(str, "Status T"))
1092 		return icSigStatusT;
1093 
1094 	if (!strcmp(str, "Status M"))
1095 		return icSigStatusM;
1096 
1097 	if (!strcmp(str, "DIN with no polarizing filter"))
1098 		return icSigDN;
1099 
1100 	if (!strcmp(str, "DIN with polarizing filter"))
1101 		return icSigDNP;
1102 
1103 	if (!strcmp(str, "Narrow band DIN with no polarizing filter"))
1104 		return icSigDNN;
1105 
1106 	if (!strcmp(str, "Narrow band DIN with polarizing filter"))
1107 		return icSigDNNP;
1108 
1109   return icSigStatusA;
1110 }
1111 
icGetDeviceAttrName(icUInt64Number devAttr)1112 const std::string icGetDeviceAttrName(icUInt64Number devAttr)
1113 {
1114 	char line[256];
1115 	std::string xml;
1116 
1117 	if (devAttr & icTransparency)
1118 		sprintf(line, "<DeviceAttributes ReflectiveOrTransparency=\"transparency\"");
1119 	else
1120 		sprintf(line, "<DeviceAttributes ReflectiveOrTransparency=\"reflective\"");
1121 	xml += line;
1122 
1123 
1124 	if (devAttr & icMatte)
1125 		sprintf(line, " GlossyOrMatte=\"matte\"");
1126 	else
1127 		sprintf(line, " GlossyOrMatte=\"glossy\"");
1128 	xml += line;
1129 
1130 
1131 	if (devAttr & icMediaNegative)
1132 		sprintf(line, " MediaPolarity=\"negative\"");
1133 	else
1134 		sprintf(line, " MediaPolarity=\"positive\"");
1135 	xml += line;
1136 
1137 	if (devAttr & icMediaBlackAndWhite)
1138 		sprintf(line, " MediaColour=\"blackAndwhite\"");
1139 	else
1140 		sprintf(line, " MediaColour=\"colour\"");
1141 	xml += line;
1142 
1143   icUInt64Number otherAttr = ~((icUInt64Number)icTransparency|icMatte|icMediaNegative|icMediaBlackAndWhite);
1144 
1145   if (devAttr & otherAttr) {
1146     sprintf(line, " VendorSpecific=\"%016I64x\"", devAttr & otherAttr);
1147     xml += line;
1148   }
1149 
1150   xml += "/>\n";
1151 
1152 	return xml;
1153 }
1154 
icGetHeaderFlagsName(icUInt32Number flags)1155 const std::string icGetHeaderFlagsName(icUInt32Number flags)
1156 {
1157 	char line[256];
1158 	std::string xml;
1159 
1160   if (flags & icEmbeddedProfileTrue)
1161 		sprintf(line, "<ProfileFlags EmbeddedInFile=\"true\" ");
1162 	else
1163 	  sprintf(line, "<ProfileFlags EmbeddedInFile=\"false\" ");
1164 	xml += line;
1165 
1166 	if (flags & icUseWithEmbeddedDataOnly)
1167 		sprintf(line, "UseWithEmbeddedDataOnly=\"true\"");
1168 	else
1169 		sprintf(line, "UseWithEmbeddedDataOnly=\"false\"");
1170 	xml += line;
1171 
1172   icUInt32Number otherFlags = ~(icEmbeddedProfileTrue|icUseWithEmbeddedDataOnly);
1173 
1174   if (flags & otherFlags) {
1175     sprintf(line, " VendorFlags=\"%08x\"", flags & otherFlags);
1176     xml += line;
1177   }
1178 
1179   xml += "/>\n";
1180 
1181   return xml;
1182 }
1183 
icGetPadSpace(double value)1184 const std::string icGetPadSpace(double value)
1185 {
1186   std::string space = "";
1187   if ( value >=0 && value < 10)
1188     space = "    ";
1189   if ( value >=10 && value < 100)
1190 	space = "   ";
1191    if ( value >=100 && value < 1000 )
1192 	space = "  ";
1193 
1194    return space;
1195 }
1196 
1197