<commit_before>/*
 * Copyright 2011, 2012 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 "HTTPRequest.h"

#include <iostream>
#include <string>

#include "utf.h"

#include "url/URI.h"
#include "http/HTTPCache.h"
#include "http/HTTPConnection.h"

#include "css/Box.h"

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

const unsigned short HttpRequest::UNSENT;
const unsigned short HttpRequest::OPENED;
const unsigned short HttpRequest::HEADERS_RECEIVED;
const unsigned short HttpRequest::LOADING;
const unsigned short HttpRequest::COMPLETE;
const unsigned short HttpRequest::DONE;

std::string HttpRequest::aboutPath;
std::string HttpRequest::cachePath("/tmp/esXXXXXX");

int HttpRequest::getContentDescriptor()
{
    return fdContent;  // TODO: call dup internally?
}

std::FILE* HttpRequest::openFile()
{
    if (fdContent == -1)
        return 0;
    std::FILE* file = fdopen(dup(fdContent), "rb");
    if (!file)
        return 0;
    rewind(file);
    return file;
}

std::fstream& HttpRequest::getContent()
{
    if (content.is_open())
        return content;

    char filename[PATH_MAX];
    if (PATH_MAX <= cachePath.length() + 9)
        return content;
    strcpy(filename, cachePath.c_str());
    strcat(filename, "/esXXXXXX");
    fdContent = mkstemp(filename);
    if (fdContent == -1)
        return content;
    content.open(filename, std::ios_base::trunc | std::ios_base::in | std::ios_base::out | std::ios::binary);
    remove(filename);

    return content;
}

bool HttpRequest::complete(bool error)
{
    readyState = handler ? COMPLETE : DONE;
    errorFlag = error;
    if (cache)
        cache->notify(this, error);
    return handler;
}

void HttpRequest::notify()
{
    readyState = DONE;
    if (handler) {
        handler();
        handler.clear();
    }
}

bool HttpRequest::notify(bool error)
{
    if (complete(error))
        notify();
    return errorFlag;
}

void HttpRequest::open(const std::u16string& method, const std::u16string& urlString)
{
    URL url(base, urlString);
    request.open(utfconv(method), url);
    readyState = OPENED;
}

void HttpRequest::setRequestHeader(const std::u16string& header, const std::u16string& value)
{
    request.setHeader(utfconv(header), utfconv(value));
}

bool HttpRequest::constructResponseFromCache(bool sync)
{
    readyState = DONE;
    errorFlag = false;
    response.update(cache->getResponseMessage());

    // TODO: deal with partial...
    int fd = cache->getContentDescriptor();
    if (0 <= fd)
        fdContent = dup(fd);

    cache = 0;
    if (sync)
        notify();
    else
        HttpConnectionManager::getInstance().complete(this, errorFlag);
    return errorFlag;
}

bool HttpRequest::send()
{
    if (request.getURL().isEmpty())
        return notify(false);

    if (request.getURL().testProtocol(u"file")) {
        if (request.getMethodCode() != HttpRequestMessage::GET)
            return notify(true);
        std::u16string host = request.getURL().getHostname();
        if (!host.empty() && host != u"localhost")  // TODO: maybe allow local host IP addresses?
            return notify(true);
        std::string path = utfconv(request.getURL().getPathname());
        fdContent = ::open(path.c_str(), O_RDONLY);
        return notify(fdContent == -1);
    }

    if (request.getURL().testProtocol(u"about")) {
        if (aboutPath.empty() || request.getMethodCode() != HttpRequestMessage::GET)
            return notify(true);
        std::string path = utfconv(request.getURL().getPathname());
        if (path.empty())
            path = aboutPath + "/about.html";
        else
            path = aboutPath + "/about/" + path;
        fdContent = ::open(path.c_str(), O_RDONLY);
        return notify(fdContent == -1);
    }

    cache = HttpCacheManager::getInstance().send(this);
    if (!cache || cache->isBusy())
        return false;
    return constructResponseFromCache(true);
}

void HttpRequest::abort()
{
    if (readyState == UNSENT)
        return;

    // TODO: implement more details.
    clearHanndler();
    HttpConnectionManager& manager = HttpConnectionManager::getInstance();
    manager.abort(this);
    readyState = UNSENT;
    errorFlag = false;
    request.clear();
    response.clear();
    if (content.is_open())
        content.close();
    if (0 <= fdContent) {
        close(fdContent);
        fdContent = -1;
    }
}

unsigned short HttpRequest::getStatus() const
{
    return response.getStatus();
}

const std::string& HttpRequest::getStatusText() const
{
    return response.getStatusText();
}

const std::string HttpRequest::getResponseHeader(std::u16string header) const
{
    return response.getResponseHeader(utfconv(header));
}

const std::string& HttpRequest::getAllResponseHeaders() const
{
    return response.getAllResponseHeaders();
}

HttpRequest::HttpRequest(const std::u16string& base) :
    base(base),
    readyState(UNSENT),
    errorFlag(false),
    fdContent(-1),
    cache(0),
    handler(0),
    boxImage(0)
{
}

HttpRequest::~HttpRequest()
{
    abort();
    delete boxImage;
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(HttpRequest::cachePath) : Fix the default path.<commit_after>/*
 * Copyright 2011, 2012 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 "HTTPRequest.h"

#include <iostream>
#include <string>

#include "utf.h"

#include "url/URI.h"
#include "http/HTTPCache.h"
#include "http/HTTPConnection.h"

#include "css/Box.h"

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

const unsigned short HttpRequest::UNSENT;
const unsigned short HttpRequest::OPENED;
const unsigned short HttpRequest::HEADERS_RECEIVED;
const unsigned short HttpRequest::LOADING;
const unsigned short HttpRequest::COMPLETE;
const unsigned short HttpRequest::DONE;

std::string HttpRequest::aboutPath;
std::string HttpRequest::cachePath("/tmp");

int HttpRequest::getContentDescriptor()
{
    return fdContent;  // TODO: call dup internally?
}

std::FILE* HttpRequest::openFile()
{
    if (fdContent == -1)
        return 0;
    std::FILE* file = fdopen(dup(fdContent), "rb");
    if (!file)
        return 0;
    rewind(file);
    return file;
}

std::fstream& HttpRequest::getContent()
{
    if (content.is_open())
        return content;

    char filename[PATH_MAX];
    if (PATH_MAX <= cachePath.length() + 9)
        return content;
    strcpy(filename, cachePath.c_str());
    strcat(filename, "/esXXXXXX");
    fdContent = mkstemp(filename);
    if (fdContent == -1)
        return content;
    content.open(filename, std::ios_base::trunc | std::ios_base::in | std::ios_base::out | std::ios::binary);
    remove(filename);

    return content;
}

bool HttpRequest::complete(bool error)
{
    readyState = handler ? COMPLETE : DONE;
    errorFlag = error;
    if (cache)
        cache->notify(this, error);
    return handler;
}

void HttpRequest::notify()
{
    readyState = DONE;
    if (handler) {
        handler();
        handler.clear();
    }
}

bool HttpRequest::notify(bool error)
{
    if (complete(error))
        notify();
    return errorFlag;
}

void HttpRequest::open(const std::u16string& method, const std::u16string& urlString)
{
    URL url(base, urlString);
    request.open(utfconv(method), url);
    readyState = OPENED;
}

void HttpRequest::setRequestHeader(const std::u16string& header, const std::u16string& value)
{
    request.setHeader(utfconv(header), utfconv(value));
}

bool HttpRequest::constructResponseFromCache(bool sync)
{
    readyState = DONE;
    errorFlag = false;
    response.update(cache->getResponseMessage());

    // TODO: deal with partial...
    int fd = cache->getContentDescriptor();
    if (0 <= fd)
        fdContent = dup(fd);

    cache = 0;
    if (sync)
        notify();
    else
        HttpConnectionManager::getInstance().complete(this, errorFlag);
    return errorFlag;
}

bool HttpRequest::send()
{
    if (request.getURL().isEmpty())
        return notify(false);

    if (request.getURL().testProtocol(u"file")) {
        if (request.getMethodCode() != HttpRequestMessage::GET)
            return notify(true);
        std::u16string host = request.getURL().getHostname();
        if (!host.empty() && host != u"localhost")  // TODO: maybe allow local host IP addresses?
            return notify(true);
        std::string path = utfconv(request.getURL().getPathname());
        fdContent = ::open(path.c_str(), O_RDONLY);
        return notify(fdContent == -1);
    }

    if (request.getURL().testProtocol(u"about")) {
        if (aboutPath.empty() || request.getMethodCode() != HttpRequestMessage::GET)
            return notify(true);
        std::string path = utfconv(request.getURL().getPathname());
        if (path.empty())
            path = aboutPath + "/about.html";
        else
            path = aboutPath + "/about/" + path;
        fdContent = ::open(path.c_str(), O_RDONLY);
        return notify(fdContent == -1);
    }

    cache = HttpCacheManager::getInstance().send(this);
    if (!cache || cache->isBusy())
        return false;
    return constructResponseFromCache(true);
}

void HttpRequest::abort()
{
    if (readyState == UNSENT)
        return;

    // TODO: implement more details.
    clearHanndler();
    HttpConnectionManager& manager = HttpConnectionManager::getInstance();
    manager.abort(this);
    readyState = UNSENT;
    errorFlag = false;
    request.clear();
    response.clear();
    if (content.is_open())
        content.close();
    if (0 <= fdContent) {
        close(fdContent);
        fdContent = -1;
    }
}

unsigned short HttpRequest::getStatus() const
{
    return response.getStatus();
}

const std::string& HttpRequest::getStatusText() const
{
    return response.getStatusText();
}

const std::string HttpRequest::getResponseHeader(std::u16string header) const
{
    return response.getResponseHeader(utfconv(header));
}

const std::string& HttpRequest::getAllResponseHeaders() const
{
    return response.getAllResponseHeaders();
}

HttpRequest::HttpRequest(const std::u16string& base) :
    base(base),
    readyState(UNSENT),
    errorFlag(false),
    fdContent(-1),
    cache(0),
    handler(0),
    boxImage(0)
{
}

HttpRequest::~HttpRequest()
{
    abort();
    delete boxImage;
}

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


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2014, Itseez Inc, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
#include "kdtree.hpp"

/****************************************************************************************\
*                              K-Nearest Neighbors Classifier                            *
\****************************************************************************************/

namespace cv {
namespace ml {

const String NAME_BRUTE_FORCE = "opencv_ml_knn";
const String NAME_KDTREE = "opencv_ml_knn_kd";

class Impl
{
public:
    Impl()
    {
        defaultK = 10;
        isclassifier = true;
        Emax = INT_MAX;
    }

    virtual ~Impl() {}
    virtual String getModelName() const = 0;
    virtual int getType() const = 0;
    virtual float findNearest( InputArray _samples, int k,
                               OutputArray _results,
                               OutputArray _neighborResponses,
                               OutputArray _dists ) const = 0;

