<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <windows.h>
#include    <shellapi.h>
#include    <shlobj.h>
#elif   qPlatform_POSIX
#include    <unistd.h>
#endif

#include    "../../Characters/StringBuilder.h"
#include    "../../Containers/Set.h"
#if     qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#include    "../../Execution/Platform/Windows/HRESULTErrorException.h"
#endif
#include    "../../Execution/ErrNoException.h"

#include    "../../IO/FileAccessException.h"
#include    "../../IO/FileBusyException.h"
#include    "../../IO/FileFormatException.h"
#include    "../../Memory/SmallStackBuffer.h"

#include    "FileUtils.h"

#include    "FileSystem.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
using   Execution::Platform::Windows::ThrowIfZeroGetLastError;
#endif

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 **************************** FileSystem::FileSystem ****************************
 ********************************************************************************
 */
IO::FileSystem::FileSystem  IO::FileSystem::FileSystem::Default ()
{
    static  IO::FileSystem::FileSystem  sThe_;
    return sThe_;
}

bool    IO::FileSystem::FileSystem::Access (const String& fileFullPath, FileAccessMode accessMode) const
{
#if     qPlatform_Windows
    if ((accessMode & FileAccessMode::eRead) == FileAccessMode::eRead) {
        DWORD attribs = ::GetFileAttributesW (fileFullPath.c_str ());
        if (attribs == INVALID_FILE_ATTRIBUTES) {
            return false;
        }
    }
    if ((accessMode & FileAccessMode::eWrite) == FileAccessMode::eWrite) {
        DWORD attribs = ::GetFileAttributesW (fileFullPath.c_str ());
        if ((attribs == INVALID_FILE_ATTRIBUTES) or (attribs & FILE_ATTRIBUTE_READONLY)) {
            return false;
        }
    }
    return true;
#elif   qPlatform_POSIX
    // Not REALLY right - but an OK hack for now... -- LGP 2011-09-26
    //http://linux.die.net/man/2/access
    if ((accessMode & FileAccessMode::eRead) == FileAccessMode::eRead) {
        if (access (fileFullPath.AsSDKString().c_str (), R_OK) != 0) {
            return false;
        }
    }
    if ((accessMode & FileAccessMode::eWrite) == FileAccessMode::eWrite) {
        if (access (fileFullPath.AsSDKString().c_str (), W_OK) != 0) {
            return false;
        }
    }
    return true;
#else
    AssertNotImplemented ();
    return false;
#endif
}

void    IO::FileSystem::FileSystem::CheckAccess (const String& fileFullPath, FileAccessMode accessMode)
{
    // quick hack - not fully implemented - but since advsiory only - not too important...

    if (not Access (fileFullPath, accessMode)) {
        // FOR NOW - MIMIC OLD CODE - BUT FIX TO CHECK READ AND WRITE (AND BOTH) ACCESS DEPENDING ON ARGS) -- LGP 2009-08-15
        Execution::DoThrow (FileAccessException (fileFullPath, accessMode));
    }
}

void    IO::FileSystem::FileSystem::CheckFileAccess (const String& fileFullPath, bool checkCanRead, bool checkCanWrite)
{
    if (checkCanRead and checkCanWrite) {
        CheckAccess (fileFullPath, IO::FileAccessMode::eReadWrite);
    }
    else if (checkCanRead) {
        CheckAccess (fileFullPath, IO::FileAccessMode::eRead);
    }
    else if (checkCanWrite) {
        CheckAccess (fileFullPath, IO::FileAccessMode::eWrite);
    }
}

String IO::FileSystem::FileSystem::ResolveShortcut (const String& path2FileOrShortcut)
{
#if     qPlatform_Windows
    // @todo WRONG semantics if file doesnt exist. Wed should raise an exception here.
    // But OK if not a shortcut. THEN just rutn the givne file
    //
    //
    // NB: this requires COM, and for now - I don't want the support module depending on the COM module,
    // so just allow this to fail if COM isn't initialized.
    //      -- LGP 2007-09-23
    //
    {
        SHFILEINFO   info;
        memset (&info, 0, sizeof (info));
        if (::SHGetFileInfo (path2FileOrShortcut.AsSDKString ().c_str (), 0, &info, sizeof (info), SHGFI_ATTRIBUTES) == 0)
        {
            return path2FileOrShortcut;
        }
        // not a shortcut?
        if (!(info.dwAttributes & SFGAO_LINK))
        {
            return path2FileOrShortcut;
        }
    }

    // obtain the IShellLink interface
    IShellLink*     psl =   nullptr;
    IPersistFile*   ppf =   nullptr;
    try {
        if (FAILED (::CoCreateInstance (CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl))) {
            return path2FileOrShortcut;
        }
        if (SUCCEEDED (psl->QueryInterface (IID_IPersistFile, (LPVOID*)&ppf))) {
            if (SUCCEEDED (ppf->Load (path2FileOrShortcut.c_str (), STGM_READ))) {
                // Resolve the link, this may post UI to find the link
                if (SUCCEEDED (psl->Resolve(0, SLR_NO_UI))) {
                    TCHAR   path[MAX_PATH + 1];
                    memset (path, 0, sizeof (path));
                    if (SUCCEEDED (psl->GetPath (path, NEltsOf (path), nullptr, 0))) {
                        ppf->Release ();
                        ppf = nullptr;
                        psl->Release ();
                        psl = nullptr;
                        return String::FromSDKString (path);
                    }
                }
            }
        }
    }
    catch (...) {
        if (ppf != nullptr) {
            ppf->Release ();
        }
        if (psl != nullptr) {
            psl->Release ();
        }
        Execution::DoReThrow ();
    }
    if (ppf != nullptr) {
        ppf->Release ();
    }
    if (psl != nullptr) {
        psl->Release ();
    }
    return path2FileOrShortcut;
#else
    Memory::SmallStackBuffer<Characters::SDKChar> buf (1024);
    ssize_t n;
    while ( (n = ::readlink (path2FileOrShortcut.AsSDKString ().c_str (), buf, buf.GetSize ())) == buf.GetSize ()) {
        buf.GrowToSize (buf.GetSize () * 2);
    }
    if (n < 0) {
        auto    e   =   errno;
        if (e == EINVAL) {
            // According to http://linux.die.net/man/2/readlink - this means the target is not a shortcut which is OK
            return path2FileOrShortcut;
        }
        else {
            Execution::errno_ErrorException::DoThrow (e);
        }
    }
    Assert (n <= buf.GetSize ());   // could leave no room for NUL-byte, but not needed
    constexpr   bool    kWorkaroundBuggyCentos5ReturnsNulBytesInBuf_ = true;
    if (kWorkaroundBuggyCentos5ReturnsNulBytesInBuf_) {
        const Characters::SDKChar*  b   =   buf.begin ();
        const Characters::SDKChar*  e   =   b + n;
        const Characters::SDKChar*  i = find (b, e, '\0');
        if (i != e) {
            size_t  newN = i - buf.begin ();
            Assert (newN < n);
            n = newN;
        }
    }
    return String::FromSDKString (SDKString (buf.begin (), buf.begin () + n));
#endif
}

String IO::FileSystem::FileSystem::CanonicalizeName (const String& path2FileOrShortcut, bool throwIfComponentsNotFound)
{
#if     qPlatform_POSIX
    //  We used to call canonicalize_file_name() - but this doesnt work with AIX 7.1/g++4.9.2, and
    //  according to http://man7.org/linux/man-pages/man3/canonicalize_file_name.3.html:
    //  The call canonicalize_file_name(path) is equivalent to the call:
    //      realpath(path, NULL)
    char*   tmp { ::realpath (path2FileOrShortcut.AsSDKString ().c_str (), nullptr) };
    if (tmp == nullptr) {
        errno_ErrorException::DoThrow (errno);
    }
    String  result  { String::FromNarrowSDKString (tmp) };
    free (tmp);
    return result;
#elif   qPlatform_Windows

    // @todo LARGELY UNSTED ROUGH DRAFT - 2015-05-11
    /*
     *  Note:   PathCanonicalize has lots of problems, PathCanonicalizeCh, and
     *  PathCchCanonicalizeEx is better, but only works with windows 8 or later.
     */
    using   Characters::StringBuilder;
    String  tmp =   ResolveShortcut (path2FileOrShortcut);
    StringBuilder sb;
    Components  c   =   GetPathComponents (path2FileOrShortcut);
    if (c.fAbsolutePath == Components::eAbsolutePath) {
        // use UNC notation
        sb += L"\\\\?";
        if (c.fDriveLetter) {
            sb += *c.fDriveLetter;
        }
        else if (c.fServerAndShare) {
            sb += c.fServerAndShare->fServer + L"\\" +  c.fServerAndShare->fShare;
        }
        else {
            Execution::DoThrow (Execution::StringException (L"for absolute path need drive letter or server/share"));
        }
    }
    else {
        if (c.fDriveLetter) {
            sb += *c.fDriveLetter + L":";
        }
    }
    bool    prefixWIthSlash  = false;
    for (String i : c.fPath) {
        if (prefixWIthSlash) {
            sb += L"\\";
        }
        sb += i;
        prefixWIthSlash = true;
    }
    return sb.str ();
#else
    AssertNotImplemented ();
    return path2FileOrShortcut;
#endif
}

String IO::FileSystem::FileSystem::CanonicalizeName (const String& path2FileOrShortcut, const String& relativeToDirectory, bool throwIfComponentsNotFound)
{
    AssertNotImplemented ();
    return path2FileOrShortcut;
}

IO::FileSystem::FileSystem::Components    IO::FileSystem::FileSystem::GetPathComponents (const String& fileName)
{
    // @todo LARGELY UNSTED ROUGH DRAFT - 2015-05-11
    // See http://en.wikipedia.org/wiki/Path_%28computing%29 to write this
#if 0
//windows
C:
    \user\docs\Letter.txt
    / user / docs / Letter.txt
C:
    Letter.txt
    \\Server01\user\docs\Letter.txt
    \\ ? \UNC\Server01\user\docs\Letter.txt
    \\ ? \C : \user\docs\Letter.txt
    C : \user\docs\somefile.ext : alternate_stream_name
    . / inthisdir
    .. / .. / greatgrandparent
#endif
#if 0
// unix
    / home / user / docs / Letter.txt
    . / inthisdir
    .. / .. / greatgrandparent
    ~ / .rcinfo
#endif
    IO::FileSystem::FileSystem::Components  result;
    using   Traversal::Iterator;
    using   Characters::Character;

#if     qPlatform_Windows
    bool    isUNCName = fileName.length () > 2 and fileName.StartsWith (L"\\\\");
    bool    isAbsolutePath = fileName.length () >= 1 and fileName.StartsWith (L"\\");
#else
#endif
#if     qPlatform_Windows
    const   Set<Character>  kSlashChars_ = { '\\', '/' };
#else
    const   Set<Character>  kSlashChars_ = { '/' };
#endif
    Sequence<String>    rawComponents = fileName.Tokenize (kSlashChars_, false);
    Iterator<String>    i   =   rawComponents.begin ();
#if     qPlatform_Windows
    if (isUNCName) {
        // work todo
    }
#endif
    for (; i != rawComponents.end (); ++i) {
        result.fPath.Append (*i);
    }
    AssertNotImplemented ();
    return result;
}

FileOffset_t    IO::FileSystem::FileSystem::GetFileSize (const String& fileName)
{
#if     qPlatform_Windows
    WIN32_FILE_ATTRIBUTE_DATA   fileAttrData;
    (void)::memset (&fileAttrData, 0, sizeof (fileAttrData));
    Execution::Platform::Windows::ThrowIfFalseGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData));
    return fileAttrData.nFileSizeLow + (static_cast<FileOffset_t> (fileAttrData.nFileSizeHigh) << 32);
#else
    AssertNotImplemented ();
    return 0;
#endif
}

DateTime        IO::FileSystem::FileSystem::GetFileLastModificationDate (const String& fileName)
{
#if     qPlatform_Windows
    WIN32_FILE_ATTRIBUTE_DATA   fileAttrData;
    (void)::memset (&fileAttrData, 0, sizeof (fileAttrData));
    ThrowIfFalseGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData));
    return DateTime (fileAttrData.ftLastWriteTime);
#else
    AssertNotImplemented ();
    return DateTime ();
#endif
}

DateTime    IO::FileSystem::FileSystem::GetFileLastAccessDate (const String& fileName)
{
#if     qPlatform_Windows
    WIN32_FILE_ATTRIBUTE_DATA   fileAttrData;
    (void)::memset (&fileAttrData, 0, sizeof (fileAttrData));
    ThrowIfFalseGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData));
    return DateTime (fileAttrData.ftLastAccessTime);
