text:
extern "C"
{
#include <_libdwarf.h>

#ifndef DW_AT_MIPS_linkage_name
#   define DW_AT_MIPS_linkage_name  0x2007
#endif
}

#include <gelf.h>

#if AMDT_BUILD_TARGET == AMDT_WINDOWS_OS
    #define DWARF_API  __cdecl
#else
    #define DWARF_API
#endif

static int DWARF_API Access_get_section_info(void* pObj, Dwarf_Half index, Dwarf_Obj_Access_Section* pSection, int* pError);
static Dwarf_Endianness DWARF_API Access_get_byte_order(void* pObj);
static Dwarf_Small DWARF_API Access_get_length_size(void* pObj);
static Dwarf_Small DWARF_API Access_get_pointer_size(void* pObj);
static Dwarf_Unsigned DWARF_API Access_get_section_count(void* pObj);
static int DWARF_API Access_load_section(void* pObj, Dwarf_Half index, Dwarf_Small** ppData, int* pError);

static wchar_t* GetDemangledName(Dwarf_Debug dbg, Dwarf_Die die);
static wchar_t* ExtractSubprogramName(Dwarf_Debug dbg, Dwarf_Die die);
static Dwarf_Die DieFindAttribute(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half nattr);
static void InitCompilationUnit(Dwarf_Debug dbg);

#if AMDT_BUILD_TARGET == AMDT_WINDOWS_OS
    #define ACQUIRE_DWARF_LOCK(_lock)   osCriticalSectionLocker guard(const_cast<osCriticalSection&>(_lock))
#else
    #define ACQUIRE_DWARF_LOCK(_lock)
#endif

DwarfSymbolEngine::DwarfSymbolEngine() : m_pExe(NULL), m_dbg(NULL), m_pBuffers(NULL), m_pAuxSymEngine(NULL),
    m_processInlineSamples(false), m_aggregateInlineSamples(false)
{
}

DwarfSymbolEngine::~DwarfSymbolEngine()
{
    Clear();
}

bool DwarfSymbolEngine::Initialize(const ExecutableFile& exe, ModularSymbolEngine* pAuxSymEngine, Elf* pElf)
{
    bool ret = true;
    m_pExe = &exe;

    if (NULL == m_pExe)
    {
        ret = false;
    }

    ret = ret && (DW_DLE_NONE == _dwarf_alloc(&m_dbg, DW_DLC_READ, NULL));

    m_processInlineSamples = m_pExe->IsProcessInlineInfo();
    m_aggregateInlineSamples = m_pExe->IsAggregateInlinedInstances();

    if (ret)
    {
        if (NULL != pElf)
        {
            ret = (DW_DLE_NONE == _dwarf_elf_init(m_dbg, pElf, NULL));
        }
        else
        {
            static const Dwarf_Obj_Access_Methods PeAccessMethods =
            {
                Access_get_section_info,
                Access_get_byte_order,
                Access_get_length_size,
                Access_get_pointer_size,
                Access_get_section_count,
                Access_load_section
            };

            Dwarf_Obj_Access_Interface* iface = new Dwarf_Obj_Access_Interface;
            iface->object = this;
            iface->methods = &PeAccessMethods;

            m_dbg->dbg_iface = iface;
            m_dbg->dbg_machine = exe.Is64Bit() ? (Dwarf_Half)EM_X86_64 : (Dwarf_Half)EM_386;
        }

        ret = ret && (DW_DLE_NONE == _dwarf_init(m_dbg, 0, NULL, NULL, NULL));

        if (ret)
        {
            InitializeFunctionsInfo();
            ret = ForeachCompilationUnit(&DwarfSymbolEngine::TraverseSubprograms);

            if (ret)
            {
                gtSort(m_pFuncsInfoVec->begin(), m_pFuncsInfoVec->end());

                if (NULL != pAuxSymEngine)
                {
                    pAuxSymEngine->Splice(*this);

                    if (pAuxSymEngine->HasSourceLineInfo())
                    {
                        m_pAuxSymEngine = pAuxSymEngine;
                    }
                    else
                    {
                        // We have no further use of the auxiliary symbol engine.
                        delete pAuxSymEngine;
                    }
                }
            }
            else
            {
                Clear(true);
            }
        }
        else
        {
            Clear(false);
        }
    }

    return ret;
}

bool DwarfSymbolEngine::TraverseSubprograms(Dwarf_Die cuDie, void*)
{
    Dwarf_Die die;
    int r = dwarf_child(cuDie, &die, NULL);
    // dwarf_child can return DW_DLE_NO_ENTRY and in that case we need to stop traversing.
    bool ret = (DW_DLV_OK == r) ? true : false;

    if (DW_DLV_OK == r)
    {
        // We are looking for symbol information that belong to a function (subprogram) which stays at level 1.
        // Therefore, we only need to iterate over the level 1 siblings.
        do
        {
            Dwarf_Half tag;

            if (dwarf_tag(die, &tag, NULL) != DW_DLV_OK)
            {
                ret = false;
                break;
            }

            if (DW_TAG_subprogram == tag)
            {
                Dwarf_Addr addrLow, addrHigh;

                if (dwarf_lowpc(die, &addrLow , NULL) == DW_DLV_OK && dwarf_highpc(die, &addrHigh , NULL) == DW_DLV_OK)
                {
                    wchar_t* pName = ExtractSubprogramName(m_dbg, die);

                    if (NULL != pName)
                    {
                        FunctionSymbolInfo funcInfo;
                        FUNCSYM_OFFSET_SUPPORT(funcInfo.m_offset = 0U;)
                        funcInfo.m_addrRanges = NULL;
                        funcInfo.m_rva = static_cast<gtRVAddr>(addrLow - m_pExe->GetImageBase());
                        funcInfo.m_size = (addrLow <= addrHigh) ? static_cast<gtUInt32>(addrHigh - addrLow) :
                                          static_cast<gtUInt32>(addrHigh);
                        funcInfo.m_pName = pName;
                        funcInfo.m_funcId = AtomicAdd(m_nextFuncId, 1);

                        m_pFuncsInfoVec->push_back(funcInfo);
                    }
                }
            }

            Dwarf_Die siblingDie = NULL;
            r = dwarf_siblingof(m_dbg, die, &siblingDie, NULL);
            dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
            die = siblingDie;

            ret = DW_DLV_ERROR != r;
        }
        while (DW_DLV_OK == r);

        if (NULL != die)
        {
            dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
        }
    }

    return ret;
}

// Process the complete subprogram DIE tree for inline information
bool DwarfSymbolEngine::ProcessInlinedFunctionInfo(Dwarf_Die rootDie, Dwarf_Addr cuAddrLow) const
{
    bool ret = false;

    gtQueue<Dwarf_Die> dieQueue;
    dieQueue.push(rootDie);

    while (!dieQueue.empty())
    {
        Dwarf_Die die = dieQueue.front();
        Dwarf_Die childDie;

        if (dwarf_child(die, &childDie, NULL) == DW_DLV_OK)
        {
            int r;

            do
            {
                bool keep_childDie = false;  // to dealloc the childDie or not
                Dwarf_Half tag;

                if (dwarf_tag(childDie, &tag, NULL) != DW_DLV_OK)
                {
                    // can't process further
                    dwarf_dealloc(m_dbg, childDie, DW_DLA_DIE);
                    break;
                }

                if (DW_TAG_subprogram == tag || DW_TAG_lexical_block == tag)
                {
                    dieQueue.push(childDie);
                    keep_childDie = true;
                }
                else if (DW_TAG_inlined_subroutine == tag)
                {
                    Dwarf_Addr addrLow = 0, addrHigh = 0;
                    gtVector<FuncAddressRange>* addrRanges = new gtVector<FuncAddressRange>;

                    DieFindLowHighAddress(childDie, tag, cuAddrLow, addrLow, addrHigh, addrRanges);

                    // if address ranges list is empty, then delete it
                    if (addrRanges->empty())
                    {
                        delete addrRanges;
                        addrRanges = NULL;
                    }
                    else
                    {
                        gtSort(addrRanges->begin(), addrRanges->end());
                    }

                    ret = AddInlinedFuncInfo(childDie, addrLow, addrHigh, addrRanges);
                    addrRanges = NULL; // list is saved to funcinfo, no need to delete

                    // inlined_subroutine might contain another inlined_subroutine
                    // add it to queue
                    dieQueue.push(childDie);
                    keep_childDie = true;
                }

                Dwarf_Die siblingDie = NULL;
                r = dwarf_siblingof(m_dbg, childDie, &siblingDie, NULL);

                if (false == keep_childDie)
                {
                    dwarf_dealloc(m_dbg, childDie, DW_DLA_DIE);
                }

                childDie = siblingDie;
                ret = DW_DLV_ERROR != r;
            }
            while (DW_DLV_OK == r);
        }

        if (die != rootDie)
        {
            // don't free rootDie, as it will be deallocated by caller
            dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
        }

        dieQueue.pop();
    }

    return ret;
}

bool DwarfSymbolEngine::AddInlinedFuncInfo(Dwarf_Die die, Dwarf_Addr addrLow, Dwarf_Addr addrHigh, gtVector<FuncAddressRange>* addrRanges) const
{
    FunctionSymbolInfo funcInfo;
    funcInfo.m_rva = static_cast<gtRVAddr>(addrLow - m_pExe->GetImageBase());
    funcInfo.m_size = static_cast<gtRVAddr>(addrHigh - addrLow);
    funcInfo.m_pName = ExtractSubprogramName(m_dbg, die);
    funcInfo.m_addrRanges = addrRanges;
    UpdateInlinedFunctionName(funcInfo);

    auto res = m_inlinedFuncsInfo.insert(FunctionsMap::value_type(funcInfo, false));

    if (false == res.second)
    {
        funcInfo.m_rva += 1;
        m_inlinedFuncsInfo.insert(FunctionsMap::value_type(funcInfo, false));
    }

    return true;
}

bool DwarfSymbolEngine::ForeachCompilationUnit(bool (DwarfSymbolEngine::* pfnProcess)(Dwarf_Die, void*), void* pData)
{
    bool ret = true;
    Dwarf_Die die = NULL;

    ACQUIRE_DWARF_LOCK(m_dwarfLock);
    InitCompilationUnit(m_dbg);

    while (dwarf_next_cu_header(m_dbg, NULL, NULL, NULL, NULL, NULL, NULL) == DW_DLV_OK)
    {
        if (dwarf_siblingof(m_dbg, NULL, &die, NULL) != DW_DLV_OK)
        {
            continue;
        }

        Dwarf_Half tag;

        if (dwarf_tag(die, &tag, NULL) != DW_DLV_OK)
        {
            ret = false;
            break;
        }

        if (DW_TAG_compile_unit == tag)
        {
            if (!(this->*pfnProcess)(die, pData))
            {
                ret = false;
                break;
            }
        }

        dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
        die = NULL;
    }

    if (NULL != die)
    {
        dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
    }

    return ret;
}