    bool train( const Ptr<TrainData>& data, int flags )
    {
        Mat new_samples = data->getTrainSamples(ROW_SAMPLE);
        Mat new_responses;
        data->getTrainResponses().convertTo(new_responses, CV_32F);
        bool update = (flags & ml::KNearest::UPDATE_MODEL) != 0 && !samples.empty();

        CV_Assert( new_samples.type() == CV_32F );

        if( !update )
        {
            clear();
        }
        else
        {
            CV_Assert( new_samples.cols == samples.cols &&
                       new_responses.cols == responses.cols );
        }

        samples.push_back(new_samples);
        responses.push_back(new_responses);

        doTrain(samples);

        return true;
    }

    virtual void doTrain(InputArray points) { (void)points; }

    void clear()
    {
        samples.release();
        responses.release();
    }

    void read( const FileNode& fn )
    {
        clear();
        isclassifier = (int)fn["is_classifier"] != 0;
        defaultK = (int)fn["default_k"];

        fn["samples"] >> samples;
        fn["responses"] >> responses;
    }

    void write( FileStorage& fs ) const
    {
        fs << "is_classifier" << (int)isclassifier;
        fs << "default_k" << defaultK;

        fs << "samples" << samples;
        fs << "responses" << responses;
    }

public:
    int defaultK;
    bool isclassifier;
    int Emax;

    Mat samples;
    Mat responses;
};

class BruteForceImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_BRUTE_FORCE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::BRUTE_FORCE; }

    void findNearestCore( const Mat& _samples, int k0, const Range& range,
                          Mat* results, Mat* neighbor_responses,
                          Mat* dists, float* presult ) const
    {
        int testidx, baseidx, i, j, d = samples.cols, nsamples = samples.rows;
        int testcount = range.end - range.start;
        int k = std::min(k0, nsamples);

        AutoBuffer<float> buf(testcount*k*2);
        float* dbuf = buf;
        float* rbuf = dbuf + testcount*k;

        const float* rptr = responses.ptr<float>();

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            for( i = 0; i < k; i++ )
            {
                dbuf[testidx*k + i] = FLT_MAX;
                rbuf[testidx*k + i] = 0.f;
            }
        }

        for( baseidx = 0; baseidx < nsamples; baseidx++ )
        {
            for( testidx = 0; testidx < testcount; testidx++ )
            {
                const float* v = samples.ptr<float>(baseidx);
                const float* u = _samples.ptr<float>(testidx + range.start);

                float s = 0;
                for( i = 0; i <= d - 4; i += 4 )
                {
                    float t0 = u[i] - v[i], t1 = u[i+1] - v[i+1];
                    float t2 = u[i+2] - v[i+2], t3 = u[i+3] - v[i+3];
                    s += t0*t0 + t1*t1 + t2*t2 + t3*t3;
                }

                for( ; i < d; i++ )
                {
                    float t0 = u[i] - v[i];
                    s += t0*t0;
                }

                Cv32suf si;
                si.f = (float)s;
                Cv32suf* dd = (Cv32suf*)(&dbuf[testidx*k]);
                float* nr = &rbuf[testidx*k];

                for( i = k; i > 0; i-- )
                    if( si.i >= dd[i-1].i )
                        break;
                if( i >= k )
                    continue;

                for( j = k-2; j >= i; j-- )
                {
                    dd[j+1].i = dd[j].i;
                    nr[j+1] = nr[j];
                }
                dd[i].i = si.i;
                nr[i] = rptr[baseidx];
            }
        }

        float result = 0.f;
        float inv_scale = 1.f/k;

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            if( neighbor_responses )
            {
                float* nr = neighbor_responses->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    nr[j] = rbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    nr[j] = 0.f;
            }

            if( dists )
            {
                float* dptr = dists->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    dptr[j] = dbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    dptr[j] = 0.f;
            }

            if( results || testidx+range.start == 0 )
            {
                if( !isclassifier || k == 1 )
                {
                    float s = 0.f;
                    for( j = 0; j < k; j++ )
                        s += rbuf[testidx*k + j];
                    result = (float)(s*inv_scale);
                }
                else
                {
                    float* rp = rbuf + testidx*k;
                    for( j = k-1; j > 0; j-- )
                    {
                        bool swap_fl = false;
                        for( i = 0; i < j; i++ )
                        {
                            if( rp[i] > rp[i+1] )
                            {
                                std::swap(rp[i], rp[i+1]);
                                swap_fl = true;
                            }
                        }
                        if( !swap_fl )
                            break;
                    }

                    result = rp[0];
                    int prev_start = 0;
                    int best_count = 0;
                    for( j = 1; j <= k; j++ )
                    {
                        if( j == k || rp[j] != rp[j-1] )
                        {
                            int count = j - prev_start;
                            if( best_count < count )
                            {
                                best_count = count;
                                result = rp[j-1];
                            }
                            prev_start = j;
                        }
                    }
                }
                if( results )
                    results->at<float>(testidx + range.start) = result;
                if( presult && testidx+range.start == 0 )
                    *presult = result;
            }
        }
    }

    struct findKNearestInvoker : public ParallelLoopBody
    {
        findKNearestInvoker(const BruteForceImpl* _p, int _k, const Mat& __samples,
                            Mat* __results, Mat* __neighbor_responses, Mat* __dists, float* _presult)
        {
            p = _p;
            k = _k;
            _samples = &__samples;
            _results = __results;
            _neighbor_responses = __neighbor_responses;
            _dists = __dists;
            presult = _presult;
        }

        void operator()(const Range& range) const CV_OVERRIDE
        {
            int delta = std::min(range.end - range.start, 256);
            for( int start = range.start; start < range.end; start += delta )
            {
                p->findNearestCore( *_samples, k, Range(start, std::min(start + delta, range.end)),
                                    _results, _neighbor_responses, _dists, presult );
            }
        }

        const BruteForceImpl* p;
        int k;
        const Mat* _samples;
        Mat* _results;
        Mat* _neighbor_responses;
        Mat* _dists;
        float* presult;
    };

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d, *pres = 0, *pnr = 0, *pd = 0;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            pres = &(res = _results.getMat());
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            pnr = &(nr = _neighborResponses.getMat());
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            pd = &(d = _dists.getMat());
        }

        findKNearestInvoker invoker(this, k, test_samples, pres, pnr, pd, &result);
        parallel_for_(Range(0, testcount), invoker);
        //invoker(Range(0, testcount));
        return result;
    }
};

class KDTreeImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_KDTREE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::KDTREE; }

    void doTrain(InputArray points) CV_OVERRIDE
    {
        tr.build(points);
    }

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            res = _results.getMat();
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            nr = _neighborResponses.getMat();
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            d = _dists.getMat();
        }

        for (int i=0; i<test_samples.rows; ++i)
        {
            Mat _res, _nr, _d;
            if (res.rows>i)
            {
                _res = res.row(i);
            }
            if (nr.rows>i)
            {
                _nr = nr.row(i);
            }
            if (d.rows>i)
            {
                _d = d.row(i);
            }
            tr.findNearest(test_samples.row(i), k, Emax, _res, _nr, _d, noArray());
        }

        return result; // currently always 0
    }

    KDTree tr;
};

//================================================================

class KNearestImpl CV_FINAL : public KNearest
{
    inline int getDefaultK() const CV_OVERRIDE { return impl->defaultK; }
    inline void setDefaultK(int val) CV_OVERRIDE { impl->defaultK = val; }
    inline bool getIsClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    inline void setIsClassifier(bool val) CV_OVERRIDE { impl->isclassifier = val; }
    inline int getEmax() const CV_OVERRIDE { return impl->Emax; }
    inline void setEmax(int val) CV_OVERRIDE { impl->Emax = val; }

public:
    int getAlgorithmType() const CV_OVERRIDE
    {
        return impl->getType();
    }
    void setAlgorithmType(int val) CV_OVERRIDE
    {
        if (val != BRUTE_FORCE && val != KDTREE)
            val = BRUTE_FORCE;
        initImpl(val);
    }

public:
    KNearestImpl()
    {
        initImpl(BRUTE_FORCE);
    }
    ~KNearestImpl()
    {
    }

    bool isClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    bool isTrained() const CV_OVERRIDE { return !impl->samples.empty(); }

    int getVarCount() const CV_OVERRIDE { return impl->samples.cols; }

    void write( FileStorage& fs ) const CV_OVERRIDE
    {
        writeFormat(fs);
        impl->write(fs);
    }

    void read( const FileNode& fn ) CV_OVERRIDE
    {
        int algorithmType = BRUTE_FORCE;
        if (fn.name() == NAME_KDTREE)
            algorithmType = KDTREE;
        initImpl(algorithmType);
        impl->read(fn);
    }

    float findNearest( InputArray samples, int k,
                       OutputArray results,
                       OutputArray neighborResponses=noArray(),
                       OutputArray dist=noArray() ) const CV_OVERRIDE
    {
        return impl->findNearest(samples, k, results, neighborResponses, dist);
    }

    float predict(InputArray inputs, OutputArray outputs, int) const CV_OVERRIDE
    {
        return impl->findNearest( inputs, impl->defaultK, outputs, noArray(), noArray() );
    }

    bool train( const Ptr<TrainData>& data, int flags ) CV_OVERRIDE
    {
        return impl->train(data, flags);
    }

    String getDefaultName() const CV_OVERRIDE { return impl->getModelName(); }

protected:
    void initImpl(int algorithmType)
    {
        if (algorithmType != KDTREE)
            impl = makePtr<BruteForceImpl>();
        else
            impl = makePtr<KDTreeImpl>();
    }
    Ptr<Impl> impl;
};

Ptr<KNearest> KNearest::create()
{
    return makePtr<KNearestImpl>();
}

}
}

/* End of file */
<commit_msg>Adds efficient sort algorithm to KNearest<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2014, Itseez Inc, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
#include "kdtree.hpp"

/****************************************************************************************\
*                              K-Nearest Neighbors Classifier                            *
\****************************************************************************************/

namespace cv {
namespace ml {

const String NAME_BRUTE_FORCE = "opencv_ml_knn";
const String NAME_KDTREE = "opencv_ml_knn_kd";

class Impl
{
public:
    Impl()
    {
        defaultK = 10;
        isclassifier = true;
        Emax = INT_MAX;
    }

    virtual ~Impl() {}
    virtual String getModelName() const = 0;
    virtual int getType() const = 0;
    virtual float findNearest( InputArray _samples, int k,
                               OutputArray _results,
                               OutputArray _neighborResponses,
                               OutputArray _dists ) const = 0;

    bool train( const Ptr<TrainData>& data, int flags )
    {
        Mat new_samples = data->getTrainSamples(ROW_SAMPLE);
        Mat new_responses;
        data->getTrainResponses().convertTo(new_responses, CV_32F);
        bool update = (flags & ml::KNearest::UPDATE_MODEL) != 0 && !samples.empty();

        CV_Assert( new_samples.type() == CV_32F );

        if( !update )
        {
            clear();
        }
        else
        {
            CV_Assert( new_samples.cols == samples.cols &&
                       new_responses.cols == responses.cols );
        }

        samples.push_back(new_samples);
        responses.push_back(new_responses);

        doTrain(samples);

        return true;
    }

