首页 > 学院 > 开发设计 > 正文

QTSSDictionaryMap 详解

2019-11-11 05:11:38
字体:
来源:转载
供稿:网友

QTSSDictionaryMap里面存放了一堆的属性(fAttrArray),每一个属性都包含属性名称,属性类型,属性权限等:DictValueElement数组存放了一组熟悉的特征 

/* * * @APPLE_LICENSE_HEADER_START@ *  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. *  * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. *  * @APPLE_LICENSE_HEADER_END@ * *//*    File:       QTSSDictionary.h    Contains:   Definitions of two classes: QTSSDictionary and QTSSDictionaryMap.                Collectively, these classes implement the "dictionary" APIs in QTSS                API. A QTSSDictionary corresponds to a QTSS_Object,                a QTSSDictionaryMap corresponds to a QTSS_ObjectType.    Created: Tue, Mar 2, 1999 @ 4:23 PM*/#ifndef _QTSSDICTIONARY_H_#define _QTSSDICTIONARY_H_#include <stdlib.h>#include "SafeStdLib.h"#include "QTSS.h"#include "OSHeaders.h"#include "OSMutex.h"#include "StrPtrLen.h"#include "MyAssert.h"#include "QTSSStream.h"class QTSSDictionary;class QTSSDictionaryMap;class QTSSAttrInfoDict;#define __DICTIONARY_TESTING__ 0//// Function prototype for attr functionstypedef void* (*QTSS_AttrFunctionPtr)(QTSSDictionary* , UInt32* );class QTSSDictionary : public QTSSStream{    public:            //        // CONSTRUCTOR / DESTRUCTOR                QTSSDictionary(QTSSDictionaryMap* inMap, OSMutex* inMutex = NULL);        virtual ~QTSSDictionary();                //        // QTSS API CALLS                // Flags used by internal callers of these routines        enum        {            kNoFlags = 0,            kDontObeyReadOnly = 1,            kDontCallCompletionRoutine = 2        };                // This version of GetValue copies the element into a buffer provided by the caller        // Returns:     QTSS_BadArgument, QTSS_NotPreemptiveSafe (if attribute is not preemptive safe),        //              QTSS_BadIndex (if inIndex is bad)        QTSS_Error GetValue(QTSS_AttributeID inAttrID, UInt32 inIndex, void* ioValueBuffer, UInt32* ioValueLen);        //This version of GetValue returns a pointer to the internal buffer for the attribute.        //Only usable if the attribute is preemptive safe.        //        // Returns:     Same as above, but also QTSS_NotEnoughSpace, if value is too big for buffer.        QTSS_Error GetValuePtr(QTSS_AttributeID inAttrID, UInt32 inIndex, void** outValueBuffer, UInt32* outValueLen)                        { return GetValuePtr(inAttrID, inIndex, outValueBuffer, outValueLen, false); }                // This version of GetValue converts the value to a string before returning it. Memory for        // the string is allocated internally.        //        // Returns: QTSS_BadArgument, QTSS_BadIndex, QTSS_ValueNotFound        QTSS_Error GetValueAsString(QTSS_AttributeID inAttrID, UInt32 inIndex, char** outString);                // Returns:     QTSS_BadArgument, QTSS_ReadOnly (if attribute is read only),        //              QTSS_BadIndex (attempt to set indexed parameter with param retrieval)        QTSS_Error SetValue(QTSS_AttributeID inAttrID, UInt32 inIndex,                            const void* inBuffer,  UInt32 inLen, UInt32 inFlags = kNoFlags);                // Returns:     QTSS_BadArgument, QTSS_ReadOnly (if attribute is read only),        QTSS_Error SetValuePtr(QTSS_AttributeID inAttrID,                            const void* inBuffer,  UInt32 inLen, UInt32 inFlags = kNoFlags);                // Returns:     QTSS_BadArgument, QTSS_ReadOnly (if attribute is read only),        QTSS_Error CreateObjectValue(QTSS_AttributeID inAttrID, UInt32* outIndex,                                        QTSSDictionary** newObject, QTSSDictionaryMap* inMap = NULL,                                         UInt32 inFlags = kNoFlags);                // Returns:     QTSS_BadArgument, QTSS_ReadOnly, QTSS_BadIndex        QTSS_Error RemoveValue(QTSS_AttributeID inAttrID, UInt32 inIndex, UInt32 inFlags = kNoFlags);                // Utility routine used by the two external flavors of GetValue        QTSS_Error GetValuePtr(QTSS_AttributeID inAttrID, UInt32 inIndex,                                            void** outValueBuffer, UInt32* outValueLen,                                            Bool16 isInternal);        //        // accessORS                QTSSDictionaryMap*  GetDictionaryMap() { return fMap; }                // Returns the Instance dictionary map for this dictionary. This may return NULL        // if there are no instance attributes in this dictionary        QTSSDictionaryMap*  GetInstanceDictMap() { return fInstanceMap; }                // Returns the number of values associated with a given attribute        UInt32              GetNumValues(QTSS_AttributeID inAttrID);        void                SetNumValues(QTSS_AttributeID inAttrID, UInt32 inNumValues);                // Meant only for internal server use. Does no error checking,        // doesn't invoke the param retrieval function.        StrPtrLen*  GetValue(QTSS_AttributeID inAttrID)                     {   return &fAttributes[inAttrID].fAttributeData;   }                            OSMutex*    GetMutex() { return fMutexP; }				void		SetLocked(Bool16 inLocked) { fLocked = inLocked; }		Bool16		IsLocked() { return fLocked; }        //        // GETTING ATTRIBUTE INFO        QTSS_Error GetAttrInfoByIndex(UInt32 inIndex, QTSSAttrInfoDict** outAttrInfoDict);        QTSS_Error GetAttrInfoByName(const char* inAttrName, QTSSAttrInfoDict** outAttrInfoDict);        QTSS_Error GetAttrInfoByID(QTSS_AttributeID inAttrID, QTSSAttrInfoDict** outAttrInfoDict);                //        // INSTANCE ATTRIBUTES                QTSS_Error  AddInstanceAttribute(   const char* inAttrName,                                            QTSS_AttrFunctionPtr inFuncPtr,                                            QTSS_AttrDataType inDataType,                                            QTSS_AttrPermission inPermission );                                                    QTSS_Error  RemoveInstanceAttribute(QTSS_AttributeID inAttr);        //        // MODIFIERS        // These functions are meant to be used by the server when it is setting up the        // dictionary attributes. They do no error checking.        // They don't set fNumAttributes & fAllocatedInternally.        void    SetVal(QTSS_AttributeID inAttrID, void* inValueBuffer, UInt32 inBufferLen);        void    SetVal(QTSS_AttributeID inAttrID, StrPtrLen* inNewValue)                    { this->SetVal(inAttrID, inNewValue->Ptr, inNewValue->Len); }        // Call this if you want to assign empty storage to an attribute        void    SetEmptyVal(QTSS_AttributeID inAttrID, void* inBuf, UInt32 inBufLen);        #if __DICTIONARY_TESTING__        static void Test(); // API test for these objects#endif    protected:            // Derived classes can provide a completion routine for some dictionary functions        virtual void    RemoveValueComplete(UInt32 /*inAttrIndex*/, QTSSDictionaryMap* /*inMap*/, UInt32 /*inValueIndex*/) {}                virtual void    SetValueComplete(UInt32 /*inAttrIndex*/, QTSSDictionaryMap* /*inMap*/,                                    UInt32 /*inValueIndex*/,  void* /*inNewValue*/, UInt32 /*inNewValueLen*/) {}        virtual void    RemoveInstanceAttrComplete(UInt32 /*inAttrindex*/, QTSSDictionaryMap* /*inMap*/) {}                virtual QTSSDictionary* CreateNewDictionary(QTSSDictionaryMap* inMap, OSMutex* inMutex);    private:            struct DictValueElement        {            // This stores all necessary information for each attribute value.                        DictValueElement() :    fAllocatedLen(0), fNumAttributes(0),                                    fAllocatedInternally(false), fIsDynamicDictionary(false) {}                                                // Does not delete! You Must call DeleteAttributeData for that            ~DictValueElement() {}                        StrPtrLen   fAttributeData; // The data            UInt32      fAllocatedLen;  // How much space do we have allocated?            UInt32      fNumAttributes; // If this is an iterated attribute, how many?            Bool16      fAllocatedInternally; //Should we delete this memory?            Bool16      fIsDynamicDictionary; //is this a dictionary object?        };                DictValueElement*   fAttributes;        DictValueElement*   fInstanceAttrs;        UInt32              fInstanceArraySize;        QTSSDictionaryMap*  fMap;        QTSSDictionaryMap*  fInstanceMap;        OSMutex*            fMutexP;		Bool16				fMyMutex;		Bool16				fLocked;                void DeleteAttributeData(DictValueElement* inDictValues, UInt32 inNumValues);};class QTSSAttrInfoDict : public QTSSDictionary{    public:            struct AttrInfo        {            // This is all the relevent information for each dictionary            // attribute.            char                    fAttrName[QTSS_MAX_ATTRIBUTE_NAME_SIZE + 1];            QTSS_AttrFunctionPtr    fFuncPtr;            QTSS_AttrDataType       fAttrDataType;            QTSS_AttrPermission     fAttrPermission;        };        QTSSAttrInfoDict();        virtual ~QTSSAttrInfoDict();            private:                AttrInfo fAttrInfo;        QTSS_AttributeID fID;                static AttrInfo sAttributes[];                friend class QTSSDictionaryMap;};class QTSSDictionaryMap{    public:            //        // This must be called before using any QTSSDictionary or QTSSDictionaryMap functionality        static void Initialize();                // Stores all meta-information for attributes                // CONSTRUCTOR FLAGS        enum        {            kNoFlags        = 0,            kAllowRemoval   = 1,    //是否允许删除元素            kIsInstanceMap  = 2,            kInstanceAttrsAllowed = 4,            kCompleteFunctionsAllowed = 8        };                //        // CONSTRUCTOR / DESTRUCTOR                QTSSDictionaryMap(UInt32 inNumReservedAttrs, UInt32 inFlags = kNoFlags);        ~QTSSDictionaryMap(){ delete fAttrArray; }        //        // QTSS API CALLS                 		//添加属性,从头遍历如果发现有        QTSS_Error      AddAttribute(   const char* inAttrName,                                        QTSS_AttrFunctionPtr inFuncPtr,                                        QTSS_AttrDataType inDataType,                                        QTSS_AttrPermission inPermission );                                                //        // Marks this attribute as removed        QTSS_Error  RemoveAttribute(QTSS_AttributeID inAttrID);        QTSS_Error  UnRemoveAttribute(QTSS_AttributeID inAttrID);        QTSS_Error  CheckRemovePermission(QTSS_AttributeID inAttrID);        //        // Searching / Iteration. These never return removed attributes        QTSS_Error  GetAttrInfoByName(const char* inAttrName, QTSSAttrInfoDict** outAttrInfoDict, Bool16 returnRemovedAttr = false);        QTSS_Error  GetAttrInfoByID(QTSS_AttributeID inID, QTSSAttrInfoDict** outAttrInfoDict);        QTSS_Error  GetAttrInfoByIndex(UInt32 inIndex, QTSSAttrInfoDict** outAttrInfoDict);        QTSS_Error  GetAttrID(const char* inAttrName, QTSS_AttributeID* outID);                //        // PRIVATE ATTR PERMISSIONS		//是否已经删除属性        enum        {            qtssPrivateAttrModeRemoved = 0x80000000        };        //        // CONVERTING attribute IDs to array indexes. Returns -1 if inAttrID doesn't exist        inline SInt32                   ConvertAttrIDToArrayIndex(QTSS_AttributeID inAttrID);        static Bool16           IsInstanceAttrID(QTSS_AttributeID inAttrID)            { return (inAttrID & 0x80000000) != 0; }        // ACCESSORS                // These functions do no error checking. Be careful.                // Includes removed attributes        UInt32          GetNumAttrs()           { return fNextAvailableID; }        UInt32          GetNumNonRemovedAttrs() { return fNumValidAttrs; }                Bool16                  IsPreemptiveSafe(UInt32 inIndex)             { Assert(inIndex < fNextAvailableID); return (Bool16) (fAttrArray[inIndex]->fAttrInfo.fAttrPermission & qtssAttrModePreempSafe); }        Bool16                  IsWriteable(UInt32 inIndex)             { Assert(inIndex < fNextAvailableID); return (Bool16) (fAttrArray[inIndex]->fAttrInfo.fAttrPermission & qtssAttrModeWrite); }				Bool16                  IsCacheable(UInt32 inIndex)             { Assert(inIndex < fNextAvailableID); return (Bool16) (fAttrArray[inIndex]->fAttrInfo.fAttrPermission & qtssAttrModeCacheable); }        Bool16                  IsRemoved(UInt32 inIndex)             { Assert(inIndex < fNextAvailableID); return (Bool16) (fAttrArray[inIndex]->fAttrInfo.fAttrPermission & qtssPrivateAttrModeRemoved) ; }        QTSS_AttrFunctionPtr    GetAttrFunction(UInt32 inIndex)            { Assert(inIndex < fNextAvailableID); return fAttrArray[inIndex]->fAttrInfo.fFuncPtr; }                    char*                   GetAttrName(UInt32 inIndex)            { Assert(inIndex < fNextAvailableID); return fAttrArray[inIndex]->fAttrInfo.fAttrName; }                    QTSS_AttributeID        GetAttrID(UInt32 inIndex)            { Assert(inIndex < fNextAvailableID); return fAttrArray[inIndex]->fID; }        QTSS_AttrDataType       GetAttrType(UInt32 inIndex)            { Assert(inIndex < fNextAvailableID); return fAttrArray[inIndex]->fAttrInfo.fAttrDataType; }                Bool16                  InstanceAttrsAllowed() { return (Bool16) (fFlags & kInstanceAttrsAllowed); }        Bool16                  CompleteFunctionsAllowed() { return (Bool16) (fFlags & kCompleteFunctionsAllowed) ; }        // MODIFIERS                // Sets this attribute ID to have this information                void        SetAttribute(   QTSS_AttributeID inID,                                     const char* inAttrName,                                    QTSS_AttrFunctionPtr inFuncPtr,                                    QTSS_AttrDataType inDataType,                                    QTSS_AttrPermission inPermission );                //        // DICTIONARY MAPS                // All dictionary maps are stored here, and are accessable        // through these routines                // This enum allows all QTSSDictionaryMaps to be stored in an array         enum        {            kServerDictIndex                = 0,            kPrefsDictIndex                 = 1,            kTextMessagesDictIndex          = 2,            kServiceDictIndex               = 3,                        kRTPStreamDictIndex             = 4,            kClientsessionDictIndex         = 5,            kRTSPSessionDictIndex           = 6,            kRTSPRequestDictIndex           = 7,            kRTSPHeaderDictIndex            = 8,            kFileDictIndex                  = 9,            kModuleDictIndex                = 10,            kModulePrefsDictIndex           = 11,            kAttrInfoDictIndex              = 12,            kQTSSUserProfileDictIndex       = 13,            kQTSSConnectedUserDictIndex     = 14,            kNumDictionaries                = 15,                        kNumDynamicDictionaryTypes      = 500,            kIllegalDictionary              = kNumDynamicDictionaryTypes + kNumDictionaries        };                // This function converts a QTSS_ObjectType to an index        static UInt32                   GetMapIndex(QTSS_ObjectType inType);        // Using one of the above predefined indexes, this returns the corresponding map        static QTSSDictionaryMap*       GetMap(UInt32 inIndex)            { Assert(inIndex < kNumDynamicDictionaryTypes + kNumDictionaries); return sDictionaryMaps[inIndex]; }        static QTSS_ObjectType          CreateNewMap();    private:        //        // Repository for dictionary maps                static QTSSDictionaryMap*       sDictionaryMaps[kNumDictionaries + kNumDynamicDictionaryTypes];        static UInt32                   sNextDynamicMap;                    enum        {            kMinArraySize = 20        };        UInt32                          fNextAvailableID;//所有的分配过的属性,只要该属性有fid标识就算(包含qtssPrivateAttrModeRemoved标识)        UInt32                          fNumValidAttrs;  //所有没有qtssPrivateAttrModeRemoved标识的属性        UInt32                          fAttrArraySize;  //整个数组的大小。如果添加元素超过该大小,会自动增加成之前的两倍。fAttrArraySize>=fNextAvailableID        QTSSAttrInfoDict**              fAttrArray;        UInt32                          fFlags;                friend class QTSSDictionary;};inline SInt32   QTSSDictionaryMap::ConvertAttrIDToArrayIndex(QTSS_AttributeID inAttrID){    SInt32 theIndex = inAttrID & 0x7FFFFFFF;    if ((theIndex < 0) || (theIndex >= (SInt32)fNextAvailableID))        return -1;    else        return theIndex;}#endif