bool DwarfSymbolEngine::TraverseSourceLines(Dwarf_Die cuDie, void* pData)
{
    std::pair<const char*, SrcLineInstanceMap*>* pFullData = static_cast<std::pair<const char*, SrcLineInstanceMap*>*>(pData);
    const char* pSourceFilePath = pFullData->first;
    SrcLineInstanceMap& srcLineInstanceMap = *pFullData->second;

    // Do not call dwarf_dealloc() routines on this pointer. _dwarf_deinit() does the deallocation.
    char** srcFiles = NULL;
    Dwarf_Signed srcCount;

    if (DW_DLV_OK == dwarf_srcfiles(cuDie, &srcFiles, &srcCount, NULL))
    {
        for (int srcIndex = 0, sources = static_cast<int>(srcCount); srcIndex < sources; ++srcIndex)
        {
            if (0 == strcmp(pSourceFilePath, srcFiles[srcIndex]))
            {
                Dwarf_Line* pLineBuf;
                Dwarf_Signed lineCount = 0;

                if (DW_DLV_OK == dwarf_srclines(cuDie, &pLineBuf, &lineCount, NULL))
                {
                    for (int lineIndex = 0, lines = static_cast<int>(lineCount); lineIndex < lines; ++lineIndex)
                    {
                        // Check if this is end of text sequence
                        Dwarf_Bool lineEndSeq = 0;

                        if (DW_DLV_OK == dwarf_lineendsequence(pLineBuf[lineIndex], &lineEndSeq, NULL))
                        {
                            if (lineEndSeq)
                            {
                                continue;
                            }
                        }

                        // Skip lines NOT in pSourceFilePath
                        //
                        // Note that this can happen when we are looking at lines from other source files
                        // that are inlined into pSourceFilePath
                        Dwarf_Unsigned lineFileNo = 0;

                        if (DW_DLV_OK != dwarf_line_srcfileno(pLineBuf[lineIndex], &lineFileNo, NULL) ||
                            (lineFileNo - 1) != static_cast<Dwarf_Unsigned>(srcIndex))
                        {
                            continue;
                        }

                        Dwarf_Unsigned lineNo;
                        dwarf_lineno(pLineBuf[lineIndex], &lineNo, NULL);

                        Dwarf_Addr lineAddr;
                        dwarf_lineaddr(pLineBuf[lineIndex], &lineAddr, NULL);

                        gtRVAddr rva = static_cast<gtRVAddr>(lineAddr - m_pExe->GetImageBase());
                        srcLineInstanceMap[rva] = static_cast<unsigned>(lineNo);
                    }

                    dwarf_srclines_dealloc(m_dbg, pLineBuf, lineCount);
                }
            }
        }
    }

    return true;
}

bool DwarfSymbolEngine::EnumerateSourceLineInstances(const wchar_t* pSourceFilePath, SrcLineInstanceMap& srcLineInstanceMap, bool handleInline)
{
    GT_UNREFERENCED_PARAMETER(handleInline);
    bool ret = true;

    if (NULL != m_pAuxSymEngine)
    {
        ret = m_pAuxSymEngine->EnumerateSourceLineInstances(pSourceFilePath, srcLineInstanceMap);
    }

    if (ret)
    {
        char sourceFilePathMb[OS_MAX_PATH];

        if ((size_t)(-1) != wcstombs(sourceFilePathMb, pSourceFilePath, OS_MAX_PATH))
        {
            std::pair<const char*, SrcLineInstanceMap*> data(sourceFilePathMb, &srcLineInstanceMap);
            ForeachCompilationUnit(&DwarfSymbolEngine::TraverseSourceLines, &data);
        }
    }

    return ret;
}

bool DwarfSymbolEngine::TraverseSourceLineInfo(Dwarf_Die cuDie, void* pData)
{
    SourceLineInfo& sourceLine = *static_cast<SourceLineInfo*>(pData);

    Dwarf_Die die;
    int r = dwarf_child(cuDie, &die, NULL);
    bool ret = (DW_DLV_OK == r) ? true : false;

    if (DW_DLV_OK == r)
    {
        Dwarf_Addr addr = static_cast<Dwarf_Addr>(sourceLine.m_rva) + m_pExe->GetImageBase();

        // We are looking for symbol information that belong to a function (subprogram) which stays at level 1.
        // Therefore, we only need to iterate over the level 1 siblings.
        do
        {
            Dwarf_Half tag;

            if (dwarf_tag(die, &tag, NULL) != DW_DLV_OK)
            {
                ret = false;
                break;
            }

            if (DW_TAG_subprogram == tag)
            {
                Dwarf_Addr addrLow, addrHigh;

                if (dwarf_lowpc(die, &addrLow , NULL) == DW_DLV_OK && dwarf_highpc(die, &addrHigh , NULL) == DW_DLV_OK)
                {
                    if (addrLow > addrHigh)
                    {
                        addrHigh += addrLow;
                    }

                    if (addrLow <= addr && addr <= addrHigh)
                    {
                        Dwarf_Line* pLineBuf;
                        Dwarf_Signed lineCount = 0;

                        if (DW_DLV_OK == dwarf_srclines(cuDie, &pLineBuf, &lineCount, NULL))
                        {
                            sourceLine.m_offset = sourceLine.m_rva + 1;
                            char* pSrcFilePath = NULL;

                            for (int lineIndex = 0, lines = static_cast<int>(lineCount); lineIndex < lines; ++lineIndex)
                            {
                                // Check if this is end of text sequence
                                Dwarf_Bool lineEndSeq = 0;

                                if (DW_DLV_OK == dwarf_lineendsequence(pLineBuf[lineIndex], &lineEndSeq, NULL))
                                {
                                    if (lineEndSeq)
                                    {
                                        continue;
                                    }
                                }

                                Dwarf_Addr lineAddr;

                                if (DW_DLV_OK != dwarf_lineaddr(pLineBuf[lineIndex], &lineAddr, NULL))
                                {
                                    continue;
                                }

                                gtRVAddr offset = static_cast<gtRVAddr>(addr - lineAddr);

                                if (offset >= sourceLine.m_offset)
                                {
                                    continue;
                                }

                                char* pLineSrc = NULL;
                                dwarf_linesrc(pLineBuf[lineIndex], &pLineSrc, NULL);

                                if (NULL == pLineSrc)
                                {
                                    continue;
                                }

                                Dwarf_Unsigned lineNo;

                                if (DW_DLV_OK != dwarf_lineno(pLineBuf[lineIndex], &lineNo, NULL))
                                {
                                    continue;
                                }

                                sourceLine.m_offset = offset;
                                sourceLine.m_line = static_cast<unsigned>(lineNo);
                                pSrcFilePath = pLineSrc;

                                if (0 == offset)
                                {
                                    break;
                                }
                            }

                            dwarf_srclines_dealloc(m_dbg, pLineBuf, lineCount);

                            if (NULL != pSrcFilePath && (size_t)(-1) != mbstowcs(sourceLine.m_filePath, pSrcFilePath, OS_MAX_PATH))
                            {
                                sourceLine.m_rva -= sourceLine.m_offset;
                            }
                        }

                        ret = false;
                        break;
                    }
                }
            }

            Dwarf_Die siblingDie = NULL;
            r = dwarf_siblingof(m_dbg, die, &siblingDie, NULL);
            dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
            die = siblingDie;

            ret = DW_DLV_ERROR != r;
        }
        while (DW_DLV_OK == r);

        if (NULL != die)
        {
            dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
        }
    }

    return ret;
}

bool DwarfSymbolEngine::FindSourceLine(gtRVAddr rva, SourceLineInfo& sourceLine, bool handleInline)
{
    bool ret = false;

    if (NULL != m_pAuxSymEngine)
    {
        ret = m_pAuxSymEngine->FindSourceLine(rva, sourceLine, handleInline);
    }

    if (!ret)
    {
        const FunctionSymbolInfo* pFuncInfo = LookupFunction(rva, NULL, handleInline);

        if (NULL != pFuncInfo)
        {
            sourceLine.m_filePath[0] = L'\0';
            sourceLine.m_rva = rva;
            ForeachCompilationUnit(&DwarfSymbolEngine::TraverseSourceLineInfo, &sourceLine);
            sourceLine.m_rva = pFuncInfo->m_rva;

            if (L'\0' != sourceLine.m_filePath[0])
            {
                ret = true;
            }
        }
    }

    return ret;
}

gtByte* DwarfSymbolEngine::AllocateBuffer(unsigned size)
{
    gtByte** pNewBuffer = reinterpret_cast<gtByte**>(new gtByte[sizeof(gtByte**) + size]);
    *pNewBuffer = m_pBuffers ? *m_pBuffers : NULL;
    m_pBuffers = pNewBuffer;
    return reinterpret_cast<gtByte*>(pNewBuffer + 1);
}

void DwarfSymbolEngine::Clear(bool deinit)
{
    while (NULL != m_pBuffers)
    {
        gtByte* pAllocBuffer = reinterpret_cast<gtByte*>(m_pBuffers);
        m_pBuffers = reinterpret_cast<gtByte**>(*m_pBuffers);
        delete [] pAllocBuffer;
    }

    if (NULL != m_dbg)
    {
        if (deinit)
        {
            _dwarf_deinit(m_dbg);
        }

        if (IsElf())
        {
            _dwarf_elf_deinit(m_dbg);
        }
        else
        {
            delete m_dbg->dbg_iface;
        }

        free(m_dbg);
        m_dbg = NULL;
    }

    if (NULL != m_pFuncsInfoVec)
    {
        ClearFunctionsInfo();
    }

    if (NULL != m_pAuxSymEngine)
    {
        delete m_pAuxSymEngine;
    }

    if (true == m_processInlineSamples)
    {
        ClearInlinedFunctionInfo();
    }
}

void DwarfSymbolEngine::ClearInlinedFunctionInfo()
{
    if (!m_inlinedFuncsInfo.empty())
    {
        for (FunctionsMap::iterator it = m_inlinedFuncsInfo.begin();
             it != m_inlinedFuncsInfo.end(); ++it)
        {
            if (NULL != it->first.m_pName)
            {
                delete[] it->first.m_pName;
            }

            if (NULL != it->first.m_addrRanges)
            {
                delete it->first.m_addrRanges;
            }
        }

        m_inlinedFuncsInfo.clear();
    }

    if (m_processedInlineInfo.empty())
    {
        for (FunctionsMap::iterator it = m_processedInlineInfo.begin();
             it != m_processedInlineInfo.end(); ++it)
        {
            if (NULL != it->first.m_pName)
            {
                delete[] it->first.m_pName;
            }
        }

        m_processedInlineInfo.clear();
    }
}

bool DwarfSymbolEngine::IsElf() const
{
    return (this != m_dbg->dbg_iface->object);
}

const FunctionSymbolInfo* DwarfSymbolEngine::LookupFunction(gtRVAddr rva, gtRVAddr* pNextRva, bool handleInline) const
{
    const FunctionSymbolInfo* pFunc = DwarfSymbolEngine::LookupBoundingFunction(rva, pNextRva, handleInline);

    if (NULL != pFunc)
    {
        if (0 == pFunc->m_size)
        {
            if (m_pExe->LookupSectionIndex(pFunc->m_rva) != m_pExe->LookupSectionIndex(rva))
            {
                pFunc = NULL;
            }
        }
        else if (false == handleInline && (pFunc->m_rva + pFunc->m_size) <= rva)
        {
            pFunc = NULL;
        }
    }

    return pFunc;
}

const FunctionSymbolInfo* DwarfSymbolEngine::LookupInlinedFunction(gtRVAddr rva) const
{
    const FunctionSymbolInfo* pFunc = NULL;
    FunctionSymbolInfo funcInfo;
    funcInfo.m_pName = NULL;
    funcInfo.m_rva = rva;
    funcInfo.m_addrRanges = NULL;
    bool found = false;

    if (m_processInlineSamples)
    {
        // first, check if we have already processed this RVA for inline info
        FunctionsMap::iterator it = m_processedInlineInfo.upper_bound(funcInfo);

        if (m_processedInlineInfo.begin() != it)
        {
            --it;

            if (it->first.m_rva <= rva && rva < (it->first.m_rva + it->first.m_size))
            {
                // we have already processed this RVA
                found = true;
            }
        }

        // If we have not processed this RVA for inlined info, then process now
        if (!found)
        {
            // Search for inlined info for this RVA
            found = ProcessInlinedFunctionByRva(rva);
        }

        // if processed, then search RVA in the inlined functions map
        if (found)
        {
            FunctionsMap::iterator mit = m_inlinedFuncsInfo.upper_bound(funcInfo);

            while (m_inlinedFuncsInfo.begin() != mit)
            {
                --mit;

                if (mit->first.m_rva <= rva)
                {
                    bool matchFound = false;

                    if (NULL != mit->first.m_addrRanges)
                    {
                        // do a linear search in the addr range vector
                        for (auto& itr : * (mit->first.m_addrRanges))
                        {
                            if (itr.m_rvaStart <= rva && rva < itr.m_rvaEnd)
                            {
                                matchFound = true;
                                break;
                            }

                            // no further search needed
                            if (rva < itr.m_rvaStart)
                            {
                                break;
                            }
                        }
                    }

                    if (!matchFound)
                    {
                        if (rva < (mit->first.m_rva + mit->first.m_size))
                        {
                            matchFound = true;
                        }
                    }

                    if (matchFound)
                    {
                        if (mit->second)
                        {
                            pFunc = &mit->first;
                        }
                        else
                        {
                            pFunc = FindAggrInlineInstance(mit->first.m_pName);
                        }

                        break;
                    }
                }
                else
                {
                    // no more functions would match
                    break;
                }
            }
        }
    }

    return pFunc;
}

