<commit_before>#include <FWApplication.h>

#include <Dialog.h>
#include <GridView.h>
#include <TableLayout.h>
#include <PlatformThread.h>
#include <SysEvent.h>
#include <LinearLayout.h>
#include <FrameLayout.h>
#include <TextLabel.h>
#include <TextField.h>
#include <Button.h>

using namespace std;

class AppMessageDialog : public Dialog {
 public:
  AppMessageDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");
    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    addChild(mainLayout);

    auto dialogMessage = make_shared<TextLabel>(message);
    mainLayout->addChild(dialogMessage);
    mainLayout->style("margin-left", "8");
    mainLayout->style("margin-right", "8");

    auto okButton = std::make_shared<Button>("OK");
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#ffffff");
    okButton->style("background", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "8");
    okButton->style("margin-right", "8");
    okButton->style("margin-bottom", "2");
    mainLayout->addChild(okButton);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppMessageDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    endModal();
  }
};

class AppInputDialog : public Dialog {
 public:
  AppInputDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");

    auto topLayout = make_shared<FrameLayout>();
    addChild(topLayout);

    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    mainLayout->style("background-color", "#ffffff");
    mainLayout->style("margin", 4);

    topLayout->addChild(mainLayout);

//    auto dialogTitle = std::make_shared<TextLabel>(title);
//    dialogTitle->style("background-color", "#ffffff");
//    dialogTitle->style("width", "match-parent");
//    dialogTitle->style("gravity", "center-horizontal");
//    dialogTitle->style("height", "wrap-content");
//    dialogTitle->style("font-size", "24");
//    dialogTitle->style("padding-top", "12");
//    dialogTitle->style("padding-bottom", "16");
//    dialogTitle->style("font-weight", "bold");
//    dialogTitle->style("padding-left", "14");
//    dialogTitle->style("padding-right", "14");
//    dialogTitle->style("color", "#c1272d");
//    mainLayout->addChild(dialogTitle);

    auto dialogMessage = make_shared<TextLabel>(message);
    dialogMessage->style("padding", "14");
    mainLayout->addChild(dialogMessage);

    textField = make_shared<TextField>();
    textField->style("width", "match-parent");
    textField->style("min-width", "100");
    textField->style("padding-bottom", "10");
    textField->style("padding-top", "10");
    textField->style("hint", "Enter code here");
    textField->style("padding-left", "14");
    textField->style("margin-bottom", 4);
    mainLayout->addChild(textField);

    auto buttonLayout = make_shared<LinearLayout>(2);

    auto okButton = std::make_shared<Button>("OK", 1);
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#ffffff");
    okButton->style("background", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "4");
    okButton->style("margin-right", "2");
    okButton->style("margin-bottom", "4");
    buttonLayout->addChild(okButton);
    auto cancelButton = std::make_shared<Button>("Cancel", 2);
    cancelButton->style("width", "match-parent");
    cancelButton->style("height", "match-parent");
    cancelButton->style("color", "#ffffff");
    cancelButton->style("background", "#c1272d");
    cancelButton->style("border-radius", "4");
    cancelButton->style("weight", "1");
    cancelButton->style("margin-left", "4");
    cancelButton->style("margin-right", "2");
    cancelButton->style("margin-bottom", "4");
    buttonLayout->addChild(cancelButton);

    mainLayout->addChild(buttonLayout);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppInputDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    if (ev.getElementId() == 1) {
      endModal(1);
    } else if (ev.getElementId() == 2) {
      endModal(0);
    }
  }

  const std::string & getValue() { return textField->getValue(); }

 private:
  std::shared_ptr<TextField> textField;
};

class DebugDialog : public Dialog {
public:
  DebugDialog() : Dialog("Debug") {
    auto mainLayout = make_shared<LinearLayout>(FW_VERTICAL);
    addChild(mainLayout);

    mainLayout->addChild(make_shared<TextLabel>("Debug screen")).style("font-size", "14")
      .style("white-space", "nowrap")
      .style("margin", 5);

    mainLayout->addChild(make_shared<TextLabel>("Stuff")).style("font-size", "12").style("margin", 5);

    auto table = make_shared<TableLayout>(2);
    table->style("margin", 5);
    mainLayout->addChild(table);

    mainLayout->addChild(make_shared<TextLabel>("Threads")).style("font-size", "12").style("margin", 5);

    auto grid = make_shared<GridView>();
    grid->style("margin", 5);
    grid->addColumn("Runnable");
    grid->addColumn("State");
    mainLayout->addChild(grid);
  }

  void load() {
    auto & grid = find("GridView").front();
    populateThreads(dynamic_cast<GridView&>(grid), getThread());
  }

protected:
  void populateThreads(GridView & grid, PlatformThread & thread) {
    string runnable_name, runnable_status;
    auto runnable = thread.getRunnablePtr();
    if (runnable) {
      runnable_name = runnable->getName();
      runnable_status = runnable->getStatusText();
    }
    grid.setValue(numThreadRows, 0, runnable_name);
    grid.setValue(numThreadRows, 1, runnable_status);
    numThreadRows++;
    for (auto & td : thread.getSubThreads()) {
      populateThreads(grid, *td.second);
    }
  }

private:
  int numThreadRows = 0;
};

void
FWApplication::onSysEvent(SysEvent & ev) {
  if (ev.getType() == SysEvent::BACK) {
    int poppedView = popViewBackHistory();
    if (poppedView != 0) {
      Command c(Command::SET_INT_VALUE, poppedView);
      c.setValue(3);
      sendCommand(c);
    } else {
      Command c(Command::QUIT_APP, poppedView);
      sendCommand(c);
    }
  } else if (ev.getType() == SysEvent::SHOW_DEBUG) {
    auto dialog = make_shared<DebugDialog>();
    dialog->showModal(this);
  }
}

void
FWApplication::showMessageDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppMessageDialog>(title, message);
  dialog->showModal(this);
}

std::string
FWApplication::showInputDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppInputDialog>(title, message);
  if (dialog->showModal(this)) {
    return dialog->getValue();
  } else {
    return "";
  }
}
<commit_msg>fix back behaviour for iOS<commit_after>#include <FWApplication.h>

#include <Dialog.h>
#include <GridView.h>
#include <TableLayout.h>
#include <PlatformThread.h>
#include <SysEvent.h>
#include <LinearLayout.h>
#include <FrameLayout.h>
#include <TextLabel.h>
#include <TextField.h>
#include <Button.h>

using namespace std;

class AppMessageDialog : public Dialog {
 public:
  AppMessageDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");
    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    addChild(mainLayout);

    auto dialogMessage = make_shared<TextLabel>(message);
    mainLayout->addChild(dialogMessage);
    mainLayout->style("margin-left", "8");
    mainLayout->style("margin-right", "8");

    auto okButton = std::make_shared<Button>("OK");
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#ffffff");
    okButton->style("background", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "8");
    okButton->style("margin-right", "8");
    okButton->style("margin-bottom", "2");
    mainLayout->addChild(okButton);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppMessageDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    endModal();
  }
};

class AppInputDialog : public Dialog {
 public:
  AppInputDialog(const std::string & title, const std::string & message) : Dialog(title) {
    style("height", "wrap-content");

    auto topLayout = make_shared<FrameLayout>();
    addChild(topLayout);

    auto mainLayout = make_shared<LinearLayout>(1);
    mainLayout->style("width", "match-parent");
    mainLayout->style("height", "wrap-content");
    mainLayout->style("background-color", "#ffffff");
    mainLayout->style("margin", 4);

    topLayout->addChild(mainLayout);

//    auto dialogTitle = std::make_shared<TextLabel>(title);
//    dialogTitle->style("background-color", "#ffffff");
//    dialogTitle->style("width", "match-parent");
//    dialogTitle->style("gravity", "center-horizontal");
//    dialogTitle->style("height", "wrap-content");
//    dialogTitle->style("font-size", "24");
//    dialogTitle->style("padding-top", "12");
//    dialogTitle->style("padding-bottom", "16");
//    dialogTitle->style("font-weight", "bold");
//    dialogTitle->style("padding-left", "14");
//    dialogTitle->style("padding-right", "14");
//    dialogTitle->style("color", "#c1272d");
//    mainLayout->addChild(dialogTitle);

    auto dialogMessage = make_shared<TextLabel>(message);
    dialogMessage->style("padding", "14");
    mainLayout->addChild(dialogMessage);

    textField = make_shared<TextField>();
    textField->style("width", "match-parent");
    textField->style("min-width", "100");
    textField->style("padding-bottom", "10");
    textField->style("padding-top", "10");
    textField->style("hint", "Enter code here");
    textField->style("padding-left", "14");
    textField->style("margin-bottom", 4);
    mainLayout->addChild(textField);

    auto buttonLayout = make_shared<LinearLayout>(2);

    auto okButton = std::make_shared<Button>("OK", 1);
    okButton->style("width", "match-parent");
    okButton->style("height", "match-parent");
    okButton->style("color", "#ffffff");
    okButton->style("background", "#c1272d");
    okButton->style("border-radius", "4");
    okButton->style("weight", "1");
    okButton->style("margin-left", "4");
    okButton->style("margin-right", "2");
    okButton->style("margin-bottom", "4");
    buttonLayout->addChild(okButton);
    auto cancelButton = std::make_shared<Button>("Cancel", 2);
    cancelButton->style("width", "match-parent");
    cancelButton->style("height", "match-parent");
    cancelButton->style("color", "#ffffff");
    cancelButton->style("background", "#c1272d");
    cancelButton->style("border-radius", "4");
    cancelButton->style("weight", "1");
    cancelButton->style("margin-left", "4");
    cancelButton->style("margin-right", "2");
    cancelButton->style("margin-bottom", "4");
    buttonLayout->addChild(cancelButton);

    mainLayout->addChild(buttonLayout);
  }

  bool isA(const std::string & className) const override {
    if (className == "AppInputDialog") return true;
    return Dialog::isA(className);
  }

  void onCommandEvent(CommandEvent & ev) override {
    if (ev.getElementId() == 1) {
      endModal(1);
    } else if (ev.getElementId() == 2) {
      endModal(0);
    }
  }

  const std::string & getValue() { return textField->getValue(); }

 private:
  std::shared_ptr<TextField> textField;
};

class DebugDialog : public Dialog {
public:
  DebugDialog() : Dialog("Debug") {
    auto mainLayout = make_shared<LinearLayout>(FW_VERTICAL);
    addChild(mainLayout);

    mainLayout->addChild(make_shared<TextLabel>("Debug screen")).style("font-size", "14")
      .style("white-space", "nowrap")
      .style("margin", 5);

    mainLayout->addChild(make_shared<TextLabel>("Stuff")).style("font-size", "12").style("margin", 5);

    auto table = make_shared<TableLayout>(2);
    table->style("margin", 5);
    mainLayout->addChild(table);

    mainLayout->addChild(make_shared<TextLabel>("Threads")).style("font-size", "12").style("margin", 5);

    auto grid = make_shared<GridView>();
    grid->style("margin", 5);
    grid->addColumn("Runnable");
    grid->addColumn("State");
    mainLayout->addChild(grid);
  }