#else
    AssertNotImplemented ();
    return DateTime ();
#endif
}

void        IO::FileSystem::FileSystem::RemoveFile (const String& fileName)
{
#if     qPlatform_Windows && qTargetPlatformSDKUseswchar_t
    Execution::ThrowErrNoIfNegative (::_wunlink (fileName.c_str ()));
#else
    Execution::ThrowErrNoIfNegative (::unlink (fileName.AsNarrowSDKString ().c_str ()));
#endif
}

void       IO::FileSystem::FileSystem::RemoveFileIf (const String& fileName)
{
#if     qPlatform_Windows && qTargetPlatformSDKUseswchar_t
    int r = ::_wunlink (fileName.c_str ());
#else
    int r = ::unlink (fileName.AsNarrowSDKString ().c_str ());
#endif
    if (r < 0) {
        if (errno != ENOENT) {
            errno_ErrorException::DoThrow (errno);
        }
    }
}

String  IO::FileSystem::FileSystem::GetCurrentDirectory () const
{
#if     qPlatform_POSIX
    SDKChar buf[MAX_PATH];
    Execution::ThrowErrNoIfNull (::getcwd (buf, NEltsOf (buf)));
    return String::FromSDKString (buf);
#elif   qPlatform_Windows
    SDKChar buf[MAX_PATH];
    ThrowIfZeroGetLastError (::GetCurrentDirectory (MAX_PATH, buf));
    return String::FromSDKString (buf);
#else
#endif
}

void    IO::FileSystem::FileSystem::SetCurrentDirectory (const String& newDir)
{
#if     qPlatform_POSIX
    Execution::ThrowErrNoIfNegative (::chdir (newDir.AsNarrowSDKString ().c_str ()));
#elif   qPlatform_Windows
    ::SetCurrentDirectory(newDir.AsSDKString ().c_str ());
#else
#endif
}
<commit_msg>POSIX typo<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <windows.h>
#include    <shellapi.h>
#include    <shlobj.h>
#elif   qPlatform_POSIX
#include    <unistd.h>
#endif

#include    "../../Characters/StringBuilder.h"
#include    "../../Containers/Set.h"
#if     qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#include    "../../Execution/Platform/Windows/HRESULTErrorException.h"
#endif
#include    "../../Execution/ErrNoException.h"

#include    "../../IO/FileAccessException.h"
#include    "../../IO/FileBusyException.h"
#include    "../../IO/FileFormatException.h"
#include    "../../Memory/SmallStackBuffer.h"

#include    "FileUtils.h"

#include    "FileSystem.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
using   Execution::Platform::Windows::ThrowIfZeroGetLastError;
#endif

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 **************************** FileSystem::FileSystem ****************************
 ********************************************************************************
 */
IO::FileSystem::FileSystem  IO::FileSystem::FileSystem::Default ()
{
    static  IO::FileSystem::FileSystem  sThe_;
    return sThe_;
}

bool    IO::FileSystem::FileSystem::Access (const String& fileFullPath, FileAccessMode accessMode) const
{
#if     qPlatform_Windows
    if ((accessMode & FileAccessMode::eRead) == FileAccessMode::eRead) {
        DWORD attribs = ::GetFileAttributesW (fileFullPath.c_str ());
        if (attribs == INVALID_FILE_ATTRIBUTES) {
            return false;
        }
    }
    if ((accessMode & FileAccessMode::eWrite) == FileAccessMode::eWrite) {
        DWORD attribs = ::GetFileAttributesW (fileFullPath.c_str ());
        if ((attribs == INVALID_FILE_ATTRIBUTES) or (attribs & FILE_ATTRIBUTE_READONLY)) {
            return false;
        }
    }
    return true;
#elif   qPlatform_POSIX
    // Not REALLY right - but an OK hack for now... -- LGP 2011-09-26
    //http://linux.die.net/man/2/access
    if ((accessMode & FileAccessMode::eRead) == FileAccessMode::eRead) {
        if (access (fileFullPath.AsSDKString().c_str (), R_OK) != 0) {
            return false;
        }
    }
    if ((accessMode & FileAccessMode::eWrite) == FileAccessMode::eWrite) {
        if (access (fileFullPath.AsSDKString().c_str (), W_OK) != 0) {
            return false;
        }
    }
    return true;
#else
    AssertNotImplemented ();
    return false;
#endif
}

void    IO::FileSystem::FileSystem::CheckAccess (const String& fileFullPath, FileAccessMode accessMode)
{
    // quick hack - not fully implemented - but since advsiory only - not too important...

    if (not Access (fileFullPath, accessMode)) {
        // FOR NOW - MIMIC OLD CODE - BUT FIX TO CHECK READ AND WRITE (AND BOTH) ACCESS DEPENDING ON ARGS) -- LGP 2009-08-15
        Execution::DoThrow (FileAccessException (fileFullPath, accessMode));
    }
}

void    IO::FileSystem::FileSystem::CheckFileAccess (const String& fileFullPath, bool checkCanRead, bool checkCanWrite)
{
    if (checkCanRead and checkCanWrite) {
        CheckAccess (fileFullPath, IO::FileAccessMode::eReadWrite);
    }
    else if (checkCanRead) {
        CheckAccess (fileFullPath, IO::FileAccessMode::eRead);
    }
    else if (checkCanWrite) {
        CheckAccess (fileFullPath, IO::FileAccessMode::eWrite);
    }
}

String IO::FileSystem::FileSystem::ResolveShortcut (const String& path2FileOrShortcut)
{
#if     qPlatform_Windows
    // @todo WRONG semantics if file doesnt exist. Wed should raise an exception here.
    // But OK if not a shortcut. THEN just rutn the givne file
    //
    //
    // NB: this requires COM, and for now - I don't want the support module depending on the COM module,
    // so just allow this to fail if COM isn't initialized.
    //      -- LGP 2007-09-23
    //
    {
        SHFILEINFO   info;
        memset (&info, 0, sizeof (info));
        if (::SHGetFileInfo (path2FileOrShortcut.AsSDKString ().c_str (), 0, &info, sizeof (info), SHGFI_ATTRIBUTES) == 0)
        {
            return path2FileOrShortcut;
        }
        // not a shortcut?
        if (!(info.dwAttributes & SFGAO_LINK))
        {
            return path2FileOrShortcut;
        }
    }

    // obtain the IShellLink interface
    IShellLink*     psl =   nullptr;
    IPersistFile*   ppf =   nullptr;
    try {
        if (FAILED (::CoCreateInstance (CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl))) {
            return path2FileOrShortcut;
        }
        if (SUCCEEDED (psl->QueryInterface (IID_IPersistFile, (LPVOID*)&ppf))) {
            if (SUCCEEDED (ppf->Load (path2FileOrShortcut.c_str (), STGM_READ))) {
                // Resolve the link, this may post UI to find the link
                if (SUCCEEDED (psl->Resolve(0, SLR_NO_UI))) {
                    TCHAR   path[MAX_PATH + 1];
                    memset (path, 0, sizeof (path));
                    if (SUCCEEDED (psl->GetPath (path, NEltsOf (path), nullptr, 0))) {
                        ppf->Release ();
                        ppf = nullptr;
                        psl->Release ();
                        psl = nullptr;
                        return String::FromSDKString (path);
                    }
                }
            }
        }
    }
    catch (...) {
        if (ppf != nullptr) {
            ppf->Release ();
        }
        if (psl != nullptr) {
            psl->Release ();
        }
        Execution::DoReThrow ();
    }
    if (ppf != nullptr) {
        ppf->Release ();
    }
    if (psl != nullptr) {
        psl->Release ();
    }
    return path2FileOrShortcut;
#else
    Memory::SmallStackBuffer<Characters::SDKChar> buf (1024);
    ssize_t n;
    while ( (n = ::readlink (path2FileOrShortcut.AsSDKString ().c_str (), buf, buf.GetSize ())) == buf.GetSize ()) {
        buf.GrowToSize (buf.GetSize () * 2);
    }
    if (n < 0) {
        auto    e   =   errno;
        if (e == EINVAL) {
            // According to http://linux.die.net/man/2/readlink - this means the target is not a shortcut which is OK
            return path2FileOrShortcut;
        }
        else {
            Execution::errno_ErrorException::DoThrow (e);
        }
    }
    Assert (n <= buf.GetSize ());   // could leave no room for NUL-byte, but not needed
    constexpr   bool    kWorkaroundBuggyCentos5ReturnsNulBytesInBuf_ = true;
    if (kWorkaroundBuggyCentos5ReturnsNulBytesInBuf_) {
        const Characters::SDKChar*  b   =   buf.begin ();
        const Characters::SDKChar*  e   =   b + n;
        const Characters::SDKChar*  i = find (b, e, '\0');
        if (i != e) {
            size_t  newN = i - buf.begin ();
            Assert (newN < n);
            n = newN;
        }
    }
    return String::FromSDKString (SDKString (buf.begin (), buf.begin () + n));
#endif
}

String IO::FileSystem::FileSystem::CanonicalizeName (const String& path2FileOrShortcut, bool throwIfComponentsNotFound)
{
#if     qPlatform_POSIX
    //  We used to call canonicalize_file_name() - but this doesnt work with AIX 7.1/g++4.9.2, and
    //  according to http://man7.org/linux/man-pages/man3/canonicalize_file_name.3.html:
    //  The call canonicalize_file_name(path) is equivalent to the call:
    //      realpath(path, NULL)
    char*   tmp { ::realpath (path2FileOrShortcut.AsSDKString ().c_str (), nullptr) };
    if (tmp == nullptr) {
        errno_ErrorException::DoThrow (errno);
    }
    String  result  { String::FromNarrowSDKString (tmp) };
    free (tmp);
    return result;
#elif   qPlatform_Windows

    // @todo LARGELY UNSTED ROUGH DRAFT - 2015-05-11
    /*
     *  Note:   PathCanonicalize has lots of problems, PathCanonicalizeCh, and
     *  PathCchCanonicalizeEx is better, but only works with windows 8 or later.
     */
    using   Characters::StringBuilder;
    String  tmp =   ResolveShortcut (path2FileOrShortcut);
    StringBuilder sb;
    Components  c   =   GetPathComponents (path2FileOrShortcut);
    if (c.fAbsolutePath == Components::eAbsolutePath) {
        // use UNC notation
        sb += L"\\\\?";
        if (c.fDriveLetter) {
            sb += *c.fDriveLetter;
        }
        else if (c.fServerAndShare) {
            sb += c.fServerAndShare->fServer + L"\\" +  c.fServerAndShare->fShare;
        }
        else {
            Execution::DoThrow (Execution::StringException (L"for absolute path need drive letter or server/share"));
        }
    }
    else {
        if (c.fDriveLetter) {
            sb += *c.fDriveLetter + L":";
        }
    }
    bool    prefixWIthSlash  = false;
    for (String i : c.fPath) {
        if (prefixWIthSlash) {
            sb += L"\\";
        }
        sb += i;
        prefixWIthSlash = true;
    }
    return sb.str ();
#else
    AssertNotImplemented ();
    return path2FileOrShortcut;
#endif
}

String IO::FileSystem::FileSystem::CanonicalizeName (const String& path2FileOrShortcut, const String& relativeToDirectory, bool throwIfComponentsNotFound)
{
    AssertNotImplemented ();
    return path2FileOrShortcut;
}

IO::FileSystem::FileSystem::Components    IO::FileSystem::FileSystem::GetPathComponents (const String& fileName)
{
    // @todo LARGELY UNSTED ROUGH DRAFT - 2015-05-11
    // See http://en.wikipedia.org/wiki/Path_%28computing%29 to write this
#if 0
//windows
C:
    \user\docs\Letter.txt
    / user / docs / Letter.txt
C:
    Letter.txt
    \\Server01\user\docs\Letter.txt
    \\ ? \UNC\Server01\user\docs\Letter.txt
    \\ ? \C : \user\docs\Letter.txt
    C : \user\docs\somefile.ext : alternate_stream_name
    . / inthisdir
    .. / .. / greatgrandparent
#endif
#if 0
// unix
    / home / user / docs / Letter.txt
    . / inthisdir
    .. / .. / greatgrandparent
    ~ / .rcinfo
#endif
    IO::FileSystem::FileSystem::Components  result;
    using   Traversal::Iterator;
    using   Characters::Character;

#if     qPlatform_Windows
    bool    isUNCName = fileName.length () > 2 and fileName.StartsWith (L"\\\\");
    bool    isAbsolutePath = fileName.length () >= 1 and fileName.StartsWith (L"\\");
#else
#endif
#if     qPlatform_Windows
    const   Set<Character>  kSlashChars_ = { '\\', '/' };
#else
    const   Set<Character>  kSlashChars_ = { '/' };
#endif
    Sequence<String>    rawComponents = fileName.Tokenize (kSlashChars_, false);
    Iterator<String>    i   =   rawComponents.begin ();
#if     qPlatform_Windows
    if (isUNCName) {
        // work todo
    }
#endif
    for (; i != rawComponents.end (); ++i) {
        result.fPath.Append (*i);
    }
    AssertNotImplemented ();
    return result;
}

