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;}
新闻热点
疑难解答