/* * * @APPLE_LICENSE_HEADER_START@ *  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. *  * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. *  * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. *  * @APPLE_LICENSE_HEADER_END@ * *//*    File:       QTSSDictionary.cpp    Contains:   Implementation of object defined in QTSSDictionary.h                    */#include "QTSSDictionary.h"#include <string.h>#include <stdio.h>#include "MyAssert.h"#include "OSMemory.h"#include "QTSSDataConverter.h"#include <errno.h>QTSSDictionary::QTSSDictionary(QTSSDictionaryMap* inMap, OSMutex* inMutex) :   fAttributes(NULL), fInstanceAttrs(NULL), fInstanceArraySize(0),    fMap(inMap), fInstanceMap(NULL), fMutexP(inMutex), fMyMutex(false), fLocked(false){    if (fMap != NULL)        fAttributes = NEW DictValueElement[inMap->GetNumAttrs()];	if (fMutexP == NULL)	{		fMyMutex = true;		fMutexP = NEW OSMutex();	}}QTSSDictionary::~QTSSDictionary(){    if (fMap != NULL)        this->DeleteAttributeData(fAttributes, fMap->GetNumAttrs());    if (fAttributes != NULL)        delete [] fAttributes;    delete fInstanceMap;    this->DeleteAttributeData(fInstanceAttrs, fInstanceArraySize);    delete [] fInstanceAttrs;	if (fMyMutex)		delete fMutexP;}QTSSDictionary* QTSSDictionary::CreateNewDictionary(QTSSDictionaryMap* inMap, OSMutex* inMutex){    return NEW QTSSDictionary(inMap, inMutex);}QTSS_Error QTSSDictionary::GetValuePtr(QTSS_AttributeID inAttrID, UInt32 inIndex,                                            void** outValueBuffer, UInt32* outValueLen,                                            Bool16 isInternal){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }    if (theMap == NULL)        return QTSS_AttrDoesntExist;        SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);    if (theMapIndex < 0)        return QTSS_AttrDoesntExist;    if (theMap->IsRemoved(theMapIndex))        return QTSS_AttrDoesntExist;    if ((!isInternal) && (!theMap->IsPreemptiveSafe(theMapIndex)) && !this->IsLocked())        return QTSS_NotPreemptiveSafe;    // An iterated attribute cannot have a param retrieval function    if ((inIndex > 0) && (theMap->GetAttrFunction(theMapIndex) != NULL))        return QTSS_BadIndex;    // Check to make sure the index parameter is legal    if ((inIndex > 0) && (inIndex >= theAttrs[theMapIndex].fNumAttributes))        return QTSS_BadIndex;                    // Retrieve the parameter    char* theBuffer = theAttrs[theMapIndex].fAttributeData.Ptr;    *outValueLen = theAttrs[theMapIndex].fAttributeData.Len;    	Bool16 cacheable = theMap->IsCacheable(theMapIndex);	if ( (theMap->GetAttrFunction(theMapIndex) != NULL) && ((cacheable && (*outValueLen == 0)) || !cacheable) )    {        // If function is cacheable: 		// If the parameter doesn't have a value assigned yet, and there is an attribute        // retrieval function provided, invoke that function now.		// If function is *not* cacheable:		// always call the function		        theBuffer = (char*)theMap->GetAttrFunction(theMapIndex)(this, outValueLen);        //If the param retrieval function didn't return an explicit value for this attribute,        //refetch the parameter out of the array, in case the function modified it.                if (theBuffer == NULL)        {            theBuffer = theAttrs[theMapIndex].fAttributeData.Ptr;            *outValueLen = theAttrs[theMapIndex].fAttributeData.Len;        }            }#if DEBUG    else        // Make sure we aren't outside the bounds of attribute memory        Assert(theAttrs[theMapIndex].fAllocatedLen >=            (theAttrs[theMapIndex].fAttributeData.Len * (theAttrs[theMapIndex].fNumAttributes)));#endif    // Return an error if there is no data for this attribute    if (*outValueLen == 0)        return QTSS_ValueNotFound;                theBuffer += theAttrs[theMapIndex].fAttributeData.Len * inIndex;    *outValueBuffer = theBuffer;            // strings need an extra dereference - moved it up    if ((theMap->GetAttrType(theMapIndex) == qtssAttrDataTypeCharArray) && (theAttrs[theMapIndex].fNumAttributes > 1))        {            char** string = (char**)theBuffer;            *outValueBuffer = *string;            //*outValueLen = strlen(*string) + 1;            *outValueLen = strlen(*string);    }        return QTSS_NoErr;}QTSS_Error QTSSDictionary::GetValue(QTSS_AttributeID inAttrID, UInt32 inIndex,                                            void* ioValueBuffer, UInt32* ioValueLen){    // If there is a mutex, lock it and get a pointer to the proper attribute    OSMutexLocker locker(fMutexP);    void* tempValueBuffer = NULL;    UInt32 tempValueLen = 0;    QTSS_Error theErr = this->GetValuePtr(inAttrID, inIndex, &tempValueBuffer, &tempValueLen, true);    if (theErr != QTSS_NoErr)        return theErr;            if (theErr == QTSS_NoErr)    {        // If caller provided a buffer that's too small for this attribute, report that error        if (tempValueLen > *ioValueLen)            theErr = QTSS_NotEnoughSpace;                    // Only copy out the attribute if the buffer is big enough        if ((ioValueBuffer != NULL) && (theErr == QTSS_NoErr))            ::memcpy(ioValueBuffer, tempValueBuffer, tempValueLen);                    // Always set the ioValueLen to be the actual length of the attribute.        *ioValueLen = tempValueLen;    }    return QTSS_NoErr;}QTSS_Error QTSSDictionary::GetValueAsString(QTSS_AttributeID inAttrID, UInt32 inIndex, char** outString){    void* tempValueBuffer;    UInt32 tempValueLen = 0;    if (outString == NULL)          return QTSS_BadArgument;            OSMutexLocker locker(fMutexP);    QTSS_Error theErr = this->GetValuePtr(inAttrID, inIndex, &tempValueBuffer,                                            &tempValueLen, true);    if (theErr != QTSS_NoErr)        return theErr;            QTSSDictionaryMap* theMap = fMap;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))        theMap = fInstanceMap;    if (theMap == NULL)        return QTSS_AttrDoesntExist;        SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);    Assert(theMapIndex >= 0);        *outString = QTSSDataConverter::ValueToString(tempValueBuffer, tempValueLen, theMap->GetAttrType(theMapIndex));    return QTSS_NoErr;}QTSS_Error QTSSDictionary::CreateObjectValue(QTSS_AttributeID inAttrID, UInt32* outIndex,                                        QTSSDictionary** newObject, QTSSDictionaryMap* inMap, UInt32 inFlags){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }        if (theMap == NULL)        return QTSS_AttrDoesntExist;        SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);        // If there is a mutex, make this action atomic.    OSMutexLocker locker(fMutexP);        if (theMapIndex < 0)        return QTSS_AttrDoesntExist;    if ((!(inFlags & kDontObeyReadOnly)) && (!theMap->IsWriteable(theMapIndex)))        return QTSS_ReadOnly;    if (theMap->IsRemoved(theMapIndex))        return QTSS_AttrDoesntExist;    if (theMap->GetAttrType(theMapIndex) != qtssAttrDataTypeQTSS_Object)        return QTSS_BadArgument;            UInt32 numValues = theAttrs[theMapIndex].fNumAttributes;    // if normal QTSSObjects have been added, then we can't add a dynamic one    if (!theAttrs[theMapIndex].fIsDynamicDictionary && (numValues > 0))        return QTSS_ReadOnly;    QTSSDictionary* oldDict = NULL;    *outIndex = numValues;  // add the object into the next spot    UInt32 len = sizeof(QTSSDictionary*);    QTSSDictionary* dict = CreateNewDictionary(inMap, fMutexP);        // kind of a hack to avoid the check in SetValue    theAttrs[theMapIndex].fIsDynamicDictionary = false;    QTSS_Error err = SetValue(inAttrID, *outIndex, &dict, len, inFlags);    if (err != QTSS_NoErr)    {        delete dict;        return err;    }        if (oldDict != NULL)    {        delete oldDict;    }        theAttrs[theMapIndex].fIsDynamicDictionary = true;    *newObject = dict;        return QTSS_NoErr;}QTSS_Error QTSSDictionary::SetValue(QTSS_AttributeID inAttrID, UInt32 inIndex,                                        const void* inBuffer,  UInt32 inLen,                                        UInt32 inFlags){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }        if (theMap == NULL)        return QTSS_AttrDoesntExist;        SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);        // If there is a mutex, make this action atomic.    OSMutexLocker locker(fMutexP);        if (theMapIndex < 0)        return QTSS_AttrDoesntExist;    if ((!(inFlags & kDontObeyReadOnly)) && (!theMap->IsWriteable(theMapIndex)))        return QTSS_ReadOnly;    if (theMap->IsRemoved(theMapIndex))        return QTSS_AttrDoesntExist;    if (theAttrs[theMapIndex].fIsDynamicDictionary)        return QTSS_ReadOnly;        UInt32 numValues = theAttrs[theMapIndex].fNumAttributes;    QTSS_AttrDataType dataType = theMap->GetAttrType(theMapIndex);    UInt32 attrLen = inLen;    if (dataType == qtssAttrDataTypeCharArray)    {        if (inIndex > 0)            attrLen = sizeof(char*);    // value just contains a pointer                if ((numValues == 1) && (inIndex == 1))        {            // we're adding a second value, so we need to change the storage from directly            // storing the string to an array of string pointers                          // creating new memory here just to create a null terminated string                // instead of directly using the old storage as the old storage didn't                 // have its string null terminated                        UInt32 tempStringLen = theAttrs[theMapIndex].fAttributeData.Len;                        char* temp = NEW char[tempStringLen + 1];                        ::memcpy(temp, theAttrs[theMapIndex].fAttributeData.Ptr, tempStringLen);                        temp[tempStringLen] = '/0';                        delete [] theAttrs[theMapIndex].fAttributeData.Ptr;                                    //char* temp = theAttrs[theMapIndex].fAttributeData.Ptr;                        theAttrs[theMapIndex].fAllocatedLen = 16 * sizeof(char*);            theAttrs[theMapIndex].fAttributeData.Ptr = NEW char[theAttrs[theMapIndex].fAllocatedLen];            theAttrs[theMapIndex].fAttributeData.Len = sizeof(char*);            // store off original string as first value in array            *(char**)theAttrs[theMapIndex].fAttributeData.Ptr = temp;                        // question: why isn't theAttrs[theMapIndex].fAllocatedInternally set to true?        }    }    else    {        // If this attribute is iterated, this new value        // must be the same size as all the others.        if (((inIndex > 0) || (numValues > 1))                 &&(theAttrs[theMapIndex].fAttributeData.Len != 0) && (inLen != theAttrs[theMapIndex].fAttributeData.Len))            return QTSS_BadArgument;    }        //    // Can't put empty space into the array of values    if (inIndex > numValues)        return QTSS_BadIndex;            if ((attrLen * (inIndex + 1)) > theAttrs[theMapIndex].fAllocatedLen)    {        // We need to reallocate this buffer.        UInt32 theLen;                if (inIndex == 0)            theLen = attrLen;   // most attributes are single valued, so allocate just enough space        else            theLen = 2 * (attrLen * (inIndex + 1));// Allocate twice as much as we need        char* theNewBuffer = NEW char[theLen];        if (inIndex > 0)        {            // Copy out the old attribute data            ::memcpy(theNewBuffer, theAttrs[theMapIndex].fAttributeData.Ptr,                        theAttrs[theMapIndex].fAllocatedLen);        }                // Now get rid of the old stuff. Delete the buffer        // if it was already allocated internally        if (theAttrs[theMapIndex].fAllocatedInternally)            delete [] theAttrs[theMapIndex].fAttributeData.Ptr;                // Finally, update this attribute structure with all the new values.        theAttrs[theMapIndex].fAttributeData.Ptr = theNewBuffer;        theAttrs[theMapIndex].fAllocatedLen = theLen;        theAttrs[theMapIndex].fAllocatedInternally = true;    }            // At this point, we should always have enough space to write what we want    Assert(theAttrs[theMapIndex].fAllocatedLen >= (attrLen * (inIndex + 1)));        // Copy the new data to the right place in our data buffer    void *attributeBufferPtr;    if ((dataType != qtssAttrDataTypeCharArray) || ((numValues < 2) && (inIndex == 0)))    {        attributeBufferPtr = theAttrs[theMapIndex].fAttributeData.Ptr + (inLen * inIndex);        theAttrs[theMapIndex].fAttributeData.Len = inLen;    }    else    {            //attributeBufferPtr = NEW char[inLen];            // allocating one extra so that we can null terminate the string            attributeBufferPtr = NEW char[inLen + 1];                char* tempBuffer = (char*)attributeBufferPtr;                tempBuffer[inLen] = '/0';                        //char** valuePtr = (char**)theAttrs[theMapIndex].fAttributeData.Ptr + (inLen * inIndex);        // The offset should be (attrLen * inIndex) and not (inLen * inIndex)         char** valuePtr = (char**)(theAttrs[theMapIndex].fAttributeData.Ptr + (attrLen * inIndex));        if (inIndex < numValues)    // we're replacing an existing string            delete *valuePtr;        *valuePtr = (char*)attributeBufferPtr;    }        ::memcpy(attributeBufferPtr, inBuffer, inLen);        // Set the number of attributes to be proper    if (inIndex >= theAttrs[theMapIndex].fNumAttributes)    {        //        // We should never have to increment num attributes by more than 1        Assert(theAttrs[theMapIndex].fNumAttributes == inIndex);        theAttrs[theMapIndex].fNumAttributes++;    }    //    // Call the completion routine    if (((fMap == NULL) || fMap->CompleteFunctionsAllowed()) && !(inFlags & kDontCallCompletionRoutine))        this->SetValueComplete(theMapIndex, theMap, inIndex, attributeBufferPtr, inLen);        return QTSS_NoErr;}QTSS_Error QTSSDictionary::SetValuePtr(QTSS_AttributeID inAttrID,                                        const void* inBuffer,  UInt32 inLen,                                        UInt32 inFlags){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }        if (theMap == NULL)        return QTSS_AttrDoesntExist;        SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);        // If there is a mutex, make this action atomic.    OSMutexLocker locker(fMutexP);        if (theMapIndex < 0)        return QTSS_AttrDoesntExist;    if ((!(inFlags & kDontObeyReadOnly)) && (!theMap->IsWriteable(theMapIndex)))        return QTSS_ReadOnly;    if (theMap->IsRemoved(theMapIndex))        return QTSS_AttrDoesntExist;    if (theAttrs[theMapIndex].fIsDynamicDictionary)        return QTSS_ReadOnly;        UInt32 numValues = theAttrs[theMapIndex].fNumAttributes;    if ((numValues > 0) || (theAttrs[theMapIndex].fAttributeData.Ptr != NULL))        return QTSS_BadArgument;    // you can only set the pointer if you haven't done set value    theAttrs[theMapIndex].fAttributeData.Ptr = (char*) inBuffer;    theAttrs[theMapIndex].fAttributeData.Len = inLen;    theAttrs[theMapIndex].fAllocatedLen = inLen;        // This function assumes there is only one value and that it isn't allocated internally    theAttrs[theMapIndex].fNumAttributes = 1;                return QTSS_NoErr;}QTSS_Error QTSSDictionary::RemoveValue(QTSS_AttributeID inAttrID, UInt32 inIndex, UInt32 inFlags){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }        if (theMap == NULL)        return QTSS_AttrDoesntExist;        SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);        // If there is a mutex, make this action atomic.    OSMutexLocker locker(fMutexP);        if (theMapIndex < 0)        return QTSS_AttrDoesntExist;    if ((!(inFlags & kDontObeyReadOnly)) && (!theMap->IsWriteable(theMapIndex)))        return QTSS_ReadOnly;    if (theMap->IsRemoved(theMapIndex))        return QTSS_AttrDoesntExist;    if ((theMap->GetAttrFunction(theMapIndex) != NULL) && (inIndex > 0))        return QTSS_BadIndex;            UInt32 numValues = theAttrs[theMapIndex].fNumAttributes;    UInt32 theValueLen = theAttrs[theMapIndex].fAttributeData.Len;    if (theAttrs[theMapIndex].fIsDynamicDictionary)    {        // this is an internally allocated dictionary, so we need to desctruct it        Assert(theMap->GetAttrType(theMapIndex) == qtssAttrDataTypeQTSS_Object);        Assert(theValueLen == sizeof(QTSSDictionary*));        QTSSDictionary* dict = *(QTSSDictionary**)(theAttrs[theMapIndex].fAttributeData.Ptr + (theValueLen * inIndex));        delete dict;    }        QTSS_AttrDataType dataType = theMap->GetAttrType(theMapIndex);    if ((dataType == qtssAttrDataTypeCharArray) && (numValues > 1))    {        // we need to delete the string        char* str = *(char**)(theAttrs[theMapIndex].fAttributeData.Ptr + (theValueLen * inIndex));        delete str;    }    //    // If there are values after this one in the array, move them.    if (inIndex + 1 < theAttrs[theMapIndex].fNumAttributes)     {	        ::memmove(  theAttrs[theMapIndex].fAttributeData.Ptr + (theValueLen * inIndex),                theAttrs[theMapIndex].fAttributeData.Ptr + (theValueLen * (inIndex + 1)),                theValueLen * ( (theAttrs[theMapIndex].fNumAttributes) - inIndex - 1));    } // else this is the last in the array so just truncate.    //    // Update our number of values    theAttrs[theMapIndex].fNumAttributes--;    if (theAttrs[theMapIndex].fNumAttributes == 0)        theAttrs[theMapIndex].fAttributeData.Len = 0;    if ((dataType == qtssAttrDataTypeCharArray) && (theAttrs[theMapIndex].fNumAttributes == 1))    {        // we only have one string left, so we don't need the extra pointer        char* str = *(char**)(theAttrs[theMapIndex].fAttributeData.Ptr);        delete theAttrs[theMapIndex].fAttributeData.Ptr;        theAttrs[theMapIndex].fAttributeData.Ptr = str;        theAttrs[theMapIndex].fAttributeData.Len = strlen(str);        theAttrs[theMapIndex].fAllocatedLen = strlen(str);    }    //    // Call the completion routine    if (((fMap == NULL) || fMap->CompleteFunctionsAllowed()) && !(inFlags & kDontCallCompletionRoutine))        this->RemoveValueComplete(theMapIndex, theMap, inIndex);            return QTSS_NoErr;}UInt32  QTSSDictionary::GetNumValues(QTSS_AttributeID inAttrID){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }    if (theMap == NULL)        return 0;    SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);    if (theMapIndex < 0)        return 0;    return theAttrs[theMapIndex].fNumAttributes;}void    QTSSDictionary::SetNumValues(QTSS_AttributeID inAttrID, UInt32 inNumValues){    // Check first to see if this is a static attribute or an instance attribute    QTSSDictionaryMap* theMap = fMap;    DictValueElement* theAttrs = fAttributes;    if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        theMap = fInstanceMap;        theAttrs = fInstanceAttrs;    }    if (theMap == NULL)        return;    SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID);    if (theMapIndex < 0)        return;    UInt32 numAttributes = theAttrs[theMapIndex].fNumAttributes;    // this routine can only be ever used to reduce the number of values            if (inNumValues >= numAttributes || numAttributes == 0)        return;    QTSS_AttrDataType dataType = theMap->GetAttrType(theMapIndex);    if (theAttrs[theMapIndex].fIsDynamicDictionary || (dataType == qtssAttrDataTypeCharArray))    {                 // getting rid of dictionaries or strings is tricky, so it's easier to call remove value        for (UInt32 removeCount = numAttributes - inNumValues; removeCount > 0; removeCount--)        {	// the delete index passed to RemoveValue is always the last in the array.            this->RemoveValue(inAttrID, theAttrs[theMapIndex].fNumAttributes - 1, kDontObeyReadOnly);        }    }    else    {        theAttrs[theMapIndex].fNumAttributes = inNumValues;        if (inNumValues == 0)            theAttrs[theMapIndex].fAttributeData.Len = 0;    }}void    QTSSDictionary::SetVal( QTSS_AttributeID inAttrID,                                    void* inValueBuffer,                                    UInt32 inBufferLen){     Assert(inAttrID >= 0);    Assert(fMap);    Assert((UInt32)inAttrID < fMap->GetNumAttrs());    fAttributes[inAttrID].fAttributeData.Ptr = (char*)inValueBuffer;    fAttributes[inAttrID].fAttributeData.Len = inBufferLen;    fAttributes[inAttrID].fAllocatedLen = inBufferLen;        // This function assumes there is only one value and that it isn't allocated internally    fAttributes[inAttrID].fNumAttributes = 1;}void    QTSSDictionary::SetEmptyVal(QTSS_AttributeID inAttrID, void* inBuf, UInt32 inBufLen){    Assert(inAttrID >= 0);    Assert(fMap);    Assert((UInt32)inAttrID < fMap->GetNumAttrs());    fAttributes[inAttrID].fAttributeData.Ptr = (char*)inBuf;    fAttributes[inAttrID].fAllocatedLen = inBufLen;#if !ALLOW_NON_Word_ALIGN_ACCESS    //if (((UInt32) inBuf % 4) > 0)    //  qtss_printf("bad align by %d/n",((UInt32) inBuf % 4) );    Assert( ((PointerSizedInt) inBuf % 4) == 0 );#endif}QTSS_Error  QTSSDictionary::AddInstanceAttribute(   const char* inAttrName,                                                    QTSS_AttrFunctionPtr inFuncPtr,                                                    QTSS_AttrDataType inDataType,                                                    QTSS_AttrPermission inPermission ){    if ((fMap != NULL) && !fMap->InstanceAttrsAllowed())        return QTSS_InstanceAttrsNotAllowed;            OSMutexLocker locker(fMutexP);    //    // Check to see if this attribute exists in the static map. If it does,    // we can't add it as an instance attribute, so return an error    QTSSAttrInfoDict* throwAway = NULL;    QTSS_Error theErr;    if (fMap != NULL)    {        theErr = fMap->GetAttrInfoByName(inAttrName, &throwAway);        if (theErr == QTSS_NoErr)            return QTSS_AttrNameExists;    }        if (fInstanceMap == NULL)    {        UInt32 theFlags = QTSSDictionaryMap::kAllowRemoval | QTSSDictionaryMap::kIsInstanceMap;        if ((fMap == NULL) || fMap->CompleteFunctionsAllowed())            theFlags |= QTSSDictionaryMap::kCompleteFunctionsAllowed;                    fInstanceMap = new QTSSDictionaryMap( 0, theFlags );    }        //    // Add the attribute into the Dictionary Map.    theErr = fInstanceMap->AddAttribute(inAttrName, inFuncPtr, inDataType, inPermission);    if (theErr != QTSS_NoErr)        return theErr;        //    // Check to see if our DictValueElement array needs to be reallocated       if (fInstanceMap->GetNumAttrs() >= fInstanceArraySize)    {        UInt32 theNewArraySize = fInstanceArraySize * 2;        if (theNewArraySize == 0)            theNewArraySize = QTSSDictionaryMap::kMinArraySize;        Assert(theNewArraySize > fInstanceMap->GetNumAttrs());                DictValueElement* theNewArray = NEW DictValueElement[theNewArraySize];        if (fInstanceAttrs != NULL)        {            ::memcpy(theNewArray, fInstanceAttrs, sizeof(DictValueElement) * fInstanceArraySize);            //            // Delete the old instance attr structs, this does not delete the actual attribute memory            delete [] fInstanceAttrs;        }        fInstanceAttrs = theNewArray;        fInstanceArraySize = theNewArraySize;    }    return QTSS_NoErr;}QTSS_Error  QTSSDictionary::RemoveInstanceAttribute(QTSS_AttributeID inAttr){    OSMutexLocker locker(fMutexP);    if (fInstanceMap != NULL)    {           QTSS_Error theErr = fInstanceMap->CheckRemovePermission(inAttr);        if (theErr != QTSS_NoErr)            return theErr;        this->SetNumValues(inAttr,(UInt32) 0); // make sure to set num values to 0 since it is a deleted attribute        fInstanceMap->RemoveAttribute(inAttr);    }    else        return QTSS_BadArgument;        //    // Call the completion routine    SInt32 theMapIndex = fInstanceMap->ConvertAttrIDToArrayIndex(inAttr);    this->RemoveInstanceAttrComplete(theMapIndex, fInstanceMap);        return QTSS_NoErr;}QTSS_Error QTSSDictionary::GetAttrInfoByIndex(UInt32 inIndex, QTSSAttrInfoDict** outAttrInfoDict){    if (outAttrInfoDict == NULL)        return QTSS_BadArgument;            OSMutexLocker locker(fMutexP);    UInt32 numInstanceValues = 0;    UInt32 numStaticValues = 0;        if (fMap != NULL)        numStaticValues = fMap->GetNumNonRemovedAttrs();        if (fInstanceMap != NULL)        numInstanceValues = fInstanceMap->GetNumNonRemovedAttrs();        if (inIndex >= (numStaticValues + numInstanceValues))        return QTSS_AttrDoesntExist;        if ( (numStaticValues > 0)  && (inIndex < numStaticValues) )        return fMap->GetAttrInfoByIndex(inIndex, outAttrInfoDict);    else    {        Assert(fInstanceMap != NULL);        return fInstanceMap->GetAttrInfoByIndex(inIndex - numStaticValues, outAttrInfoDict);    }}QTSS_Error QTSSDictionary::GetAttrInfoByID(QTSS_AttributeID inAttrID, QTSSAttrInfoDict** outAttrInfoDict){    if (outAttrInfoDict == NULL)        return QTSS_BadArgument;            if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID))    {        OSMutexLocker locker(fMutexP);        if (fInstanceMap != NULL)            return fInstanceMap->GetAttrInfoByID(inAttrID, outAttrInfoDict);    }    else        if (fMap != NULL) return fMap->GetAttrInfoByID(inAttrID, outAttrInfoDict);                return QTSS_AttrDoesntExist;}QTSS_Error QTSSDictionary::GetAttrInfoByName(const char* inAttrName, QTSSAttrInfoDict** outAttrInfoDict){    QTSS_Error theErr = QTSS_AttrDoesntExist;    if (outAttrInfoDict == NULL)        return QTSS_BadArgument;            // Retrieve the Dictionary Map for this object type    if (fMap != NULL)        theErr = fMap->GetAttrInfoByName(inAttrName, outAttrInfoDict);        if (theErr == QTSS_AttrDoesntExist)    {        OSMutexLocker locker(fMutexP);        if (fInstanceMap != NULL)            theErr = fInstanceMap->GetAttrInfoByName(inAttrName, outAttrInfoDict);    }    return theErr;}void QTSSDictionary::DeleteAttributeData(DictValueElement* inDictValues, UInt32 inNumValues){    for (UInt32 x = 0; x < inNumValues; x++)    {        if (inDictValues[x].fAllocatedInternally)            delete [] inDictValues[x].fAttributeData.Ptr;    }}QTSSAttrInfoDict::AttrInfo  QTSSAttrInfoDict::sAttributes[] ={    /* 0 */ { "qtssAttrName",       NULL,       qtssAttrDataTypeCharArray,  qtssAttrModeRead | qtssAttrModePreempSafe },    /* 1 */ { "qtssAttrID",         NULL,       qtssAttrDataTypeUInt32,     qtssAttrModeRead | qtssAttrModePreempSafe },    /* 2 */ { "qtssAttrDataType",   NULL,       qtssAttrDataTypeUInt32,     qtssAttrModeRead | qtssAttrModePreempSafe },    /* 3 */ { "qtssAttrPermissions",NULL,       qtssAttrDataTypeUInt32,     qtssAttrModeRead | qtssAttrModePreempSafe }};QTSSAttrInfoDict::QTSSAttrInfoDict(): QTSSDictionary(QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kAttrInfoDictIndex)), fID(qtssIllegalAttrID){}QTSSAttrInfoDict::~QTSSAttrInfoDict() {}QTSSDictionaryMap*      QTSSDictionaryMap::sDictionaryMaps[kNumDictionaries + kNumDynamicDictionaryTypes];UInt32                  QTSSDictionaryMap::sNextDynamicMap = kNumDictionaries;void QTSSDictionaryMap::Initialize(){    //    // Have to do this one first because this dict map is used by all the other    // dict maps.    sDictionaryMaps[kAttrInfoDictIndex]     = new QTSSDictionaryMap(qtssAttrInfoNumParams);    // Setup the Attr Info attributes before constructing any other dictionaries    for (UInt32 x = 0; x < qtssAttrInfoNumParams; x++)        sDictionaryMaps[kAttrInfoDictIndex]->SetAttribute(x, QTSSAttrInfoDict::sAttributes[x].fAttrName,                                                            QTSSAttrInfoDict::sAttributes[x].fFuncPtr,                                                            QTSSAttrInfoDict::sAttributes[x].fAttrDataType,                                                            QTSSAttrInfoDict::sAttributes[x].fAttrPermission);    sDictionaryMaps[kServerDictIndex]       = new QTSSDictionaryMap(qtssSvrNumParams, QTSSDictionaryMap::kCompleteFunctionsAllowed);    sDictionaryMaps[kPrefsDictIndex]        = new QTSSDictionaryMap(qtssPrefsNumParams, QTSSDictionaryMap::kInstanceAttrsAllowed | QTSSDictionaryMap::kCompleteFunctionsAllowed);    sDictionaryMaps[kTextMessagesDictIndex] = new QTSSDictionaryMap(qtssMsgNumParams);    sDictionaryMaps[kServiceDictIndex]      = new QTSSDictionaryMap(0);    sDictionaryMaps[kRTPStreamDictIndex]    = new QTSSDictionaryMap(qtssRTPStrNumParams);	sDictionaryMaps[kClientSessionDictIndex]= new QTSSDictionaryMap(qtssCliSesNumParams, QTSSDictionaryMap::kCompleteFunctionsAllowed);    sDictionaryMaps[kRTSPSessionDictIndex]  = new QTSSDictionaryMap(qtssRTSPSesNumParams);    sDictionaryMaps[kRTSPRequestDictIndex]  = new QTSSDictionaryMap(qtssRTSPReqNumParams);    sDictionaryMaps[kRTSPHeaderDictIndex]   = new QTSSDictionaryMap(qtssNumHeaders);    sDictionaryMaps[kFileDictIndex]         = new QTSSDictionaryMap(qtssFlObjNumParams);    sDictionaryMaps[kModuleDictIndex]       = new QTSSDictionaryMap(qtssModNumParams);    sDictionaryMaps[kModulePrefsDictIndex]  = new QTSSDictionaryMap(0, QTSSDictionaryMap::kInstanceAttrsAllowed | QTSSDictionaryMap::kCompleteFunctionsAllowed);    sDictionaryMaps[kQTSSUserProfileDictIndex] = new QTSSDictionaryMap(qtssUserNumParams);    sDictionaryMaps[kQTSSConnectedUserDictIndex] = new QTSSDictionaryMap(qtssConnectionNumParams);}QTSSDictionaryMap::QTSSDictionaryMap(UInt32 inNumReservedAttrs, UInt32 inFlags):   fNextAvailableID(inNumReservedAttrs), fNumValidAttrs(inNumReservedAttrs),fAttrArraySize(inNumReservedAttrs), fFlags(inFlags){    if (fAttrArraySize < kMinArraySize)        fAttrArraySize = kMinArraySize;    fAttrArray = NEW QTSSAttrInfoDict*[fAttrArraySize];    ::memset(fAttrArray, 0, sizeof(QTSSAttrInfoDict*) * fAttrArraySize);}QTSS_Error QTSSDictionaryMap::AddAttribute( const char* inAttrName,                                            QTSS_AttrFunctionPtr inFuncPtr,                                            QTSS_AttrDataType inDataType,                                            QTSS_AttrPermission inPermission){    if (inAttrName == NULL || ::strlen(inAttrName) > QTSS_MAX_ATTRIBUTE_NAME_SIZE)        return QTSS_BadArgument;    for (UInt32 count = 0; count < fNextAvailableID; count++)    {        if  (::strcmp(&fAttrArray[count]->fAttrInfo.fAttrName[0], inAttrName) == 0)        {   // found the name in the dictionary            if (fAttrArray[count]->fAttrInfo.fAttrPermission & qtssPrivateAttrModeRemoved )            { // it is a previously removed attribute                if (fAttrArray[count]->fAttrInfo.fAttrDataType == inDataType)                { //same type so reuse the attribute                    QTSS_AttributeID attrID = fAttrArray[count]->fID;                     this->UnRemoveAttribute(attrID);                     fAttrArray[count]->fAttrInfo.fFuncPtr = inFuncPtr; // reset                    fAttrArray[count]->fAttrInfo.fAttrPermission = inPermission;// reset                    return QTSS_NoErr; // nothing left to do. It is re-added.                }                                // a removed attribute with the same name but different type--so keep checking                 continue;            }            // an error, an active attribute with this name exists            return QTSS_AttrNameExists;        }    }    if (fAttrArraySize == fNextAvailableID)    {        // If there currently isn't an attribute array, or if the current array        // is full, allocate a new array and copy all the old stuff over to the new array.                UInt32 theNewArraySize = fAttrArraySize * 2;        if (theNewArraySize == 0)            theNewArraySize = kMinArraySize;                QTSSAttrInfoDict** theNewArray = NEW QTSSAttrInfoDict*[theNewArraySize];        ::memset(theNewArray, 0, sizeof(QTSSAttrInfoDict*) * theNewArraySize);        if (fAttrArray != NULL)        {            ::memcpy(theNewArray, fAttrArray, sizeof(QTSSAttrInfoDict*) * fAttrArraySize);            delete [] fAttrArray;        }        fAttrArray = theNewArray;        fAttrArraySize = theNewArraySize;    }        QTSS_AttributeID theID = fNextAvailableID;    fNextAvailableID++;    fNumValidAttrs++;    if (fFlags & kIsInstanceMap)        theID |= 0x80000000; // Set the high order bit to indicate this is an instance attr    // Copy the information into the first available element    // Currently, all attributes added in this fashion are always writeable    this->SetAttribute(theID, inAttrName, inFuncPtr, inDataType, inPermission);     return QTSS_NoErr;}void QTSSDictionaryMap::SetAttribute(   QTSS_AttributeID inID,                                         const char* inAttrName,                                        QTSS_AttrFunctionPtr inFuncPtr,                                        QTSS_AttrDataType inDataType,                                        QTSS_AttrPermission inPermission ){    UInt32 theIndex = QTSSDictionaryMap::ConvertAttrIDToArrayIndex(inID);    UInt32 theNameLen = ::strlen(inAttrName);    Assert(theNameLen < QTSS_MAX_ATTRIBUTE_NAME_SIZE);    Assert(fAttrArray[theIndex] == NULL);        fAttrArray[theIndex] = NEW QTSSAttrInfoDict;        //Copy the information into the first available element    fAttrArray[theIndex]->fID = inID;            ::strcpy(&fAttrArray[theIndex]->fAttrInfo.fAttrName[0], inAttrName);    fAttrArray[theIndex]->fAttrInfo.fFuncPtr = inFuncPtr;    fAttrArray[theIndex]->fAttrInfo.fAttrDataType = inDataType;     fAttrArray[theIndex]->fAttrInfo.fAttrPermission = inPermission;        fAttrArray[theIndex]->SetVal(qtssAttrName, &fAttrArray[theIndex]->fAttrInfo.fAttrName[0], theNameLen);    fAttrArray[theIndex]->SetVal(qtssAttrID, &fAttrArray[theIndex]->fID, sizeof(fAttrArray[theIndex]->fID));    fAttrArray[theIndex]->SetVal(qtssAttrDataType, &fAttrArray[theIndex]->fAttrInfo.fAttrDataType, sizeof(fAttrArray[theIndex]->fAttrInfo.fAttrDataType));    fAttrArray[theIndex]->SetVal(qtssAttrPermissions, &fAttrArray[theIndex]->fAttrInfo.fAttrPermission, sizeof(fAttrArray[theIndex]->fAttrInfo.fAttrPermission));}QTSS_Error  QTSSDictionaryMap::CheckRemovePermission(QTSS_AttributeID inAttrID){    SInt32 theIndex = this->ConvertAttrIDToArrayIndex(inAttrID);    if (theIndex < 0)        return QTSS_AttrDoesntExist;        if (0 == (fAttrArray[theIndex]->fAttrInfo.fAttrPermission & qtssAttrModeDelete))         return QTSS_BadArgument;    if (!(fFlags & kAllowRemoval))        return QTSS_BadArgument;        return QTSS_NoErr;}QTSS_Error  QTSSDictionaryMap::RemoveAttribute(QTSS_AttributeID inAttrID){    SInt32 theIndex = this->ConvertAttrIDToArrayIndex(inAttrID);    if (theIndex < 0)        return QTSS_AttrDoesntExist;        Assert(fFlags & kAllowRemoval);    if (!(fFlags & kAllowRemoval))        return QTSS_BadArgument;        //qtss_printf("QTSSDictionaryMap::RemoveAttribute arraySize=%lu numNonRemove= %lu fAttrArray[%lu]->fAttrInfo.fAttrName=%s/n",this->GetNumAttrs(), this->GetNumNonRemovedAttrs(), theIndex,fAttrArray[theIndex]->fAttrInfo.fAttrName);    //    // Don't actually touch the attribute or anything. Just flag the    // it as removed.    fAttrArray[theIndex]->fAttrInfo.fAttrPermission |= qtssPrivateAttrModeRemoved;    fNumValidAttrs--;//有效元素减1    Assert(fNumValidAttrs < 1000000);    return QTSS_NoErr;}QTSS_Error  QTSSDictionaryMap::UnRemoveAttribute(QTSS_AttributeID inAttrID){    if (this->ConvertAttrIDToArrayIndex(inAttrID) == -1)        return QTSS_AttrDoesntExist;        SInt32 theIndex = this->ConvertAttrIDToArrayIndex(inAttrID);    if (theIndex < 0)        return QTSS_AttrDoesntExist;            fAttrArray[theIndex]->fAttrInfo.fAttrPermission &= ~qtssPrivateAttrModeRemoved;        fNumValidAttrs++;    return QTSS_NoErr;}QTSS_Error  QTSSDictionaryMap::GetAttrInfoByName(const char* inAttrName, QTSSAttrInfoDict** outAttrInfoObject,                                                    Bool16 returnRemovedAttr){    if (outAttrInfoObject == NULL)        return QTSS_BadArgument;    for (UInt32 count = 0; count < fNextAvailableID; count++)    {        if (::strcmp(&fAttrArray[count]->fAttrInfo.fAttrName[0], inAttrName) == 0)        {            if ((fAttrArray[count]->fAttrInfo.fAttrPermission & qtssPrivateAttrModeRemoved) && (!returnRemovedAttr))                continue;                            *outAttrInfoObject = fAttrArray[count];            return QTSS_NoErr;        }       }    return QTSS_AttrDoesntExist;}QTSS_Error  QTSSDictionaryMap::GetAttrInfoByID(QTSS_AttributeID inID, QTSSAttrInfoDict** outAttrInfoObject){    if (outAttrInfoObject == NULL)        return QTSS_BadArgument;    SInt32 theIndex = this->ConvertAttrIDToArrayIndex(inID);    if (theIndex < 0)        return QTSS_AttrDoesntExist;        if (fAttrArray[theIndex]->fAttrInfo.fAttrPermission & qtssPrivateAttrModeRemoved)        return QTSS_AttrDoesntExist;            *outAttrInfoObject = fAttrArray[theIndex];    return QTSS_NoErr;}QTSS_Error  QTSSDictionaryMap::GetAttrInfoByIndex(UInt32 inIndex, QTSSAttrInfoDict** outAttrInfoObject){    if (outAttrInfoObject == NULL)        return QTSS_BadArgument;    if (inIndex >= this->GetNumNonRemovedAttrs())        return QTSS_AttrDoesntExist;            UInt32 actualIndex = inIndex;    UInt32 max = this->GetNumAttrs();    if (fFlags & kAllowRemoval)    {        // If this dictionary map allows attributes to be removed, then        // the iteration index and array indexes won't line up exactly, so        // we have to iterate over the whole map all the time        actualIndex = 0;        for (UInt32 x = 0; x < max; x++)        {   if (fAttrArray[x] && (fAttrArray[x]->fAttrInfo.fAttrPermission & qtssPrivateAttrModeRemoved) )            {   continue;            }                            if (actualIndex == inIndex)            {   actualIndex = x;                break;            }            actualIndex++;        }    }    //qtss_printf("QTSSDictionaryMap::GetAttrInfoByIndex arraySize=%lu numNonRemove= %lu fAttrArray[%lu]->fAttrInfo.fAttrName=%s/n",this->GetNumAttrs(), this->GetNumNonRemovedAttrs(), actualIndex,fAttrArray[actualIndex]->fAttrInfo.fAttrName);    Assert(actualIndex < fNextAvailableID);    Assert(!(fAttrArray[actualIndex]->fAttrInfo.fAttrPermission & qtssPrivateAttrModeRemoved));    *outAttrInfoObject = fAttrArray[actualIndex];    return QTSS_NoErr;}QTSS_Error  QTSSDictionaryMap::GetAttrID(const char* inAttrName, QTSS_AttributeID* outID){    if (outID == NULL)        return QTSS_BadArgument;    QTSSAttrInfoDict* theAttrInfo = NULL;    QTSS_Error theErr = this->GetAttrInfoByName(inAttrName, &theAttrInfo);    if (theErr == QTSS_NoErr)        *outID = theAttrInfo->fID;    return theErr;}UInt32  QTSSDictionaryMap::GetMapIndex(QTSS_ObjectType inType){     if (inType < sNextDynamicMap)        return inType;          switch (inType)     {        case qtssRTPStreamObjectType:       return kRTPStreamDictIndex;        case qtssClientSessionObjectType:   return kClientSessionDictIndex;        case qtssRTSPSessionObjectType:     return kRTSPSessionDictIndex;        case qtssRTSPRequestObjectType:     return kRTSPRequestDictIndex;        case qtssRTSPHeaderObjectType:      return kRTSPHeaderDictIndex;        case qtssServerObjectType:          return kServerDictIndex;        case qtssPrefsobjectType:           return kPrefsDictIndex;        case qtssTextMessagesObjectType:    return kTextMessagesDictIndex;        case qtssFileObjectType:            return kFileDictIndex;        case qtssModuleObjectType:          return kModuleDictIndex;        case qtssModulePrefsObjectType:     return kModulePrefsDictIndex;        case qtssAttrInfoObjectType:        return kAttrInfoDictIndex;        case qtssUserProfileObjectType:     return kQTSSUserProfileDictIndex;        case qtssConnectedUserObjectType:   return kQTSSConnectedUserDictIndex;        default:                            return kIllegalDictionary;     }     return kIllegalDictionary;}QTSS_ObjectType QTSSDictionaryMap::CreateNewMap(){    if (sNextDynamicMap == kNumDictionaries + kNumDynamicDictionaryTypes)        return 0;            sDictionaryMaps[sNextDynamicMap] = new QTSSDictionaryMap(0);    QTSS_ObjectType result = (QTSS_ObjectType)sNextDynamicMap;    sNextDynamicMap++;        return result;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表