FileOffset_t    IO::FileSystem::FileSystem::GetFileSize (const String& fileName)
{
#if     qPlatform_Windows
    WIN32_FILE_ATTRIBUTE_DATA   fileAttrData;
    (void)::memset (&fileAttrData, 0, sizeof (fileAttrData));
    Execution::Platform::Windows::ThrowIfFalseGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData));
    return fileAttrData.nFileSizeLow + (static_cast<FileOffset_t> (fileAttrData.nFileSizeHigh) << 32);
#else
    AssertNotImplemented ();
    return 0;
#endif
}

DateTime        IO::FileSystem::FileSystem::GetFileLastModificationDate (const String& fileName)
{
#if     qPlatform_Windows
    WIN32_FILE_ATTRIBUTE_DATA   fileAttrData;
    (void)::memset (&fileAttrData, 0, sizeof (fileAttrData));
    ThrowIfFalseGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData));
    return DateTime (fileAttrData.ftLastWriteTime);
#else
    AssertNotImplemented ();
    return DateTime ();
#endif
}

DateTime    IO::FileSystem::FileSystem::GetFileLastAccessDate (const String& fileName)
{
#if     qPlatform_Windows
    WIN32_FILE_ATTRIBUTE_DATA   fileAttrData;
    (void)::memset (&fileAttrData, 0, sizeof (fileAttrData));
    ThrowIfFalseGetLastError (::GetFileAttributesExW (fileName.c_str (), GetFileExInfoStandard, &fileAttrData));
    return DateTime (fileAttrData.ftLastAccessTime);
#else
    AssertNotImplemented ();
    return DateTime ();
#endif
}

void        IO::FileSystem::FileSystem::RemoveFile (const String& fileName)
{
#if     qPlatform_Windows && qTargetPlatformSDKUseswchar_t
    Execution::ThrowErrNoIfNegative (::_wunlink (fileName.c_str ()));
#else
    Execution::ThrowErrNoIfNegative (::unlink (fileName.AsNarrowSDKString ().c_str ()));
#endif
}

void       IO::FileSystem::FileSystem::RemoveFileIf (const String& fileName)
{
#if     qPlatform_Windows && qTargetPlatformSDKUseswchar_t
    int r = ::_wunlink (fileName.c_str ());
#else
    int r = ::unlink (fileName.AsNarrowSDKString ().c_str ());
#endif
    if (r < 0) {
        if (errno != ENOENT) {
            errno_ErrorException::DoThrow (errno);
        }
    }
}

String  IO::FileSystem::FileSystem::GetCurrentDirectory () const
{
#if     qPlatform_POSIX
    SDKChar buf[PATH_MAX];
    Execution::ThrowErrNoIfNull (::getcwd (buf, NEltsOf (buf)));
    return String::FromSDKString (buf);
#elif   qPlatform_Windows
    SDKChar buf[MAX_PATH];
    ThrowIfZeroGetLastError (::GetCurrentDirectory (NEltsOf (buf), buf));
    return String::FromSDKString (buf);
#else
#endif
}

void    IO::FileSystem::FileSystem::SetCurrentDirectory (const String& newDir)
{
#if     qPlatform_POSIX
    Execution::ThrowErrNoIfNegative (::chdir (newDir.AsNarrowSDKString ().c_str ()));
#elif   qPlatform_Windows
    ::SetCurrentDirectory(newDir.AsSDKString ().c_str ());
#else
#endif
}
<|endoftext|>


<commit_before>#include "motor/multirotor_tri_motor_mapper.hpp"

#include <array>
#include <cstddef>
#include "protocol/messages.hpp"
#include "util/time.hpp"
#include <chprintf.h>

constexpr float M_PI = 3.1415926535;

MultirotorTriMotorMapper::MultirotorTriMotorMapper(PWMDeviceGroup<3>& motors, PWMDeviceGroup<1>& servos, Communicator& communicator, Logger& logger)
  : motors(motors),
    servos(servos),
    throttleStream(communicator, 5),
    logger(logger){
}

void MultirotorTriMotorMapper::run(bool armed, ActuatorSetpoint& input) {
  // TODO(yoos): comment on motor indexing convention starting from positive
  // X in counterclockwise order.
  // Calculate servo output
  std::array<float, 1> sOutputs;
  sOutputs[0] = 0.540 - 0.5*input.yaw;   // Magic number servo bias for pusher yaw prop.
  sOutputs[0] = std::min(1.0, std::max(-1.0, sOutputs[0]));
  servos.set(armed, sOutputs);

  // Scale throttle to compensate for roll and pitch up to max angles
  input.throttle /= std::cos(std::min(std::fabs(input.roll), M_PI/3));
  input.throttle /= std::cos(std::min(std::fabs(input.pitch), M_PI/3));
  input.throttle = std::min(input.throttle, 1.0);   // Not entirely necessary, but perhaps preserve some control authority.

  // Calculate motor outputs
  std::array<float, 3> mOutputs;
  mOutputs[0] = input.throttle + 0.866025*input.roll - 0.5*input.pitch;   // Left
  mOutputs[1] = input.throttle                       +     input.pitch;   // Tail
  mOutputs[2] = input.throttle - 0.866025*input.roll - 0.5*input.pitch;   // Right
  motors.set(armed, mOutputs);

  // Scale tail thrust per servo tilt
  // TODO(yoos): Again, resolve magic number.
  mOutputs[1] /= std::cos(3.1415926535/4*input.yaw);

  // DEBUG
  //static int loop=0;
  //if (loop == 0) {
  //  chprintf((BaseSequentialStream*)&SD4, "MM %f %f %f %f\r\n", mOutputs[0], mOutputs[1], mOutputs[2], sOutputs[0]);
  //}
  //loop = (loop+1) % 50;

  protocol::message::motor_throttle_message_t m {
    .time = ST2MS(chibios_rt::System::getTime()),
    .throttles = { mOutputs[0], mOutputs[1], mOutputs[2], sOutputs[0] }
  };

  if(throttleStream.ready()) {
    throttleStream.publish(m);
  }
  logger.write(m);
}
<commit_msg>Scale tail thrust based on capped output.<commit_after>#include "motor/multirotor_tri_motor_mapper.hpp"

#include <array>
#include <cstddef>
#include "protocol/messages.hpp"
#include "util/time.hpp"
#include <chprintf.h>

constexpr float M_PI = 3.1415926535;

MultirotorTriMotorMapper::MultirotorTriMotorMapper(PWMDeviceGroup<3>& motors, PWMDeviceGroup<1>& servos, Communicator& communicator, Logger& logger)
  : motors(motors),
    servos(servos),
    throttleStream(communicator, 5),
    logger(logger){
}

void MultirotorTriMotorMapper::run(bool armed, ActuatorSetpoint& input) {
  // TODO(yoos): comment on motor indexing convention starting from positive
  // X in counterclockwise order.
  // Calculate servo output
  std::array<float, 1> sOutputs;
  sOutputs[0] = 0.540 - 0.5*input.yaw;   // Magic number servo bias for pusher yaw prop.
  sOutputs[0] = std::min(1.0, std::max(-1.0, sOutputs[0]));
  servos.set(armed, sOutputs);

  // Scale throttle to compensate for roll and pitch up to max angles
  input.throttle /= std::cos(std::min(std::fabs(input.roll), M_PI/3));
  input.throttle /= std::cos(std::min(std::fabs(input.pitch), M_PI/3));
  input.throttle = std::min(input.throttle, 1.0);   // Not entirely necessary, but perhaps preserve some control authority.

  // Calculate motor outputs
  std::array<float, 3> mOutputs;
  mOutputs[0] = input.throttle + 0.866025*input.roll - 0.5*input.pitch;   // Left
  mOutputs[1] = input.throttle                       +     input.pitch;   // Tail
  mOutputs[2] = input.throttle - 0.866025*input.roll - 0.5*input.pitch;   // Right
  motors.set(armed, mOutputs);

  // Scale tail thrust per servo tilt
  // TODO(yoos): Again, resolve magic number.
  mOutputs[1] /= std::cos(3.1415926535/4*sOutputs[0]);

  // DEBUG
  //static int loop=0;
  //if (loop == 0) {
  //  chprintf((BaseSequentialStream*)&SD4, "MM %f %f %f %f\r\n", mOutputs[0], mOutputs[1], mOutputs[2], sOutputs[0]);
  //}
  //loop = (loop+1) % 50;

  protocol::message::motor_throttle_message_t m {
    .time = ST2MS(chibios_rt::System::getTime()),
    .throttles = { mOutputs[0], mOutputs[1], mOutputs[2], sOutputs[0] }
  };

  if(throttleStream.ready()) {
    throttleStream.publish(m);
  }
  logger.write(m);
}
<|endoftext|>


<commit_before>#include <babylon/materials/textures/raw_texture_2d_array.h>

#include <babylon/engines/engine.h>
#include <babylon/engines/scene.h>
#include <babylon/materials/textures/internal_texture.h>

namespace BABYLON {

RawTexture2DArray::RawTexture2DArray(const ArrayBufferView& data, int width, int height, int depth,
                                     unsigned int iFormat, Scene* scene, bool generateMipMaps,
                                     bool iInvertY, unsigned int iSamplingMode,
                                     unsigned int iTextureType)
    : Texture{nullptr, scene, !generateMipMaps, iInvertY}, format{iFormat}
{
  _texture = scene->getEngine()->createRawTexture2DArray(data,            //
                                                         width,           //
                                                         height,          //
                                                         depth,           //
                                                         iFormat,         //
                                                         generateMipMaps, //
                                                         invertY,         //
                                                         iSamplingMode,   //
                                                         "",              //
                                                         iTextureType     //
  );

  is2DArray = true;
}

RawTexture2DArray::~RawTexture2DArray() = default;

void RawTexture2DArray::update(const ArrayBufferView& data)
{
  if (!_texture) {
    return;
  }
  _getEngine()->updateRawTexture2DArray(_texture, data, _texture->format, _texture->invertY, "",
                                        _texture->type);
}

} // end of namespace BABYLON
<commit_msg>Checking for valid engine reference<commit_after>#include <babylon/materials/textures/raw_texture_2d_array.h>

#include <babylon/engines/engine.h>
#include <babylon/engines/scene.h>
#include <babylon/materials/textures/internal_texture.h>

namespace BABYLON {

RawTexture2DArray::RawTexture2DArray(const ArrayBufferView& data, int width, int height, int depth,
                                     unsigned int iFormat, Scene* scene, bool generateMipMaps,
                                     bool iInvertY, unsigned int iSamplingMode,
                                     unsigned int iTextureType)
    : Texture{nullptr, scene, !generateMipMaps, iInvertY}, format{iFormat}
{
  _texture = scene->getEngine()->createRawTexture2DArray(data,            //
                                                         width,           //
                                                         height,          //
                                                         depth,           //
                                                         iFormat,         //
                                                         generateMipMaps, //
                                                         invertY,         //
                                                         iSamplingMode,   //
                                                         "",              //
                                                         iTextureType     //
  );

  is2DArray = true;
}

RawTexture2DArray::~RawTexture2DArray() = default;

void RawTexture2DArray::update(const ArrayBufferView& data)
{
  if (!_texture || !_getEngine()) {
    return;
  }
  _getEngine()->updateRawTexture2DArray(_texture, data, _texture->format, _texture->invertY, "",
                                        _texture->type);
}

} // end of namespace BABYLON
<|endoftext|>


<commit_before>/*
 * File:   rigResection.hpp
 * Author: sgaspari
 *
 * Created on January 2, 2016, 5:51 PM
 */

#pragma once

#include <openMVG/types.hpp>
#include <openMVG/cameras/Camera_Pinhole_Radial.hpp>
#include <openMVG/geometry/pose3.hpp>

#include <vector>

namespace openMVG{
namespace localization{

#if HAVE_OPENGV

bool rigResection(const std::vector<openMVG::Mat2X> &pts2d,
                  const std::vector<openMVG::Mat3X> &pts3d,
                  const std::vector<cameras::Pinhole_Intrinsic_Radial_K3 > &vec_queryIntrinsics,
                  const std::vector<geometry::Pose3 > &vec_subPoses,
                  geometry::Pose3 &rigPose,
                  std::vector<std::vector<std::size_t> > &inliers,
                  double threshold = 1e-6,
                  size_t maxIterations = 100,
                  bool verbosity = true);

#endif

}
}
<commit_msg>[localization] doc rigResection<commit_after>/*
 * File:   rigResection.hpp
 * Author: sgaspari
 *
 * Created on January 2, 2016, 5:51 PM
 */