    virtual void doTrain(InputArray points) { (void)points; }

    void clear()
    {
        samples.release();
        responses.release();
    }

    void read( const FileNode& fn )
    {
        clear();
        isclassifier = (int)fn["is_classifier"] != 0;
        defaultK = (int)fn["default_k"];

        fn["samples"] >> samples;
        fn["responses"] >> responses;
    }

    void write( FileStorage& fs ) const
    {
        fs << "is_classifier" << (int)isclassifier;
        fs << "default_k" << defaultK;

        fs << "samples" << samples;
        fs << "responses" << responses;
    }

public:
    int defaultK;
    bool isclassifier;
    int Emax;

    Mat samples;
    Mat responses;
};

class BruteForceImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_BRUTE_FORCE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::BRUTE_FORCE; }

    void findNearestCore( const Mat& _samples, int k0, const Range& range,
                          Mat* results, Mat* neighbor_responses,
                          Mat* dists, float* presult ) const
    {
        int testidx, baseidx, i, j, d = samples.cols, nsamples = samples.rows;
        int testcount = range.end - range.start;
        int k = std::min(k0, nsamples);

        AutoBuffer<float> buf(testcount*k*2);
        float* dbuf = buf;
        float* rbuf = dbuf + testcount*k;

        const float* rptr = responses.ptr<float>();

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            for( i = 0; i < k; i++ )
            {
                dbuf[testidx*k + i] = FLT_MAX;
                rbuf[testidx*k + i] = 0.f;
            }
        }

        for( baseidx = 0; baseidx < nsamples; baseidx++ )
        {
            for( testidx = 0; testidx < testcount; testidx++ )
            {
                const float* v = samples.ptr<float>(baseidx);
                const float* u = _samples.ptr<float>(testidx + range.start);

                float s = 0;
                for( i = 0; i <= d - 4; i += 4 )
                {
                    float t0 = u[i] - v[i], t1 = u[i+1] - v[i+1];
                    float t2 = u[i+2] - v[i+2], t3 = u[i+3] - v[i+3];
                    s += t0*t0 + t1*t1 + t2*t2 + t3*t3;
                }

                for( ; i < d; i++ )
                {
                    float t0 = u[i] - v[i];
                    s += t0*t0;
                }

                Cv32suf si;
                si.f = (float)s;
                Cv32suf* dd = (Cv32suf*)(&dbuf[testidx*k]);
                float* nr = &rbuf[testidx*k];

                for( i = k; i > 0; i-- )
                    if( si.i >= dd[i-1].i )
                        break;
                if( i >= k )
                    continue;

                for( j = k-2; j >= i; j-- )
                {
                    dd[j+1].i = dd[j].i;
                    nr[j+1] = nr[j];
                }
                dd[i].i = si.i;
                nr[i] = rptr[baseidx];
            }
        }

        float result = 0.f;
        float inv_scale = 1.f/k;

        for( testidx = 0; testidx < testcount; testidx++ )
        {
            if( neighbor_responses )
            {
                float* nr = neighbor_responses->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    nr[j] = rbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    nr[j] = 0.f;
            }

            if( dists )
            {
                float* dptr = dists->ptr<float>(testidx + range.start);
                for( j = 0; j < k; j++ )
                    dptr[j] = dbuf[testidx*k + j];
                for( ; j < k0; j++ )
                    dptr[j] = 0.f;
            }

            if( results || testidx+range.start == 0 )
            {
                if( !isclassifier || k == 1 )
                {
                    float s = 0.f;
                    for( j = 0; j < k; j++ )
                        s += rbuf[testidx*k + j];
                    result = (float)(s*inv_scale);
                }
                else
                {
                    float* rp = rbuf + testidx*k;
                    std::sort(rp, rp+k);

                    result = rp[0];
                    int prev_start = 0;
                    int best_count = 0;
                    for( j = 1; j <= k; j++ )
                    {
                        if( j == k || rp[j] != rp[j-1] )
                        {
                            int count = j - prev_start;
                            if( best_count < count )
                            {
                                best_count = count;
                                result = rp[j-1];
                            }
                            prev_start = j;
                        }
                    }
                }
                if( results )
                    results->at<float>(testidx + range.start) = result;
                if( presult && testidx+range.start == 0 )
                    *presult = result;
            }
        }
    }

    struct findKNearestInvoker : public ParallelLoopBody
    {
        findKNearestInvoker(const BruteForceImpl* _p, int _k, const Mat& __samples,
                            Mat* __results, Mat* __neighbor_responses, Mat* __dists, float* _presult)
        {
            p = _p;
            k = _k;
            _samples = &__samples;
            _results = __results;
            _neighbor_responses = __neighbor_responses;
            _dists = __dists;
            presult = _presult;
        }

        void operator()(const Range& range) const CV_OVERRIDE
        {
            int delta = std::min(range.end - range.start, 256);
            for( int start = range.start; start < range.end; start += delta )
            {
                p->findNearestCore( *_samples, k, Range(start, std::min(start + delta, range.end)),
                                    _results, _neighbor_responses, _dists, presult );
            }
        }

        const BruteForceImpl* p;
        int k;
        const Mat* _samples;
        Mat* _results;
        Mat* _neighbor_responses;
        Mat* _dists;
        float* presult;
    };

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d, *pres = 0, *pnr = 0, *pd = 0;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            pres = &(res = _results.getMat());
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            pnr = &(nr = _neighborResponses.getMat());
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            pd = &(d = _dists.getMat());
        }

        findKNearestInvoker invoker(this, k, test_samples, pres, pnr, pd, &result);
        parallel_for_(Range(0, testcount), invoker);
        //invoker(Range(0, testcount));
        return result;
    }
};

class KDTreeImpl CV_FINAL : public Impl
{
public:
    String getModelName() const CV_OVERRIDE { return NAME_KDTREE; }
    int getType() const CV_OVERRIDE { return ml::KNearest::KDTREE; }

    void doTrain(InputArray points) CV_OVERRIDE
    {
        tr.build(points);
    }

    float findNearest( InputArray _samples, int k,
                       OutputArray _results,
                       OutputArray _neighborResponses,
                       OutputArray _dists ) const CV_OVERRIDE
    {
        float result = 0.f;
        CV_Assert( 0 < k );

        Mat test_samples = _samples.getMat();
        CV_Assert( test_samples.type() == CV_32F && test_samples.cols == samples.cols );
        int testcount = test_samples.rows;

        if( testcount == 0 )
        {
            _results.release();
            _neighborResponses.release();
            _dists.release();
            return 0.f;
        }

        Mat res, nr, d;
        if( _results.needed() )
        {
            _results.create(testcount, 1, CV_32F);
            res = _results.getMat();
        }
        if( _neighborResponses.needed() )
        {
            _neighborResponses.create(testcount, k, CV_32F);
            nr = _neighborResponses.getMat();
        }
        if( _dists.needed() )
        {
            _dists.create(testcount, k, CV_32F);
            d = _dists.getMat();
        }

        for (int i=0; i<test_samples.rows; ++i)
        {
            Mat _res, _nr, _d;
            if (res.rows>i)
            {
                _res = res.row(i);
            }
            if (nr.rows>i)
            {
                _nr = nr.row(i);
            }
            if (d.rows>i)
            {
                _d = d.row(i);
            }
            tr.findNearest(test_samples.row(i), k, Emax, _res, _nr, _d, noArray());
        }

        return result; // currently always 0
    }

    KDTree tr;
};

//================================================================

class KNearestImpl CV_FINAL : public KNearest
{
    inline int getDefaultK() const CV_OVERRIDE { return impl->defaultK; }
    inline void setDefaultK(int val) CV_OVERRIDE { impl->defaultK = val; }
    inline bool getIsClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    inline void setIsClassifier(bool val) CV_OVERRIDE { impl->isclassifier = val; }
    inline int getEmax() const CV_OVERRIDE { return impl->Emax; }
    inline void setEmax(int val) CV_OVERRIDE { impl->Emax = val; }

public:
    int getAlgorithmType() const CV_OVERRIDE
    {
        return impl->getType();
    }
    void setAlgorithmType(int val) CV_OVERRIDE
    {
        if (val != BRUTE_FORCE && val != KDTREE)
            val = BRUTE_FORCE;
        initImpl(val);
    }

public:
    KNearestImpl()
    {
        initImpl(BRUTE_FORCE);
    }
    ~KNearestImpl()
    {
    }

    bool isClassifier() const CV_OVERRIDE { return impl->isclassifier; }
    bool isTrained() const CV_OVERRIDE { return !impl->samples.empty(); }

    int getVarCount() const CV_OVERRIDE { return impl->samples.cols; }

    void write( FileStorage& fs ) const CV_OVERRIDE
    {
        writeFormat(fs);
        impl->write(fs);
    }

    void read( const FileNode& fn ) CV_OVERRIDE
    {
        int algorithmType = BRUTE_FORCE;
        if (fn.name() == NAME_KDTREE)
            algorithmType = KDTREE;
        initImpl(algorithmType);
        impl->read(fn);
    }

    float findNearest( InputArray samples, int k,
                       OutputArray results,
                       OutputArray neighborResponses=noArray(),
                       OutputArray dist=noArray() ) const CV_OVERRIDE
    {
        return impl->findNearest(samples, k, results, neighborResponses, dist);
    }

    float predict(InputArray inputs, OutputArray outputs, int) const CV_OVERRIDE
    {
        return impl->findNearest( inputs, impl->defaultK, outputs, noArray(), noArray() );
    }

    bool train( const Ptr<TrainData>& data, int flags ) CV_OVERRIDE
    {
        return impl->train(data, flags);
    }

    String getDefaultName() const CV_OVERRIDE { return impl->getModelName(); }

protected:
    void initImpl(int algorithmType)
    {
        if (algorithmType != KDTREE)
            impl = makePtr<BruteForceImpl>();
        else
            impl = makePtr<KDTreeImpl>();
    }
    Ptr<Impl> impl;
};

Ptr<KNearest> KNearest::create()
{
    return makePtr<KNearestImpl>();
}

}
}

/* End of file */
<|endoftext|>