  void load() {
    auto & grid = find("GridView").front();
    populateThreads(dynamic_cast<GridView&>(grid), getThread());
  }

protected:
  void populateThreads(GridView & grid, PlatformThread & thread) {
    string runnable_name, runnable_status;
    auto runnable = thread.getRunnablePtr();
    if (runnable) {
      runnable_name = runnable->getName();
      runnable_status = runnable->getStatusText();
    }
    grid.setValue(numThreadRows, 0, runnable_name);
    grid.setValue(numThreadRows, 1, runnable_status);
    numThreadRows++;
    for (auto & td : thread.getSubThreads()) {
      populateThreads(grid, *td.second);
    }
  }

private:
  int numThreadRows = 0;
};

void
FWApplication::onSysEvent(SysEvent & ev) {
  if (ev.getType() == SysEvent::BACK) {
    int poppedView = popViewBackHistory();
    if (poppedView != 0) {
#ifdef __ANDROID__
      Command c(Command::SET_INT_VALUE, poppedView);
      c.setValue(3);
      sendCommand(c);
#else
      Element * e = getRegisteredElement(poppedView);
      if (e) e->show();
#endif
    } else {
      Command c(Command::QUIT_APP, poppedView);
      sendCommand(c);
    }
  } else if (ev.getType() == SysEvent::SHOW_DEBUG) {
    auto dialog = make_shared<DebugDialog>();
    dialog->showModal(this);
  }
}

void
FWApplication::showMessageDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppMessageDialog>(title, message);
  dialog->showModal(this);
}

std::string
FWApplication::showInputDialog(const std::string & title, const std::string & message) {
  auto dialog = make_shared<AppInputDialog>(title, message);
  if (dialog->showModal(this)) {
    return dialog->getValue();
  } else {
    return "";
  }
}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   CEGUIDefaultResourceProvider.cpp
    created:    8/7/2004
    author:     James '_mental_' O'Sullivan
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUIDefaultResourceProvider.h"
#include "CEGUIExceptions.h"

#if defined(__WIN32__) || defined(_WIN32)
#   include <io.h>
#   include <windows.h>
#   include <string>

//----------------------------------------------------------------------------//
std::wstring Utf8ToUtf16(const std::string& utf8text)
{
    const int textLen = MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(),
                                            utf8text.size() + 1, 0, 0);

    if (textLen == 0)
        throw CEGUI::InvalidRequestException(
            "Utf8ToUtf16 - MultiByteToWideChar failed");

    std::wstring wideStr(textLen, 0);
    MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(), utf8text.size() + 1,
                        &wideStr[0], wideStr.size());
    return wideStr;
}