#pragma once

#include <openMVG/types.hpp>
#include <openMVG/cameras/Camera_Pinhole_Radial.hpp>
#include <openMVG/geometry/pose3.hpp>

#include <vector>

namespace openMVG{
namespace localization{

#if HAVE_OPENGV

/**
 * @brief It computes the pose of a camera rig given the 2d-3d associations of
 * each camera along with the internal calibration of each camera and the external
 * calibration of the cameras wrt the main one.
 *
 * @param[in] vec_pts2d A vector of the same size as the number of the camera in
 * the rig, each element of the vector contains the 2d points of the associations
 * for each camera.
 * @param[in] vec_pts3d A vector of the same size as the number of the camera in
 * the rig, each element of the vector contains the 3d points of the associations
 * for each camera. A 2d-3d association is represented by (vec_pts2d[i].col(j), vec_pts3d[i].col(j)).
 * @param[in] vec_queryIntrinsics A vector containing the intrinsics for each
 * camera of the rig.
 * @param[in] vec_subPoses A vector containing the subposes of the cameras wrt
 * the main one, ie the camera 0. This vector has numCameras-1 elements.
 * @param[out] rigPose The rig pose referred to the position of the main camera.
 * @param[out] inliers A vector of the same size as the number of cameras c
 * ontaining the indices of inliers.
 * @param[in] threshold The threshold to use in the ransac process. Note that the
 * threshold is an cos(angle), more specifically it's the maximum angle allowed
 * between the 3D direction of the feature point and the 3D direction of the
 * associated 3D point. The reprojection error computed in the ransac is 1-cos(angle),
 * where angle is the angle between the two directions.
 * @param[in] maxIterations Maximum number of iteration for the ransac process.
 * @param[in] verbosity Mute/unmute the debugging messages.
 * @return true if the ransac has success.
 */
bool rigResection(const std::vector<openMVG::Mat2X> &vec_pts2d,
                  const std::vector<openMVG::Mat3X> &vec_pts3d,
                  const std::vector<cameras::Pinhole_Intrinsic_Radial_K3 > &vec_queryIntrinsics,
                  const std::vector<geometry::Pose3 > &vec_subPoses,
                  geometry::Pose3 &rigPose,
                  std::vector<std::vector<std::size_t> > &inliers,
                  double threshold = 1-std::cos(0.00141421368),   // ~0.1deg
                  size_t maxIterations = 100,
                  bool verbosity = true);

#endif

}
}
<|endoftext|>


<commit_before>#include "Decoder_polar_SCAN_naive_sys.hpp"