<commit_before>/*
   Copyright 2016 Mitchell Young

   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 "pin_mesh_rect.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <sstream>
#include <string>

#include "pugixml.hpp"

#include "error.hpp"

namespace mocc {
PinMesh_Rect::PinMesh_Rect(const pugi::xml_node &input) : PinMesh(input)
{
    // Parse the number of x and y divisions
    int ndiv_x = input.child("sub_x").text().as_int(0);
    if (ndiv_x < 1) {
        throw EXCEPT("Failed to read valid number of X divisions in rect "
                     "pin mesh.");
    }
    int ndiv_y = input.child("sub_y").text().as_int(0);
    if (ndiv_y < 1) {
        throw EXCEPT("Failed to read valid number of Y divisions in rect "
                     "pin mesh.");
    }

    n_xsreg_ = ndiv_x * ndiv_y;
    n_reg_   = ndiv_x * ndiv_y;

    nx_ = ndiv_x;
    ny_ = ndiv_y;

    real_t dx = pitch_x_ / ndiv_x;
    real_t dy = pitch_y_ / ndiv_y;

    real_t h_pitch_x = 0.5 * pitch_x_;
    real_t h_pitch_y = 0.5 * pitch_y_;

    for (int i = 0; i <= ndiv_x; i++) {
        hx_.push_back(i * dx - h_pitch_x);
    }
    for (int i = 0; i <= ndiv_y; i++) {
        hy_.push_back(i * dy - h_pitch_y);
    }

    // Form lines representing the mesh boundaries
    for (unsigned ix = 1; ix < hx_.size() - 1; ix++) {
        real_t xi = hx_[ix];
        lines_.push_back(Line(Point2(xi, -h_pitch_y), Point2(xi, h_pitch_y)));
    }
    for (unsigned iy = 1; iy < hy_.size() - 1; iy++) {
        real_t yi = hy_[iy];
        lines_.push_back(Line(Point2(-h_pitch_x, yi), Point2(h_pitch_x, yi)));
    }

    // Determine FSR volumes
    vol_ = VecF(n_reg_, dx * dy);

    return;
}

std::pair<real_t, Surface>
PinMesh_Rect::distance_to_surface(Point2 p, Direction dir) const
{
    std::pair<real_t, Surface> ret;
    ret.second = Surface::INTERNAL;
    ret.first  = std::numeric_limits<real_t>::max();
    for (const auto &l : lines_) {
        real_t d  = l.distance_to_surface(p, dir);
        ret.first = (d < ret.first) ? d : ret.first;
    }

    Box bound(Point2(-0.5 * pitch_x_, -0.5 * pitch_y_),
              Point2(0.5 * pitch_x_, 0.5 * pitch_y_));
    auto bound_d = bound.distance_to_surface(p, dir);
    if (bound_d.first < ret.first) {
        ret.first  = bound_d.first;
        ret.second = bound_d.second;
    }

    return ret;
}

int PinMesh_Rect::trace(Point2 p1, Point2 p2, int first_reg, VecF &s,
                        VecI &reg) const
{
    // Make a vector to store the collision points and add the start and end
    // points to it
    std::vector<Point2> ps;
    ps.push_back(p1);
    ps.push_back(p2);

    // Create a line object for the input points to test for collisions with
    Line l(p1, p2);

    // Test for collisions with all of the lines in the mesh
    for (auto &li : lines_) {
        Point2 p;
        int ret = Intersect(li, l, p);
        if (ret == 1) {
            ps.push_back(p);
        }
    }

    // Sort the points
    std::sort(ps.begin(), ps.end());
    ps.erase(std::unique(ps.begin(), ps.end()), ps.end());

    // Determine segment lengths and region indices
    for (unsigned int ip = 1; ip < ps.size(); ip++) {
        s.push_back(ps[ip].distance(ps[ip - 1]));
        reg.push_back(this->find_reg(Midpoint(ps[ip], ps[ip - 1])) + first_reg);
    }

    return ps.size() - 1;
}

/**
 * In the rectangular mesh, the indices are ordered naturally. The first
 * region is in the lower left, the last in the upper right, proceeding
 * first in the x direction, then in the y. nothing too fancy.
 */
int PinMesh_Rect::find_reg(Point2 p) const
{
    // Make sure the point is inside the pin
    if (fabs(p.x) > 0.5 * pitch_x_) {
        return -1;
    }
    if (fabs(p.y) > 0.5 * pitch_y_) {
        return -1;
    }

    int ix;
    for (ix = 0; ix < (int)hx_.size(); ix++) {
        if (hx_[ix] > p.x) {
            break;
        }
    }
    int iy;
    for (iy = 0; iy < (int)hy_.size(); iy++) {
        if (hy_[iy] > p.y) {
            break;
        }
    }

    int ireg = nx_ * iy + ix;
    assert(ireg < n_reg_);
    return ireg;
}

void PinMesh_Rect::print(std::ostream &os) const
{
    PinMesh::print(os);
    os << std::endl;
    os << "Type: Rectangular" << std::endl;
    os << "X Divisions: " << std::endl;
    for (const auto &xi : hx_) {
        os << "    " << xi << std::endl;
    }
    os << "Y Divisions: " << std::endl;
    for (const auto &yi : hy_) {
        os << "    " << yi << std::endl;
    }
    return;
}

int PinMesh_Rect::find_reg(Point2 p, Direction dir) const
{
    // Make sure the point is inside the pin
    if (((p.x < -0.5 * pitch_x_ + REAL_FUZZ) && (dir.ox < 0.0)) ||
        ((p.x > 0.5 * pitch_x_ - REAL_FUZZ) && (dir.ox > 0.0)) ||
        ((p.y < -0.5 * pitch_y_ + REAL_FUZZ) && (dir.oy < 0.0)) ||
        ((p.y > 0.5 * pitch_y_ - REAL_FUZZ) && (dir.oy > 0.0))) {
        return -1;
    }

    int ix = std::distance(
        hx_.begin(), std::lower_bound(hx_.begin(), hx_.end(), p.x, fuzzy_lt));
    if (fp_equiv_abs(p.x, hx_[ix])) {
        ix = (dir.ox > 0.0) ? ix + 1 : ix;
    }
    ix = std::max(0, std::min((int)nx_-1, ix-1));

    int iy = std::distance(
        hy_.begin(), std::lower_bound(hy_.begin(), hy_.end(), p.y, fuzzy_lt));
    if (fp_equiv_abs(p.y, hy_[iy])) {
        iy = (dir.oy > 0.0) ? iy + 1 : iy;
    }
    iy = std::max(0, std::min((int)ny_-1, iy-1));

    int ireg = nx_ * iy + ix;
    assert(ireg < n_reg_);
    return ireg;
}

std::string PinMesh_Rect::draw() const
{
    std::stringstream buf;

    for (auto l : lines_) {
        buf << "ctx.move_to(" << l.p1.x << ", " << l.p1.y << ")" << std::endl;
        buf << "ctx.line_to(" << l.p2.x << ", " << l.p2.y << ")" << std::endl;
        buf << "ctx.close_path()" << std::endl;
    }
    buf << "ctx.stroke()";

    return buf.str();
}
}
<commit_msg>fix bug in non-direction PinMesh_Rect find_reg<commit_after>/*
   Copyright 2016 Mitchell Young

   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 "pin_mesh_rect.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <sstream>
#include <string>

#include "pugixml.hpp"

#include "error.hpp"

namespace mocc {
PinMesh_Rect::PinMesh_Rect(const pugi::xml_node &input) : PinMesh(input)
{
    // Parse the number of x and y divisions
    int ndiv_x = input.child("sub_x").text().as_int(0);
    if (ndiv_x < 1) {
        throw EXCEPT("Failed to read valid number of X divisions in rect "
                     "pin mesh.");
    }
    int ndiv_y = input.child("sub_y").text().as_int(0);
    if (ndiv_y < 1) {
        throw EXCEPT("Failed to read valid number of Y divisions in rect "
                     "pin mesh.");
    }

    n_xsreg_ = ndiv_x * ndiv_y;
    n_reg_   = ndiv_x * ndiv_y;

    nx_ = ndiv_x;
    ny_ = ndiv_y;

    real_t dx = pitch_x_ / ndiv_x;
    real_t dy = pitch_y_ / ndiv_y;

    real_t h_pitch_x = 0.5 * pitch_x_;
    real_t h_pitch_y = 0.5 * pitch_y_;

    for (int i = 0; i <= ndiv_x; i++) {
        hx_.push_back(i * dx - h_pitch_x);
    }
    for (int i = 0; i <= ndiv_y; i++) {
        hy_.push_back(i * dy - h_pitch_y);
    }

    // Form lines representing the mesh boundaries
    for (unsigned ix = 1; ix < hx_.size() - 1; ix++) {
        real_t xi = hx_[ix];
        lines_.push_back(Line(Point2(xi, -h_pitch_y), Point2(xi, h_pitch_y)));
    }
    for (unsigned iy = 1; iy < hy_.size() - 1; iy++) {
        real_t yi = hy_[iy];
        lines_.push_back(Line(Point2(-h_pitch_x, yi), Point2(h_pitch_x, yi)));
    }

    // Determine FSR volumes
    vol_ = VecF(n_reg_, dx * dy);

    return;
}

std::pair<real_t, Surface>
PinMesh_Rect::distance_to_surface(Point2 p, Direction dir) const
{
    std::pair<real_t, Surface> ret;
    ret.second = Surface::INTERNAL;
    ret.first  = std::numeric_limits<real_t>::max();
    for (const auto &l : lines_) {
        real_t d  = l.distance_to_surface(p, dir);
        ret.first = (d < ret.first) ? d : ret.first;
    }

    Box bound(Point2(-0.5 * pitch_x_, -0.5 * pitch_y_),
              Point2(0.5 * pitch_x_, 0.5 * pitch_y_));
    auto bound_d = bound.distance_to_surface(p, dir);
    if (bound_d.first < ret.first) {
        ret.first  = bound_d.first;
        ret.second = bound_d.second;
    }

    return ret;
}

int PinMesh_Rect::trace(Point2 p1, Point2 p2, int first_reg, VecF &s,
                        VecI &reg) const
{
    // Make a vector to store the collision points and add the start and end
    // points to it
    std::vector<Point2> ps;
    ps.push_back(p1);
    ps.push_back(p2);

    // Create a line object for the input points to test for collisions with
    Line l(p1, p2);

    // Test for collisions with all of the lines in the mesh
    for (auto &li : lines_) {
        Point2 p;
        int ret = Intersect(li, l, p);
        if (ret == 1) {
            ps.push_back(p);
        }
    }

    // Sort the points
    std::sort(ps.begin(), ps.end());
    ps.erase(std::unique(ps.begin(), ps.end()), ps.end());

    // Determine segment lengths and region indices
    for (unsigned int ip = 1; ip < ps.size(); ip++) {
        s.push_back(ps[ip].distance(ps[ip - 1]));
        reg.push_back(this->find_reg(Midpoint(ps[ip], ps[ip - 1])) + first_reg);
    }

    return ps.size() - 1;
}

/**
 * In the rectangular mesh, the indices are ordered naturally. The first
 * region is in the lower left, the last in the upper right, proceeding
 * first in the x direction, then in the y. nothing too fancy.
 */
int PinMesh_Rect::find_reg(Point2 p) const
{
    // Make sure the point is inside the pin
    if (fabs(p.x) > 0.5 * pitch_x_) {
        return -1;
    }
    if (fabs(p.y) > 0.5 * pitch_y_) {
        return -1;
    }

    int ix = std::distance(
        hx_.begin(), std::lower_bound(hx_.begin(), hx_.end(), p.x, fuzzy_lt));
    int iy = std::distance(
        hy_.begin(), std::lower_bound(hy_.begin(), hy_.end(), p.y, fuzzy_lt));
    ix--;
    iy--;

    int ireg = nx_ * iy + ix;
    assert(ireg < n_reg_);
    return ireg;
}