//----------------------------------------------------------------------------//
#else
#   include <sys/types.h>
#   include <sys/stat.h>
#   include <dirent.h>
#   include <fnmatch.h>
#endif

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
void DefaultResourceProvider::loadRawDataContainer(const String& filename,
                                                   RawDataContainer& output,
                                                   const String& resourceGroup)
{
    if (filename.empty())
        throw InvalidRequestException("DefaultResourceProvider::load: "
            "Filename supplied for data loading must be valid");

    const String final_filename(getFinalFilename(filename, resourceGroup));

#if defined(__WIN32__) || defined(_WIN32)
    FILE* file = _wfopen(Utf8ToUtf16(final_filename.c_str()).c_str(), L"rb");
#else
    FILE* file = fopen(final_filename.c_str(), "rb");
#endif

    if (file == 0)
        throw InvalidRequestException("DefaultResourceProvider::load: " +
            final_filename + " does not exist");

    fseek(file, 0, SEEK_END);
    const long size = ftell(file);
    fseek(file, 0, SEEK_SET);

    unsigned char* const buffer = new unsigned char[size];

    const size_t size_read = fread(buffer, sizeof(char), size, file);
    fclose(file);

    if (size_read != size)
    {
        delete[] buffer;
        throw GenericException("DefaultResourceProvider::loadRawDataContainer: "
            "A problem occurred while reading file: " + final_filename);
    }

    output.setData(buffer);
    output.setSize(size);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::unloadRawDataContainer(RawDataContainer& data)
{
    uint8* const ptr = data.getDataPtr();
    delete[] ptr;
    data.setData(0);
    data.setSize(0);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::setResourceGroupDirectory(
                                                const String& resourceGroup,
                                                const String& directory)
{
    if (directory.length() == 0)
        return;

#if defined(_WIN32) || defined(__WIN32__)
    // while we rarely use the unportable '\', the user may have
    const String separators("\\/");
#else
    const String separators("/");
#endif

    if (String::npos == separators.find(directory[directory.length() - 1]))
        d_resourceGroups[resourceGroup] = directory + '/';
    else
        d_resourceGroups[resourceGroup] = directory;
}

//----------------------------------------------------------------------------//
const String& DefaultResourceProvider::getResourceGroupDirectory(
                                                const String& resourceGroup)
{
    return d_resourceGroups[resourceGroup];
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::clearResourceGroupDirectory(
                                                const String& resourceGroup)
{
    ResourceGroupMap::iterator iter = d_resourceGroups.find(resourceGroup);

    if (iter != d_resourceGroups.end())
        d_resourceGroups.erase(iter);
}

//----------------------------------------------------------------------------//
String DefaultResourceProvider::getFinalFilename(
                                            const String& filename,
                                            const String& resourceGroup) const
{
    String final_filename;

    // look up resource group directory
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resourceGroup.empty() ?
            d_defaultResourceGroup :
            resourceGroup);

    // if there was an entry for this group, use it's directory as the
    // first part of the filename
    if (iter != d_resourceGroups.end())
        final_filename = (*iter).second;

    // append the filename part that we were passed
    final_filename += filename;

    // return result
    return final_filename;
}

//----------------------------------------------------------------------------//
size_t DefaultResourceProvider::getResourceGroupFileNames(
    std::vector<String>& out_vec,
    const String& file_pattern,
    const String& resource_group)
{
    // look-up resource group name
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resource_group.empty() ? d_defaultResourceGroup :
                              resource_group);
    // get directory that's set for the resource group
    const String dir_name(
        iter != d_resourceGroups.end() ? (*iter).second : "./");

    size_t entries = 0;

// Win32 code.
#if defined(__WIN32__) || defined(_WIN32)
    intptr_t f;
    struct _finddata_t fd;

    if ((f = _findfirst((dir_name + file_pattern).c_str(), &fd)) != -1)
    {
        do
        {
            if ((fd.attrib & _A_SUBDIR))
                continue;

            out_vec.push_back(fd.name);
            ++entries;
        }
        while (_findnext(f, &fd) == 0);

        _findclose(f);
    }

// Everybody else
#else
    DIR* dirp;

    if ((dirp = opendir(dir_name.c_str())))
    {
        struct dirent* dp;

        while ((dp = readdir(dirp)))
        {
            const String filename(dir_name + dp->d_name);
            struct stat s;

            if ((stat(filename.c_str(), &s) == 0) &&
                    S_ISREG(s.st_mode) &&
                    (fnmatch(file_pattern.c_str(), dp->d_name, 0) == 0))
            {
                out_vec.push_back(dp->d_name);
                ++entries;
            }
        }

        closedir(dirp);
    }
#endif

    return entries;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<commit_msg>FIX: The Windows utf-16 / wchar_t patch adding support for filenames encoded as utf16 was missing support for that facility in the DefaultResourceProvider::getResourceGroupFileNames function.  This fix adds that support.<commit_after>/***********************************************************************
    filename:   CEGUIDefaultResourceProvider.cpp
    created:    8/7/2004
    author:     James '_mental_' O'Sullivan
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2010 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "CEGUIDefaultResourceProvider.h"
#include "CEGUIExceptions.h"

#if defined(__WIN32__) || defined(_WIN32)
#   include <io.h>
#   include <windows.h>
#   include <string>

//----------------------------------------------------------------------------//
std::wstring Utf8ToUtf16(const std::string& utf8text)
{
    const int textLen = MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(),
                                            utf8text.size() + 1, 0, 0);

    if (textLen == 0)
        throw CEGUI::InvalidRequestException(
            "Utf8ToUtf16 - MultiByteToWideChar failed");

    std::wstring wideStr(textLen, 0);
    MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(), utf8text.size() + 1,
                        &wideStr[0], wideStr.size());
    return wideStr;
}

//----------------------------------------------------------------------------//
CEGUI::String Utf16ToString(const wchar_t* const utf16text)
{
    const int len = WideCharToMultiByte(CP_UTF8, 0, utf16text, -1,
                                        0, 0, 0, 0);
    if (!len)
        throw CEGUI::InvalidRequestException(
            "Utf16ToUtf8 - WideCharToMultiByte failed");

    CEGUI::utf8* buff = new CEGUI::utf8[len + 1];
    WideCharToMultiByte(CP_UTF8, 0, utf16text, -1,
                        reinterpret_cast<char*>(buff), len, 0, 0);
    const CEGUI::String result(buff);
    delete[] buff;

    return result;
}

//----------------------------------------------------------------------------//
#else
#   include <sys/types.h>
#   include <sys/stat.h>
#   include <dirent.h>
#   include <fnmatch.h>
#endif

// Start of CEGUI namespace section
namespace CEGUI
{

//----------------------------------------------------------------------------//
void DefaultResourceProvider::loadRawDataContainer(const String& filename,
                                                   RawDataContainer& output,
                                                   const String& resourceGroup)
{
    if (filename.empty())
        throw InvalidRequestException("DefaultResourceProvider::load: "
            "Filename supplied for data loading must be valid");

    const String final_filename(getFinalFilename(filename, resourceGroup));

#if defined(__WIN32__) || defined(_WIN32)
    FILE* file = _wfopen(Utf8ToUtf16(final_filename.c_str()).c_str(), L"rb");
#else
    FILE* file = fopen(final_filename.c_str(), "rb");
#endif

    if (file == 0)
        throw InvalidRequestException("DefaultResourceProvider::load: " +
            final_filename + " does not exist");

    fseek(file, 0, SEEK_END);
    const long size = ftell(file);
    fseek(file, 0, SEEK_SET);

    unsigned char* const buffer = new unsigned char[size];

    const size_t size_read = fread(buffer, sizeof(char), size, file);
    fclose(file);

    if (size_read != size)
    {
        delete[] buffer;
        throw GenericException("DefaultResourceProvider::loadRawDataContainer: "
            "A problem occurred while reading file: " + final_filename);
    }

    output.setData(buffer);
    output.setSize(size);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::unloadRawDataContainer(RawDataContainer& data)
{
    uint8* const ptr = data.getDataPtr();
    delete[] ptr;
    data.setData(0);
    data.setSize(0);
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::setResourceGroupDirectory(
                                                const String& resourceGroup,
                                                const String& directory)
{
    if (directory.length() == 0)
        return;

#if defined(_WIN32) || defined(__WIN32__)
    // while we rarely use the unportable '\', the user may have
    const String separators("\\/");
#else
    const String separators("/");
#endif

    if (String::npos == separators.find(directory[directory.length() - 1]))
        d_resourceGroups[resourceGroup] = directory + '/';
    else
        d_resourceGroups[resourceGroup] = directory;
}

//----------------------------------------------------------------------------//
const String& DefaultResourceProvider::getResourceGroupDirectory(
                                                const String& resourceGroup)
{
    return d_resourceGroups[resourceGroup];
}

//----------------------------------------------------------------------------//
void DefaultResourceProvider::clearResourceGroupDirectory(
                                                const String& resourceGroup)
{
    ResourceGroupMap::iterator iter = d_resourceGroups.find(resourceGroup);

    if (iter != d_resourceGroups.end())
        d_resourceGroups.erase(iter);
}

//----------------------------------------------------------------------------//
String DefaultResourceProvider::getFinalFilename(
                                            const String& filename,
                                            const String& resourceGroup) const
{
    String final_filename;

    // look up resource group directory
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resourceGroup.empty() ?
            d_defaultResourceGroup :
            resourceGroup);

    // if there was an entry for this group, use it's directory as the
    // first part of the filename
    if (iter != d_resourceGroups.end())
        final_filename = (*iter).second;

    // append the filename part that we were passed
    final_filename += filename;

    // return result
    return final_filename;
}

//----------------------------------------------------------------------------//
size_t DefaultResourceProvider::getResourceGroupFileNames(
    std::vector<String>& out_vec,
    const String& file_pattern,
    const String& resource_group)
{
    // look-up resource group name
    ResourceGroupMap::const_iterator iter =
        d_resourceGroups.find(resource_group.empty() ? d_defaultResourceGroup :
                              resource_group);
    // get directory that's set for the resource group
    const String dir_name(
        iter != d_resourceGroups.end() ? (*iter).second : "./");

    size_t entries = 0;

// Win32 code.
#if defined(__WIN32__) || defined(_WIN32)
    intptr_t f;
    struct _wfinddata_t fd;

    if ((f = _wfindfirst(Utf8ToUtf16((dir_name + file_pattern).c_str()).c_str(), &fd)) != -1)
    {
        do
        {
            if ((fd.attrib & _A_SUBDIR))
                continue;

            out_vec.push_back(Utf16ToString(fd.name));
            ++entries;
        }
        while (_wfindnext(f, &fd) == 0);

        _findclose(f);
    }

// Everybody else
#else
    DIR* dirp;

    if ((dirp = opendir(dir_name.c_str())))
    {
        struct dirent* dp;

        while ((dp = readdir(dirp)))
        {
            const String filename(dir_name + dp->d_name);
            struct stat s;

            if ((stat(filename.c_str(), &s) == 0) &&
                    S_ISREG(s.st_mode) &&
                    (fnmatch(file_pattern.c_str(), dp->d_name, 0) == 0))
            {
                out_vec.push_back(dp->d_name);
                ++entries;
            }
        }

        closedir(dirp);
    }
#endif

    return entries;
}

//----------------------------------------------------------------------------//

} // End of  CEGUI namespace section

<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "network.h"
#include "string.h"
#include "mutex.h"

////////////////////////////////////////////////////////////////////////////////
/// Platforms supporting Socket interface
////////////////////////////////////////////////////////////////////////////////

#if defined(__WIN32__)
#define _WINSOCK_DEPRECATED_NO_WARNINGS
//#include <winsock2.h>
//#include <io.h>
typedef int socklen_t;
#define SHUT_RDWR 0x2
#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#define SOCKET int
#define INVALID_SOCKET -1
#define closesocket close
#endif

/*! ignore if not supported */
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif

#define BUFFERING 1

namespace embree
{
  namespace network
  {
    __forceinline void initialize() {
#ifdef __WIN32__
      static bool initialized = false;
      static MutexSys initMutex;
      Lock<MutexSys> lock(initMutex);
      WSADATA wsaData;
      short version = MAKEWORD(1,1);
      if (WSAStartup(version,&wsaData) != 0)
        THROW_RUNTIME_ERROR("Winsock initialization failed");
      initialized = true;
#endif
    }

    struct buffered_socket_t
    {
      buffered_socket_t (SOCKET fd, size_t isize = 64*1024, size_t osize = 64*1024)
        : fd(fd),
          ibuf(new char[isize]), isize(isize), istart(0), iend(0),
          obuf(new char[osize]), osize(osize), oend(0) {
      }

      ~buffered_socket_t () {
        delete[] ibuf; ibuf = nullptr;
        delete[] obuf; obuf = nullptr;
      }

      SOCKET fd;               //!< file descriptor of the socket
      char* ibuf;
      size_t isize;
      size_t istart,iend;
      char* obuf;
      size_t osize;
      size_t oend;
    };

    socket_t connect(const char* host, unsigned short port)
    {
      initialize();

      /*! create a new socket */
      SOCKET sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot create socket");

      /*! perform DNS lookup */
      struct hostent* server = ::gethostbyname(host);
      if (server == nullptr) THROW_RUNTIME_ERROR("server "+std::string(host)+" not found");

      /*! perform connection */
      struct sockaddr_in serv_addr;
      memset((char*)&serv_addr, 0, sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_port = (unsigned short) htons(port);
      memcpy((char*)&serv_addr.sin_addr.s_addr, (char*)server->h_addr, server->h_length);

      if (::connect(sockfd,(struct sockaddr*) &serv_addr,sizeof(serv_addr)) < 0)
        THROW_RUNTIME_ERROR("connection to "+std::string(host)+":"+toString(port)+" failed");

      /*! enable TCP_NODELAY */
#ifdef TCP_NODELAY
      { int flag = 1; ::setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(int)); }
#endif

      /*! we do not want SIGPIPE to be thrown */
#ifdef SO_NOSIGPIPE
      { int flag = 1; setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (const char*) &flag, sizeof(int)); }
#endif

      return (socket_t) new buffered_socket_t(sockfd);
    }

    socket_t bind(unsigned short port)
    {
      initialize();

      /*! create a new socket */
      SOCKET sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot create socket");

      /* When the server completes, the server socket enters a time-wait state during which the local
      address and port used by the socket are believed to be in use by the OS. The wait state may
      last several minutes. This socket option allows bind() to reuse the port immediately. */
#ifdef SO_REUSEADDR
      { int flag = true; ::setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(int)); }
#endif

      /*! bind socket to port */
      struct sockaddr_in serv_addr;
      memset((char *) &serv_addr, 0, sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_port = (unsigned short) htons(port);
      serv_addr.sin_addr.s_addr = INADDR_ANY;

      if (::bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
        THROW_RUNTIME_ERROR("binding to port "+toString(port)+" failed");

      /*! listen to port, up to 5 pending connections */
      if (::listen(sockfd,5) < 0)
        THROW_RUNTIME_ERROR("listening on socket failed");

      return (socket_t) new buffered_socket_t(sockfd);
    }

    socket_t listen(socket_t hsock)
    {
      SOCKET sockfd = ((buffered_socket_t*) hsock)->fd;

      /*! accept incoming connection */
      struct sockaddr_in addr;
      socklen_t len = sizeof(addr);
      SOCKET fd = ::accept(sockfd, (struct sockaddr *) &addr, &len);
      if (fd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot accept connection");

      /*! enable TCP_NODELAY */
#ifdef TCP_NODELAY
      { int flag = 1; ::setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char*)&flag,sizeof(int)); }
#endif

      /*! we do not want SIGPIPE to be thrown */
#ifdef SO_NOSIGPIPE
      { int flag = 1; setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&flag, sizeof(int)); }
#endif

      return (socket_t) new buffered_socket_t(fd);
    }

    void read(socket_t hsock_i, void* data_i, size_t bytes)
    {
#if BUFFERING
      char* data = (char*)data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        if (hsock->istart == hsock->iend) {
          ssize_t n = ::recv(hsock->fd,hsock->ibuf,int(hsock->isize),MSG_NOSIGNAL);
          if      (n == 0) throw Disconnect();
          else if (n  < 0) THROW_RUNTIME_ERROR("error reading from socket");
          hsock->istart = 0;
          hsock->iend = n;
        }
        size_t bsize = hsock->iend-hsock->istart;
        if (bytes < bsize) bsize = bytes;
        memcpy(data,hsock->ibuf+hsock->istart,bsize);
        data += bsize;
        hsock->istart += bsize;
        bytes -= bsize;
      }
#else
      char* data = (char*) data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        ssize_t n = ::read(hsock->fd,data,bytes);
        if      (n == 0) throw Disconnect();
        else if (n  < 0) THROW_RUNTIME_ERROR("error reading from socket");
        data+=n;
        bytes-=n;
      }
#endif
    }

    void write(socket_t hsock_i, const void* data_i, size_t bytes)
    {
#if BUFFERING
      const char* data = (const char*) data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        if (hsock->oend == hsock->osize) flush(hsock_i);
        size_t bsize = hsock->osize-hsock->oend;
        if (bytes < bsize) bsize = bytes;
        memcpy(hsock->obuf+hsock->oend,data,bsize);
        data += bsize;
        hsock->oend += bsize;
        bytes -= bsize;
      }
#else
      const char* data = (const char*) data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        ssize_t n = ::write(hsock->fd,data,bytes);
        if (n  < 0) THROW_RUNTIME_ERROR("error writing to socket");
        data+=n;
        bytes-=n;
      }