bool DwarfSymbolEngine::ProcessInlinedFunctionByRva(gtRVAddr rva) const
{
    bool ret = false;
    Dwarf_Addr addr = static_cast<Dwarf_Addr>(rva) + m_pExe->GetImageBase();
    Dwarf_Die cuDie = NULL;
    Dwarf_Addr cuAddrLow = 0;

    ACQUIRE_DWARF_LOCK(m_dwarfLock);
    InitCompilationUnit(m_dbg);

    // iterate over CUs till we find matching CU
    while (dwarf_next_cu_header(m_dbg, NULL, NULL, NULL, NULL, NULL, NULL) == DW_DLV_OK)
    {
        // get the first DIE of current CU
        if (dwarf_siblingof(m_dbg, NULL, &cuDie, NULL) != DW_DLV_OK)
        {
            break;
        }

        Dwarf_Half tag;

        if (dwarf_tag(cuDie, &tag, NULL) != DW_DLV_OK)
        {
            break;
        }

        if (DW_TAG_compile_unit == tag)
        {
            // get highpc and lowpc
            Dwarf_Addr addrLow = 0, addrHigh = 0;

            if (DieFindLowHighAddress(cuDie, tag, cuAddrLow, addrLow, addrHigh, NULL))
            {
                if (addrLow < addrHigh && addrLow <= addr && addr < addrHigh)
                {
                    ret = true;
                    break;
                }
            }
        }
    }

    // iterate over subprograms till we find matching subprogram
    if (ret)
    {
        Dwarf_Die die = NULL;

        if (dwarf_child(cuDie, &die, NULL) == DW_DLV_OK)
        {
            int r;

            do
            {
                Dwarf_Half tag;

                if (dwarf_tag(die, &tag, NULL) != DW_DLV_OK)
                {
                    ret = false;
                    break;
                }

                if (DW_TAG_subprogram == tag)
                {
                    Dwarf_Addr addrLow = 0, addrHigh = 0;

                    if (DieFindLowHighAddress(die, tag, cuAddrLow, addrLow, addrHigh, NULL))
                    {
                        if (addrLow < addrHigh && addrLow <= addr && addr < addrHigh)
                        {
                            // Process inlined information present in this subprogram
                            ret = ProcessInlinedFunctionInfo(die, cuAddrLow);

                            if (ret)
                            {
                                // Update map that we have processed current function for inline information
                                FunctionSymbolInfo funcInfo;
                                FUNCSYM_OFFSET_SUPPORT(funcInfo.m_offset = 0U;)
                                funcInfo.m_addrRanges = NULL;
                                funcInfo.m_rva = static_cast<gtRVAddr>(addrLow - m_pExe->GetImageBase());
                                funcInfo.m_size = static_cast<gtUInt32>(addrHigh - addrLow);
                                funcInfo.m_pName = NULL;    // no need to store function name
                                m_processedInlineInfo.insert(FunctionsMap::value_type(funcInfo, true));
                                break;
                            }
                        }
                    }
                }

                Dwarf_Die siblingDie = NULL;
                r = dwarf_siblingof(m_dbg, die, &siblingDie, NULL);
                dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
                die = siblingDie;
                ret = DW_DLV_ERROR != r;

            }
            while (DW_DLV_OK == r);
        }
    }

    if (NULL != cuDie)
    {
        dwarf_dealloc(m_dbg, cuDie, DW_DLA_DIE);
    }

    return ret;
}

static wchar_t* GetDemangledName(Dwarf_Debug dbg, Dwarf_Die die)
{
    wchar_t* pName = NULL;

    // Getting DW_AT_linkage_name attribute; originally called DW_AT_MIPS_linkage_name in pre-DWARF4.
    Dwarf_Attribute attr;

    if (dwarf_attr(die, DW_AT_linkage_name , &attr, NULL) == DW_DLV_OK ||
        dwarf_attr(die, DW_AT_MIPS_linkage_name , &attr, NULL) == DW_DLV_OK)
    {
        char* pMangledName;

        if ((dwarf_formstring(attr, &pMangledName, NULL) == DW_DLV_OK) && (NULL != pMangledName))
        {
            pName = SymbolEngine::DemangleNameIA(pMangledName);
            dwarf_dealloc(dbg, pMangledName, DW_DLA_STRING);
        }

        dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
    }

    char* pDieName;

    if (NULL == pName && dwarf_diename(die, &pDieName, NULL) == DW_DLV_OK)
    {
        pName = SymbolEngine::DemangleNameIA(pDieName);
        dwarf_dealloc(dbg, pDieName, DW_DLA_STRING);
    }

    return pName;
}

static wchar_t* ExtractSubprogramName(Dwarf_Debug dbg, Dwarf_Die die)
{
    wchar_t* pName = GetDemangledName(dbg, die);

    if (NULL == pName)
    {
        // In some case, the subprogram DIE does not have name,
        // but instead the DW_AT_abstract_origin, or DW_AT_specification attribute.

        Dwarf_Die offDie = DieFindAttribute(dbg, die, DW_AT_abstract_origin);

        if (NULL != offDie)
        {
            pName = GetDemangledName(dbg, offDie);

            if (NULL == pName)
            {
                Dwarf_Die spcDie = DieFindAttribute(dbg, offDie, DW_AT_specification);

                if (NULL != spcDie)
                {
                    pName = GetDemangledName(dbg, spcDie);
                    dwarf_dealloc(dbg, spcDie, DW_DLA_DIE);
                }
            }

            dwarf_dealloc(dbg, offDie, DW_DLA_DIE);
        }

        if (NULL == pName)
        {
            offDie = DieFindAttribute(dbg, die, DW_AT_specification);

            if (NULL != offDie)
            {
                pName = GetDemangledName(dbg, offDie);
                dwarf_dealloc(dbg, offDie, DW_DLA_DIE);
            }
        }
    }

    return pName;
}

static Dwarf_Die DieFindAttribute(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Half nattr)
{
    Dwarf_Die offDie = NULL;

    Dwarf_Attribute attr;

    if (dwarf_attr(die, nattr , &attr, NULL) == DW_DLV_OK)
    {
        // Get the global offset
        Dwarf_Off globalOff;

        if (dwarf_global_formref(attr, &globalOff, NULL) == DW_DLV_OK)
        {
            dwarf_offdie(dbg, globalOff, &offDie, NULL);
        }

        dwarf_dealloc(dbg, attr, DW_DLA_ATTR);
    }

    return offDie;
}

static void InitCompilationUnit(Dwarf_Debug dbg)
{
    dbg->dbg_cu_current = NULL;
}

static int DWARF_API Access_get_section_info(void* pObj, Dwarf_Half index, Dwarf_Obj_Access_Section* pSection, int* pError)
{
    DwarfSymbolEngine* pEngine = static_cast<DwarfSymbolEngine*>(pObj);
    assert(NULL != pEngine);

    const ExecutableFile* pExe = pEngine->GetExecutable();
    assert(NULL != pExe);

    int ret;

    if (NULL != pSection)
    {
        unsigned sectionIndex = static_cast<unsigned>(index);

        unsigned nameLength;
        const char* pName = pExe->GetSectionName(sectionIndex, &nameLength);

        if (NULL != pName)
        {
            if ('\0' != pName[nameLength] || (8 == nameLength && 0 == memcmp(pName, ".eh_frame", 8)))
            {
                const unsigned isEhFrame = static_cast<unsigned>(0 == memcmp(pName, ".eh_frame", 8));

                char* pZtName = pEngine->AllocateBuffer(nameLength + isEhFrame + 1U);

                memcpy(pZtName, pName, nameLength);
                pZtName[nameLength] = 'e';
                pZtName[nameLength + isEhFrame] = '\0';
                pName = pZtName;
            }

            gtRVAddr startRva, endRva;
            pExe->GetSectionRvaLimits(sectionIndex, startRva, endRva);
            pSection->addr = static_cast<Dwarf_Addr>(pExe->RvaToVa(startRva));
            pSection->size = static_cast<Dwarf_Unsigned>(pExe->GetSectionSize(sectionIndex));
            pSection->name = pName;

            ret = DW_DLV_OK;
        }
        else
        {
            if (NULL != pError)
            {
                *pError = DW_DLE_NO_ENTRY;
            }

            ret = DW_DLV_NO_ENTRY;
        }
    }
    else
    {
        if (NULL != pError)
        {
            *pError = DW_DLE_ARGUMENT;
        }

        ret = DW_DLV_ERROR;
    }

    return ret;
}

static Dwarf_Endianness DWARF_API Access_get_byte_order(void* pObj)
{
    (void)pObj; // Unused
    return DW_OBJECT_LSB;
}

static Dwarf_Small DWARF_API Access_get_length_size(void* pObj)
{
    (void)pObj; // Unused
    return 4U;
}

static Dwarf_Small DWARF_API Access_get_pointer_size(void* pObj)
{
    DwarfSymbolEngine* pEngine = static_cast<DwarfSymbolEngine*>(pObj);
    assert(NULL != pEngine);

    const ExecutableFile* pExe = pEngine->GetExecutable();
    assert(NULL != pExe);

    return 4U << static_cast<unsigned>(pExe->Is64Bit());
}

static Dwarf_Unsigned DWARF_API Access_get_section_count(void* pObj)
{
    DwarfSymbolEngine* pEngine = static_cast<DwarfSymbolEngine*>(pObj);
    assert(NULL != pEngine);

    const ExecutableFile* pExe = pEngine->GetExecutable();
    assert(NULL != pExe);

    return static_cast<Dwarf_Unsigned>(pExe->GetSectionsCount());
}

static int DWARF_API Access_load_section(void* pObj, Dwarf_Half index, Dwarf_Small** ppData, int* pError)
{
    DwarfSymbolEngine* pEngine = static_cast<DwarfSymbolEngine*>(pObj);
    assert(NULL != pEngine);

    const ExecutableFile* pExe = pEngine->GetExecutable();
    assert(NULL != pExe);

    int ret;

    if (NULL != ppData)
    {
        const gtUByte* pBytes = pExe->GetSectionBytes(static_cast<unsigned>(index));

        if (NULL != pBytes)
        {
            *ppData = const_cast<gtUByte*>(pBytes);
            ret = DW_DLV_OK;
        }
        else
        {
            if (NULL != pError)
            {
                *pError = DW_DLE_NO_ENTRY;
            }

            ret = DW_DLV_NO_ENTRY;
        }
    }
    else
    {
        if (NULL != pError)
        {
            *pError = DW_DLE_ARGUMENT;
        }

        ret = DW_DLV_ERROR;
    }

    return ret;
}