namespace aff3ct
{
namespace module
{
template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::Decoder_polar_SCAN_naive_sys(const int &K, const int &N, const int &max_iter, const mipp::vector<B> &frozen_bits,
                               const int n_frames, const std::string name)
: Decoder_polar_SCAN_naive<B,R,I,F,V,H>(K, N, max_iter, frozen_bits, n_frames, name)
{
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::~Decoder_polar_SCAN_naive_sys()
{
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
void Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::_soft_decode(const R *sys, const R *par, R *ext, const int frame_id)
{
	// ----------------------------------------------------------------------------------------------------------- LOAD
	this->_load_init();

	// init the softGraph (special case for the right most stage)
	auto sys_idx = 0, par_idx = 0;
	for (auto i = 0; i < this->N; i++)
		if (!this->frozen_bits[i])
			this->soft_graph[this->layers_count - 1][i] = sys[sys_idx++];
		else
			this->soft_graph[this->layers_count - 1][i] = par[par_idx++];

	// --------------------------------------------------------------------------------------------------------- DECODE
	Decoder_polar_SCAN_naive<B,R,I,F,V,H>::_decode();

	// ---------------------------------------------------------------------------------------------------------- STORE
	sys_idx = 0;
	for (auto i = 0; i < this->N; i++)
		if (!this->frozen_bits[i]) // if "i" is NOT a frozen bit (information bit = sytematic bit)
			ext[sys_idx++] = this->feedback_graph[this->layers_count -1][i];
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
void Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::_soft_decode(const R *Y_N1, R *Y_N2, const int frame_id)
{
	// ----------------------------------------------------------------------------------------------------------- LOAD
	this->_load(Y_N1);

	// --------------------------------------------------------------------------------------------------------- DECODE
	Decoder_polar_SCAN_naive<B,R,I,F,V,H>::_decode();

	// ---------------------------------------------------------------------------------------------------------- STORE
	for (auto i = 0; i < this->N; i++)
		Y_N2[i] = this->feedback_graph[this->layers_count -1][i];
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
void Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::_store(B *V_N) const
{
	auto k = 0;
	for (auto i = 0; i < this->N; i++)
	{
		if (!this->frozen_bits[i]) // if i is not a frozen bit
			V_N[k++] = (H(this->feedback_graph[this->layers_count -1][i]) == 0) ? (B)0 : (B)1;
	}
}
}
}
<commit_msg>Modification of the SCAN store function.<commit_after>#include "Decoder_polar_SCAN_naive_sys.hpp"

namespace aff3ct
{
namespace module
{
template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::Decoder_polar_SCAN_naive_sys(const int &K, const int &N, const int &max_iter, const mipp::vector<B> &frozen_bits,
                               const int n_frames, const std::string name)
: Decoder_polar_SCAN_naive<B,R,I,F,V,H>(K, N, max_iter, frozen_bits, n_frames, name)
{
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::~Decoder_polar_SCAN_naive_sys()
{
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
void Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::_soft_decode(const R *sys, const R *par, R *ext, const int frame_id)
{
	// ----------------------------------------------------------------------------------------------------------- LOAD
	this->_load_init();

	// init the softGraph (special case for the right most stage)
	auto sys_idx = 0, par_idx = 0;
	for (auto i = 0; i < this->N; i++)
		if (!this->frozen_bits[i])
			this->soft_graph[this->layers_count - 1][i] = sys[sys_idx++];
		else
			this->soft_graph[this->layers_count - 1][i] = par[par_idx++];

	// --------------------------------------------------------------------------------------------------------- DECODE
	Decoder_polar_SCAN_naive<B,R,I,F,V,H>::_decode();

	// ---------------------------------------------------------------------------------------------------------- STORE
	sys_idx = 0;
	for (auto i = 0; i < this->N; i++)
		if (!this->frozen_bits[i]) // if "i" is NOT a frozen bit (information bit = sytematic bit)
			ext[sys_idx++] = this->feedback_graph[this->layers_count -1][i];
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
void Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::_soft_decode(const R *Y_N1, R *Y_N2, const int frame_id)
{
	// ----------------------------------------------------------------------------------------------------------- LOAD
	this->_load(Y_N1);

	// --------------------------------------------------------------------------------------------------------- DECODE
	Decoder_polar_SCAN_naive<B,R,I,F,V,H>::_decode();

	// ---------------------------------------------------------------------------------------------------------- STORE
	for (auto i = 0; i < this->N; i++)
		Y_N2[i] = this->feedback_graph[this->layers_count -1][i];
}

template <typename B, typename R,
          tools::proto_i<R> I, tools::proto_f<R> F, tools::proto_v<R> V, tools::proto_h<B,R> H>
void Decoder_polar_SCAN_naive_sys<B,R,I,F,V,H>
::_store(B *V_N) const
{
	auto k = 0;
	for (auto i = 0; i < this->N; i++)
	{
		if (!this->frozen_bits[i]) // if i is not a frozen bit
			V_N[k++] = (H(this->feedback_graph[this->layers_count -1][i] + this->soft_graph[this->layers_count -1][i]) == 0) ? (B)0 : (B)1;
	}
}
}
}
<|endoftext|>


<commit_before>/**
 * Author: derselbst
 * Description: provides functions that are used by the worker processes to check whether a bruteforced string generated by the master process matches pwdHash
 */

#include <iostream>
#include <cstring> // memcmp()
#include <string>
#include <queue>
#include <limits>
#include <iomanip>
#include <openssl/sha.h>
#include <byteswap.h>
#include <mpi.h>

using namespace std;

#include "worker.h"
#include "master.h"
#include "alphabet.h"

// contains the hash of the unknown password
char pwdHash[SHA256_DIGEST_LENGTH];

// contains the hash of a bruteforced string
char bruteHash[SHA256_DIGEST_LENGTH];

// used when sending messages
enum MpiMsgTag
{
    task,
    success // hashes match, unused ATM
};

/**
 * @brief prints 32 bytes of memory
 *
 * prints a hex dump of 32 bytes of memory pointed to
 *
 * @param[in]   pbuf: pointer to some memory, usually containing an SHA256 hash
 */
void printSHAHash(const unsigned int *const pbuf)
{
    // byteswap the integer pointed to, to display hex dump in correct order
    // TODO: how to deal with big endian machines
    cout << std::hex << std::uppercase << setw(8) << setfill('0')
         << bswap_32(*(pbuf))
         << bswap_32(*(pbuf+1))
         << bswap_32(*(pbuf+2))
         << bswap_32(*(pbuf+3))
         << bswap_32(*(pbuf+4))
         << bswap_32(*(pbuf+5))
         << bswap_32(*(pbuf+6))
         << bswap_32(*(pbuf+7))
         << endl;
}

/**
 * @brief generates an SHA256 hash
 *
 * generates an SHA256 hash using openSSL
 *
 * @param[in]      input:   a const pointer to const block of data, usually a char array of which the hash is being generated
 * @param[in]      length:  the number of bytes the that input points to holds
 * @param[in,out]  hashStr: const pointer to an array of SHA256_DIGEST_LENGTH bytes that will receive the hash
 *
 * @return returns true if the hash has been generated successfully; returns false if input or hashStr is NULL or length==0; else: false
 */
bool generateSHA256(const void *const input, const size_t &length, char *const hashStr)
{
    if(!hashStr || !input || length==0)
    {
        return false;
    }

    SHA256_CTX hash;
    if(!SHA256_Init(&hash))
    {
        return false;
    }

    if(!SHA256_Update(&hash, input, length))
    {
        return false;
    }

    if(!SHA256_Final(reinterpret_cast<unsigned char*>(hashStr), &hash))
    {
        return false;
    }

    return true;
}

/**
 * @brief checks equality of two hashes
 *
 * calculates the SHA256 hash of 'password' and compares it
 * with the initial password hash
 *
 * @param[in]   password: a const string containing a guessed password
 *
 * @return returns true if hashes match; false if generation of hash failed or hashes not match
 */
bool checkPassword(const string &password)
{
#ifdef VERBOSE
    cout << "checking " << password << endl;
#endif // VERBOSE

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(password.c_str(), password.length(), bruteHash))
    {
        cerr << "Error when generating SHA256 from \"" << password << "\"" << endl;
        return false;
    }

    if (!memcmp(bruteHash, pwdHash, SHA256_DIGEST_LENGTH))
    {
        cout << "match [" << password << "]" << endl << "hash: " << endl;
        printSHAHash((unsigned int*)bruteHash);
        return true;
    }

    return false;
}

/**
 * @brief the main loop for a worker process
 *
 * continuously looks for incoming strings, generates the SHA
 * hash of it and checks if it matches the secret hash
 */
void worker()
{
    char buf[MaxChars];
    MPI_Status state;

    while(true)
    {
        // check for new msg
        MPI_Probe(MasterProcess, task, MPI_COMM_WORLD, &state);

        int len;
        // now check status to determine how many bytes were actually received
        MPI_Get_count(&state, MPI_BYTE, &len);

        // receive len bytes
        MPI_Recv(buf, len, MPI_BYTE, MasterProcess, task, MPI_COMM_WORLD, &state);

        string baseStr(buf, len);

        for(int i=0; i<SizeAlphabet; i++)
        {
            if(checkPassword(baseStr+alphabet[i]))
            {
                //success, tell master
                //MPI_Send(const_cast<char*>(baseStr+alphabet[i].c_str()), baseStr+alphabet[i].length(), MPI_CHAR, MasterProcess, success, MPI_COMM_WORLD);
                cout << "Password found: " << baseStr+alphabet[i] << endl;
                MPI_Abort(MPI_COMM_WORLD, 0);

                break;
            }
        }
    }
}
<commit_msg>receive MPI_ANY_TAG<commit_after>/**
 * Author: derselbst
 * Description: provides functions that are used by the worker processes to check whether a bruteforced string generated by the master process matches pwdHash
 */

#include <iostream>
#include <cstring> // memcmp()
#include <string>
#include <queue>
#include <limits>
#include <iomanip>
#include <openssl/sha.h>
#include <byteswap.h>
#include <mpi.h>

using namespace std;

#include "worker.h"
#include "master.h"
#include "alphabet.h"

// contains the hash of the unknown password
char pwdHash[SHA256_DIGEST_LENGTH];

// contains the hash of a bruteforced string
char bruteHash[SHA256_DIGEST_LENGTH];

// used when sending messages
enum MpiMsgTag
{
    task,
    success // hashes match, unused ATM
};

/**
 * @brief prints 32 bytes of memory
 *
 * prints a hex dump of 32 bytes of memory pointed to
 *
 * @param[in]   pbuf: pointer to some memory, usually containing an SHA256 hash
 */
void printSHAHash(const unsigned int *const pbuf)
{
    // byteswap the integer pointed to, to display hex dump in correct order
    // TODO: how to deal with big endian machines
    cout << std::hex << std::uppercase << setw(8) << setfill('0')
         << bswap_32(*(pbuf))
         << bswap_32(*(pbuf+1))
         << bswap_32(*(pbuf+2))
         << bswap_32(*(pbuf+3))
         << bswap_32(*(pbuf+4))
         << bswap_32(*(pbuf+5))
         << bswap_32(*(pbuf+6))
         << bswap_32(*(pbuf+7))
         << endl;
}

/**
 * @brief generates an SHA256 hash
 *
 * generates an SHA256 hash using openSSL
 *
 * @param[in]      input:   a const pointer to const block of data, usually a char array of which the hash is being generated
 * @param[in]      length:  the number of bytes the that input points to holds
 * @param[in,out]  hashStr: const pointer to an array of SHA256_DIGEST_LENGTH bytes that will receive the hash
 *
 * @return returns true if the hash has been generated successfully; returns false if input or hashStr is NULL or length==0; else: false
 */
bool generateSHA256(const void *const input, const size_t &length, char *const hashStr)
{
    if(!hashStr || !input || length==0)
    {
        return false;
    }

    SHA256_CTX hash;
    if(!SHA256_Init(&hash))
    {
        return false;
    }

    if(!SHA256_Update(&hash, input, length))
    {
        return false;
    }

    if(!SHA256_Final(reinterpret_cast<unsigned char*>(hashStr), &hash))
    {
        return false;
    }

    return true;
}

/**
 * @brief checks equality of two hashes
 *
 * calculates the SHA256 hash of 'password' and compares it
 * with the initial password hash
 *
 * @param[in]   password: a const string containing a guessed password
 *
 * @return returns true if hashes match; false if generation of hash failed or hashes not match
 */
bool checkPassword(const string &password)
{
#ifdef VERBOSE
    cout << "checking " << password << endl;
#endif // VERBOSE

    // generate sha hash from entered string and write it to pwdHash
    if(!generateSHA256(password.c_str(), password.length(), bruteHash))
    {
        cerr << "Error when generating SHA256 from \"" << password << "\"" << endl;
        return false;
    }

    if (!memcmp(bruteHash, pwdHash, SHA256_DIGEST_LENGTH))
    {
        cout << "match [" << password << "]" << endl << "hash: " << endl;
        printSHAHash((unsigned int*)bruteHash);
        return true;
    }

    return false;
}

/**
 * @brief the main loop for a worker process
 *
 * continuously looks for incoming strings, generates the SHA
 * hash of it and checks if it matches the secret hash
 */
void worker()
{
    char buf[MaxChars];
    MPI_Status state;

    while(true)
    {
        // check for new msg
        MPI_Probe(MasterProcess, MPI_ANY_TAG, MPI_COMM_WORLD, &state);

        int len;
        // now check status to determine how many bytes were actually received
        MPI_Get_count(&state, MPI_BYTE, &len);

        // receive len bytes
        MPI_Recv(buf, len, MPI_BYTE, MasterProcess, MPI_ANY_TAG, MPI_COMM_WORLD, &state);

        string baseStr(buf, len);

        for(int i=0; i<SizeAlphabet; i++)
        {
            if(checkPassword(baseStr+alphabet[i]))
            {
                //success, tell master
                //MPI_Send(const_cast<char*>(baseStr+alphabet[i].c_str()), baseStr+alphabet[i].length(), MPI_CHAR, MasterProcess, success, MPI_COMM_WORLD);
                cout << "Password found: " << baseStr+alphabet[i] << endl;
                MPI_Abort(MPI_COMM_WORLD, 0);

                break;
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>new macro for MC gen train, Pythia with shoving and flavour ropes<commit_after><|endoftext|>


<commit_before><commit_msg>Updated maximum histogram bucket for UseCountering of CSS properties.<commit_after><|endoftext|>


<commit_before>/**
 * @file head_finder.cpp
 * @author Chase Geigle
 */

#include <unordered_set>
#include <vector>

#include "logging/logger.h"
#include "meta.h"
#include "parser/trees/visitors/head_finder.h"
#include "parser/trees/internal_node.h"
#include "parser/trees/leaf_node.h"
#include "util/optional.h"

namespace meta
{
namespace parser
{

namespace
{

/**
 * A normal head rule following Collins' head finding algorithm.
 */
struct normal_head_rule : public head_rule
{
    template <class... Args>
    normal_head_rule(Args&&... args)
        : candidates_{{std::forward<Args>(args)...}}
    {
        // nothing
    }

    std::vector<class_label> candidates_;
};

/**
 * A head rule that starts its search from the leftmost child.
 */
struct head_initial : public normal_head_rule
{
    using normal_head_rule::normal_head_rule;

    uint64_t find_head(const internal_node& inode) const override
    {
        for (const auto& cand : candidates_)
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                auto child = inode.child(idx);
                if (child->category() == cand)
                    return idx;
            }
        }

        // no matches, use left most node
        return 0;
    }
};

/**
 * A head rule that starts its search from the rightmost child.
 */
struct head_final : public normal_head_rule
{
    using normal_head_rule::normal_head_rule;

    uint64_t find_head(const internal_node& inode) const override
    {
        for (const auto& cand : candidates_)
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                // iterate in reverse, from right to left
                auto ridx = inode.num_children() - 1 - idx;
                auto child = inode.child(ridx);
                if (child->category() == cand)
                    return ridx;
            }
        }

        // no matches, use right most node
        return inode.num_children() - 1;
    }
};

/**
 * The special case for noun phrases in Collins' head finding algorithm.
 * @see Collins' thesis, page 238-239
 */
struct head_np : public head_rule
{
    struct head_final_np
    {
        std::unordered_set<class_label> candidates_;

        util::optional<uint64_t> find_head(const internal_node& inode) const
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                auto ridx = inode.num_children() - 1 - idx;
                auto child = inode.child(ridx);
                if (candidates_.find(child->category()) != candidates_.end())
                    return {ridx};
            }

            return util::nullopt;
        }
    };

    struct head_initial_np
    {
        std::unordered_set<class_label> candidates_;

        util::optional<uint64_t> find_head(const internal_node& inode) const
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                auto child = inode.child(idx);
                if (candidates_.find(child->category()) != candidates_.end())
                    return {idx};
            }

            return util::nullopt;
        }
    };

    uint64_t find_head(const internal_node& inode) const override
    {
        head_final_np first_pass{{"NN"_cl, "NNP"_cl, "NNPS"_cl, "NNS"_cl,
                                  "NX"_cl, "POS"_cl, "JJR"_cl}};
        if (auto idx = first_pass.find_head(inode))
            return *idx;

        head_initial_np second_pass{{"NP"_cl}};
        if (auto idx = second_pass.find_head(inode))
            return *idx;

        head_final_np third_pass{{"$"_cl, "ADJP"_cl, "PRN"_cl}};
        if (auto idx = third_pass.find_head(inode))
            return *idx;

        head_final_np fourth_pass{{"CD"_cl}};
        if (auto idx = fourth_pass.find_head(inode))
            return *idx;

        head_final_np fifth_pass{{"JJ"_cl, "JJS"_cl, "RB"_cl, "QP"_cl}};
        if (auto idx = fifth_pass.find_head(inode))
            return *idx;

        // no matches, just use last child
        return inode.num_children() - 1;
    }
};
}

head_finder::head_finder()
{
    /// @see: http://www.cs.columbia.edu/~mcollins/papers/heads
    /// @see Collins' thesis, page 240
    rules_["ADJP"_cl] = make_unique<head_initial>(
        "NNS"_cl, "QP"_cl, "NN"_cl, "$"_cl, "ADVP"_cl, "JJ"_cl, "VBN"_cl,
        "VBG"_cl, "ADJP"_cl, "JJR"_cl, "NP"_cl, "JJS"_cl, "DT"_cl, "FW"_cl,
        "RBR"_cl, "RBS"_cl, "SBAR"_cl, "RB"_cl);

    rules_["ADVP"_cl] = make_unique<head_final>(
        "RB"_cl, "RBR"_cl, "RBS"_cl, "FW"_cl, "ADVP"_cl, "TO"_cl, "CD"_cl,
        "JJR"_cl, "JJ"_cl, "IN"_cl, "NP"_cl, "JJS"_cl, "NN"_cl);

    rules_["CONJP"_cl] = make_unique<head_final>("CC"_cl, "RB"_cl, "IN"_cl);

    rules_["FRAG"_cl] = make_unique<head_final>();

    rules_["INTJ"_cl] = make_unique<head_initial>();

    rules_["LST"_cl] = make_unique<head_final>("LS"_cl, ":"_cl);

    rules_["NAC"_cl] = make_unique<head_initial>(
        "NN"_cl, "NNS"_cl, "NNP"_cl, "NNPS"_cl, "NP"_cl, "NAC"_cl, "EX"_cl,
        "$"_cl, "CD"_cl, "QP"_cl, "PRP"_cl, "VBG"_cl, "JJ"_cl, "JJS"_cl,
        "JJR"_cl, "ADJP"_cl, "FW"_cl);

    rules_["PP"_cl] = make_unique<head_final>("IN"_cl, "TO"_cl, "VBG"_cl,
                                              "VBN"_cl, "RP"_cl, "FW"_cl);

    rules_["PRN"_cl] = make_unique<head_initial>();

    rules_["PRT"_cl] = make_unique<head_final>("RP"_cl);

    rules_["QP"_cl] = make_unique<head_initial>(
        "$"_cl, "IN"_cl, "NNS"_cl, "NN"_cl, "JJ"_cl, "RB"_cl, "DT"_cl, "CD"_cl,
        "NCD"_cl, "QP"_cl, "JJR"_cl, "JJS"_cl);

    rules_["RRC"_cl] = make_unique<head_final>("VP"_cl, "NP"_cl, "ADVP"_cl,
                                               "ADJP"_cl, "PP"_cl);

    rules_["S"_cl]
        = make_unique<head_initial>("TO"_cl, "IN"_cl, "VP"_cl, "S"_cl,
                                    "SBAR"_cl, "ADJP"_cl, "UCP"_cl, "NP"_cl);

    rules_["SBAR"_cl] = make_unique<head_initial>(
        "WHNP"_cl, "WHPP"_cl, "WHADVP"_cl, "WHADJP"_cl, "IN"_cl, "DT"_cl,
        "S"_cl, "SQ"_cl, "SINV"_cl, "SBAR"_cl, "FRAG"_cl);

    rules_["SBARQ"_cl] = make_unique<head_initial>("SQ"_cl, "S"_cl, "SINV"_cl,
                                                   "SBARQ"_cl, "FRAG"_cl);

    rules_["SINV"_cl] = make_unique<head_initial>(
        "VBZ"_cl, "VBD"_cl, "VBP"_cl, "VB"_cl, "MD"_cl, "VP"_cl, "S"_cl,
        "SINV"_cl, "ADJP"_cl, "NP"_cl);

    rules_["SQ"_cl] = make_unique<head_initial>(
        "VBZ"_cl, "VBD"_cl, "VBP"_cl, "VB"_cl, "MD"_cl, "VP"_cl, "SQ"_cl);

    rules_["UCP"_cl] = make_unique<head_final>();

    rules_["VP"_cl] = make_unique<head_initial>(
        "TO"_cl, "VBD"_cl, "VBN"_cl, "MD"_cl, "VBZ"_cl, "VB"_cl, "VBG"_cl,
        "VBP"_cl, "VP"_cl, "ADJP"_cl, "NN"_cl, "NNS"_cl, "NP"_cl);

    rules_["WHADJP"_cl]
        = make_unique<head_initial>("CC"_cl, "WRB"_cl, "JJ"_cl, "ADJP"_cl);

    rules_["WHADVP"_cl] = make_unique<head_final>("CC"_cl, "WRB"_cl);

    rules_["WHNP"_cl] = make_unique<head_initial>(
        "WDT"_cl, "WP"_cl, "WP$"_cl, "WHADJP"_cl, "WHPP"_cl, "WHNP"_cl);

    rules_["WHPP"_cl] = make_unique<head_final>("IN"_cl, "TO"_cl, "FW"_cl);

    rules_["NP"_cl] = make_unique<head_np>();

    rules_["NX"_cl]
        = make_unique<head_initial>(); // not present in collins' thesis...

    rules_["X"_cl]
        = make_unique<head_final>(); // not present in collins' thesis...

    rules_["ROOT"_cl] = make_unique<head_initial>();
}

head_finder::head_finder(rule_table&& table) : rules_{std::move(table)}
{
    // nothing
}

void head_finder::operator()(leaf_node&)
{
    // head annotations are only populated for internal nodes; leaf nodes
    // are the trivial case
    return;
}

void head_finder::operator()(internal_node& inode)
{
    // recurse, as we need the head annotations of all child nodes first
    inode.each_child([&](node* child)
                     {
                         child->accept(*this);
                     });

    if (rules_.find(inode.category()) == rules_.end())
        LOG(fatal) << "No rule found for category " << inode.category()
                   << " in rule table" << ENDLG;

    // run the head finder for the syntactic category of the current node
    auto idx = rules_.at(inode.category())->find_head(inode);
    inode.head(inode.child(idx));

    // clean up stage for handling coordinating clauses
    if (idx > 1 && inode.child(idx - 1)->category() == class_label{"CC"})
        inode.head(inode.child(idx - 2));
}
}
}
<commit_msg>Appease the compilers when in release mode.<commit_after>/**
 * @file head_finder.cpp
 * @author Chase Geigle
 */

#include <unordered_set>
#include <vector>

#include "logging/logger.h"
#include "meta.h"
#include "parser/trees/visitors/head_finder.h"
#include "parser/trees/internal_node.h"
#include "parser/trees/leaf_node.h"
#include "util/optional.h"

namespace meta
{
namespace parser
{

namespace
{

/**
 * A normal head rule following Collins' head finding algorithm.
 */
struct normal_head_rule : public head_rule
{
    template <class... Args>
    normal_head_rule(Args&&... args)
        : candidates_({std::forward<Args>(args)...})
    {
        // nothing
    }