int PinMesh_Rect::find_reg(Point2 p, Direction dir) const
{
    // Make sure the point is inside the pin
    if (((p.x < -0.5 * pitch_x_ + REAL_FUZZ) && (dir.ox < 0.0)) ||
        ((p.x > 0.5 * pitch_x_ - REAL_FUZZ) && (dir.ox > 0.0)) ||
        ((p.y < -0.5 * pitch_y_ + REAL_FUZZ) && (dir.oy < 0.0)) ||
        ((p.y > 0.5 * pitch_y_ - REAL_FUZZ) && (dir.oy > 0.0))) {
        return -1;
    }

    int ix = std::distance(
        hx_.begin(), std::lower_bound(hx_.begin(), hx_.end(), p.x, fuzzy_lt));
    if (fp_equiv_abs(p.x, hx_[ix])) {
        ix = (dir.ox > 0.0) ? ix + 1 : ix;
    }
    ix = std::max(0, std::min((int)nx_ - 1, ix - 1));

    int iy = std::distance(
        hy_.begin(), std::lower_bound(hy_.begin(), hy_.end(), p.y, fuzzy_lt));
    if (fp_equiv_abs(p.y, hy_[iy])) {
        iy = (dir.oy > 0.0) ? iy + 1 : iy;
    }
    iy = std::max(0, std::min((int)ny_ - 1, iy - 1));

    int ireg = nx_ * iy + ix;
    assert(ireg < n_reg_);
    return ireg;
}

void PinMesh_Rect::print(std::ostream &os) const
{
    PinMesh::print(os);
    os << std::endl;
    os << "Type: Rectangular" << std::endl;
    os << "X Divisions: " << std::endl;
    for (const auto &xi : hx_) {
        os << "    " << xi << std::endl;
    }
    os << "Y Divisions: " << std::endl;
    for (const auto &yi : hy_) {
        os << "    " << yi << std::endl;
    }
    return;
}

std::string PinMesh_Rect::draw() const
{
    std::stringstream buf;

    for (auto l : lines_) {
        buf << "ctx.move_to(" << l.p1.x << ", " << l.p1.y << ")" << std::endl;
        buf << "ctx.line_to(" << l.p2.x << ", " << l.p2.y << ")" << std::endl;
        buf << "ctx.close_path()" << std::endl;
    }
    buf << "ctx.stroke()";

    return buf.str();
}
}
<|endoftext|>


<commit_before>/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2018 Couchbase, 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 "rnd.h"
#include "internal.h"

#if !defined(COMPILER_SUPPORTS_CXX11) || (defined(_MSC_VER) && _MSC_VER < 1600)
static volatile int rnd_initialized = 0;
LCB_INTERNAL_API
void lcb_rnd_global_init(void)
{
    if (rnd_initialized) {
        return;
    }
    rnd_initialized = 1;
    if (lcb_getenv_boolean("LCB_NO_SRAND")) {
        return;
    }
    srand(time(NULL));
}

LCB_INTERNAL_API
lcb_U32 lcb_next_rand32(void)
{
    return (lcb_U32)rand();
}

LCB_INTERNAL_API
lcb_U64 lcb_next_rand64(void)
{
    return (lcb_U64)rand();
}
#else

#include <random>

LCB_INTERNAL_API
lcb_U32 lcb_next_rand32(void)
{
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution< lcb_U32 > dis;
    return dis(gen);
}

LCB_INTERNAL_API
lcb_U64 lcb_next_rand64(void)
{
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution< lcb_U64 > dis;
    return dis(gen);
}
#endif
<commit_msg>CCBC-963: remove global state from random generator fallback<commit_after>/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2018 Couchbase, 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 "rnd.h"
#include "internal.h"

#if !defined(COMPILER_SUPPORTS_CXX11) || (defined(_MSC_VER) && _MSC_VER < 1600)
LCB_INTERNAL_API
void lcb_rnd_global_init(void)
{
    if (lcb_getenv_boolean("LCB_NO_SRAND")) {
        return;
    }
    srand(time(NULL));
}

LCB_INTERNAL_API
lcb_U32 lcb_next_rand32(void)
{
    return (lcb_U32)rand();
}

LCB_INTERNAL_API
lcb_U64 lcb_next_rand64(void)
{
    return (lcb_U64)rand();
}
#else

#include <random>

LCB_INTERNAL_API
lcb_U32 lcb_next_rand32(void)
{
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution< lcb_U32 > dis;
    return dis(gen);
}

LCB_INTERNAL_API
lcb_U64 lcb_next_rand64(void)
{
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_int_distribution< lcb_U64 > dis;
    return dis(gen);
}
#endif
<|endoftext|>


<commit_before>#ifndef MP_LINKEDLIST_HPP
#define MP_LINKEDLIST_HPP

#include <boost/smart_ptr/intrusive_ref_counter.hpp>
#include <boost/atomic.hpp>
#include <assert.h>
#include "IntrusivePtr.hpp"

// lockfree

template<typename T>
class LinkedList {
public:
	struct Item;
	typedef IntrusivePtr<Item> ItemPtr;

	enum ItemState {
		S_Uninitialized,
		S_MainLink,
		S_Data,
	};

	struct Item : public boost::intrusive_ref_counter< Item, boost::thread_safe_counter > {
		ItemPtr prev, next;
		boost::atomic<ItemState> state;
		T value;

		Item() : state(S_Uninitialized), value() {}

		bool isEmpty() {
			ItemPtr nextCpy(next);
			if(!nextCpy) // can happen when clear() meanwhile
				return true;
			return nextCpy->state != S_Data;
		}

		bool insertBefore(ItemPtr& item) {
			ItemPtr oldPrev = prev.exchange(item);
			if(oldPrev) {
				ItemPtr oldPrevNext = oldPrev->next.exchange(item);
				// If pop_front() meanwhile and oldPrev was the first item,
				// we might have reset oldPrev->next already or will soon.
				// In the latter case, it will set item->prev = main, which is correct;
				// we do the same here, it doesn't matter which comes first.
				// Otherwise, we get here:
				if(!oldPrevNext) {
					// oldPrev is being returned by pop_front()
					oldPrev->next = NULL;
				}
				else {
					item->prev = oldPrev;
				}
			} else {
				// oldPrev == NULL -> clear() or pop_front() item.
				return false;
			}
			item->next = this;
			return true;
		}
	};

private:
	ItemPtr main; // prev = last, next = first

	ItemPtr _newMain() {
		ItemPtr m = new Item();
		m->next = m;
		m->prev = m;
		m->state = S_MainLink;
		return m;
	}

	void _releaseMain(const ItemPtr& m) {
		ItemPtr ptr = m;
		while(true) {
			ptr = ptr->next.exchange(NULL);
			if(!ptr) break;
		}
		ptr = m;
		while(true) {
			ptr = ptr->prev.exchange(NULL);
			if(!ptr) break;
		}
	}

public:
	LinkedList() {
		main = _newMain();
	}

	~LinkedList() {
		clear();

	}

	// The iterator is not thread-safe, i.e. you can't access
	// a single iterator from multiple threads. However,
	// the list can be accessed and modified from other threads.
	struct Iterator {
		ItemPtr ptr;

		Iterator(const ItemPtr& _ptr) : ptr(_ptr) {}

		T& operator*() {
			return ptr->value;
		}

		Iterator& operator++() {
			if(isEnd()) return *this;
			ptr = ptr->next;
			return *this;
		}

		bool operator==(const Iterator& other) const {
			if(isEnd() && other.isEnd()) return true;
			return ptr == other.ptr;
		}

		bool operator!=(const Iterator& other) const {
			return !(*this == other);
		}

		bool isEnd() const {
			if(ptr.get() == NULL) return true;
			if(ptr->state != S_Data) return true;
			return false;
		}
	};

	Iterator begin() {
		ItemPtr backup(main);
		return Iterator(backup->next);
	}

	Iterator end() {
		return Iterator(NULL);
	}

	// only single producer supported
	ItemPtr push_back(ItemPtr item = NULL) {
		ItemPtr mainCpy(main);
		if(!item) item.reset(new Item());
		item->state = S_Uninitialized;
		mainCpy->insertBefore(item);
		item->state = S_Data;
		return item;
	}

	// only single consumer supported
	ItemPtr pop_front() {
		ItemPtr mainCpy(main);
		ItemPtr first = mainCpy->next;
		if(!first || first == mainCpy || first->state != S_Data)
			return NULL;
		first->prev = NULL;
		ItemPtr firstNext = first->next.exchange(NULL);
		if(firstNext) // can happen to be NULL when clear() meanwhile
			// e.g. if firstNext==main and push_front() meanwhile,
			// main->prev != first. in that case, don't change.
			firstNext->prev.compare_exchange(first, mainCpy);
		if(!mainCpy->next.compare_exchange(first, firstNext))
			assert(false); // this can only happen if there was another consumer
		return first;
	}

	void clear() {
		ItemPtr oldMain = main.exchange(_newMain());
		_releaseMain(oldMain);
	}

	bool empty() {
		return ItemPtr(main)->isEmpty();
	}

	// be very careful! noone must use pop_front() or clear() meanwhile
	T& front() { return main->next->value; }
	T& back() { return main->prev->value; }

	// not threading-safe!
	size_t size() {
		ItemPtr ptr = main;
		size_t c = 0;
		while(true) {
			ptr = ptr->next;
			if(ptr->state != S_Data) break;
			c++;
		}
		return c;
	}

	// not threading-safe!
	void _checkSanity() {
		assert(main->state == S_MainLink);
		ItemPtr ptr = main;
		size_t c1 = 0;
		while(true) {
			assert(ptr->next->prev == ptr);
			assert(ptr->prev->next == ptr);
			ptr = ptr->next;
			if(ptr->state == S_MainLink) break;
			else if(ptr->state == S_Data) {} // ok
			else if(ptr->state == S_Uninitialized) assert(false);
			else assert(false);
			c1++;
		}
		assert(ptr->state == S_MainLink);
		size_t c2 = 0;
		ptr = main;
		while(true) {
			assert(ptr->next->prev == ptr);
			assert(ptr->prev->next == ptr);
			ptr = ptr->prev;
			if(ptr->state == S_MainLink) break;
			else if(ptr->state == S_Data) {} // ok
			else if(ptr->state == S_Uninitialized) assert(false);
			else assert(false);
			c2++;
		}
		assert(ptr->state == S_MainLink);
		assert(c1 == c2);
		if(c1 == 0) {
			assert(main->next == main);
			assert(main->prev == main);
		}
	}
};

#endif // LINKEDLIST_HPP
<commit_msg>better<commit_after>#ifndef MP_LINKEDLIST_HPP
#define MP_LINKEDLIST_HPP

#include <boost/smart_ptr/intrusive_ref_counter.hpp>
#include <boost/atomic.hpp>
#include <assert.h>
#include "IntrusivePtr.hpp"

// lockfree

template<typename T>
class LinkedList {
public:
	struct Item;
	typedef IntrusivePtr<Item> ItemPtr;

	enum ItemState {
		S_Uninitialized,
		S_MainLink,
		S_Data,
	};

	struct Item : public boost::intrusive_ref_counter< Item, boost::thread_safe_counter > {
		ItemPtr prev, next;
		boost::atomic<ItemState> state;
		T value;

		Item() : state(S_Uninitialized), value() {}

		bool isEmpty() {
			ItemPtr nextCpy(next);
			if(!nextCpy) // can happen when clear() meanwhile
				return true;
			return nextCpy->state != S_Data;
		}

		bool insertBefore(ItemPtr item) {
			ItemPtr oldPrev = prev.exchange(item);
			if(oldPrev) {
				bool success = oldPrev->next.compare_exchange(this, item);
				// If pop_front() meanwhile and oldPrev was the first item,
				// we might have reset oldPrev->next already or will soon.
				// In the latter case, it will set item->prev = main, which is correct;
				// we do the same here, it doesn't matter which comes first.
				if(success)
					item->prev = oldPrev;
			} else {
				// oldPrev == NULL -> clear() or pop_front() item.
				return false;
			}
			item->next = this;
			return true;
		}
	};

private:
	ItemPtr main; // prev = last, next = first

	ItemPtr _newMain() {
		ItemPtr m = new Item();
		m->next = m;
		m->prev = m;
		m->state = S_MainLink;
		return m;
	}

	void _releaseMain(const ItemPtr& m) {
		ItemPtr ptr = m;
		while(true) {
			ptr = ptr->next.exchange(NULL);
			if(!ptr) break;
		}
		ptr = m;
		while(true) {
			ptr = ptr->prev.exchange(NULL);
			if(!ptr) break;
		}
	}

public:
	LinkedList() {
		main = _newMain();
	}

	~LinkedList() {
		clear();

	}

	// The iterator is not thread-safe, i.e. you can't access
	// a single iterator from multiple threads. However,
	// the list can be accessed and modified from other threads.
	struct Iterator {
		ItemPtr ptr;

		Iterator(const ItemPtr& _ptr) : ptr(_ptr) {}

		T& operator*() {
			return ptr->value;
		}

		Iterator& operator++() {
			if(isEnd()) return *this;
			ptr = ptr->next;
			return *this;
		}

		bool operator==(const Iterator& other) const {
			if(isEnd() && other.isEnd()) return true;
			return ptr == other.ptr;
		}

		bool operator!=(const Iterator& other) const {
			return !(*this == other);
		}

		bool isEnd() const {
			if(ptr.get() == NULL) return true;
			if(ptr->state != S_Data) return true;
			return false;
		}
	};

	Iterator begin() {
		ItemPtr backup(main);
		return Iterator(backup->next);
	}

	Iterator end() {
		return Iterator(NULL);
	}

	// only single producer supported
	ItemPtr push_back(ItemPtr item = NULL) {
		ItemPtr mainCpy(main);
		if(!item) item.reset(new Item());
		item->state = S_Uninitialized;
		mainCpy->insertBefore(item);
		item->state = S_Data;
		return item;
	}

	// only single consumer supported
	ItemPtr pop_front() {
		ItemPtr mainCpy(main);
		ItemPtr first = mainCpy->next;
		if(!first || first == mainCpy || first->state != S_Data)
			return NULL;
		first->prev = NULL;
		ItemPtr firstNext = first->next.exchange(NULL);
		if(firstNext) // can happen to be NULL when clear() meanwhile
			// e.g. if firstNext==main and push_front() meanwhile,
			// main->prev != first. in that case, don't change.
			firstNext->prev.compare_exchange(first, mainCpy);
		if(!mainCpy->next.compare_exchange(first, firstNext))
			assert(false); // this can only happen if there was another consumer
		return first;
	}

	void clear() {
		ItemPtr oldMain = main.exchange(_newMain());
		_releaseMain(oldMain);
	}

	bool empty() {
		return ItemPtr(main)->isEmpty();
	}

	// be very careful! noone must use pop_front() or clear() meanwhile
	T& front() { return main->next->value; }
	T& back() { return main->prev->value; }

	// not threading-safe!
	size_t size() {
		ItemPtr ptr = main;
		size_t c = 0;
		while(true) {
			ptr = ptr->next;
			if(ptr->state != S_Data) break;
			c++;
		}
		return c;
	}

	// not threading-safe!
	void _checkSanity() {
		assert(main->state == S_MainLink);
		ItemPtr ptr = main;
		size_t c1 = 0;
		while(true) {
			assert(ptr->next->prev == ptr);
			assert(ptr->prev->next == ptr);
			ptr = ptr->next;
			if(ptr->state == S_MainLink) break;
			else if(ptr->state == S_Data) {} // ok
			else if(ptr->state == S_Uninitialized) assert(false);
			else assert(false);
			c1++;
		}
		assert(ptr->state == S_MainLink);
		size_t c2 = 0;
		ptr = main;
		while(true) {
			assert(ptr->next->prev == ptr);
			assert(ptr->prev->next == ptr);
			ptr = ptr->prev;
			if(ptr->state == S_MainLink) break;
			else if(ptr->state == S_Data) {} // ok
			else if(ptr->state == S_Uninitialized) assert(false);
			else assert(false);
			c2++;
		}
		assert(ptr->state == S_MainLink);
		assert(c1 == c2);
		if(c1 == 0) {
			assert(main->next == main);
			assert(main->prev == main);
		}
	}
};

#endif // LINKEDLIST_HPP
<|endoftext|>