bool DwarfSymbolEngine::DieFindLowHighAddress(Dwarf_Die die, Dwarf_Half tag, Dwarf_Addr& cuAddrLow, Dwarf_Addr& addrLow, Dwarf_Addr& addrHigh, gtVector<FuncAddressRange>* addrRanges) const
{
    bool ret = false;
    Dwarf_Attribute attrRange;

    // if lowpc, highpc attribute present
    if (dwarf_lowpc(die, &addrLow, NULL) == DW_DLV_OK &&
        dwarf_highpc(die, &addrHigh, NULL) == DW_DLV_OK)
    {
        if (addrLow > addrHigh)
        {
            addrHigh += addrLow;
        }

        if (DW_TAG_compile_unit == tag)
        {
            cuAddrLow = addrLow;
        }

        ret = true;
    }
    // else if ranges attribute present
    else if (dwarf_attr(die, DW_AT_ranges, &attrRange, NULL) == DW_DLV_OK)
    {
        Dwarf_Off offset = 0;
        Dwarf_Unsigned offsetData = 0;
        Dwarf_Ranges* pRanges = NULL;
        Dwarf_Signed count = 0;

        // Before DWARF4, DW_FORM_data{4,8} was used for rangelistptr,
        // which can be fetched by dwarf_formudata()
        // Since DWARF4, DW_FORM_sec_offset is used for rangelistptr,
        // which can be fetched by dwarf_global_formref()
        // Try first with global_formref(), if fails then try with formudata()
        if ((dwarf_global_formref(attrRange, &offset, NULL) == DW_DLV_OK &&
             dwarf_get_ranges_a(m_dbg, offset, die, &pRanges, &count, NULL, NULL) == DW_DLV_OK) ||
            (dwarf_formudata(attrRange, &offsetData, NULL) == DW_DLV_OK &&
             dwarf_get_ranges_a(m_dbg, static_cast<Dwarf_Off>(offsetData), die, &pRanges, &count, NULL, NULL) == DW_DLV_OK))
        {
            if (DW_TAG_compile_unit == tag)
            {
                // for compile_unit DIE, read lowpc to get the base address
                if (dwarf_lowpc(die, &cuAddrLow, NULL) != DW_DLV_OK)
                {
                    // if failed, set image base as base address
                    cuAddrLow = m_pExe->GetImageBase();
                }
            }

            Dwarf_Addr offsetLow  = 0xFFFFFFFFFFFFFFFFULL;
            Dwarf_Addr offsetHigh = 0ULL;

            // compare the saved entry with the rest of the entris to find low/high offsets
            int i = 0;

            while (i < count)
            {
                if (DW_RANGES_ENTRY == pRanges[i].dwr_type)
                {
                    Dwarf_Addr newLow  = pRanges[i].dwr_addr1;
                    Dwarf_Addr newHigh = pRanges[i].dwr_addr2;
                    offsetLow  = (offsetLow > newLow) ? newLow : offsetLow;
                    offsetHigh = (offsetHigh < newHigh) ? newHigh : offsetHigh;

                    if (NULL != addrRanges)
                    {
                        gtRVAddr rva1 = static_cast<gtRVAddr>(newLow + cuAddrLow - m_pExe->GetImageBase());
                        gtRVAddr rva2 = static_cast<gtRVAddr>(newHigh + cuAddrLow - m_pExe->GetImageBase());
                        FuncAddressRange ar(rva1, rva2);
                        addrRanges->push_back(ar);
                    }
                }

                i++;
            }

            addrLow = offsetLow + cuAddrLow;
            addrHigh = offsetHigh + cuAddrLow;

            dwarf_ranges_dealloc(m_dbg, pRanges, count);
            ret = true;
        }

        dwarf_dealloc(m_dbg, attrRange, DW_DLA_ATTR);
    }

    return ret;
}

void DwarfSymbolEngine::UpdateInlinedFunctionName(FunctionSymbolInfo& funcInfo) const
{
    if (true == m_processInlineSamples)
    {
        gtString inlinedName = L"[inlined] ";
        inlinedName += funcInfo.m_pName;
        delete[] funcInfo.m_pName;
        size_t len = wcslen(inlinedName.asCharArray());
        funcInfo.m_pName = new wchar_t[len + 1];
        wcscpy(funcInfo.m_pName, inlinedName.asCharArray());
        funcInfo.m_pName[len] = L'\0';
    }
}

gtRVAddr DwarfSymbolEngine::TranslateToInlineeRVA(gtRVAddr rva) const
{
    FunctionSymbolInfo funcInfo;
    funcInfo.m_pName = NULL;
    funcInfo.m_rva = rva;

    const FunctionSymbolInfo* pFunc = NULL;
    const FunctionSymbolInfo* pMatchFunc = NULL;

    FunctionsMap::iterator mit = m_inlinedFuncsInfo.upper_bound(funcInfo);

    while (m_inlinedFuncsInfo.begin() != mit)
    {
        --mit;

        if (mit->first.m_rva <= rva)
        {
            bool matchFound = false;

            if (NULL != mit->first.m_addrRanges)
            {
                // do a linear search in the addr range vector
                for (auto& it : * (mit->first.m_addrRanges))
                {
                    // matching range found
                    if (it.m_rvaStart <= rva && rva < it.m_rvaEnd)
                    {
                        matchFound = true;
                        break; // out of for loop
                    }

                    // no further search needed
                    if (rva < it.m_rvaStart)
                    {
                        break; // out of for loop
                    }
                }
            }

            if (!matchFound)
            {
                if (rva < (mit->first.m_rva + mit->first.m_size))
                {
                    matchFound = true;
                }
            }

            if (matchFound)
            {
                pMatchFunc = &mit->first;

                if (mit->second)
                {
                    pFunc = pMatchFunc;
                }
                else
                {
                    pFunc = FindAggrInlineInstance(mit->first.m_pName);
                }

                break; // out of while loop
            }
        }
        else
        {
            // no more functions would match
            break;
        }
    }

    gtRVAddr funcRva = rva;

    if (NULL != pFunc && pFunc != pMatchFunc)
    {
        funcRva = pFunc->m_rva;
        gtRVAddr offset = 0;

        if (NULL != pMatchFunc->m_addrRanges)
        {
            // calculate offset from the ranges
            for (auto& it : * (pMatchFunc->m_addrRanges))
            {
                if (rva < it.m_rvaStart)
                {
                    break;
                }

                if (rva < it.m_rvaEnd)
                {
                    offset += rva - it.m_rvaStart;
                }
                else
                {
                    offset += it.m_rvaEnd - it.m_rvaStart;
                }
            }
        }
        else
        {
            offset = rva - pMatchFunc->m_rva;
        }

        if (NULL != pFunc->m_addrRanges)
        {
            for (auto& it : * (pFunc->m_addrRanges))
            {
                if (offset >= (it.m_rvaEnd - it.m_rvaStart))
                {
                    offset -= (it.m_rvaEnd - it.m_rvaStart);
                }
                else
                {
                    funcRva = it.m_rvaStart + offset;
                    break;
                }
            }
        }
        else
        {
            funcRva += offset;
        }
    }

    return funcRva;
}

//TODO: Optimize the linear search.
const FunctionSymbolInfo* DwarfSymbolEngine::FindAggrInlineInstance(const wchar_t* name) const
{
    const FunctionSymbolInfo* pFunc = NULL;
    FunctionsMap::iterator firstIt = m_inlinedFuncsInfo.end();

    for (FunctionsMap::iterator it = m_inlinedFuncsInfo.begin();
         it != m_inlinedFuncsInfo.end(); ++it)
    {
        if (0 == wcscmp(name, it->first.m_pName))
        {
            if (firstIt == m_inlinedFuncsInfo.end())
            {
                firstIt = it;
            }

            if (true == it->second)
            {
                pFunc = &it->first;
                break;
            }
        }
    }

    // if the instance is choosen first time, then mark the instance
    if (NULL == pFunc && m_inlinedFuncsInfo.end() != firstIt)
    {
        firstIt->second = true;
        pFunc = &firstIt->first;
    }

    return pFunc;
}

// This function is called only when rva is an inlined rva.
gtVector<gtRVAddr> DwarfSymbolEngine::FindNestedInlineFunctions(gtRVAddr rva) const
{
    gtVector<gtRVAddr> list;
    auto it = m_nestedFuncMap.find(rva);

    // LookupInlinedFunction() can be replaced with a smipler new function IsRvaInlined()
    if (m_nestedFuncMap.end() == it && LookupInlinedFunction(rva) != NULL)
    {
        // rva not addded to map. Add it now
        ProcessNestedInlinedFunctionInfo(rva);

        // search the map again after processing
        it = m_nestedFuncMap.find(rva);
    }

    if (m_nestedFuncMap.end() != it)
    {
        // copy the pre-processed list
        list = it->second;
    }
    else
    {
        // failed to find any list. just return the same rva back.
        list.push_back(rva);
    }

    return list;
}

// This function is called only when rva is not added to map.
bool DwarfSymbolEngine::ProcessNestedInlinedFunctionInfo(gtRVAddr rva) const
{
    bool ret = false;
    gtVector<gtRVAddr> list;
    Dwarf_Addr addr = static_cast<Dwarf_Addr>(rva) + m_pExe->GetImageBase();
    Dwarf_Die cuDie = NULL;
    Dwarf_Addr cuAddrLow = 0;

    ACQUIRE_DWARF_LOCK(m_dwarfLock);
    InitCompilationUnit(m_dbg);

    // iterate over CUs till we find matching CU
    while (dwarf_next_cu_header(m_dbg, NULL, NULL, NULL, NULL, NULL, NULL) == DW_DLV_OK)
    {
        // get the first DIE of current CU
        if (dwarf_siblingof(m_dbg, NULL, &cuDie, NULL) != DW_DLV_OK)
        {
            continue;
        }

        Dwarf_Half tag;

        if (dwarf_tag(cuDie, &tag, NULL) != DW_DLV_OK)
        {
            break;
        }

        if (DW_TAG_compile_unit == tag)
        {
            // get highpc and lowpc
            Dwarf_Addr addrLow = 0, addrHigh = 0;

            if (DieFindLowHighAddress(cuDie, tag, cuAddrLow, addrLow, addrHigh, NULL))
            {
                if (addrLow <= addr && addr < addrHigh)
                {
                    ret = true;
                    break;
                }
            }
        }
    }

    bool possibleLeafFuncFound = false;

    // Iterate over subprograms, inlined_subroutines till we find matching inlined_subroutine
    // Traverse the DIE tree from top subprogram till leaf/last inlined function
    // Add the last non-inlined caller function and rest inlined callee functions into the vector
    if (ret)
    {
        Dwarf_Die die = NULL;

        if (dwarf_child(cuDie, &die, NULL) == DW_DLV_OK)
        {
            int r;

            do
            {
                bool visitChild = false;
                Dwarf_Half tag;

                if (dwarf_tag(die, &tag, NULL) != DW_DLV_OK)
                {
                    break;
                }

                if (DW_TAG_subprogram == tag || DW_TAG_lexical_block == tag || DW_TAG_inlined_subroutine == tag)
                {
                    Dwarf_Addr addrLow = 0, addrHigh = 0;

                    if (DieFindLowHighAddress(die, tag, cuAddrLow, addrLow, addrHigh, NULL))
                    {
                        // Need to add check in addr-ranges here for RVA matching later
                        if (addrLow <= addr && addr < addrHigh)
                        {
                            if (DW_TAG_subprogram == tag)
                            {
                                // reached a non-inlined caller function
                                // clear if anything already added to list
                                list.clear();
                                gtRVAddr rva1 = static_cast<gtRVAddr>(addrLow - m_pExe->GetImageBase());
                                list.push_back(rva1);
                            }
                            else if (DW_TAG_inlined_subroutine == tag)
                            {
                                // reached a inlined callee function instance
                                gtRVAddr rva1 = static_cast<gtRVAddr>(addrLow - m_pExe->GetImageBase());
                                rva1 = TranslateToInlineeRVA(rva1);
                                list.push_back(rva1);
                                possibleLeafFuncFound = true;
                            }

                            visitChild = true;
                        }
                    }
                }

                Dwarf_Die nextDie = NULL;

                if (visitChild)
                {
                    r = dwarf_child(die, &nextDie, NULL);
                }
                else
                {
                    r = dwarf_siblingof(m_dbg, die, &nextDie, NULL);
                }

                dwarf_dealloc(m_dbg, die, DW_DLA_DIE);
                die = nextDie;
            }
            while (DW_DLV_OK == r);
        }
    }

    if (NULL != cuDie)
    {
        dwarf_dealloc(m_dbg, cuDie, DW_DLA_DIE);
    }

    if (possibleLeafFuncFound)
    {
        m_nestedFuncMap[rva] = list;
    }

    return true;
}