#endif
    }

    void flush(socket_t hsock_i)
    {
#if BUFFERING
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      char* data = hsock->obuf;
      size_t bytes = hsock->oend;
      while (bytes > 0) {
        ssize_t n = ::send(hsock->fd,data,(int)bytes,MSG_NOSIGNAL);
        if (n < 0) THROW_RUNTIME_ERROR("error writing to socket");
        bytes -= n;
        data += n;
      }
      hsock->oend = 0;
#endif
    }

    void close(socket_t hsock_i) {
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      ::shutdown(hsock->fd,SHUT_RDWR);
      delete hsock;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
/// All Platforms
////////////////////////////////////////////////////////////////////////////////

namespace embree
{
  namespace network
  {
    bool read_bool(socket_t socket)
    {
      bool value = 0;
      read(socket,&value,sizeof(bool));
      return value;
    }

    char read_char(socket_t socket)
    {
      char value = 0;
      read(socket,&value,sizeof(char));
      return value;
    }

    int read_int(socket_t socket)
    {
      int value = 0;
      read(socket,&value,sizeof(int));
      return value;
    }

    float read_float(socket_t socket)
    {
      float value = 0.0f;
      read(socket,&value,sizeof(float));
      return value;
    }

    std::string read_string(socket_t socket)
    {
      int bytes = read_int(socket);
      char* str = new char[bytes+1];
      read(socket,str,bytes);
      str[bytes] = 0x00;
      std::string s(str);
      delete[] str;
      return s;
    }

    void write(socket_t socket, bool value) {
      write(socket,&value,sizeof(bool));
    }

    void write(socket_t socket, char value) {
      write(socket,&value,sizeof(char));
    }

    void write(socket_t socket, int value) {
      write(socket,&value,sizeof(int));
    }

    void write(socket_t socket, float value) {
      write(socket,&value,sizeof(float));
    }

    void write(socket_t socket, const std::string& str) {
      write(socket,(int)str.size());
      write(socket,str.c_str(),str.size());
    }
  }
}
<commit_msg>made buffered_socket_t non-copyable<commit_after>// ======================================================================== //
// Copyright 2009-2016 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "network.h"
#include "string.h"
#include "mutex.h"

////////////////////////////////////////////////////////////////////////////////
/// Platforms supporting Socket interface
////////////////////////////////////////////////////////////////////////////////

#if defined(__WIN32__)
#define _WINSOCK_DEPRECATED_NO_WARNINGS
//#include <winsock2.h>
//#include <io.h>
typedef int socklen_t;
#define SHUT_RDWR 0x2
#else
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#define SOCKET int
#define INVALID_SOCKET -1
#define closesocket close
#endif

/*! ignore if not supported */
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif

#define BUFFERING 1

namespace embree
{
  namespace network
  {
    __forceinline void initialize() {
#ifdef __WIN32__
      static bool initialized = false;
      static MutexSys initMutex;
      Lock<MutexSys> lock(initMutex);
      WSADATA wsaData;
      short version = MAKEWORD(1,1);
      if (WSAStartup(version,&wsaData) != 0)
        THROW_RUNTIME_ERROR("Winsock initialization failed");
      initialized = true;
#endif
    }

    struct buffered_socket_t
    {
      buffered_socket_t (SOCKET fd, size_t isize = 64*1024, size_t osize = 64*1024)
        : fd(fd),
          ibuf(new char[isize]), isize(isize), istart(0), iend(0),
          obuf(new char[osize]), osize(osize), oend(0) {
      }

      ~buffered_socket_t () {
        delete[] ibuf; ibuf = nullptr;
        delete[] obuf; obuf = nullptr;
      }

    private:
      buffered_socket_t (const buffered_socket_t& other) DELETED; // do not implement
      buffered_socket_t& operator= (const buffered_socket_t& other) DELETED; // do not implement

    public:
      SOCKET fd;               //!< file descriptor of the socket
      char* ibuf;
      size_t isize;
      size_t istart,iend;
      char* obuf;
      size_t osize;
      size_t oend;
    };

    socket_t connect(const char* host, unsigned short port)
    {
      initialize();

      /*! create a new socket */
      SOCKET sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot create socket");

      /*! perform DNS lookup */
      struct hostent* server = ::gethostbyname(host);
      if (server == nullptr) THROW_RUNTIME_ERROR("server "+std::string(host)+" not found");

      /*! perform connection */
      struct sockaddr_in serv_addr;
      memset((char*)&serv_addr, 0, sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_port = (unsigned short) htons(port);
      memcpy((char*)&serv_addr.sin_addr.s_addr, (char*)server->h_addr, server->h_length);

      if (::connect(sockfd,(struct sockaddr*) &serv_addr,sizeof(serv_addr)) < 0)
        THROW_RUNTIME_ERROR("connection to "+std::string(host)+":"+toString(port)+" failed");

      /*! enable TCP_NODELAY */
#ifdef TCP_NODELAY
      { int flag = 1; ::setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(int)); }
#endif

      /*! we do not want SIGPIPE to be thrown */
#ifdef SO_NOSIGPIPE
      { int flag = 1; setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (const char*) &flag, sizeof(int)); }
#endif

      return (socket_t) new buffered_socket_t(sockfd);
    }

    socket_t bind(unsigned short port)
    {
      initialize();

      /*! create a new socket */
      SOCKET sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
      if (sockfd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot create socket");

      /* When the server completes, the server socket enters a time-wait state during which the local
      address and port used by the socket are believed to be in use by the OS. The wait state may
      last several minutes. This socket option allows bind() to reuse the port immediately. */
#ifdef SO_REUSEADDR
      { int flag = true; ::setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(int)); }
#endif

      /*! bind socket to port */
      struct sockaddr_in serv_addr;
      memset((char *) &serv_addr, 0, sizeof(serv_addr));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_port = (unsigned short) htons(port);
      serv_addr.sin_addr.s_addr = INADDR_ANY;

      if (::bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
        THROW_RUNTIME_ERROR("binding to port "+toString(port)+" failed");

      /*! listen to port, up to 5 pending connections */
      if (::listen(sockfd,5) < 0)
        THROW_RUNTIME_ERROR("listening on socket failed");

      return (socket_t) new buffered_socket_t(sockfd);
    }

    socket_t listen(socket_t hsock)
    {
      SOCKET sockfd = ((buffered_socket_t*) hsock)->fd;

      /*! accept incoming connection */
      struct sockaddr_in addr;
      socklen_t len = sizeof(addr);
      SOCKET fd = ::accept(sockfd, (struct sockaddr *) &addr, &len);
      if (fd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot accept connection");

      /*! enable TCP_NODELAY */
#ifdef TCP_NODELAY
      { int flag = 1; ::setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char*)&flag,sizeof(int)); }
#endif

      /*! we do not want SIGPIPE to be thrown */
#ifdef SO_NOSIGPIPE
      { int flag = 1; setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&flag, sizeof(int)); }
#endif

      return (socket_t) new buffered_socket_t(fd);
    }

    void read(socket_t hsock_i, void* data_i, size_t bytes)
    {
#if BUFFERING
      char* data = (char*)data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        if (hsock->istart == hsock->iend) {
          ssize_t n = ::recv(hsock->fd,hsock->ibuf,int(hsock->isize),MSG_NOSIGNAL);
          if      (n == 0) throw Disconnect();
          else if (n  < 0) THROW_RUNTIME_ERROR("error reading from socket");
          hsock->istart = 0;
          hsock->iend = n;
        }
        size_t bsize = hsock->iend-hsock->istart;
        if (bytes < bsize) bsize = bytes;
        memcpy(data,hsock->ibuf+hsock->istart,bsize);
        data += bsize;
        hsock->istart += bsize;
        bytes -= bsize;
      }
#else
      char* data = (char*) data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        ssize_t n = ::read(hsock->fd,data,bytes);
        if      (n == 0) throw Disconnect();
        else if (n  < 0) THROW_RUNTIME_ERROR("error reading from socket");
        data+=n;
        bytes-=n;
      }
#endif
    }

    void write(socket_t hsock_i, const void* data_i, size_t bytes)
    {
#if BUFFERING
      const char* data = (const char*) data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        if (hsock->oend == hsock->osize) flush(hsock_i);
        size_t bsize = hsock->osize-hsock->oend;
        if (bytes < bsize) bsize = bytes;
        memcpy(hsock->obuf+hsock->oend,data,bsize);
        data += bsize;
        hsock->oend += bsize;
        bytes -= bsize;
      }
#else
      const char* data = (const char*) data_i;
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      while (bytes) {
        ssize_t n = ::write(hsock->fd,data,bytes);
        if (n  < 0) THROW_RUNTIME_ERROR("error writing to socket");
        data+=n;
        bytes-=n;
      }
