////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
// All rights reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// THIS IS AUTO-GENERATED CODE.  PLEASE DO NOT EDIT (File bug reports against tools).
///
/// Auto-generated by: Parameter Parser V7.4.1 (8cca6579792b9fcef3bc725ff070c5ec453c7c85)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  parameterfilesymboltableentry.cpp
/// @brief Auto-generated Chromatix parameter file
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "parametersetmanager.h"
#include "parameterfilesymboltableentry.h"
#include "parameterfilesymboltable.h"

ParameterFileSymbolTableEntry::ParameterFileSymbolTableEntry()
{
    Table         = nullptr;
    ID            = 0;
    DuplicateID   = 0;
    Module        = nullptr;
    Position      = 0;
    Data          = nullptr;
    DataSize      = 0;
    DataAllocated = false;
}

ParameterFileSymbolTableEntry::~ParameterFileSymbolTableEntry()
{
    PARAMETER_DELETE Module;
    Module = nullptr;

    if (DataAllocated)
    {
        PARAMETER_DELETE[] Data;
    }

    Data = nullptr;
}

BYTE ParameterFileSymbolTableEntry::GetAlignment()
{
    return Table->Alignment;
}

void ParameterFileSymbolTableEntry::Init(
    ParameterFileSymbolTable* const table)
{
    Table      = table;
    Position   = 0;
    Data       = nullptr;
}

bool ParameterFileSymbolTableEntry::Load(
    BYTE* const                buffer,
    const CHAR* const          fileName,
    ParameterBinaryFile* const file,
    UINT32 const               length,
    UINT32&                    pos,
    UINT32 const               dataOffset,
    IModeTable*                modeTable,
    bool const                 isModule,
    UINT32                     id)
{
    UINT32 readSize   = length;
    UINT32 readPos    = pos;
    UINT8* readBuffer = buffer;

    if (file != nullptr)
    {
        const UINT32 tableOffset = isModule || Table->DataTableOffset == 0 ? Table->SymbolTableOffset : Table->DataTableOffset;
        readSize   = Table->GetSymbolEntrySize();
        readBuffer = file->Read(tableOffset + readPos, readSize);
        readPos    = 0;
    }

    bool result = readBuffer != nullptr;
    if (result)
    {
        UINT32 offset       = 0;
        UINT64 nameHash     = 0;
        UINT64 versionValue = 0;
        UINT32 modeId       = 0;
        CHAR   type[TYPE_LEN + 1];

        type[0] = 0;
        ID = id;
        if (Table->Version < Table->StructSymbolsVersion)
        {
            result = ParameterUtils::Read(&ID, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
        }

        if (result && isModule)
        {
            UINT64 modeValue = 0;

            if (Table->Version < Table->StructSymbolsVersion)
            {
                result = ParameterUtils::ReadString(type, readBuffer, readSize, readPos, TYPE_LEN + 1, TYPE_LEN, GetAlignment(), Table->SetManager);
            }
            else
            {
                result = ParameterUtils::Read(&nameHash, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
            }
            if (result)
            {
                result = ParameterUtils::Read(&versionValue, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
            }

            if (GetAlignment() == 1 && Table->Version < Table->AlignedEndVersion)
            {
                // Alignment 1 is legacy (V 1.0.x) binary format, read mode, submode, and group
                if (result)
                {
                    result = ParameterUtils::Read(&modeValue, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
                }
            }

            if (result)
            {
                result = ParameterUtils::Read(&modeId, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
            }
        }

        if (result)
        {
            result = ParameterUtils::Read(&offset,   readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
        }
        if (result)
        {
            result = ParameterUtils::Read(&DataSize, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
        }

        if (Table->Version > Table->AlignedEndVersion)
        {
            // Versions after 3.0.1 (aligned end version) have an duplicate ID entry.
            // If DuplicateID != ID, then this entry's data is a duplicate of DuplicateID's
            if (result)
            {
                result = ParameterUtils::Read(&DuplicateID, readBuffer, readSize, readPos, GetAlignment(), Table->SetManager);
                if (isModule && DuplicateID > Table->Count())
                {
                    PARAMETER_LOG_ERROR(Table->SetManager, "Invalid DuplicateID value %u, should be less than module table count: %u\n",
                        DuplicateID, Table->Count());
                }
                else if (!isModule && DuplicateID > Table->DTCount())
                {
                    PARAMETER_LOG_ERROR(Table->SetManager, "Invalid DuplicateID value %u, should be less than data table count: %u\n",
                        DuplicateID, Table->DTCount());
                }
            }
        }
        else
        {
            DuplicateID = ID;
        }

        if (isModule && ParameterFileSymbolTableEntry::CheckIsModule(modeId))
        {
            Module = PARAMETER_NEW ModuleData(ID, DuplicateID, modeTable, nameHash, versionValue, modeId, Table->SetManager);
        }

        if (fileName == nullptr || file == nullptr)
        {
            Data          = buffer + dataOffset + offset;
            DataAllocated = false;
            pos           = readPos;
        }
        else
        {
            PARAMETER_DELETE[] readBuffer;
            Data          = DataSize > 0 ? file->Read(dataOffset + offset, DataSize) : 0;
            DataAllocated = true;
            pos           = pos + readPos;
        }
    }

    return result;
}

bool ParameterFileSymbolTableEntry::IsFixedCountVersion()
{
    return Table != nullptr && Table->Version >= Table->MultiModeTableVersion;
}

void* ParameterFileSymbolTableEntry::SetFromDupObject(
    INT32 const location)
{
    void* result = nullptr;
    DupObjInfo* dupInfo = GetDupObject(location);
    if (dupInfo != nullptr)
    {
        result = dupInfo->Object;
    }

    return result;
}

void ParameterFileSymbolTableEntry::LogMessage(
    bool const        isError,
    const CHAR* const str, ...)
{
    CHAR message[ParameterLogging::MESSAGE_LEN];
    va_list args;
    va_start(args, str);
    PARAMETER_VSPRINTF(message, ParameterLogging::MESSAGE_LEN, str, args);
    va_end(args);

    ParameterLogging::Write(Table->SetManager, isError ? 
        ParameterLogging::ParameterLogLevel::Error : 
        ParameterLogging::ParameterLogLevel::Warning, "%s", message);
}

UINT32 ParameterFileSymbolTableEntry::ReadLoadDataLimit(
    UINT32 parentLimit)
{
    UINT32 limit = LOAD_LIMIT_MAX;

    if (Table->Version >= Table->StructSymbolsVersion)
    {
        Read(limit, nullptr, parentLimit);
        limit += Position;
        if (limit > parentLimit)
        {
            PARAMETER_LOG_ERROR(Table->SetManager,
                "Load limit (%u) exceeds available size (%u). XSD structure modified\n", 
                 limit, parentLimit);
            limit = parentLimit;
        }
    }

    return limit;
}

bool ParameterFileSymbolTableEntry::ReadPointerEntry(
    ParameterFileSymbolTableEntry& entry)
{
    bool result = false;
    if (Table != nullptr)
    {
        result = Table->ReadPointerEntry(entry, this);
    }

    return result;
}

bool ParameterFileSymbolTableEntry::GetCountAndPointerEntry(
    UINT32&                         count,
    ParameterFileSymbolTableEntry*& pointerEntry,
    ParameterFileSymbolTableEntry&  pointerEntryCls,
    SIZE_T                          elementSize,
    UINT32                          minCount,
    UINT64                          nameHash,
    bool                            alwaysRead,
    bool                            isFixed, // Indicates the caller is a fixed length array
    bool                            isArray, // Indicates the caller is a variable length array
    ParameterDefinitionElement*     element,
    bool&                           countChanged,
    UINT32 const                    loadDataLimit)
{
    bool result = true;
    countChanged = false;

    if (((element == nullptr || element->Info == nullptr) && alwaysRead) ||
        (element != nullptr && element->Info != nullptr && (element->IsPointer() || (element->IsString() && !isFixed && !isArray && !element->IsFixed()))))
    {
        Read(count, nullptr, loadDataLimit);
        pointerEntry = &pointerEntryCls;
        result = ReadPointerEntry(pointerEntryCls);

        if (element != nullptr && element->Info != nullptr)
        {
            elementSize = element->GetSize();
        }
        else if (Table != nullptr && Table->Version < Table->StructSymbolsVersion)
        {
            // Binary format V5 and older do not have the load limit varible, so remove its size
            elementSize -= sizeof(UINT32);
        }
        if (count * elementSize > pointerEntry->DataSize)
        {
            // Minimun size * count exceeds avaialable data
            SIZE_T newCount = PARAMETER_MAX(minCount, pointerEntry->DataSize / elementSize);
            PARAMETER_LOG_ERROR(Table->SetManager,
                "Minimun %ld size (%u) * count (%u) exceeds avaialable data (%u), setting count to %u to prevent allocation errors\n",
                nameHash, elementSize, count, pointerEntry->DataSize, newCount);
            count = (UINT32)newCount;
            countChanged = true;
        }
    }
    else if (IsFixedCountVersion())
    {
        if ((element != nullptr && element->IsFixed()) || ((element == nullptr || element->Info == nullptr) && isFixed && count > 1))
        {
            // Read the fixed array count
            Read(count, nullptr, loadDataLimit);
            countChanged = element != nullptr && element->Info != nullptr && count != element->Info->MaxCount;
        }
        else if (element != nullptr && element->Info != nullptr)
        {
            count        = element->Info->MaxCount;
            countChanged = count != element->Info->MaxCount;
        }
    }

    return result;
}

ParameterDefinitionElement* ParameterFileSymbolTableEntry::AdjustPositionAndGetElement(
    ParameterLoadParameters& params,
    bool const               setVerified,
    bool&                    posChanged)
{
    ParameterDefinitionElement* result = nullptr;
    ParameterDefinitionElement* const parent = params.Element;
    posChanged = false;
    if (parent != nullptr && parent->Info != nullptr && parent->Info->Structure != nullptr)
    {
        if (params.UseParent)
        {
            result = parent;
            if (parent->NameHash != params.NameHash)
            {
                PARAMETER_LOG_WARNING(Table->SetManager, "%s: Use Parent requested, but parent name hash (0x%llx) does not match variable name hash (0x%llx)\n",
                    __FUNCTION__, parent->NameHash, params.NameHash);
            }
        }
        else
        {
            result = parent->Info->Structure->FindChild(params.NameHash);
        }

        if (result != nullptr && result->Info != nullptr)
        {
            UINT32 pos = params.Position + (parent->Info->Structure->Size * params.Index) + (params.UseParentOffset ? result->Info->ParentOffset : 0);

            if (Position != pos)
            {
                posChanged = true;
                PARAMETER_LOG_WARNING(Table->SetManager,
                    "Binary file position (%u) differs from expected (%u), XSD structure modified\n", pos, Position);

                if (pos < params.LoadDataLimit)
                {
                    params.Position = pos;
                }
                else
                {
                    LogMessage(true,
                        "Error Reading 0x%llx: Adjusted position (%u) exceeds load limit (%u)\n",
                        params.NameHash, pos, params.LoadDataLimit);
                }
            }
            else if (setVerified)
            {
                result->Verified = true;
            }
        }
    }

    return result;
}

void ParameterFileSymbolTableEntry::UpdatePosition(
    UINT32            limit)
{
    if (limit != LOAD_LIMIT_MAX)
    {
        if (Position != limit)
        {
            PARAMETER_LOG_WARNING(Table->SetManager, "Binary file structure bytes (%u) does not match expected bytes (%u). XSD structure modified\n", limit, Position);
        }
        Position = limit;
    }
}

void ParameterFileSymbolTableEntry::ReadStructureFixedArray(
    ParameterLoadArrayFunc   loadArrayFunc,
    void*                    arrayPtr,
    UINT32 const             fixedCount,
    ParameterLoadParameters& params)
{
    UINT32                         variableCount = fixedCount;
    ParameterFileSymbolTableEntry* pointerEntry  = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;

    bool posChanged   = false;
    bool countChanged = false;
    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(variableCount, pointerEntry, pointerEntryCls, sizeof(UINT32) * 2, fixedCount, params.NameHash,
        false, fixedCount > 1U, false, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        (fixedCount == 1U || element->IsFixed()) && fixedCount == element->Info->MaxCount && !element->IsPointer() && element->Info->Type == ParameterDefinitionType_Structure)
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        // Read variableCount entries from the binary file
        UINT32 elementPos = pointerEntry->Position; // Default to the pointer beginning
        if (pointerEntry == this)
        {
            // Not a pointer, use parent position instead
            elementPos = params.Position;
            if (IsFixedCountVersion() && ((element != nullptr && element->IsFixed()) || ((element == nullptr || element->Info == nullptr) && fixedCount > 1U)))
            {
                // Fixed array in binary file, add in the count size
                elementPos += 4U;
            }
        }

        localParams.Entry           = pointerEntry;
        localParams.UseParent       = true;
        localParams.UseParentOffset = this == pointerEntry;
        localParams.Element         = element;
        localParams.Position        = elementPos;
        localParams.LoadDataLimit   = LOAD_LIMIT_MAX;

        (*loadArrayFunc)(localParams, arrayPtr, fixedCount);

        if (variableCount != fixedCount)
        {
            LogMessage(false,
                "0x%llx expected count (%u) != the binary count (%u), the binary XSD != the source XSD\n",
                params.NameHash, fixedCount, variableCount);
        }
    }
    else
    {
        LogMessage(false, "%s: 0x%llx entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }
}

void* ParameterFileSymbolTableEntry::ReadStructureArray(
    ParameterLoadArrayFunc   loadArrayFunc,
    ParameterAllocArrayFunc  allocArrayFunc,
    UINT32&                  count,
    UINT32&                  id,
    UINT32                   minCount,
    ParameterLoadParameters& params,
    INT32 const              location)
{
    void* varArrayPtr = nullptr;
    ParameterFileSymbolTableEntry* pointerEntry = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;

    bool posChanged   = false;
    bool countChanged = false;
    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(count, pointerEntry, pointerEntryCls, sizeof(UINT32) * 2, minCount, params.NameHash,
        true, false, true, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        element->IsPointer() && element->Info->Type == ParameterDefinitionType_Structure)
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        id = pointerEntry->ID;
        if (element == nullptr || element->Info == nullptr || element->IsPointer() || element->IsString())
        {
            varArrayPtr = pointerEntry->SetFromDupObject(location);
        }

        if (varArrayPtr == nullptr)
        {
            if (result && count > 0)
            {
                varArrayPtr = (*allocArrayFunc)(count);
            }
            if (!result || varArrayPtr == nullptr)
            {
                if (count > 0)
                {
                    LogMessage(true, "Failed to allocate 0x%llx\n", params.NameHash);
                }
                count = 0;
            }

            UINT32 elementPos = pointerEntry->Position; // Default to the pointer beginning
            if (pointerEntry == this)
            {
                // Not a pointer, use parent position instead
                elementPos = params.Position;
                if (IsFixedCountVersion() && (element != nullptr && element->IsFixed()))
                {
                    // Fixed array in binary file, add in the count size
                    elementPos += 4U;
                }
            }

            if (varArrayPtr != nullptr)
            {
                localParams.Entry            = pointerEntry;
                localParams.UseParent        = true;
                localParams.UseParentOffset  = this == pointerEntry;
                localParams.Element          = element;
                localParams.Position         = elementPos;
                localParams.LoadDataLimit    = LOAD_LIMIT_MAX;

                (*loadArrayFunc)(localParams, varArrayPtr, count);

                if ((element == nullptr || element->Info == nullptr || element->IsPointer() || element->IsString()))
                {
                    (void)pointerEntry->SetDupObject(varArrayPtr, location);
                }
            }
        }
    }
    else
    {
        LogMessage(false, "%s: 0x%llx entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }

    if (varArrayPtr == nullptr)
    {
        count = 0;
    }

    return varArrayPtr;
}

void ParameterFileSymbolTableEntry::ReadOptionalStructure(
    ParameterLoadArrayFunc   loadArrayFunc,
    void*                    variable,
    UINT32&                  exists,
    UINT32&                  id,
    ParameterLoadParameters& params)
{
    ParameterFileSymbolTableEntry* pointerEntry = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;

    bool posChanged   = false;
    bool countChanged = false;

    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(exists, pointerEntry, pointerEntryCls, sizeof(UINT32) * 2, 0, params.NameHash,
        true, false, true, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        !element->IsFixed() && element->IsPointer() && element->Info->MaxCount == 1U && element->Info->Type == ParameterDefinitionType_Structure)
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        id = pointerEntry->ID;
        if (exists != 0)
        {
            localParams.Entry           = pointerEntry;
            localParams.UseParent       = true;
            localParams.UseParentOffset = this == pointerEntry;
            localParams.Element         = element;
            localParams.Position        = pointerEntry->Position;
            localParams.Index           = 0;
            localParams.LoadDataLimit   = LOAD_LIMIT_MAX;
            loadArrayFunc(localParams, variable, 1);
        }
    }
    else
    {
        LogMessage(false, "%s: 0x%llx entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }

    if (!result)
    {
        exists = 0;
    }
}

void ParameterFileSymbolTableEntry::ReadStringFixedArray(
    CHAR**                   str,
    UINT32 const             fixedCount,
    ParameterLoadParameters& params,
    INT32 const              location)
{
    UINT32                         variableCount = fixedCount;
    ParameterFileSymbolTableEntry* pointerEntry  = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;

    bool posChanged   = false;
    bool countChanged = false;

    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(variableCount, pointerEntry, pointerEntryCls, sizeof(UINT32) * 2, fixedCount, params.NameHash,
        false, true, false, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        (fixedCount == 1U || element->IsFixed()) && fixedCount == element->Info->MaxCount && !element->IsPointer() && element->IsString())
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        // Read variableCount entries from the binary file
        for (UINT32 i = 0; str != nullptr && i < fixedCount; i++)
        {
            str[i] = nullptr;
            if (i < variableCount)
            {
                pointerEntry->ReadString(str[i], location, ParameterFileSymbolTableEntry::LOAD_LIMIT_MAX);
            }
        }

        if (variableCount != fixedCount)
        {
            LogMessage(false,
                "0x%llx expected count (%u) != the binary count (%u), the binary XSD != the source XSD\n",
                params.NameHash, fixedCount, variableCount);
        }
    }
    else
    {
        PARAMETER_LOG_ERROR(Table->SetManager, "%s: 0x%llx entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }
}

void ParameterFileSymbolTableEntry::ReadStringArray(
    CHAR**&                  str,
    UINT32&                  count,
    UINT32&                  id,
    UINT32 const             minCount,
    ParameterLoadParameters& params,
    INT32 const              location)
{
    ParameterFileSymbolTableEntry* pointerEntry = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;

    bool posChanged   = false;
    bool countChanged = false;

    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(count, pointerEntry, pointerEntryCls, sizeof(UINT32) * 2, minCount, params.NameHash,
        true, false, true, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        element->IsPointer() && element->IsString())
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        id = pointerEntry->ID;
        if (element == nullptr || element->Info == nullptr || element->IsPointer())
        {
            pointerEntry->SetFromDupObject(str, location);
        }

        if (str == nullptr)
        {
            if (result && count > 0)
            {
                str = PARAMETER_NEW CHAR*[count];
            }
            if (!result || str == nullptr)
            {
                if (count > 0)
                {
                    LogMessage(true, "Failed to allocate 0x%llx\n", params.NameHash);
                }
                count = 0;
            }

            for (UINT32 i = 0; i < count; i++)
            {
                pointerEntry->ReadString(str[i], location, ParameterFileSymbolTableEntry::LOAD_LIMIT_MAX);
            }

            if (str != nullptr && (element == nullptr || element->Info == nullptr || element->IsPointer()))
            {
                (void)pointerEntry->SetDupObject(str, location);
            }
        }
    }
    else
    {
        PARAMETER_LOG_ERROR(Table->SetManager, "%s: 0x%llx entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }

    if (str == nullptr)
    {
        count = 0;
    }
}

void ParameterFileSymbolTableEntry::ReadOptionalString(
    CHAR*&                   str,
    UINT32&                  exists,
    UINT32&                  id,
    ParameterLoadParameters& params,
    INT32 const              location)
{
    ParameterFileSymbolTableEntry* pointerEntry = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;

    bool posChanged   = false;
    bool countChanged = false;

    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(exists, pointerEntry, pointerEntryCls, sizeof(UINT32) * 2, 0, params.NameHash,
        true, false, true, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        !element->IsFixed() && element->IsPointer() && element->Info->MaxCount == 1U && element->IsString())
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        id = pointerEntry->ID;
        if (exists != 0)
        {
            pointerEntry->ReadString(str, location, ParameterFileSymbolTableEntry::LOAD_LIMIT_MAX);
        }
    }
    else
    {
        PARAMETER_LOG_ERROR(Table->SetManager, "%s: 0x%llx entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }

    if (!result)
    {
        exists = 0;
    }
}

void ParameterFileSymbolTableEntry::ReadString(
    CHAR*&                   str,
    ParameterLoadParameters& params,
    INT32 const              location)
{
    ParameterFileSymbolTableEntry* pointerEntry = this;
    ParameterFileSymbolTableEntry  pointerEntryCls;
    UINT32 count = 0;

    bool posChanged   = false;
    bool countChanged = false;

    ParameterLoadParameters localParams(params);
    localParams.UseParent       = false;
    localParams.UseParentOffset = true;
    localParams.Index           = 0;
    ParameterDefinitionElement* element = AdjustPositionAndGetElement(localParams, false, posChanged);
    bool result = GetCountAndPointerEntry(count, pointerEntry, pointerEntryCls, sizeof(CHAR), 0, params.NameHash,
        true, false, false, element, countChanged, params.LoadDataLimit);

    // Test for element match and remove the element if the XSD source matches the binary
    if (params.Element != nullptr && element != nullptr && element->Info != nullptr && !element->Verified && !posChanged && !countChanged &&
        !element->IsFixed() && !element->IsPointer() && element->IsString())
    {
        element->Verified = true;
    }

    // If params.Element != null && element == null, then this element is not defined in the binary file
    // If params.Element == null then this binary file does not contain a definition table or
    // the full backwards compatibility feature is disabled (for memory or performance reasons)
    if (result && (params.Element == nullptr || params.Element->Verified || element != nullptr))
    {
        pointerEntry->ReadString(&str, count, location, ParameterFileSymbolTableEntry::LOAD_LIMIT_MAX);
    }
    else
    {
        PARAMETER_LOG_ERROR(Table->SetManager, "0x%llx: %s entry not found in the binary file, all values will be 0\n",
            __FUNCTION__, params.NameHash);
    }
}

void ParameterFileSymbolTableEntry::ReadString(
    CHAR*&       str,
    INT32 const  location,
    UINT32 const limit)
{
    UINT32 count = 0;
    Read(count, nullptr, limit);
    ParameterFileSymbolTableEntry stringPointerEntryCls;
    if (Table->ReadPointerEntry(stringPointerEntryCls, this))
    {
        stringPointerEntryCls.ReadString(&str, count, location, ParameterFileSymbolTableEntry::LOAD_LIMIT_MAX);
    }
}

void ParameterFileSymbolTableEntry::ReadString(
    CHAR** const str,
    UINT32 const maxChars,
    INT32 const  location,
    UINT32 const limit)
{
     DupObjInfo* const dupInfo = GetDupObject(location);

    *str = nullptr;
    if (dupInfo != nullptr)
    {
        *str = (CHAR*)dupInfo->Object;
    }

    if (*str == nullptr)
    {
        if (Data != nullptr)
        {
            *str = ParameterUtils::ReadString(Data, PARAMETER_MIN(DataSize, limit), Position, maxChars, GetAlignment());

            if (*str != nullptr)
            {
                SetDupObject(*str, location);
            }
        }
    }
    else
    {
        Position += maxChars;
    }

    if (*str == nullptr)
    {
        PARAMETER_LOG_WARNING(Table->SetManager, "Failed to read string entry\n");
    }
}

DupObjInfo* ParameterFileSymbolTableEntry::GetDupObject(
    INT32 const location)
{
    return Table->GetDupObject(IsModule(), DuplicateID, location);
}

DupObjInfo* ParameterFileSymbolTableEntry::SetDupObject(
    void* const obj,
    INT32 const location)
{
    return Table->SetDupObject(IsModule(), DuplicateID, obj, location);
}

ParameterSetManager* ParameterFileSymbolTableEntry::GetSetManager()
{
    return Table->SetManager;
}