text:
//-----------------------------------------------------------------------------
// File:  OssimInfo.java
//
// License:  See top level LICENSE.txt file.
//
// Author:  David Burken
//
// Description: Java ossim-info app:
//
// Example usage:
//
// java -Djava.library.path=/work/osgeo/oms/joms -cp /work/osgeo/oms/lib/joms-$OSSIM_VERSION.jar org.ossim.oms.apps.OssimInfo /data1/test/data/public/tif/Clinton_IA.tif
//
//-----------------------------------------------------------------------------
// $Id$

package org.ossim.oms.apps;

import joms.oms.Info;
import joms.oms.Init;

public class OssimInfo
{
   static
   {
      System.loadLibrary( "joms" );
   }

   /**
    * @param args
    */
   public static void main( String[] args )
   {
      // Copy the args with app name for c++ initialize.
      String[] newArgs = new String[args.length + 1];
      newArgs[0] = "joms.oms.apps.OssimInfo";
      System.arraycopy(args, 0, newArgs, 1, args.length);

      // Initialize ossim stuff:
      int argc = Init.instance().initialize(newArgs.length, newArgs);

      // Note: need to test Init::initialize stripping args.
      if ( argc >= 1 )
      {
         joms.oms.Info info = new joms.oms.Info();

         //---
         // Info::initialize returns true to  indicate the process should continue with execute.
         //---
         if ( info.initialize( newArgs.length, newArgs) )
         {
            try
            {
               info.execute();
            }
            catch( Exception e )
            {
               System.err.println("Caught Exception: " + e.getMessage());
            }
         }
      }
   }
}

redpajama_set_name: RedPajamaGithub


text:
#pragma once
#include <aws/migrationhubstrategy/MigrationHubStrategyRecommendations_EXPORTS.h>
#include <aws/migrationhubstrategy/model/DatabaseManagementPreference.h>
#include <aws/migrationhubstrategy/model/DatabaseMigrationPreference.h>
#include <utility>

namespace Aws
{
namespace Utils
{
namespace Json
{
  class JsonValue;
  class JsonView;
} // namespace Json
} // namespace Utils
namespace MigrationHubStrategyRecommendations
{
namespace Model
{

  /**
   *
 Preferences on managing your databases on AWS.

See Also:

   * AWS
   * API Reference

   */
  class AWS_MIGRATIONHUBSTRATEGYRECOMMENDATIONS_API DatabasePreferences
  {
  public:
    DatabasePreferences();
    DatabasePreferences(Aws::Utils::Json::JsonView jsonValue);
    DatabasePreferences& operator=(Aws::Utils::Json::JsonView jsonValue);
    Aws::Utils::Json::JsonValue Jsonize() const;

    /**
     *
 Specifies whether you're interested in self-managed databases or databases
     * managed by AWS.

     */
    inline const DatabaseManagementPreference& GetDatabaseManagementPreference() const{ return m_databaseManagementPreference; }

    /**
     *
 Specifies whether you're interested in self-managed databases or databases
     * managed by AWS.

     */
    inline bool DatabaseManagementPreferenceHasBeenSet() const { return m_databaseManagementPreferenceHasBeenSet; }

    /**
     *
 Specifies whether you're interested in self-managed databases or databases
     * managed by AWS.

     */
    inline void SetDatabaseManagementPreference(const DatabaseManagementPreference& value) { m_databaseManagementPreferenceHasBeenSet = true; m_databaseManagementPreference = value; }

    /**
     *
 Specifies whether you're interested in self-managed databases or databases
     * managed by AWS.

     */
    inline void SetDatabaseManagementPreference(DatabaseManagementPreference&& value) { m_databaseManagementPreferenceHasBeenSet = true; m_databaseManagementPreference = std::move(value); }

    /**
     *
 Specifies whether you're interested in self-managed databases or databases
     * managed by AWS.

     */
    inline DatabasePreferences& WithDatabaseManagementPreference(const DatabaseManagementPreference& value) { SetDatabaseManagementPreference(value); return *this;}

    /**
     *
 Specifies whether you're interested in self-managed databases or databases
     * managed by AWS.

     */
    inline DatabasePreferences& WithDatabaseManagementPreference(DatabaseManagementPreference&& value) { SetDatabaseManagementPreference(std::move(value)); return *this;}

    /**
     *
 Specifies your preferred migration path.

     */
    inline const DatabaseMigrationPreference& GetDatabaseMigrationPreference() const{ return m_databaseMigrationPreference; }

    /**
     *
 Specifies your preferred migration path.

     */
    inline bool DatabaseMigrationPreferenceHasBeenSet() const { return m_databaseMigrationPreferenceHasBeenSet; }

    /**
     *
 Specifies your preferred migration path.

     */
    inline void SetDatabaseMigrationPreference(const DatabaseMigrationPreference& value) { m_databaseMigrationPreferenceHasBeenSet = true; m_databaseMigrationPreference = value; }

    /**
     *
 Specifies your preferred migration path.

     */
    inline void SetDatabaseMigrationPreference(DatabaseMigrationPreference&& value) { m_databaseMigrationPreferenceHasBeenSet = true; m_databaseMigrationPreference = std::move(value); }

    /**
     *
 Specifies your preferred migration path.

     */
    inline DatabasePreferences& WithDatabaseMigrationPreference(const DatabaseMigrationPreference& value) { SetDatabaseMigrationPreference(value); return *this;}

    /**
     *
 Specifies your preferred migration path.

     */
    inline DatabasePreferences& WithDatabaseMigrationPreference(DatabaseMigrationPreference&& value) { SetDatabaseMigrationPreference(std::move(value)); return *this;}

  private:

    DatabaseManagementPreference m_databaseManagementPreference;
    bool m_databaseManagementPreferenceHasBeenSet;

    DatabaseMigrationPreference m_databaseMigrationPreference;
    bool m_databaseMigrationPreferenceHasBeenSet;
  };

} // namespace Model
} // namespace MigrationHubStrategyRecommendations
} // namespace Aws


text:
/*
 *   element  对象
 *   eType   click……
 *   handle  处理函数
 *   bol   是否冒泡  格式true,false
 * */

// 事件绑定
function addEvent(element, eType, handle, bol) {
    if (element.addEventListener) {
        element.addEventListener(eType, handle, bol);
    } else if (element.attachEvent) {
        element.attachEvent('on' + eType, handle);
    } else {
        element['on' + eType] = handle;
    }
}
// 事件解绑
function removeEvent(element, eType, handle, bol) {
    if (element.addEventListener) {
        element.removeEventListener(eType, handle, bol);
    } else if (element.attachEvent) {
        element.detachEvent("on" + eType, handle);
    } else {
        element["on" + eType] = null;
    }
}
//事件代理
//function on(ele,eType,handle,bol){
//    addEvent(ele,eType,function(e){
//        var e = e||window.event;   //IE8及IE8以下只支持window.event,不支持参数传人
//        var target = e.target||e.srcElement;    //IE没有e.target,有e.srcElement
//        if(target.tagName.toLowerCase()=="td"){
//            changeStyle(target);
//        }
//    },bol);
//}

function onttt(ele, inner, eType, handle) {
    console.log('xxxxyyyx');
    addEvent(ele, eType, function (e) {
        var e = e || window.event;   //IE8及IE8以下只支持window.event,不支持参数传人
        var target = e.target || e.srcElement;    //IE没有e.target,有e.srcElement
        //if (target)
        console.log(inner);
        console.log(target);
        //if(target.tagName.toLowerCase()=="td"){
        //    changeStyle(tar   get);
        //}
    }, true);
}

var o = $('#out'),
    inx = o.find('td');
onttt($('#out'), inx, 'click');

addEvent($('#out'), 'click', function(){
    console.log('test');
}, true);

console.log('xx');


text:
package org.marketcetera.photon.ui;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.marketcetera.photon.Messages;
import org.marketcetera.util.misc.ClassVersion;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.gui.AbstractTableComparatorChooser;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swt.EventTableViewer;

/**
 * Copy of {@link ca.odell.glazedlists.swt.TableComparatorChooser} that does not require a {@link EventTableViewer}.
 *
 * Upgrade note: {@link Messages#TABLE_COMPARATOR_CHOOSER_INVALID_LISTENER} was used to externalize a string.
 *
 * @see ca.odell.glazedlists.swt.TableComparatorChooser
 *
 * @author Will Horn
 * @version $Id: TableComparatorChooser.java 16841 2014-02-20 19:59:04Z colin $
 * @since 1.5.0
 */
@SuppressWarnings("deprecation")
@ClassVersion("$Id: TableComparatorChooser.java 16841 2014-02-20 19:59:04Z colin $")
public final class TableComparatorChooser<E> extends AbstractTableComparatorChooser<E> {

    private final Object sortingStrategy;

    /** the table being sorted */
    private Table table;

    /** listeners to sort change events */
    private List<Listener> sortListeners = new ArrayList<Listener>();

    /** listeners for column headers */
    private ColumnListener columnListener = new ColumnListener();

    /**
     * Creates and installs a TableComparatorChooser.
     */
    private TableComparatorChooser(Table table, TableFormat<E> format, SortedList<E> sortedList, boolean multipleColumnSort) {
        super(sortedList, format);

        // save the SWT-specific state
        this.table = table;

        // listen for events on the specified table
        for(int c = 0; c < table.getColumnCount(); c++) {
            table.getColumn(c).addSelectionListener(columnListener);
        }

        // sort using the specified approach
        sortingStrategy = SINGLE_COLUMN;
    }

    /**
     * Installs a new TableComparatorChooser that responds to clicks
     * on the specified table and uses them to sort the specified list.
     *
     * @param table the table to be sorted
     * @param format the table format to be used
     * @param sortedList the sorted list to update.
     * @param multipleColumnSort true to sort by multiple columns
     *      at a time, or false to sort by a single column. Although
     *      sorting by multiple columns is more powerful, the user interface is
     *      not as simple and this strategy should only be used where necessary.
     */
    public static <E> TableComparatorChooser<E> install(Table table, TableFormat<E> format, SortedList<E> sortedList, boolean multipleColumnSort) {
        return new TableComparatorChooser<E>(table, format, sortedList,  multipleColumnSort);
    }

    /**
     * Registers the specified {@link Listener} to receive notification whenever
     * the {@link Table} is sorted by this {@link TableComparatorChooser}.
     */
    public void addSortListener(final Listener sortListener) {
        sortListeners.add(sortListener);
    }
    /**
     * Deregisters the specified {@link Listener} to no longer receive events.
     */
    public void removeSortActionListener(final Listener sortListener) {
        for(Iterator<Listener> i = sortListeners.iterator(); i.hasNext(); ) {
            if(sortListener == i.next()) {
                i.remove();
                return;
            }
        }
        throw new IllegalArgumentException(Messages.TABLE_COMPARATOR_CHOOSER_INVALID_LISTENER.getText(sortListener));
    }

    /**
     * Handles column clicks.
     */
    class ColumnListener implements org.eclipse.swt.events.SelectionListener {
        public void widgetSelected(SelectionEvent e) {
            TableColumn column = (TableColumn)e.widget;
            Table table = column.getParent();
            int columnIndex = table.indexOf(column);
            // Using reflection to access internal code
            try {
				sortingStrategy.getClass().getMethods()[0].invoke(sortingStrategy, sortingState, columnIndex, 1, false, false);
			} catch (Exception ex) {
				throw new RuntimeException(ex);
			}
        }
        public void widgetDefaultSelected(SelectionEvent e) {
            // Do Nothing
        }
    }

    /**
     * Updates the SWT table to indicate sorting icon on the primary sort column.
     */
    protected final void updateTableSortColumn() {
        final List<Integer> sortedColumns = getSortingColumns();
        if (sortedColumns.isEmpty()) {
            // no columns sorted
            table.setSortColumn(null);
            table.setSortDirection(SWT.NONE);
        } else {
            // make GL primary sort column the SWT table sort column
            final int primaryColumnIndex = sortedColumns.get(0).intValue();
            final int sortDirection = isColumnReverse(primaryColumnIndex) ? SWT.DOWN : SWT.UP;
            table.setSortColumn(table.getColumn(primaryColumnIndex));
            table.setSortDirection(sortDirection);
        }
    }