    std::vector<class_label> candidates_;
};

/**
 * A head rule that starts its search from the leftmost child.
 */
struct head_initial : public normal_head_rule
{
    using normal_head_rule::normal_head_rule;

    uint64_t find_head(const internal_node& inode) const override
    {
        for (const auto& cand : candidates_)
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                auto child = inode.child(idx);
                if (child->category() == cand)
                    return idx;
            }
        }

        // no matches, use left most node
        return 0;
    }
};

/**
 * A head rule that starts its search from the rightmost child.
 */
struct head_final : public normal_head_rule
{
    using normal_head_rule::normal_head_rule;

    uint64_t find_head(const internal_node& inode) const override
    {
        for (const auto& cand : candidates_)
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                // iterate in reverse, from right to left
                auto ridx = inode.num_children() - 1 - idx;
                auto child = inode.child(ridx);
                if (child->category() == cand)
                    return ridx;
            }
        }

        // no matches, use right most node
        return inode.num_children() - 1;
    }
};

/**
 * The special case for noun phrases in Collins' head finding algorithm.
 * @see Collins' thesis, page 238-239
 */
struct head_np : public head_rule
{
    struct head_final_np
    {
        std::unordered_set<class_label> candidates_;

        util::optional<uint64_t> find_head(const internal_node& inode) const
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                auto ridx = inode.num_children() - 1 - idx;
                auto child = inode.child(ridx);
                if (candidates_.find(child->category()) != candidates_.end())
                    return {ridx};
            }

            return util::nullopt;
        }
    };

    struct head_initial_np
    {
        std::unordered_set<class_label> candidates_;

        util::optional<uint64_t> find_head(const internal_node& inode) const
        {
            for (uint64_t idx = 0; idx < inode.num_children(); ++idx)
            {
                auto child = inode.child(idx);
                if (candidates_.find(child->category()) != candidates_.end())
                    return {idx};
            }

            return util::nullopt;
        }
    };

    uint64_t find_head(const internal_node& inode) const override
    {
        head_final_np first_pass{{"NN"_cl, "NNP"_cl, "NNPS"_cl, "NNS"_cl,
                                  "NX"_cl, "POS"_cl, "JJR"_cl}};
        if (auto idx = first_pass.find_head(inode))
            return *idx;

        head_initial_np second_pass{{"NP"_cl}};
        if (auto idx = second_pass.find_head(inode))
            return *idx;

        head_final_np third_pass{{"$"_cl, "ADJP"_cl, "PRN"_cl}};
        if (auto idx = third_pass.find_head(inode))
            return *idx;

        head_final_np fourth_pass{{"CD"_cl}};
        if (auto idx = fourth_pass.find_head(inode))
            return *idx;

        head_final_np fifth_pass{{"JJ"_cl, "JJS"_cl, "RB"_cl, "QP"_cl}};
        if (auto idx = fifth_pass.find_head(inode))
            return *idx;

        // no matches, just use last child
        return inode.num_children() - 1;
    }
};
}

head_finder::head_finder()
{
    /// @see: http://www.cs.columbia.edu/~mcollins/papers/heads
    /// @see Collins' thesis, page 240
    rules_["ADJP"_cl] = make_unique<head_initial>(
        "NNS"_cl, "QP"_cl, "NN"_cl, "$"_cl, "ADVP"_cl, "JJ"_cl, "VBN"_cl,
        "VBG"_cl, "ADJP"_cl, "JJR"_cl, "NP"_cl, "JJS"_cl, "DT"_cl, "FW"_cl,
        "RBR"_cl, "RBS"_cl, "SBAR"_cl, "RB"_cl);

    rules_["ADVP"_cl] = make_unique<head_final>(
        "RB"_cl, "RBR"_cl, "RBS"_cl, "FW"_cl, "ADVP"_cl, "TO"_cl, "CD"_cl,
        "JJR"_cl, "JJ"_cl, "IN"_cl, "NP"_cl, "JJS"_cl, "NN"_cl);

    rules_["CONJP"_cl] = make_unique<head_final>("CC"_cl, "RB"_cl, "IN"_cl);

    rules_["FRAG"_cl] = make_unique<head_final>();

    rules_["INTJ"_cl] = make_unique<head_initial>();

    rules_["LST"_cl] = make_unique<head_final>("LS"_cl, ":"_cl);

    rules_["NAC"_cl] = make_unique<head_initial>(
        "NN"_cl, "NNS"_cl, "NNP"_cl, "NNPS"_cl, "NP"_cl, "NAC"_cl, "EX"_cl,
        "$"_cl, "CD"_cl, "QP"_cl, "PRP"_cl, "VBG"_cl, "JJ"_cl, "JJS"_cl,
        "JJR"_cl, "ADJP"_cl, "FW"_cl);

    rules_["PP"_cl] = make_unique<head_final>("IN"_cl, "TO"_cl, "VBG"_cl,
                                              "VBN"_cl, "RP"_cl, "FW"_cl);

    rules_["PRN"_cl] = make_unique<head_initial>();

    rules_["PRT"_cl] = make_unique<head_final>("RP"_cl);

    rules_["QP"_cl] = make_unique<head_initial>(
        "$"_cl, "IN"_cl, "NNS"_cl, "NN"_cl, "JJ"_cl, "RB"_cl, "DT"_cl, "CD"_cl,
        "NCD"_cl, "QP"_cl, "JJR"_cl, "JJS"_cl);

    rules_["RRC"_cl] = make_unique<head_final>("VP"_cl, "NP"_cl, "ADVP"_cl,
                                               "ADJP"_cl, "PP"_cl);

    rules_["S"_cl]
        = make_unique<head_initial>("TO"_cl, "IN"_cl, "VP"_cl, "S"_cl,
                                    "SBAR"_cl, "ADJP"_cl, "UCP"_cl, "NP"_cl);

    rules_["SBAR"_cl] = make_unique<head_initial>(
        "WHNP"_cl, "WHPP"_cl, "WHADVP"_cl, "WHADJP"_cl, "IN"_cl, "DT"_cl,
        "S"_cl, "SQ"_cl, "SINV"_cl, "SBAR"_cl, "FRAG"_cl);

    rules_["SBARQ"_cl] = make_unique<head_initial>("SQ"_cl, "S"_cl, "SINV"_cl,
                                                   "SBARQ"_cl, "FRAG"_cl);

    rules_["SINV"_cl] = make_unique<head_initial>(
        "VBZ"_cl, "VBD"_cl, "VBP"_cl, "VB"_cl, "MD"_cl, "VP"_cl, "S"_cl,
        "SINV"_cl, "ADJP"_cl, "NP"_cl);

    rules_["SQ"_cl] = make_unique<head_initial>(
        "VBZ"_cl, "VBD"_cl, "VBP"_cl, "VB"_cl, "MD"_cl, "VP"_cl, "SQ"_cl);

    rules_["UCP"_cl] = make_unique<head_final>();

    rules_["VP"_cl] = make_unique<head_initial>(
        "TO"_cl, "VBD"_cl, "VBN"_cl, "MD"_cl, "VBZ"_cl, "VB"_cl, "VBG"_cl,
        "VBP"_cl, "VP"_cl, "ADJP"_cl, "NN"_cl, "NNS"_cl, "NP"_cl);

    rules_["WHADJP"_cl]
        = make_unique<head_initial>("CC"_cl, "WRB"_cl, "JJ"_cl, "ADJP"_cl);

    rules_["WHADVP"_cl] = make_unique<head_final>("CC"_cl, "WRB"_cl);

    rules_["WHNP"_cl] = make_unique<head_initial>(
        "WDT"_cl, "WP"_cl, "WP$"_cl, "WHADJP"_cl, "WHPP"_cl, "WHNP"_cl);

    rules_["WHPP"_cl] = make_unique<head_final>("IN"_cl, "TO"_cl, "FW"_cl);

    rules_["NP"_cl] = make_unique<head_np>();

    rules_["NX"_cl]
        = make_unique<head_initial>(); // not present in collins' thesis...

    rules_["X"_cl]
        = make_unique<head_final>(); // not present in collins' thesis...

    rules_["ROOT"_cl] = make_unique<head_initial>();
}

head_finder::head_finder(rule_table&& table) : rules_{std::move(table)}
{
    // nothing
}

void head_finder::operator()(leaf_node&)
{
    // head annotations are only populated for internal nodes; leaf nodes
    // are the trivial case
    return;
}

void head_finder::operator()(internal_node& inode)
{
    // recurse, as we need the head annotations of all child nodes first
    inode.each_child([&](node* child)
                     {
                         child->accept(*this);
                     });

    if (rules_.find(inode.category()) == rules_.end())
        LOG(fatal) << "No rule found for category " << inode.category()
                   << " in rule table" << ENDLG;

    // run the head finder for the syntactic category of the current node
    auto idx = rules_.at(inode.category())->find_head(inode);
    inode.head(inode.child(idx));

    // clean up stage for handling coordinating clauses
    if (idx > 1 && inode.child(idx - 1)->category() == class_label{"CC"})
        inode.head(inode.child(idx - 2));
}
}
}
<|endoftext|>


<commit_before>/*
 * This file is part of the UnTech Editor Suite.
 * Copyright (c) 2016 - 2018, Marcus Rowe <undisbeliever@gmail.com>.
 * Distributed under The MIT License: https://opensource.org/licenses/MIT
 */

#pragma once
#include "models/common/vectorset.h"
#include "models/metasprite/metasprite.h"
#include "models/metasprite/spriteimporter.h"
#include <cstring>
#include <iomanip>
#include <map>
#include <sstream>
#include <stdexcept>

namespace UnTech {
namespace MetaSprite {
namespace Utsi2UtmsPrivate {

namespace MS = UnTech::MetaSprite::MetaSprite;
namespace SI = UnTech::MetaSprite::SpriteImporter;

class PaletteConverter {
    const SI::FrameSet& siFrameSet;
    const Image& image;
    MS::FrameSet& msFrameSet;
    ErrorList& errorList;

    // Faster than std::unordered_map, only contains a max of 16 elements
    std::map<rgba, unsigned> _colorMap;

public:
    PaletteConverter(const SI::FrameSet& siFrameSet,
                     const Image& image,
                     MS::FrameSet& msFrameSet,
                     ErrorList& errorList)
        : siFrameSet(siFrameSet)
        , image(image)
        , msFrameSet(msFrameSet)
        , errorList(errorList)
        , _colorMap()
    {
    }

