//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2010 Marti Maria Saguer
+// Copyright (c) 1998-2016 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
+// 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
+// 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
+// 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.
//
//---------------------------------------------------------------------------------
// IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
-#define MAXID 128 // Max lenght of identifier
-#define MAXSTR 1024 // Max lenght of string
+#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 DIR_CHAR '/'
#endif
+
// Symbols
-typedef enum {
+typedef enum {
- SNONE,
+ SUNDEFINED,
SINUM, // Integer
SDNUM, // Real
SIDENT, // Identifier
// How to write the value
-typedef enum {
+typedef enum {
WRITE_UNCOOKED,
- WRITE_STRINGIFY,
+ WRITE_STRINGIFY,
WRITE_HEXADECIMAL,
WRITE_BINARY,
WRITE_PAIR
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
+ char** Data; // The binary stream
} TABLE;
FILE* Stream; // File stream or NULL if holded in memory
} FILECTX;
-// This struct hold all information about an open IT8 handler.
+// This struct hold all information about an open IT8 handler.
typedef struct {
- char SheetType[MAXSTR]; // The first row of the IT8 (the type)
cmsUInt32Number TablesCount; // How many tables in this stream
cmsUInt32Number nTable; // The actual table
// Parser state machine
SYMBOL sy; // Current symbol
int ch; // Current character
-
+
int inum; // integer value
cmsFloat64Number dnum; // real value
char id[MAXID]; // identifier
// Allowed keywords & datasets. They have visibility on whole stream
KEYVALUE* ValidKeywords;
KEYVALUE* ValidSampleID;
-
+
char* Source; // Points to loc. being parsed
int lineno; // line counter for error reporting
-
+
FILECTX* FileStack[MAXINCLUDE]; // Stack of files being parsed
int IncludeSP; // Include Stack Pointer
// The keyword->symbol translation table. Sorting is required.
static const KEYWORD TabKeys[] = {
-
+
{"$INCLUDE", SINCLUDE}, // This is an extension!
{".INCLUDE", SINCLUDE}, // This is an extension!
// 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,
+ {"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
+ {"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
+ {"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
+ {"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
+ // 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
+ // 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
+ {"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.
// 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.
+ "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
"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_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
#define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *))
-//Forward declaration of some internal functions
+//Forward declaration of some internal functions
static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
-// Checks if c is a separator
+// Checks whatever c is a separator
static
cmsBool isseparator(int c)
{
- return (c == ' ') || (c == '\t') || (c == '\r');
+ return (c == ' ') || (c == '\t') ;
}
-// Checks whatever if c is a valid identifier char
-static
+// 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 if c is a valid identifier middle char.
+// Checks whatsever c is a valid identifier middle char.
static
cmsBool isidchar(int c)
{
return isalnum(c) || ismiddle(c);
}
-// Checks whatsever if c is a valid identifier first char.
+// Checks whatsever c is a valid identifier first char.
static
cmsBool isfirstidchar(int c)
{
if(path == NULL)
return FALSE;
- if (path[0] == 0)
+ if (path[0] == 0)
return FALSE;
strncpy(ThreeChars, path, 3);
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
+static
cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen)
{
char *tail;
return TRUE;
}
- // No, search for last
- strncpy(buffer, basePath, MaxLen);
+ // No, search for last
+ strncpy(buffer, basePath, MaxLen);
buffer[MaxLen-1] = 0;
tail = strrchr(buffer, DIR_CHAR);
if (len >= MaxLen) return FALSE;
// No need to assure zero terminator over here
- strncpy(tail + 1, relPath, MaxLen - len);
+ strncpy(tail + 1, relPath, MaxLen - len);
- return TRUE;
+ return TRUE;
}
static
const char* NoMeta(const char* str)
{
- if (strchr(str, '%') != NULL)
+ if (strchr(str, '%') != NULL)
return "**** CORRUPTED FORMAT STRING ***";
return str;
} else
it8 ->ch = 0; // EOF
- }
+ }
}
else {
it8->ch = *it8->Source;
else l = x + 1;
}
- return SNONE;
+ return SUNDEFINED;
}
if (it8->ch == '.') { // Decimal point
cmsFloat64Number frac = 0.0; // fraction
- int prec = 0; // precision
+ int prec = 0; // precision
NextCh(it8); // Eats dec. point
}
}
+// 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
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;
+ if (key == SUNDEFINED) 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)) {
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 (it8 ->sy == SINUM) {
- sprintf(it8->id, "%d", it8->inum);
+ snprintf(it8->id, 127, "%d", it8->inum);
}
else {
- sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum);
+ snprintf(it8->id, 127, 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';
+
+ *idptr = '\0';
it8->sy = SIDENT;
}
return;
-
+
}
else
switch ((int) it8->ch) {
case -1:
it8->sy = SEOF;
break;
-
-
- // Next line
+
+
+ // 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')
+ while (it8->ch && it8->ch != '\n' && it8->ch != '\r')
NextCh(it8);
-
+
it8->sy = SCOMMENT;
break;
-
+
// String.
case '\'':
case '\"':
sng = it8->ch;
k = 0;
NextCh(it8);
-
+
while (k < MAXSTR && it8->ch != sng) {
-
+
if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1;
- else {
+ 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;
+ SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
+ return;
}
-
+
} while (it8->sy == SCOMMENT);
// Handle the include special token
// TODO: how to manage out-of-memory conditions?
}
- if (BuildAbsolutePath(it8->str,
- it8->FileStack[it8->IncludeSP]->FileName,
+ if (BuildAbsolutePath(it8->str,
+ it8->FileStack[it8->IncludeSP]->FileName,
FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
SynError(it8, "File path too long");
return;
it8->IncludeSP++;
it8 ->ch = ' ';
- InSymbol(it8);
+ InSymbol(it8);
}
-
+
}
// Checks end of line separator
{
switch (it8->sy) {
- case SIDENT: strncpy(Buffer, it8->id, max);
+ 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);
+ case SSTRING: strncpy(Buffer, it8->str, max);
Buffer[max-1] = 0;
break;
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;
}
}
if (it8->MemoryBlock)
- _cmsFree(it8 ->ContextID, it8->MemoryBlock);
+ _cmsFree(it8 ->ContextID, it8->MemoryBlock);
_cmsFree(it8 ->ContextID, it8);
}
cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used;
cmsUInt8Number* ptr;
- size = _cmsALIGNLONG(size);
+ size = _cmsALIGNMEM(size);
if (size > Free) {
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;
-
+
}
if (ptr) strncpy (ptr, str, Size-1);
return ptr;
-}
+}
// Searches through linked list
if (*Key != '#') { // Comments are ignored
if (cmsstrcasecmp(Key, p->Keyword) == 0)
- break;
- }
+ break;
}
+ }
if (p == NULL)
return FALSE;
for (; p != NULL; p = p->NextSubkey) {
+ if (p ->Subkey == NULL) continue;
+
if (LastPtr) *LastPtr = p;
if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
- return TRUE;
- }
+ return TRUE;
+ }
return FALSE;
}
KEYVALUE* last;
- // Check if property is already in list
+ // 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);
+ // return SynError(it8, "duplicate key <%s>", Key);
}
else {
p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE));
if (p == NULL)
{
- SynError(it8, "AddToList: out of memory");
+ SynError(it8, "AddToList: out of memory");
return NULL;
}
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)
+ while (last->Next != NULL)
last = last->Next;
}
t->HeaderList = NULL;
t->DataFormat = NULL;
t->Data = NULL;
-
+
it8 ->TablesCount++;
}
it8 ->nTable = nTable;
- return nTable;
+ return (cmsInt32Number) nTable;
}
cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
{
cmsIT8* it8;
- int i;
+ 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->Allocator.BlockSize = 0;
it8->ValidKeywords = NULL;
it8->ValidSampleID = NULL;
- it8 -> sy = SNONE;
+ it8 -> sy = SUNDEFINED;
it8 -> ch = ' ';
it8 -> Source = NULL;
it8 -> inum = 0;
it8 -> lineno = 1;
strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
- strcpy(it8->SheetType, "CGATS.17");
+ cmsIT8SetSheetType((cmsHANDLE) it8, "CGATS.17");
// Initialize predefined properties & data
-
+
for (i=0; i < NUMPREDEFINEDPROPS; i++)
AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as);
const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8)
{
- cmsIT8* it8 = (cmsIT8*) hIT8;
-
- return it8 ->SheetType;
-
+ return GetTable((cmsIT8*) hIT8)->SheetType;
}
cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type)
{
- cmsIT8* it8 = (cmsIT8*) hIT8;
+ TABLE* t = GetTable((cmsIT8*) hIT8);
- strncpy(it8 ->SheetType, Type, MAXSTR-1);
- it8 ->SheetType[MAXSTR-1] = 0;
+ strncpy(t ->SheetType, Type, MAXSTR-1);
+ t ->SheetType[MAXSTR-1] = 0;
return TRUE;
}
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)
{
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;
+ snprintf(Buffer, 1023, 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, "%d", Val);
- return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
+ snprintf(Buffer, 1023, "%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;
-
+ cmsIT8* it8 = (cmsIT8*) hIT8;
+
return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL;
}
{
const char *v = cmsIT8GetProperty(hIT8, cProp);
- if (v) return atof(v);
- else return 0.0;
+ if (v == NULL) return 0.0;
+
+ return ParseFloatNumber(v);
}
const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey)
t -> nSamples = 10;
}
- t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *));
+ t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
if (t->DataFormat == NULL) {
SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
SynError(it8, "More than NUMBER_OF_FIELDS fields.");
return FALSE;
}
-
- if (t->DataFormat) {
+
+ if (t->DataFormat) {
t->DataFormat[n] = AllocString(it8, label);
}
t-> nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
- t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*));
+ 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");
TABLE* t = GetTable(it8);
int nSamples = t -> nSamples;
int nPatches = t -> nPatches;
-
+
if (nSet >= nPatches || nField >= nSamples)
return NULL;
if (nSet > t -> nPatches || nSet < 0) {
- return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches);
+ 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;
}
{
cmsUInt32Number len;
- if (str == NULL)
+ if (str == NULL)
str = " ";
-
- // Lenghth to write
+
+ // 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;
}
-
- }
+
+ }
}
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);
+ Writef(fp, "%c", *Pt);
if (*Pt == '\n') {
WriteStr(fp, "# ");
}
}
-
+
WriteStr(fp, "\n#\n");
continue;
}
switch (p ->WriteAs) {
case WRITE_UNCOOKED:
- Writef(fp, "\t%s", p ->Value);
+ Writef(fp, "\t%s", p ->Value);
break;
case WRITE_STRINGIFY:
// Saves whole file
cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
{
- SAVESTREAM sd;
+ SAVESTREAM sd;
cmsUInt32Number i;
cmsIT8* it8 = (cmsIT8*) hIT8;
sd.stream = fopen(cFileName, "wt");
if (!sd.stream) return FALSE;
-
- WriteStr(&sd, it8->SheetType);
- WriteStr(&sd, "\n");
+
for (i=0; i < it8 ->TablesCount; i++) {
cmsIT8SetTable(hIT8, i);
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;
+ SAVESTREAM sd;
cmsUInt32Number i;
cmsIT8* it8 = (cmsIT8*) hIT8;
sd.Used = 0;
- if (sd.Base)
+ if (sd.Base)
sd.Max = *BytesNeeded; // Write to memory?
- else
+ else
sd.Max = 0; // Just counting the needed bytes
-
- WriteStr(&sd, it8->SheetType);
- WriteStr(&sd, "\n");
+
for (i=0; i < it8 ->TablesCount; i++) {
- cmsIT8SetTable(hIT8, i);
- WriteHeader(it8, &sd);
- WriteDataFormat(&sd, it8);
- WriteData(&sd, it8);
+ 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;
+ *sd.Ptr = 0;
*BytesNeeded = sd.Used;
static
cmsBool DataFormatSection(cmsIT8* it8)
{
- int iField = 0;
+ int iField = 0;
TABLE* t = GetTable(it8);
InSymbol(it8); // Eats "BEGIN_DATA_FORMAT"
it8->sy != SEOLN &&
it8->sy != SEOF &&
it8->sy != SSYNERROR) {
-
+
if (it8->sy != SIDENT) {
-
- return SynError(it8, "Sample type expected");
+
+ return SynError(it8, "Sample type expected");
}
-
+
if (!SetDataFormat(it8, iField, it8->id)) return FALSE;
iField++;
-
+
InSymbol(it8);
SkipEOLN(it8);
}
if (iField != t ->nSamples) {
SynError(it8, "Count mismatch. NUMBER_OF_FIELDS was %d, found %d\n", t ->nSamples, iField);
-
+
}
return TRUE;
if (iField >= t -> nSamples) {
iField = 0;
iSet++;
-
+
}
if (it8->sy != SEND_DATA && it8->sy != SEOF) {
return FALSE;
iField++;
-
+
InSymbol(it8);
- SkipEOLN(it8);
+ SkipEOLN(it8);
}
}
SkipEOLN(it8);
Skip(it8, SEND_DATA);
SkipEOLN(it8);
-
+
// Check for data completion.
if ((iSet+1) != t -> nPatches)
case SKEYWORD:
InSymbol(it8);
- if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE;
+ 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 (!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
+#ifdef CMS_STRICT_CGATS
return SynError(it8, "Undefined keyword '%s'", VarName);
#else
Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE;
if(Key->WriteAs != WRITE_PAIR) {
- AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
+ AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
(it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
}
else {
for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
{
char *Value, *temp;
-
+
// identify token pair boundary
Nextkey = (char*) strchr(Subkey, ';');
if(Nextkey)
// gobble any space at the right
temp = Value + strlen(Value) - 1;
- while(*temp == ' ') *temp-- = '\0';
+ while(*temp == ' ') *temp-- = '\0';
// trim the strings from the left
Subkey += strspn(Subkey, " ");
AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
}
}
-
+
InSymbol(it8);
break;
-
+
case SEOLN: break;
default:
static
-cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
+void ReadType(cmsIT8* it8, char* SheetTypePtr)
{
- char* SheetTypePtr = it8 ->SheetType;
-
- if (nosheet == 0) {
-
// 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 &&
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;
TABLE* t = it8 ->Tab + j;
t -> SampleID = 0;
- it8 ->nTable = j;
+ it8 ->nTable = j;
for (idField = 0; idField < t -> nSamples; idField++)
{
if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
- t -> SampleID = idField;
-
- for (i=0; i < t -> nPatches; i++) {
+ 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) {
-
+
+ if (Label) {
+
cmsUInt32Number k;
- // This is the label, search for a table containing
+ // This is the label, search for a table containing
// this property
for (k=0; k < it8 ->TablesCount; k++) {
char Buffer[256];
char *Type = p ->Value;
- int nTable = k;
+ int nTable = (int) k;
snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type );
-
+
SetData(it8, i, idField, Buffer);
}
}
// 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 cols = 1, space = 0, quot = 0;
+ int words = 1, space = 0, quot = 0;
int i;
- if (n < 10) return FALSE; // Too small
+ if (n < 10) return 0; // Too small
if (n > 132)
n = 132;
{
case '\n':
case '\r':
- return quot == 1 || cols > 2 ? 0 : cols;
+ return ((quot == 1) || (words > 2)) ? 0 : words;
case '\t':
case ' ':
if(!quot && !space)
default:
if (Buffer[i] < 32) return 0;
if (Buffer[i] > 127) return 0;
- cols += space;
+ words += space;
space = 0;
break;
}
}
- return FALSE;
-
+ return 0;
}
Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp);
- if (fclose(fp) != 0)
- return FALSE;
+ if (fclose(fp) != 0)
+ return FALSE;
Ptr[Size] = '\0';
cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len)
{
- cmsHANDLE hIT8;
+ cmsHANDLE hIT8;
cmsIT8* it8;
- int type;
+ int type;
- _cmsAssert(Ptr != NULL);
- _cmsAssert(len != 0);
+ _cmsAssert(Ptr != NULL);
+ _cmsAssert(len != 0);
type = IsMyBlock((cmsUInt8Number*)Ptr, len);
if (type == 0) return NULL;
-
+
hIT8 = cmsIT8Alloc(ContextID);
if (!hIT8) return NULL;
strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH-1);
it8-> Source = it8 -> MemoryBlock;
- if (!ParseIT8(it8, type-1)) {
-
- cmsIT8Free(hIT8);
- return FALSE;
+ if (!ParseIT8(it8, type-1)) {
+
+ cmsIT8Free(hIT8);
+ return FALSE;
}
CookPointers(it8);
cmsHANDLE CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName)
{
- cmsHANDLE hIT8;
+ cmsHANDLE hIT8;
cmsIT8* it8;
- int type;
-
- _cmsAssert(cFileName != NULL);
+ int type;
- type = IsMyFile(cFileName);
+ _cmsAssert(cFileName != NULL);
+
+ type = IsMyFile(cFileName);
if (type == 0) return NULL;
hIT8 = cmsIT8Alloc(ContextID);
- it8 = (cmsIT8*) hIT8;
+ it8 = (cmsIT8*) hIT8;
if (!hIT8) return NULL;
it8 ->FileStack[0]->Stream = fopen(cFileName, "rt");
- if (!it8 ->FileStack[0]->Stream) {
+ if (!it8 ->FileStack[0]->Stream) {
cmsIT8Free(hIT8);
return NULL;
}
-
- strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1);
+
+ strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1);
it8->FileStack[0]->FileName[cmsMAX_PATH-1] = 0;
- if (!ParseIT8(it8, type-1)) {
-
+ if (!ParseIT8(it8, type-1)) {
+
fclose(it8 ->FileStack[0]->Stream);
- cmsIT8Free(hIT8);
- return NULL;
+ cmsIT8Free(hIT8);
+ return NULL;
}
CookPointers(it8);
it8 ->nTable = 0;
- if (fclose(it8 ->FileStack[0]->Stream)!= 0) {
- cmsIT8Free(hIT8);
- return NULL;
- }
+ 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;
+ cmsIT8* it8 = (cmsIT8*) hIT8;
+ TABLE* t;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
- t = GetTable(it8);
+ t = GetTable(it8);
- if (SampleNames)
- *SampleNames = t -> DataFormat;
- return t -> nSamples;
+ if (SampleNames)
+ *SampleNames = t -> DataFormat;
+ return t -> nSamples;
}
cmsUInt32Number n;
char **Props;
TABLE* t;
-
- _cmsAssert(hIT8 != NULL);
- t = GetTable(it8);
+ _cmsAssert(hIT8 != NULL);
+
+ t = GetTable(it8);
// Pass#1 - count properties
cmsUInt32Number n;
const char **Props;
TABLE* t;
-
- _cmsAssert(hIT8 != NULL);
+
+ _cmsAssert(hIT8 != NULL);
- t = GetTable(it8);
+ t = GetTable(it8);
if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
*SubpropertyNames = 0;
for (i=0; i < t-> nPatches; i++) {
data = GetData(it8, i, t->SampleID);
-
+
if (data != NULL) {
if (cmsstrcasecmp(data, cPatch) == 0)
}
}
- // SynError(it8, "Couldn't find patch '%s'\n", cPatch);
+ // SynError(it8, "Couldn't find patch '%s'\n", cPatch);
return -1;
}
data = GetData(it8, i, t->SampleID);
- if (data == NULL)
+ if (data == NULL)
return i;
}
for (i=0; i < t->nSamples; i++) {
fld = GetDataFormat(it8, i);
- if (cmsstrcasecmp(fld, cSample) == 0)
- return i;
+ if (fld != NULL) {
+ if (cmsstrcasecmp(fld, cSample) == 0)
+ return i;
+ }
}
-
+
return -1;
}
{
cmsIT8* it8 = (cmsIT8*) hIT8;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
return LocateSample(it8, cSample);
}
{
cmsIT8* it8 = (cmsIT8*) hIT8;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
return GetData(it8, row, col);
}
const char* Buffer;
Buffer = cmsIT8GetDataRowCol(hIT8, row, col);
-
- if (Buffer) {
- return atof(Buffer);
-
- } else
- return 0;
+ 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);
+ _cmsAssert(hIT8 != NULL);
+
+ return SetData(it8, row, col, Val);
}
cmsIT8* it8 = (cmsIT8*) hIT8;
char Buff[256];
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
- sprintf(Buff, it8->DoubleFormatter, Val);
-
- return SetData(it8, row, col, Buff);
+ snprintf(Buff, 255, it8->DoubleFormatter, Val);
+
+ return SetData(it8, row, col, Buff);
}
-const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample)
+const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample)
{
cmsIT8* it8 = (cmsIT8*) hIT8;
int iField, iSet;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
iField = LocateSample(it8, cSample);
- if (iField < 0) {
+ if (iField < 0) {
return NULL;
}
iSet = LocatePatch(it8, cPatch);
- if (iSet < 0) {
+ if (iSet < 0) {
return NULL;
}
const char* Buffer;
Buffer = cmsIT8GetData(it8, cPatch, cSample);
-
- if (Buffer) {
- return atof(Buffer);
-
- } else {
-
- return 0;
- }
+ return ParseFloatNumber(Buffer);
}
cmsIT8* it8 = (cmsIT8*) hIT8;
int iField, iSet;
TABLE* t;
-
- _cmsAssert(hIT8 != NULL);
- t = GetTable(it8);
+ _cmsAssert(hIT8 != NULL);
+
+ t = GetTable(it8);
iField = LocateSample(it8, cSample);
- if (iField < 0)
+ if (iField < 0)
return FALSE;
if (t-> nPatches == 0) {
iSet = LocateEmptyPatch(it8);
if (iSet < 0) {
- return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);
+ return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);
}
iField = t -> SampleID;
cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch,
- const char* cSample,
- cmsFloat64Number Val)
+ const char* cSample,
+ cmsFloat64Number Val)
{
- cmsIT8* it8 = (cmsIT8*) hIT8;
- char Buff[256];
+ cmsIT8* it8 = (cmsIT8*) hIT8;
+ char Buff[256];
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
- snprintf(Buff, 255, it8->DoubleFormatter, Val);
- return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
+ 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;
+ cmsIT8* it8 = (cmsIT8*) hIT8;
+ TABLE* t;
+ char* Data;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
- t = GetTable(it8);
- Data = GetData(it8, nPatch, t->SampleID);
+ t = GetTable(it8);
+ Data = GetData(it8, nPatch, t->SampleID);
- if (!Data) return NULL;
- if (!buffer) return Data;
+ if (!Data) return NULL;
+ if (!buffer) return Data;
- strncpy(buffer, Data, MAXSTR-1);
- buffer[MAXSTR-1] = 0;
- return buffer;
+ strncpy(buffer, Data, MAXSTR-1);
+ buffer[MAXSTR-1] = 0;
+ return buffer;
}
int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch)
{
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
return LocatePatch((cmsIT8*)hIT8, cPatch);
}
cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8)
{
- cmsIT8* it8 = (cmsIT8*) hIT8;
+ cmsIT8* it8 = (cmsIT8*) hIT8;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
- return it8 ->TablesCount;
+ return it8 ->TablesCount;
}
-// This handles the "LABEL" extension.
+// 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)
+ if (cField == NULL)
cField = "LABEL";
- cLabelFld = cmsIT8GetData(hIT8, cSet, cField);
+ 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 (cmsstrcasecmp(Type, ExpectedType) != 0) return -1;
}
- return cmsIT8SetTable(hIT8, nTable);
+ return cmsIT8SetTable(hIT8, nTable);
}
cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample)
{
- cmsIT8* it8 = (cmsIT8*) hIT8;
- int pos;
+ cmsIT8* it8 = (cmsIT8*) hIT8;
+ int pos;
- _cmsAssert(hIT8 != NULL);
+ _cmsAssert(hIT8 != NULL);
- pos = LocateSample(it8, cSample);
- if(pos == -1)
- return FALSE;
+ pos = LocateSample(it8, cSample);
+ if(pos == -1)
+ return FALSE;
- it8->Tab[it8->nTable].SampleID = pos;
- return TRUE;
+ it8->Tab[it8->nTable].SampleID = pos;
+ return TRUE;
}
if (Formatter == NULL)
strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
else
- strcpy(it8->DoubleFormatter, Formatter);
+ strncpy(it8->DoubleFormatter, Formatter, sizeof(it8->DoubleFormatter));
+
+ it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
}