    /**
     * Updates the comparator in use and applies it to the table.
     *
     *
This method is called when the sorting state changed.

     */
    protected final void rebuildComparator() {
        super.rebuildComparator();
        // update sorting icon in SWT table
        updateTableSortColumn();
        // notify interested listeners that the sorting has changed
        Event sortEvent = new Event();
        sortEvent.widget = table;
        for(Iterator<Listener> i = sortListeners.iterator(); i.hasNext(); ) {
            i.next().handleEvent(sortEvent);
        }
    }

    /**
     * Releases the resources consumed by this {@link TableComparatorChooser} so that it
     * may eventually be garbage collected.
     *
     *
A {@link TableComparatorChooser} will be garbage collected without a call to
     * {@link #dispose()}, but not before its source {@link EventList} is garbage
     * collected. By calling {@link #dispose()}, you allow the {@link TableComparatorChooser}
     * to be garbage collected before its source {@link EventList}. This is
     * necessary for situations where an {@link TableComparatorChooser} is short-lived but
     * its source {@link EventList} is long-lived.
     *
     *
Warning: It is an error
     * to call any method on a {@link TableComparatorChooser} after it has been disposed.
     */
    public void dispose() {
        // stop listening for events on the specified table
        for(int c = 0; c < table.getColumnCount(); c++) {
            table.getColumn(c).removeSelectionListener(columnListener);
        }
    }
}


text:
/**
 *
 * The classes in this package represent SpringLayout's domain model.
 *
 */

package me.yv84.springlayout.model;


text:
package eu.dnetlib.iis.wf.report.pushgateway.process;

import eu.dnetlib.iis.wf.report.pushgateway.converter.LabelConf;
import eu.dnetlib.iis.wf.report.pushgateway.converter.LabeledMetricConf;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;

@ExtendWith(MockitoExtension.class)
public class PushMetricsProcessLabeledMetricConfByPatternProducerTest {

    @Test
    public void shouldProduceEmptyOnError() {
        // given
        PushMetricsProcess.LabeledMetricConfByPatternProducer labeledMetricConfByPatternProducer = new PushMetricsProcess.LabeledMetricConfByPatternProducer();

        // when
        Optional<Map<String, LabeledMetricConf>> result = labeledMetricConfByPatternProducer.create(() -> null);

        // then
        assertFalse(result.isPresent());
    }

    @Test
    public void shouldProduceEmptyOnEmptyMap() {
        // given
        PushMetricsProcess.LabeledMetricConfByPatternProducer labeledMetricConfByPatternProducer = new PushMetricsProcess.LabeledMetricConfByPatternProducer();

        // when
        Optional<Map<String, LabeledMetricConf>> result = labeledMetricConfByPatternProducer.create(Collections::emptyMap);

        // then
        assertFalse(result.isPresent());
    }

    @Test
    public void shouldProduceEmptyOnMapOfEmptyKey() {
        // given
        PushMetricsProcess.LabeledMetricConfByPatternProducer labeledMetricConfByPatternProducer = new PushMetricsProcess.LabeledMetricConfByPatternProducer();

        // when
        Optional<Map<String, LabeledMetricConf>> result = labeledMetricConfByPatternProducer.create(() -> Collections.singletonMap("", mock(LabeledMetricConf.class)));

        // then
        assertFalse(result.isPresent());
    }

    @Test
    public void shouldProduceEmptyOnMapOfNullValue() {
        // given
        PushMetricsProcess.LabeledMetricConfByPatternProducer labeledMetricConfByPatternProducer = new PushMetricsProcess.LabeledMetricConfByPatternProducer();

        // when
        Optional<Map<String, LabeledMetricConf>> result = labeledMetricConfByPatternProducer.create(() -> Collections.singletonMap("pattern", null));

        // then
        assertFalse(result.isPresent());
    }

    @Test
    public void shouldProduceNonEmpty() {
        // given
        PushMetricsProcess.LabeledMetricConfByPatternProducer labeledMetricConfByPatternProducer = new PushMetricsProcess.LabeledMetricConfByPatternProducer();
        String labeledMetricsPropertiesPath = "eu/dnetlib/iis/wf/report/pushgateway/process/test/oozie_app/labeled_metrics.properties";

        // when
        Optional<Map<String, LabeledMetricConf>> result = labeledMetricConfByPatternProducer
                .create(Collections.singletonMap("labeledMetricsPropertiesFile", labeledMetricsPropertiesPath));

        // then
        assertTrue(result.isPresent());
        assertEquals(Stream.of(
                new AbstractMap.SimpleImmutableEntry<>("a0\\.b0\\.c0\\.d0\\.\\S+",
                        new LabeledMetricConf("a0_b0_c0_d0", Collections.singletonList(new LabelConf("label_name_1", "$4")))),
                new AbstractMap.SimpleImmutableEntry<>("a1\\.b1\\.c1\\.\\S+\\.\\S+",
                        new LabeledMetricConf("a1_b1_c1", Arrays.asList(
                                new LabelConf("label_name_1", "$3"), new LabelConf("label_name_2", "$4")))),
                new AbstractMap.SimpleImmutableEntry<>("a2\\.b2\\.\\S+\\.\\S+\\.\\S+",
                        new LabeledMetricConf("a2_b2", Arrays.asList(
                                new LabelConf("label_name_1", "$2"), new LabelConf("label_name_2", "$3_$4")))),
                new AbstractMap.SimpleImmutableEntry<>("a3\\.b3\\.\\S+\\.\\S+\\.\\S+",
                        new LabeledMetricConf("a3_b3", Arrays.asList(
                                new LabelConf("label_name_1", "$2"), new LabelConf("label_name_2", "$4")))),
                new AbstractMap.SimpleImmutableEntry<>("a4\\.b4\\.c4\\.\\S+\\.\\S+",
                        new LabeledMetricConf("a4_b4_c4", Collections.singletonList(new LabelConf("label_name_1", "$4")))),
                new AbstractMap.SimpleImmutableEntry<>("a5\\.b5\\.c5\\.a\\.\\S+",
                        new LabeledMetricConf("a5_b5_c5", Collections.singletonList(new LabelConf("label_name_1", "$4")))),
                new AbstractMap.SimpleImmutableEntry<>("a5\\.b5\\.c5\\.b\\.\\S+",
                        new LabeledMetricConf("a5_b5_c5", Collections.singletonList(new LabelConf("label_name_1", "$4"))))
                ).collect(Collectors.toMap(AbstractMap.SimpleImmutableEntry::getKey, AbstractMap.SimpleImmutableEntry::getValue)),
                result.get());
    }

}


text:
import Enum from '../../lib/Enum';

export default new Enum(['idle', 'sending', 'validating'], 'messageSender');


text:
<!DOCTYPE html>

		<title>Sistema de cursos - Reestablecer mi contraseña</title>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<meta name="keywords" content="your,keywords">
		<meta name="description" content="Short explanation about this website">

		<link rel="icon" type="image/png" href="<?=base_url()?>assets/img/inscripcion.png" />
		<link type="text/css" rel="stylesheet" href="<?=base_url();?>assets/css/theme-1/bootstrap.css?1422792965" />
		<link type="text/css" rel="stylesheet" href="<?=base_url();?>assets/css/theme-1/materialadmin.css?1425466319" />
		<link type="text/css" rel="stylesheet" href="<?=base_url();?>assets/css/theme-1/font-awesome.min.css?1422529194" />
		<link type="text/css" rel="stylesheet" href="<?=base_url();?>assets/css/theme-1/material-design-iconic-font.min.css?1421434286" />
		<link type="text/css" rel="stylesheet" href="<?=base_url();?>assets/css/theme-1/libs/toastr/toastr.css?1425466569" />
		<link type="text/css" rel="stylesheet" href="<?=base_url();?>assets/css/custom.css" />

			<div class="img-backdrop" style="background-image: url('<?=base_url();?>assets/img/buldingbanner.jpg'); background-size: cover;">

							<img class="img-circle" src="<?=base_url();?>assets/img/lock.png" alt="" />

							REESTABLECER CONTRASEÑA

								Oh rayos! Esta página no esta disponible, esto podria deberse a que el enlace ha caducado.

							<a class="btn btn-primary " href="<?=base_url()?>"> Página principal


text:
# Installation
<!-- [[TOC]] -->

## Install Composer

To install PrioritizeRoutes, you will first need to install [Composer][composer] if you haven't already.

## Install PrioritizeRoutes

### Install via Composer

You can install PrioritizeRoutes by simply requiring the package with [Composer][composer] inside your projects root. To do so, run the following command:

```bash
$ composer require cupoftea/prioritize-routes ~1.1
```

### Setting up PrioritizeRoutes

You will need to add the following service providers to your `config/app.php`:

```php
	'providers' => [

		/*
		 * Laravel Framework Service Providers...
		 */

        'Illuminate\Foundation\Providers\ArtisanServiceProvider',
        'Illuminate\Auth\AuthServiceProvider',
        'Illuminate\Bus\BusServiceProvider',

        ...

        'CupOfTea\PrioritizeRoutes\PrioritizeRoutesServiceProvider',

	],
```

[composer]: https://getcomposer.org/doc/00-intro.md


text:
/**
 * Author: DrowsyFlesh
 * Create: 2019/3/21
 * Description:
 */
import {UIManager} from 'Libs/UIManager';

new UIManager('tbilibili');


