diff options
Diffstat (limited to 'third_party/lcms2-2.6/src/cmscgats.c')
-rw-r--r-- | third_party/lcms2-2.6/src/cmscgats.c | 2776 |
1 files changed, 0 insertions, 2776 deletions
diff --git a/third_party/lcms2-2.6/src/cmscgats.c b/third_party/lcms2-2.6/src/cmscgats.c deleted file mode 100644 index cce4cedbad..0000000000 --- a/third_party/lcms2-2.6/src/cmscgats.c +++ /dev/null @@ -1,2776 +0,0 @@ -//--------------------------------------------------------------------------------- -// -// Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -//--------------------------------------------------------------------------------- -// - -#include "lcms2_internal.h" - - -// IT8.7 / CGATS.17-200x handling ----------------------------------------------------------------------------- - - -#define MAXID 128 // Max length of identifier -#define MAXSTR 1024 // Max length of string -#define MAXTABLES 255 // Max Number of tables in a single stream -#define MAXINCLUDE 20 // Max number of nested includes - -#define DEFAULT_DBL_FORMAT "%.10g" // Double formatting - -#ifdef CMS_IS_WINDOWS_ -//sunliang.liu modified 2010426 for wince error -# ifndef _WIN32_WCE -# include <io.h> -# endif -# define DIR_CHAR '\\' -#else -# define DIR_CHAR '/' -#endif - - -// Symbols -typedef enum { - - SNONE, - SINUM, // Integer - SDNUM, // Real - SIDENT, // Identifier - SSTRING, // string - SCOMMENT, // comment - SEOLN, // End of line - SEOF, // End of stream - SSYNERROR, // Syntax error found on stream - - // Keywords - - SBEGIN_DATA, - SBEGIN_DATA_FORMAT, - SEND_DATA, - SEND_DATA_FORMAT, - SKEYWORD, - SDATA_FORMAT_ID, - SINCLUDE - - } SYMBOL; - - -// How to write the value -typedef enum { - - WRITE_UNCOOKED, - WRITE_STRINGIFY, - WRITE_HEXADECIMAL, - WRITE_BINARY, - WRITE_PAIR - - } WRITEMODE; - -// Linked list of variable names -typedef struct _KeyVal { - - struct _KeyVal* Next; - char* Keyword; // Name of variable - struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item - char* Subkey; // If key is a dictionary, points to the subkey name - char* Value; // Points to value - WRITEMODE WriteAs; // How to write the value - - } KEYVALUE; - - -// Linked list of memory chunks (Memory sink) -typedef struct _OwnedMem { - - struct _OwnedMem* Next; - void * Ptr; // Point to value - - } OWNEDMEM; - -// Suballocator -typedef struct _SubAllocator { - - cmsUInt8Number* Block; - cmsUInt32Number BlockSize; - cmsUInt32Number Used; - - } SUBALLOCATOR; - -// Table. Each individual table can hold properties and rows & cols -typedef struct _Table { - - char SheetType[MAXSTR]; // The first row of the IT8 (the type) - - int nSamples, nPatches; // Cols, Rows - int SampleID; // Pos of ID - - KEYVALUE* HeaderList; // The properties - - char** DataFormat; // The binary stream descriptor - char** Data; // The binary stream - - } TABLE; - -// File stream being parsed -typedef struct _FileContext { - char FileName[cmsMAX_PATH]; // File name if being readed from file - FILE* Stream; // File stream or NULL if holded in memory - } FILECTX; - -// This struct hold all information about an open IT8 handler. -typedef struct { - - - cmsUInt32Number TablesCount; // How many tables in this stream - cmsUInt32Number nTable; // The actual table - - TABLE Tab[MAXTABLES]; - - // Memory management - OWNEDMEM* MemorySink; // The storage backend - SUBALLOCATOR Allocator; // String suballocator -- just to keep it fast - - // Parser state machine - SYMBOL sy; // Current symbol - int ch; // Current character - - cmsInt32Number inum; // integer value - cmsFloat64Number dnum; // real value - - char id[MAXID]; // identifier - char str[MAXSTR]; // string - - // Allowed keywords & datasets. They have visibility on whole stream - KEYVALUE* ValidKeywords; - KEYVALUE* ValidSampleID; - - char* Source; // Points to loc. being parsed - cmsInt32Number lineno; // line counter for error reporting - - FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed - cmsInt32Number IncludeSP; // Include Stack Pointer - - char* MemoryBlock; // The stream if holded in memory - - char DoubleFormatter[MAXID];// Printf-like 'cmsFloat64Number' formatter - - cmsContext ContextID; // The threading context - - } cmsIT8; - - -// The stream for save operations -typedef struct { - - FILE* stream; // For save-to-file behaviour - - cmsUInt8Number* Base; - cmsUInt8Number* Ptr; // For save-to-mem behaviour - cmsUInt32Number Used; - cmsUInt32Number Max; - - } SAVESTREAM; - - -// ------------------------------------------------------ cmsIT8 parsing routines - - -// A keyword -typedef struct { - - const char *id; - SYMBOL sy; - - } KEYWORD; - -// The keyword->symbol translation table. Sorting is required. -static const KEYWORD TabKeys[] = { - - {"$INCLUDE", SINCLUDE}, // This is an extension! - {".INCLUDE", SINCLUDE}, // This is an extension! - - {"BEGIN_DATA", SBEGIN_DATA }, - {"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT }, - {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID}, - {"END_DATA", SEND_DATA}, - {"END_DATA_FORMAT", SEND_DATA_FORMAT}, - {"KEYWORD", SKEYWORD} - }; - -#define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD)) - -// Predefined properties - -// A property -typedef struct { - const char *id; // The identifier - WRITEMODE as; // How is supposed to be written - } PROPERTY; - -static PROPERTY PredefinedProperties[] = { - - {"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS - {"NUMBER_OF_SETS", WRITE_UNCOOKED}, // Required - NUMBER OF SETS - {"ORIGINATOR", WRITE_STRINGIFY}, // Required - Identifies the specific system, organization or individual that created the data file. - {"FILE_DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file. - {"CREATED", WRITE_STRINGIFY}, // Required - Indicates date of creation of the data file. - {"DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file. - {"DIFFUSE_GEOMETRY", WRITE_STRINGIFY}, // The diffuse geometry used. Allowed values are "sphere" or "opal". - {"MANUFACTURER", WRITE_STRINGIFY}, - {"MANUFACTURE", WRITE_STRINGIFY}, // Some broken Fuji targets does store this value - {"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm. - {"SERIAL", WRITE_STRINGIFY}, // Uniquely identifies individual physical target. - - {"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code - // uniquely identifying th e material. This is intend ed to be used for IT8.7 - // physical targets only (i.e . IT8.7/1 a nd IT8.7/2). - - {"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and - // model number) to generate the data reported. This data will often - // provide more information about the particular data collected than an - // extensive list of specific details. This is particularly important for - // spectral data or data derived from spectrophotometry. - - {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide - // a guide to the potential for issues of paper fluorescence, etc. - - {"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported. - // Where standard conditions have been defined (e.g., SWOP at nominal) - // named conditions may suffice. Otherwise, detailed information is - // needed. - - {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during - // measurement. Allowed values are "black" "white" or "na". - - {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic - - // below properties are new in recent specs: - - {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated - // along with details of the geometry and the aperture size and shape. For example, - // for transmission measurements it is important to identify 0/diffuse, diffuse/0, - // opal or integrating sphere, etc. For reflection it is important to identify 0/45, - // 45/0, sphere (specular included or excluded), etc. - - {"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to - // denote the use of filters such as none, D65, Red, Green or Blue. - - {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed - // values are "yes" "white" "none" or "na" - - {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the - // calculation of various data parameters (2 degree and 10 degree), CIE standard - // illuminant functions used in the calculation of various data parameters (e.g., D50, - // D65, etc.), density status response, etc. If used there shall be at least one - // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute - // in the set shall be {"name" and shall identify the particular parameter used. - // The second shall be {"value" and shall provide the value associated with that name. - // For ASCII data, a string containing the Name and Value attribute pairs shall follow - // the weighting function keyword. A semi-colon separates attribute pairs from each - // other and within the attribute the name and value are separated by a comma. - - {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name - // of the calculation, parameter is the name of the parameter used in the calculation - // and value is the value of the parameter. - - {"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc. - - {"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target. - - {"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table. - - {"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table. -}; - -#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY)) - - -// Predefined sample types on dataset -static const char* PredefinedSampleID[] = { - "SAMPLE_ID", // Identifies sample that data represents - "STRING", // Identifies label, or other non-machine readable value. - // Value must begin and end with a " symbol - - "CMYK_C", // Cyan component of CMYK data expressed as a percentage - "CMYK_M", // Magenta component of CMYK data expressed as a percentage - "CMYK_Y", // Yellow component of CMYK data expressed as a percentage - "CMYK_K", // Black component of CMYK data expressed as a percentage - "D_RED", // Red filter density - "D_GREEN", // Green filter density - "D_BLUE", // Blue filter density - "D_VIS", // Visual filter density - "D_MAJOR_FILTER", // Major filter d ensity - "RGB_R", // Red component of RGB data - "RGB_G", // Green component of RGB data - "RGB_B", // Blue com ponent of RGB data - "SPECTRAL_NM", // Wavelength of measurement expressed in nanometers - "SPECTRAL_PCT", // Percentage reflectance/transmittance - "SPECTRAL_DEC", // Reflectance/transmittance - "XYZ_X", // X component of tristimulus data - "XYZ_Y", // Y component of tristimulus data - "XYZ_Z", // Z component of tristimulus data - "XYY_X" // x component of chromaticity data - "XYY_Y", // y component of chromaticity data - "XYY_CAPY", // Y component of tristimulus data - "LAB_L", // L* component of Lab data - "LAB_A", // a* component of Lab data - "LAB_B", // b* component of Lab data - "LAB_C", // C*ab component of Lab data - "LAB_H", // hab component of Lab data - "LAB_DE", // CIE dE - "LAB_DE_94", // CIE dE using CIE 94 - "LAB_DE_CMC", // dE using CMC - "LAB_DE_2000", // CIE dE using CIE DE 2000 - "MEAN_DE", // Mean Delta E (LAB_DE) of samples compared to batch average - // (Used for data files for ANSI IT8.7/1 and IT8.7/2 targets) - "STDEV_X", // Standard deviation of X (tristimulus data) - "STDEV_Y", // Standard deviation of Y (tristimulus data) - "STDEV_Z", // Standard deviation of Z (tristimulus data) - "STDEV_L", // Standard deviation of L* - "STDEV_A", // Standard deviation of a* - "STDEV_B", // Standard deviation of b* - "STDEV_DE", // Standard deviation of CIE dE - "CHI_SQD_PAR"}; // The average of the standard deviations of L*, a* and b*. It is - // used to derive an estimate of the chi-squared parameter which is - // recommended as the predictor of the variability of dE - -#define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *)) - -//Forward declaration of some internal functions -static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size); - -// Checks whatever c is a separator -static -cmsBool isseparator(int c) -{ - return (c == ' ') || (c == '\t') ; -} - -// Checks whatever c is a valid identifier char -static -cmsBool ismiddle(int c) -{ - return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127)); -} - -// Checks whatsever c is a valid identifier middle char. -static -cmsBool isidchar(int c) -{ - return isalnum(c) || ismiddle(c); -} - -// Checks whatsever c is a valid identifier first char. -static -cmsBool isfirstidchar(int c) -{ - return !isdigit(c) && ismiddle(c); -} - -// Guess whether the supplied path looks like an absolute path -static -cmsBool isabsolutepath(const char *path) -{ - char ThreeChars[4]; - - if(path == NULL) - return FALSE; - if (path[0] == 0) - return FALSE; - - strncpy(ThreeChars, path, 3); - ThreeChars[3] = 0; - - if(ThreeChars[0] == DIR_CHAR) - return TRUE; - -#ifdef CMS_IS_WINDOWS_ - if (isalpha((int) ThreeChars[0]) && ThreeChars[1] == ':') - return TRUE; -#endif - return FALSE; -} - - -// Makes a file path based on a given reference path -// NOTE: this function doesn't check if the path exists or even if it's legal -static -cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen) -{ - char *tail; - cmsUInt32Number len; - - // Already absolute? - if (isabsolutepath(relPath)) { - - strncpy(buffer, relPath, MaxLen); - buffer[MaxLen-1] = 0; - return TRUE; - } - - // No, search for last - strncpy(buffer, basePath, MaxLen); - buffer[MaxLen-1] = 0; - - tail = strrchr(buffer, DIR_CHAR); - if (tail == NULL) return FALSE; // Is not absolute and has no separators?? - - len = (cmsUInt32Number) (tail - buffer); - if (len >= MaxLen) return FALSE; - - // No need to assure zero terminator over here - strncpy(tail + 1, relPath, MaxLen - len); - - return TRUE; -} - - -// Make sure no exploit is being even tried -static -const char* NoMeta(const char* str) -{ - if (strchr(str, '%') != NULL) - return "**** CORRUPTED FORMAT STRING ***"; - - return str; -} - -// Syntax error -static -cmsBool SynError(cmsIT8* it8, const char *Txt, ...) -{ - char Buffer[256], ErrMsg[1024]; - va_list args; - - va_start(args, Txt); - vsnprintf(Buffer, 255, Txt, args); - Buffer[255] = 0; - va_end(args); - - snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer); - ErrMsg[1023] = 0; - it8->sy = SSYNERROR; - cmsSignalError(it8 ->ContextID, cmsERROR_CORRUPTION_DETECTED, "%s", ErrMsg); - return FALSE; -} - -// Check if current symbol is same as specified. issue an error else. -static -cmsBool Check(cmsIT8* it8, SYMBOL sy, const char* Err) -{ - if (it8 -> sy != sy) - return SynError(it8, NoMeta(Err)); - return TRUE; -} - -// Read Next character from stream -static -void NextCh(cmsIT8* it8) -{ - if (it8 -> FileStack[it8 ->IncludeSP]->Stream) { - - it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream); - - if (feof(it8 -> FileStack[it8 ->IncludeSP]->Stream)) { - - if (it8 ->IncludeSP > 0) { - - fclose(it8 ->FileStack[it8->IncludeSP--]->Stream); - it8 -> ch = ' '; // Whitespace to be ignored - - } else - it8 ->ch = 0; // EOF - } - } - else { - it8->ch = *it8->Source; - if (it8->ch) it8->Source++; - } -} - - -// Try to see if current identifier is a keyword, if so return the referred symbol -static -SYMBOL BinSrchKey(const char *id) -{ - int l = 1; - int r = NUMKEYS; - int x, res; - - while (r >= l) - { - x = (l+r)/2; - res = cmsstrcasecmp(id, TabKeys[x-1].id); - if (res == 0) return TabKeys[x-1].sy; - if (res < 0) r = x - 1; - else l = x + 1; - } - - return SNONE; -} - - -// 10 ^n -static -cmsFloat64Number xpow10(int n) -{ - return pow(10, (cmsFloat64Number) n); -} - - -// Reads a Real number, tries to follow from integer number -static -void ReadReal(cmsIT8* it8, int inum) -{ - it8->dnum = (cmsFloat64Number) inum; - - while (isdigit(it8->ch)) { - - it8->dnum = it8->dnum * 10.0 + (it8->ch - '0'); - NextCh(it8); - } - - if (it8->ch == '.') { // Decimal point - - cmsFloat64Number frac = 0.0; // fraction - int prec = 0; // precision - - NextCh(it8); // Eats dec. point - - while (isdigit(it8->ch)) { - - frac = frac * 10.0 + (it8->ch - '0'); - prec++; - NextCh(it8); - } - - it8->dnum = it8->dnum + (frac / xpow10(prec)); - } - - // Exponent, example 34.00E+20 - if (toupper(it8->ch) == 'E') { - - cmsInt32Number e; - cmsInt32Number sgn; - - NextCh(it8); sgn = 1; - - if (it8->ch == '-') { - - sgn = -1; NextCh(it8); - } - else - if (it8->ch == '+') { - - sgn = +1; - NextCh(it8); - } - - e = 0; - while (isdigit(it8->ch)) { - - if ((cmsFloat64Number) e * 10L < (cmsFloat64Number) +2147483647.0) - e = e * 10 + (it8->ch - '0'); - - NextCh(it8); - } - - e = sgn*e; - it8 -> dnum = it8 -> dnum * xpow10(e); - } -} - -// Parses a float number -// This can not call directly atof because it uses locale dependant -// parsing, while CCMX files always use . as decimal separator -static -cmsFloat64Number ParseFloatNumber(const char *Buffer) -{ - cmsFloat64Number dnum = 0.0; - int sign = 1; - - // keep safe - if (Buffer == NULL) return 0.0; - - if (*Buffer == '-' || *Buffer == '+') { - - sign = (*Buffer == '-') ? -1 : 1; - Buffer++; - } - - - while (*Buffer && isdigit((int) *Buffer)) { - - dnum = dnum * 10.0 + (*Buffer - '0'); - if (*Buffer) Buffer++; - } - - if (*Buffer == '.') { - - cmsFloat64Number frac = 0.0; // fraction - int prec = 0; // precission - - if (*Buffer) Buffer++; - - while (*Buffer && isdigit((int) *Buffer)) { - - frac = frac * 10.0 + (*Buffer - '0'); - prec++; - if (*Buffer) Buffer++; - } - - dnum = dnum + (frac / xpow10(prec)); - } - - // Exponent, example 34.00E+20 - if (*Buffer && toupper(*Buffer) == 'E') { - - int e; - int sgn; - - if (*Buffer) Buffer++; - sgn = 1; - - if (*Buffer == '-') { - - sgn = -1; - if (*Buffer) Buffer++; - } - else - if (*Buffer == '+') { - - sgn = +1; - if (*Buffer) Buffer++; - } - - e = 0; - while (*Buffer && isdigit((int) *Buffer)) { - - if ((cmsFloat64Number) e * 10L < INT_MAX) - e = e * 10 + (*Buffer - '0'); - - if (*Buffer) Buffer++; - } - - e = sgn*e; - dnum = dnum * xpow10(e); - } - - return sign * dnum; -} - - -// Reads next symbol -static -void InSymbol(cmsIT8* it8) -{ - register char *idptr; - register int k; - SYMBOL key; - int sng; - - do { - - while (isseparator(it8->ch)) - NextCh(it8); - - if (isfirstidchar(it8->ch)) { // Identifier - - k = 0; - idptr = it8->id; - - do { - - if (++k < MAXID) *idptr++ = (char) it8->ch; - - NextCh(it8); - - } while (isidchar(it8->ch)); - - *idptr = '\0'; - - - key = BinSrchKey(it8->id); - if (key == SNONE) it8->sy = SIDENT; - else it8->sy = key; - - } - else // Is a number? - if (isdigit(it8->ch) || it8->ch == '.' || it8->ch == '-' || it8->ch == '+') - { - int sign = 1; - - if (it8->ch == '-') { - sign = -1; - NextCh(it8); - } - - it8->inum = 0; - it8->sy = SINUM; - - if (it8->ch == '0') { // 0xnnnn (Hexa) or 0bnnnn (Binary) - - NextCh(it8); - if (toupper(it8->ch) == 'X') { - - int j; - - NextCh(it8); - while (isxdigit(it8->ch)) - { - it8->ch = toupper(it8->ch); - if (it8->ch >= 'A' && it8->ch <= 'F') j = it8->ch -'A'+10; - else j = it8->ch - '0'; - - if ((long) it8->inum * 16L > (long) INT_MAX) - { - SynError(it8, "Invalid hexadecimal number"); - return; - } - - it8->inum = it8->inum * 16 + j; - NextCh(it8); - } - return; - } - - if (toupper(it8->ch) == 'B') { // Binary - - int j; - - NextCh(it8); - while (it8->ch == '0' || it8->ch == '1') - { - j = it8->ch - '0'; - - if ((long) it8->inum * 2L > (long) INT_MAX) - { - SynError(it8, "Invalid binary number"); - return; - } - - it8->inum = it8->inum * 2 + j; - NextCh(it8); - } - return; - } - } - - - while (isdigit(it8->ch)) { - - if ((cmsFloat64Number) it8->inum * 10L > (cmsFloat64Number) +2147483647.0) { - ReadReal(it8, it8->inum); - it8->sy = SDNUM; - it8->dnum *= sign; - return; - } - - it8->inum = it8->inum * 10 + (it8->ch - '0'); - NextCh(it8); - } - - if (it8->ch == '.') { - - ReadReal(it8, it8->inum); - it8->sy = SDNUM; - it8->dnum *= sign; - return; - } - - it8 -> inum *= sign; - - // Special case. Numbers followed by letters are taken as identifiers - - if (isidchar(it8 ->ch)) { - - if (it8 ->sy == SINUM) { - - sprintf(it8->id, "%d", it8->inum); - } - else { - - sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum); - } - - k = (int) strlen(it8 ->id); - idptr = it8 ->id + k; - do { - - if (++k < MAXID) *idptr++ = (char) it8->ch; - - NextCh(it8); - - } while (isidchar(it8->ch)); - - *idptr = '\0'; - it8->sy = SIDENT; - } - return; - - } - else - switch ((int) it8->ch) { - - // EOF marker -- ignore it - case '\x1a': - NextCh(it8); - break; - - // Eof stream markers - case 0: - case -1: - it8->sy = SEOF; - break; - - - // Next line - case '\r': - NextCh(it8); - if (it8 ->ch == '\n') - NextCh(it8); - it8->sy = SEOLN; - it8->lineno++; - break; - - case '\n': - NextCh(it8); - it8->sy = SEOLN; - it8->lineno++; - break; - - // Comment - case '#': - NextCh(it8); - while (it8->ch && it8->ch != '\n' && it8->ch != '\r') - NextCh(it8); - - it8->sy = SCOMMENT; - break; - - // String. - case '\'': - case '\"': - idptr = it8->str; - sng = it8->ch; - k = 0; - NextCh(it8); - - while (k < MAXSTR && it8->ch != sng) { - - if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1; - else { - *idptr++ = (char) it8->ch; - NextCh(it8); - k++; - } - } - - it8->sy = SSTRING; - *idptr = '\0'; - NextCh(it8); - break; - - - default: - SynError(it8, "Unrecognized character: 0x%x", it8 ->ch); - return; - } - - } while (it8->sy == SCOMMENT); - - // Handle the include special token - - if (it8 -> sy == SINCLUDE) { - - FILECTX* FileNest; - - if(it8 -> IncludeSP >= (MAXINCLUDE-1)) { - - SynError(it8, "Too many recursion levels"); - return; - } - - InSymbol(it8); - if (!Check(it8, SSTRING, "Filename expected")) return; - - FileNest = it8 -> FileStack[it8 -> IncludeSP + 1]; - if(FileNest == NULL) { - - FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX)); - //if(FileNest == NULL) - // TODO: how to manage out-of-memory conditions? - } - - if (BuildAbsolutePath(it8->str, - it8->FileStack[it8->IncludeSP]->FileName, - FileNest->FileName, cmsMAX_PATH-1) == FALSE) { - SynError(it8, "File path too long"); - return; - } - - FileNest->Stream = fopen(FileNest->FileName, "rt"); - if (FileNest->Stream == NULL) { - - SynError(it8, "File %s not found", FileNest->FileName); - return; - } - it8->IncludeSP++; - - it8 ->ch = ' '; - InSymbol(it8); - } - -} - -// Checks end of line separator -static -cmsBool CheckEOLN(cmsIT8* it8) -{ - if (!Check(it8, SEOLN, "Expected separator")) return FALSE; - while (it8 -> sy == SEOLN) - InSymbol(it8); - return TRUE; - -} - -// Skip a symbol - -static -void Skip(cmsIT8* it8, SYMBOL sy) -{ - if (it8->sy == sy && it8->sy != SEOF) - InSymbol(it8); -} - - -// Skip multiple EOLN -static -void SkipEOLN(cmsIT8* it8) -{ - while (it8->sy == SEOLN) { - InSymbol(it8); - } -} - - -// Returns a string holding current value -static -cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* ErrorTitle) -{ - switch (it8->sy) { - - case SEOLN: // Empty value - Buffer[0]=0; - break; - case SIDENT: strncpy(Buffer, it8->id, max); - Buffer[max-1]=0; - break; - case SINUM: snprintf(Buffer, max, "%d", it8 -> inum); break; - case SDNUM: snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break; - case SSTRING: strncpy(Buffer, it8->str, max); - Buffer[max-1] = 0; - break; - - - default: - return SynError(it8, "%s", ErrorTitle); - } - - Buffer[max] = 0; - return TRUE; -} - -// ---------------------------------------------------------- Table - -static -TABLE* GetTable(cmsIT8* it8) -{ - if ((it8 -> nTable >= it8 ->TablesCount)) { - - SynError(it8, "Table %d out of sequence", it8 -> nTable); - return it8 -> Tab; - } - - return it8 ->Tab + it8 ->nTable; -} - -// ---------------------------------------------------------- Memory management - - -// Frees an allocator and owned memory -void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - if (it8 == NULL) - return; - - if (it8->MemorySink) { - - OWNEDMEM* p; - OWNEDMEM* n; - - for (p = it8->MemorySink; p != NULL; p = n) { - - n = p->Next; - if (p->Ptr) _cmsFree(it8 ->ContextID, p->Ptr); - _cmsFree(it8 ->ContextID, p); - } - } - - if (it8->MemoryBlock) - _cmsFree(it8 ->ContextID, it8->MemoryBlock); - - _cmsFree(it8 ->ContextID, it8); -} - - -// Allocates a chunk of data, keep linked list -static -void* AllocBigBlock(cmsIT8* it8, cmsUInt32Number size) -{ - OWNEDMEM* ptr1; - void* ptr = _cmsMallocZero(it8->ContextID, size); - - if (ptr != NULL) { - - ptr1 = (OWNEDMEM*) _cmsMallocZero(it8 ->ContextID, sizeof(OWNEDMEM)); - - if (ptr1 == NULL) { - - _cmsFree(it8 ->ContextID, ptr); - return NULL; - } - - ptr1-> Ptr = ptr; - ptr1-> Next = it8 -> MemorySink; - it8 -> MemorySink = ptr1; - } - - return ptr; -} - - -// Suballocator. -static -void* AllocChunk(cmsIT8* it8, cmsUInt32Number size) -{ - cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used; - cmsUInt8Number* ptr; - - size = _cmsALIGNMEM(size); - - if (size > Free) { - - if (it8 -> Allocator.BlockSize == 0) - - it8 -> Allocator.BlockSize = 20*1024; - else - it8 ->Allocator.BlockSize *= 2; - - if (it8 ->Allocator.BlockSize < size) - it8 ->Allocator.BlockSize = size; - - it8 ->Allocator.Used = 0; - it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize); - } - - ptr = it8 ->Allocator.Block + it8 ->Allocator.Used; - it8 ->Allocator.Used += size; - - return (void*) ptr; - -} - - -// Allocates a string -static -char *AllocString(cmsIT8* it8, const char* str) -{ - cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1; - char *ptr; - - - ptr = (char *) AllocChunk(it8, Size); - if (ptr) strncpy (ptr, str, Size-1); - - return ptr; -} - -// Searches through linked list - -static -cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYVALUE** LastPtr) -{ - if (LastPtr) *LastPtr = p; - - for (; p != NULL; p = p->Next) { - - if (LastPtr) *LastPtr = p; - - if (*Key != '#') { // Comments are ignored - - if (cmsstrcasecmp(Key, p->Keyword) == 0) - break; - } - } - - if (p == NULL) - return FALSE; - - if (Subkey == 0) - return TRUE; - - for (; p != NULL; p = p->NextSubkey) { - - if (p ->Subkey == NULL) continue; - - if (LastPtr) *LastPtr = p; - - if (cmsstrcasecmp(Subkey, p->Subkey) == 0) - return TRUE; - } - - return FALSE; -} - - - -// Add a property into a linked list -static -KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs) -{ - KEYVALUE* p; - KEYVALUE* last; - - - // Check if property is already in list - - if (IsAvailableOnList(*Head, Key, Subkey, &p)) { - - // This may work for editing properties - - // return SynError(it8, "duplicate key <%s>", Key); - } - else { - - last = p; - - // Allocate the container - p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE)); - if (p == NULL) - { - SynError(it8, "AddToList: out of memory"); - return NULL; - } - - // Store name and value - p->Keyword = AllocString(it8, Key); - p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey); - - // Keep the container in our list - if (*Head == NULL) { - *Head = p; - } - else - { - if (Subkey != NULL && last != NULL) { - - last->NextSubkey = p; - - // If Subkey is not null, then last is the last property with the same key, - // but not necessarily is the last property in the list, so we need to move - // to the actual list end - while (last->Next != NULL) - last = last->Next; - } - - if (last != NULL) last->Next = p; - } - - p->Next = NULL; - p->NextSubkey = NULL; - } - - p->WriteAs = WriteAs; - - if (xValue != NULL) { - - p->Value = AllocString(it8, xValue); - } - else { - p->Value = NULL; - } - - return p; -} - -static -KEYVALUE* AddAvailableProperty(cmsIT8* it8, const char* Key, WRITEMODE as) -{ - return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as); -} - - -static -KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key) -{ - return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED); -} - - -static -void AllocTable(cmsIT8* it8) -{ - TABLE* t; - - t = it8 ->Tab + it8 ->TablesCount; - - t->HeaderList = NULL; - t->DataFormat = NULL; - t->Data = NULL; - - it8 ->TablesCount++; -} - - -cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE IT8, cmsUInt32Number nTable) -{ - cmsIT8* it8 = (cmsIT8*) IT8; - - if (nTable >= it8 ->TablesCount) { - - if (nTable == it8 ->TablesCount) { - - AllocTable(it8); - } - else { - SynError(it8, "Table %d is out of sequence", nTable); - return -1; - } - } - - it8 ->nTable = nTable; - - return (cmsInt32Number) nTable; -} - - - -// Init an empty container -cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID) -{ - cmsIT8* it8; - cmsUInt32Number i; - - it8 = (cmsIT8*) _cmsMallocZero(ContextID, sizeof(cmsIT8)); - if (it8 == NULL) return NULL; - - AllocTable(it8); - - it8->MemoryBlock = NULL; - it8->MemorySink = NULL; - - it8 ->nTable = 0; - - it8->ContextID = ContextID; - it8->Allocator.Used = 0; - it8->Allocator.Block = NULL; - it8->Allocator.BlockSize = 0; - - it8->ValidKeywords = NULL; - it8->ValidSampleID = NULL; - - it8 -> sy = SNONE; - it8 -> ch = ' '; - it8 -> Source = NULL; - it8 -> inum = 0; - it8 -> dnum = 0.0; - - it8->FileStack[0] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX)); - it8->IncludeSP = 0; - it8 -> lineno = 1; - - strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); - cmsIT8SetSheetType((cmsHANDLE) it8, "CGATS.17"); - - // Initialize predefined properties & data - - for (i=0; i < NUMPREDEFINEDPROPS; i++) - AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as); - - for (i=0; i < NUMPREDEFINEDSAMPLEID; i++) - AddAvailableSampleID(it8, PredefinedSampleID[i]); - - - return (cmsHANDLE) it8; -} - - -const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8) -{ - return GetTable((cmsIT8*) hIT8)->SheetType; -} - -cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type) -{ - TABLE* t = GetTable((cmsIT8*) hIT8); - - strncpy(t ->SheetType, Type, MAXSTR-1); - t ->SheetType[MAXSTR-1] = 0; - return TRUE; -} - -cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - if (!Val) return FALSE; - if (!*Val) return FALSE; - - return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL; -} - -// Sets a property -cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const char *Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - if (!Val) return FALSE; - if (!*Val) return FALSE; - - return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL; -} - -cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - char Buffer[1024]; - - sprintf(Buffer, it8->DoubleFormatter, Val); - - return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; -} - -cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - char Buffer[1024]; - - sprintf(Buffer, "%u", Val); - - return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; -} - -cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL; -} - -cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL; -} - -// Gets a property -const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* Key) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - KEYVALUE* p; - - if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p)) - { - return p -> Value; - } - return NULL; -} - - -cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp) -{ - const char *v = cmsIT8GetProperty(hIT8, cProp); - - if (v == NULL) return 0.0; - - return ParseFloatNumber(v); -} - -const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - KEYVALUE* p; - - if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) { - return p -> Value; - } - return NULL; -} - -// ----------------------------------------------------------------- Datasets - - -static -void AllocateDataFormat(cmsIT8* it8) -{ - TABLE* t = GetTable(it8); - - if (t -> DataFormat) return; // Already allocated - - t -> nSamples = (int) cmsIT8GetPropertyDbl(it8, "NUMBER_OF_FIELDS"); - - if (t -> nSamples <= 0) { - - SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS"); - t -> nSamples = 10; - } - - t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *)); - if (t->DataFormat == NULL) { - - SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array"); - } - -} - -static -const char *GetDataFormat(cmsIT8* it8, int n) -{ - TABLE* t = GetTable(it8); - - if (t->DataFormat) - return t->DataFormat[n]; - - return NULL; -} - -static -cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label) -{ - TABLE* t = GetTable(it8); - - if (!t->DataFormat) - AllocateDataFormat(it8); - - if (n > t -> nSamples) { - SynError(it8, "More than NUMBER_OF_FIELDS fields."); - return FALSE; - } - - if (t->DataFormat) { - t->DataFormat[n] = AllocString(it8, label); - } - - return TRUE; -} - - -cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample) -{ - cmsIT8* it8 = (cmsIT8*) h; - return SetDataFormat(it8, n, Sample); -} - -static -void AllocateDataSet(cmsIT8* it8) -{ - TABLE* t = GetTable(it8); - - if (t -> Data) return; // Already allocated - - t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); - t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); - - t-> Data = (char**)AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * ((cmsUInt32Number) t->nPatches + 1) *sizeof (char*)); - if (t->Data == NULL) { - - SynError(it8, "AllocateDataSet: Unable to allocate data array"); - } - -} - -static -char* GetData(cmsIT8* it8, int nSet, int nField) -{ - TABLE* t = GetTable(it8); - int nSamples = t -> nSamples; - int nPatches = t -> nPatches; - - if (nSet >= nPatches || nField >= nSamples) - return NULL; - - if (!t->Data) return NULL; - return t->Data [nSet * nSamples + nField]; -} - -static -cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val) -{ - TABLE* t = GetTable(it8); - - if (!t->Data) - AllocateDataSet(it8); - - if (!t->Data) return FALSE; - - if (nSet > t -> nPatches || nSet < 0) { - - return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches); - } - - if (nField > t ->nSamples || nField < 0) { - return SynError(it8, "Sample %d out of range, there are %d samples", nField, t ->nSamples); - - } - - t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val); - return TRUE; -} - - -// --------------------------------------------------------------- File I/O - - -// Writes a string to file -static -void WriteStr(SAVESTREAM* f, const char *str) -{ - cmsUInt32Number len; - - if (str == NULL) - str = " "; - - // Length to write - len = (cmsUInt32Number) strlen(str); - f ->Used += len; - - - if (f ->stream) { // Should I write it to a file? - - if (fwrite(str, 1, len, f->stream) != len) { - cmsSignalError(0, cmsERROR_WRITE, "Write to file error in CGATS parser"); - return; - } - - } - else { // Or to a memory block? - - if (f ->Base) { // Am I just counting the bytes? - - if (f ->Used > f ->Max) { - - cmsSignalError(0, cmsERROR_WRITE, "Write to memory overflows in CGATS parser"); - return; - } - - memmove(f ->Ptr, str, len); - f->Ptr += len; - } - - } -} - - -// Write formatted - -static -void Writef(SAVESTREAM* f, const char* frm, ...) -{ - char Buffer[4096]; - va_list args; - - va_start(args, frm); - vsnprintf(Buffer, 4095, frm, args); - Buffer[4095] = 0; - WriteStr(f, Buffer); - va_end(args); - -} - -// Writes full header -static -void WriteHeader(cmsIT8* it8, SAVESTREAM* fp) -{ - KEYVALUE* p; - TABLE* t = GetTable(it8); - - // Writes the type - WriteStr(fp, t->SheetType); - WriteStr(fp, "\n"); - - for (p = t->HeaderList; (p != NULL); p = p->Next) - { - if (*p ->Keyword == '#') { - - char* Pt; - - WriteStr(fp, "#\n# "); - for (Pt = p ->Value; *Pt; Pt++) { - - - Writef(fp, "%c", *Pt); - - if (*Pt == '\n') { - WriteStr(fp, "# "); - } - } - - WriteStr(fp, "\n#\n"); - continue; - } - - - if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) { - -#ifdef CMS_STRICT_CGATS - WriteStr(fp, "KEYWORD\t\""); - WriteStr(fp, p->Keyword); - WriteStr(fp, "\"\n"); -#endif - - AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED); - } - - WriteStr(fp, p->Keyword); - if (p->Value) { - - switch (p ->WriteAs) { - - case WRITE_UNCOOKED: - Writef(fp, "\t%s", p ->Value); - break; - - case WRITE_STRINGIFY: - Writef(fp, "\t\"%s\"", p->Value ); - break; - - case WRITE_HEXADECIMAL: - Writef(fp, "\t0x%X", atoi(p ->Value)); - break; - - case WRITE_BINARY: - Writef(fp, "\t0x%B", atoi(p ->Value)); - break; - - case WRITE_PAIR: - Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value); - break; - - default: SynError(it8, "Unknown write mode %d", p ->WriteAs); - return; - } - } - - WriteStr (fp, "\n"); - } - -} - - -// Writes the data format -static -void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8) -{ - int i, nSamples; - TABLE* t = GetTable(it8); - - if (!t -> DataFormat) return; - - WriteStr(fp, "BEGIN_DATA_FORMAT\n"); - WriteStr(fp, " "); - nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS")); - - for (i = 0; i < nSamples; i++) { - - WriteStr(fp, t->DataFormat[i]); - WriteStr(fp, ((i == (nSamples-1)) ? "\n" : "\t")); - } - - WriteStr (fp, "END_DATA_FORMAT\n"); -} - - -// Writes data array -static -void WriteData(SAVESTREAM* fp, cmsIT8* it8) -{ - int i, j; - TABLE* t = GetTable(it8); - - if (!t->Data) return; - - WriteStr (fp, "BEGIN_DATA\n"); - - t->nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS")); - - for (i = 0; i < t-> nPatches; i++) { - - WriteStr(fp, " "); - - for (j = 0; j < t->nSamples; j++) { - - char *ptr = t->Data[i*t->nSamples+j]; - - if (ptr == NULL) WriteStr(fp, "\"\""); - else { - // If value contains whitespace, enclose within quote - - if (strchr(ptr, ' ') != NULL) { - - WriteStr(fp, "\""); - WriteStr(fp, ptr); - WriteStr(fp, "\""); - } - else - WriteStr(fp, ptr); - } - - WriteStr(fp, ((j == (t->nSamples-1)) ? "\n" : "\t")); - } - } - WriteStr (fp, "END_DATA\n"); -} - - - -// Saves whole file -cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName) -{ - SAVESTREAM sd; - cmsUInt32Number i; - cmsIT8* it8 = (cmsIT8*) hIT8; - - memset(&sd, 0, sizeof(sd)); - - sd.stream = fopen(cFileName, "wt"); - if (!sd.stream) return FALSE; - - for (i=0; i < it8 ->TablesCount; i++) { - - cmsIT8SetTable(hIT8, i); - WriteHeader(it8, &sd); - WriteDataFormat(&sd, it8); - WriteData(&sd, it8); - } - - if (fclose(sd.stream) != 0) return FALSE; - - return TRUE; -} - - -// Saves to memory -cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded) -{ - SAVESTREAM sd; - cmsUInt32Number i; - cmsIT8* it8 = (cmsIT8*) hIT8; - - memset(&sd, 0, sizeof(sd)); - - sd.stream = NULL; - sd.Base = (cmsUInt8Number*) MemPtr; - sd.Ptr = sd.Base; - - sd.Used = 0; - - if (sd.Base) - sd.Max = *BytesNeeded; // Write to memory? - else - sd.Max = 0; // Just counting the needed bytes - - for (i=0; i < it8 ->TablesCount; i++) { - - cmsIT8SetTable(hIT8, i); - WriteHeader(it8, &sd); - WriteDataFormat(&sd, it8); - WriteData(&sd, it8); - } - - sd.Used++; // The \0 at the very end - - if (sd.Base) - *sd.Ptr = 0; - - *BytesNeeded = sd.Used; - - return TRUE; -} - - -// -------------------------------------------------------------- Higer level parsing - -static -cmsBool DataFormatSection(cmsIT8* it8) -{ - int iField = 0; - TABLE* t = GetTable(it8); - - InSymbol(it8); // Eats "BEGIN_DATA_FORMAT" - CheckEOLN(it8); - - while (it8->sy != SEND_DATA_FORMAT && - it8->sy != SEOLN && - it8->sy != SEOF && - it8->sy != SSYNERROR) { - - if (it8->sy != SIDENT) { - - return SynError(it8, "Sample type expected"); - } - - if (!SetDataFormat(it8, iField, it8->id)) return FALSE; - iField++; - - InSymbol(it8); - SkipEOLN(it8); - } - - SkipEOLN(it8); - Skip(it8, SEND_DATA_FORMAT); - SkipEOLN(it8); - - if (iField != t ->nSamples) { - SynError(it8, "Count mismatch. NUMBER_OF_FIELDS was %d, found %d\n", t ->nSamples, iField); - - - } - - return TRUE; -} - - - -static -cmsBool DataSection (cmsIT8* it8) -{ - int iField = 0; - int iSet = 0; - char Buffer[256]; - TABLE* t = GetTable(it8); - - InSymbol(it8); // Eats "BEGIN_DATA" - CheckEOLN(it8); - - if (!t->Data) - AllocateDataSet(it8); - - while (it8->sy != SEND_DATA && it8->sy != SEOF) - { - if (iField >= t -> nSamples) { - iField = 0; - iSet++; - - } - - if (it8->sy != SEND_DATA && it8->sy != SEOF) { - - if (!GetVal(it8, Buffer, 255, "Sample data expected")) - return FALSE; - - if (!SetData(it8, iSet, iField, Buffer)) - return FALSE; - - iField++; - - InSymbol(it8); - SkipEOLN(it8); - } - } - - SkipEOLN(it8); - Skip(it8, SEND_DATA); - SkipEOLN(it8); - - // Check for data completion. - - if ((iSet+1) != t -> nPatches) - return SynError(it8, "Count mismatch. NUMBER_OF_SETS was %d, found %d\n", t ->nPatches, iSet+1); - - return TRUE; -} - - - - -static -cmsBool HeaderSection(cmsIT8* it8) -{ - char VarName[MAXID]; - char Buffer[MAXSTR]; - KEYVALUE* Key; - - while (it8->sy != SEOF && - it8->sy != SSYNERROR && - it8->sy != SBEGIN_DATA_FORMAT && - it8->sy != SBEGIN_DATA) { - - - switch (it8 -> sy) { - - case SKEYWORD: - InSymbol(it8); - if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE; - if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE; - InSymbol(it8); - break; - - - case SDATA_FORMAT_ID: - InSymbol(it8); - if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE; - if (!AddAvailableSampleID(it8, Buffer)) return FALSE; - InSymbol(it8); - break; - - - case SIDENT: - strncpy(VarName, it8->id, MAXID-1); - VarName[MAXID-1] = 0; - - if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) { - -#ifdef CMS_STRICT_CGATS - return SynError(it8, "Undefined keyword '%s'", VarName); -#else - Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); - if (Key == NULL) return FALSE; -#endif - } - - InSymbol(it8); - if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE; - - if(Key->WriteAs != WRITE_PAIR) { - AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, - (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); - } - else { - const char *Subkey; - char *Nextkey; - if (it8->sy != SSTRING) - return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); - - // chop the string as a list of "subkey, value" pairs, using ';' as a separator - for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) - { - char *Value, *temp; - - // identify token pair boundary - Nextkey = (char*) strchr(Subkey, ';'); - if(Nextkey) - *Nextkey++ = '\0'; - - // for each pair, split the subkey and the value - Value = (char*) strrchr(Subkey, ','); - if(Value == NULL) - return SynError(it8, "Invalid value for property '%s'.", VarName); - - // gobble the spaces before the coma, and the coma itself - temp = Value++; - do *temp-- = '\0'; while(temp >= Subkey && *temp == ' '); - - // gobble any space at the right - temp = Value + strlen(Value) - 1; - while(*temp == ' ') *temp-- = '\0'; - - // trim the strings from the left - Subkey += strspn(Subkey, " "); - Value += strspn(Value, " "); - - if(Subkey[0] == 0 || Value[0] == 0) - return SynError(it8, "Invalid value for property '%s'.", VarName); - AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); - } - } - - InSymbol(it8); - break; - - - case SEOLN: break; - - default: - return SynError(it8, "expected keyword or identifier"); - } - - SkipEOLN(it8); - } - - return TRUE; - -} - - -static -void ReadType(cmsIT8* it8, char* SheetTypePtr) -{ - // First line is a very special case. - - while (isseparator(it8->ch)) - NextCh(it8); - - while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) { - - *SheetTypePtr++= (char) it8 ->ch; - NextCh(it8); - } - - *SheetTypePtr = 0; -} - - -static -cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet) -{ - char* SheetTypePtr = it8 ->Tab[0].SheetType; - - if (nosheet == 0) { - ReadType(it8, SheetTypePtr); - } - - InSymbol(it8); - - SkipEOLN(it8); - - while (it8-> sy != SEOF && - it8-> sy != SSYNERROR) { - - switch (it8 -> sy) { - - case SBEGIN_DATA_FORMAT: - if (!DataFormatSection(it8)) return FALSE; - break; - - case SBEGIN_DATA: - - if (!DataSection(it8)) return FALSE; - - if (it8 -> sy != SEOF) { - - AllocTable(it8); - it8 ->nTable = it8 ->TablesCount - 1; - - // Read sheet type if present. We only support identifier and string. - // <ident> <eoln> is a type string - // anything else, is not a type string - if (nosheet == 0) { - - if (it8 ->sy == SIDENT) { - - // May be a type sheet or may be a prop value statement. We cannot use insymbol in - // this special case... - while (isseparator(it8->ch)) - NextCh(it8); - - // If a newline is found, then this is a type string - if (it8 ->ch == '\n' || it8->ch == '\r') { - - cmsIT8SetSheetType(it8, it8 ->id); - InSymbol(it8); - } - else - { - // It is not. Just continue - cmsIT8SetSheetType(it8, ""); - } - } - else - // Validate quoted strings - if (it8 ->sy == SSTRING) { - cmsIT8SetSheetType(it8, it8 ->str); - InSymbol(it8); - } - } - - } - break; - - case SEOLN: - SkipEOLN(it8); - break; - - default: - if (!HeaderSection(it8)) return FALSE; - } - - } - - return (it8 -> sy != SSYNERROR); -} - - - -// Init usefull pointers - -static -void CookPointers(cmsIT8* it8) -{ - int idField, i; - char* Fld; - cmsUInt32Number j; - cmsUInt32Number nOldTable = it8 ->nTable; - - for (j=0; j < it8 ->TablesCount; j++) { - - TABLE* t = it8 ->Tab + j; - - t -> SampleID = 0; - it8 ->nTable = j; - - for (idField = 0; idField < t -> nSamples; idField++) - { - if (t ->DataFormat == NULL){ - SynError(it8, "Undefined DATA_FORMAT"); - return; - } - - Fld = t->DataFormat[idField]; - if (!Fld) continue; - - - if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) { - - t -> SampleID = idField; - - for (i=0; i < t -> nPatches; i++) { - - char *Data = GetData(it8, i, idField); - if (Data) { - char Buffer[256]; - - strncpy(Buffer, Data, 255); - Buffer[255] = 0; - - if (strlen(Buffer) <= strlen(Data)) - strcpy(Data, Buffer); - else - SetData(it8, i, idField, Buffer); - - } - } - - } - - // "LABEL" is an extension. It keeps references to forward tables - - if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) { - - // Search for table references... - for (i=0; i < t -> nPatches; i++) { - - char *Label = GetData(it8, i, idField); - - if (Label) { - - cmsUInt32Number k; - - // This is the label, search for a table containing - // this property - - for (k=0; k < it8 ->TablesCount; k++) { - - TABLE* Table = it8 ->Tab + k; - KEYVALUE* p; - - if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) { - - // Available, keep type and table - char Buffer[256]; - - char *Type = p ->Value; - int nTable = (int) k; - - snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type ); - - SetData(it8, i, idField, Buffer); - } - } - - - } - - } - - - } - - } - } - - it8 ->nTable = nOldTable; -} - -// Try to infere if the file is a CGATS/IT8 file at all. Read first line -// that should be something like some printable characters plus a \n -// returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line? -static -int IsMyBlock(cmsUInt8Number* Buffer, int n) -{ - int words = 1, space = 0, quot = 0; - int i; - - if (n < 10) return 0; // Too small - - if (n > 132) - n = 132; - - for (i = 1; i < n; i++) { - - switch(Buffer[i]) - { - case '\n': - case '\r': - return ((quot == 1) || (words > 2)) ? 0 : words; - case '\t': - case ' ': - if(!quot && !space) - space = 1; - break; - case '\"': - quot = !quot; - break; - default: - if (Buffer[i] < 32) return 0; - if (Buffer[i] > 127) return 0; - words += space; - space = 0; - break; - } - } - - return 0; -} - - -static -cmsBool IsMyFile(const char* FileName) -{ - FILE *fp; - cmsUInt32Number Size; - cmsUInt8Number Ptr[133]; - - fp = fopen(FileName, "rt"); - if (!fp) { - cmsSignalError(0, cmsERROR_FILE, "File '%s' not found", FileName); - return FALSE; - } - - Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp); - - if (fclose(fp) != 0) - return FALSE; - - Ptr[Size] = '\0'; - - return IsMyBlock(Ptr, Size); -} - -// ---------------------------------------------------------- Exported routines - - -cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len) -{ - cmsHANDLE hIT8; - cmsIT8* it8; - int type; - - _cmsAssert(Ptr != NULL); - _cmsAssert(len != 0); - - type = IsMyBlock((cmsUInt8Number*)Ptr, len); - if (type == 0) return NULL; - - hIT8 = cmsIT8Alloc(ContextID); - if (!hIT8) return NULL; - - it8 = (cmsIT8*) hIT8; - it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1); - - strncpy(it8 ->MemoryBlock, (const char*) Ptr, len); - it8 ->MemoryBlock[len] = 0; - - strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH-1); - it8-> Source = it8 -> MemoryBlock; - - if (!ParseIT8(it8, type-1)) { - - cmsIT8Free(hIT8); - return FALSE; - } - - CookPointers(it8); - it8 ->nTable = 0; - - _cmsFree(ContextID, it8->MemoryBlock); - it8 -> MemoryBlock = NULL; - - return hIT8; - - -} - - -cmsHANDLE CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName) -{ - - cmsHANDLE hIT8; - cmsIT8* it8; - int type; - - _cmsAssert(cFileName != NULL); - - type = IsMyFile(cFileName); - if (type == 0) return NULL; - - hIT8 = cmsIT8Alloc(ContextID); - it8 = (cmsIT8*) hIT8; - if (!hIT8) return NULL; - - - it8 ->FileStack[0]->Stream = fopen(cFileName, "rt"); - - if (!it8 ->FileStack[0]->Stream) { - cmsIT8Free(hIT8); - return NULL; - } - - - strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1); - it8->FileStack[0]->FileName[cmsMAX_PATH-1] = 0; - - if (!ParseIT8(it8, type-1)) { - - fclose(it8 ->FileStack[0]->Stream); - cmsIT8Free(hIT8); - return NULL; - } - - CookPointers(it8); - it8 ->nTable = 0; - - if (fclose(it8 ->FileStack[0]->Stream)!= 0) { - cmsIT8Free(hIT8); - return NULL; - } - - return hIT8; - -} - -int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - TABLE* t; - - _cmsAssert(hIT8 != NULL); - - t = GetTable(it8); - - if (SampleNames) - *SampleNames = t -> DataFormat; - return t -> nSamples; -} - - -cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - KEYVALUE* p; - cmsUInt32Number n; - char **Props; - TABLE* t; - - _cmsAssert(hIT8 != NULL); - - t = GetTable(it8); - - // Pass#1 - count properties - - n = 0; - for (p = t -> HeaderList; p != NULL; p = p->Next) { - n++; - } - - - Props = (char **) AllocChunk(it8, sizeof(char *) * n); - - // Pass#2 - Fill pointers - n = 0; - for (p = t -> HeaderList; p != NULL; p = p->Next) { - Props[n++] = p -> Keyword; - } - - *PropertyNames = Props; - return n; -} - -cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - KEYVALUE *p, *tmp; - cmsUInt32Number n; - const char **Props; - TABLE* t; - - _cmsAssert(hIT8 != NULL); - - - t = GetTable(it8); - - if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) { - *SubpropertyNames = 0; - return 0; - } - - // Pass#1 - count properties - - n = 0; - for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) { - if(tmp->Subkey != NULL) - n++; - } - - - Props = (const char **) AllocChunk(it8, sizeof(char *) * n); - - // Pass#2 - Fill pointers - n = 0; - for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) { - if(tmp->Subkey != NULL) - Props[n++] = p ->Subkey; - } - - *SubpropertyNames = Props; - return n; -} - -static -int LocatePatch(cmsIT8* it8, const char* cPatch) -{ - int i; - const char *data; - TABLE* t = GetTable(it8); - - for (i=0; i < t-> nPatches; i++) { - - data = GetData(it8, i, t->SampleID); - - if (data != NULL) { - - if (cmsstrcasecmp(data, cPatch) == 0) - return i; - } - } - - // SynError(it8, "Couldn't find patch '%s'\n", cPatch); - return -1; -} - - -static -int LocateEmptyPatch(cmsIT8* it8) -{ - int i; - const char *data; - TABLE* t = GetTable(it8); - - for (i=0; i < t-> nPatches; i++) { - - data = GetData(it8, i, t->SampleID); - - if (data == NULL) - return i; - - } - - return -1; -} - -static -int LocateSample(cmsIT8* it8, const char* cSample) -{ - int i; - const char *fld; - TABLE* t = GetTable(it8); - - for (i=0; i < t->nSamples; i++) { - - fld = GetDataFormat(it8, i); - if (cmsstrcasecmp(fld, cSample) == 0) - return i; - } - - return -1; - -} - - -int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - _cmsAssert(hIT8 != NULL); - - return LocateSample(it8, cSample); -} - - - -const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - _cmsAssert(hIT8 != NULL); - - return GetData(it8, row, col); -} - - -cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col) -{ - const char* Buffer; - - Buffer = cmsIT8GetDataRowCol(hIT8, row, col); - - if (Buffer == NULL) return 0.0; - - return ParseFloatNumber(Buffer); -} - - -cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, const char* Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - _cmsAssert(hIT8 != NULL); - - return SetData(it8, row, col, Val); -} - - -cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFloat64Number Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - char Buff[256]; - - _cmsAssert(hIT8 != NULL); - - sprintf(Buff, it8->DoubleFormatter, Val); - - return SetData(it8, row, col, Buff); -} - - - -const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - int iField, iSet; - - _cmsAssert(hIT8 != NULL); - - iField = LocateSample(it8, cSample); - if (iField < 0) { - return NULL; - } - - iSet = LocatePatch(it8, cPatch); - if (iSet < 0) { - return NULL; - } - - return GetData(it8, iSet, iField); -} - - -cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE it8, const char* cPatch, const char* cSample) -{ - const char* Buffer; - - Buffer = cmsIT8GetData(it8, cPatch, cSample); - - return ParseFloatNumber(Buffer); -} - - - -cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - int iField, iSet; - TABLE* t; - - _cmsAssert(hIT8 != NULL); - - t = GetTable(it8); - - iField = LocateSample(it8, cSample); - - if (iField < 0) - return FALSE; - - if (t-> nPatches == 0) { - - AllocateDataFormat(it8); - AllocateDataSet(it8); - CookPointers(it8); - } - - if (cmsstrcasecmp(cSample, "SAMPLE_ID") == 0) { - - iSet = LocateEmptyPatch(it8); - if (iSet < 0) { - return SynError(it8, "Couldn't add more patches '%s'\n", cPatch); - } - - iField = t -> SampleID; - } - else { - iSet = LocatePatch(it8, cPatch); - if (iSet < 0) { - return FALSE; - } - } - - return SetData(it8, iSet, iField, Val); -} - - -cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch, - const char* cSample, - cmsFloat64Number Val) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - char Buff[256]; - - _cmsAssert(hIT8 != NULL); - - snprintf(Buff, 255, it8->DoubleFormatter, Val); - return cmsIT8SetData(hIT8, cPatch, cSample, Buff); -} - -// Buffer should get MAXSTR at least - -const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - TABLE* t; - char* Data; - - _cmsAssert(hIT8 != NULL); - - t = GetTable(it8); - Data = GetData(it8, nPatch, t->SampleID); - - if (!Data) return NULL; - if (!buffer) return Data; - - strncpy(buffer, Data, MAXSTR-1); - buffer[MAXSTR-1] = 0; - return buffer; -} - -int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch) -{ - _cmsAssert(hIT8 != NULL); - - return LocatePatch((cmsIT8*)hIT8, cPatch); -} - -cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - _cmsAssert(hIT8 != NULL); - - return it8 ->TablesCount; -} - -// This handles the "LABEL" extension. -// Label, nTable, Type - -int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType) -{ - const char* cLabelFld; - char Type[256], Label[256]; - int nTable; - - _cmsAssert(hIT8 != NULL); - - if (cField != NULL && *cField == 0) - cField = "LABEL"; - - if (cField == NULL) - cField = "LABEL"; - - cLabelFld = cmsIT8GetData(hIT8, cSet, cField); - if (!cLabelFld) return -1; - - if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3) - return -1; - - if (ExpectedType != NULL && *ExpectedType == 0) - ExpectedType = NULL; - - if (ExpectedType) { - - if (cmsstrcasecmp(Type, ExpectedType) != 0) return -1; - } - - return cmsIT8SetTable(hIT8, nTable); -} - - -cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - int pos; - - _cmsAssert(hIT8 != NULL); - - pos = LocateSample(it8, cSample); - if(pos == -1) - return FALSE; - - it8->Tab[it8->nTable].SampleID = pos; - return TRUE; -} - - -void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter) -{ - cmsIT8* it8 = (cmsIT8*) hIT8; - - _cmsAssert(hIT8 != NULL); - - if (Formatter == NULL) - strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); - else - strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter)); - - it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0; -} |