#endif
    }

    void flush(socket_t hsock_i)
    {
#if BUFFERING
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      char* data = hsock->obuf;
      size_t bytes = hsock->oend;
      while (bytes > 0) {
        ssize_t n = ::send(hsock->fd,data,(int)bytes,MSG_NOSIGNAL);
        if (n < 0) THROW_RUNTIME_ERROR("error writing to socket");
        bytes -= n;
        data += n;
      }
      hsock->oend = 0;
#endif
    }

    void close(socket_t hsock_i) {
      buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
      ::shutdown(hsock->fd,SHUT_RDWR);
      delete hsock;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
/// All Platforms
////////////////////////////////////////////////////////////////////////////////

namespace embree
{
  namespace network
  {
    bool read_bool(socket_t socket)
    {
      bool value = 0;
      read(socket,&value,sizeof(bool));
      return value;
    }

    char read_char(socket_t socket)
    {
      char value = 0;
      read(socket,&value,sizeof(char));
      return value;
    }

    int read_int(socket_t socket)
    {
      int value = 0;
      read(socket,&value,sizeof(int));
      return value;
    }

    float read_float(socket_t socket)
    {
      float value = 0.0f;
      read(socket,&value,sizeof(float));
      return value;
    }

    std::string read_string(socket_t socket)
    {
      int bytes = read_int(socket);
      char* str = new char[bytes+1];
      read(socket,str,bytes);
      str[bytes] = 0x00;
      std::string s(str);
      delete[] str;
      return s;
    }

    void write(socket_t socket, bool value) {
      write(socket,&value,sizeof(bool));
    }

    void write(socket_t socket, char value) {
      write(socket,&value,sizeof(char));
    }

    void write(socket_t socket, int value) {
      write(socket,&value,sizeof(int));
    }

    void write(socket_t socket, float value) {
      write(socket,&value,sizeof(float));
    }

    void write(socket_t socket, const std::string& str) {
      write(socket,(int)str.size());
      write(socket,str.c_str(),str.size());
    }
  }
}
<|endoftext|>


<commit_before>/***********************************************************************
    created:    Fri, 4th July 2014
    author:     Henri I Hyyryläinen
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

namespace CEGUI
{
// Shaders for Ogre renderer adapted from OpenGL and Direct3D11 shaders

//! A string containing an HLSL vertex shader for solid colouring of a polygon
static Ogre::String VertexShaderColoured_HLSL(""
"uniform float4x4 worldViewProjMatrix;\n"
"\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"};\n"
"\n"
"VS_OUT main(float4 position : POSITION, float4 colour : COLOR)\n"
"{\n"
"	VS_OUT o;\n"
"\n"
"   o.position = mul(worldViewProjMatrix, position);\n"
"	o.colour = colour;\n"
"\n"
"	return output;\n"
"}\n"
);

//! A string containing an HLSL fragment shader for solid colouring of a polygon
static Ogre::String PixelShaderColoured_HLSL(""
"uniform float alphaPercentage;\n"
"\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"};\n"
"\n"
"float4 main(VS_OUT input) : COLOR\n"
"{\n"
"   float4 colour = input.colour;\n"
"   colour.a *= alphaPercentage;\n"
"	return colour;\n"
"}\n"
"\n"
);

/*!
A string containing an HLSL vertex shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String VertexShaderTextured_HLSL(""
"uniform float4x4 worldViewProjMatrix;\n"
"\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"   float2 uv : TEXCOORD0;\n"
"};\n"
"\n"
"// Vertex shader\n"
"VS_OUT main(float4 position : POSITION, float2 uv : TEXCOORD0, float4 colour : COLOR)\n"
"{\n"
"	VS_OUT o;\n"
"\n"
"   o.position = mul(worldViewProjMatrix, position);\n"
"   o.uv = uv;\n"
"	o.colour = colour;\n"
"\n"
"	return output;\n"
"}\n"
);

/*!
A string containing an HLSL fragment shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String PixelShaderTextured_HLSL(""
"uniform float alphaPercentage;\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"   float2 uv : TEXCOORD0;\n"
"};\n"
"\n"
"float4 main(float4 colour : COLOR, float2 uv : TEXCOORD0, "
"               uniform sampler2D texture0 : TEXUNIT0) : COLOR\n"
"{\n"
"   colour = tex2D(texture0, uv) * colour;\n"
"   colour.a *= alphaPercentage;\n"
"	return colour;\n"
"}\n"
"\n"
);

//! Shader for older OpenGL versions < 3
static Ogre::String VertexShaderTextured_GLSL_Compat(""
    "void main(void)"
    "{"
    "    gl_TexCoord[0] = gl_MultiTexCoord0;"
    "    gl_FrontColor = gl_Color;"
    "    gl_Position = gl_worldViewProjMatrix * gl_Vertex;"
    "}"
);

//! Shader for older OpenGL versions < 3
static Ogre::String PixelShaderTextured_GLSL_Compat(""
    "uniform sampler2D texture0;"
    "uniform float alphaPercentage;\n"
    "void main(void)"
    "{"
    "    gl_FragColor = texture2D(texture0, gl_TexCoord[0].st) * gl_Color;"
    "    gl_FragColor.a *= alphaPercentage;\n"
    "}"
);

//! Shader for older OpenGL versions < 3
static Ogre::String VertexShaderColoured_GLSL_Compat(""
    "void main(void)"
    "{"
    "    gl_FrontColor = gl_Color;"
    "    gl_Position = gl_worldViewProjMatrix * gl_Vertex;"
    "}"
);

//! Shader for older OpenGL versions < 3
static Ogre::String PixelShaderColoured_GLSL_Compat(""
    "uniform float alphaPercentage;\n"
    "void main(void)\n"
    "{"
    "    gl_FragColor = gl_Color;"
    "    gl_FragColor.a *= alphaPercentage;\n"
    "}"
);

//! A string containing an OpenGL3 vertex shader for solid colouring of a polygon
static Ogre::String VertexShaderColoured_GLSL(""
    "#version 150 core\n"

    "uniform mat4 worldViewProjMatrix;\n"

    "in vec4 vertex;\n"
    "in vec4 colour;\n"

    "out vec4 exColour;"

    "void main(void)\n"
    "{\n"
    "   exColour = colour;\n"

    "   gl_Position = worldViewProjMatrix * vertex;\n"
    "}"
);

//! A string containing an OpenGL3 fragment shader for solid colouring of a polygon
static Ogre::String PixelShaderColoured_GLSL(""
    "#version 150 core\n"

    "in vec4 exColour;\n"

    "out vec4 fragColour;\n"

    "uniform float alphaPercentage;\n"

    "void main(void)\n"
    "{\n"
    "   fragColour = exColour;\n"
    "   fragColour.a *= alphaPercentage;\n"
    "}"
);

/*!
A string containing an OpenGL3 vertex shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String VertexShaderTextured_GLSL(""
    "#version 150 core\n"

    "uniform mat4 worldViewProjMatrix;\n"

    "in vec4 vertex;\n"
    "in vec4 colour;\n"
    "in vec2 uv0;\n"

    "out vec2 exTexCoord;\n"
    "out vec4 exColour;\n"

    "void main()\n"
    "{\n"
    "   exTexCoord = uv0;\n"
    "   exColour = colour;\n"

    "   gl_Position = worldViewProjMatrix * vertex;\n"
    "}"
);

/*!
A string containing an OpenGL3 fragment shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String PixelShaderTextured_GLSL(""
    "#version 150 core\n"

    "uniform sampler2D texture0;\n"
    "uniform float alphaPercentage;\n"

    "in vec2 exTexCoord;\n"
    "in vec4 exColour;\n"

    "out vec4 fragColour;\n"

    "void main(void)\n"
    "{\n"
    "   fragColour = texture(texture0, exTexCoord) * exColour;\n"
    "   fragColour.a *= alphaPercentage;\n"
    "}"
);

}

<commit_msg>Made Ogre renderer OpenGL shaders use older version to make it work better on linux<commit_after>/***********************************************************************
    created:    Fri, 4th July 2014
    author:     Henri I Hyyryläinen
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

namespace CEGUI
{
// Shaders for Ogre renderer adapted from OpenGL and Direct3D11 shaders

//! A string containing an HLSL vertex shader for solid colouring of a polygon
static Ogre::String VertexShaderColoured_HLSL(""
"uniform float4x4 worldViewProjMatrix;\n"
"\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"};\n"
"\n"
"VS_OUT main(float4 position : POSITION, float4 colour : COLOR)\n"
"{\n"
"	VS_OUT o;\n"
"\n"
"   o.position = mul(worldViewProjMatrix, position);\n"
"	o.colour = colour;\n"
"\n"
"	return output;\n"
"}\n"
);

//! A string containing an HLSL fragment shader for solid colouring of a polygon
static Ogre::String PixelShaderColoured_HLSL(""
"uniform float alphaPercentage;\n"
"\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"};\n"
"\n"
"float4 main(VS_OUT input) : COLOR\n"
"{\n"
"   float4 colour = input.colour;\n"
"   colour.a *= alphaPercentage;\n"
"	return colour;\n"
"}\n"
"\n"
);

/*!
A string containing an HLSL vertex shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String VertexShaderTextured_HLSL(""
"uniform float4x4 worldViewProjMatrix;\n"
"\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"   float2 uv : TEXCOORD0;\n"
"};\n"
"\n"
"// Vertex shader\n"
"VS_OUT main(float4 position : POSITION, float2 uv : TEXCOORD0, float4 colour : COLOR)\n"
"{\n"
"	VS_OUT o;\n"
"\n"
"   o.position = mul(worldViewProjMatrix, position);\n"
"   o.uv = uv;\n"
"	o.colour = colour;\n"
"\n"
"	return output;\n"
"}\n"
);

/*!
A string containing an HLSL fragment shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String PixelShaderTextured_HLSL(""
"uniform float alphaPercentage;\n"
"struct VS_OUT\n"
"{\n"
"	float4 position : POSITION;\n"
"	float4 colour : COLOR;\n"
"   float2 uv : TEXCOORD0;\n"
"};\n"
"\n"
"float4 main(float4 colour : COLOR, float2 uv : TEXCOORD0, "
"               uniform sampler2D texture0 : TEXUNIT0) : COLOR\n"
"{\n"
"   colour = tex2D(texture0, uv) * colour;\n"
"   colour.a *= alphaPercentage;\n"
"	return colour;\n"
"}\n"
"\n"
);

//! Shader for older OpenGL versions < 3
static Ogre::String VertexShaderTextured_GLSL_Compat(""
    "void main(void)"
    "{"
    "    gl_TexCoord[0] = gl_MultiTexCoord0;"
    "    gl_FrontColor = gl_Color;"
    "    gl_Position = gl_worldViewProjMatrix * gl_Vertex;"
    "}"
);

//! Shader for older OpenGL versions < 3
static Ogre::String PixelShaderTextured_GLSL_Compat(""
    "uniform sampler2D texture0;"
    "uniform float alphaPercentage;\n"
    "void main(void)"
    "{"
    "    gl_FragColor = texture2D(texture0, gl_TexCoord[0].st) * gl_Color;"
    "    gl_FragColor.a *= alphaPercentage;\n"
    "}"
);

//! Shader for older OpenGL versions < 3
static Ogre::String VertexShaderColoured_GLSL_Compat(""
    "void main(void)"
    "{"
    "    gl_FrontColor = gl_Color;"
    "    gl_Position = gl_worldViewProjMatrix * gl_Vertex;"
    "}"
);

//! Shader for older OpenGL versions < 3
static Ogre::String PixelShaderColoured_GLSL_Compat(""
    "uniform float alphaPercentage;\n"
    "void main(void)\n"
    "{"
    "    gl_FragColor = gl_Color;"
    "    gl_FragColor.a *= alphaPercentage;\n"
    "}"
);

//! A string containing an OpenGL3 vertex shader for solid colouring of a polygon
static Ogre::String VertexShaderColoured_GLSL(""
    "#version 130 core\n"

    "uniform mat4 worldViewProjMatrix;\n"

    "in vec4 vertex;\n"
    "in vec4 colour;\n"

    "out vec4 exColour;"

    "void main(void)\n"
    "{\n"
    "   exColour = colour;\n"

    "   gl_Position = worldViewProjMatrix * vertex;\n"
    "}"
);

//! A string containing an OpenGL3 fragment shader for solid colouring of a polygon
static Ogre::String PixelShaderColoured_GLSL(""
    "#version 130 core\n"

    "in vec4 exColour;\n"

    "out vec4 fragColour;\n"

    "uniform float alphaPercentage;\n"

    "void main(void)\n"
    "{\n"
    "   fragColour = exColour;\n"
    "   fragColour.a *= alphaPercentage;\n"
    "}"
);

/*!
A string containing an OpenGL3 vertex shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String VertexShaderTextured_GLSL(""
    "#version 130 core\n"

    "uniform mat4 worldViewProjMatrix;\n"

    "in vec4 vertex;\n"
    "in vec4 colour;\n"
    "in vec2 uv0;\n"

    "out vec2 exTexCoord;\n"
    "out vec4 exColour;\n"

    "void main()\n"
    "{\n"
    "   exTexCoord = uv0;\n"
    "   exColour = colour;\n"

    "   gl_Position = worldViewProjMatrix * vertex;\n"
    "}"
);

/*!
A string containing an OpenGL3 fragment shader for polygons that should be coloured
based on a texture. The fetched texture colour will be multiplied by a colour
supplied to the shader, resulting in the final colour.
*/
static Ogre::String PixelShaderTextured_GLSL(""
    "#version 130 core\n"

    "uniform sampler2D texture0;\n"
    "uniform float alphaPercentage;\n"

    "in vec2 exTexCoord;\n"
    "in vec4 exColour;\n"

    "out vec4 fragColour;\n"

    "void main(void)\n"
    "{\n"
    "   fragColour = texture(texture0, exTexCoord) * exColour;\n"
    "   fragColour.a *= alphaPercentage;\n"
    "}"
);

}

<|endoftext|>


<commit_before>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CSSMediaRuleImp.h"
#include "ObjectArrayImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

using namespace css;

void CSSMediaRuleImp::append(css::CSSRule rule)
{
    ruleList.push_back(rule);
}

// CSSRule
unsigned short CSSMediaRuleImp::getType()
{
    return CSSRule::MEDIA_RULE;
}