text:
"""
user template tags
========================
Tags for including plugin javascript assets into a template.
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

from django import template

from .. import hooks
from kolibri.core.webpack.utils import webpack_asset_render

register = template.Library()

@register.simple_tag()
def style_guide_assets():
    """
    Using in a template will inject script tags that include the javascript assets defined
    by any concrete hook that subclasses UserSyncHook.
    :return: HTML of script tags to insert into style_guide/style_guide.html
    """
    return webpack_asset_render(hooks.StyleGuideSyncHook, is_async=False)

@register.simple_tag()
def style_guide_async_assets():
    """
    Using in a template will inject script tags that include the javascript assets defined
    by any concrete hook that subclasses StyleGuideSyncHook.
    :return: HTML of script tags to insert into style_guide/style_guide.html
    """
    return webpack_asset_render(hooks.StyleGuideAsyncHook, is_async=True)


text:
<?php
namespace RS\Scraper;
require_once '/vendor/simplehtmldom/simple_html_dom.php';

abstract class Scraper
{
    protected $html;
    protected $scrapedInfo;
    private static $USE_PROXY = FALSE;

    public function __construct()
    {
        $this->loadHTML();
    }

    protected function loadHTML()
    {
        $context = NULL;
        if(self::$USE_PROXY)
        {
            $auth = base64_encode('mathias.vandebroeck:tiogapass');
            $contextOptions = array
            (
                   /*'http' => array
                   (
                          'proxy' => 'tcp://proxies.finbel.intra:8080', // This needs to be the server and the port of the NTLM Authentication Proxy Server.
                          'request_fulluri' => true,
                          'header' => array("Proxy-Authorization: Basic $auth")
                   ), */
                    'http' => array
                    (
                          'proxy' => 'tcp://10.12.3.196:8118', // This needs to be the server and the port of the NTLM Authentication Proxy Server.
                          'request_fulluri' => true,
                    ),
            );
            $context = stream_context_create($contextOptions);
        }
        $this->html = \file_get_html($this->getURL(), FALSE, $context);
    }

    /**
     * Abstract method for injecting the correct URL for a specific Scraper
     *
     */
    abstract protected function getURL();

    /**
     * ScrapeHTML function that uses the html-var to extract information to the scrapedInfo-var
     *
     */
    abstract protected function scrapeHTML();

    /**
     * Gets the value of html.
     *
     * @return mixed
     */
    public function getHtml()
    {
        return $this->html;
    }

    /**
     * Sets the value of html.
     *
     * @param mixed $html the html
     *
     * @return self
     */
    public function setHtml($html)
    {
        $this->html = $html;
        return $this;
    }

    /**
     * Gets the value of scrapedInfo.
     *
     * @return mixed
     */
    public function getScrapedInfo()
    {
        if(empty($this->scrapedInfo))
            $this->scrapedInfo = $this->scrapeHTML();
        return $this->scrapedInfo;
    }

    /**
     * Sets the value of scrapedInfo.
     *
     * @param mixed $scrapedInfo the scraped info
     *
     * @return self
     */
    public function setScrapedInfo($scrapedInfo)
    {
        $this->scrapedInfo = $scrapedInfo;
        return $this;
    }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>tcc-transaction</artifactId>
        <groupId>org.mengyun</groupId>
        <version>1.2.3.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>tcc-transaction-api</artifactId>

</project>


text:
package org.teavm.classlib.java.nio.charset.impl;

import org.teavm.classlib.java.nio.charset.TCharset;
import org.teavm.classlib.java.nio.charset.TCharsetDecoder;
import org.teavm.classlib.java.nio.charset.TCharsetEncoder;

/**
 *
 * @author Alexey Andreev
 */
public class TUTF8Charset extends TCharset {
    public TUTF8Charset() {
        super("UTF-8", new String[0]);
    }

    @Override
    public boolean contains(TCharset cs) {
        return cs == this;
    }

    @Override
    public TCharsetDecoder newDecoder() {
        return new TUTF8Decoder(this);
    }

    @Override
    public TCharsetEncoder newEncoder() {
        return new TUTF8Encoder(this);
    }
}


text:
package com.johnsnowlabs.nlp.annotators.sentence_detector_dl

import com.johnsnowlabs.ml.tensorflow.{TensorflowSentenceDetectorDL, TensorflowWrapper, Variables}
import com.johnsnowlabs.nlp.AnnotatorType.DOCUMENT
import com.johnsnowlabs.nlp.util.io.ResourceHelper
import com.johnsnowlabs.nlp.{Annotation, AnnotatorApproach}
import org.apache.commons.io.IOUtils
import org.apache.spark.ml.PipelineModel
import org.apache.spark.ml.param._
import org.apache.spark.ml.util.Identifiable
import org.apache.spark.sql.functions.col
import org.apache.spark.sql.{Dataset, Row}
import org.tensorflow.Graph
import org.tensorflow.proto.framework.GraphDef

import scala.collection.mutable

/** Trains an annotator that detects sentence boundaries using a deep learning approach.
  *
  * For pretrained models see [[SentenceDetectorDLModel]].
  *
  * Currently, only the CNN model is supported for training, but in the future the architecture of
  * the model can be set with `setModelArchitecture`.
  *
  * The default model `"cnn"` is based on the paper
  * [[https://konvens.org/proceedings/2019/papers/KONVENS2019_paper_41.pdf Deep-EOS: General-Purpose Neural Networks for Sentence Boundary Detection (2020, Stefan Schweter, Sajawel Ahmed)]]
  * using a CNN architecture. We also modified the original implementation a little bit to cover
  * broken sentences and some impossible end of line chars.
  *
  * Each extracted sentence can be returned in an Array or exploded to separate rows, if
  * `explodeSentences` is set to `true`.
  *
  * For extended examples of usage, see the
  * [[https://github.com/JohnSnowLabs/spark-nlp-workshop/blob/master/tutorials/Certification_Trainings/Public/9.SentenceDetectorDL.ipynb Spark NLP Workshop]]
  * and the
  * [[https://github.com/JohnSnowLabs/spark-nlp/blob/master/src/test/scala/com/johnsnowlabs/nlp/annotators/sentence_detector_dl/SentenceDetectorDLSpec.scala SentenceDetectorDLSpec]].
  *
  * ==Example==
  * The training process needs data, where each data point is a sentence.
  *
  * In this example the `train.txt` file has the form of
  * {{{
  * ...
  * Slightly more moderate language would make our present situation – namely the lack of progress – a little easier.
  * His political successors now have great responsibilities to history and to the heritage of values bequeathed to them by Nelson Mandela.
  * ...
  * }}}
  * where each line is one sentence. Training can then be started like so:
  * {{{
  * import com.johnsnowlabs.nlp.base.DocumentAssembler
  * import com.johnsnowlabs.nlp.annotators.sentence_detector_dl.SentenceDetectorDLApproach
  * import org.apache.spark.ml.Pipeline
  *
  * val trainingData = spark.read.text("train.txt").toDF("text")
  *
  * val documentAssembler = new DocumentAssembler()
  *   .setInputCol("text")
  *   .setOutputCol("document")
  *
  * val sentenceDetector = new SentenceDetectorDLApproach()
  *   .setInputCols(Array("document"))
  *   .setOutputCol("sentences")
  *   .setEpochsNumber(100)
  *
  * val pipeline = new Pipeline().setStages(Array(documentAssembler, sentenceDetector))
  *
  * val model = pipeline.fit(trainingData)
  * }}}
  *
  * @see
  *   [[SentenceDetectorDLModel]] for pretrained models
  * @see
  *   [[com.johnsnowlabs.nlp.annotators.sbd.pragmatic.SentenceDetector SentenceDetector]] for non
  *   deep learning extraction
  * @param uid
  *   required uid for storing annotator to disk
  * @groupname anno Annotator types
  * @groupdesc anno
  *   Required input and expected output annotator types
  * @groupname Ungrouped Members
  * @groupname param Parameters
  * @groupname setParam Parameter setters
  * @groupname getParam Parameter getters
  * @groupname Ungrouped Members
  * @groupprio param  1
  * @groupprio anno  2
  * @groupprio Ungrouped 3
  * @groupprio setParam  4
  * @groupprio getParam  5
  * @groupdesc param
  *   A list of (hyper-)parameter keys this annotator can take. Users can set and get the
  *   parameter values through setters and getters, respectively.
  */
class SentenceDetectorDLApproach(override val uid: String)
    extends AnnotatorApproach[SentenceDetectorDLModel] {

  def this() = this(Identifiable.randomUID("SentenceDetectorDLApproach"))

  /** Trains TensorFlow model for multi-class text classification */
  override val description = "Trains a deep sentence detector"

  /** Input annotator type : DOCUMENT
    *
    * @group anno
    */
  override val inputAnnotatorTypes: Array[AnnotatorType] = Array(DOCUMENT)

  /** Output annotator type : DOCUMENT
    *
    * @group anno
    */
  override val outputAnnotatorType: String = DOCUMENT

  /** Model architecture (Default: `"cnn"`)
    *
    * @group param
    */
  var modelArchitecture =
    new Param[String](this, "modelArchitecture", "Model Architecture: one of (CNN)")

  /** Set architecture
    *
    * @group setParam
    */
  def setModel(modelArchitecture: String): SentenceDetectorDLApproach.this.type =
    set(this.modelArchitecture, modelArchitecture)

  /** Get model architecture
    *
    * @group getParam
    */
  def getModel: String = $(this.modelArchitecture)

  /** Impossible penultimates, which should not be split on Default:
    * {{{
    * Array(
    *   "Bros", "No", "al", "vs", "etc", "Fig", "Dr", "Prof", "PhD", "MD", "Co", "Corp", "Inc",
    *   "bros", "VS", "Vs", "ETC", "fig", "dr", "prof", "PHD", "phd", "md", "co", "corp", "inc",
    *   "Jan", "Feb", "Mar", "Apr", "Jul", "Aug", "Sep", "Sept", "Oct", "Nov", "Dec",
    *   "St", "st",
    *   "AM", "PM", "am", "pm",
    *   "e.g", "f.e", "i.e"
    * )
    * }}}
    *
    * @group param
    */
  val impossiblePenultimates =
    new StringArrayParam(this, "impossiblePenultimates", "Impossible penultimates")

  /** Set impossible penultimates
    *
    * @group setParam
    */
  def setImpossiblePenultimates(
      impossiblePenultimates: Array[String]): SentenceDetectorDLApproach.this.type =
    set(this.impossiblePenultimates, impossiblePenultimates)

  /** Get impossible penultimates
    *
    * @group getParam
    */
  def getImpossiblePenultimates: Array[String] = $(this.impossiblePenultimates)

  /** Maximum number of epochs to train (Default: `5`)
    *
    * @group param
    */
  val epochsNumber = new IntParam(this, "epochsNumber", "Number of epochs to train")

  /** Maximum number of epochs to train (Default: `5`)
    *
    * @group setParam
    */
  def setEpochsNumber(epochs: Int): SentenceDetectorDLApproach.this.type =
    set(this.epochsNumber, epochs)

  /** Maximum number of epochs to train (Default: `5`)
    *
    * @group getParam
    */
  def getEpochsNumber: Int = $(this.epochsNumber)

  /** Path to folder to output logs (Default: `""`) If no path is specified, no logs are generated
    *
    * @group param
    */
  val outputLogsPath =
    new Param[String](this, "outputLogsPath", "Folder path to save training logs")

  /** Set the output log path
    *
    * @group setParam
    */
  def setOutputLogsPath(outputLogsPath: String): SentenceDetectorDLApproach.this.type =
    set(this.outputLogsPath, outputLogsPath)

  /** Get output logs path
    *
    * @group getParam
    */
  def getOutputLogsPath: String = $(this.outputLogsPath)

  /** Choose the proportion of training dataset to be validated against the model on each Epoch
    * (Default: `0.0f`). The value should be between `0.0` and `1.0` and by default it is `0.0`
    * and off.
    *
    * @group param
    */
  val validationSplit = new FloatParam(
    this,
    "validationSplit",
    "Choose the proportion of training dataset to be validated against the model on each Epoch. The value should be between 0.0 and 1.0 and by default it is 0.0 and off.")

  /** Choose the proportion of training dataset to be validated against the model on each Epoch.
    * The value should be between 0.0 and 1.0 and by default it is 0.0 and off.
    *
    * @group setParam
    */
  def setValidationSplit(validationSplit: Float): SentenceDetectorDLApproach.this.type =
    set(this.validationSplit, validationSplit)

  /** Choose the proportion of training dataset to be validated against the model on each Epoch.
    * The value should be between 0.0 and 1.0 and by default it is 0.0 and off.
    *
    * @group getParam
    */
  def getValidationSplit: Float = $(this.validationSplit)

  private var graphFilename: Option[String] = None

  def getGraphFilename: String = {
    graphFilename.getOrElse("sentence_detector_dl/%s.pb".format(getModel))
  }

  def setGraphFile(graphFilename: String): SentenceDetectorDLApproach.this.type = {
    this.graphFilename = Some(graphFilename)
    this
  }

  /** A flag indicating whether to split sentences into different Dataset rows. Useful for higher
    * parallelism in fat rows (Default: `false`)
    *
    * @group getParam
    */
  def explodeSentences =
    new BooleanParam(this, "explodeSentences", "Split sentences in separate rows")

  /** Whether to split sentences into different Dataset rows. Useful for higher parallelism in fat
    * rows. Defaults to false.
    *
    * @group setParam
    */
  def setExplodeSentences(value: Boolean): SentenceDetectorDLApproach.this.type =
    set(this.explodeSentences, value)

  /** Whether to split sentences into different Dataset rows. Useful for higher parallelism in fat
    * rows. Defaults to false.
    *
    * @group getParam
    */
  def getExplodeSentences: Boolean = $(this.explodeSentences)

  /** Length at which sentences will be forcibly split (Ignored if not set)
    *
    * @group param
    */

  val splitLength: IntParam =
    new IntParam(this, "splitLength", "length at which sentences will be forcibly split.")

  /** Length at which sentences will be forcibly split
    * @group setParam
    */
  def setSplitLength(value: Int): this.type = set(splitLength, value)

  /** Length at which sentences will be forcibly split
    * @group getParam
    */
  def getSplitLength: Int = $(splitLength)

  /** Set the minimum allowed length for each sentence (Default: `0`)
    *
    * @group param
    */

  val minLength =
    new IntParam(this, "minLength", "Set the minimum allowed length for each sentence")

  /** Set the minimum allowed length for each sentence
    * @group setParam
    */
  def setMinLength(value: Int): this.type = {
    require(value >= 0, "minLength must be greater equal than 0")
    require(value.isValidInt, "minLength must be Int")
    set(minLength, value)
  }

  /** Get the minimum allowed length for each sentence
    * @group getParam
    */
  def getMinLength: Int = $(minLength)

  /** Set the maximum allowed length for each sentence (Ignored if not set)
    *
    * @group param
    */
  val maxLength =
    new IntParam(this, "maxLength", "Set the maximum allowed length for each sentence")

  /** Set the maximum allowed length for each sentence
    * @group setParam
    */
  def setMaxLength(value: Int): this.type = {
    require(
      value >= $ {
        minLength
      },
      "maxLength must be greater equal than minLength")
    require(value.isValidInt, "minLength must be Int")
    set(maxLength, value)
  }

  /** Get the maximum allowed length for each sentence
    * @group getParam
    */
  def getMaxLength: Int = $(maxLength)

  /** Characters used to explicitly mark sentence bounds (Default: None)
    *
    * @group param
    */
  val customBounds: StringArrayParam = new StringArrayParam(
    this,
    "customBounds",
    "characters used to explicitly mark sentence bounds")

  /** Custom sentence separator text
    * @group setParam
    */
  def setCustomBounds(value: Array[String]): this.type = set(customBounds, value)

  /** Custom sentence separator text
    * @group getParam
    */
  def getCustomBounds: Array[String] = $(customBounds)

  /** Whether to only utilize custom bounds for sentence detection (Default: `false`)
    *
    * @group param
    */
  val useCustomBoundsOnly = new BooleanParam(
    this,
    "useCustomBoundsOnly",
    "whether to only utilize custom bounds for sentence detection")

  /** Use only custom bounds without considering those of Pragmatic Segmenter. Defaults to false.
    * Needs customBounds.
    * @group setParam
    */
  def setUseCustomBoundsOnly(value: Boolean): this.type = set(useCustomBoundsOnly, value)

  /** Use only custom bounds without considering those of Pragmatic Segmenter. Defaults to false.
    * Needs customBounds.
    * @group getParam
    */
  def getUseCustomBoundsOnly: Boolean = $(useCustomBoundsOnly)

  setDefault(
    modelArchitecture -> "cnn",
    impossiblePenultimates -> Array(
      "Bros",
      "No",
      "al",
      "vs",
      "etc",
      "Fig",
      "Dr",
      "Prof",
      "PhD",
      "MD",
      "Co",
      "Corp",
      "Inc",
      "bros",
      "VS",
      "Vs",
      "ETC",
      "fig",
      "dr",
      "prof",
      "PHD",
      "phd",
      "md",
      "co",
      "corp",
      "inc",
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "Jul",
      "Aug",
      "Sep",
      "Sept",
      "Oct",
      "Nov",
      "Dec",
      "St",
      "st",
      "AM",
      "PM",
      "am",
      "pm",
      "e.g",
      "f.e",
      "i.e"),
    epochsNumber -> 5,
    outputLogsPath -> "",
    validationSplit -> 0.0f,
    explodeSentences -> false,
    minLength -> 0,
    maxLength -> Int.MaxValue,
    splitLength -> Int.MaxValue,
    useCustomBoundsOnly -> false,
    customBounds -> Array.empty[String])

  override def train(
      dataset: Dataset[_],
      recursivePipeline: Option[PipelineModel]): SentenceDetectorDLModel = {

    val text = dataset
      .select(getInputCols.map(col): _*)
      .collect()
      .map(row => {
        getInputCols.indices
          .map(i =>
            row
              .get(i)
              .asInstanceOf[mutable.WrappedArray[Row]]
              .map(s => Annotation(s).result)
              .mkString("\n"))
          .mkString("\n")
      })
      .mkString("\n")

    val encoder = new SentenceDetectorDLEncoder()
    encoder.buildVocabulary(text)

    val data = encoder.getTrainingData(text)

    val graph = new Graph()
    val graphStream = ResourceHelper.getResourceStream(getGraphFilename)
    val graphBytesDef = IOUtils.toByteArray(graphStream)
    graph.importGraphDef(GraphDef.parseFrom(graphBytesDef))

    val tfWrapper =
      new TensorflowWrapper(Variables(Array.empty[Array[Byte]], Array.empty[Byte]), graphBytesDef)

    /** FIXME inspect ops for init */
    // graph.operations().foreach(println)

    val tfModel = new TensorflowSentenceDetectorDL(
      tfWrapper,
      outputLogsPath = if (getOutputLogsPath.nonEmpty) Some(getOutputLogsPath) else None)

    tfModel.train(
      data._2,
      data._1.map(Array(_)),
      batchSize = 32,
      epochsNumber = getEpochsNumber,
      learningRate = 0.0001f,
      validationSplit = getValidationSplit,
      classWeights = Array(1.0f),
      dropout = 1.0f,
      uuid = "sentence_detector_dl")

    val model = new SentenceDetectorDLModel

    model.setModel(getModel)
    model.setEncoder(encoder)
    model.setImpossiblePenultimates(getImpossiblePenultimates)
    model.setExplodeSentences(getExplodeSentences)
    model.setMinLength(getMinLength)
    model.setMaxLength(getMaxLength)
    model.setSplitLength(getSplitLength)
    model.setCustomBounds(getCustomBounds)
    model.setUseCustomBoundsOnly(getUseCustomBoundsOnly)
    model.setupTFClassifier(dataset.sparkSession, tfModel.model)

    model
  }
}


text:
using gaxgrpc = Google.Api.Gax.Grpc;
using proto = Google.Protobuf;
using grpccore = Grpc.Core;
using sys = System;
using scg = System.Collections.Generic;
using stt = System.Threading.Tasks;

namespace Testing.BasicClientStreaming
{
    public sealed partial class BasicClientStreamingSettings : gaxgrpc::ServiceSettingsBase
    {
        private BasicClientStreamingSettings(BasicClientStreamingSettings existing) : base(existing)
        {
            // TEST_START
            MethodClientStreamingSettings = existing.MethodClientStreamingSettings;
            // TEST_END
        }

        // TEST_START
        public gaxgrpc::ClientStreamingSettings MethodClientStreamingSettings { get; set; } = new gaxgrpc::ClientStreamingSettings(100);
        // TEST_END
    }

    public abstract partial class BasicClientStreamingClient
    {
        // TEST_START
        ///
        /// Client streaming methods for
        /// <see cref="MethodClient(gaxgrpc::CallSettings,gaxgrpc::ClientStreamingSettings)"/>.
        ///
        public abstract partial class MethodClientStream : gaxgrpc::ClientStreamingBase<Request, Response>
        {
        }

        ///
        ///
        /// <param name="callSettings">If not null, applies overrides to this RPC call.</param>
        /// <param name="streamingSettings">If not null, applies streaming overrides to this RPC call.</param>
        /// <returns>The client stream.</returns>
        public virtual MethodClientStream MethodClient(gaxgrpc::CallSettings callSettings = null, gaxgrpc::ClientStreamingSettings streamingSettings = null) =>
            throw new sys::NotImplementedException();
        // TEST_END
    }

    /// BasicClientStreaming client wrapper implementation, for convenient use.
    /// <remarks>
    /// </remarks>
    public sealed partial class BasicClientStreamingClientImpl : BasicClientStreamingClient
    {
        public BasicClientStreamingClientImpl() => _callMethodClient = null;

        // TEST_START
        private readonly gaxgrpc::ApiClientStreamingCall<Request, Response> _callMethodClient;
        // TEST_END

        // TEST_START
        partial void Modify_ApiCall<TRequest, TResponse>(ref gaxgrpc::ApiCall<TRequest, TResponse> call) where TRequest : class, proto::IMessage<TRequest> where TResponse : class, proto::IMessage<TResponse>;
        // TEST_END

        // TEST_START
        partial void Modify_RequestCallSettings(ref gaxgrpc::CallSettings settings);

        partial void Modify_RequestRequest(ref Request request);
        // TEST_END

        // TEST_START
        internal sealed partial class MethodClientStreamImpl : MethodClientStream
        {
            /// Construct the client streaming method for <c>MethodClient</c>.
            /// <param name="service">The service containing this streaming method.</param>
            /// <param name="call">The underlying gRPC client streaming call.</param>
            /// <param name="writeBuffer">
            /// The <see cref="gaxgrpc::BufferedClientStreamWriter{Request}"/> instance associated with this streaming
            /// call.
            /// </param>
            public MethodClientStreamImpl(BasicClientStreamingClientImpl service, grpccore::AsyncClientStreamingCall<Request, Response> call, gaxgrpc::BufferedClientStreamWriter<Request> writeBuffer)
            {
                _service = service;
                GrpcCall = call;
                _writeBuffer = writeBuffer;
            }

            private BasicClientStreamingClientImpl _service;

            private gaxgrpc::BufferedClientStreamWriter<Request> _writeBuffer;

            public override grpccore::AsyncClientStreamingCall<Request, Response> GrpcCall { get; }

            private Request ModifyRequest(Request request)
            {
                _service.Modify_RequestRequest(ref request);
                return request;
            }

            public override stt::Task TryWriteAsync(Request message) => _writeBuffer.TryWriteAsync(ModifyRequest(message));

            public override stt::Task WriteAsync(Request message) => _writeBuffer.WriteAsync(ModifyRequest(message));

            public override stt::Task TryWriteAsync(Request message, grpccore::WriteOptions options) =>
                _writeBuffer.TryWriteAsync(ModifyRequest(message), options);

            public override stt::Task WriteAsync(Request message, grpccore::WriteOptions options) =>
                _writeBuffer.WriteAsync(ModifyRequest(message), options);

            public override stt::Task TryWriteCompleteAsync() => _writeBuffer.TryWriteCompleteAsync();

            public override stt::Task WriteCompleteAsync() => _writeBuffer.WriteCompleteAsync();
        }
        // TEST_END

        // TEST_START
        ///
        ///
        /// <param name="callSettings">If not null, applies overrides to this RPC call.</param>
        /// <param name="streamingSettings">If not null, applies streaming overrides to this RPC call.</param>
        /// <returns>The client stream.</returns>
        public override BasicClientStreamingClient.MethodClientStream MethodClient(gaxgrpc::CallSettings callSettings = null, gaxgrpc::ClientStreamingSettings streamingSettings = null)
        {
            Modify_RequestCallSettings(ref callSettings);
            gaxgrpc::ClientStreamingSettings effectiveStreamingSettings = streamingSettings ?? _callMethodClient.StreamingSettings;
            grpccore::AsyncClientStreamingCall<Request, Response> call = _callMethodClient.Call(callSettings);
            gaxgrpc::BufferedClientStreamWriter<Request> writeBuffer = new gaxgrpc::BufferedClientStreamWriter<Request>(call.RequestStream, effectiveStreamingSettings.BufferedClientWriterCapacity);
            return new MethodClientStreamImpl(this, call, writeBuffer);
        }
        // TEST_END
    }
}


text:
use clap::App;

use options::Options;

pub trait Runnable {
    fn execute(&self, &Options);
    fn configure(&self) -> App;
    fn get_name(&self) -> &'static str;
    fn get_description(&self) -> &'static str;
}


text:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import {StoreModule} from '@ngrx/store';
import {EffectsModule} from '@ngrx/effects';
import {SharedModule} from './core/modules/shared.module';
import {ReactiveFormsModule} from '@angular/forms';
import {HttpClientModule} from '@angular/common/http';
import {SocketIoModule} from 'ngx-socket-io';
import {ServiceWorkerModule } from '@angular/service-worker';
import {environment} from '@app/env';
import {ROOT_REDUCERS} from '@app/root-store';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    SharedModule,
    ReactiveFormsModule,
    HttpClientModule,
    SocketIoModule,
    StoreModule.forRoot(ROOT_REDUCERS), /* Initialise the Central Store with Application's main reducer*/
    EffectsModule.forRoot([]), /* Start monitoring app's side effects */
    !environment.production ? StoreDevtoolsModule.instrument({ maxAge: 50 }) : [],
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }