types.h

Go to the documentation of this file.
00001 
00007 /*
00008  *  Copyright (c) 2003, Matt Beard
00009  *
00010  *  This software is provided 'as-is', without any express or implied warranty.
00011  *  In no event will the authors be held liable for any damages arising from
00012  *  the use of this software.
00013  *
00014  *  Permission is granted to anyone to use this software for any purpose,
00015  *  including commercial applications, and to alter it and redistribute it
00016  *  freely, subject to the following restrictions:
00017  *
00018  *    1. The origin of this software must not be misrepresented; you must
00019  *       not claim that you wrote the original software. If you use this
00020  *       software in a product, an acknowledgment in the product
00021  *       documentation would be appreciated but is not required.
00022  *  
00023  *    2. Altered source versions must be plainly marked as such, and must
00024  *       not be misrepresented as being the original software.
00025  *  
00026  *    3. This notice may not be removed or altered from any source
00027  *       distribution.
00028  */
00029 
00030 #ifndef MXFLIB__TYPES_H
00031 #define MXFLIB__TYPES_H
00032 
00033 // Ensure NULL is available
00034 #include <stdlib.h>
00035 
00036 // Standard library includes
00037 #include <list>
00038 
00039 
00040 /*                        */
00041 /* Basic type definitions */
00042 /*                        */
00043 
00044 namespace mxflib
00045 {
00046     typedef Int64 Length;               
00047     typedef Int64 Position;             
00048 
00049     typedef UInt16 Tag;                 
00050 
00052     typedef std::pair<UInt32, UInt32> U32Pair;
00053 }
00054 
00055 
00056 // Some string conversion utilities
00057 namespace mxflib
00058 {
00060     inline std::string Tag2String(Tag value)
00061     {
00062         char Buffer[8];
00063         sprintf(Buffer, "%02x.%02x", value >> 8, value & 0xff);
00064         return std::string(Buffer);
00065     }
00066 }
00067 
00068 
00069 namespace mxflib
00070 {
00071     template <int SIZE> class Identifier /*: public RefCount<Identifier<SIZE> >*/
00072     {
00073     protected:
00074         UInt8 Ident[SIZE];
00075     public:
00076         Identifier(const UInt8 *ID = NULL) { if(ID == NULL) memset(Ident,0,SIZE); else memcpy(Ident,ID, SIZE); };
00077         Identifier(const SmartPtr<Identifier> ID) { ASSERT(SIZE == ID->Size()); if(!ID) memset(Ident,0,SIZE); else memcpy(Ident,ID->Ident, SIZE); };
00078         
00080         void Set(const UInt8 *ID = NULL) { if(ID == NULL) memset(Ident,0,SIZE); else memcpy(Ident,ID, SIZE); };
00081 
00083         void Set(int Index, UInt8 Value) { if(Index < SIZE) Ident[Index] = Value; };
00084 
00086         const UInt8 *GetValue(void) const { return Ident; };
00087 
00089         int Size(void) const { return SIZE; };
00090 
00091         bool operator!(void) const
00092         {
00093             int i;
00094             for(i=0; i<SIZE; i++) if(Ident[i]) return false;
00095             return true;
00096         }
00097 
00098         bool operator<(const Identifier& Other) const
00099         {
00100             if(Other.Size() < SIZE ) return (memcmp(Ident, Other.Ident, Other.Size()) < 0);
00101                                 else return (memcmp(Ident, Other.Ident, SIZE) < 0);
00102         }
00103 
00104         bool operator==(const Identifier& Other) const
00105         {
00106             if(Other.Size() != SIZE ) return false;
00107                                  else return (memcmp(Ident, Other.Ident, SIZE) == 0);
00108         }
00109 
00110         std::string GetString(void) const
00111         {
00112             std::string Ret;
00113             char Buffer[8];
00114 
00115             for(int i=0; i<SIZE; i++)
00116             {
00117                 sprintf(Buffer, "%02x", Ident[i]);
00118                 if(i!=0) Ret += " ";
00119 
00120                 Ret += Buffer;
00121             }
00122 
00123             return Ret;
00124         }
00125     };
00126 
00127 }
00128 
00129 namespace mxflib
00130 {
00131     // Forward declare UUID
00132     class UUID;
00133     
00135     typedef SmartPtr<UUID> UUIDPtr;
00136     
00138     typedef Identifier<16> Identifier16;
00139 
00141     class UL : public RefCount<UL>, public Identifier16
00142     {
00143     private:
00145         UL();
00146 
00147     public:
00149 
00151         UL(const UInt8 *ID) : Identifier16(ID) {};
00152 
00154         UL(const SmartPtr<UL> ID) { if(!ID) memset(Ident,0,16); else memcpy(Ident,ID->Ident, 16); };
00155 
00157         UL(const UL &RHS) { memcpy(Ident,RHS.Ident, 16); };
00158 
00160         UL(const UUID &RHS) { operator=(RHS); }
00161 
00163         UL(const UUIDPtr &RHS) { operator=(*RHS); }
00164 
00166         UL(const UUID *RHS) { operator=(*RHS); }
00167 
00169 
00172         bool operator==(const UL &RHS) const
00173         {
00174             // Most differences are in the second 8 bytes so we check those first
00175             UInt8 const *pLHS = &Ident[8];
00176             UInt8 const *pRHS = &RHS.Ident[8];
00177             
00178             if(*pLHS++ != *pRHS++) return false;        // Test byte 8
00179             if(*pLHS++ != *pRHS++) return false;        // Test byte 9
00180             if(*pLHS++ != *pRHS++) return false;        // Test byte 10
00181             if(*pLHS++ != *pRHS++) return false;        // Test byte 11
00182             if(*pLHS++ != *pRHS++) return false;        // Test byte 12
00183             if(*pLHS++ != *pRHS++) return false;        // Test byte 13
00184             if(*pLHS++ != *pRHS++) return false;        // Test byte 14
00185             if(*pLHS != *pRHS) return false;            // Test byte 15
00186 
00187             // Now we test the first 8 bytes, but in reverse as the first 4 are almost certainly "06 0e 2b 34"
00188             // We use predecrement from the original start values so that the compiler will optimize the address calculation if possible
00189             pLHS = &Ident[8];
00190             pRHS = &RHS.Ident[8];
00191 
00192             if(*--pLHS != *--pRHS) return false;        // Test byte 7
00193             if(*--pLHS != *--pRHS) return false;        // Test byte 6
00194             if(*--pLHS != *--pRHS) return false;        // Test byte 5
00195             if(*--pLHS != *--pRHS) return false;        // Test byte 4
00196             if(*--pLHS != *--pRHS) return false;        // Test byte 3
00197             if(*--pLHS != *--pRHS) return false;        // Test byte 2
00198             if(*--pLHS != *--pRHS) return false;        // Test byte 1
00199             
00200             return (*--pLHS == *--pRHS);                // Test byte 0
00201         }
00202 
00204 
00207         bool Matches(const UL &RHS) const
00208         {
00209             // Most differences are in the second 8 bytes so we check those first
00210             UInt8 const *pLHS = &Ident[8];
00211             UInt8 const *pRHS = &RHS.Ident[8];
00212             
00213             if(*pLHS++ != *pRHS++) return false;        // Test byte 8
00214             if(*pLHS++ != *pRHS++) return false;        // Test byte 9
00215             if(*pLHS++ != *pRHS++) return false;        // Test byte 10
00216             if(*pLHS++ != *pRHS++) return false;        // Test byte 11
00217             if(*pLHS++ != *pRHS++) return false;        // Test byte 12
00218             if(*pLHS++ != *pRHS++) return false;        // Test byte 13
00219             if(*pLHS++ != *pRHS++) return false;        // Test byte 14
00220             if(*pLHS != *pRHS) return false;            // Test byte 15
00221 
00222             // Now we test the first 8 bytes, but in reverse as the first 4 are almost certainly "06 0e 2b 34"
00223             // We use predecrement from the original start values so that the compiler will optimize the address calculation if possible
00224             pLHS = &Ident[8];
00225             pRHS = &RHS.Ident[8];
00226 
00227             // Skip the UL version number
00228             --pLHS;
00229             --pRHS;
00230 
00231             if(*--pLHS != *--pRHS) return false;        // Test byte 6
00232             if(*--pLHS != *--pRHS) return false;        // Test byte 5
00233             if(*--pLHS != *--pRHS) return false;        // Test byte 4
00234             if(*--pLHS != *--pRHS) return false;        // Test byte 3
00235             if(*--pLHS != *--pRHS) return false;        // Test byte 2
00236             if(*--pLHS != *--pRHS) return false;        // Test byte 1
00237             
00238             return (*--pLHS == *--pRHS);                // Test byte 0
00239         }
00240 
00242         UL &operator=(const UUID &RHS);
00243 
00245         UL &operator=(const UUIDPtr &RHS) { return operator=(*RHS); }
00246 
00248         UL &operator=(const UUID *RHS) { return operator=(*RHS); }
00249 
00251         std::string GetString(void) const
00252         {
00253             char Buffer[100];
00254 
00255             // Check which format should be used
00256             if( !(0x80&Ident[0]) )
00257             {   
00258                 // This is a UL rather than a UUID packed into a UL datatype
00259                 // Print as compact SMPTE format [060e2b34.rrss.mmvv.ccs1s2s3.s4s5s6s7]
00260                 // Stored in the following 0-based index order: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
00261                 // (i.e. network byte order)
00262                 sprintf (Buffer, "[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x]",
00263                                    Ident[0], Ident[1], Ident[2], Ident[3], Ident[4], Ident[5], Ident[6], Ident[7],
00264                                    Ident[8], Ident[9], Ident[10], Ident[11], Ident[12], Ident[13], Ident[14], Ident[15]
00265                         );
00266             }
00267             else
00268             {   
00269                 // Half-swapped UUID
00270                 // Print as compact GUID format {8899aabb-ccdd-eeff-0011-223344556677}
00271                 sprintf (Buffer, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
00272                                    Ident[8], Ident[9], Ident[10], Ident[11], Ident[12], Ident[13], Ident[14], Ident[15],
00273                                    Ident[0], Ident[1], Ident[2], Ident[3], Ident[4], Ident[5], Ident[6], Ident[7]
00274                         );
00275             }
00276 
00277             return std::string(Buffer);
00278         }
00279     };
00280 
00282     typedef SmartPtr<UL> ULPtr;
00283 
00285     typedef std::list<ULPtr> ULList;
00286 }
00287 
00288 
00289 namespace mxflib
00290 {
00292     class UUID : public Identifier16, public RefCount<UUID>
00293     {
00294     public:
00296         UUID() { MakeUUID(Ident); };
00297 
00299 
00301         UUID(const UInt8 *ID) : Identifier16(ID) {};
00302 
00304         UUID(const SmartPtr<UUID> ID) { if(!ID) memset(Ident,0,16); else memcpy(Ident,ID->Ident, 16); };
00305 
00307         UUID(const UUID &RHS) { memcpy(Ident,RHS.Ident, 16); };
00308 
00310         UUID(const UL &RHS) { operator=(RHS); }
00311 
00313         UUID(const ULPtr &RHS) { operator=(*RHS); }
00314 
00316         UUID(const UL *RHS) { operator=(*RHS); }
00317 
00319         UUID &operator=(const UL &RHS)
00320         {
00321             memcpy(Ident, &RHS.GetValue()[8], 8);
00322             memcpy(&Ident[8], RHS.GetValue(), 8);
00323             return *this;
00324         }
00325 
00327         UUID &operator=(const ULPtr &RHS) { return operator=(*RHS); }
00328 
00330         UUID &operator=(const UL *RHS) { return operator=(*RHS); }
00331 
00333         std::string GetString(void) const
00334         {
00335             char Buffer[100];
00336 
00337             // Check which format should be used
00338             if( !(0x80&Ident[8]) )
00339             {   // Half-swapped UL packed into a UUID datatype
00340                 // Print as compact SMPTE format [bbaa9988.ddcc.ffee.00010203.04050607]
00341                 // Stored with upper/lower 8 bytes exchanged
00342                 // Stored in the following 0-based index order: 88 99 aa bb cc dd ee ff 00 01 02 03 04 05 06 07
00343                 sprintf (Buffer, "[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x]",
00344                                    Ident[8], Ident[9], Ident[10], Ident[11], Ident[12], Ident[13], Ident[14], Ident[15],
00345                                    Ident[0], Ident[1], Ident[2], Ident[3], Ident[4], Ident[5], Ident[6], Ident[7]
00346                         );
00347             }
00348             else
00349             {   // UUID
00350                 // Stored in the following 0-based index order: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff
00351                 // (i.e. network byte order)
00352                 // Print as compact GUID format {00112233-4455-6677-8899-aabbccddeeff}
00353                 sprintf (Buffer, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
00354                                    Ident[0], Ident[1], Ident[2], Ident[3], Ident[4], Ident[5], Ident[6], Ident[7],
00355                                    Ident[8], Ident[9], Ident[10], Ident[11], Ident[12], Ident[13], Ident[14], Ident[15]
00356                         );
00357             }
00358 
00359             return std::string(Buffer);
00360         }
00361     };
00362 }
00363 
00364 
00365 namespace mxflib
00366 {
00368     /*  DRAGONS: Defined here as we need UUID to be fully defined */
00369     inline UL &UL::operator=(const UUID &RHS)
00370     {
00371         memcpy(Ident, &RHS.GetValue()[8], 8);
00372         memcpy(&Ident[8], RHS.GetValue(), 8);
00373         return *this;
00374     }
00375 }
00376 
00377 
00378 namespace mxflib
00379 {
00380     typedef Identifier<32> Identifier32;
00381     class UMID : public Identifier32, public RefCount<UMID>
00382     {
00383     public:
00385 
00387         UMID(const UInt8 *ID = NULL) : Identifier32(ID) {};
00388 
00390 
00392         UMID(const SmartPtr<UMID> ID) { if(!ID) memset(Ident,0,32); else memcpy(Ident,ID->Ident, 32); };
00393 
00395         UMID(const UMID &RHS) { memcpy(Ident,RHS.Ident, 16); };
00396 
00398 
00399         UInt32 GetInstance(void) const
00400         {
00401             return (Ident[13] << 16) | (Ident[14] << 8) | Ident[15];
00402         }
00403 
00405 
00406         //  TODO: Should add an option to generate a random instance number
00407         void SetInstance(int Instance, int Method = -1)
00408         {
00409             UInt8 Buffer[4];
00410             PutU32(Instance, Buffer);
00411 
00412             // Set the instance number
00413             memcpy(&Ident[13], &Buffer[1], 3);
00414 
00415             // Set the method if a new one is specified
00416             if(Method >= 0)
00417             {
00418                 Ident[11] = (Ident[11] & 0xf0) | Method;
00419             }
00420         }
00421 
00423         void SetMaterial( ULPtr aUL )
00424         {
00425             // Set the instance number
00426             memcpy(&Ident[16], aUL->GetValue(), 16);
00427 
00428             // DRAGONS: Is this the right method for a UL?
00429             Ident[11] = (Ident[11] & 0x0f) | 2<<4;
00430         }
00431     };
00432 
00434     typedef SmartPtr<UMID> UMIDPtr;
00435 }
00436 
00437 
00438 namespace mxflib
00439 {
00441     class Rational
00442     {
00443     public:
00444         Int32 Numerator;                
00445         Int32 Denominator;              
00446     
00448         Rational() : Numerator(0), Denominator(0) {};
00449 
00451         Rational(Int32 Num, Int32 Den) : Numerator(Num), Denominator(Den) {};
00452 
00454         Int32 GreatestCommonDivisor(void) 
00455         {
00456             Int32 a;            
00457             Int32 b;            
00458             
00459             // Set the larger and smaller values
00460             if(Numerator>Denominator)
00461             {
00462                 a = Numerator;
00463                 b = Denominator;
00464             }
00465             else
00466             {
00467                 a = Denominator;
00468                 b = Numerator;
00469             }
00470             
00471             // Euclid's Algorithm
00472             while (b != 0) 
00473             {
00474                 Int32 Temp = b;
00475                 b = a % b;
00476                 a = Temp;
00477             }
00478 
00479             // Return the GCD
00480             return a;
00481         }
00482 
00484         void Reduce(void)
00485         {
00486             Int32 GCD = GreatestCommonDivisor();
00487             Numerator /= GCD;
00488             Denominator /= GCD;
00489         }
00490         
00492         inline bool operator==(const Rational &RHS)
00493         {
00494             return (Numerator == RHS.Numerator) && (Denominator == RHS.Denominator);
00495         }
00496     };
00497 
00499     inline Int64 GreatestCommonDivisor( Int64 Numerator, Int64 Denominator )
00500     {
00501         Int64 a;            
00502         Int64 b;            
00503         
00504         // Set the larger and smaller values
00505         if(Numerator>Denominator)
00506         {
00507             a = Numerator;
00508             b = Denominator;
00509         }
00510         else
00511         {
00512             a = Denominator;
00513             b = Numerator;
00514         }
00515         
00516         // Euclid's Algorithm
00517         while (b != 0) 
00518         {
00519             Int64 Temp = b;
00520             b = a % b;
00521             a = Temp;
00522         }
00523 
00524         // Return the GCD
00525         return a;
00526     }
00527 
00529     inline Rational operator/(const Rational Dividend, const Rational Divisor)
00530     {
00531         // Multiply the numerator of the dividend by the denominator of the divisor (getting a 64-bit result)
00532         Int64 Numerator = Dividend.Numerator;
00533         Numerator *= Divisor.Denominator;
00534 
00535         // Multiply the denominator of the dividend by the numerator of the divisor (getting a 64-bit result)
00536         Int64 Denominator = Dividend.Denominator;
00537         Denominator *= Divisor.Numerator;
00538 
00539         // Calculate the greated common divisor
00540         Int64 GCD = GreatestCommonDivisor(Numerator, Denominator);
00541         
00542         Numerator /= GCD;
00543         Denominator /= GCD;
00544 
00545         // Lossy-reduction of any fractions that won't fit in a 32-bit/ 32-bit rational
00546         // TDOD: Check if this is ever required
00547         while( (Numerator & INT64_C(0xffffffff00000000)) ||  (Denominator & INT64_C(0xffffffff00000000)))
00548         {
00549             Numerator >>= 1;
00550             Denominator >>= 1;
00551         }
00552 
00553         return Rational(static_cast<Int32>(Numerator), static_cast<Int32>(Denominator));
00554     }
00555 
00557     inline Rational operator*(const Rational Multiplicand, const Rational Multiplier)
00558     {
00559         // Multiply the numerator of the multiplicand by the numerator of the multiplier (getting a 64-bit result)
00560         Int64 Numerator = Multiplicand.Numerator;
00561         Numerator *= Multiplier.Numerator;
00562 
00563         // Multiply the denominator of the multiplicand by the denominator of the multiplier (getting a 64-bit result)
00564         Int64 Denominator = Multiplicand.Denominator;
00565         Denominator *= Multiplier.Denominator;
00566 
00567         // Calculate the greated common divisor
00568         Int64 GCD = GreatestCommonDivisor(Numerator, Denominator);
00569         
00570         Numerator /= GCD;
00571         Denominator /= GCD;
00572 
00573         // Lossy-reduction of any fractions that won't fit in a 32-bit/ 32-bit rational
00574         // TDOD: Check if this is ever required
00575         while( (Numerator & INT64_C(0xffffffff00000000)) ||  (Denominator & INT64_C(0xffffffff00000000)))
00576         {
00577             Numerator >>= 1;
00578             Denominator >>= 1;
00579         }
00580 
00581         return Rational(static_cast<Int32>(Numerator), static_cast<Int32>(Denominator));
00582     }
00583 
00585     inline Position operator*(const Position Multiplicand, const Rational Multiplier)
00586     {
00587         Position Ret = Multiplicand * Multiplier.Numerator;
00588 
00589         Int64 Remainder = Ret % Multiplier.Denominator;
00590 
00591         Ret = Ret / Multiplier.Denominator;
00592 
00593         // Round up any result that is nearer to the next position
00594         if(Remainder >= (Multiplier.Denominator/2)) Ret++;
00595 
00596         return Ret;
00597     }
00598 }
00599 
00600 
00601 #endif // MXFLIB__TYPES_H
00602 

Generated on Mon Apr 2 15:20:54 2007 for MXFLib by  doxygen 1.5.1-p1