std::u16string CSSMediaRuleImp::getCssText()
{
    std::u16string text = u"@media " + mediaList.getMediaText() + u" {";
    for (auto i = ruleList.begin(); i != ruleList.end(); ++i)
        text += (*i).getCssText();
    text += u"}";
    std::u16string media = mediaList.getMediaText();
    if (!media.empty())
        text += u" " + media;
    return text;
}

// CSSMediaRule
stylesheets::MediaList CSSMediaRuleImp::getMedia()
{
    return &mediaList;
}

void CSSMediaRuleImp::setMedia(const std::u16string& media)
{
    mediaList.setMediaText(media);
}

CSSRuleList CSSMediaRuleImp::getCssRules()
{
    return new(std::nothrow) ObjectArrayImp<CSSMediaRuleImp, CSSRule, &CSSMediaRuleImp::ruleList>(this);
}

unsigned int CSSMediaRuleImp::insertRule(const std::u16string& rule, unsigned int index)
{
    // TODO: implement me!
    return 0;
}

void CSSMediaRuleImp::deleteRule(unsigned int index)
{
    // TODO: implement me!
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(CSSMediaRuleImp::getCssText) : Fix a bug<commit_after>/*
 * Copyright 2010-2013 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CSSMediaRuleImp.h"
#include "ObjectArrayImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

using namespace css;

void CSSMediaRuleImp::append(css::CSSRule rule)
{
    ruleList.push_back(rule);
}

// CSSRule
unsigned short CSSMediaRuleImp::getType()
{
    return CSSRule::MEDIA_RULE;
}

std::u16string CSSMediaRuleImp::getCssText()
{
    std::u16string text = u"@media " + mediaList.getMediaText() + u" { ";
    for (auto i = ruleList.begin(); i != ruleList.end(); ++i)
        text += (*i).getCssText() + u" ";
    text += u'}';
    return text;
}

// CSSMediaRule
stylesheets::MediaList CSSMediaRuleImp::getMedia()
{
    return &mediaList;
}

void CSSMediaRuleImp::setMedia(const std::u16string& media)
{
    mediaList.setMediaText(media);
}

CSSRuleList CSSMediaRuleImp::getCssRules()
{
    return new(std::nothrow) ObjectArrayImp<CSSMediaRuleImp, CSSRule, &CSSMediaRuleImp::ruleList>(this);
}

unsigned int CSSMediaRuleImp::insertRule(const std::u16string& rule, unsigned int index)
{
    // TODO: implement me!
    return 0;
}

void CSSMediaRuleImp::deleteRule(unsigned int index)
{
    // TODO: implement me!
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>#include "chainerx/routines/reduction.h"

#include <cmath>
#include <cstdint>
#include <numeric>
#include <utility>
#include <vector>

#include <absl/types/optional.h>

#include "chainerx/array.h"
#include "chainerx/axes.h"
#include "chainerx/backprop_mode.h"
#include "chainerx/backward_builder.h"
#include "chainerx/backward_context.h"
#include "chainerx/dtype.h"
#include "chainerx/error.h"
#include "chainerx/graph.h"
#include "chainerx/kernels/reduction.h"
#include "chainerx/macro.h"
#include "chainerx/routines/arithmetic.h"
#include "chainerx/routines/creation.h"
#include "chainerx/routines/explog.h"
#include "chainerx/routines/manipulation.h"
#include "chainerx/routines/routines_util.h"
#include "chainerx/routines/statistics.h"
#include "chainerx/routines/type_util.h"
#include "chainerx/shape.h"

namespace chainerx {

Array Sum(const Array& a, const OptionalAxes& axis, bool keepdims) {
    Axes sorted_axis = internal::GetSortedAxesOrAll(axis, a.ndim());

    // Decide the output dtype for integral input dtype.
    Dtype out_dtype{};
    switch (GetKind(a.dtype())) {
        case DtypeKind::kBool:
        case DtypeKind::kInt:  // fallthrough
            out_dtype = Dtype::kInt64;
            break;
        case DtypeKind::kUInt:
            out_dtype = Dtype::kInt64;  // TODO(niboshi): This should be kUInt64
            break;
        default:
            out_dtype = a.dtype();
    }

    Array out = internal::EmptyReduced(a.shape(), out_dtype, sorted_axis, keepdims, a.device());
    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<SumKernel>(a, sorted_axis, out);
    }

    BackwardBuilder bb{"sum", a, out};
    if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
        bt.Define([sorted_axis, in_shape = a.shape(), keepdims](BackwardContext& bctx) {
            const Array& gout = *bctx.output_grad();
            CHAINERX_ASSERT(std::is_sorted(sorted_axis.begin(), sorted_axis.end()));

            if (!(in_shape.ndim() == 0 || sorted_axis.empty() || keepdims)) {
                Shape out_shape_broadcastable = gout.shape();
                for (auto axis : sorted_axis) {
                    out_shape_broadcastable.insert(out_shape_broadcastable.begin() + axis, 1);
                }
                bctx.input_grad() = gout.Reshape(out_shape_broadcastable).BroadcastTo(in_shape);
            } else {
                bctx.input_grad() = gout.BroadcastTo(in_shape);
            }
        });
    }
    bb.Finalize();
    return out;
}

Array Softmax(const Array& x, const OptionalAxes& axis) {
    Dtype dtype = internal::GetMathResultDtype(x.dtype());
    const Array& x_cast = x.dtype() == dtype ? x : x.AsType(dtype);
    Axes sorted_axis = internal::GetSortedAxesOrAll(axis.has_value() ? axis : OptionalAxes{1}, x.ndim());
    Array xmax = AMax(x_cast, sorted_axis, true);
    Array exps = Exp(x_cast - xmax);
    Array sums = Sum(exps, sorted_axis, true);
    return exps * Reciprocal(sums);
}

Array LogSumExp(const Array& x, const OptionalAxes& axis, bool keepdims) {
    Dtype dtype = internal::GetMathResultDtype(x.dtype());
    const Array& x_cast = x.dtype() == dtype ? x : x.AsType(dtype);
    Axes sorted_axis = internal::GetSortedAxesOrAll(axis, x.ndim());
    Array xmax = AMax(x_cast, sorted_axis, true);
    Array logs = Log(Sum(Exp(x_cast - xmax), sorted_axis, keepdims));
    return (keepdims ? xmax : Squeeze(xmax, axis)) + logs;
}

Array LogSoftmax(const Array& x, const OptionalAxes& axis) {
    Dtype dtype = internal::GetMathResultDtype(x.dtype());
    const Array& x_cast = x.dtype() == dtype ? x : x.AsType(dtype);
    return x_cast - LogSumExp(x_cast, axis.has_value() ? axis : OptionalAxes{1}, true);
}

Array Cumsum(const Array& a, absl::optional<int8_t> axis) {
    int8_t axis_norm;
    Array a_reshaped = Copy(a);
    if (axis.has_value()) {
        axis_norm = internal::NormalizeAxis(*axis, a.ndim());
    } else {
        axis_norm = 0;
        a_reshaped = a.Reshape(Shape{a.GetTotalSize()});
    }

    Shape out_shape = a_reshaped.shape();
    Array out = Empty(out_shape, a_reshaped.dtype(), a_reshaped.device());
    // Decide the output dtype for integral input dtype.
    Dtype out_dtype{};
    switch (GetKind(a_reshaped.dtype())) {
        case DtypeKind::kBool:
        case DtypeKind::kInt:  // fallthrough
            out_dtype = Dtype::kInt64;
            break;
        case DtypeKind::kUInt:
            out_dtype = Dtype::kInt64;  // TODO(niboshi): This should be kUInt64
            break;
        default:
            out_dtype = a_reshaped.dtype();
    }

    const Array& out_cast = out.AsType(out_dtype);
    const Array& a_cast = a_reshaped.dtype() != out_cast.dtype() ? a_reshaped.AsType(out_cast.dtype()) : a_reshaped;

    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<CumsumKernel>(a_cast, axis_norm, out_cast);
    }
    // Backward not implemented yet
    return out_cast;
}

}  // namespace chainerx
<commit_msg>Remove redundant copy<commit_after>#include "chainerx/routines/reduction.h"

#include <cmath>
#include <cstdint>
#include <numeric>
#include <utility>
#include <vector>

#include <absl/types/optional.h>

#include "chainerx/array.h"
#include "chainerx/axes.h"
#include "chainerx/backprop_mode.h"
#include "chainerx/backward_builder.h"
#include "chainerx/backward_context.h"
#include "chainerx/dtype.h"
#include "chainerx/error.h"
#include "chainerx/graph.h"
#include "chainerx/kernels/reduction.h"
#include "chainerx/macro.h"
#include "chainerx/routines/arithmetic.h"
#include "chainerx/routines/creation.h"
#include "chainerx/routines/explog.h"
#include "chainerx/routines/manipulation.h"
#include "chainerx/routines/routines_util.h"
#include "chainerx/routines/statistics.h"
#include "chainerx/routines/type_util.h"
#include "chainerx/shape.h"

namespace chainerx {

Array Sum(const Array& a, const OptionalAxes& axis, bool keepdims) {
    Axes sorted_axis = internal::GetSortedAxesOrAll(axis, a.ndim());

    // Decide the output dtype for integral input dtype.
    Dtype out_dtype{};
    switch (GetKind(a.dtype())) {
        case DtypeKind::kBool:
        case DtypeKind::kInt:  // fallthrough
            out_dtype = Dtype::kInt64;
            break;
        case DtypeKind::kUInt:
            out_dtype = Dtype::kInt64;  // TODO(niboshi): This should be kUInt64
            break;
        default:
            out_dtype = a.dtype();
    }

    Array out = internal::EmptyReduced(a.shape(), out_dtype, sorted_axis, keepdims, a.device());
    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<SumKernel>(a, sorted_axis, out);
    }

    BackwardBuilder bb{"sum", a, out};
    if (BackwardBuilder::Target bt = bb.CreateTarget(0)) {
        bt.Define([sorted_axis, in_shape = a.shape(), keepdims](BackwardContext& bctx) {
            const Array& gout = *bctx.output_grad();
            CHAINERX_ASSERT(std::is_sorted(sorted_axis.begin(), sorted_axis.end()));

            if (!(in_shape.ndim() == 0 || sorted_axis.empty() || keepdims)) {
                Shape out_shape_broadcastable = gout.shape();
                for (auto axis : sorted_axis) {
                    out_shape_broadcastable.insert(out_shape_broadcastable.begin() + axis, 1);
                }
                bctx.input_grad() = gout.Reshape(out_shape_broadcastable).BroadcastTo(in_shape);
            } else {
                bctx.input_grad() = gout.BroadcastTo(in_shape);
            }
        });
    }
    bb.Finalize();
    return out;
}

Array Softmax(const Array& x, const OptionalAxes& axis) {
    Dtype dtype = internal::GetMathResultDtype(x.dtype());
    const Array& x_cast = x.dtype() == dtype ? x : x.AsType(dtype);
    Axes sorted_axis = internal::GetSortedAxesOrAll(axis.has_value() ? axis : OptionalAxes{1}, x.ndim());
    Array xmax = AMax(x_cast, sorted_axis, true);
    Array exps = Exp(x_cast - xmax);
    Array sums = Sum(exps, sorted_axis, true);
    return exps * Reciprocal(sums);
}

Array LogSumExp(const Array& x, const OptionalAxes& axis, bool keepdims) {
    Dtype dtype = internal::GetMathResultDtype(x.dtype());
    const Array& x_cast = x.dtype() == dtype ? x : x.AsType(dtype);
    Axes sorted_axis = internal::GetSortedAxesOrAll(axis, x.ndim());
    Array xmax = AMax(x_cast, sorted_axis, true);
    Array logs = Log(Sum(Exp(x_cast - xmax), sorted_axis, keepdims));
    return (keepdims ? xmax : Squeeze(xmax, axis)) + logs;
}

Array LogSoftmax(const Array& x, const OptionalAxes& axis) {
    Dtype dtype = internal::GetMathResultDtype(x.dtype());
    const Array& x_cast = x.dtype() == dtype ? x : x.AsType(dtype);
    return x_cast - LogSumExp(x_cast, axis.has_value() ? axis : OptionalAxes{1}, true);
}

Array Cumsum(const Array& a, absl::optional<int8_t> axis) {
    int8_t axis_norm;
    Array a_reshaped{};
    if (axis.has_value()) {
        axis_norm = internal::NormalizeAxis(*axis, a.ndim());
        a_reshaped = Copy(a);
    } else {
        axis_norm = 0;
        // TODO(imanishi): Fix after chainerx::Ravel is supported.
        a_reshaped = a.Reshape(Shape{a.GetTotalSize()});
    }

    Shape out_shape = a_reshaped.shape();
    Array out = Empty(out_shape, a_reshaped.dtype(), a_reshaped.device());
    // Decide the output dtype for integral input dtype.
    Dtype out_dtype{};
    switch (GetKind(a_reshaped.dtype())) {
        case DtypeKind::kBool:
        case DtypeKind::kInt:  // fallthrough
            out_dtype = Dtype::kInt64;
            break;
        case DtypeKind::kUInt:
            out_dtype = Dtype::kInt64;  // TODO(niboshi): This should be kUInt64
            break;
        default:
            out_dtype = a_reshaped.dtype();
    }

    const Array& out_cast = out.AsType(out_dtype);
    const Array& a_cast = a_reshaped.dtype() != out_cast.dtype() ? a_reshaped.AsType(out_cast.dtype()) : a_reshaped;

    {
        NoBackpropModeScope scope{};
        a.device().backend().CallKernel<CumsumKernel>(a_cast, axis_norm, out_cast);
    }
    // Backward not implemented yet
    return out_cast;
}

}  // namespace chainerx
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "FirmwarePluginManager.h"
#include "FirmwarePlugin.h"

FirmwarePluginManager::FirmwarePluginManager(QGCApplication* app)
    : QGCTool(app)
    , _genericFirmwarePlugin(NULL)
{

}

FirmwarePluginManager::~FirmwarePluginManager()
{
    delete _genericFirmwarePlugin;
}

QList<MAV_AUTOPILOT> FirmwarePluginManager::knownFirmwareTypes(void)
{
    if (_knownFirmwareTypes.isEmpty()) {
        QList<FirmwarePluginFactory*> factoryList = FirmwarePluginFactoryRegister::instance()->pluginFactories();

        for (int i=0; i<factoryList.count(); i++) {
            _knownFirmwareTypes.append(factoryList[i]->knownFirmwareTypes());
        }
    }

    _knownFirmwareTypes.append(MAV_AUTOPILOT_GENERIC);

    return _knownFirmwareTypes;
}

FirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType)
{
    FirmwarePlugin* _plugin = NULL;
    QList<FirmwarePluginFactory*> factoryList = FirmwarePluginFactoryRegister::instance()->pluginFactories();

    // Find the plugin which supports this vehicle
    for (int i=0; i<factoryList.count(); i++) {
        if ((_plugin = factoryList[i]->firmwarePluginForAutopilot(autopilotType, vehicleType))) {
            return _plugin;
        }
    }

    // Default plugin fallback
    if (!_genericFirmwarePlugin) {
        _genericFirmwarePlugin = new FirmwarePlugin;
    }
    return _genericFirmwarePlugin;
}
<commit_msg>Add MAV_AUTOPILOT_GENERIC only once.<commit_after>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "FirmwarePluginManager.h"
#include "FirmwarePlugin.h"

FirmwarePluginManager::FirmwarePluginManager(QGCApplication* app)
    : QGCTool(app)
    , _genericFirmwarePlugin(NULL)
{

}

FirmwarePluginManager::~FirmwarePluginManager()
{
    delete _genericFirmwarePlugin;
}

QList<MAV_AUTOPILOT> FirmwarePluginManager::knownFirmwareTypes(void)
{
    if (_knownFirmwareTypes.isEmpty()) {
        QList<FirmwarePluginFactory*> factoryList = FirmwarePluginFactoryRegister::instance()->pluginFactories();
        for (int i = 0; i < factoryList.count(); i++) {
            _knownFirmwareTypes.append(factoryList[i]->knownFirmwareTypes());
        }
        _knownFirmwareTypes.append(MAV_AUTOPILOT_GENERIC);
    }
    return _knownFirmwareTypes;
}

FirmwarePlugin* FirmwarePluginManager::firmwarePluginForAutopilot(MAV_AUTOPILOT autopilotType, MAV_TYPE vehicleType)
{
    FirmwarePlugin* _plugin = NULL;
    QList<FirmwarePluginFactory*> factoryList = FirmwarePluginFactoryRegister::instance()->pluginFactories();

    // Find the plugin which supports this vehicle
    for (int i=0; i<factoryList.count(); i++) {
        if ((_plugin = factoryList[i]->firmwarePluginForAutopilot(autopilotType, vehicleType))) {
            return _plugin;
        }
    }

    // Default plugin fallback
    if (!_genericFirmwarePlugin) {
        _genericFirmwarePlugin = new FirmwarePlugin;
    }
    return _genericFirmwarePlugin;
}
<|endoftext|>


<commit_before>#include <iostream>

#include <boost/timer/timer.hpp>

#include "perf_sim.h"

static const uint32 PORT_LATENCY = 1;
static const uint32 PORT_FANOUT = 1;
static const uint32 PORT_BW = 1;

PerfMIPS::PerfMIPS(bool log) : Log( log), rf(), checker()
{
    executed_instrs = 0;

    wp_fetch_2_decode = make_write_port<uint32>("FETCH_2_DECODE", PORT_BW, PORT_FANOUT);
    rp_fetch_2_decode = make_read_port<uint32>("FETCH_2_DECODE", PORT_LATENCY);
    wp_decode_2_fetch_stall = make_write_port<bool>("DECODE_2_FETCH_STALL", PORT_BW, PORT_FANOUT);
    rp_decode_2_fetch_stall = make_read_port<bool>("DECODE_2_FETCH_STALL", PORT_LATENCY);

    wp_decode_2_execute = make_write_port<FuncInstr>("DECODE_2_EXECUTE", PORT_BW, PORT_FANOUT);
    rp_decode_2_execute = make_read_port<FuncInstr>("DECODE_2_EXECUTE", PORT_LATENCY);
    wp_execute_2_decode_stall = make_write_port<bool>("EXECUTE_2_DECODE_STALL", PORT_BW, PORT_FANOUT);
    rp_execute_2_decode_stall = make_read_port<bool>("EXECUTE_2_DECODE_STALL", PORT_LATENCY);

    wp_execute_2_memory = make_write_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_BW, PORT_FANOUT);
    rp_execute_2_memory = make_read_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_LATENCY);
    wp_memory_2_execute_stall = make_write_port<bool>("MEMORY_2_EXECUTE_STALL", PORT_BW, PORT_FANOUT);
    rp_memory_2_execute_stall = make_read_port<bool>("MEMORY_2_EXECUTE_STALL", PORT_LATENCY);

    wp_memory_2_writeback = make_write_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_BW, PORT_FANOUT);
    rp_memory_2_writeback = make_read_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_LATENCY);
    wp_writeback_2_memory_stall = make_write_port<bool>("WRITEBACK_2_MEMORY_STALL", PORT_BW, PORT_FANOUT);
    rp_writeback_2_memory_stall = make_read_port<bool>("WRITEBACK_2_MEMORY_STALL", PORT_LATENCY);

    init_ports();
}

void PerfMIPS::run( const std::string& tr, uint64 instrs_to_run)
{
    assert( instrs_to_run < MAX_VAL32);
    uint64 cycle = 0;

    decode_next_time = false;

    mem = new FuncMemory( tr.c_str());
    checker.init( tr);

    PC = mem->startPC();
    PC_is_valid = true;

    boost::timer::cpu_timer timer;

    while (executed_instrs < instrs_to_run)
    {
        clock_writeback( cycle);
        clock_decode( cycle);
        clock_fetch( cycle);
        clock_execute( cycle);
        clock_memory( cycle);
        ++cycle;

        if ( cycle - last_writeback_cycle >= 1000)
            serr << "Deadlock was detected. The process will be aborted.\n\n" << critical;
        sout << "Executed instructions: " << executed_instrs << std::endl << std::endl;

        check_ports( cycle);
    }

    auto time = timer.elapsed().wall;
    auto frequency = 1e6 * cycle / time;
    auto ipc = 1.0 * executed_instrs / cycle;
    auto simips = 1e6 * executed_instrs / time;

    std::cout << std::endl << "****************************"
              << std::endl << "cycles:   " << cycle
              << std::endl << "IPC:      " << ipc
              << std::endl << "sim freq: " << frequency << " kHz"
              << std::endl << "sim IPS:  " << simips    << " kips"
              << std::endl << "****************************"
              << std::endl;

    delete mem;
}

void PerfMIPS::clock_fetch( int cycle) {
    sout << "fetch   cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_decode_2_fetch_stall->read( &is_stall, cycle);
    if ( is_stall)
    {
        sout << "bubble\n";
        return;
    }

    if (PC_is_valid)
    {
        uint32 module_data = mem->read(PC);
        wp_fetch_2_decode->write( module_data, cycle);

        sout << std::hex << "0x" << module_data << std::endl;
    }
    else
    {
        sout << "bubble\n";
    }
}

void PerfMIPS::clock_decode( int cycle) {
    sout << "decode  cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_execute_2_decode_stall->read( &is_stall, cycle);
    if ( is_stall) {
        wp_decode_2_fetch_stall->write( true, cycle);

        sout << "bubble\n";
        return;
    }

    bool is_anything_from_fetch = rp_fetch_2_decode->read( &decode_data, cycle);

    FuncInstr instr( decode_data, PC);

    if ( instr.isJump() && is_anything_from_fetch)
        PC_is_valid = false;

    if ( !is_anything_from_fetch && !decode_next_time)
    {
        sout << "bubble\n";
        return;
    }

    if ( rf.check( instr.get_src1_num()) &&
         rf.check( instr.get_src2_num()) &&
         rf.check( instr.get_dst_num()))
    {
        rf.read_src1( instr);
        rf.read_src2( instr);
        rf.invalidate( instr.get_dst_num());
        wp_decode_2_execute->write( instr, cycle);

        decode_next_time = false;

        if (!instr.isJump())
            PC += 4;

        sout << instr << std::endl;
    }
    else
    {
        wp_decode_2_fetch_stall->write( true, cycle);
        decode_next_time = true;
        sout << "bubble\n";
    }
}

void PerfMIPS::clock_execute( int cycle)
{
    std::ostringstream oss;
    sout << "execute cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_memory_2_execute_stall->read( &is_stall, cycle);
    if ( is_stall)
    {
        wp_execute_2_decode_stall->write( true, cycle);

        sout << "bubble\n";
        return;
    }

    FuncInstr instr;
    if ( !rp_decode_2_execute->read( &instr, cycle))
    {
        sout << "bubble\n";
        return;
    }

    instr.execute();
    wp_execute_2_memory->write( instr, cycle);

    sout << instr << std::endl;
}

void PerfMIPS::clock_memory( int cycle)
{
    sout << "memory  cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_writeback_2_memory_stall->read( &is_stall, cycle);
    if ( is_stall)
    {
        wp_memory_2_execute_stall->write( true, cycle);
        sout << "bubble\n";
        return;
    }

    FuncInstr instr;
    if ( !rp_execute_2_memory->read( &instr, cycle))
    {
        sout << "bubble\n";
        return;
    }

    load_store(instr);
    wp_memory_2_writeback->write( instr, cycle);

    sout << instr << std::endl;
}

void PerfMIPS::clock_writeback( int cycle)
{
    sout << "wb      cycle " << std::dec << cycle << ":";

    FuncInstr instr;
    if ( !rp_memory_2_writeback->read( &instr, cycle))
    {
        sout << "bubble\n";
        return;
    }

    if ( instr.isJump())
    {
        PC_is_valid = true;
        PC = instr.get_new_PC();
    }

    rf.write_dst( instr);

    sout << instr << std::endl;

    check(instr);

    ++executed_instrs;
    last_writeback_cycle = cycle;
}

void PerfMIPS::check( const FuncInstr& instr)
{
    std::ostringstream perf_dump_s;
    perf_dump_s << instr << std::endl;
    std::string perf_dump = perf_dump_s.str();

    std::ostringstream checker_dump_s;
    checker.step(checker_dump_s);
    std::string checker_dump = checker_dump_s.str();

    if (checker_dump != perf_dump)
    {
        serr << "****************************" << std::endl
             << "Mismatch: " << std::endl
             << "Checker output: " << checker_dump
             << "PerfSim output: " << perf_dump
             << critical;
    }
}

PerfMIPS::~PerfMIPS() {

}
<commit_msg>Move deadlock detector to WB stage<commit_after>#include <iostream>

#include <boost/timer/timer.hpp>

#include "perf_sim.h"

static const uint32 PORT_LATENCY = 1;
static const uint32 PORT_FANOUT = 1;
static const uint32 PORT_BW = 1;

PerfMIPS::PerfMIPS(bool log) : Log( log), rf(), checker()
{
    executed_instrs = 0;

    wp_fetch_2_decode = make_write_port<uint32>("FETCH_2_DECODE", PORT_BW, PORT_FANOUT);
    rp_fetch_2_decode = make_read_port<uint32>("FETCH_2_DECODE", PORT_LATENCY);
    wp_decode_2_fetch_stall = make_write_port<bool>("DECODE_2_FETCH_STALL", PORT_BW, PORT_FANOUT);
    rp_decode_2_fetch_stall = make_read_port<bool>("DECODE_2_FETCH_STALL", PORT_LATENCY);

    wp_decode_2_execute = make_write_port<FuncInstr>("DECODE_2_EXECUTE", PORT_BW, PORT_FANOUT);
    rp_decode_2_execute = make_read_port<FuncInstr>("DECODE_2_EXECUTE", PORT_LATENCY);
    wp_execute_2_decode_stall = make_write_port<bool>("EXECUTE_2_DECODE_STALL", PORT_BW, PORT_FANOUT);
    rp_execute_2_decode_stall = make_read_port<bool>("EXECUTE_2_DECODE_STALL", PORT_LATENCY);

    wp_execute_2_memory = make_write_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_BW, PORT_FANOUT);
    rp_execute_2_memory = make_read_port<FuncInstr>("EXECUTE_2_MEMORY", PORT_LATENCY);
    wp_memory_2_execute_stall = make_write_port<bool>("MEMORY_2_EXECUTE_STALL", PORT_BW, PORT_FANOUT);
    rp_memory_2_execute_stall = make_read_port<bool>("MEMORY_2_EXECUTE_STALL", PORT_LATENCY);

    wp_memory_2_writeback = make_write_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_BW, PORT_FANOUT);
    rp_memory_2_writeback = make_read_port<FuncInstr>("MEMORY_2_WRITEBACK", PORT_LATENCY);
    wp_writeback_2_memory_stall = make_write_port<bool>("WRITEBACK_2_MEMORY_STALL", PORT_BW, PORT_FANOUT);
    rp_writeback_2_memory_stall = make_read_port<bool>("WRITEBACK_2_MEMORY_STALL", PORT_LATENCY);

    init_ports();
}

void PerfMIPS::run( const std::string& tr, uint64 instrs_to_run)
{
    assert( instrs_to_run < MAX_VAL32);
    uint64 cycle = 0;

    decode_next_time = false;

    mem = new FuncMemory( tr.c_str());
    checker.init( tr);

    PC = mem->startPC();
    PC_is_valid = true;

    boost::timer::cpu_timer timer;

    while (executed_instrs < instrs_to_run)
    {
        clock_writeback( cycle);
        clock_decode( cycle);
        clock_fetch( cycle);
        clock_execute( cycle);
        clock_memory( cycle);
        ++cycle;

        sout << "Executed instructions: " << executed_instrs << std::endl << std::endl;

        check_ports( cycle);
    }

    auto time = timer.elapsed().wall;
    auto frequency = 1e6 * cycle / time;
    auto ipc = 1.0 * executed_instrs / cycle;
    auto simips = 1e6 * executed_instrs / time;

    std::cout << std::endl << "****************************"
              << std::endl << "cycles:   " << cycle
              << std::endl << "IPC:      " << ipc
              << std::endl << "sim freq: " << frequency << " kHz"
              << std::endl << "sim IPS:  " << simips    << " kips"
              << std::endl << "****************************"
              << std::endl;

    delete mem;
}

void PerfMIPS::clock_fetch( int cycle) {
    sout << "fetch   cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_decode_2_fetch_stall->read( &is_stall, cycle);
    if ( is_stall)
    {
        sout << "bubble\n";
        return;
    }

    if (PC_is_valid)
    {
        uint32 module_data = mem->read(PC);
        wp_fetch_2_decode->write( module_data, cycle);

        sout << std::hex << "0x" << module_data << std::endl;
    }
    else
    {
        sout << "bubble\n";
    }
}

void PerfMIPS::clock_decode( int cycle) {
    sout << "decode  cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_execute_2_decode_stall->read( &is_stall, cycle);
    if ( is_stall) {
        wp_decode_2_fetch_stall->write( true, cycle);

        sout << "bubble\n";
        return;
    }

    bool is_anything_from_fetch = rp_fetch_2_decode->read( &decode_data, cycle);

    FuncInstr instr( decode_data, PC);

    if ( instr.isJump() && is_anything_from_fetch)
        PC_is_valid = false;

    if ( !is_anything_from_fetch && !decode_next_time)
    {
        sout << "bubble\n";
        return;
    }

    if ( rf.check( instr.get_src1_num()) &&
         rf.check( instr.get_src2_num()) &&
         rf.check( instr.get_dst_num()))
    {
        rf.read_src1( instr);
        rf.read_src2( instr);
        rf.invalidate( instr.get_dst_num());
        wp_decode_2_execute->write( instr, cycle);

        decode_next_time = false;

        if (!instr.isJump())
            PC += 4;

        sout << instr << std::endl;
    }
    else
    {
        wp_decode_2_fetch_stall->write( true, cycle);
        decode_next_time = true;
        sout << "bubble\n";
    }
}

void PerfMIPS::clock_execute( int cycle)
{
    std::ostringstream oss;
    sout << "execute cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_memory_2_execute_stall->read( &is_stall, cycle);
    if ( is_stall)
    {
        wp_execute_2_decode_stall->write( true, cycle);

        sout << "bubble\n";
        return;
    }

    FuncInstr instr;
    if ( !rp_decode_2_execute->read( &instr, cycle))
    {
        sout << "bubble\n";
        return;
    }

    instr.execute();
    wp_execute_2_memory->write( instr, cycle);

    sout << instr << std::endl;
}

void PerfMIPS::clock_memory( int cycle)
{
    sout << "memory  cycle " << std::dec << cycle << ":";

    bool is_stall = false;
    rp_writeback_2_memory_stall->read( &is_stall, cycle);
    if ( is_stall)
    {
        wp_memory_2_execute_stall->write( true, cycle);
        sout << "bubble\n";
        return;
    }

    FuncInstr instr;
    if ( !rp_execute_2_memory->read( &instr, cycle))
    {
        sout << "bubble\n";
        return;
    }

    load_store(instr);
    wp_memory_2_writeback->write( instr, cycle);

    sout << instr << std::endl;
}

void PerfMIPS::clock_writeback( int cycle)
{
    sout << "wb      cycle " << std::dec << cycle << ":";

    FuncInstr instr;
    if ( !rp_memory_2_writeback->read( &instr, cycle))
    {
        sout << "bubble\n";
        if ( cycle - last_writeback_cycle >= 1000)
        {
            serr << "Deadlock was detected. The process will be aborted."
                 << std::endl << std::endl << critical;
        }
        return;
    }

    if ( instr.isJump())
    {
        PC_is_valid = true;
        PC = instr.get_new_PC();
    }

    rf.write_dst( instr);

    sout << instr << std::endl;

    check(instr);

    ++executed_instrs;
    last_writeback_cycle = cycle;
}

void PerfMIPS::check( const FuncInstr& instr)
{
    std::ostringstream perf_dump_s;
    perf_dump_s << instr << std::endl;
    std::string perf_dump = perf_dump_s.str();

    std::ostringstream checker_dump_s;
    checker.step(checker_dump_s);
    std::string checker_dump = checker_dump_s.str();

    if (checker_dump != perf_dump)
    {
        serr << "****************************" << std::endl
             << "Mismatch: " << std::endl
             << "Checker output: " << checker_dump
             << "PerfSim output: " << perf_dump
             << critical;
    }
}

PerfMIPS::~PerfMIPS() {

}
<|endoftext|>