    const auto& colorMap() const { return _colorMap; }

    void process()
    {
        try {
            if (siFrameSet.palette.usesUserSuppliedPalette()) {
                buildUserSuppliedPalettes();
            }
            else {
                buildAutomaticPalette();
            }
        }
        catch (const std::exception& ex) {
            errorList.addError(siFrameSet, ex.what());
        }
    }

private:
    vectorset<rgba> getColorsFromImage() const
    {
        assert(image.empty() == false);

        vectorset<rgba> colors;

        for (const auto& siFrameIt : siFrameSet.frames) {
            const SI::Frame& siFrame = siFrameIt.second;

            for (const SI::FrameObject& obj : siFrame.objects) {
                unsigned lx = siFrame.location.aabb.x + obj.location.x;
                unsigned ly = siFrame.location.aabb.y + obj.location.y;

                for (unsigned y = 0; y < obj.sizePx(); y++) {
                    const rgba* p = image.scanline(ly + y) + lx;

                    for (unsigned x = 0; x < obj.sizePx(); x++) {
                        colors.insert(*p++);
                    }
                }

                if (colors.size() > (PALETTE_COLORS)) {
                    throw std::runtime_error("Too many colors, expected a max of 16");
                }
            }
        }

        // remove transparent from colors list
        auto tIt = colors.find(siFrameSet.transparentColor);
        if (tIt != colors.end()) {
            colors.erase(tIt);
        }
        else {
            errorList.addWarning(siFrameSet, "Transparent color is not in frame objects");
        }

        return colors;
    }

    inline void buildUserSuppliedPalettes()
    {
        validateUserSuppliedPalettes();

        const unsigned colorSize = siFrameSet.palette.colorSize;

        for (unsigned pal = 0; pal < siFrameSet.palette.nPalettes; pal++) {
            const unsigned yPos = image.size().height - pal * colorSize - 1;

            msFrameSet.palettes.emplace_back();
            Snes::Palette4bpp& palette = msFrameSet.palettes.back();

            for (unsigned i = 0; i < PALETTE_COLORS; i++) {
                const rgba c = image.getPixel(i * colorSize, yPos);

                palette.color(i).setRgb(c);

                if (pal == 0) {
                    _colorMap.insert({ c, i });
                }
            }
        }
    }

    inline void validateUserSuppliedPalettes() const
    {
        const usize imageSize = image.size();
        const usize paletteSize = siFrameSet.palette.paletteSize();

        if (imageSize.width < paletteSize.width || imageSize.height < paletteSize.height) {
            throw std::runtime_error("Cannot load custom palette, image is too small");
        }

        for (unsigned pal = 0; pal < siFrameSet.palette.nPalettes; pal++) {
            validateUserSuppliedPalette(pal);
        }

        validateFirstUserSuppliedPalette();
    }

    inline void validateUserSuppliedPalette(unsigned pal) const
    {
        const unsigned colorSize = siFrameSet.palette.colorSize;
        const unsigned yPos = image.size().height - pal * colorSize - 1;

        const rgba* scanline = image.scanline(yPos);

        // ensure the scanlines of the palette equal

        for (unsigned l = 1; l < colorSize; l++) {
            const rgba* linetoTest = image.scanline(yPos - l);

            if (std::memcmp(scanline, linetoTest, sizeof(rgba) * colorSize * PALETTE_COLORS) != 0) {
                throw std::runtime_error("Custom Palette is invalid A");
            }
        }

        // ensure each of the palette colors are equally colored squares
        for (unsigned c = 0; c < PALETTE_COLORS; c++) {
            const rgba* imgBits = scanline + c * colorSize;

            for (unsigned i = 1; i < colorSize; i++) {
                if (imgBits[0] != imgBits[i]) {
                    throw std::runtime_error("Custom Palette is invalid");
                }
            }
        }

        // ensure first color is transparent
        if (scanline[0] != siFrameSet.transparentColor) {
            throw std::runtime_error("First color of custom palette " + std::to_string(pal)
                                     + " is not the transparent color");
        }
    }

    inline void validateFirstUserSuppliedPalette() const
    {
        const unsigned colorSize = siFrameSet.palette.colorSize;

        vectorset<rgba> colorSet = getColorsFromImage();
        const rgba* scanline = image.scanline(image.size().height - 1);

        for (unsigned i = 0; i < PALETTE_COLORS; i++) {
            const rgba c = scanline[i * colorSize];
            colorSet.erase(c);
        }

        if (colorSet.size() > 0) {
            std::stringstream out;
            out << "Palette 0 is invalid (missing";

            for (const rgba& c : colorSet) {
                out << " " << std::hex << std::setfill('0') << std::setw(6) << c.rgb();
            }
            out << ")";

            throw std::runtime_error(out.str());
        }
    }

    inline void buildAutomaticPalette()
    {
        vectorset<rgba> colors = getColorsFromImage();
        assert(colors.size() <= PALETTE_COLORS - 1);

        // Store palette in MetaSprite
        msFrameSet.palettes.emplace_back();
        Snes::Palette4bpp& palette = msFrameSet.palettes.back();

        _colorMap.insert({ siFrameSet.transparentColor, 0 });
        palette.color(0).setRgb(siFrameSet.transparentColor);

        int i = 1;
        for (auto& c : colors) {
            _colorMap.insert({ c, i });
            palette.color(i).setRgb(c);
            i++;
        }
    }
};
}
}
}
<commit_msg>Fix crash in utsi2utms palette converter<commit_after>/*
 * This file is part of the UnTech Editor Suite.
 * Copyright (c) 2016 - 2018, Marcus Rowe <undisbeliever@gmail.com>.
 * Distributed under The MIT License: https://opensource.org/licenses/MIT
 */

#pragma once
#include "models/common/vectorset.h"
#include "models/metasprite/metasprite.h"
#include "models/metasprite/spriteimporter.h"
#include <cstring>
#include <iomanip>
#include <map>
#include <sstream>
#include <stdexcept>

namespace UnTech {
namespace MetaSprite {
namespace Utsi2UtmsPrivate {

namespace MS = UnTech::MetaSprite::MetaSprite;
namespace SI = UnTech::MetaSprite::SpriteImporter;

class PaletteConverter {
    const SI::FrameSet& siFrameSet;
    const Image& image;
    MS::FrameSet& msFrameSet;
    ErrorList& errorList;

    // Faster than std::unordered_map, only contains a max of 16 elements
    std::map<rgba, unsigned> _colorMap;

public:
    PaletteConverter(const SI::FrameSet& siFrameSet,
                     const Image& image,
                     MS::FrameSet& msFrameSet,
                     ErrorList& errorList)
        : siFrameSet(siFrameSet)
        , image(image)
        , msFrameSet(msFrameSet)
        , errorList(errorList)
        , _colorMap()
    {
    }

    const auto& colorMap() const { return _colorMap; }

    void process()
    {
        try {
            if (siFrameSet.palette.usesUserSuppliedPalette()) {
                buildUserSuppliedPalettes();
            }
            else {
                buildAutomaticPalette();
            }
        }
        catch (const std::exception& ex) {
            errorList.addError(siFrameSet, ex.what());
        }
    }

private:
    vectorset<rgba> getColorsFromImage() const
    {
        assert(image.empty() == false);

        vectorset<rgba> colors;

        for (const auto& siFrameIt : siFrameSet.frames) {
            const SI::Frame& siFrame = siFrameIt.second;

            for (const SI::FrameObject& obj : siFrame.objects) {
                unsigned lx = siFrame.location.aabb.x + obj.location.x;
                unsigned ly = siFrame.location.aabb.y + obj.location.y;

                for (unsigned y = 0; y < obj.sizePx(); y++) {
                    const rgba* p = image.scanline(ly + y) + lx;

                    for (unsigned x = 0; x < obj.sizePx(); x++) {
                        const bool newColor = colors.insert(*p++);
                        if (newColor) {
                            if (colors.size() > PALETTE_COLORS) {
                                throw std::runtime_error("Too many colors, expected a maximum of 16 colors");
                            }
                        }
                    }
                }
            }
        }

        // remove transparent from colors list
        auto tIt = colors.find(siFrameSet.transparentColor);
        if (tIt != colors.end()) {
            colors.erase(tIt);
        }
        else {
            errorList.addWarning(siFrameSet, "Transparent color is not in frame objects");

            if (colors.size() > (PALETTE_COLORS - 1)) {
                throw std::runtime_error("Too many colors, expected a maximum of 15 colors after removing transparency");
            }
        }

        return colors;
    }

    inline void buildUserSuppliedPalettes()
    {
        validateUserSuppliedPalettes();

        const unsigned colorSize = siFrameSet.palette.colorSize;

        for (unsigned pal = 0; pal < siFrameSet.palette.nPalettes; pal++) {
            const unsigned yPos = image.size().height - pal * colorSize - 1;

            msFrameSet.palettes.emplace_back();
            Snes::Palette4bpp& palette = msFrameSet.palettes.back();

            for (unsigned i = 0; i < PALETTE_COLORS; i++) {
                const rgba c = image.getPixel(i * colorSize, yPos);

                palette.color(i).setRgb(c);

                if (pal == 0) {
                    _colorMap.insert({ c, i });
                }
            }
        }
    }

    inline void validateUserSuppliedPalettes() const
    {
        const usize imageSize = image.size();
        const usize paletteSize = siFrameSet.palette.paletteSize();

        if (imageSize.width < paletteSize.width || imageSize.height < paletteSize.height) {
            throw std::runtime_error("Cannot load custom palette, image is too small");
        }

        for (unsigned pal = 0; pal < siFrameSet.palette.nPalettes; pal++) {
            validateUserSuppliedPalette(pal);
        }

        validateFirstUserSuppliedPalette();
    }

    inline void validateUserSuppliedPalette(unsigned pal) const
    {
        const unsigned colorSize = siFrameSet.palette.colorSize;
        const unsigned yPos = image.size().height - pal * colorSize - 1;

        const rgba* scanline = image.scanline(yPos);

        // ensure the scanlines of the palette equal

        for (unsigned l = 1; l < colorSize; l++) {
            const rgba* linetoTest = image.scanline(yPos - l);

            if (std::memcmp(scanline, linetoTest, sizeof(rgba) * colorSize * PALETTE_COLORS) != 0) {
                throw std::runtime_error("Custom Palette is invalid A");
            }
        }

        // ensure each of the palette colors are equally colored squares
        for (unsigned c = 0; c < PALETTE_COLORS; c++) {
            const rgba* imgBits = scanline + c * colorSize;

            for (unsigned i = 1; i < colorSize; i++) {
                if (imgBits[0] != imgBits[i]) {
                    throw std::runtime_error("Custom Palette is invalid");
                }
            }
        }

        // ensure first color is transparent
        if (scanline[0] != siFrameSet.transparentColor) {
            throw std::runtime_error("First color of custom palette " + std::to_string(pal)
                                     + " is not the transparent color");
        }
    }

    inline void validateFirstUserSuppliedPalette() const
    {
        const unsigned colorSize = siFrameSet.palette.colorSize;

        vectorset<rgba> colorSet = getColorsFromImage();
        assert(colorSet.size() <= PALETTE_COLORS - 1);

        const rgba* scanline = image.scanline(image.size().height - 1);

        for (unsigned i = 0; i < PALETTE_COLORS; i++) {
            const rgba c = scanline[i * colorSize];
            colorSet.erase(c);
        }

        if (colorSet.size() > 0) {
            std::stringstream out;
            out << "Palette 0 is invalid (missing";

            for (const rgba& c : colorSet) {
                out << " " << std::hex << std::setfill('0') << std::setw(6) << c.rgb();
            }
            out << ")";

            throw std::runtime_error(out.str());
        }
    }

    inline void buildAutomaticPalette()
    {
        vectorset<rgba> colors = getColorsFromImage();
        assert(colors.size() <= PALETTE_COLORS - 1);

        // Store palette in MetaSprite
        msFrameSet.palettes.emplace_back();
        Snes::Palette4bpp& palette = msFrameSet.palettes.back();

        _colorMap.insert({ siFrameSet.transparentColor, 0 });
        palette.color(0).setRgb(siFrameSet.transparentColor);

        int i = 1;
        for (auto& c : colors) {
            _colorMap.insert({ c, i });
            palette.color(i).setRgb(c);
            i++;
        }
    }
};
}
}
}
<|endoftext|>


<commit_before>extern "C" {

#include "halide_hexagon_remote.h"
#include <sys/mman.h>
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>

#define FARF_LOW 1
#include "HAP_farf.h"

}

#include "../HalideRuntime.h"

