Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/lcms2/src/cmserr.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 //--------------------------------------------------------------------------------- | |
| 2 // | |
| 3 // Little Color Management System | |
| 4 // Copyright (c) 1998-2023 Marti Maria Saguer | |
| 5 // | |
| 6 // Permission is hereby granted, free of charge, to any person obtaining | |
| 7 // a copy of this software and associated documentation files (the "Software"), | |
| 8 // to deal in the Software without restriction, including without limitation | |
| 9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| 10 // and/or sell copies of the Software, and to permit persons to whom the Software | |
| 11 // is furnished to do so, subject to the following conditions: | |
| 12 // | |
| 13 // The above copyright notice and this permission notice shall be included in | |
| 14 // all copies or substantial portions of the Software. | |
| 15 // | |
| 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | |
| 18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
| 20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
| 21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
| 22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 23 // | |
| 24 //--------------------------------------------------------------------------------- | |
| 25 | |
| 26 #include "lcms2_internal.h" | |
| 27 | |
| 28 | |
| 29 // This function is here to help applications to prevent mixing lcms versions on header and shared objects. | |
| 30 int CMSEXPORT cmsGetEncodedCMMversion(void) | |
| 31 { | |
| 32 return LCMS_VERSION; | |
| 33 } | |
| 34 | |
| 35 // I am so tired about incompatibilities on those functions that here are some replacements | |
| 36 // that hopefully would be fully portable. | |
| 37 | |
| 38 // compare two strings ignoring case | |
| 39 int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2) | |
| 40 { | |
| 41 CMSREGISTER const unsigned char *us1 = (const unsigned char *)s1, | |
| 42 *us2 = (const unsigned char *)s2; | |
| 43 | |
| 44 while (toupper(*us1) == toupper(*us2++)) | |
| 45 if (*us1++ == '\0') | |
| 46 return 0; | |
| 47 | |
| 48 return (toupper(*us1) - toupper(*--us2)); | |
| 49 } | |
| 50 | |
| 51 // long int because C99 specifies ftell in such way (7.19.9.2) | |
| 52 long int CMSEXPORT cmsfilelength(FILE* f) | |
| 53 { | |
| 54 long int p , n; | |
| 55 | |
| 56 p = ftell(f); // register current file position | |
| 57 if (p == -1L) | |
| 58 return -1L; | |
| 59 | |
| 60 if (fseek(f, 0, SEEK_END) != 0) { | |
| 61 return -1L; | |
| 62 } | |
| 63 | |
| 64 n = ftell(f); | |
| 65 fseek(f, p, SEEK_SET); // file position restored | |
| 66 | |
| 67 return n; | |
| 68 } | |
| 69 | |
| 70 | |
| 71 // Memory handling ------------------------------------------------------------------ | |
| 72 // | |
| 73 // This is the interface to low-level memory management routines. By default a simple | |
| 74 // wrapping to malloc/free/realloc is provided, although there is a limit on the max | |
| 75 // amount of memory that can be reclaimed. This is mostly as a safety feature to prevent | |
| 76 // bogus or evil code to allocate huge blocks that otherwise lcms would never need. | |
| 77 | |
| 78 #define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U)) | |
| 79 | |
| 80 // User may override this behaviour by using a memory plug-in, which basically replaces | |
| 81 // the default memory management functions. In this case, no check is performed and it | |
| 82 // is up to the plug-in writer to keep in the safe side. There are only three functions | |
| 83 // required to be implemented: malloc, realloc and free, although the user may want to | |
| 84 // replace the optional mallocZero, calloc and dup as well. | |
| 85 | |
| 86 cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin); | |
| 87 | |
| 88 // ********************************************************************************* | |
| 89 | |
| 90 // This is the default memory allocation function. It does a very coarse | |
| 91 // check of amount of memory, just to prevent exploits | |
| 92 static | |
| 93 void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size) | |
| 94 { | |
| 95 // Never allow 0 or over maximum | |
| 96 if (size == 0 || size > MAX_MEMORY_FOR_ALLOC) return NULL; | |
| 97 | |
| 98 return (void*) malloc(size); | |
| 99 | |
| 100 cmsUNUSED_PARAMETER(ContextID); | |
| 101 } | |
| 102 | |
| 103 // Generic allocate & zero | |
| 104 static | |
| 105 void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size) | |
| 106 { | |
| 107 void *pt = _cmsMalloc(ContextID, size); | |
| 108 if (pt == NULL) return NULL; | |
| 109 | |
| 110 memset(pt, 0, size); | |
| 111 return pt; | |
| 112 } | |
| 113 | |
| 114 | |
| 115 // The default free function. The only check proformed is against NULL pointers | |
| 116 static | |
| 117 void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr) | |
| 118 { | |
| 119 // free(NULL) is defined a no-op by C99, therefore it is safe to | |
| 120 // avoid the check, but it is here just in case... | |
| 121 | |
| 122 if (Ptr) free(Ptr); | |
| 123 | |
| 124 cmsUNUSED_PARAMETER(ContextID); | |
| 125 } | |
| 126 | |
| 127 // The default realloc function. Again it checks for exploits. If Ptr is NULL, | |
| 128 // realloc behaves the same way as malloc and allocates a new block of size bytes. | |
| 129 static | |
| 130 void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size) | |
| 131 { | |
| 132 | |
| 133 if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never realloc over 512Mb | |
| 134 | |
| 135 return realloc(Ptr, size); | |
| 136 | |
| 137 cmsUNUSED_PARAMETER(ContextID); | |
| 138 } | |
| 139 | |
| 140 | |
| 141 // The default calloc function. Allocates an array of num elements, each one of size bytes | |
| 142 // all memory is initialized to zero. | |
| 143 static | |
| 144 void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) | |
| 145 { | |
| 146 cmsUInt32Number Total = num * size; | |
| 147 | |
| 148 // Preserve calloc behaviour | |
| 149 if (Total == 0) return NULL; | |
| 150 | |
| 151 // Safe check for overflow. | |
| 152 if (num >= UINT_MAX / size) return NULL; | |
| 153 | |
| 154 // Check for overflow | |
| 155 if (Total < num || Total < size) { | |
| 156 return NULL; | |
| 157 } | |
| 158 | |
| 159 if (Total > MAX_MEMORY_FOR_ALLOC) return NULL; // Never alloc over 512Mb | |
| 160 | |
| 161 return _cmsMallocZero(ContextID, Total); | |
| 162 } | |
| 163 | |
| 164 // Generic block duplication | |
| 165 static | |
| 166 void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size) | |
| 167 { | |
| 168 void* mem; | |
| 169 | |
| 170 if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb | |
| 171 | |
| 172 mem = _cmsMalloc(ContextID, size); | |
| 173 | |
| 174 if (mem != NULL && Org != NULL) | |
| 175 memmove(mem, Org, size); | |
| 176 | |
| 177 return mem; | |
| 178 } | |
| 179 | |
| 180 | |
| 181 // Pointers to memory manager functions in Context0 | |
| 182 _cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn, | |
| 183 _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn | |
| 184 }; | |
| 185 | |
| 186 | |
| 187 // Reset and duplicate memory manager | |
| 188 void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) | |
| 189 { | |
| 190 _cmsAssert(ctx != NULL); | |
| 191 | |
| 192 if (src != NULL) { | |
| 193 | |
| 194 // Duplicate | |
| 195 ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType)); | |
| 196 } | |
| 197 else { | |
| 198 | |
| 199 // To reset it, we use the default allocators, which cannot be overridden | |
| 200 ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager; | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 // Auxiliary to fill memory management functions from plugin (or context 0 defaults) | |
| 205 void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr) | |
| 206 { | |
| 207 if (Plugin == NULL) { | |
| 208 | |
| 209 memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk)); | |
| 210 } | |
| 211 else { | |
| 212 | |
| 213 ptr ->MallocPtr = Plugin -> MallocPtr; | |
| 214 ptr ->FreePtr = Plugin -> FreePtr; | |
| 215 ptr ->ReallocPtr = Plugin -> ReallocPtr; | |
| 216 | |
| 217 // Make sure we revert to defaults | |
| 218 ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn; | |
| 219 ptr ->CallocPtr = _cmsCallocDefaultFn; | |
| 220 ptr ->DupPtr = _cmsDupDefaultFn; | |
| 221 | |
| 222 if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr; | |
| 223 if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr; | |
| 224 if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr; | |
| 225 | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 | |
| 230 // Plug-in replacement entry | |
| 231 cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data) | |
| 232 { | |
| 233 cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data; | |
| 234 _cmsMemPluginChunkType* ptr; | |
| 235 | |
| 236 // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure. | |
| 237 // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the | |
| 238 // context internal data should be malloc'ed by using those functions. | |
| 239 if (Data == NULL) { | |
| 240 | |
| 241 struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID; | |
| 242 | |
| 243 // Return to the default allocators | |
| 244 if (ContextID != NULL) { | |
| 245 ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager; | |
| 246 } | |
| 247 return TRUE; | |
| 248 } | |
| 249 | |
| 250 // Check for required callbacks | |
| 251 if (Plugin -> MallocPtr == NULL || | |
| 252 Plugin -> FreePtr == NULL || | |
| 253 Plugin -> ReallocPtr == NULL) return FALSE; | |
| 254 | |
| 255 // Set replacement functions | |
| 256 ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 257 if (ptr == NULL) | |
| 258 return FALSE; | |
| 259 | |
| 260 _cmsInstallAllocFunctions(Plugin, ptr); | |
| 261 return TRUE; | |
| 262 } | |
| 263 | |
| 264 // Generic allocate | |
| 265 void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size) | |
| 266 { | |
| 267 _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 268 return ptr ->MallocPtr(ContextID, size); | |
| 269 } | |
| 270 | |
| 271 // Generic allocate & zero | |
| 272 void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size) | |
| 273 { | |
| 274 _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 275 return ptr->MallocZeroPtr(ContextID, size); | |
| 276 } | |
| 277 | |
| 278 // Generic calloc | |
| 279 void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size) | |
| 280 { | |
| 281 _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 282 return ptr->CallocPtr(ContextID, num, size); | |
| 283 } | |
| 284 | |
| 285 // Generic reallocate | |
| 286 void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size) | |
| 287 { | |
| 288 _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 289 return ptr->ReallocPtr(ContextID, Ptr, size); | |
| 290 } | |
| 291 | |
| 292 // Generic free memory | |
| 293 void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr) | |
| 294 { | |
| 295 if (Ptr != NULL) { | |
| 296 _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 297 ptr ->FreePtr(ContextID, Ptr); | |
| 298 } | |
| 299 } | |
| 300 | |
| 301 // Generic block duplication | |
| 302 void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size) | |
| 303 { | |
| 304 _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin); | |
| 305 return ptr ->DupPtr(ContextID, Org, size); | |
| 306 } | |
| 307 | |
| 308 // ******************************************************************************************** | |
| 309 | |
| 310 // Sub allocation takes care of many pointers of small size. The memory allocated in | |
| 311 // this way have be freed at once. Next function allocates a single chunk for linked list | |
| 312 // I prefer this method over realloc due to the big impact on xput realloc may have if | |
| 313 // memory is being swapped to disk. This approach is safer (although that may not be true on all platforms) | |
| 314 static | |
| 315 _cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial) | |
| 316 { | |
| 317 _cmsSubAllocator_chunk* chunk; | |
| 318 | |
| 319 // 20K by default | |
| 320 if (Initial == 0) | |
| 321 Initial = 20*1024; | |
| 322 | |
| 323 // Create the container | |
| 324 chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk)); | |
| 325 if (chunk == NULL) return NULL; | |
| 326 | |
| 327 // Initialize values | |
| 328 chunk ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial); | |
| 329 if (chunk ->Block == NULL) { | |
| 330 | |
| 331 // Something went wrong | |
| 332 _cmsFree(ContextID, chunk); | |
| 333 return NULL; | |
| 334 } | |
| 335 | |
| 336 chunk ->BlockSize = Initial; | |
| 337 chunk ->Used = 0; | |
| 338 chunk ->next = NULL; | |
| 339 | |
| 340 return chunk; | |
| 341 } | |
| 342 | |
| 343 // The suballocated is nothing but a pointer to the first element in the list. We also keep | |
| 344 // the thread ID in this structure. | |
| 345 _cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial) | |
| 346 { | |
| 347 _cmsSubAllocator* sub; | |
| 348 | |
| 349 // Create the container | |
| 350 sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator)); | |
| 351 if (sub == NULL) return NULL; | |
| 352 | |
| 353 sub ->ContextID = ContextID; | |
| 354 | |
| 355 sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial); | |
| 356 if (sub ->h == NULL) { | |
| 357 _cmsFree(ContextID, sub); | |
| 358 return NULL; | |
| 359 } | |
| 360 | |
| 361 return sub; | |
| 362 } | |
| 363 | |
| 364 | |
| 365 // Get rid of whole linked list | |
| 366 void _cmsSubAllocDestroy(_cmsSubAllocator* sub) | |
| 367 { | |
| 368 _cmsSubAllocator_chunk *chunk, *n; | |
| 369 | |
| 370 for (chunk = sub ->h; chunk != NULL; chunk = n) { | |
| 371 | |
| 372 n = chunk->next; | |
| 373 if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block); | |
| 374 _cmsFree(sub ->ContextID, chunk); | |
| 375 } | |
| 376 | |
| 377 // Free the header | |
| 378 _cmsFree(sub ->ContextID, sub); | |
| 379 } | |
| 380 | |
| 381 | |
| 382 // Get a pointer to small memory block. | |
| 383 void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size) | |
| 384 { | |
| 385 cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used; | |
| 386 cmsUInt8Number* ptr; | |
| 387 | |
| 388 size = _cmsALIGNMEM(size); | |
| 389 | |
| 390 // Check for memory. If there is no room, allocate a new chunk of double memory size. | |
| 391 if (size > Free) { | |
| 392 | |
| 393 _cmsSubAllocator_chunk* chunk; | |
| 394 cmsUInt32Number newSize; | |
| 395 | |
| 396 newSize = sub -> h ->BlockSize * 2; | |
| 397 if (newSize < size) newSize = size; | |
| 398 | |
| 399 chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize); | |
| 400 if (chunk == NULL) return NULL; | |
| 401 | |
| 402 // Link list | |
| 403 chunk ->next = sub ->h; | |
| 404 sub ->h = chunk; | |
| 405 | |
| 406 } | |
| 407 | |
| 408 ptr = sub -> h ->Block + sub -> h ->Used; | |
| 409 sub -> h -> Used += size; | |
| 410 | |
| 411 return (void*) ptr; | |
| 412 } | |
| 413 | |
| 414 // Duplicate in pool | |
| 415 void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size) | |
| 416 { | |
| 417 void *NewPtr; | |
| 418 | |
| 419 // Dup of null pointer is also NULL | |
| 420 if (ptr == NULL) | |
| 421 return NULL; | |
| 422 | |
| 423 NewPtr = _cmsSubAlloc(s, size); | |
| 424 | |
| 425 if (ptr != NULL && NewPtr != NULL) { | |
| 426 memcpy(NewPtr, ptr, size); | |
| 427 } | |
| 428 | |
| 429 return NewPtr; | |
| 430 } | |
| 431 | |
| 432 | |
| 433 | |
| 434 // Error logging ****************************************************************** | |
| 435 | |
| 436 // There is no error handling at all. When a function fails, it returns proper value. | |
| 437 // For example, all create functions does return NULL on failure. Other return FALSE | |
| 438 // It may be interesting, for the developer, to know why the function is failing. | |
| 439 // for that reason, lcms2 does offer a logging function. This function does receive | |
| 440 // a ENGLISH string with some clues on what is going wrong. You can show this | |
| 441 // info to the end user, or just create some sort of log. | |
| 442 // The logging function should NOT terminate the program, as this obviously can leave | |
| 443 // resources. It is the programmer's responsibility to check each function return code | |
| 444 // to make sure it didn't fail. | |
| 445 | |
| 446 // Error messages are limited to MAX_ERROR_MESSAGE_LEN | |
| 447 | |
| 448 #define MAX_ERROR_MESSAGE_LEN 1024 | |
| 449 | |
| 450 // --------------------------------------------------------------------------------------------------------- | |
| 451 | |
| 452 // This is our default log error | |
| 453 static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text); | |
| 454 | |
| 455 // Context0 storage, which is global | |
| 456 _cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction }; | |
| 457 | |
| 458 // Allocates and inits error logger container for a given context. If src is NULL, only initializes the value | |
| 459 // to the default. Otherwise, it duplicates the value. The interface is standard across all context clients | |
| 460 void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx, | |
| 461 const struct _cmsContext_struct* src) | |
| 462 { | |
| 463 static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction }; | |
| 464 void* from; | |
| 465 | |
| 466 if (src != NULL) { | |
| 467 from = src ->chunks[Logger]; | |
| 468 } | |
| 469 else { | |
| 470 from = &LogErrorChunk; | |
| 471 } | |
| 472 | |
| 473 ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType)); | |
| 474 } | |
| 475 | |
| 476 // The default error logger does nothing. | |
| 477 static | |
| 478 void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text) | |
| 479 { | |
| 480 // fprintf(stderr, "[lcms]: %s\n", Text); | |
| 481 // fflush(stderr); | |
| 482 | |
| 483 cmsUNUSED_PARAMETER(ContextID); | |
| 484 cmsUNUSED_PARAMETER(ErrorCode); | |
| 485 cmsUNUSED_PARAMETER(Text); | |
| 486 } | |
| 487 | |
| 488 // Change log error, context based | |
| 489 void CMSEXPORT cmsSetLogErrorHandler(cmsContext ContextID, cmsLogErrorHandlerFunction Fn) | |
| 490 { | |
| 491 _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); | |
| 492 | |
| 493 if (lhg != NULL) { | |
| 494 | |
| 495 if (Fn == NULL) | |
| 496 lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction; | |
| 497 else | |
| 498 lhg -> LogErrorHandler = Fn; | |
| 499 } | |
| 500 } | |
| 501 | |
| 502 // Log an error | |
| 503 // ErrorText is a text holding an english description of error. | |
| 504 void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...) | |
| 505 { | |
| 506 va_list args; | |
| 507 char Buffer[MAX_ERROR_MESSAGE_LEN]; | |
| 508 _cmsLogErrorChunkType* lhg; | |
| 509 | |
| 510 | |
| 511 va_start(args, ErrorText); | |
| 512 vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args); | |
| 513 va_end(args); | |
| 514 | |
| 515 // Check for the context, if specified go there. If not, go for the global | |
| 516 lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger); | |
| 517 if (lhg ->LogErrorHandler) { | |
| 518 lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer); | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 // Utility function to print signatures | |
| 523 void _cmsTagSignature2String(char String[5], cmsTagSignature sig) | |
| 524 { | |
| 525 cmsUInt32Number be; | |
| 526 | |
| 527 // Convert to big endian | |
| 528 be = _cmsAdjustEndianess32((cmsUInt32Number) sig); | |
| 529 | |
| 530 // Move chars | |
| 531 memmove(String, &be, 4); | |
| 532 | |
| 533 // Make sure of terminator | |
| 534 String[4] = 0; | |
| 535 } | |
| 536 | |
| 537 //-------------------------------------------------------------------------------------------------- | |
| 538 | |
| 539 | |
| 540 static | |
| 541 void* defMtxCreate(cmsContext id) | |
| 542 { | |
| 543 _cmsMutex* ptr_mutex = (_cmsMutex*) _cmsMalloc(id, sizeof(_cmsMutex)); | |
| 544 if (ptr_mutex != NULL) | |
| 545 _cmsInitMutexPrimitive(ptr_mutex); | |
| 546 return (void*) ptr_mutex; | |
| 547 } | |
| 548 | |
| 549 static | |
| 550 void defMtxDestroy(cmsContext id, void* mtx) | |
| 551 { | |
| 552 _cmsDestroyMutexPrimitive((_cmsMutex *) mtx); | |
| 553 _cmsFree(id, mtx); | |
| 554 } | |
| 555 | |
| 556 static | |
| 557 cmsBool defMtxLock(cmsContext id, void* mtx) | |
| 558 { | |
| 559 cmsUNUSED_PARAMETER(id); | |
| 560 return _cmsLockPrimitive((_cmsMutex *) mtx) == 0; | |
| 561 } | |
| 562 | |
| 563 static | |
| 564 void defMtxUnlock(cmsContext id, void* mtx) | |
| 565 { | |
| 566 cmsUNUSED_PARAMETER(id); | |
| 567 _cmsUnlockPrimitive((_cmsMutex *) mtx); | |
| 568 } | |
| 569 | |
| 570 | |
| 571 | |
| 572 // Pointers to memory manager functions in Context0 | |
| 573 _cmsMutexPluginChunkType _cmsMutexPluginChunk = { defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; | |
| 574 | |
| 575 // Allocate and init mutex container. | |
| 576 void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx, | |
| 577 const struct _cmsContext_struct* src) | |
| 578 { | |
| 579 static _cmsMutexPluginChunkType MutexChunk = {defMtxCreate, defMtxDestroy, defMtxLock, defMtxUnlock }; | |
| 580 void* from; | |
| 581 | |
| 582 if (src != NULL) { | |
| 583 from = src ->chunks[MutexPlugin]; | |
| 584 } | |
| 585 else { | |
| 586 from = &MutexChunk; | |
| 587 } | |
| 588 | |
| 589 ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType)); | |
| 590 } | |
| 591 | |
| 592 // Register new ways to transform | |
| 593 cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data) | |
| 594 { | |
| 595 cmsPluginMutex* Plugin = (cmsPluginMutex*) Data; | |
| 596 _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); | |
| 597 | |
| 598 if (Data == NULL) { | |
| 599 | |
| 600 // No lock routines | |
| 601 ctx->CreateMutexPtr = NULL; | |
| 602 ctx->DestroyMutexPtr = NULL; | |
| 603 ctx->LockMutexPtr = NULL; | |
| 604 ctx ->UnlockMutexPtr = NULL; | |
| 605 return TRUE; | |
| 606 } | |
| 607 | |
| 608 // Factory callback is required | |
| 609 if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL || | |
| 610 Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE; | |
| 611 | |
| 612 ctx->CreateMutexPtr = Plugin->CreateMutexPtr; | |
| 613 ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr; | |
| 614 ctx ->LockMutexPtr = Plugin ->LockMutexPtr; | |
| 615 ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr; | |
| 616 | |
| 617 // All is ok | |
| 618 return TRUE; | |
| 619 } | |
| 620 | |
| 621 // Generic Mutex fns | |
| 622 void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID) | |
| 623 { | |
| 624 _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); | |
| 625 | |
| 626 if (ptr ->CreateMutexPtr == NULL) return NULL; | |
| 627 | |
| 628 return ptr ->CreateMutexPtr(ContextID); | |
| 629 } | |
| 630 | |
| 631 void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx) | |
| 632 { | |
| 633 _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); | |
| 634 | |
| 635 if (ptr ->DestroyMutexPtr != NULL && mtx != NULL) { | |
| 636 | |
| 637 ptr ->DestroyMutexPtr(ContextID, mtx); | |
| 638 } | |
| 639 } | |
| 640 | |
| 641 cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx) | |
| 642 { | |
| 643 _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); | |
| 644 | |
| 645 if (ptr ->LockMutexPtr == NULL) return TRUE; | |
| 646 | |
| 647 return ptr ->LockMutexPtr(ContextID, mtx); | |
| 648 } | |
| 649 | |
| 650 void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx) | |
| 651 { | |
| 652 _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin); | |
| 653 | |
| 654 if (ptr ->UnlockMutexPtr != NULL) { | |
| 655 | |
| 656 ptr ->UnlockMutexPtr(ContextID, mtx); | |
| 657 } | |
| 658 } | |
| 659 | |
| 660 // The global Context0 storage for parallelization plug-in | |
| 661 _cmsParallelizationPluginChunkType _cmsParallelizationPluginChunk = { 0 }; | |
| 662 | |
| 663 // Allocate parallelization container. | |
| 664 void _cmsAllocParallelizationPluginChunk(struct _cmsContext_struct* ctx, | |
| 665 const struct _cmsContext_struct* src) | |
| 666 { | |
| 667 if (src != NULL) { | |
| 668 void* from = src->chunks[ParallelizationPlugin]; | |
| 669 ctx->chunks[ParallelizationPlugin] = _cmsSubAllocDup(ctx->MemPool, from, sizeof(_cmsParallelizationPluginChunkType)); | |
| 670 } | |
| 671 else { | |
| 672 _cmsParallelizationPluginChunkType ParallelizationPluginChunk = { 0 }; | |
| 673 ctx->chunks[ParallelizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &ParallelizationPluginChunk, sizeof(_cmsParallelizationPluginChunkType)); | |
| 674 } | |
| 675 } | |
| 676 | |
| 677 // Register parallel processing | |
| 678 cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Data) | |
| 679 { | |
| 680 cmsPluginParalellization* Plugin = (cmsPluginParalellization*)Data; | |
| 681 _cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(ContextID, ParallelizationPlugin); | |
| 682 | |
| 683 if (Data == NULL) { | |
| 684 | |
| 685 // No parallelization routines | |
| 686 ctx->MaxWorkers = 0; | |
| 687 ctx->WorkerFlags = 0; | |
| 688 ctx->SchedulerFn = NULL; | |
| 689 return TRUE; | |
| 690 } | |
| 691 | |
| 692 // callback is required | |
| 693 if (Plugin->SchedulerFn == NULL) return FALSE; | |
| 694 | |
| 695 ctx->MaxWorkers = Plugin->MaxWorkers; | |
| 696 ctx->WorkerFlags = Plugin->WorkerFlags; | |
| 697 ctx->SchedulerFn = Plugin->SchedulerFn; | |
| 698 | |
| 699 // All is ok | |
| 700 return TRUE; | |
| 701 } | |
| 702 |
