pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plank_ContainersMisc.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 #ifndef PLANK_CONTAINERSMISC_H
00040 #define PLANK_CONTAINERSMISC_H
00041 
00042 #include "../random/plank_RNG.h"
00043 
00044 static inline PlankI pl_AlignI (const PlankI value, const PlankI alignment)
00045 {
00046     return value + (alignment - (value % alignment)) * !!(value % alignment);
00047 }
00048 
00049 static inline PlankUI pl_AlignUI (const PlankUI value, const PlankUI alignment)
00050 {
00051     return value + (alignment - (value % alignment)) * !!(value % alignment);
00052 }
00053 
00054 static inline PlankLL pl_AlignLL (const PlankLL value, const PlankLL alignment)
00055 {
00056     return value + (alignment - (value % alignment)) * !!(value % alignment);
00057 }
00058 
00059 static inline PlankULL pl_AlignULL (const PlankULL value, const PlankULL alignment)
00060 {
00061     return value + (alignment - (value % alignment)) * !!(value % alignment);
00062 }
00063 
00064 
00065 static inline void pl_SwapP (PlankP* a, PlankP* b)
00066 {
00067     PlankP temp;
00068     temp = *a;
00069     *a = *b;
00070     *b = temp;
00071 }
00072 
00074 typedef struct PlankUI24
00075 {
00076     PlankUC data[3];
00077 } PlankUI24;
00078 
00080 typedef struct PlankI24
00081 {
00082     PlankUC data[3];
00083 } PlankI24;
00084 
00088 typedef struct PlankF80
00089 {
00090     PlankUC data[10];
00091 } PlankF80;
00092 
00093 
00095 typedef struct PlankPascalString255
00096 {
00097     PlankUC data[256];
00098 } PlankPascalString255;
00099 
00100 
00103 static inline PlankUI24 pl_ConvertUIToUI24 (const PlankUI i32)
00104 {
00105 #if PLANK_LITTLEENDIAN
00106     PlankUI24 i24;
00107     i24 = *(PlankUI24*)&i32;
00108     return i24;
00109 #elif PLANK_BIGENDIAN
00110     PlankUI24 i24;
00111     unsigned char* bits;
00112     
00113     bits = (unsigned char*)&i32;
00114     i24 = *(PlankUI24*)(bits + 1);
00115     return i24;
00116 #else
00117         #error Neither PLANK_BIGENDIAN or PLANK_LITTLEENDIAN are set to 1
00118 #endif
00119 }
00120 
00121 
00124 static inline PlankUI pl_ConvertUI24ToUI (const PlankUI24 i24)
00125 {
00126 #if PLANK_LITTLEENDIAN
00127     PlankUI i32;
00128     i32 = *(PlankUI*)&i24 & 0xffffff;
00129     return i32;
00130 #elif PLANK_BIGENDIAN
00131         PlankUI i32;
00132     i32 = (*(PlankUI*)&i24 >> 8) & 0xffffff;
00133     return i32;
00134 #else
00135     #error Neither PLANK_BIGENDIAN or PLANK_LITTLEENDIAN are set to 1
00136 #endif
00137 }
00138 
00141 static inline PlankI24 pl_ConvertIToI24 (const PlankI i32)
00142 {
00143 #if PLANK_LITTLEENDIAN
00144     PlankI24 i24;
00145     i24 = *(PlankI24*)&i32;
00146     return i24;
00147 #elif PLANK_BIGENDIAN
00148     PlankI24 i24;
00149     unsigned char* bits;
00150     
00151     bits = (unsigned char*)&i32;
00152     i24 = *(PlankI24*)(bits + 1);
00153     return i24;    
00154 #else
00155     #error Neither PLANK_BIGENDIAN or PLANK_LITTLEENDIAN are set to 1
00156 #endif
00157 }
00158 
00161 static inline PlankI pl_ConvertI24ToI (const PlankI24 i24)
00162 {
00163 #if PLANK_LITTLEENDIAN
00164     PlankI i32;
00165     i32 = *(PlankI*)&i24 & 0xffffff;
00166             
00167     if (i32 & 0x00800000)
00168         return i32 | 0xff000000;
00169     else
00170         return i32;
00171 #elif PLANK_BIGENDIAN
00172         PlankI i32;
00173     i32 = (*(PlankI*)&i24 >> 8) & 0xffffff;
00174         
00175     if (i32 & 0x00800000)
00176         return i32 | 0xff000000;
00177     else
00178         return i32;
00179 #else
00180     #error Neither PLANK_BIGENDIAN or PLANK_LITTLEENDIAN are set to 1
00181 #endif
00182 }
00183 
00184 typedef struct PlankVec2F
00185 {
00186     float values[2];
00187 } PlankVec2F;
00188 
00189 typedef struct PlankVec3F
00190 {
00191     float values[3];
00192 } PlankVec3F;
00193 
00194 typedef struct PlankVec4F
00195 {
00196     float values[4];
00197 } PlankVec4F;
00198 
00199 typedef struct PlankVec2D
00200 {
00201     double values[2];
00202 } PlankVec2D;
00203 
00204 typedef struct PlankVec3D
00205 {
00206     double values[3];
00207 } PlankVec3D;
00208 
00209 typedef struct PlankVec4D
00210 {
00211     double values[4];
00212 } PlankVec4D;
00213 
00219 static inline PlankUC pl_CountOnesUC (PlankUC x)
00220 {
00221     x -= ((x >> 1) & 0x55);
00222     x = (((x >> 2) & 0x33) + (x & 0x33));
00223     x = (((x >> 4) + x) & 0x0f);
00224     return x;           
00225 }
00226 
00227 static inline PlankUC pl_CountLeadingZerosUC (PlankUC x)
00228 {
00229     x |= (x >> 1);
00230     x |= (x >> 2);
00231     x |= (x >> 4);
00232     return 8 - pl_CountOnesUC (x);
00233 }
00234 
00235 static inline PlankUC pl_CountTrailingZerosUC (PlankUC x) 
00236 {
00237     return 8 - pl_CountLeadingZerosUC (~x & (x - 1));
00238 }
00239 
00240 static inline PlankUC pl_CountLeadingOnesUC (PlankUC x) 
00241 {
00242     return pl_CountLeadingZerosUC (~x);
00243 }
00244 
00245 static inline PlankUC pl_CountTrailingOnesUC (PlankUC x) 
00246 {
00247     return 8 - pl_CountLeadingZerosUC (x & (~x - 1));
00248 }
00249 
00250 static inline PlankUC pl_NumBitsRequiredUC (PlankUC x) 
00251 {
00252     return 8 - pl_CountLeadingZerosUC (x);
00253 }
00254 
00255 static inline PlankUC pl_Log2CeilUC (PlankUC x) 
00256 {
00257     return 8 - pl_CountLeadingZerosUC (x - 1);
00258 }
00259 
00260 static inline PlankUC pl_NextPowerOf2UC (PlankUC x) 
00261 {
00262     return (PlankUC)1 << pl_Log2CeilUC (x);
00263 }
00264 
00265 static inline PlankB pl_IsPowerOf2UC (PlankUC x) 
00266 {
00267     return (x & (x - 1)) == 0;
00268 }
00269 
00270 static inline PlankUS pl_CountOnesUS (PlankUS x)
00271 {
00272     x -= ((x >> 1) & 0x5555);
00273     x = (((x >> 2) & 0x3333) + (x & 0x3333));
00274     x = (((x >> 4) + x) & 0x0f0f);
00275     x += (x >> 8);
00276     return x & 0x001f;          
00277 }
00278 
00279 static inline PlankUS pl_CountLeadingZerosUS (PlankUS x)
00280 {
00281     x |= (x >> 1);
00282     x |= (x >> 2);
00283     x |= (x >> 4);
00284     x |= (x >> 8);
00285     return 16 - pl_CountOnesUS (x);
00286 }
00287 
00288 static inline PlankUS pl_CountTrailingZerosUS (PlankUS x) 
00289 {
00290     return 16 - pl_CountLeadingZerosUS (~x & (x - 1));
00291 }
00292 
00293 static inline PlankUS pl_CountLeadingOnesUS (PlankUS x) 
00294 {
00295     return pl_CountLeadingZerosUS (~x);
00296 }
00297 
00298 static inline PlankUS pl_CountTrailingOnesUS (PlankUS x) 
00299 {
00300     return 16 - pl_CountLeadingZerosUS (x & (~x - 1));
00301 }
00302 
00303 static inline PlankUS pl_NumBitsRequiredUS (PlankUS x) 
00304 {
00305     return 16 - pl_CountLeadingZerosUS (x);
00306 }
00307 
00308 static inline PlankUS pl_Log2CeilUS (PlankUS x) 
00309 {
00310     return 16 - pl_CountLeadingZerosUS (x - 1);
00311 }
00312 
00313 static inline PlankUS pl_NextPowerOf2US (PlankUS x) 
00314 {
00315     return 1 << pl_Log2CeilUS (x);
00316 }
00317 
00318 static inline PlankB pl_IsPowerOf2US (PlankUS x) 
00319 {
00320     return (x & (x - 1)) == (PlankUS)0;
00321 }
00322 
00323 static inline PlankUI pl_CountOnesUI (PlankUI x)
00324 {
00325     x -= ((x >> 1) & 0x55555555);
00326     x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
00327     x = (((x >> 4) + x) & 0x0f0f0f0f);
00328     x += (x >> 8);
00329     x += (x >> 16);
00330     return x & 0x0000003f;              
00331 }
00332 
00333 static inline PlankUI pl_CountLeadingZerosUI (PlankUI x)
00334 {
00335     x |= (x >> 1);
00336     x |= (x >> 2);
00337     x |= (x >> 4);
00338     x |= (x >> 8);
00339     x |= (x >> 16);
00340     return 32 - pl_CountOnesUI (x);
00341 }
00342 
00343 static inline PlankUI pl_CountTrailingZerosUI (PlankUI x) 
00344 {
00345     return 32 - pl_CountLeadingZerosUI (~x & (x - 1));
00346 }
00347 
00348 static inline PlankUI pl_CountLeadingOnesUI (PlankUI x) 
00349 {
00350     return pl_CountLeadingZerosUI (~x);
00351 }
00352 
00353 static inline PlankUI pl_CountTrailingOnesUI (PlankUI x) 
00354 {
00355     return 32 - pl_CountLeadingZerosUI (x & (~x - 1));
00356 }
00357 
00358 static inline PlankUI pl_NumBitsRequiredUI (PlankUI x) 
00359 {
00360     return 32 - pl_CountLeadingZerosUI (x);
00361 }
00362 
00363 static inline PlankUI pl_Log2CeilUI (PlankUI x) 
00364 {
00365     return 32 - pl_CountLeadingZerosUI (x - 1);
00366 }
00367 
00368 static inline PlankUI pl_NextPowerOf2UI (PlankUI x) 
00369 {
00370     return 1 << pl_Log2CeilUI (x);
00371 }
00372 
00373 static inline PlankB pl_IsPowerOf2UI (PlankUI x) 
00374 {
00375     return (x & (x - 1)) == (PlankUI)0;
00376 }
00377 
00378 static inline PlankULL pl_CountOnesULL (PlankULL x)
00379 {
00380     x -= ((x >> 1) & 0x5555555555555555ULL);
00381     x = (((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL));
00382     x = (((x >> 4) + x) & 0x0f0f0f0f0f0f0f0fULL);
00383     x += (x >> 8);
00384     x += (x >> 16);
00385     x += (x >> 32);
00386     return x & 0x000000000000007fULL;           
00387 }
00388 
00389 static inline PlankULL pl_CountLeadingZerosULL (PlankULL x)
00390 {
00391     x |= (x >> 1);
00392     x |= (x >> 2);
00393     x |= (x >> 4);
00394     x |= (x >> 8);
00395     x |= (x >> 16);
00396     x |= (x >> 32);
00397     return 64 - pl_CountOnesULL (x);
00398 }
00399 
00400 static inline PlankULL pl_CountTrailingZerosULL (PlankULL x) 
00401 {
00402     return 64 - pl_CountLeadingZerosULL (~x & (x - 1));
00403 }
00404 
00405 static inline PlankULL pl_CountLeadingOnesULL (PlankULL x) 
00406 {
00407     return pl_CountLeadingZerosULL (~x);
00408 }
00409 
00410 static inline PlankULL pl_CountTrailingOnesULL (PlankULL x) 
00411 {
00412     return 64 - pl_CountLeadingZerosULL (x & (~x - 1));
00413 }
00414 
00415 static inline PlankULL pl_NumBitsRequiredULL (PlankULL x) 
00416 {
00417     return 64 - pl_CountLeadingZerosULL (x);
00418 }
00419 
00420 static inline PlankULL pl_Log2CeilULL (PlankULL x) 
00421 {
00422     return 64 - pl_CountLeadingZerosULL (x - 1);
00423 }
00424 
00425 static inline PlankULL pl_NextPowerOf2ULL (PlankULL x) 
00426 {
00427     return 1ULL << pl_Log2CeilULL (x);
00428 }
00429 
00430 static inline PlankB pl_IsPowerOf2ULL (PlankULL x) 
00431 {
00432     return (x & (x - 1)) == (PlankULL)0;
00433 }
00434 
00436 
00437 
00444 static inline void pl_SwapEndianUS (unsigned short *bits)
00445 {
00446     *bits = (*bits >> 8) | (*bits << 8);
00447 }
00448 
00450 static inline void pl_SwapEndianUI24 (PlankUI24 *bits)
00451 {
00452     PlankUC temp = bits->data[0];
00453     bits->data[0] = bits->data[2];
00454     bits->data[2] = temp;
00455 }
00456 
00458 static inline void pl_SwapEndianUI (unsigned int *bits)
00459 {
00460     *bits = (*bits >> 24) | ((*bits << 8) & 0x00ff0000) | ((*bits >> 8) & 0x0000ff00) | (*bits << 24);
00461 }
00462 
00464 static inline void pl_SwapEndianULL (PlankULL *bits)
00465 {    
00466     *bits = (*bits >> 56) | 
00467             ((*bits << 40) & 0x00ff000000000000ULL) |
00468             ((*bits << 24) & 0x0000ff0000000000ULL) |
00469             ((*bits << 8)  & 0x000000ff00000000ULL) |
00470             ((*bits >> 8)  & 0x00000000ff000000ULL) |
00471             ((*bits >> 24) & 0x0000000000ff0000ULL) |
00472             ((*bits >> 40) & 0x000000000000ff00ULL) |
00473             (*bits << 56);
00474 }
00475 
00476 static inline void pl_SwapEndianF80 (PlankF80 *bits)
00477 {
00478     PlankF80 temp = *bits;
00479     
00480     bits->data[0] = temp.data[9];
00481     bits->data[1] = temp.data[8];
00482     bits->data[2] = temp.data[7];
00483     bits->data[3] = temp.data[6];
00484     bits->data[4] = temp.data[5];
00485     bits->data[5] = temp.data[4];
00486     bits->data[6] = temp.data[3];
00487     bits->data[7] = temp.data[2];
00488     bits->data[8] = temp.data[1];
00489     bits->data[9] = temp.data[0];
00490 }
00491 
00493 static inline void pl_SwapEndianUL (PlankUL *data)
00494 {
00495 #if PLANK_32BIT
00496     pl_SwapEndianUI ((unsigned int*)data);
00497 #elif PLANK_64BIT
00498     pl_SwapEndianULL ((PlankULL*)data);
00499 #else
00500     #error Neither PLANK_32BIT or PLANK_64BIT are set to 1
00501 #endif
00502 }
00503 
00505 static inline void pl_SwapEndianS (short *data)
00506 {
00507     pl_SwapEndianUS ((unsigned short*)data);
00508 }
00509 
00511 static inline void pl_SwapEndianI (int *data)
00512 {
00513     pl_SwapEndianUI ((unsigned int*)data);
00514 }
00515 
00517 static inline void pl_SwapEndianI24 (PlankI24 *data)
00518 {
00519     pl_SwapEndianUI24 ((PlankUI24*)data);
00520 }
00521 
00523 static inline void pl_SwapEndianL (long *data)
00524 {
00525 #if PLANK_32BIT
00526     pl_SwapEndianUI ((unsigned int*)data);
00527 #elif PLANK_64BIT
00528     pl_SwapEndianULL ((PlankULL*)data);
00529 #else
00530     #error Neither PLANK_32BIT or PLANK_64BIT are set to 1
00531 #endif    
00532 }
00533 
00535 static inline void pl_SwapEndianLL (PlankLL *data)
00536 {
00537     pl_SwapEndianULL ((PlankULL*)data);
00538 }
00539 
00541 static inline void pl_SwapEndianF (float *data)
00542 {
00543     pl_SwapEndianUI ((unsigned int*)data);
00544 }
00545 
00547 static inline void pl_SwapEndianD (double *data)
00548 {
00549     pl_SwapEndianULL ((PlankULL*)data);
00550 }
00551 
00553 
00554 
00557 static inline PlankFourCharCode pl_FourCharCode (const char* data)
00558 {
00559     PlankFourCharCode code;
00560     
00561     code = (data[0] == '\0') ? 0 : *(PlankFourCharCode*)data;
00562     
00563 #if PLANK_BIGENDIAN
00564     pl_SwapEndianI ((int*)code);
00565 #endif
00566     return code;
00567 }
00568 
00569 #define PLANKFOURCHARCODE(data) (*(const PlankFourCharCode*)data)
00570 
00571 static inline PlankFourCharCodeString pl_FourCharCode2String (const PlankFourCharCode code)
00572 {   
00573     PlankFourCharCodeString string;
00574     *(PlankFourCharCode*)string.string = code;
00575     
00576 #if PLANK_BIGENDIAN
00577     pl_SwapEndianI ((int*)code);
00578 #endif
00579     
00580     string.string[4] = '\0';
00581 
00582     return string;
00583 }
00584 
00586 static inline PlankUI pl_F802I (const PlankF80 extended)
00587 {
00588     PlankUI mantissa;
00589     PlankUI last = 0;
00590     PlankUC exp;
00591     
00592 #if PLANK_LITTLEENDIAN
00593     pl_SwapEndianUI ((PlankUI*)(extended.data + 2));
00594 #endif
00595     
00596     mantissa = *(PlankUI*)(extended.data + 2);
00597     exp = 30 - *(extended.data + 1);
00598     
00599     while (exp)
00600     {
00601         last = mantissa;
00602         mantissa = mantissa >> 1;
00603         --exp;
00604     }
00605     
00606     if (last & 0x00000001) 
00607         ++mantissa;
00608     
00609     return mantissa;
00610 }
00611 
00613 static inline PlankF80 pl_I2F80 (const PlankUI value)
00614 {
00615     PlankF80 extended;
00616     PlankI temp = value;
00617     PlankUI exp;
00618     PlankUC i;
00619     
00620     pl_MemoryZero (&extended, sizeof (PlankF80));
00621     
00622     if (value == 0)
00623         goto exit;
00624     
00625     exp = temp;
00626     exp = exp >> 1;
00627     
00628     for (i = 0; i < 32; ++i) 
00629     { 
00630         exp = exp >> 1;
00631         
00632         if (!exp) 
00633             break;
00634     }
00635     
00636     if (value == -1)
00637         extended.data[0] = 191;
00638     else if (value == 1)
00639         extended.data[0] = 63;
00640 //    else if (value < 0)
00641 //        extended.data[0] = 192;
00642     else
00643         extended.data[0] = 64;
00644     
00645     extended.data[1] = i;
00646     
00647     for (i = 32; i > 0; --i)
00648     {
00649         if (temp & 0x80000000) 
00650             break;
00651         
00652         temp <<= 1; 
00653     } 
00654         
00655     *(PlankUI*)(extended.data + 2) = temp;
00656     
00657 #if PLANK_LITTLEENDIAN
00658     pl_SwapEndianUI ((PlankUI*)(extended.data + 2));
00659 #endif 
00660     
00661 exit:
00662     return extended;
00663 }
00664 
00669 typedef struct PlankGUID* PlankGUIDRef;
00670 
00671 typedef struct PlankGUID
00672 {
00673     PlankUI  data1;
00674     PlankUS  data2;
00675     PlankUS  data3;
00676     PlankUC  data4[8];
00677 } PlankGUID;
00678 
00679 
00680 static inline void pl_GUID_InitRandom (PlankGUIDRef p)
00681 {
00682     PlankRNGRef rng;
00683     rng = pl_RNGGlobal();
00684     
00685     p->data1 = pl_RNG_NextInt (rng, 0xffffffff);
00686     p->data2 = (PlankUS)pl_RNG_NextInt (rng, 0xffff);
00687     p->data3 = (PlankUS)pl_RNG_NextInt (rng, 0x0fff) | 0x4000;
00688     *(PlankULL*)&p->data4 = (((PlankULL)pl_RNG_NextInt (rng, 0xffffffff)) << 32) | pl_RNG_NextInt (rng, 0xffffffff);
00689     p->data4[0] = ((PlankUC)(pl_RNG_NextInt (rng, 4) + 8) << 4) | (PlankUC)(pl_RNG_NextInt (rng, 0x0f));
00690 }
00691 
00692 static inline void pl_GUID_Init42244 (PlankGUIDRef p, const PlankUI data1, const PlankUS data2, const PlankUS data3, const PlankUI data4hi, const PlankUI data4lo)
00693 {
00694     p->data1 = data1;
00695     p->data2 = data2;
00696     p->data3 = data3;
00697     *(PlankULL*)&p->data4 = (((PlankULL)data4hi) << 32) | data4lo;
00698 }
00699 
00700 static inline void pl_GUID_Init4228 (PlankGUIDRef p, const PlankUI data1, const PlankUS data2, const PlankUS data3, const PlankULL data4)
00701 {
00702     p->data1 = data1;
00703     p->data2 = data2;
00704     p->data3 = data3;
00705     *(PlankULL*)&p->data4 = data4;
00706 }
00707 
00708 static inline void pl_GUID_Init4221x8 (PlankGUIDRef p, const PlankUI data1, const PlankUS data2, const PlankUS data3,
00709                                         const PlankUC data4_0,
00710                                         const PlankUC data4_1,
00711                                         const PlankUC data4_2,
00712                                         const PlankUC data4_3,
00713                                         const PlankUC data4_4,
00714                                         const PlankUC data4_5,
00715                                         const PlankUC data4_6,
00716                                         const PlankUC data4_7)
00717 {
00718     p->data1 = data1;
00719     p->data2 = data2;
00720     p->data3 = data3;
00721     p->data4[0] = data4_0;
00722     p->data4[1] = data4_1;
00723     p->data4[2] = data4_2;
00724     p->data4[3] = data4_3;
00725     p->data4[4] = data4_4;
00726     p->data4[5] = data4_5;
00727     p->data4[6] = data4_6;
00728     p->data4[7] = data4_7;
00729 }
00730 
00731 static inline void pl_GUID_Init422p (PlankGUIDRef p, const PlankUI data1, const PlankUS data2, const PlankUS data3, const PlankUC* data4)
00732 {
00733     p->data1 = data1;
00734     p->data2 = data2;
00735     p->data3 = data3;
00736     pl_MemoryCopy (&p->data4, data4, 8);
00737 }
00738 
00739 static inline const char* pl_HexDigit2CharMap()
00740 {
00741     static char map[16];
00742     static PlankB firstTime = PLANK_TRUE;
00743     
00744     if (firstTime)
00745     {
00746         pl_MemoryCopy(map, "0123456789abcdef", 16);
00747         firstTime = PLANK_FALSE;
00748     }
00749     
00750     return map;
00751 }
00752 
00753 static inline const char* pl_Char2HexDigitMap()
00754 {
00755     static char map[128];
00756     static PlankB firstTime = PLANK_TRUE;
00757     int i;
00758     
00759     if (firstTime)
00760     {
00761         // invalid chars
00762         for (i = 0; i < 128; ++i)
00763             map[i] = -2;
00764         
00765         // valid chars >= -1
00766         map['-'] = -1;
00767         map['0'] = 0;
00768         map['1'] = 1;
00769         map['2'] = 2;
00770         map['3'] = 3;
00771         map['4'] = 4;
00772         map['5'] = 5;
00773         map['6'] = 6;
00774         map['7'] = 7;
00775         map['8'] = 8;
00776         map['9'] = 9;
00777         map['a'] = 10;
00778         map['b'] = 11;
00779         map['c'] = 12;
00780         map['d'] = 13;
00781         map['e'] = 14;
00782         map['f'] = 15;
00783         map['A'] = 10;
00784         map['B'] = 11;
00785         map['C'] = 12;
00786         map['D'] = 13;
00787         map['E'] = 14;
00788         map['F'] = 15;
00789     }
00790     
00791     return map;
00792 }
00793 
00794 
00795 static inline PlankResult pl_GUID_InitHexString (PlankGUIDRef p, const char* string)
00796 {
00797     const char *map;
00798     PlankResult result;
00799     PlankUL i, len;
00800     
00801     result = PlankResult_OK;
00802     map = pl_Char2HexDigitMap();
00803     
00804     if (string[0] == '{')
00805         string++;
00806     
00807     len = strlen (string);
00808     
00809     if (len < 36 || len > 37 )
00810     {
00811         result = PlankResult_UnknownError;
00812         goto exit;
00813     }
00814     
00815     if ((len == 37) && string[36] != '}')
00816     {
00817         result = PlankResult_UnknownError;
00818         goto exit;
00819     }
00820     
00821     if ((string[8] != '-') || (string[13] != '-') || (string[18] != '-') || (string[23] != '-'))
00822     {
00823         result = PlankResult_UnknownError;
00824         goto exit;
00825     }
00826     
00827     for (i = 0; i < 36; ++i)
00828     {
00829         if (map[string[i]] < -1)
00830         {
00831             result = PlankResult_UnknownError;
00832             goto exit;
00833         }
00834     }
00835     
00836     p->data1 =  (((PlankUI)map[string[ 0]]) << 28) |
00837                 (((PlankUI)map[string[ 1]]) << 24) |
00838                 (((PlankUI)map[string[ 2]]) << 20) |
00839                 (((PlankUI)map[string[ 3]]) << 16) |
00840                 (((PlankUI)map[string[ 4]]) << 12) |
00841                 (((PlankUI)map[string[ 5]]) <<  8) |
00842                 (((PlankUI)map[string[ 6]]) <<  4) |
00843                 (((PlankUI)map[string[ 7]]) <<  0);
00844     
00845     p->data2 =  (((PlankUS)map[string[ 9]]) << 12) |
00846                 (((PlankUS)map[string[10]]) <<  8) |
00847                 (((PlankUS)map[string[11]]) <<  4) |
00848                 (((PlankUS)map[string[12]]) <<  0);
00849     
00850     p->data3 =  (((PlankUS)map[string[14]]) << 12) |
00851                 (((PlankUS)map[string[15]]) <<  8) |
00852                 (((PlankUS)map[string[16]]) <<  4) |
00853                 (((PlankUS)map[string[17]]) <<  0);
00854     
00855     p->data4[0] = (((PlankUC)map[string[19]]) << 4) | (((PlankUC)map[string[20]]) << 0);
00856     p->data4[1] = (((PlankUC)map[string[21]]) << 4) | (((PlankUC)map[string[22]]) << 0);
00857     
00858     p->data4[2] = (((PlankUC)map[string[24]]) << 4) | (((PlankUC)map[string[25]]) << 0);
00859     p->data4[3] = (((PlankUC)map[string[26]]) << 4) | (((PlankUC)map[string[27]]) << 0);
00860     p->data4[4] = (((PlankUC)map[string[28]]) << 4) | (((PlankUC)map[string[29]]) << 0);
00861     p->data4[5] = (((PlankUC)map[string[30]]) << 4) | (((PlankUC)map[string[31]]) << 0);
00862     p->data4[6] = (((PlankUC)map[string[32]]) << 4) | (((PlankUC)map[string[33]]) << 0);
00863     p->data4[7] = (((PlankUC)map[string[34]]) << 4) | (((PlankUC)map[string[35]]) << 0);
00864     
00865 exit:
00866     return result;
00867 }
00868 
00869 static inline PlankResult pl_GUID_InitChunkString (PlankGUIDRef p, const char* string)
00870 {
00871     const char *map;
00872     char chunkID[5];
00873     PlankResult result;
00874     PlankUL i, len;
00875     
00876     result = PlankResult_OK;
00877     map = pl_Char2HexDigitMap();
00878     
00879     if (string[0] == '{')
00880         string++;
00881 
00882     len = strlen (string);
00883     
00884     if (len < 32 || len > 33)
00885     {
00886         result = PlankResult_UnknownError;
00887         goto exit;
00888     }
00889     
00890     if ((len == 33) && string[32] != '}')
00891     {
00892         result = PlankResult_UnknownError;
00893         goto exit;
00894     }
00895     
00896     if ((string[4] != '-') || (string[9] != '-') || (string[14] != '-') || (string[19] != '-'))
00897     {
00898         result = PlankResult_UnknownError;
00899         goto exit;
00900     }
00901     
00902     for (i = 5; i < 32; ++i)
00903     {
00904         if (map[string[i]] < -1)
00905         {
00906             result = PlankResult_UnknownError;
00907             goto exit;
00908         }
00909     }
00910     
00911     chunkID[0] = string[0];
00912     chunkID[1] = string[1];
00913     chunkID[2] = string[2];
00914     chunkID[3] = string[3];
00915     chunkID[4] = '\0';
00916     
00917     p->data1 = pl_FourCharCode (chunkID);
00918     
00919     p->data2 =  (((PlankUS)map[string[ 5]]) << 12) |
00920                 (((PlankUS)map[string[ 6]]) <<  8) |
00921                 (((PlankUS)map[string[ 7]]) <<  4) |
00922                 (((PlankUS)map[string[ 8]]) <<  0);
00923     
00924     p->data3 =  (((PlankUS)map[string[10]]) << 12) |
00925                 (((PlankUS)map[string[11]]) <<  8) |
00926                 (((PlankUS)map[string[12]]) <<  4) |
00927                 (((PlankUS)map[string[13]]) <<  0);
00928     
00929     p->data4[0] = (((PlankUC)map[string[15]]) << 4) | (((PlankUC)map[string[16]]) << 0);
00930     p->data4[1] = (((PlankUC)map[string[17]]) << 4) | (((PlankUC)map[string[18]]) << 0);
00931     
00932     p->data4[2] = (((PlankUC)map[string[20]]) << 4) | (((PlankUC)map[string[21]]) << 0);
00933     p->data4[3] = (((PlankUC)map[string[22]]) << 4) | (((PlankUC)map[string[23]]) << 0);
00934     p->data4[4] = (((PlankUC)map[string[24]]) << 4) | (((PlankUC)map[string[25]]) << 0);
00935     p->data4[5] = (((PlankUC)map[string[26]]) << 4) | (((PlankUC)map[string[27]]) << 0);
00936     p->data4[6] = (((PlankUC)map[string[28]]) << 4) | (((PlankUC)map[string[29]]) << 0);
00937     p->data4[7] = (((PlankUC)map[string[30]]) << 4) | (((PlankUC)map[string[31]]) << 0);
00938     
00939 exit:
00940     return result;
00941 }
00942 
00943 static inline PlankResult pl_GUID_InitString (PlankGUIDRef p, const char* string)
00944 {
00945     PlankUL len;
00946     
00947     len = strlen (string);
00948 
00949     if (len == 32 || len == 34)
00950         return pl_GUID_InitChunkString (p, string);
00951     else if (len == 36 || len == 38)
00952         return pl_GUID_InitHexString (p, string);
00953     else
00954         return PlankResult_UnknownError;
00955 }
00956 
00957 static inline void pl_GUID_HexString (const PlankGUID* p, const PlankB withBraces, char* string)
00958 {
00959     const char *map;
00960     
00961     map = pl_HexDigit2CharMap();
00962     
00963     if (withBraces)
00964         *string++ = '{';
00965     
00966     *string++ = map[(p->data1 >> 28) & 0x0f];
00967     *string++ = map[(p->data1 >> 24) & 0x0f];
00968     *string++ = map[(p->data1 >> 20) & 0x0f];
00969     *string++ = map[(p->data1 >> 16) & 0x0f];
00970     *string++ = map[(p->data1 >> 12) & 0x0f];
00971     *string++ = map[(p->data1 >>  8) & 0x0f];
00972     *string++ = map[(p->data1 >>  4) & 0x0f];
00973     *string++ = map[(p->data1 >>  0) & 0x0f];
00974     *string++ = '-';
00975     *string++ = map[(p->data2 >> 12) & 0x0f];
00976     *string++ = map[(p->data2 >>  8) & 0x0f];
00977     *string++ = map[(p->data2 >>  4) & 0x0f];
00978     *string++ = map[(p->data2 >>  0) & 0x0f];
00979     *string++ = '-';
00980     *string++ = map[(p->data3 >> 12) & 0x0f];
00981     *string++ = map[(p->data3 >>  8) & 0x0f];
00982     *string++ = map[(p->data3 >>  4) & 0x0f];
00983     *string++ = map[(p->data3 >>  0) & 0x0f];
00984     *string++ = '-';
00985     *string++ = map[(p->data4[0] >>  4) & 0x0f];
00986     *string++ = map[(p->data4[0] >>  0) & 0x0f];
00987     *string++ = map[(p->data4[1] >>  4) & 0x0f];
00988     *string++ = map[(p->data4[1] >>  0) & 0x0f];
00989     *string++ = '-';
00990     *string++ = map[(p->data4[2] >>  4) & 0x0f];
00991     *string++ = map[(p->data4[2] >>  0) & 0x0f];
00992     *string++ = map[(p->data4[3] >>  4) & 0x0f];
00993     *string++ = map[(p->data4[3] >>  0) & 0x0f];
00994     *string++ = map[(p->data4[4] >>  4) & 0x0f];
00995     *string++ = map[(p->data4[4] >>  0) & 0x0f];
00996     *string++ = map[(p->data4[5] >>  4) & 0x0f];
00997     *string++ = map[(p->data4[5] >>  0) & 0x0f];
00998     *string++ = map[(p->data4[6] >>  4) & 0x0f];
00999     *string++ = map[(p->data4[6] >>  0) & 0x0f];
01000     *string++ = map[(p->data4[7] >>  4) & 0x0f];
01001     *string++ = map[(p->data4[7] >>  0) & 0x0f];
01002     
01003     if (withBraces)
01004         *string++ = '}';
01005     
01006     *string++ = '\0';
01007 }
01008 
01009 static inline void pl_GUID_ChunkString (const PlankGUID* p, const PlankB withBraces, char* string)
01010 {
01011     const char *map;
01012     
01013     map = pl_HexDigit2CharMap();
01014     
01015     if (withBraces)
01016         *string++ = '{';
01017 
01018 #if PLANK_LITTLEENDIAN
01019     *string++ = ((char*)&p->data1)[0];
01020     *string++ = ((char*)&p->data1)[1];
01021     *string++ = ((char*)&p->data1)[2];
01022     *string++ = ((char*)&p->data1)[3];
01023 #endif
01024 #if PLANK_BIGENDIAN
01025     *string++ = ((char*)&p->data1)[3];
01026     *string++ = ((char*)&p->data1)[2];
01027     *string++ = ((char*)&p->data1)[1];
01028     *string++ = ((char*)&p->data1)[0];
01029 #endif
01030     *string++ = '-';
01031     *string++ = map[(p->data2 >> 12) & 0x0f];
01032     *string++ = map[(p->data2 >>  8) & 0x0f];
01033     *string++ = map[(p->data2 >>  4) & 0x0f];
01034     *string++ = map[(p->data2 >>  0) & 0x0f];
01035     *string++ = '-';
01036     *string++ = map[(p->data3 >> 12) & 0x0f];
01037     *string++ = map[(p->data3 >>  8) & 0x0f];
01038     *string++ = map[(p->data3 >>  4) & 0x0f];
01039     *string++ = map[(p->data3 >>  0) & 0x0f];
01040     *string++ = '-';
01041     *string++ = map[(p->data4[0] >>  4) & 0x0f];
01042     *string++ = map[(p->data4[0] >>  0) & 0x0f];
01043     *string++ = map[(p->data4[1] >>  4) & 0x0f];
01044     *string++ = map[(p->data4[1] >>  0) & 0x0f];
01045     *string++ = '-';
01046     *string++ = map[(p->data4[2] >>  4) & 0x0f];
01047     *string++ = map[(p->data4[2] >>  0) & 0x0f];
01048     *string++ = map[(p->data4[3] >>  4) & 0x0f];
01049     *string++ = map[(p->data4[3] >>  0) & 0x0f];
01050     *string++ = map[(p->data4[4] >>  4) & 0x0f];
01051     *string++ = map[(p->data4[4] >>  0) & 0x0f];
01052     *string++ = map[(p->data4[5] >>  4) & 0x0f];
01053     *string++ = map[(p->data4[5] >>  0) & 0x0f];
01054     *string++ = map[(p->data4[6] >>  4) & 0x0f];
01055     *string++ = map[(p->data4[6] >>  0) & 0x0f];
01056     *string++ = map[(p->data4[7] >>  4) & 0x0f];
01057     *string++ = map[(p->data4[7] >>  0) & 0x0f];
01058     
01059     if (withBraces)
01060         *string++ = '}';
01061 
01062     *string++ = '\0';
01063 }
01064 
01065 
01066 static inline PlankB pl_GUID_Equal (const PlankGUID* p, const PlankGUID* other)
01067 {
01068     return pl_MemoryCompare (p, other, sizeof (PlankGUID));
01069 }
01070 
01071 static inline PlankB pl_GUID_EqualWithString (const PlankGUID* p, const char* other)
01072 {
01073     PlankGUID guid;
01074     
01075     if (pl_GUID_InitString (&guid, other) != PlankResult_OK)
01076         return PLANK_FALSE;
01077     
01078     return pl_MemoryCompare (p, &guid, sizeof (PlankGUID));
01079 }
01080 
01081 
01082 static inline PlankB pl_GUID_IsNull (const PlankGUID* p)
01083 {
01084     return (p->data1 == 0) && (p->data2 == 0) && (p->data3 == 0) && ((*(PlankULL*)p->data4) == 0);
01085 }
01086 
01088 
01089 
01090 #endif // PLANK_CONTAINERSMISC_H
 All Classes Functions Typedefs Enumerations Enumerator Properties