void halide_print(void *user_context, const char *str) {
    FARF(LOW, "%s", str);
}

void halide_error(void *user_context, const char *str) {
    halide_print(user_context, str);
}

void *halide_malloc(void *user_context, size_t x) {
    // Allocate enough space for aligning the pointer we return.
    const size_t alignment = 128;
    void *orig = malloc(x + alignment);
    if (orig == NULL) {
        // Will result in a failed assertion and a call to halide_error
        return NULL;
    }
    // We want to store the original pointer prior to the pointer we return.
    void *ptr = (void *)(((size_t)orig + alignment + sizeof(void*) - 1) & ~(alignment - 1));
    ((void **)ptr)[-1] = orig;
    return ptr;
}

void halide_free(void *user_context, void *ptr) {
    free(((void**)ptr)[-1]);
}

int halide_do_task(void *user_context, halide_task_t f, int idx,
                   uint8_t *closure) {
    return f(user_context, idx, closure);
}

int halide_do_par_for(void *user_context, halide_task_t f,
                      int min, int size, uint8_t *closure) {
    for (int x = min; x < min + size; x++) {
        int result = halide_do_task(user_context, f, x, closure);
        if (result) {
            return result;
        }
    }
    return 0;
}

static const int alignment = 4096;

extern "C" {

int halide_hexagon_remote_initialize_kernels(const unsigned char *code, int codeLen, int init_runtime_offset,
                                             halide_hexagon_remote_uintptr_t *module_ptr) {
    // Map some memory for the code and copy it in.
    int aligned_codeLen = (codeLen + alignment - 1) & ~(alignment - 1);
    void *executable = mmap(0, aligned_codeLen, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
    if (executable == MAP_FAILED) {
        return -1;
    }
    memcpy(executable, code, codeLen);

    // Change memory to be executable (but not writable).
    if (mprotect(executable, aligned_codeLen, PROT_READ | PROT_EXEC) < 0) {
        munmap(executable, aligned_codeLen);
        return -1;
    }

    // Initialize the runtime. The Hexagon runtime can't call any
    // system functions (because we can't link them), so we put all
    // the implementations that need to do so here, and pass poiners
    // to them in here.
    typedef int (*init_runtime_t)(halide_malloc_t user_malloc,
                                  halide_free_t custom_free,
                                  halide_print_t print,
                                  halide_error_handler_t error_handler,
                                  halide_do_par_for_t do_par_for,
                                  halide_do_task_t do_task);
    init_runtime_t init_runtime = (init_runtime_t)((char *)executable + init_runtime_offset);
    int result = init_runtime(halide_malloc,
                              halide_free,
                              halide_print,
                              halide_error,
                              halide_do_par_for,
                              halide_do_task);
    if (result != 0) {
        munmap(executable, aligned_codeLen);
        return result;
    }

    *module_ptr = (halide_hexagon_remote_uintptr_t)executable;
    return 0;
}

int halide_hexagon_remote_run(halide_hexagon_remote_uintptr_t module_ptr, int offset,
                              const halide_hexagon_remote_buffer *arg_ptrs, int arg_ptrsLen,
                              halide_hexagon_remote_buffer *outputs, int outputsLen) {
    // Get a pointer to the argv version of the pipeline.
    typedef int (*pipeline_argv_t)(void **);
    pipeline_argv_t pipeline = (pipeline_argv_t)(module_ptr + offset);

    // Construct a list of arguments.
    void **args = (void **)__builtin_alloca((arg_ptrsLen + outputsLen) * sizeof(void *));
    for (int i = 0; i < arg_ptrsLen; i++) {
        args[i] = arg_ptrs[i].data;
    }
    for (int i = 0; i < outputsLen; i++) {
        args[i + arg_ptrsLen] = outputs[i].data;
    }

    // Call the pipeline and return the result.
    return pipeline(args);
}

int halide_hexagon_remote_release_kernels(halide_hexagon_remote_uintptr_t module_ptr, int codeLen) {
    void *executable = (void *)module_ptr;
    codeLen = (codeLen + alignment - 1) & (alignment - 1);
    munmap(executable, codeLen);
    return 0;
}

}  // extern "C"
<commit_msg>Reduced confusion between two alignment constants.<commit_after>extern "C" {

#include "halide_hexagon_remote.h"
#include <sys/mman.h>
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>

#define FARF_LOW 1
#include "HAP_farf.h"

}

#include "../HalideRuntime.h"

void halide_print(void *user_context, const char *str) {
    FARF(LOW, "%s", str);
}

void halide_error(void *user_context, const char *str) {
    halide_print(user_context, str);
}

void *halide_malloc(void *user_context, size_t x) {
    // Allocate enough space for aligning the pointer we return.
    const size_t alignment = 128;
    void *orig = malloc(x + alignment);
    if (orig == NULL) {
        // Will result in a failed assertion and a call to halide_error
        return NULL;
    }
    // We want to store the original pointer prior to the pointer we return.
    void *ptr = (void *)(((size_t)orig + alignment + sizeof(void*) - 1) & ~(alignment - 1));
    ((void **)ptr)[-1] = orig;
    return ptr;
}

void halide_free(void *user_context, void *ptr) {
    free(((void**)ptr)[-1]);
}

int halide_do_task(void *user_context, halide_task_t f, int idx,
                   uint8_t *closure) {
    return f(user_context, idx, closure);
}

int halide_do_par_for(void *user_context, halide_task_t f,
                      int min, int size, uint8_t *closure) {
    for (int x = min; x < min + size; x++) {
        int result = halide_do_task(user_context, f, x, closure);
        if (result) {
            return result;
        }
    }
    return 0;
}

extern "C" {

const int map_alignment = 4096;

int halide_hexagon_remote_initialize_kernels(const unsigned char *code, int codeLen, int init_runtime_offset,
                                             halide_hexagon_remote_uintptr_t *module_ptr) {
    // Map some memory for the code and copy it in.
    int aligned_codeLen = (codeLen + map_alignment - 1) & ~(map_alignment - 1);
    void *executable = mmap(0, aligned_codeLen, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
    if (executable == MAP_FAILED) {
        return -1;
    }
    memcpy(executable, code, codeLen);

    // Change memory to be executable (but not writable).
    if (mprotect(executable, aligned_codeLen, PROT_READ | PROT_EXEC) < 0) {
        munmap(executable, aligned_codeLen);
        return -1;
    }

    // Initialize the runtime. The Hexagon runtime can't call any
    // system functions (because we can't link them), so we put all
    // the implementations that need to do so here, and pass poiners
    // to them in here.
    typedef int (*init_runtime_t)(halide_malloc_t user_malloc,
                                  halide_free_t custom_free,
                                  halide_print_t print,
                                  halide_error_handler_t error_handler,
                                  halide_do_par_for_t do_par_for,
                                  halide_do_task_t do_task);
    init_runtime_t init_runtime = (init_runtime_t)((char *)executable + init_runtime_offset);
    int result = init_runtime(halide_malloc,
                              halide_free,
                              halide_print,
                              halide_error,
                              halide_do_par_for,
                              halide_do_task);
    if (result != 0) {
        munmap(executable, aligned_codeLen);
        return result;
    }

    *module_ptr = (halide_hexagon_remote_uintptr_t)executable;
    return 0;
}

int halide_hexagon_remote_run(halide_hexagon_remote_uintptr_t module_ptr, int offset,
                              const halide_hexagon_remote_buffer *arg_ptrs, int arg_ptrsLen,
                              halide_hexagon_remote_buffer *outputs, int outputsLen) {
    // Get a pointer to the argv version of the pipeline.
    typedef int (*pipeline_argv_t)(void **);
    pipeline_argv_t pipeline = (pipeline_argv_t)(module_ptr + offset);

    // Construct a list of arguments.
    void **args = (void **)__builtin_alloca((arg_ptrsLen + outputsLen) * sizeof(void *));
    for (int i = 0; i < arg_ptrsLen; i++) {
        args[i] = arg_ptrs[i].data;
    }
    for (int i = 0; i < outputsLen; i++) {
        args[i + arg_ptrsLen] = outputs[i].data;
    }

    // Call the pipeline and return the result.
    return pipeline(args);
}

int halide_hexagon_remote_release_kernels(halide_hexagon_remote_uintptr_t module_ptr, int codeLen) {
    void *executable = (void *)module_ptr;
    codeLen = (codeLen + map_alignment - 1) & (map_alignment - 1);
    munmap(executable, codeLen);
    return 0;
}

}  // extern "C"
<|endoftext|>


<commit_before>
#include "yeseulWhitneyScene.h"

void yeseulWhitneyScene::setup(){

    setAuthor("Yeseul Song");
    setOriginalArtist("John Whitney");

    parameters.add(spinSpeed.set("spinSpeed", 10, 20, 70));
    parameters.add(diffusionInterval.set("diffusionInterval", 5, 5, 10));
    parameters.add(diffusionSize.set("diffusionSize", 1.3, 1, 3));

    lastDiffusionTime = 0;

    integratedTime = 0;
    lastTime = 0;

    loadCode("scenes/yeseulWhitneyScene/exampleCode.cpp");

}

void yeseulWhitneyScene::update(){

}

void yeseulWhitneyScene::draw(){

    ofPushMatrix();

    ofTranslate(dimensions.width/2, dimensions.height/2);

    drawPattern();

    diffusion();

    ofPopMatrix();

}

void yeseulWhitneyScene::drawPattern(){

    ofSetColor(255);
    ofFill();

    float now = getElapsedTimef();
    if (lastTime == 0) {
        lastTime = now;
    }
    float dt = now - lastTime;
    lastTime = now;

    integratedTime += spinSpeed * dt;
    float k = integratedTime;

    for (int r=0; r<35; r+=1) {
        ofRotate(k*sin(r));
        for (int a=0; a<20; a+=1) {
            ofRotate(360/20);
            ofDrawCircle(0, r*10, 1);

        }
    }

}

void yeseulWhitneyScene::diffusion() {

    float t = getElapsedTimef();

    if (lastDiffusionTime == 0 || diffusionInterval <= t - lastDiffusionTime) {
        diffs.push_back(circlesDiffusion(t, diffusionSize));
        cout << "add difff" << diffusionInterval << endl;
        lastDiffusionTime = t;
    }

    for(int i = 0; i < diffs.size(); i++){
        if(diffs[i].bKill){
            cout << "kill diff: " << i << endl;
            diffs.erase(diffs.begin() + i);
            i--;
        }
    }

    for(int i = 0; i < diffs.size(); i++){
        diffs[i].draw(t);
    }
}

<commit_msg>Update yeseulWhitneyScene.cpp<commit_after>
#include "yeseulWhitneyScene.h"

void yeseulWhitneyScene::setup(){

    setAuthor("Yeseul Song");
    setOriginalArtist("John Whitney");

    parameters.add(spinSpeed.set("spinSpeed", 10, 10, 70));
    parameters.add(diffusionInterval.set("diffusionInterval", 5, 5, 10));
    parameters.add(diffusionSize.set("diffusionSize", 1.3, 1, 3));

    lastDiffusionTime = 0;

    integratedTime = 0;
    lastTime = 0;

    loadCode("scenes/yeseulWhitneyScene/exampleCode.cpp");

}

void yeseulWhitneyScene::update(){

}

void yeseulWhitneyScene::draw(){

    ofPushMatrix();

    ofTranslate(dimensions.width/2, dimensions.height/2);

    drawPattern();

    diffusion();

    ofPopMatrix();

}

void yeseulWhitneyScene::drawPattern(){

    ofSetColor(255);
    ofFill();

    float now = getElapsedTimef();
    if (lastTime == 0) {
        lastTime = now;
    }
    float dt = now - lastTime;
    lastTime = now;

    integratedTime += spinSpeed * dt;
    float k = integratedTime;

    for (int r=0; r<35; r+=1) {
        ofRotate(k*sin(r));
        for (int a=0; a<20; a+=1) {
            ofRotate(360/20);
            ofDrawCircle(0, r*10, 1);

        }
    }

}

void yeseulWhitneyScene::diffusion() {

    float t = getElapsedTimef();

    if (lastDiffusionTime == 0 || diffusionInterval <= t - lastDiffusionTime) {
        diffs.push_back(circlesDiffusion(t, diffusionSize));
        cout << "add difff" << diffusionInterval << endl;
        lastDiffusionTime = t;
    }

    for(int i = 0; i < diffs.size(); i++){
        if(diffs[i].bKill){
            cout << "kill diff: " << i << endl;
            diffs.erase(diffs.begin() + i);
            i--;
        }
    }

    for(int i = 0; i < diffs.size(); i++){
        diffs[i].draw(t);
    }
}

<|endoftext|>