<commit_before>/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                    _______    _                                     *
 *                   (  ____ \  ( \     |\     /|                      *
 *                   | (    \/  | (     ( \   / )                      *
 *                   | (__      | |      \ (_) /                       *
 *                   |  __)     | |       \   /                        *
 *                   | (        | |        ) (                         *
 *                   | )        | (____/\  | |                         *
 *                   |/         (_______/  \_/                         *
 *                                                                     *
 *                                                                     *
 *     fly is an awesome c++11 network library.                        *
 *                                                                     *
 *   @author: lichuan                                                  *
 *   @qq: 308831759                                                    *
 *   @email: 308831759@qq.com                                          *
 *   @github: https://github.com/lichuan/fly                           *
 *   @date: 2015-06-22 18:22:00                                        *
 *                                                                     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <unistd.h>
#include <cstring>
#include <netinet/in.h>
#include "fly/net/connection.hpp"
#include "fly/net/poller_task.hpp"
#include "fly/base/logger.hpp"

namespace fly {
namespace net {

fly::base::ID_Allocator Connection::m_id_allocator;

Connection::~Connection()
{
    while(auto *message_chunk = m_recv_msg_queue.pop())
    {
        delete message_chunk;
    }

    while(auto *message_chunk = m_send_msg_queue.pop())
    {
        delete message_chunk;
    }
}

Connection::Connection(int32 fd, const Addr &peer_addr)
{
    m_fd = fd;
    m_peer_addr = peer_addr;
}

uint64 Connection::id()
{
    return m_id;
}

void Connection::send(rapidjson::Document &doc)
{
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    doc.Accept(writer);
    send(buffer.GetString(), buffer.GetSize());
}

void Connection::send(const void *data, uint32 size)
{
    Message_Chunk *message_chunk = new Message_Chunk(size + sizeof(uint32));
    uint32 *uint32_ptr = (uint32*)message_chunk->read_ptr();
    *uint32_ptr = htonl(size);
    memcpy(message_chunk->read_ptr() + sizeof(uint32), data, size);
    message_chunk->write_ptr(size + sizeof(uint32));
    m_send_msg_queue.push(message_chunk);
    m_poller_task->write_connection(shared_from_this());
}

void Connection::close()
{
    m_poller_task->close_connection(shared_from_this());
}

const Addr& Connection::peer_addr()
{
    return m_peer_addr;
}

void Connection::parse()
{
    while(true)
    {
        char *msg_length_buf = (char*)(&m_cur_msg_length);
        uint32 remain_bytes = sizeof(uint32);

        if(m_cur_msg_length != 0)
        {
            goto after_parse_length;
        }

        if(m_recv_msg_queue.length() < sizeof(uint32))
        {
            break;
        }

        while(auto *message_chunk = m_recv_msg_queue.pop())
        {
            uint32 length = message_chunk->length();

            if(length < remain_bytes)
            {
                memcpy(msg_length_buf + sizeof(uint32) - remain_bytes, message_chunk->read_ptr(), length);
                remain_bytes -= length;
                delete message_chunk;
            }
            else
            {
                memcpy(msg_length_buf + sizeof(uint32) - remain_bytes, message_chunk->read_ptr(), remain_bytes);

                if(length == remain_bytes)
                {
                    delete message_chunk;
                }
                else
                {
                    message_chunk->read_ptr(remain_bytes);
                    m_recv_msg_queue.push_front(message_chunk);
                }

                break;
            }
        }

        m_cur_msg_length = ntohl(m_cur_msg_length);

    after_parse_length:
        if(m_recv_msg_queue.length() < m_cur_msg_length)
        {
            break;
        }

        const uint32 MAX_MSG_LEN = 65536;
        char data[MAX_MSG_LEN] = {0};
        remain_bytes = m_cur_msg_length;

        if(m_cur_msg_length > MAX_MSG_LEN / 2)
        {
            LOG_ERROR("message length exceed half of MAX_MSG_LEN(65536)");

            if(m_cur_msg_length > MAX_MSG_LEN)
            {
                LOG_FATAL("message length exceed MAX_MSG_LEN");

                break;
            }
        }

        while(auto *message_chunk = m_recv_msg_queue.pop())
        {
            uint32 length = message_chunk->length();

            if(length < remain_bytes)
            {
                memcpy(data + m_cur_msg_length - remain_bytes, message_chunk->read_ptr(), length);
                remain_bytes -= length;
                delete message_chunk;
            }
            else
            {
                memcpy(data + m_cur_msg_length - remain_bytes, message_chunk->read_ptr(), remain_bytes);

                if(length == remain_bytes)
                {
                    delete message_chunk;
                }
                else
                {
                    message_chunk->read_ptr(remain_bytes);
                    m_recv_msg_queue.push_front(message_chunk);
                }

                std::unique_ptr<Message> message(new Message(shared_from_this()));
                message->m_raw_data.assign(data, m_cur_msg_length);
                m_cur_msg_length = 0;
                rapidjson::Document &doc = message->doc();
                doc.Parse(message->m_raw_data.c_str());

                if(!doc.HasParseError())
                {
                    if(!doc.HasMember("msg_type"))
                    {
                        break;
                    }

                    const rapidjson::Value &message_type = doc["msg_type"];

                    if(!message_type.IsUint())
                    {
                        break;
                    }

                    message->m_type = message_type.GetUint();

                    if(!doc.HasMember("msg_cmd"))
                    {
                        break;
                    }

                    const rapidjson::Value &message_cmd = doc["msg_cmd"];

                    if(!message_cmd.IsUint())
                    {
                        break;
                    }

                    message->m_cmd = message_cmd.GetUint();
                    m_dispatch_cb(std::move(message));
                }

                break;
            }
        }
    }
}

}
}
<commit_msg>rename variable<commit_after>/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                    _______    _                                     *
 *                   (  ____ \  ( \     |\     /|                      *
 *                   | (    \/  | (     ( \   / )                      *
 *                   | (__      | |      \ (_) /                       *
 *                   |  __)     | |       \   /                        *
 *                   | (        | |        ) (                         *
 *                   | )        | (____/\  | |                         *
 *                   |/         (_______/  \_/                         *
 *                                                                     *
 *                                                                     *
 *     fly is an awesome c++11 network library.                        *
 *                                                                     *
 *   @author: lichuan                                                  *
 *   @qq: 308831759                                                    *
 *   @email: 308831759@qq.com                                          *
 *   @github: https://github.com/lichuan/fly                           *
 *   @date: 2015-06-22 18:22:00                                        *
 *                                                                     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <unistd.h>
#include <cstring>
#include <netinet/in.h>
#include "fly/net/connection.hpp"
#include "fly/net/poller_task.hpp"
#include "fly/base/logger.hpp"

namespace fly {
namespace net {

fly::base::ID_Allocator Connection::m_id_allocator;

Connection::~Connection()
{
    while(auto *message_chunk = m_recv_msg_queue.pop())
    {
        delete message_chunk;
    }

    while(auto *message_chunk = m_send_msg_queue.pop())
    {
        delete message_chunk;
    }
}

Connection::Connection(int32 fd, const Addr &peer_addr)
{
    m_fd = fd;
    m_peer_addr = peer_addr;
}

uint64 Connection::id()
{
    return m_id;
}

void Connection::send(rapidjson::Document &doc)
{
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    doc.Accept(writer);
    send(buffer.GetString(), buffer.GetSize());
}

void Connection::send(const void *data, uint32 size)
{
    Message_Chunk *message_chunk = new Message_Chunk(size + sizeof(uint32));
    uint32 *uint32_ptr = (uint32*)message_chunk->read_ptr();
    *uint32_ptr = htonl(size);
    memcpy(message_chunk->read_ptr() + sizeof(uint32), data, size);
    message_chunk->write_ptr(size + sizeof(uint32));
    m_send_msg_queue.push(message_chunk);
    m_poller_task->write_connection(shared_from_this());
}

void Connection::close()
{
    m_poller_task->close_connection(shared_from_this());
}

const Addr& Connection::peer_addr()
{
    return m_peer_addr;
}

void Connection::parse()
{
    while(true)
    {
        char *msg_length_buf = (char*)(&m_cur_msg_length);
        uint32 remain_bytes = sizeof(uint32);

        if(m_cur_msg_length != 0)
        {
            goto after_parse_length;
        }

        if(m_recv_msg_queue.length() < sizeof(uint32))
        {
            break;
        }

        while(auto *message_chunk = m_recv_msg_queue.pop())
        {
            uint32 length = message_chunk->length();

            if(length < remain_bytes)
            {
                memcpy(msg_length_buf + sizeof(uint32) - remain_bytes, message_chunk->read_ptr(), length);
                remain_bytes -= length;
                delete message_chunk;
            }
            else
            {
                memcpy(msg_length_buf + sizeof(uint32) - remain_bytes, message_chunk->read_ptr(), remain_bytes);

                if(length == remain_bytes)
                {
                    delete message_chunk;
                }
                else
                {
                    message_chunk->read_ptr(remain_bytes);
                    m_recv_msg_queue.push_front(message_chunk);
                }

                break;
            }
        }

        m_cur_msg_length = ntohl(m_cur_msg_length);

    after_parse_length:
        if(m_recv_msg_queue.length() < m_cur_msg_length)
        {
            break;
        }

        const uint32 MAX_MSG_LEN = 65536;
        char data[MAX_MSG_LEN] = {0};
        remain_bytes = m_cur_msg_length;

        if(m_cur_msg_length > MAX_MSG_LEN / 2)
        {
            LOG_ERROR("message length exceed half of MAX_MSG_LEN(65536)");

            if(m_cur_msg_length > MAX_MSG_LEN)
            {
                LOG_FATAL("message length exceed MAX_MSG_LEN");

                break;
            }
        }

        while(auto *message_chunk = m_recv_msg_queue.pop())
        {
            uint32 length = message_chunk->length();

            if(length < remain_bytes)
            {
                memcpy(data + m_cur_msg_length - remain_bytes, message_chunk->read_ptr(), length);
                remain_bytes -= length;
                delete message_chunk;
            }
            else
            {
                memcpy(data + m_cur_msg_length - remain_bytes, message_chunk->read_ptr(), remain_bytes);

                if(length == remain_bytes)
                {
                    delete message_chunk;
                }
                else
                {
                    message_chunk->read_ptr(remain_bytes);
                    m_recv_msg_queue.push_front(message_chunk);
                }

                std::unique_ptr<Message> message(new Message(shared_from_this()));
                message->m_raw_data.assign(data, m_cur_msg_length);
                m_cur_msg_length = 0;
                rapidjson::Document &doc = message->doc();
                doc.Parse(message->m_raw_data.c_str());

                if(!doc.HasParseError())
                {
                    if(!doc.HasMember("msg_type"))
                    {
                        break;
                    }

                    const rapidjson::Value &msg_type = doc["msg_type"];

                    if(!msg_type.IsUint())
                    {
                        break;
                    }

                    message->m_type = msg_type.GetUint();

                    if(!doc.HasMember("msg_cmd"))
                    {
                        break;
                    }

                    const rapidjson::Value &msg_cmd = doc["msg_cmd"];

                    if(!msg_cmd.IsUint())
                    {
                        break;
                    }

                    message->m_cmd = msg_cmd.GetUint();
                    m_dispatch_cb(std::move(message));
                }

                break;
            }
        }
    }
}

}
}
<|endoftext|>


<commit_before>#include "cv_capture.h"
#include "precompiled.hpp"
#if _MSC_VER
RUNTIME_COMPILER_LINKLIBRARY("ole32.lib")
#endif
using namespace EagleLib;
using namespace EagleLib::Nodes;

template <class T> void SafeRelease(T **ppT)
{
    if (*ppT)
    {
        (*ppT)->Release();
        *ppT = NULL;
    }
}

frame_grabber_cv::frame_grabber_cv():
    FrameGrabberThreaded()
{
    playback_frame_number = -1;
}

bool frame_grabber_cv::LoadFile(const std::string& file_path)
{
    if(d_LoadFile(file_path))
    {
        return true;
    }else
    {
        return h_LoadFile(file_path);
    }
    return false;
}

bool frame_grabber_cv::d_LoadFile(const std::string& file_path)
{
    d_cam.release();
    try
    {
        auto d_temp = cv::cudacodec::createVideoReader(file_path);
        if (d_temp)
        {
            d_cam = d_temp;
            loaded_document = file_path;
            return true;
        }
    }
    catch (cv::Exception& e)
    {

    }
    return false;
}

bool frame_grabber_cv::h_LoadFile(const std::string& file_path)
{
    h_cam.release();
    //LOG(info) << "Attemping to load " << file_path;
    BOOST_LOG_TRIVIAL(info ) << "[" << GetTreeName() << "::h_loadFile] Trying to load: \"" << file_path << "\"";
    boost::mutex::scoped_lock lock(buffer_mtx);

    frame_buffer.clear();
    buffer_begin_frame_number = 0;
    buffer_end_frame_number = 0;
    playback_frame_number = -1;
    try
    {
        h_cam.reset(new cv::VideoCapture());
        if (h_cam)
        {
            int index = -1;
            try
            {
                index = boost::lexical_cast<int>(file_path);
            }
            catch (boost::bad_lexical_cast e)
            {
                index = -1;
            }
            if (index == -1)
            {
                if (h_cam->open(file_path))
                {
                    loaded_document = file_path;
                    playback_frame_number = 0;
                    return true;
                }
            }
            else
            {
                if (h_cam->open(index))
                {
                    loaded_document = file_path;
                    playback_frame_number = 0;
                    return true;
                }
            }
        }
    }
    catch (cv::Exception& e)
    {
        LOG(debug) << "Unable to load " << file_path << " due to " << e.what();
    }
    return false;
}

long long frame_grabber_cv::GetNumFrames()
{
    if (d_cam)
    {
        return -1;
    }
    if (h_cam)
    {
        return h_cam->get(cv::CAP_PROP_FRAME_COUNT);
    }
    return -1;
}

TS<SyncedMemory> frame_grabber_cv::GetCurrentFrame(cv::cuda::Stream& stream)
{
    return TS<SyncedMemory>(current_frame.timestamp, current_frame.frame_number, current_frame.clone(stream));
}

TS<SyncedMemory> frame_grabber_cv::GetFrameImpl(int index, cv::cuda::Stream& stream)
{
    if (d_cam)
    {

    }
    if (h_cam)
    {
        if (h_cam->set(cv::CAP_PROP_POS_FRAMES, index))
        {
            return GetNextFrameImpl(stream);
        }
    }
    return TS<SyncedMemory>();
}

TS<SyncedMemory> frame_grabber_cv::GetNextFrameImpl(cv::cuda::Stream& stream)
{
    if (d_cam)
    {

    }
    if (h_cam)
    {
        cv::Mat h_mat;
        if (h_cam->read(h_mat))
        {
            if (!h_mat.empty())
            {
                cv::cuda::GpuMat d_mat;
                d_mat.upload(h_mat, stream);
                return TS<SyncedMemory>(h_cam->get(cv::CAP_PROP_POS_MSEC), (long long)h_cam->get(cv::CAP_PROP_POS_FRAMES), h_mat, d_mat);
            }
        }
    }
    return TS<SyncedMemory>();
}

frame_grabber_camera::frame_grabber_camera()
{
    this->_is_stream = true;
}
::std::vector<::std::string> frame_grabber_camera::ListLoadableDocuments()
{
    ::std::vector<::std::string> output;
#ifdef _MSC_VER
    MFStartup(MF_VERSION);
    HRESULT hr = S_OK;
    IMFAttributes *pAttributes = NULL;
    UINT32      m_cDevices; // contains the number of devices
    IMFActivate **m_ppDevices = NULL; // contains properties about each device

                                      // Initialize an attribute store. We will use this to
                                      // specify the enumeration parameters.

    hr = MFCreateAttributes(&pAttributes, 1);

    // Ask for source type = video capture devices
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
            );
    }
    // Enumerate devices.
    if (SUCCEEDED(hr))
    {
        hr = MFEnumDeviceSources(pAttributes, &m_ppDevices, &m_cDevices);
    }
    for (int i = 0; i < m_cDevices; ++i)
    {
        HRESULT hr = S_OK;
        wchar_t* ppszName = nullptr;
        hr = m_ppDevices[i]->GetAllocatedString(
            MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
            &ppszName,
            NULL
            );
        std::wstring wstring(ppszName);
        output.push_back(boost::lexical_cast<std::string>(i) + " - " + std::string(wstring.begin(), wstring.end()));
    }

    SafeRelease(&pAttributes);

    for (UINT32 i = 0; i < m_cDevices; i++)
    {
        SafeRelease(&m_ppDevices[i]);
    }
    CoTaskMemFree(m_ppDevices);
    m_ppDevices = NULL;

    m_cDevices = 0;

#else

#endif
    return output;
}
int frame_grabber_camera::CanLoadDocument(const std::string& doc)
{
    auto pos = doc.find(" - ");
    if(pos != std::string::npos)
    {
        try
        {
            int index = boost::lexical_cast<int>(doc.substr(pos));
            return 10;
        }catch(...)
        {
        }
    }else
    {
        try
        {
            int index = boost::lexical_cast<int>(doc);
            return 10;
        }
        catch (...)
        {
        }
    }
    auto cameras = ListLoadableDocuments();
    for(const auto& camera : cameras)
    {
        if(camera == doc)
            return 10;
    }
    return 0;
}
rcc::shared_ptr<ICoordinateManager> frame_grabber_camera::GetCoordinateManager()
{
    return rcc::shared_ptr<ICoordinateManager>();
}
TS<SyncedMemory> frame_grabber_camera::GetNextFrameImpl(cv::cuda::Stream& stream)
{
    if (d_cam)
    {

    }
    if (h_cam)
    {
        cv::Mat h_mat;
        if (h_cam->read(h_mat))
        {
            if (!h_mat.empty())
            {
                cv::cuda::GpuMat d_mat;
                d_mat.upload(h_mat, stream);
                return TS<SyncedMemory>(0.0, current_timestamp++, h_mat, d_mat);
            }else
            {
                LOG_EVERY_N(warning, 90) << "h_cam->read returned empty frame";
            }
        }else
        {
            LOG_EVERY_N(warning, 90) << "h_cam->read(h_mat) failed";
        }
    }
    if(!d_cam && !h_cam)
    {
        LOG_EVERY_N(warning, 10000) << "no video capture device specified";
    }
    return TS<SyncedMemory>();
}
bool frame_grabber_camera::LoadFile(const std::string& file_path)
{
    auto cameras = ListLoadableDocuments();
    int index = 0;
    for(auto camera : cameras)
    {
        if(camera == file_path)
        {
            h_cam.reset(new cv::VideoCapture());
            return h_cam->open(index);
        }
        ++index;
    }
    return false;
}
MO_REGISTER_CLASS(frame_grabber_camera);<commit_msg>Bugfix for loading camera on windows.<commit_after>#include "cv_capture.h"
#include "precompiled.hpp"
#if _MSC_VER
RUNTIME_COMPILER_LINKLIBRARY("ole32.lib")
#endif
using namespace EagleLib;
using namespace EagleLib::Nodes;

template <class T> void SafeRelease(T **ppT)
{
    if (*ppT)
    {
        (*ppT)->Release();
        *ppT = NULL;
    }
}

frame_grabber_cv::frame_grabber_cv():
    FrameGrabberThreaded()
{
    playback_frame_number = -1;
}

bool frame_grabber_cv::LoadFile(const std::string& file_path)
{
    if(d_LoadFile(file_path))
    {
        return true;
    }else
    {
        return h_LoadFile(file_path);
    }
    return false;
}

bool frame_grabber_cv::d_LoadFile(const std::string& file_path)
{
    d_cam.release();
    try
    {
        auto d_temp = cv::cudacodec::createVideoReader(file_path);
        if (d_temp)
        {
            d_cam = d_temp;
            loaded_document = file_path;
            return true;
        }
    }
    catch (cv::Exception& e)
    {

    }
    return false;
}

bool frame_grabber_cv::h_LoadFile(const std::string& file_path)
{
    h_cam.release();
    //LOG(info) << "Attemping to load " << file_path;
    BOOST_LOG_TRIVIAL(info ) << "[" << GetTreeName() << "::h_loadFile] Trying to load: \"" << file_path << "\"";
    boost::mutex::scoped_lock lock(buffer_mtx);

    frame_buffer.clear();
    buffer_begin_frame_number = 0;
    buffer_end_frame_number = 0;
    playback_frame_number = -1;
    try
    {
        h_cam.reset(new cv::VideoCapture());
        if (h_cam)
        {
            int index = -1;
            try
            {
                index = boost::lexical_cast<int>(file_path);
            }
            catch (boost::bad_lexical_cast e)
            {
                index = -1;
            }
            if (index == -1)
            {
                if (h_cam->open(file_path))
                {
                    loaded_document = file_path;
                    playback_frame_number = 0;
                    return true;
                }
            }
            else
            {
                if (h_cam->open(index))
                {
                    loaded_document = file_path;
                    playback_frame_number = 0;
                    return true;
                }
            }
        }
    }
    catch (cv::Exception& e)
    {
        LOG(debug) << "Unable to load " << file_path << " due to " << e.what();
    }
    return false;
}

long long frame_grabber_cv::GetNumFrames()
{
    if (d_cam)
    {
        return -1;
    }
    if (h_cam)
    {
        return h_cam->get(cv::CAP_PROP_FRAME_COUNT);
    }
    return -1;
}

TS<SyncedMemory> frame_grabber_cv::GetCurrentFrame(cv::cuda::Stream& stream)
{
    return TS<SyncedMemory>(current_frame.timestamp, current_frame.frame_number, current_frame.clone(stream));
}

TS<SyncedMemory> frame_grabber_cv::GetFrameImpl(int index, cv::cuda::Stream& stream)
{
    if (d_cam)
    {

    }
    if (h_cam)
    {
        if (h_cam->set(cv::CAP_PROP_POS_FRAMES, index))
        {
            return GetNextFrameImpl(stream);
        }
    }
    return TS<SyncedMemory>();
}

TS<SyncedMemory> frame_grabber_cv::GetNextFrameImpl(cv::cuda::Stream& stream)
{
    if (d_cam)
    {

    }
    if (h_cam)
    {
        cv::Mat h_mat;
        if (h_cam->read(h_mat))
        {
            if (!h_mat.empty())
            {
                cv::cuda::GpuMat d_mat;
                d_mat.upload(h_mat, stream);
                return TS<SyncedMemory>(h_cam->get(cv::CAP_PROP_POS_MSEC), (long long)h_cam->get(cv::CAP_PROP_POS_FRAMES), h_mat, d_mat);
            }
        }
    }
    return TS<SyncedMemory>();
}

frame_grabber_camera::frame_grabber_camera()
{
    this->_is_stream = true;
}
::std::vector<::std::string> frame_grabber_camera::ListLoadableDocuments()
{
    ::std::vector<::std::string> output;
#ifdef _MSC_VER
    MFStartup(MF_VERSION);
    HRESULT hr = S_OK;
    IMFAttributes *pAttributes = NULL;
    UINT32      m_cDevices; // contains the number of devices
    IMFActivate **m_ppDevices = NULL; // contains properties about each device

                                      // Initialize an attribute store. We will use this to
                                      // specify the enumeration parameters.

    hr = MFCreateAttributes(&pAttributes, 1);

    // Ask for source type = video capture devices
    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetGUID(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
            );
    }
    // Enumerate devices.
    if (SUCCEEDED(hr))
    {
        hr = MFEnumDeviceSources(pAttributes, &m_ppDevices, &m_cDevices);
    }
    for (int i = 0; i < m_cDevices; ++i)
    {
        HRESULT hr = S_OK;
        wchar_t* ppszName = nullptr;
        hr = m_ppDevices[i]->GetAllocatedString(
            MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
            &ppszName,
            NULL
            );
        std::wstring wstring(ppszName);
        output.push_back(boost::lexical_cast<std::string>(i) + " - " + std::string(wstring.begin(), wstring.end()));
    }

    SafeRelease(&pAttributes);

    for (UINT32 i = 0; i < m_cDevices; i++)
    {
        SafeRelease(&m_ppDevices[i]);
    }
    CoTaskMemFree(m_ppDevices);
    m_ppDevices = NULL;

    m_cDevices = 0;

#else

#endif
    return output;
}
int frame_grabber_camera::CanLoadDocument(const std::string& doc)
{
    auto pos = doc.find(" - ");
    if(pos != std::string::npos)
    {
        try
        {
            int index = boost::lexical_cast<int>(doc.substr(pos));
            return 10;
        }catch(...)
        {
        }
    }else
    {
        try
        {
            int index = boost::lexical_cast<int>(doc);
            return 10;
        }
        catch (...)
        {
        }
    }
    auto cameras = ListLoadableDocuments();
    for(const auto& camera : cameras)
    {
        if(camera == doc)
            return 10;
    }
    return 0;
}
rcc::shared_ptr<ICoordinateManager> frame_grabber_camera::GetCoordinateManager()
{
    return rcc::shared_ptr<ICoordinateManager>();
}
TS<SyncedMemory> frame_grabber_camera::GetNextFrameImpl(cv::cuda::Stream& stream)
{
    if (d_cam)
    {

    }
    if (h_cam)
    {
        cv::Mat h_mat;
        if (h_cam->read(h_mat))
        {
            if (!h_mat.empty())
            {
                cv::cuda::GpuMat d_mat;
                d_mat.upload(h_mat, stream);
                return TS<SyncedMemory>(0.0, current_timestamp++, h_mat, d_mat);
            }else
            {
                LOG_EVERY_N(warning, 90) << "h_cam->read returned empty frame";
            }
        }else
        {
            LOG_EVERY_N(warning, 90) << "h_cam->read(h_mat) failed";
        }
    }
    if(!d_cam && !h_cam)
    {
        LOG_EVERY_N(warning, 10000) << "no video capture device specified";
    }
    return TS<SyncedMemory>();
}
bool frame_grabber_camera::LoadFile(const std::string& file_path)
{
    auto cameras = ListLoadableDocuments();
    int index = 0;
    for(auto camera : cameras)
    {
        if(camera == file_path)
        {
            h_cam.reset(new cv::VideoCapture());
            return h_cam->open(index);
        }
        ++index;
    }
    auto func = [&cameras]()
    {
        std::stringstream ss;
        for (auto& cam : cameras)
            ss << cam << ", ";
        return ss.str();
    };
    LOG(debug) << "Unable to load " << file_path << " queried cameras: " << func() << " trying to requery";
    cameras = ListLoadableDocuments();
    for (auto camera : cameras)
    {
        if (camera == file_path)
        {
            h_cam.reset(new cv::VideoCapture());
            return h_cam->open(index);
        }
        ++index;
    }
    LOG(warning) << "Unable to load " << file_path << " queried cameras: " << func();
    return false;
}
MO_REGISTER_CLASS(frame_grabber_camera);<|endoftext|>