carb/dictionary/IDictionary.h
File members: carb/dictionary/IDictionary.h
// Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include "../Framework.h"
#include "../Interface.h"
#include "../Types.h"
#include "../extras/Hash.h"
#include "../cpp/StringView.h"
#include "../../omni/String.h"
#include <cstdint>
namespace carb
{
namespace dictionary
{
enum class ItemType
{
eBool,
eInt,
eFloat,
eString,
eDictionary,
eCount
};
struct Item DOXYGEN_EMPTY_CLASS;
enum class UpdateAction
{
eOverwrite,
eKeep,
eReplaceSubtree
};
enum class ItemFlag
{
eUnitSubtree,
};
typedef UpdateAction (*OnUpdateItemFn)(
const Item* dstItem, ItemType dstItemType, const Item* srcItem, ItemType srcItemType, void* userData);
inline UpdateAction overwriteOriginal(
const Item* dstItem, ItemType dstItemType, const Item* srcItem, ItemType srcItemType, void* userData)
{
CARB_UNUSED(dstItem, dstItemType, srcItem, srcItemType, userData);
return UpdateAction::eOverwrite;
}
inline UpdateAction keepOriginal(
const Item* dstItem, ItemType dstItemType, const Item* srcItem, ItemType srcItemType, void* userData)
{
CARB_UNUSED(dstItemType, srcItem, srcItemType, userData);
if (!dstItem)
{
// If the destination item doesn't exist - allow to create a new one
return UpdateAction::eOverwrite;
}
return UpdateAction::eKeep;
}
constexpr OnUpdateItemFn kUpdateItemOverwriteOriginal = overwriteOriginal;
constexpr OnUpdateItemFn kUpdateItemKeepOriginal = keepOriginal;
struct SubscriptionId DOXYGEN_EMPTY_CLASS;
enum class ChangeEventType
{
eCreated,
eChanged,
eDestroyed
};
using OnNodeChangeEventFn = void (*)(const Item* changedItem, ChangeEventType eventType, void* userData);
using OnTreeChangeEventFn = void (*)(const Item* treeItem,
const Item* changedItem,
ChangeEventType eventType,
void* userData);
struct IDictionary
{
// Version 1.0: Initial
// Version 1.1: Ordering guarantees for createItem(), update(), duplicateItem().
CARB_PLUGIN_INTERFACE("carb::dictionary::IDictionary", 1, 1)
const Item*(CARB_ABI* getItem)(const Item* baseItem, const char* path);
Item*(CARB_ABI* getItemMutable)(Item* baseItem, const char* path);
size_t(CARB_ABI* getItemChildCount)(const Item* item);
const Item*(CARB_ABI* getItemChildByIndex)(const Item* item, size_t childIndex);
Item*(CARB_ABI* getItemChildByIndexMutable)(Item* item, size_t childIndex);
const Item*(CARB_ABI* getItemParent)(const Item* item);
Item*(CARB_ABI* getItemParentMutable)(Item* item);
ItemType(CARB_ABI* getItemType)(const Item* item);
const char*(CARB_ABI* createStringBufferFromItemName)(const Item* item);
const char*(CARB_ABI* getItemName)(const Item* item);
Item*(CARB_ABI* createItem)(Item* baseItem, const char* path, ItemType itemType);
bool(CARB_ABI* isAccessibleAs)(ItemType itemType, const Item* item);
int64_t(CARB_ABI* getAsInt64)(const Item* item);
void(CARB_ABI* setInt64)(Item* item, int64_t value);
int32_t getAsInt(const Item* item);
void setInt(Item* item, int32_t value);
Item* makeInt64AtPath(Item* baseItem, const char* path, int64_t value);
Item* makeIntAtPath(Item* baseItem, const char* path, int32_t value);
double(CARB_ABI* getAsFloat64)(const Item* item);
void(CARB_ABI* setFloat64)(Item* item, double value);
float getAsFloat(const Item* item);
void setFloat(Item* item, float value);
Item* makeFloat64AtPath(Item* baseItem, const char* path, double value);
Item* makeFloatAtPath(Item* baseItem, const char* path, float value);
bool(CARB_ABI* getAsBool)(const Item* item);
void(CARB_ABI* setBool)(Item* item, bool value);
Item* makeBoolAtPath(Item* baseItem, const char* path, bool value);
const char*(CARB_ABI* internalCreateStringBufferFromItemValue)(const Item* item, size_t* pStringLen);
const char* createStringBufferFromItemValue(const Item* item, size_t* pStringLen = nullptr) const
{
return internalCreateStringBufferFromItemValue(item, pStringLen);
}
const char*(CARB_ABI* internalGetStringBuffer)(const Item* item, size_t* pStringLen);
const char* getStringBuffer(const Item* item, size_t* pStringLen = nullptr)
{
return internalGetStringBuffer(item, pStringLen);
}
void(CARB_ABI* internalSetString)(Item* item, const char* value, size_t stringLen);
void setString(Item* item, const char* value, size_t stringLen = size_t(-1)) const
{
internalSetString(item, value, stringLen);
}
Item* makeStringAtPath(Item* baseItem, const char* path, const char* value, size_t stringLen = size_t(-1));
Item* makeDictionaryAtPath(Item* parentItem, const char* path);
template <typename T>
T get(const dictionary::Item* item);
template <typename T>
T get(const dictionary::Item* baseItem, const char* path);
template <typename T>
void makeAtPath(dictionary::Item* baseItem, const char* path, T value);
bool(CARB_ABI* isAccessibleAsArray)(const Item* item);
bool(CARB_ABI* isAccessibleAsArrayOf)(ItemType itemType, const Item* item);
size_t(CARB_ABI* getArrayLength)(const Item* item);
ItemType(CARB_ABI* getPreferredArrayType)(const Item* item);
int64_t(CARB_ABI* getAsInt64At)(const Item* item, size_t index);
void(CARB_ABI* setInt64At)(Item* item, size_t index, int64_t value);
int32_t getAsIntAt(const Item* item, size_t index);
void setIntAt(Item* item, size_t index, int32_t value);
void(CARB_ABI* getAsInt64Array)(const Item* item, int64_t* arrayOut, size_t arrayBufferLength);
void(CARB_ABI* setInt64Array)(Item* item, const int64_t* array, size_t arrayLength);
void(CARB_ABI* getAsIntArray)(const Item* item, int32_t* arrayOut, size_t arrayBufferLength);
void(CARB_ABI* setIntArray)(Item* item, const int32_t* array, size_t arrayLength);
double(CARB_ABI* getAsFloat64At)(const Item* item, size_t index);
void(CARB_ABI* setFloat64At)(Item* item, size_t index, double value);
float getAsFloatAt(const Item* item, size_t index);
void setFloatAt(Item* item, size_t index, float value);
void(CARB_ABI* getAsFloat64Array)(const Item* item, double* arrayOut, size_t arrayBufferLength);
void(CARB_ABI* setFloat64Array)(Item* item, const double* array, size_t arrayLength);
void(CARB_ABI* getAsFloatArray)(const Item* item, float* arrayOut, size_t arrayBufferLength);
void(CARB_ABI* setFloatArray)(Item* item, const float* array, size_t arrayLength);
bool(CARB_ABI* getAsBoolAt)(const Item* item, size_t index);
void(CARB_ABI* setBoolAt)(Item* item, size_t index, bool value);
void(CARB_ABI* getAsBoolArray)(const Item* item, bool* arrayOut, size_t arrayBufferLength);
void(CARB_ABI* setBoolArray)(Item* item, const bool* array, size_t arrayLength);
const char*(CARB_ABI* internalCreateStringBufferFromItemValueAt)(const Item* item, size_t index, size_t* pStringLen);
const char* createStringBufferFromItemValueAt(const Item* item, size_t index, size_t* pStringLen = nullptr) const
{
return internalCreateStringBufferFromItemValueAt(item, index, pStringLen);
}
const char*(CARB_ABI* internalGetStringBufferAt)(const Item* item, size_t index, size_t* pStringLen);
const char* getStringBufferAt(const Item* item, size_t index, size_t* pStringLen = nullptr) const
{
return internalGetStringBufferAt(item, index, pStringLen);
}
void(CARB_ABI* internalSetStringAt)(Item* item, size_t index, const char* value, size_t stringLen);
void setStringAt(Item* item, size_t index, const char* value, size_t stringLen = size_t(-1)) const
{
internalSetStringAt(item, index, value, stringLen);
}
void(CARB_ABI* getStringBufferArray)(const Item* item, const char** arrayOut, size_t arrayBufferLength);
void(CARB_ABI* setStringArray)(Item* item, const char* const* array, size_t arrayLength);
const Item*(CARB_ABI* getItemAt)(const Item* item, size_t index);
Item*(CARB_ABI* getItemAtMutable)(Item* item, size_t index);
void(CARB_ABI* getItemArray)(const Item* item, const Item** arrayOut, size_t arrayBufferLength);
template <typename ArrayElementType>
void setArray(Item* item, const ArrayElementType* array, size_t arrayLength);
void(CARB_ABI* update)(Item* dstBaseItem,
const char* dstPath,
const Item* srcBaseItem,
const char* srcPath,
OnUpdateItemFn onUpdateItemFn,
void* userData);
void(CARB_ABI* destroyItem)(Item* item);
void(CARB_ABI* destroyStringBuffer)(const char* stringBuffer);
void deleteChildren(Item* item);
bool(CARB_ABI* getItemFlag)(const Item* item, ItemFlag flag);
void(CARB_ABI* setItemFlag)(Item* item, ItemFlag flag, bool flagValue);
void copyItemFlags(Item* dstItem, const Item* srcItem);
SubscriptionId*(CARB_ABI* subscribeToNodeChangeEvents)(Item* baseItem,
const char* path,
OnNodeChangeEventFn onChangeEventFn,
void* userData);
SubscriptionId*(CARB_ABI* subscribeToTreeChangeEvents)(Item* baseItem,
const char* path,
OnTreeChangeEventFn onChangeEventFn,
void* userData);
void(CARB_ABI* unsubscribeToChangeEvents)(SubscriptionId* subscriptionId);
void(CARB_ABI* unsubscribeItemFromNodeChangeEvents)(Item* item);
void(CARB_ABI* unsubscribeItemFromTreeChangeEvents)(Item* item);
void(CARB_ABI* readLock)(const Item* item);
void(CARB_ABI* writeLock)(Item* item);
void(CARB_ABI* unlock)(const Item* item);
const extras::hash128_t(CARB_ABI* getHash)(const Item* item);
Item*(CARB_ABI* duplicateItemInternal)(const Item* item, Item* newParent, const char* newKey);
int(CARB_ABI* lexicographicalCompare)(const Item* itemA, const Item* itemB);
Item* duplicateItem(const Item* item)
{
return duplicateItemInternal(item, nullptr, nullptr);
}
Item* duplicateItem(const Item* item, Item* newParent, const char* newKey)
{
return duplicateItemInternal(item, newParent, newKey);
}
};
class ScopedWrite
{
const IDictionary* m_pDictionary;
Item* m_pItem;
public:
ScopedWrite(const IDictionary& dictionary, Item* item) : m_pDictionary(std::addressof(dictionary)), m_pItem(item)
{
m_pDictionary->writeLock(m_pItem);
}
~ScopedWrite()
{
m_pDictionary->unlock(m_pItem);
}
CARB_PREVENT_COPY_AND_MOVE(ScopedWrite);
};
class ScopedRead
{
const IDictionary* m_pDictionary;
const Item* m_pItem;
public:
ScopedRead(const IDictionary& dictionary, const Item* item)
: m_pDictionary(std::addressof(dictionary)), m_pItem(item)
{
m_pDictionary->readLock(m_pItem);
}
~ScopedRead()
{
m_pDictionary->unlock(m_pItem);
}
CARB_PREVENT_COPY_AND_MOVE(ScopedRead);
};
inline int32_t IDictionary::getAsInt(const Item* item)
{
auto val = getAsInt64(item);
CARB_ASSERT(val >= INT_MIN && val <= INT_MAX);
return int32_t(val);
}
inline void IDictionary::setInt(Item* item, int32_t value)
{
setInt64(item, static_cast<int64_t>(value));
}
inline Item* IDictionary::makeIntAtPath(Item* baseItem, const char* path, int32_t value)
{
return makeInt64AtPath(baseItem, path, static_cast<int64_t>(value));
}
inline float IDictionary::getAsFloat(const Item* item)
{
return static_cast<float>(getAsFloat64(item));
}
inline void IDictionary::setFloat(Item* item, float value)
{
setFloat64(item, static_cast<double>(value));
}
inline Item* IDictionary::makeFloatAtPath(Item* baseItem, const char* path, float value)
{
return makeFloat64AtPath(baseItem, path, static_cast<double>(value));
}
inline int32_t IDictionary::getAsIntAt(const Item* item, size_t index)
{
auto val = getAsInt64At(item, index);
CARB_ASSERT(val >= INT_MIN && val <= INT_MAX);
return int32_t(val);
}
inline void IDictionary::setIntAt(Item* item, size_t index, int32_t value)
{
setInt64At(item, index, static_cast<int64_t>(value));
}
inline float IDictionary::getAsFloatAt(const Item* item, size_t index)
{
return static_cast<float>(getAsFloat64At(item, index));
}
inline void IDictionary::setFloatAt(Item* item, size_t index, float value)
{
setFloat64At(item, index, static_cast<double>(value));
}
inline Item* IDictionary::makeInt64AtPath(Item* parentItem, const char* path, int64_t value)
{
ScopedWrite g(*this, parentItem);
Item* item = getItemMutable(parentItem, path);
if (!item)
{
item = createItem(parentItem, path, ItemType::eInt);
}
setInt64(item, value);
return item;
}
inline Item* IDictionary::makeFloat64AtPath(Item* parentItem, const char* path, double value)
{
ScopedWrite g(*this, parentItem);
Item* item = getItemMutable(parentItem, path);
if (!item)
{
item = createItem(parentItem, path, ItemType::eFloat);
}
setFloat64(item, value);
return item;
}
inline Item* IDictionary::makeBoolAtPath(Item* parentItem, const char* path, bool value)
{
ScopedWrite g(*this, parentItem);
Item* item = getItemMutable(parentItem, path);
if (!item)
{
item = createItem(parentItem, path, ItemType::eBool);
}
setBool(item, value);
return item;
}
inline Item* IDictionary::makeStringAtPath(Item* parentItem, const char* path, const char* value, size_t stringLen)
{
ScopedWrite g(*this, parentItem);
Item* item = getItemMutable(parentItem, path);
if (!item)
{
item = createItem(parentItem, path, ItemType::eString);
}
setString(item, value, stringLen);
return item;
}
inline Item* IDictionary::makeDictionaryAtPath(Item* parentItem, const char* path)
{
ScopedWrite g(*this, parentItem);
Item* item = getItemMutable(parentItem, path);
if (!item)
{
item = createItem(parentItem, path, ItemType::eDictionary);
return item;
}
ItemType itemType = getItemType(item);
if (itemType != ItemType::eDictionary)
{
destroyItem(item);
item = createItem(parentItem, path, ItemType::eDictionary);
}
return item;
}
#ifndef DOXYGEN_BUILD
template <>
inline int32_t IDictionary::get<int32_t>(const dictionary::Item* item)
{
return getAsInt(item);
}
template <>
inline int64_t IDictionary::get<int64_t>(const dictionary::Item* item)
{
return getAsInt64(item);
}
template <>
inline float IDictionary::get<float>(const dictionary::Item* item)
{
return getAsFloat(item);
}
template <>
inline double IDictionary::get<double>(const dictionary::Item* item)
{
return getAsFloat64(item);
}
template <>
inline bool IDictionary::get<bool>(const dictionary::Item* item)
{
return getAsBool(item);
}
template <>
inline const char* IDictionary::get<const char*>(const dictionary::Item* item)
{
return getStringBuffer(item);
}
template <>
inline Int2 IDictionary::get<Int2>(const dictionary::Item* item)
{
Int2 value;
getAsIntArray(item, &value.x, 2);
return value;
}
template <>
inline Int3 IDictionary::get<Int3>(const dictionary::Item* item)
{
Int3 value;
getAsIntArray(item, &value.x, 3);
return value;
}
template <>
inline Int4 IDictionary::get<Int4>(const dictionary::Item* item)
{
Int4 value;
getAsIntArray(item, &value.x, 4);
return value;
}
template <>
inline Uint2 IDictionary::get<Uint2>(const dictionary::Item* item)
{
int64_t value[2];
getAsInt64Array(item, value, 2);
return { static_cast<uint32_t>(value[0]), static_cast<uint32_t>(value[1]) };
}
template <>
inline Uint3 IDictionary::get<Uint3>(const dictionary::Item* item)
{
int64_t value[3];
getAsInt64Array(item, value, 3);
return { static_cast<uint32_t>(value[0]), static_cast<uint32_t>(value[1]), static_cast<uint32_t>(value[2]) };
}
template <>
inline Uint4 IDictionary::get<Uint4>(const dictionary::Item* item)
{
int64_t value[4];
getAsInt64Array(item, value, 4);
return { static_cast<uint32_t>(value[0]), static_cast<uint32_t>(value[1]), static_cast<uint32_t>(value[2]),
static_cast<uint32_t>(value[3]) };
}
template <>
inline Float2 IDictionary::get<Float2>(const dictionary::Item* item)
{
Float2 value;
getAsFloatArray(item, &value.x, 2);
return value;
}
template <>
inline Float3 IDictionary::get<Float3>(const dictionary::Item* item)
{
Float3 value;
getAsFloatArray(item, &value.x, 3);
return value;
}
template <>
inline Float4 IDictionary::get<Float4>(const dictionary::Item* item)
{
Float4 value;
getAsFloatArray(item, &value.x, 4);
return value;
}
template <>
inline Double2 IDictionary::get<Double2>(const dictionary::Item* item)
{
Double2 value;
getAsFloat64Array(item, &value.x, 2);
return value;
}
template <>
inline Double3 IDictionary::get<Double3>(const dictionary::Item* item)
{
Double3 value;
getAsFloat64Array(item, &value.x, 3);
return value;
}
template <>
inline Double4 IDictionary::get<Double4>(const dictionary::Item* item)
{
Double4 value;
getAsFloat64Array(item, &value.x, 4);
return value;
}
template <class T>
inline T IDictionary::get(const dictionary::Item* baseItem, const char* path)
{
return get<T>(getItem(baseItem, path));
}
template <>
inline void IDictionary::makeAtPath<int32_t>(dictionary::Item* baseItem, const char* path, int32_t value)
{
makeIntAtPath(baseItem, path, value);
}
template <>
inline void IDictionary::makeAtPath<int64_t>(dictionary::Item* baseItem, const char* path, int64_t value)
{
makeInt64AtPath(baseItem, path, value);
}
template <>
inline void IDictionary::makeAtPath<float>(dictionary::Item* baseItem, const char* path, float value)
{
makeFloatAtPath(baseItem, path, value);
}
template <>
inline void IDictionary::makeAtPath<double>(dictionary::Item* baseItem, const char* path, double value)
{
makeFloat64AtPath(baseItem, path, value);
}
template <>
inline void IDictionary::makeAtPath<bool>(dictionary::Item* baseItem, const char* path, bool value)
{
makeBoolAtPath(baseItem, path, value);
}
template <>
inline void IDictionary::makeAtPath<const char*>(dictionary::Item* baseItem, const char* path, const char* value)
{
makeStringAtPath(baseItem, path, value);
}
template <>
inline void IDictionary::makeAtPath<std::string>(dictionary::Item* baseItem, const char* path, std::string value)
{
makeStringAtPath(baseItem, path, value.data(), value.size());
}
template <>
inline void IDictionary::makeAtPath<cpp::string_view>(dictionary::Item* baseItem, const char* path, cpp::string_view value)
{
makeStringAtPath(baseItem, path, value.data(), value.length());
}
template <>
inline void IDictionary::makeAtPath<omni::string>(dictionary::Item* baseItem, const char* path, omni::string value)
{
makeStringAtPath(baseItem, path, value.data(), value.size());
}
template <>
inline void IDictionary::setArray(Item* baseItem, const bool* array, size_t arrayLength)
{
setBoolArray(baseItem, array, arrayLength);
}
template <>
inline void IDictionary::setArray(Item* baseItem, const int32_t* array, size_t arrayLength)
{
setIntArray(baseItem, array, arrayLength);
}
template <>
inline void IDictionary::setArray(Item* baseItem, const int64_t* array, size_t arrayLength)
{
setInt64Array(baseItem, array, arrayLength);
}
template <>
inline void IDictionary::setArray(Item* baseItem, const float* array, size_t arrayLength)
{
setFloatArray(baseItem, array, arrayLength);
}
template <>
inline void IDictionary::setArray(Item* baseItem, const double* array, size_t arrayLength)
{
setFloat64Array(baseItem, array, arrayLength);
}
template <>
inline void IDictionary::setArray(Item* baseItem, const char* const* array, size_t arrayLength)
{
setStringArray(baseItem, array, arrayLength);
}
template <>
inline void IDictionary::makeAtPath<Int2>(dictionary::Item* baseItem, const char* path, Int2 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<int32_t>(item, &value.x, 2);
}
template <>
inline void IDictionary::makeAtPath<Int3>(dictionary::Item* baseItem, const char* path, Int3 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<int32_t>(item, &value.x, 3);
}
template <>
inline void IDictionary::makeAtPath<Int4>(dictionary::Item* baseItem, const char* path, Int4 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<int32_t>(item, &value.x, 4);
}
template <>
inline void IDictionary::makeAtPath<Uint2>(dictionary::Item* baseItem, const char* path, Uint2 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
int64_t values64[] = { value.x, value.y };
setArray<int64_t>(item, values64, 2);
}
template <>
inline void IDictionary::makeAtPath<Uint3>(dictionary::Item* baseItem, const char* path, Uint3 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
int64_t values64[] = { value.x, value.y, value.z };
setArray<int64_t>(item, values64, 3);
}
template <>
inline void IDictionary::makeAtPath<Uint4>(dictionary::Item* baseItem, const char* path, Uint4 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
int64_t values64[] = { value.x, value.y, value.z, value.w };
setArray<int64_t>(item, values64, 4);
}
template <>
inline void IDictionary::makeAtPath<Float2>(dictionary::Item* baseItem, const char* path, Float2 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<float>(item, &value.x, 2);
}
template <>
inline void IDictionary::makeAtPath<Float3>(dictionary::Item* baseItem, const char* path, Float3 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<float>(item, &value.x, 3);
}
template <>
inline void IDictionary::makeAtPath<Float4>(dictionary::Item* baseItem, const char* path, Float4 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<float>(item, &value.x, 4);
}
template <>
inline void IDictionary::makeAtPath<Double2>(dictionary::Item* baseItem, const char* path, Double2 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<double>(item, &value.x, 2);
}
template <>
inline void IDictionary::makeAtPath<Double3>(dictionary::Item* baseItem, const char* path, Double3 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<double>(item, &value.x, 3);
}
template <>
inline void IDictionary::makeAtPath<Double4>(dictionary::Item* baseItem, const char* path, Double4 value)
{
dictionary::Item* item = baseItem;
if (path && path[0] != '\0')
{
item = makeDictionaryAtPath(baseItem, path);
}
setArray<double>(item, &value.x, 4);
}
#endif
inline void IDictionary::deleteChildren(Item* item)
{
ScopedWrite g(*this, item);
size_t childCount = getItemChildCount(item);
while (childCount != 0)
destroyItem(getItemChildByIndexMutable(item, --childCount));
}
inline void IDictionary::copyItemFlags(Item* dstItem, const Item* srcItem)
{
setItemFlag(dstItem, ItemFlag::eUnitSubtree, getItemFlag(srcItem, ItemFlag::eUnitSubtree));
}
} // namespace dictionary
} // namespace carb