<commit_before>#include <iostream>
#include <fstream>
#include <regex>

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn/dnn.hpp>

using namespace cv;
using namespace cv::dnn;

std::string keys =
        "{ help  h                          | | Print help message. }"
        "{ inputImage i                     | | Path to an input image. Skip this argument to capture frames from a camera. }"
        "{ modelPath mp                     | | Path to a binary .onnx file contains trained DB detector model. "
            "Download links are provided in doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown}"
        "{ inputHeight ih                    |736| image height of the model input. It should be multiple by 32.}"
        "{ inputWidth iw                     |736| image width of the model input. It should be multiple by 32.}"
        "{ binaryThreshold bt               |0.3| Confidence threshold of the binary map. }"
        "{ polygonThreshold pt              |0.5| Confidence threshold of polygons. }"
        "{ maxCandidate max                 |200| Max candidates of polygons. }"
        "{ unclipRatio ratio                |2.0| unclip ratio. }"
        "{ evaluate e                       |false| false: predict with input images; true: evaluate on benchmarks. }"
        "{ evalDataPath edp                  | | Path to benchmarks for evaluation. "
            "Download links are provided in doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown}";

int main(int argc, char** argv)
{
    // Parse arguments
    CommandLineParser parser(argc, argv, keys);
    parser.about("Use this script to run the official PyTorch implementation (https://github.com/MhLiao/DB) of "
                 "Real-time Scene Text Detection with Differentiable Binarization (https://arxiv.org/abs/1911.08947)\n"
                 "The current version of this script is a variant of the original network without deformable convolution");
    if (argc == 1 || parser.has("help"))
    {
        parser.printMessage();
        return 0;
    }

    float binThresh = parser.get<float>("binaryThreshold");
    float polyThresh = parser.get<float>("polygonThreshold");
    uint maxCandidates = parser.get<uint>("maxCandidate");
    String modelPath = parser.get<String>("modelPath");
    double unclipRatio = parser.get<double>("unclipRatio");
    int height = parser.get<int>("inputHeight");
    int width = parser.get<int>("inputWidth");

    if (!parser.check())
    {
        parser.printErrors();
        return 1;
    }

    // Load the network
    CV_Assert(!modelPath.empty());
    TextDetectionModel_DB detector(modelPath);
    detector.setBinaryThreshold(binThresh)
            .setPolygonThreshold(polyThresh)
            .setUnclipRatio(unclipRatio)
            .setMaxCandidates(maxCandidates);

    double scale = 1.0 / 255.0;
    Size inputSize = Size(width, height);
    Scalar mean = Scalar(122.67891434, 116.66876762, 104.00698793);
    detector.setInputParams(scale, inputSize, mean);

    // Create a window
    static const std::string winName = "TextDetectionModel";

    if (parser.get<bool>("evaluate")) {
        // for evaluation
        String evalDataPath = parser.get<String>("evalDataPath");
        CV_Assert(!evalDataPath.empty());
        String testListPath = evalDataPath + "/test_list.txt";
        std::ifstream testList;
        testList.open(testListPath);
        CV_Assert(testList.is_open());

        // Create a window for showing groundtruth
        static const std::string winNameGT = "GT";

        String testImgPath;
        while (std::getline(testList, testImgPath)) {
            String imgPath = evalDataPath + "/test_images/" + testImgPath;
            std::cout << "Image Path: " << imgPath << std::endl;

            Mat frame = imread(samples::findFile(imgPath), IMREAD_COLOR);
            CV_Assert(!frame.empty());
            Mat src = frame.clone();

            // Inference
            std::vector<std::vector<Point>> results;
            detector.detect(frame, results);

            polylines(frame, results, true, Scalar(0, 255, 0), 2);
            imshow(winName, frame);

            // load groundtruth
            String imgName = testImgPath.substr(0, testImgPath.length() - 4);
            String gtPath = evalDataPath + "/test_gts/" + imgName + ".txt";
            // std::cout << gtPath << std::endl;
            std::ifstream gtFile;
            gtFile.open(gtPath);
            CV_Assert(gtFile.is_open());

            std::vector<std::vector<Point>> gts;
            String gtLine;
            while (std::getline(gtFile, gtLine)) {
                size_t splitLoc = gtLine.find_last_of(',');
                String text = gtLine.substr(splitLoc+1);
                if ( text == "###\r" || text == "1") {
                    // ignore difficult instances
                    continue;
                }
                gtLine = gtLine.substr(0, splitLoc);

                std::regex delimiter(",");
                std::vector<String> v(std::sregex_token_iterator(gtLine.begin(), gtLine.end(), delimiter, -1),
                                      std::sregex_token_iterator());
                std::vector<int> loc;
                std::vector<Point> pts;
                for (auto && s : v) {
                    loc.push_back(atoi(s.c_str()));
                }
                for (size_t i = 0; i < loc.size() / 2; i++) {
                    pts.push_back(Point(loc[2 * i], loc[2 * i + 1]));
                }
                gts.push_back(pts);
            }
            polylines(src, gts, true, Scalar(0, 255, 0), 2);
            imshow(winNameGT, src);

            waitKey();
        }
    } else {
        // Open an image file
        CV_Assert(parser.has("inputImage"));
        Mat frame = imread(samples::findFile(parser.get<String>("inputImage")));
        CV_Assert(!frame.empty());

        // Detect
        std::vector<std::vector<Point>> results;
        detector.detect(frame, results);

        polylines(frame, results, true, Scalar(0, 255, 0), 2);
        imshow(winName, frame);
        waitKey();
    }

    return 0;
}
<commit_msg>samples: replace regex<commit_after>#include <iostream>
#include <fstream>

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/dnn/dnn.hpp>

using namespace cv;
using namespace cv::dnn;

std::string keys =
        "{ help  h                          | | Print help message. }"
        "{ inputImage i                     | | Path to an input image. Skip this argument to capture frames from a camera. }"
        "{ modelPath mp                     | | Path to a binary .onnx file contains trained DB detector model. "
            "Download links are provided in doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown}"
        "{ inputHeight ih                    |736| image height of the model input. It should be multiple by 32.}"
        "{ inputWidth iw                     |736| image width of the model input. It should be multiple by 32.}"
        "{ binaryThreshold bt               |0.3| Confidence threshold of the binary map. }"
        "{ polygonThreshold pt              |0.5| Confidence threshold of polygons. }"
        "{ maxCandidate max                 |200| Max candidates of polygons. }"
        "{ unclipRatio ratio                |2.0| unclip ratio. }"
        "{ evaluate e                       |false| false: predict with input images; true: evaluate on benchmarks. }"
        "{ evalDataPath edp                  | | Path to benchmarks for evaluation. "
            "Download links are provided in doc/tutorials/dnn/dnn_text_spotting/dnn_text_spotting.markdown}";

static
void split(const std::string& s, char delimiter, std::vector<std::string>& elems)
{
    elems.clear();
    size_t prev_pos = 0;
    size_t pos = 0;
    while ((pos = s.find(delimiter, prev_pos)) != std::string::npos)
    {
        elems.emplace_back(s.substr(prev_pos, pos - prev_pos));
        prev_pos = pos + 1;
    }
    if (prev_pos < s.size())
        elems.emplace_back(s.substr(prev_pos, s.size() - prev_pos));
}

int main(int argc, char** argv)
{
    // Parse arguments
    CommandLineParser parser(argc, argv, keys);
    parser.about("Use this script to run the official PyTorch implementation (https://github.com/MhLiao/DB) of "
                 "Real-time Scene Text Detection with Differentiable Binarization (https://arxiv.org/abs/1911.08947)\n"
                 "The current version of this script is a variant of the original network without deformable convolution");
    if (argc == 1 || parser.has("help"))
    {
        parser.printMessage();
        return 0;
    }

    float binThresh = parser.get<float>("binaryThreshold");
    float polyThresh = parser.get<float>("polygonThreshold");
    uint maxCandidates = parser.get<uint>("maxCandidate");
    String modelPath = parser.get<String>("modelPath");
    double unclipRatio = parser.get<double>("unclipRatio");
    int height = parser.get<int>("inputHeight");
    int width = parser.get<int>("inputWidth");

    if (!parser.check())
    {
        parser.printErrors();
        return 1;
    }

    // Load the network
    CV_Assert(!modelPath.empty());
    TextDetectionModel_DB detector(modelPath);
    detector.setBinaryThreshold(binThresh)
            .setPolygonThreshold(polyThresh)
            .setUnclipRatio(unclipRatio)
            .setMaxCandidates(maxCandidates);

    double scale = 1.0 / 255.0;
    Size inputSize = Size(width, height);
    Scalar mean = Scalar(122.67891434, 116.66876762, 104.00698793);
    detector.setInputParams(scale, inputSize, mean);

    // Create a window
    static const std::string winName = "TextDetectionModel";

    if (parser.get<bool>("evaluate")) {
        // for evaluation
        String evalDataPath = parser.get<String>("evalDataPath");
        CV_Assert(!evalDataPath.empty());
        String testListPath = evalDataPath + "/test_list.txt";
        std::ifstream testList;
        testList.open(testListPath);
        CV_Assert(testList.is_open());

        // Create a window for showing groundtruth
        static const std::string winNameGT = "GT";

        String testImgPath;
        while (std::getline(testList, testImgPath)) {
            String imgPath = evalDataPath + "/test_images/" + testImgPath;
            std::cout << "Image Path: " << imgPath << std::endl;

            Mat frame = imread(samples::findFile(imgPath), IMREAD_COLOR);
            CV_Assert(!frame.empty());
            Mat src = frame.clone();

            // Inference
            std::vector<std::vector<Point>> results;
            detector.detect(frame, results);

            polylines(frame, results, true, Scalar(0, 255, 0), 2);
            imshow(winName, frame);

            // load groundtruth
            String imgName = testImgPath.substr(0, testImgPath.length() - 4);
            String gtPath = evalDataPath + "/test_gts/" + imgName + ".txt";
            // std::cout << gtPath << std::endl;
            std::ifstream gtFile;
            gtFile.open(gtPath);
            CV_Assert(gtFile.is_open());

            std::vector<std::vector<Point>> gts;
            String gtLine;
            while (std::getline(gtFile, gtLine)) {
                size_t splitLoc = gtLine.find_last_of(',');
                String text = gtLine.substr(splitLoc+1);
                if ( text == "###\r" || text == "1") {
                    // ignore difficult instances
                    continue;
                }
                gtLine = gtLine.substr(0, splitLoc);

                std::vector<std::string> v;
                split(gtLine, ',', v);

                std::vector<int> loc;
                std::vector<Point> pts;
                for (auto && s : v) {
                    loc.push_back(atoi(s.c_str()));
                }
                for (size_t i = 0; i < loc.size() / 2; i++) {
                    pts.push_back(Point(loc[2 * i], loc[2 * i + 1]));
                }
                gts.push_back(pts);
            }
            polylines(src, gts, true, Scalar(0, 255, 0), 2);
            imshow(winNameGT, src);

            waitKey();
        }
    } else {
        // Open an image file
        CV_Assert(parser.has("inputImage"));
        Mat frame = imread(samples::findFile(parser.get<String>("inputImage")));
        CV_Assert(!frame.empty());

        // Detect
        std::vector<std::vector<Point>> results;
        detector.detect(frame, results);

        polylines(frame, results, true, Scalar(0, 255, 0), 2);
        imshow(winName, frame);
        waitKey();
    }

    return 0;
}
<|endoftext|>


<commit_before>/***********************************************************************
created:    4/6/2012
author:     Lukas E Meindl
*************************************************************************/
/***************************************************************************
*   Copyright (C) 2004 - 2012 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 "SampleData.h"
#include "Sample.h"

#include "Samples_xmlHandler.h"

#include "CEGUI/DynamicModule.h"
#include "CEGUI/Version.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/System.h"
#include "CEGUI/TextureTarget.h"
#include "CEGUI/BasicImage.h"
#include "CEGUI/GUIContext.h"
#include "CEGUI/Texture.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/Window.h"
#include "CEGUI/Vector.h"

using namespace CEGUI;

#define S_(X) #X
#define STRINGIZE(X) S_(X)

typedef Sample& (*getSampleInstance)();
#define GetSampleInstanceFuncName "getSampleInstance"

SampleData::SampleData(CEGUI::String sampleName,
                       CEGUI::String summary,
                       CEGUI::String description,
                       SampleType sampleTypeEnum,
                       CEGUI::String credits)
    : d_name(sampleName)
    , d_summary(summary)
    , d_description(description)
    , d_type(sampleTypeEnum)
    , d_usedFilesString("")
    , d_credits(credits)
    , d_sampleWindow(0)
    , d_guiContext(0)
    , d_textureTarget(0)
    , d_textureTargetImage(0)
{
}

SampleData::~SampleData()
{

}

CEGUI::String SampleData::getName()
{
    return d_name;
}

CEGUI::String SampleData::getSummary()
{
    return "Summary:\n" + d_summary;
}

CEGUI::String SampleData::getCredits()
{
    return "Credits:\n" + d_credits;
}

CEGUI::String SampleData::getSampleTypeString()
{
    switch(d_type)
    {
    case ST_Module:
        return SampleDataHandler::SampleTypeCppModule;
        break;
    case ST_Lua:
        return SampleDataHandler::SampleTypeLua;
        break;
    case ST_Python:
        return SampleDataHandler::SampleTypePython;
    default:
        return "";
    }
}

CEGUI::String SampleData::getDescription()
{
    return "Description:\n" + d_description;
}

CEGUI::String SampleData::getUsedFilesString()
{
    return "Used files:\n" + d_usedFilesString;
}

void SampleData::setSampleWindow(CEGUI::Window* sampleWindow)
{
    d_sampleWindow = sampleWindow;
}

CEGUI::Window* SampleData::getSampleWindow()
{
    return d_sampleWindow;
}

void SampleData::initialise(int width, int height)
{
    CEGUI::System& system(System::getSingleton());

    CEGUI::Sizef size(static_cast<float>(width), static_cast<float>(height));

    d_textureTarget = system.getRenderer()->createTextureTarget();
    d_guiContext = &system.createGUIContext((RenderTarget&)*d_textureTarget);
    d_textureTarget->declareRenderSize(size);

    CEGUI::String imageName(d_textureTarget->getTexture().getName());
    d_textureTargetImage = static_cast<CEGUI::BasicImage*>(&CEGUI::ImageManager::getSingleton().create("BasicImage", "SampleBrowser/" + imageName));
    d_textureTargetImage->setTexture(&d_textureTarget->getTexture());

    setTextureTargetImageArea(static_cast<float>(height), static_cast<float>(width));
}

void SampleData::deinitialise()
{
    CEGUI::System& system(System::getSingleton());

    if(d_guiContext)
    {
        system.destroyGUIContext(*d_guiContext);
        d_guiContext = 0;
    }

    if(d_textureTarget)
    {
        system.getRenderer()->destroyTextureTarget(d_textureTarget);
        d_textureTarget = 0;
    }

    if(d_textureTargetImage)
    {
        CEGUI::ImageManager::getSingleton().destroy(*d_textureTargetImage);
        d_textureTargetImage = 0;
    }
}

GUIContext* SampleData::getGuiContext()
{
    return d_guiContext;
}

void SampleData::handleNewWindowSize(float width, float height)
{
    setTextureTargetImageArea(height, width);

    CEGUI::Sizef windowSize(width, height);
    if(d_textureTarget)
    {
        d_textureTarget->declareRenderSize(windowSize);

        d_sampleWindow->getRenderingSurface()->invalidate();
    }
}

CEGUI::Image& SampleData::getRTTImage()
{
    return *d_textureTargetImage;
}

void SampleData::setGUIContextRTT()
{
    d_guiContext->setRenderTarget(*d_textureTarget);
}

void SampleData::clearRTTTexture()
{
    d_textureTarget->clear();
}

void SampleData::setTextureTargetImageArea(float height, float width)
{
    if(d_textureTarget)
    {
        bool isTextureTargetVerticallyFlipped = d_textureTarget->isRenderingInverted();
        CEGUI::Rectf renderArea;
        if(isTextureTargetVerticallyFlipped)
            renderArea = CEGUI::Rectf(0.0f, height, width, 0.0f);
        else
            renderArea = CEGUI::Rectf(0.0f, 0.0f, width, height);

        if(d_textureTargetImage)
            d_textureTargetImage->setArea(renderArea);
    }
}

//----------------------------------------------------------------------------//
SampleDataModule::SampleDataModule(CEGUI::String sampleName,
                                   CEGUI::String summary,
                                   CEGUI::String description,
                                   SampleType sampleTypeEnum,
                                   CEGUI::String credits)
    : SampleData(sampleName, summary, description, sampleTypeEnum, credits)
    , d_dynamicModule(0)
    , d_sample(0)
{
}

SampleDataModule::~SampleDataModule()
{
}

void SampleDataModule::initialise(int width, int height)
{
    SampleData::initialise(width, height);

    getSampleInstanceFromDLL();

    d_sample->initialise(d_guiContext);
    d_usedFilesString = d_sample->getUsedFilesString();
}

void SampleDataModule::deinitialise()
{
    if(d_sample)
        d_sample->deinitialise();

    SampleData::deinitialise();
}

void SampleDataModule::getSampleInstanceFromDLL()
{
    CEGUI::DynamicModule* sampleModule = new CEGUI::DynamicModule(d_name);
    getSampleInstance functionPointerGetSample = (getSampleInstance)sampleModule->getSymbolAddress(CEGUI::String(GetSampleInstanceFuncName));

    if(functionPointerGetSample == 0)
    {
        CEGUI::String errorMessage = "The sample creation function is not defined in the dynamic library of " + d_name;
        CEGUI_THROW(CEGUI::InvalidRequestException(errorMessage.c_str()));
    }

    d_sample =  &(functionPointerGetSample());
}

void SampleDataModule::onEnteringSample()
{
    d_sample->onEnteringSample();
}

void SampleDataModule::update(float timeSinceLastUpdate)
{
    d_sample->update(timeSinceLastUpdate);
}
<commit_msg>Undo an addition of a new line at the end of "samples_framework/src/SampleData.cpp".<commit_after>/***********************************************************************
created:    4/6/2012
author:     Lukas E Meindl
*************************************************************************/
/***************************************************************************
*   Copyright (C) 2004 - 2012 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 "SampleData.h"
#include "Sample.h"

#include "Samples_xmlHandler.h"

#include "CEGUI/DynamicModule.h"
#include "CEGUI/Version.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/System.h"
#include "CEGUI/TextureTarget.h"
#include "CEGUI/BasicImage.h"
#include "CEGUI/GUIContext.h"
#include "CEGUI/Texture.h"
#include "CEGUI/ImageManager.h"
#include "CEGUI/Window.h"
#include "CEGUI/Vector.h"

using namespace CEGUI;

#define S_(X) #X
#define STRINGIZE(X) S_(X)

typedef Sample& (*getSampleInstance)();
#define GetSampleInstanceFuncName "getSampleInstance"

SampleData::SampleData(CEGUI::String sampleName,
                       CEGUI::String summary,
                       CEGUI::String description,
                       SampleType sampleTypeEnum,
                       CEGUI::String credits)
    : d_name(sampleName)
    , d_summary(summary)
    , d_description(description)
    , d_type(sampleTypeEnum)
    , d_usedFilesString("")
    , d_credits(credits)
    , d_sampleWindow(0)
    , d_guiContext(0)
    , d_textureTarget(0)
    , d_textureTargetImage(0)
{
}

SampleData::~SampleData()
{

}

CEGUI::String SampleData::getName()
{
    return d_name;
}

CEGUI::String SampleData::getSummary()
{
    return "Summary:\n" + d_summary;
}

CEGUI::String SampleData::getCredits()
{
    return "Credits:\n" + d_credits;
}

CEGUI::String SampleData::getSampleTypeString()
{
    switch(d_type)
    {
    case ST_Module:
        return SampleDataHandler::SampleTypeCppModule;
        break;
    case ST_Lua:
        return SampleDataHandler::SampleTypeLua;
        break;
    case ST_Python:
        return SampleDataHandler::SampleTypePython;
    default:
        return "";
    }
}

CEGUI::String SampleData::getDescription()
{
    return "Description:\n" + d_description;
}

CEGUI::String SampleData::getUsedFilesString()
{
    return "Used files:\n" + d_usedFilesString;
}

void SampleData::setSampleWindow(CEGUI::Window* sampleWindow)
{
    d_sampleWindow = sampleWindow;
}

CEGUI::Window* SampleData::getSampleWindow()
{
    return d_sampleWindow;
}

void SampleData::initialise(int width, int height)
{
    CEGUI::System& system(System::getSingleton());

    CEGUI::Sizef size(static_cast<float>(width), static_cast<float>(height));

    d_textureTarget = system.getRenderer()->createTextureTarget();
    d_guiContext = &system.createGUIContext((RenderTarget&)*d_textureTarget);
    d_textureTarget->declareRenderSize(size);

    CEGUI::String imageName(d_textureTarget->getTexture().getName());
    d_textureTargetImage = static_cast<CEGUI::BasicImage*>(&CEGUI::ImageManager::getSingleton().create("BasicImage", "SampleBrowser/" + imageName));
    d_textureTargetImage->setTexture(&d_textureTarget->getTexture());

    setTextureTargetImageArea(static_cast<float>(height), static_cast<float>(width));
}

void SampleData::deinitialise()
{
    CEGUI::System& system(System::getSingleton());

    if(d_guiContext)
    {
        system.destroyGUIContext(*d_guiContext);
        d_guiContext = 0;
    }

    if(d_textureTarget)
    {
        system.getRenderer()->destroyTextureTarget(d_textureTarget);
        d_textureTarget = 0;
    }

    if(d_textureTargetImage)
    {
        CEGUI::ImageManager::getSingleton().destroy(*d_textureTargetImage);
        d_textureTargetImage = 0;
    }
}

GUIContext* SampleData::getGuiContext()
{
    return d_guiContext;
}

void SampleData::handleNewWindowSize(float width, float height)
{
    setTextureTargetImageArea(height, width);

    CEGUI::Sizef windowSize(width, height);
    if(d_textureTarget)
    {
        d_textureTarget->declareRenderSize(windowSize);

        d_sampleWindow->getRenderingSurface()->invalidate();
    }
}

CEGUI::Image& SampleData::getRTTImage()
{
    return *d_textureTargetImage;
}

void SampleData::setGUIContextRTT()
{
    d_guiContext->setRenderTarget(*d_textureTarget);
}

void SampleData::clearRTTTexture()
{
    d_textureTarget->clear();
}

void SampleData::setTextureTargetImageArea(float height, float width)
{
    if(d_textureTarget)
    {
        bool isTextureTargetVerticallyFlipped = d_textureTarget->isRenderingInverted();
        CEGUI::Rectf renderArea;
        if(isTextureTargetVerticallyFlipped)
            renderArea = CEGUI::Rectf(0.0f, height, width, 0.0f);
        else
            renderArea = CEGUI::Rectf(0.0f, 0.0f, width, height);

        if(d_textureTargetImage)
            d_textureTargetImage->setArea(renderArea);
    }
}

//----------------------------------------------------------------------------//
SampleDataModule::SampleDataModule(CEGUI::String sampleName,
                                   CEGUI::String summary,
                                   CEGUI::String description,
                                   SampleType sampleTypeEnum,
                                   CEGUI::String credits)
    : SampleData(sampleName, summary, description, sampleTypeEnum, credits)
    , d_dynamicModule(0)
    , d_sample(0)
{
}

SampleDataModule::~SampleDataModule()
{
}

void SampleDataModule::initialise(int width, int height)
{
    SampleData::initialise(width, height);

    getSampleInstanceFromDLL();

    d_sample->initialise(d_guiContext);
    d_usedFilesString = d_sample->getUsedFilesString();
}

void SampleDataModule::deinitialise()
{
    if(d_sample)
        d_sample->deinitialise();

    SampleData::deinitialise();
}

void SampleDataModule::getSampleInstanceFromDLL()
{
    CEGUI::DynamicModule* sampleModule = new CEGUI::DynamicModule(d_name);
    getSampleInstance functionPointerGetSample = (getSampleInstance)sampleModule->getSymbolAddress(CEGUI::String(GetSampleInstanceFuncName));

    if(functionPointerGetSample == 0)
    {
        CEGUI::String errorMessage = "The sample creation function is not defined in the dynamic library of " + d_name;
        CEGUI_THROW(CEGUI::InvalidRequestException(errorMessage.c_str()));
    }

    d_sample =  &(functionPointerGetSample());
}

void SampleDataModule::onEnteringSample()
{
    d_sample->onEnteringSample();
}

void SampleDataModule::update(float timeSinceLastUpdate)
{
    d_sample->update(timeSinceLastUpdate);
}<|endoftext|>


<commit_before>#pragma once
#include <cstdint>

namespace haste {

using std::uint32_t;

enum class entity_type : uint32_t {
    camera = 0,
    mesh = 1,
    light = 2,
    empty = 3
};

inline uint32_t encode_material(uint32_t material_id, entity_type type) {
    return material_id << 2 | uint32_t(type);
}

inline uint32_t decode_material(uint32_t material_id) {
    return material_id >> 2;
}

struct SurfacePoint {
    vec3 _position;
    vec3 gnormal;
    mat3 _tangent;
    uint32_t material_id = UINT32_MAX;

    SurfacePoint() = default;

    SurfacePoint(
        const vec3& position,
        const vec3& normal,
        const vec3& tangent,
        uint32_t material_id)
    {
        _position = position;
        _tangent[0] = normalize(cross(normal, tangent));
        _tangent[1] = normal;
        _tangent[2] = tangent;
        material_id = material_id;
    }

    const vec3& position() const { return _position; }
    const vec3& normal() const { return _tangent[1]; }
    const vec3& tangent() const { return _tangent[2]; }
    const vec3& bitangent() const { return _tangent[0]; }
    const vec3 toWorld(const vec3& surface) const { return _tangent * surface; }
    const vec3 toSurface(const vec3& world) const { return world * _tangent; }

    uint32_t material_index() const { return material_id >> 2; }

    bool is_camera() const { return (material_id & 3u) == uint32_t(entity_type::camera); }
    bool is_mesh() const { return (material_id & 3u) == uint32_t(entity_type::mesh); }
    bool is_light() const { return (material_id & 3u) == uint32_t(entity_type::light); }
    bool is_present() const { return material_id != UINT32_MAX; }
};

}
<commit_msg>Add pack unpack functions.<commit_after>#pragma once
#include <cstdint>

namespace haste {

using std::uint32_t;

enum class entity_type : uint32_t {
    camera = 0,
    mesh = 1,
    light = 2,
    empty = 3
};

inline uint32_t encode_material(uint32_t material_id, entity_type type) {
    return material_id << 2 | uint32_t(type);
}

inline uint32_t decode_material(uint32_t material_id) {
    return material_id >> 2;
}

inline uint32_t pack_normal(vec3 n) {
    float x = clamp((n.x + 1.0f) * 0.5f, 0.f, 1.0f) * 65534.f;
    float y = clamp((n.y + 1.0f) * 0.5f, 0.f, 1.0f) * 32766.f;
    float z = n.z < 0.0f ? 0.0f : 1.0f;
    return uint32_t(x) << 16 | uint32_t(y) << 1 | uint32_t(z);
}

inline vec3 unpack_normal(uint32_t n) {
    float x = float(n >> 16) * 3.05185094e-05f - 1.0f;
    float y = float(n << 16 >> 17) * 6.10388817e-05f - 1.0f;
    float z = sqrt(1.0f - x * x - y * y) * (float(n & 1u) - 0.5f) * 2.0f;
    return vec3(x, y, z);
}

struct SurfacePoint {
    vec3 _position;
    vec3 gnormal;
    mat3 _tangent;
    uint32_t material_id = UINT32_MAX;

    SurfacePoint() = default;

    SurfacePoint(
        const vec3& position,
        const vec3& normal,
        const vec3& tangent,
        uint32_t material_id)
    {
        _position = position;
        _tangent[0] = normalize(cross(normal, tangent));
        _tangent[1] = normal;
        _tangent[2] = tangent;
        material_id = material_id;
    }

    const vec3& position() const { return _position; }
    const vec3& normal() const { return _tangent[1]; }
    const vec3& tangent() const { return _tangent[2]; }
    const vec3& bitangent() const { return _tangent[0]; }
    const vec3 toWorld(const vec3& surface) const { return _tangent * surface; }
    const vec3 toSurface(const vec3& world) const { return world * _tangent; }

    uint32_t material_index() const { return material_id >> 2; }

    bool is_camera() const { return (material_id & 3u) == uint32_t(entity_type::camera); }
    bool is_mesh() const { return (material_id & 3u) == uint32_t(entity_type::mesh); }
    bool is_light() const { return (material_id & 3u) == uint32_t(entity_type::light); }
    bool is_present() const { return material_id != UINT32_MAX; }
};

}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

   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 <paddle/framework/lod_rank_table.h>
#include "paddle/framework/op_registry.h"
#include "paddle/operators/detail/safe_ref.h"

namespace paddle {
namespace operators {

class ReorderLoDTensorByRankTableOpProtoMaker
    : public framework::OpProtoAndCheckerMaker {
 public:
  ReorderLoDTensorByRankTableOpProtoMaker(OpProto *proto,
                                          OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("X", "(LoDTensor) the input lod tensor need to be reordered.");
    AddInput("RankTable",
             "(LoDRankTable) the rank table that input need follow");
    AddOutput("Out", "(LoDTensor) reordered lod tensor");
    AddComment(R"DOC(ReorderLoDTensorByRankTable

Reorder the input X by the rank of `RankTable`. If `RankTable` is ordered by
index [3, 0, 2, 1]. Input X will reorder its sequence, the third sequence of
X will be the first sequence of Output.

NOTE: The RankTable does not need to be calculated by X.

For example:
The X = [Seq0, Seq1, Seq2, Seq3]. The indices of RankTable are [3, 0, 2, 1].

The Out =  [Seq3, Seq0, Seq2, Seq1] with correct LoD information.
)DOC");
  }
};

class ReorderLoDTensorByRankTableBase : public framework::OperatorBase {
 public:
  ReorderLoDTensorByRankTableBase(const std::string &type,
                                  const framework::VariableNameMap &inputs,
                                  const framework::VariableNameMap &outputs,
                                  const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}
  void Run(const framework::Scope &scope,
           const platform::DeviceContext &dev_ctx) const override {
    auto &x =
        detail::Ref(scope.FindVar(Input("X")),
                    "Cannot find input lod tensor variable %s", Input("X"))
            .Get<framework::LoDTensor>();
    auto &rank_table = detail::Ref(scope.FindVar(Input("RankTable")),
                                   "Cannot find input rank table variable %s",
                                   Input("RankTable"))
                           .Get<framework::LoDRankTable>();
    auto &out =
        *detail::Ref(scope.FindVar(Output("Out")),
                     "Cannot find output lod tensor variable %s", Output("Out"))
             .GetMutable<framework::LoDTensor>();

    out.Resize(x.dims());
    out.mutable_data(x.place(), x.type());
    this->process(dev_ctx, x, rank_table, &out);
  }

 protected:
  virtual void process(const platform::DeviceContext &dev_ctx,
                       const framework::LoDTensor &x,
                       const framework::LoDRankTable &rank_table,
                       framework::LoDTensor *out) const = 0;

  struct AbsoluteRankTableItem {
    size_t offset;  // the absolute/accumulated offset.
    size_t length;  // the length
    framework::LoD lod;
  };

  std::vector<AbsoluteRankTableItem> GetAbsoluteOffsetAndLengthByLoDRankTable(
      const framework::LoDTensor &x) const {
    std::vector<AbsoluteRankTableItem> absolute_table;
    size_t level = 0;
    size_t size = x.lod()[level].size();

    for (size_t i = 0; i < size - 1; ++i) {
      auto lod_offset =
          framework::GetSubLoDAndAbsoluteOffset(x.lod(), i, i + 1, level);

      auto &offset = lod_offset.second;

      absolute_table.emplace_back();
      absolute_table.back().length = offset.second - offset.first;
      absolute_table.back().offset = offset.first;
      absolute_table.back().lod = lod_offset.first;
    }
    return absolute_table;
  }

  size_t CopyTensorAndLod(const platform::DeviceContext &dev_ctx,
                          const AbsoluteRankTableItem &item,
                          const framework::LoDTensor &x,
                          framework::LoDTensor *out, size_t out_offset) const {
    auto &out_lod = *out->mutable_lod();
    auto len = item.length;
    auto x_offset = item.offset;

    if (out_lod.empty()) {
      for (size_t i = 0; i < item.lod.size(); ++i) {
        out_lod.push_back(std::vector<size_t>({0}));
      }
    }

    for (size_t i = 0; i < out_lod.size(); ++i) {
      auto &out_v = out_lod[i];
      auto &new_lod_v = item.lod[i];

      for (auto &detail : new_lod_v) {
        out_v.push_back(out_v.back() + detail);
      }
    }

    auto x_sliced = x.Slice(x_offset, x_offset + len);
    auto out_sliced = out->Slice(out_offset, out_offset + len);

    framework::CopyFrom(x_sliced, out_sliced.place(), dev_ctx, &out_sliced);
    out_offset += len;
    return out_offset;
  }
};

class ReorderLoDTensorByRankTableOp : public ReorderLoDTensorByRankTableBase {
 public:
  ReorderLoDTensorByRankTableOp(const std::string &type,
                                const framework::VariableNameMap &inputs,
                                const framework::VariableNameMap &outputs,
                                const framework::AttributeMap &attrs)
      : ReorderLoDTensorByRankTableBase(type, inputs, outputs, attrs) {}

 protected:
  void process(const platform::DeviceContext &dev_ctx,
               const framework::LoDTensor &x,
               const framework::LoDRankTable &rank_table,
               framework::LoDTensor *out) const override {
    auto absolute_table = GetAbsoluteOffsetAndLengthByLoDRankTable(x);
    size_t out_offset = 0;
    out->mutable_lod()->clear();
    for (auto &item : rank_table.items()) {
      PADDLE_ENFORCE_LT(item.index, absolute_table.size());
      out_offset = CopyTensorAndLod(dev_ctx, absolute_table[item.index], x, out,
                                    out_offset);
    }
  }
};

class IdentityInferShape : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *context) const override {
    context->SetOutputDim("Out", context->GetInputDim("X"));
  }
};

class ReorderLodTensorByRankGradOpMaker
    : public framework::SingleGradOpDescMaker {
 public:
  using framework::SingleGradOpDescMaker::SingleGradOpDescMaker;

 protected:
  std::unique_ptr<framework::OpDescBind> Apply() const override {
    auto *grad_op = new framework::OpDescBind();
    grad_op->SetType("reorder_lod_tensor_by_rank_grad");
    grad_op->SetInput("X", OutputGrad("Out"));
    grad_op->SetOutput("Out", InputGrad("X"));
    grad_op->SetInput("RankTable", Input("RankTable"));
    return std::unique_ptr<framework::OpDescBind>(grad_op);
  }
};

class ReorderLoDTensorByRankGradOp : public ReorderLoDTensorByRankTableBase {
 public:
  ReorderLoDTensorByRankGradOp(const std::string &type,
                               const framework::VariableNameMap &inputs,
                               const framework::VariableNameMap &outputs,
                               const framework::AttributeMap &attrs)
      : ReorderLoDTensorByRankTableBase(type, inputs, outputs, attrs) {}

 protected:
  void process(const platform::DeviceContext &dev_ctx,
               const framework::LoDTensor &x,
               const framework::LoDRankTable &rank_table,
               framework::LoDTensor *out) const override {
    auto absolute_table = GetAbsoluteOffsetAndLengthByLoDRankTable(x);

    // offsets = enumerate([item.index for item in rank_table.items()])
    std::vector<std::pair<size_t, size_t>> offsets;
    offsets.reserve(rank_table.items().size());
    for (size_t i = 0; i < rank_table.items().size(); ++i) {
      offsets.push_back({i, rank_table.items()[i].index});
    }

    // offsets.sort(key=lambda x: x[1])
    std::sort(
        offsets.begin(), offsets.end(),
        [](const std::pair<size_t, size_t> &a,
           const std::pair<size_t, size_t> &b) { return a.second < b.second; });

    // Copy TensorAndLod
    size_t out_offset = 0;
    for (auto &offset : offsets) {
      out_offset = this->CopyTensorAndLod(dev_ctx, absolute_table[offset.first],
                                          x, out, out_offset);
    }
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OPERATOR(reorder_lod_tensor_by_rank,
                  ops::ReorderLoDTensorByRankTableOp,
                  ops::ReorderLodTensorByRankGradOpMaker,
                  ops::ReorderLoDTensorByRankTableOpProtoMaker,
                  ops::IdentityInferShape);
REGISTER_OPERATOR(reorder_lod_tensor_by_rank_grad,
                  ops::ReorderLoDTensorByRankGradOp, ops::IdentityInferShape);
<commit_msg>Fix Compile<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

   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 <paddle/framework/lod_rank_table.h>
#include "paddle/framework/op_registry.h"
#include "paddle/operators/detail/safe_ref.h"

namespace paddle {
namespace operators {

class ReorderLoDTensorByRankTableOpProtoMaker
    : public framework::OpProtoAndCheckerMaker {
 public:
  ReorderLoDTensorByRankTableOpProtoMaker(OpProto *proto,
                                          OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("X", "(LoDTensor) the input lod tensor need to be reordered.");
    AddInput("RankTable",
             "(LoDRankTable) the rank table that input need follow");
    AddOutput("Out", "(LoDTensor) reordered lod tensor");
    AddComment(R"DOC(ReorderLoDTensorByRankTable

Reorder the input X by the rank of `RankTable`. If `RankTable` is ordered by
index [3, 0, 2, 1]. Input X will reorder its sequence, the third sequence of
X will be the first sequence of Output.

NOTE: The RankTable does not need to be calculated by X.

For example:
The X = [Seq0, Seq1, Seq2, Seq3]. The indices of RankTable are [3, 0, 2, 1].

The Out =  [Seq3, Seq0, Seq2, Seq1] with correct LoD information.
)DOC");
  }
};

class ReorderLoDTensorByRankTableBase : public framework::OperatorBase {
 public:
  ReorderLoDTensorByRankTableBase(const std::string &type,
                                  const framework::VariableNameMap &inputs,
                                  const framework::VariableNameMap &outputs,
                                  const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}
  void Run(const framework::Scope &scope,
           const platform::DeviceContext &dev_ctx) const override {
    auto &x =
        detail::Ref(scope.FindVar(Input("X")),
                    "Cannot find input lod tensor variable %s", Input("X"))
            .Get<framework::LoDTensor>();
    auto &rank_table = detail::Ref(scope.FindVar(Input("RankTable")),
                                   "Cannot find input rank table variable %s",
                                   Input("RankTable"))
                           .Get<framework::LoDRankTable>();
    auto &out =
        *detail::Ref(scope.FindVar(Output("Out")),
                     "Cannot find output lod tensor variable %s", Output("Out"))
             .GetMutable<framework::LoDTensor>();

    out.Resize(x.dims());
    out.mutable_data(x.place(), x.type());
    this->process(dev_ctx, x, rank_table, &out);
  }

 protected:
  virtual void process(const platform::DeviceContext &dev_ctx,
                       const framework::LoDTensor &x,
                       const framework::LoDRankTable &rank_table,
                       framework::LoDTensor *out) const = 0;

  struct AbsoluteRankTableItem {
    size_t offset;  // the absolute/accumulated offset.
    size_t length;  // the length
    framework::LoD lod;
  };

  std::vector<AbsoluteRankTableItem> GetAbsoluteOffsetAndLengthByLoDRankTable(
      const framework::LoDTensor &x) const {
    std::vector<AbsoluteRankTableItem> absolute_table;
    size_t level = 0;
    size_t size = x.lod()[level].size();

    for (size_t i = 0; i < size - 1; ++i) {
      auto lod_offset =
          framework::GetSubLoDAndAbsoluteOffset(x.lod(), i, i + 1, level);

      auto &offset = lod_offset.second;

      absolute_table.emplace_back();
      absolute_table.back().length = offset.second - offset.first;
      absolute_table.back().offset = offset.first;
      absolute_table.back().lod = lod_offset.first;
    }
    return absolute_table;
  }

  size_t CopyTensorAndLod(const platform::DeviceContext &dev_ctx,
                          const AbsoluteRankTableItem &item,
                          const framework::LoDTensor &x,
                          framework::LoDTensor *out, size_t out_offset) const {
    auto &out_lod = *out->mutable_lod();
    auto len = item.length;
    auto x_offset = item.offset;

    if (out_lod.empty()) {
      for (size_t i = 0; i < item.lod.size(); ++i) {
        out_lod.push_back(std::vector<size_t>({0}));
      }
    }

    for (size_t i = 0; i < out_lod.size(); ++i) {
      auto &out_v = out_lod[i];
      auto &new_lod_v = item.lod[i];

      for (auto &detail : new_lod_v) {
        out_v.push_back(out_v.back() + detail);
      }
    }

    auto x_sliced = x.Slice(x_offset, x_offset + len);
    auto out_sliced = out->Slice(out_offset, out_offset + len);

    framework::CopyFrom(x_sliced, out_sliced.place(), dev_ctx, &out_sliced);
    out_offset += len;
    return out_offset;
  }
};

class ReorderLoDTensorByRankTableOp : public ReorderLoDTensorByRankTableBase {
 public:
  ReorderLoDTensorByRankTableOp(const std::string &type,
                                const framework::VariableNameMap &inputs,
                                const framework::VariableNameMap &outputs,
                                const framework::AttributeMap &attrs)
      : ReorderLoDTensorByRankTableBase(type, inputs, outputs, attrs) {}

 protected:
  void process(const platform::DeviceContext &dev_ctx,
               const framework::LoDTensor &x,
               const framework::LoDRankTable &rank_table,
               framework::LoDTensor *out) const override {
    auto absolute_table = GetAbsoluteOffsetAndLengthByLoDRankTable(x);
    size_t out_offset = 0;
    out->mutable_lod()->clear();
    for (auto &item : rank_table.items()) {
      PADDLE_ENFORCE_LT(item.index, absolute_table.size());
      out_offset = CopyTensorAndLod(dev_ctx, absolute_table[item.index], x, out,
                                    out_offset);
    }
  }
};

class IdentityInferShape : public framework::InferShapeBase {
 public:
  void operator()(framework::InferShapeContext *context) const override {
    context->SetOutputDim("Out", context->GetInputDim("X"));
  }
};

class ReorderLodTensorByRankGradOpMaker
    : public framework::SingleGradOpDescMaker {
 public:
  using framework::SingleGradOpDescMaker::SingleGradOpDescMaker;

 protected:
  std::unique_ptr<framework::OpDesc> Apply() const override {
    auto *grad_op = new framework::OpDesc();
    grad_op->SetType("reorder_lod_tensor_by_rank_grad");
    grad_op->SetInput("X", OutputGrad("Out"));
    grad_op->SetOutput("Out", InputGrad("X"));
    grad_op->SetInput("RankTable", Input("RankTable"));
    return std::unique_ptr<framework::OpDesc>(grad_op);
  }
};

class ReorderLoDTensorByRankGradOp : public ReorderLoDTensorByRankTableBase {
 public:
  ReorderLoDTensorByRankGradOp(const std::string &type,
                               const framework::VariableNameMap &inputs,
                               const framework::VariableNameMap &outputs,
                               const framework::AttributeMap &attrs)
      : ReorderLoDTensorByRankTableBase(type, inputs, outputs, attrs) {}

 protected:
  void process(const platform::DeviceContext &dev_ctx,
               const framework::LoDTensor &x,
               const framework::LoDRankTable &rank_table,
               framework::LoDTensor *out) const override {
    auto absolute_table = GetAbsoluteOffsetAndLengthByLoDRankTable(x);

    // offsets = enumerate([item.index for item in rank_table.items()])
    std::vector<std::pair<size_t, size_t>> offsets;
    offsets.reserve(rank_table.items().size());
    for (size_t i = 0; i < rank_table.items().size(); ++i) {
      offsets.push_back({i, rank_table.items()[i].index});
    }

    // offsets.sort(key=lambda x: x[1])
    std::sort(
        offsets.begin(), offsets.end(),
        [](const std::pair<size_t, size_t> &a,
           const std::pair<size_t, size_t> &b) { return a.second < b.second; });

    // Copy TensorAndLod
    size_t out_offset = 0;
    for (auto &offset : offsets) {
      out_offset = this->CopyTensorAndLod(dev_ctx, absolute_table[offset.first],
                                          x, out, out_offset);
    }
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OPERATOR(reorder_lod_tensor_by_rank,
                  ops::ReorderLoDTensorByRankTableOp,
                  ops::ReorderLodTensorByRankGradOpMaker,
                  ops::ReorderLoDTensorByRankTableOpProtoMaker,
                  ops::IdentityInferShape);
REGISTER_OPERATOR(reorder_lod_tensor_by_rank_grad,
                  ops::ReorderLoDTensorByRankGradOp, ops::IdentityInferShape);
<|endoftext|>


<commit_before>#include "../include/cmakefile.h"
#include "../include/cmakefunction.h"
#include <algorithm>
#include <iostream>

namespace {

bool contains(const std::string& target, const std::string& search) {
  return target.find(search) != std::string::npos;
}

bool functionMatches(const std::shared_ptr<CmakeFunction>& f, const std::string& functionName, const std::string& argument) {
  if (!contains(f->name(), functionName) || f->arguments().empty()) {
    return false;
  }

  return std::any_of(f->arguments().begin(), f->arguments().end(), [argument](const CmakeFunctionArgument& arg) {
    return contains(arg.value(), argument);
  });
}

std::shared_ptr<CmakeFunction> findFunction(const std::vector<std::shared_ptr<CmakeFunction>>& functions, const std::string& functionName, const std::string& argument) {
  for (const auto& f : functions) {
    if (functionMatches(f, functionName, argument)) {
      return f;
    }
  }

  return nullptr;
}

std::shared_ptr<CmakeFunction> findProjectTarget(const std::vector<std::shared_ptr<CmakeFunction>>& functions, const std::string& argument) {
  const auto& target = findFunction(functions, "add_executable", argument);
  return target ? target : findFunction(functions, "add_library", argument);
}

int calculateFilesOffset(const std::shared_ptr<CmakeFunction>& filesFunction, const std::vector<std::string>& files) {
  int offsetForFirstArgument = (filesFunction->line() == filesFunction->arguments()[0].line()) ? 0 : 1;

  const auto offset = files.size() - (filesFunction->arguments().size() - offsetForFirstArgument) + 1;

  return offset;
}

int calculateIncludeFilesOffset(const std::shared_ptr<CmakeFunction>& includeFilesFunction, const std::vector<std::string>& includeFiles) {
  // no include files in project
  if (!includeFilesFunction && includeFiles.empty()) {
    return 0;
  }

  // include files added
  if (!includeFilesFunction && !includeFiles.empty()) {
    return includeFiles.size() + 3;
  }

  // all include files removed
  if (includeFilesFunction && includeFiles.empty()) {
    int offsetForFirstArgument = (includeFilesFunction->line() == includeFilesFunction->arguments()[0].line()) ? 0 : 1;
    return -(includeFilesFunction->arguments().size() + offsetForFirstArgument + 2);
  }

  return calculateFilesOffset(includeFilesFunction, includeFiles);
}

void updateArguments(const std::shared_ptr<CmakeFunction>& f, const std::vector<std::string>& files) {
  std::vector<CmakeFunctionArgument> newArguments = {};
  newArguments.push_back(f->arguments()[0]);

  int line = f->arguments()[0].line() + 1;
  for (const auto& file : files) {
    newArguments.emplace_back(file, true, line++, 2);
  }
  f->setArguments(newArguments);
  f->setEndLine(line);
}

}

CmakeFile::CmakeFile(std::string path, std::vector<std::shared_ptr<CmakeFunction>> functions)
  : path_(path), functions_(functions) {
}

const std::string& CmakeFile::path() const {
  return path_;
}

const std::vector<std::shared_ptr<CmakeFunction>>& CmakeFile::functions() const {
  return functions_;
}

void CmakeFile::updateFiles(const std::vector<std::string>& includeFiles, const std::vector<std::string>& srcFiles) {
  const auto includeFilesFunction = findFunction(functions_, "set", "INCLUDE_FILES");
  const auto srcFilesFunction = findFunction(functions_, "set", "SRC_FILES");

  const auto includeFilesOffset = calculateIncludeFilesOffset(includeFilesFunction, includeFiles);
  const auto srcOffset = calculateFilesOffset(srcFilesFunction, srcFiles);

  bool setIncludeFilesOffset = false;
  if (includeFiles.empty() && includeFilesFunction) {
    setIncludeFilesOffset = true;
    removeIncludeFilesFunction();
  } else if (!includeFiles.empty() && !includeFilesFunction) {
    setIncludeFilesOffset = true;
    addIncludeFilesFunction(srcFilesFunction, includeFiles);
  }

  int lineOffset = 0;
  for (const auto& f : functions_) {
    if (functionMatches(f, "set", "INCLUDE_FILES")) {
      updateArguments(f, includeFiles);
      lineOffset = includeFilesOffset;
    } else if (functionMatches(f, "set", "SRC_FILES")) {
      if (setIncludeFilesOffset) {
        lineOffset = includeFilesOffset;
      }
      updateArguments(f, srcFiles);
      f->addLineOffset(lineOffset);
      lineOffset += srcOffset;
    } else {
      f->addLineOffset(lineOffset);
    }
  }
}

void CmakeFile::removeIncludeFilesFunction() {
  functions_.erase(std::remove_if(functions_.begin(), functions_.end(), [](const auto& f) {
      return functionMatches(f, "set", "INCLUDE_FILES");
  }));

  const auto& target = findProjectTarget(functions_, "INCLUDE_FILES");
  if (!target) {
    return;
  }

  int newColumnPosition = 0;
  std::vector<CmakeFunctionArgument> shiftedArguments = {};
  std::transform(target->arguments().begin(), target->arguments().end(), std::back_inserter(shiftedArguments), [&newColumnPosition](const auto& argument) {
    const auto argumentColumn = newColumnPosition;
    if (newColumnPosition || contains(argument.value(), "INCLUDE_FILES")) {
      newColumnPosition = argument.column();
    }

    return CmakeFunctionArgument{argument.value(), argument.quoted(), argument.line(), (argumentColumn ? argumentColumn : argument.column())};
  });

  std::vector<CmakeFunctionArgument> arguments = {};
  std::copy_if(shiftedArguments.begin(), shiftedArguments.end(), std::back_inserter(arguments), [](const auto& argument) {
      return !contains(argument.value(), "INCLUDE_FILES");
  });

  target->setArguments(arguments);
}

void CmakeFile::addIncludeFilesFunction(const std::shared_ptr<CmakeFunction>& srcFilesFunction, const std::vector<std::string>& includeFiles) {
  std::vector<CmakeFunctionArgument> arguments = {};
  arguments.push_back({"INCLUDE_FILES", false, srcFilesFunction->line(), 5});

  int line = srcFilesFunction->line() + 1;
  std::transform(includeFiles.begin(), includeFiles.end(), std::back_inserter(arguments), [&line](const std::string& file) {
    return CmakeFunctionArgument{file, true, line++, 2};
  });
  functions_.insert(std::find(functions_.begin(), functions_.end(), srcFilesFunction), CmakeFunction::create("set",srcFilesFunction->line(),arguments));

  const auto& target = findProjectTarget(functions_, "SRC_FILES");
  if (!target) {
    return;
  }

  std::vector<CmakeFunctionArgument> newArguments = {};
  const int includeFilesArgumentSize = 17;
  bool includeFilesArgumentInserted = false;
  for (int i = target->arguments().size() - 1; i >= 0; i--) {
    const auto& argument = target->arguments()[i];

    if (contains(argument.value(), "SRC_FILES")) {
      newArguments.push_back(CmakeFunctionArgument{argument.value(), argument.quoted(), argument.line(), argument.column() + includeFilesArgumentSize});
      newArguments.push_back(CmakeFunctionArgument{"${INCLUDE_FILES}", false, argument.line(), argument.column()});
      includeFilesArgumentInserted = true;
      continue;
    }

    const int column = includeFilesArgumentInserted ? argument.column() : argument.column() + includeFilesArgumentSize;

    newArguments.push_back(CmakeFunctionArgument{argument.value(), argument.quoted(), argument.line(), column});
  }

  target->setArguments({newArguments.crbegin(), newArguments.crend()});
}<commit_msg>fixed segfault when trying to update project without files<commit_after>#include "../include/cmakefile.h"
#include "../include/cmakefunction.h"
#include <algorithm>
#include <iostream>

namespace {

bool contains(const std::string& target, const std::string& search) {
  return target.find(search) != std::string::npos;
}

bool functionMatches(const std::shared_ptr<CmakeFunction>& f, const std::string& functionName, const std::string& argument) {
  if (!contains(f->name(), functionName) || f->arguments().empty()) {
    return false;
  }

  return std::any_of(f->arguments().begin(), f->arguments().end(), [argument](const CmakeFunctionArgument& arg) {
    return contains(arg.value(), argument);
  });
}

std::shared_ptr<CmakeFunction> findFunction(const std::vector<std::shared_ptr<CmakeFunction>>& functions, const std::string& functionName, const std::string& argument) {
  for (const auto& f : functions) {
    if (functionMatches(f, functionName, argument)) {
      return f;
    }
  }

  return nullptr;
}

std::shared_ptr<CmakeFunction> findProjectTarget(const std::vector<std::shared_ptr<CmakeFunction>>& functions, const std::string& argument) {
  const auto& target = findFunction(functions, "add_executable", argument);
  return target ? target : findFunction(functions, "add_library", argument);
}

int calculateFilesOffset(const std::shared_ptr<CmakeFunction>& filesFunction, const std::vector<std::string>& files) {
  int offsetForFirstArgument = (filesFunction->line() == filesFunction->arguments()[0].line()) ? 0 : 1;

  const auto offset = files.size() - (filesFunction->arguments().size() - offsetForFirstArgument) + 1;

  return offset;
}

int calculateIncludeFilesOffset(const std::shared_ptr<CmakeFunction>& includeFilesFunction, const std::vector<std::string>& includeFiles) {
  // no include files in project
  if (!includeFilesFunction && includeFiles.empty()) {
    return 0;
  }

  // include files added
  if (!includeFilesFunction && !includeFiles.empty()) {
    return includeFiles.size() + 3;
  }

  // all include files removed
  if (includeFilesFunction && includeFiles.empty()) {
    int offsetForFirstArgument = (includeFilesFunction->line() == includeFilesFunction->arguments()[0].line()) ? 0 : 1;
    return -(includeFilesFunction->arguments().size() + offsetForFirstArgument + 2);
  }

  return calculateFilesOffset(includeFilesFunction, includeFiles);
}

void updateArguments(const std::shared_ptr<CmakeFunction>& f, const std::vector<std::string>& files) {
  std::vector<CmakeFunctionArgument> newArguments = {};
  newArguments.push_back(f->arguments()[0]);

  int line = f->arguments()[0].line() + 1;
  for (const auto& file : files) {
    newArguments.emplace_back(file, true, line++, 2);
  }
  f->setArguments(newArguments);
  f->setEndLine(line);
}

}

CmakeFile::CmakeFile(std::string path, std::vector<std::shared_ptr<CmakeFunction>> functions)
  : path_(path), functions_(functions) {
}

const std::string& CmakeFile::path() const {
  return path_;
}

const std::vector<std::shared_ptr<CmakeFunction>>& CmakeFile::functions() const {
  return functions_;
}

void CmakeFile::updateFiles(const std::vector<std::string>& includeFiles, const std::vector<std::string>& srcFiles) {
  // don't update if there are no files
  if (includeFiles.empty() && srcFiles.empty()) {
    return;
  }

  const auto includeFilesFunction = findFunction(functions_, "set", "INCLUDE_FILES");
  const auto srcFilesFunction = findFunction(functions_, "set", "SRC_FILES");

  const auto includeFilesOffset = calculateIncludeFilesOffset(includeFilesFunction, includeFiles);
  const auto srcOffset = calculateFilesOffset(srcFilesFunction, srcFiles);

  bool setIncludeFilesOffset = false;
  if (includeFiles.empty() && includeFilesFunction) {
    setIncludeFilesOffset = true;
    removeIncludeFilesFunction();
  } else if (!includeFiles.empty() && !includeFilesFunction) {
    setIncludeFilesOffset = true;
    addIncludeFilesFunction(srcFilesFunction, includeFiles);
  }

  int lineOffset = 0;
  for (const auto& f : functions_) {
    if (functionMatches(f, "set", "INCLUDE_FILES")) {
      updateArguments(f, includeFiles);
      lineOffset = includeFilesOffset;
    } else if (functionMatches(f, "set", "SRC_FILES")) {
      if (setIncludeFilesOffset) {
        lineOffset = includeFilesOffset;
      }
      updateArguments(f, srcFiles);
      f->addLineOffset(lineOffset);
      lineOffset += srcOffset;
    } else {
      f->addLineOffset(lineOffset);
    }
  }
}

void CmakeFile::removeIncludeFilesFunction() {
  functions_.erase(std::remove_if(functions_.begin(), functions_.end(), [](const auto& f) {
      return functionMatches(f, "set", "INCLUDE_FILES");
  }));

  const auto& target = findProjectTarget(functions_, "INCLUDE_FILES");
  if (!target) {
    return;
  }

  int newColumnPosition = 0;
  std::vector<CmakeFunctionArgument> shiftedArguments = {};
  std::transform(target->arguments().begin(), target->arguments().end(), std::back_inserter(shiftedArguments), [&newColumnPosition](const auto& argument) {
    const auto argumentColumn = newColumnPosition;
    if (newColumnPosition || contains(argument.value(), "INCLUDE_FILES")) {
      newColumnPosition = argument.column();
    }

    return CmakeFunctionArgument{argument.value(), argument.quoted(), argument.line(), (argumentColumn ? argumentColumn : argument.column())};
  });

  std::vector<CmakeFunctionArgument> arguments = {};
  std::copy_if(shiftedArguments.begin(), shiftedArguments.end(), std::back_inserter(arguments), [](const auto& argument) {
      return !contains(argument.value(), "INCLUDE_FILES");
  });

  target->setArguments(arguments);
}

void CmakeFile::addIncludeFilesFunction(const std::shared_ptr<CmakeFunction>& srcFilesFunction, const std::vector<std::string>& includeFiles) {
  std::vector<CmakeFunctionArgument> arguments = {};
  arguments.push_back({"INCLUDE_FILES", false, srcFilesFunction->line(), 5});

  int line = srcFilesFunction->line() + 1;
  std::transform(includeFiles.begin(), includeFiles.end(), std::back_inserter(arguments), [&line](const std::string& file) {
    return CmakeFunctionArgument{file, true, line++, 2};
  });
  functions_.insert(std::find(functions_.begin(), functions_.end(), srcFilesFunction), CmakeFunction::create("set",srcFilesFunction->line(),arguments));

  const auto& target = findProjectTarget(functions_, "SRC_FILES");
  if (!target) {
    return;
  }

  std::vector<CmakeFunctionArgument> newArguments = {};
  const int includeFilesArgumentSize = 17;
  bool includeFilesArgumentInserted = false;
  for (int i = target->arguments().size() - 1; i >= 0; i--) {
    const auto& argument = target->arguments()[i];

    if (contains(argument.value(), "SRC_FILES")) {
      newArguments.push_back(CmakeFunctionArgument{argument.value(), argument.quoted(), argument.line(), argument.column() + includeFilesArgumentSize});
      newArguments.push_back(CmakeFunctionArgument{"${INCLUDE_FILES}", false, argument.line(), argument.column()});
      includeFilesArgumentInserted = true;
      continue;
    }

    const int column = includeFilesArgumentInserted ? argument.column() : argument.column() + includeFilesArgumentSize;

    newArguments.push_back(CmakeFunctionArgument{argument.value(), argument.quoted(), argument.line(), column});
  }

  target->setArguments({newArguments.crbegin(), newArguments.crend()});
}<|endoftext|>


<commit_before>/*
 * Copyright 2016 Andrei Pangin
 *
 * 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <cxxabi.h>
#include "codeCache.h"
#include "vmEntry.h"

static inline bool isString(jmethodID method) {
    return (intptr_t)method < 0;
}

static inline char* asString(jmethodID method) {
    return (char*)(-(intptr_t)method);
}

static inline jmethodID asJavaMethod(const char* name) {
    return (jmethodID)(-(intptr_t)name);
}

static inline void terminateOnSpace(char* name) {
    char *space = strchr(name, ' ');
    if (space != NULL) {
        *space = '\0';
    }
}

MethodName::MethodName(jmethodID method, const char* sep) {
    if (method == NULL) {
        _str = "[unknown]";
    } else if (isString(method)) {
        _str = demangle(asString(method));
    } else {
        jclass method_class;
        char* class_name;
        char* method_name;

        jvmtiEnv* jvmti = VM::jvmti();
        jvmti->GetMethodName(method, &method_name, NULL, NULL);
        jvmti->GetMethodDeclaringClass(method, &method_class);
        jvmti->GetClassSignature(method_class, &class_name, NULL);

        snprintf(_buf, sizeof(_buf), "%s%s%s", fixClassName(class_name), sep, method_name);
        _str = _buf;

        jvmti->Deallocate((unsigned char*)class_name);
        jvmti->Deallocate((unsigned char*)method_name);
    }

    terminateOnSpace((char *)_str);
}

char* MethodName::fixClassName(char* name) {
    char* s;
    for (s = name + 1; *s; s++) {
        if (*s == '/') *s = '.';
    }
    s[-1] = 0;
    return name + 1;
}

char* MethodName::demangle(char* name) {
    if (name != NULL && name[0] == '_' && name[1] == 'Z') {
        int status;
        char* demangled = abi::__cxa_demangle(name, NULL, NULL, &status);
        if (demangled != NULL) {
            strncpy(_buf, demangled, sizeof(_buf));
            free(demangled);
            return _buf;
        }
    }

    // Defensive copy
    strncpy(_buf, name, sizeof (_buf));
    return _buf;
}

StringTable* StringTable::allocate(StringTable* next, int capacity, int size) {
    StringTable* st = (StringTable*)malloc(sizeof(StringTable) + capacity);
    st->_next = next;
    st->_capacity = capacity;
    st->_size = size;
    return st;
}

StringTable* StringTable::destroy() {
    StringTable* next = _next;
    free(this);
    return next;
}

const char* StringTable::add(const char* s, int length) {
    const char* result = (const char*)memcpy(_data + _size, s, length);
    _size += length;
    return result;
}

CodeCache::CodeCache(const char* name, const void* min_address, const void* max_address) {
    _name = strdup(name);
    _capacity = INITIAL_CODE_CACHE_CAPACITY;
    _count = 0;
    _blobs = (CodeBlob*)malloc(_capacity * sizeof(CodeBlob));
    _strings = NULL;
    _min_address = min_address;
    _max_address = max_address;
}

CodeCache::~CodeCache() {
    for (StringTable* st = _strings; st != NULL; ) {
        st = st->destroy();
    }
    free(_blobs);
    free(_name);
}

const char* CodeCache::addString(const char* s) {
    int length = strlen(s) + 1;
    if (_strings == NULL || _strings->remaining() < length) {
        _strings = StringTable::allocate(_strings, STRING_TABLE_CHUNK);
    }
    return _strings->add(s, length);
}

const char* CodeCache::addStrings(const char* s, int length) {
    _strings = StringTable::allocate(_strings, length);
    return _strings->add(s, length);
}

void CodeCache::add(const void* start, int length, jmethodID method) {
    const char* end = (const char*)start + length;
    if (start < _min_address) _min_address = start;
    if (end > _max_address) _max_address = end;

    if (_count >= _capacity) {
        // Note: we do not free old block here; it can be concurrently used in signal handler
        CodeBlob* new_blobs = (CodeBlob*)malloc(_capacity * sizeof(CodeBlob) * 2);
        memcpy(new_blobs, _blobs, _capacity * sizeof(CodeBlob));
        _capacity *= 2;
        _blobs = new_blobs;
        __sync_synchronize();
    }

    _blobs[_count]._start = start;
    _blobs[_count]._end = end;
    _blobs[_count]._method = method;
    __sync_synchronize();
    _count++;

}

void CodeCache::add(const void* start, int length, const char* name) {
    add(start, length, asJavaMethod(name));
}

void CodeCache::remove(const void* start, jmethodID method) {
    for (int i = 0; i < _count; i++) {
        if (_blobs[i]._start == start && _blobs[i]._method == method) {
            _blobs[i]._method = NULL;
            return;
        }
    }
}

void CodeCache::sort() {
    qsort(_blobs, _count, sizeof(CodeBlob), CodeBlob::comparator);
}

jmethodID CodeCache::linear_search(const void* address) {
    for (int i = 0; i < _count; i++) {
        if (address >= _blobs[i]._start && address < _blobs[i]._end) {
            return _blobs[i]._method;
        }
    }
    return asJavaMethod(_name);
}

jmethodID CodeCache::binary_search(const void* address) {
    int low = 0;
    int high = _count - 1;

    while (low <= high) {
        int mid = (unsigned int)(low + high) >> 1;
        if (_blobs[mid]._end <= address) {
            low = mid + 1;
        } else if (_blobs[mid]._start > address) {
            high = mid - 1;
        } else {
            return _blobs[mid]._method;
        }
    }

    return low > 0 ? _blobs[low - 1]._method : asJavaMethod(_name);
}
<commit_msg>Replace spaces with underscores in symbol names instead of terminating on space<commit_after>/*
 * Copyright 2016 Andrei Pangin
 *
 * 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <cxxabi.h>
#include "codeCache.h"
#include "vmEntry.h"

static inline bool isString(jmethodID method) {
    return (intptr_t)method < 0;
}

static inline char* asString(jmethodID method) {
    return (char*)(-(intptr_t)method);
}

static inline jmethodID asJavaMethod(const char* name) {
    return (jmethodID)(-(intptr_t)name);
}

static inline void escape(char* name) {
    char *pos = name;
    while (*pos) {
        if (*pos == ' ') {
            *pos = '_';
        }
        pos++;
    }
}

MethodName::MethodName(jmethodID method, const char* sep) {
    if (method == NULL) {
        _str = "[unknown]";
    } else if (isString(method)) {
        _str = demangle(asString(method));
    } else {
        jclass method_class;
        char* class_name;
        char* method_name;

        jvmtiEnv* jvmti = VM::jvmti();
        jvmti->GetMethodName(method, &method_name, NULL, NULL);
        jvmti->GetMethodDeclaringClass(method, &method_class);
        jvmti->GetClassSignature(method_class, &class_name, NULL);

        snprintf(_buf, sizeof(_buf), "%s%s%s", fixClassName(class_name), sep, method_name);
        _str = _buf;

        jvmti->Deallocate((unsigned char*)class_name);
        jvmti->Deallocate((unsigned char*)method_name);
    }

    escape((char *)_str);
}

char* MethodName::fixClassName(char* name) {
    char* s;
    for (s = name + 1; *s; s++) {
        if (*s == '/') *s = '.';
    }
    s[-1] = 0;
    return name + 1;
}

char* MethodName::demangle(char* name) {
    if (name != NULL && name[0] == '_' && name[1] == 'Z') {
        int status;
        char* demangled = abi::__cxa_demangle(name, NULL, NULL, &status);
        if (demangled != NULL) {
            strncpy(_buf, demangled, sizeof(_buf));
            free(demangled);
            return _buf;
        }
    }

    // Defensive copy
    strncpy(_buf, name, sizeof (_buf));
    return _buf;
}

StringTable* StringTable::allocate(StringTable* next, int capacity, int size) {
    StringTable* st = (StringTable*)malloc(sizeof(StringTable) + capacity);
    st->_next = next;
    st->_capacity = capacity;
    st->_size = size;
    return st;
}

StringTable* StringTable::destroy() {
    StringTable* next = _next;
    free(this);
    return next;
}

const char* StringTable::add(const char* s, int length) {
    const char* result = (const char*)memcpy(_data + _size, s, length);
    _size += length;
    return result;
}

CodeCache::CodeCache(const char* name, const void* min_address, const void* max_address) {
    _name = strdup(name);
    _capacity = INITIAL_CODE_CACHE_CAPACITY;
    _count = 0;
    _blobs = (CodeBlob*)malloc(_capacity * sizeof(CodeBlob));
    _strings = NULL;
    _min_address = min_address;
    _max_address = max_address;
}

CodeCache::~CodeCache() {
    for (StringTable* st = _strings; st != NULL; ) {
        st = st->destroy();
    }
    free(_blobs);
    free(_name);
}

const char* CodeCache::addString(const char* s) {
    int length = strlen(s) + 1;
    if (_strings == NULL || _strings->remaining() < length) {
        _strings = StringTable::allocate(_strings, STRING_TABLE_CHUNK);
    }
    return _strings->add(s, length);
}

const char* CodeCache::addStrings(const char* s, int length) {
    _strings = StringTable::allocate(_strings, length);
    return _strings->add(s, length);
}

void CodeCache::add(const void* start, int length, jmethodID method) {
    const char* end = (const char*)start + length;
    if (start < _min_address) _min_address = start;
    if (end > _max_address) _max_address = end;

    if (_count >= _capacity) {
        // Note: we do not free old block here; it can be concurrently used in signal handler
        CodeBlob* new_blobs = (CodeBlob*)malloc(_capacity * sizeof(CodeBlob) * 2);
        memcpy(new_blobs, _blobs, _capacity * sizeof(CodeBlob));
        _capacity *= 2;
        _blobs = new_blobs;
        __sync_synchronize();
    }

    _blobs[_count]._start = start;
    _blobs[_count]._end = end;
    _blobs[_count]._method = method;
    __sync_synchronize();
    _count++;

}

void CodeCache::add(const void* start, int length, const char* name) {
    add(start, length, asJavaMethod(name));
}

void CodeCache::remove(const void* start, jmethodID method) {
    for (int i = 0; i < _count; i++) {
        if (_blobs[i]._start == start && _blobs[i]._method == method) {
            _blobs[i]._method = NULL;
            return;
        }
    }
}

void CodeCache::sort() {
    qsort(_blobs, _count, sizeof(CodeBlob), CodeBlob::comparator);
}

jmethodID CodeCache::linear_search(const void* address) {
    for (int i = 0; i < _count; i++) {
        if (address >= _blobs[i]._start && address < _blobs[i]._end) {
            return _blobs[i]._method;
        }
    }
    return asJavaMethod(_name);
}

jmethodID CodeCache::binary_search(const void* address) {
    int low = 0;
    int high = _count - 1;

    while (low <= high) {
        int mid = (unsigned int)(low + high) >> 1;
        if (_blobs[mid]._end <= address) {
            low = mid + 1;
        } else if (_blobs[mid]._start > address) {
            high = mid - 1;
        } else {
            return _blobs[mid]._method;
        }
    }

    return low > 0 ? _blobs[low - 1]._method : asJavaMethod(_name);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Andrei Pangin
 *
 * 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 <stdlib.h>
#include <string.h>
#include "codeCache.h"

void CodeCache::expand() {
    CodeBlob* old_blobs = _blobs;
    CodeBlob* new_blobs = new CodeBlob[_capacity * 2];

    int live = 0;
    for (int i = 0; i < _count; i++) {
        if (_blobs[i]._method != NULL) {
            new_blobs[live++] = _blobs[i];
        }
    }

    _count = live;
    _capacity *= 2;
    _blobs = new_blobs;
    delete[] old_blobs;
}

void CodeCache::add(const void* start, int length, jmethodID method, bool update_bounds) {
    if (_count >= _capacity) {
        expand();
    }

    const void* end = (const char*)start + length;
    _blobs[_count]._start = start;
    _blobs[_count]._end = end;
    _blobs[_count]._method = method;
    _count++;

    if (update_bounds) {
        if (start < _min_address) _min_address = start;
        if (end > _max_address) _max_address = end;
    }
}

void CodeCache::remove(const void* start, jmethodID method) {
    for (int i = 0; i < _count; i++) {
        if (_blobs[i]._start == start && _blobs[i]._method == method) {
            _blobs[i]._method = NULL;
            return;
        }
    }
}

jmethodID CodeCache::find(const void* address) {
    for (int i = 0; i < _count; i++) {
        CodeBlob* cb = _blobs + i;
        if (address >= cb->_start && address < cb->_end && cb->_method != NULL) {
            return _blobs[i]._method;
        }
    }
    return NULL;
}

NativeCodeCache::NativeCodeCache(const char* name, const void* min_address, const void* max_address) {
    _name = strdup(name);
    _min_address = min_address;
    _max_address = max_address;
}

NativeCodeCache::~NativeCodeCache() {
    for (int i = 0; i < _count; i++) {
        free(_blobs[i]._method);
    }
    free(_name);
}

void NativeCodeCache::add(const void* start, int length, const char* name, bool update_bounds) {
    char* name_copy = strdup(name);
    // Replace non-printable characters
    for (char* s = name_copy; *s != 0; s++) {
        if (*s < ' ') *s = '?';
    }
    CodeCache::add(start, length, (jmethodID)name_copy, update_bounds);
}

void NativeCodeCache::sort() {
    if (_count == 0) return;

    qsort(_blobs, _count, sizeof(CodeBlob), CodeBlob::comparator);

    if (_min_address == NO_MIN_ADDRESS) _min_address = _blobs[0]._start;
    if (_max_address == NO_MAX_ADDRESS) _max_address = _blobs[_count - 1]._end;
}

const char* NativeCodeCache::binarySearch(const void* address) {
    int low = 0;
    int high = _count - 1;

    while (low <= high) {
        int mid = (unsigned int)(low + high) >> 1;
        if (_blobs[mid]._end <= address) {
            low = mid + 1;
        } else if (_blobs[mid]._start > address) {
            high = mid - 1;
        } else {
            return (const char*)_blobs[mid]._method;
        }
    }

    // Symbols with zero size can be valid functions: e.g. ASM entry points or kernel code
    if (low > 0 && _blobs[low - 1]._start == _blobs[low - 1]._end) {
        return (const char*)_blobs[low - 1]._method;
    }
    return _name;
}

const void* NativeCodeCache::findSymbol(const char* name) {
    for (int i = 0; i < _count; i++) {
        const char* blob_name = (const char*)_blobs[i]._method;
        if (blob_name != NULL && strcmp(blob_name, name) == 0) {
            return _blobs[i]._start;
        }
    }
    return NULL;
}

const void* NativeCodeCache::findSymbolByPrefix(const char* prefix) {
    int prefix_len = strlen(prefix);
    for (int i = 0; i < _count; i++) {
        const char* blob_name = (const char*)_blobs[i]._method;
        if (blob_name != NULL && strncmp(blob_name, prefix, prefix_len) == 0) {
            return _blobs[i]._start;
        }
    }
    return NULL;
}
<commit_msg>Fixed symbol resolution when return address points beyond the function<commit_after>/*
 * Copyright 2016 Andrei Pangin
 *
 * 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 <stdlib.h>
#include <string.h>
#include "codeCache.h"

void CodeCache::expand() {
    CodeBlob* old_blobs = _blobs;
    CodeBlob* new_blobs = new CodeBlob[_capacity * 2];

    int live = 0;
    for (int i = 0; i < _count; i++) {
        if (_blobs[i]._method != NULL) {
            new_blobs[live++] = _blobs[i];
        }
    }

    _count = live;
    _capacity *= 2;
    _blobs = new_blobs;
    delete[] old_blobs;
}

void CodeCache::add(const void* start, int length, jmethodID method, bool update_bounds) {
    if (_count >= _capacity) {
        expand();
    }

    const void* end = (const char*)start + length;
    _blobs[_count]._start = start;
    _blobs[_count]._end = end;
    _blobs[_count]._method = method;
    _count++;

    if (update_bounds) {
        if (start < _min_address) _min_address = start;
        if (end > _max_address) _max_address = end;
    }
}

void CodeCache::remove(const void* start, jmethodID method) {
    for (int i = 0; i < _count; i++) {
        if (_blobs[i]._start == start && _blobs[i]._method == method) {
            _blobs[i]._method = NULL;
            return;
        }
    }
}

jmethodID CodeCache::find(const void* address) {
    for (int i = 0; i < _count; i++) {
        CodeBlob* cb = _blobs + i;
        if (address >= cb->_start && address < cb->_end && cb->_method != NULL) {
            return _blobs[i]._method;
        }
    }
    return NULL;
}

NativeCodeCache::NativeCodeCache(const char* name, const void* min_address, const void* max_address) {
    _name = strdup(name);
    _min_address = min_address;
    _max_address = max_address;
}

NativeCodeCache::~NativeCodeCache() {
    for (int i = 0; i < _count; i++) {
        free(_blobs[i]._method);
    }
    free(_name);
}

void NativeCodeCache::add(const void* start, int length, const char* name, bool update_bounds) {
    char* name_copy = strdup(name);
    // Replace non-printable characters
    for (char* s = name_copy; *s != 0; s++) {
        if (*s < ' ') *s = '?';
    }
    CodeCache::add(start, length, (jmethodID)name_copy, update_bounds);
}

void NativeCodeCache::sort() {
    if (_count == 0) return;

    qsort(_blobs, _count, sizeof(CodeBlob), CodeBlob::comparator);

    if (_min_address == NO_MIN_ADDRESS) _min_address = _blobs[0]._start;
    if (_max_address == NO_MAX_ADDRESS) _max_address = _blobs[_count - 1]._end;
}

const char* NativeCodeCache::binarySearch(const void* address) {
    int low = 0;
    int high = _count - 1;

    while (low <= high) {
        int mid = (unsigned int)(low + high) >> 1;
        if (_blobs[mid]._end <= address) {
            low = mid + 1;
        } else if (_blobs[mid]._start > address) {
            high = mid - 1;
        } else {
            return (const char*)_blobs[mid]._method;
        }
    }

    // Symbols with zero size can be valid functions: e.g. ASM entry points or kernel code.
    // Also, in some cases (endless loop) the return address may point beyond the function.
    if (low > 0 && (_blobs[low - 1]._start == _blobs[low - 1]._end || _blobs[low - 1]._end == address)) {
        return (const char*)_blobs[low - 1]._method;
    }
    return _name;
}

const void* NativeCodeCache::findSymbol(const char* name) {
    for (int i = 0; i < _count; i++) {
        const char* blob_name = (const char*)_blobs[i]._method;
        if (blob_name != NULL && strcmp(blob_name, name) == 0) {
            return _blobs[i]._start;
        }
    }
    return NULL;
}

const void* NativeCodeCache::findSymbolByPrefix(const char* prefix) {
    int prefix_len = strlen(prefix);
    for (int i = 0; i < _count; i++) {
        const char* blob_name = (const char*)_blobs[i]._method;
        if (blob_name != NULL && strncmp(blob_name, prefix, prefix_len) == 0) {
            return _blobs[i]._start;
        }
    }
    return NULL;
}
<|endoftext|>