<commit_before>//
//  glmFeatureLabelLine.cpp
//  Labeling
//
//  Created by Patricio Gonzalez Vivo on 9/8/14.
//
//

#include "glmFeatureLabelLine.h"

glmFeatureLabelLine::glmFeatureLabelLine(){
}

glmFeatureLabelLine::glmFeatureLabelLine(const std::string &_text){
    setText(_text);
}

glmFeatureLabelLine::~glmFeatureLabelLine(){

}

void glmFeatureLabelLine::seedAnchorsEvery(glmAnchorLine &_anchorLine, float _minDistance, float _maxDistance){

    //  Update Fonts/Text cached values if something change
    //
    if(m_bChanged){
        updateCached();
    }

    float segmentLength = _anchorLine.getLength();

    //  How many times?
    int nTimes = segmentLength/(m_label.width+_maxDistance);

    //  At what distance between each other?
    float margin = (segmentLength-m_label.width*(float)nTimes)/((float)nTimes+1.0);

    //  Center the Labels
    float seed = margin;

    //  Add anchor points for seeds every _distance
    for (int i = 0; i < nTimes; i++) {
        _anchorLine.marks.push_back(AnchorMark(seed/_anchorLine.getLength()));
        seed += m_label.width+margin;
    }
}

void glmFeatureLabelLine::seedAnchorOnSegmentsAt(glmAnchorLine &_anchorLine, float _minDistance, float _maxDistance){

    //  Update Fonts/Text cached values if something change
    //
    if(m_bChanged){
        updateCached();
    }

    float lastSeed = 0.0;
    for (int i = 0; i < _anchorLine.size()-1; i++) {
        float offset = _anchorLine.getDistances()[i];

        float segmentLength = _anchorLine.getDistances()[i+1]-_anchorLine.getDistances()[i];//_anchorLine.getPolars()[i].r;

        //  Fits?
        //
        if( segmentLength >= (m_label.width+_maxDistance) ){

            //  How many times?
            int nTimes = segmentLength/(m_label.width+_maxDistance);

            //  At what distance between each other?
            float margin = (segmentLength-m_label.width*(float)nTimes)/((float)nTimes+1.0);

            //  Add anchors points for seeds
            float seed = margin;
            for (int i = 0; i < nTimes; i++) {
                float potentialSeed = offset + seed ;
                if( potentialSeed-lastSeed > _minDistance ){
                    lastSeed = potentialSeed;
                    _anchorLine.marks.push_back(AnchorMark(lastSeed/_anchorLine.getLength()));
                    seed += m_label.width+margin;
                }
            }

        } else if ( segmentLength >= m_label.width+_minDistance){

            //  Only one time
            //
            float margin = (segmentLength-m_label.width)*0.5;
            float potentialSeed = offset + margin ;
            if( potentialSeed-lastSeed > _minDistance){
                lastSeed = potentialSeed;
                _anchorLine.marks.push_back(AnchorMark(lastSeed/_anchorLine.getLength()));
            }
        }
    }
}

void glmFeatureLabelLine::updateCached(){
    if(m_font!=NULL&&m_text!="NONE"){

        m_lettersWidth.clear();
        m_wordsWidth.clear();

        FONScontext* ctx = m_font->getContext();
        std::string word = "";
        float wordWidth = 0.0f;

        std::cout << std::endl;

        for(int i = 0; i < m_text.size(); ++i) {
            float currentOffset = glfonsGetGlyphOffset(ctx, m_fsid, i);
            float nextOffset;
            float letterWidth;

            if(i < m_text.size() - 1) {
                nextOffset = glfonsGetGlyphOffset(ctx, m_fsid, i+1);
            } else {
                nextOffset = glfonsGetLength(ctx, m_fsid);
            }
            letterWidth = (nextOffset - currentOffset);

            float wordWidth = 0.0f;
            if( m_text[i] == ' '){
                m_lettersWidth.push_back(letterWidth);
                m_wordsWidth.push_back(wordWidth);
                wordWidth = 0.;
                word = "";
            } else {
                m_lettersWidth.push_back(letterWidth);
                wordWidth += letterWidth;
                word += &m_text[i];
            }
        }

        m_label = m_font->getStringBoundingBox(m_fsid);
    } else {
        bVisible = false;
    }
}

void glmFeatureLabelLine::draw2D(){
    if(m_font!=NULL&&m_text!="NONE"&&bVisible){

        //  Global m_alpha
        //
        if(m_cameraPos!=0 && bVisible){
            float angle = glm::dot(glm::normalize( *m_cameraPos - shapes[0].getCentroid()),glm::vec3(0.,0.,1.));
            m_alpha = lerpValue(m_alpha,powf( CLAMP(angle,0.01,1.0), 0.6 ),0.1);
        } else {
            m_alpha = lerpValue(m_alpha,0.0, 0.1);
        }

        if(m_alpha > 0.1){
            for (auto &it: m_anchorLines) {
                drawTextOn(it);
            }
        }

    }
}

void glmFeatureLabelLine::drawDebug(){

    glEnable(GL_LINE_STIPPLE);
    glLineStipple(1, 0x1111);
    for (auto &it: m_anchorLines) {
        it.draw();
    }
    glDisable(GL_LINE_STIPPLE);

    for (auto &it: m_anchorLines) {
        for (int i = 0; i < it.size(); i++) {
            if(i == 0 ){
                glLineWidth(2);
                drawCross(it[i],5);
            } else {
                glLineWidth(1);
                drawCross(it[i]);

                //  Print distances
                //
//                glPushMatrix();
//                glTranslated(it[i].x, it[i].y, it[i].z);
//                glScalef(0.75,-0.75,1);
//                glRotated(it.getPolars()[i-1].a*RAD_TO_DEG, 0, 0, -1);
//                glTranslated(5.,3.,0.);
//                m_font->drawString( toString( (int)it.getDistances()[i]), m_alpha );
//                glPopMatrix();
            }
        }
    }
}

void glmFeatureLabelLine::drawTextOn( glmAnchorLine &_anchorLine){
    if(_anchorLine.bLetterByLetter){
        drawLetterByLetter(_anchorLine);
    } else {
        drawAllTextAtOnce(_anchorLine);
    }
}

void glmFeatureLabelLine::drawAllTextAtOnce( glmAnchorLine &_anchorLine){
    for (auto &mark : _anchorLine.marks){
        glm::ivec4 viewport;
        glGetIntegerv(GL_VIEWPORT, &viewport[0]);
        glmRectangle screen = glmRectangle(viewport);

        //  Orientation
        //
        float angle = PI;
        glm::vec3 diff = _anchorLine[0]-_anchorLine[_anchorLine.size()-1];
        angle = atan2f(-diff.y, diff.x);
        float offset = mark.m_pct*_anchorLine.getLength();
        glm::vec3 src = _anchorLine.getPositionAt(offset);

        if(bVisible){
            mark.m_alpha = lerpValue(mark.m_alpha,m_alpha,0.1);
        } else {
            mark.m_alpha = lerpValue(mark.m_alpha,0.0,0.1);
        }

        if(screen.inside(src)){
            double rot = _anchorLine.getAngleAt(offset);

            glmRectangle boundingBox = glmPolyline(m_label,angle).getBoundingBox();
            boundingBox.translate( _anchorLine.getPositionAt( offset + m_label.width*0.5) );

            // Draw boundign box for debug
            //
//            boundingBox.drawCorners();

            bool bOver = false;

            for (int i = 0; i < pointLabels->size(); i++ ){
                if(pointLabels->at(i)->bVisible){
                    if( boundingBox.intersects(pointLabels->at(i)->getLabel(0) ) ){
                        bOver = true;
                        break;
                    }
                }
            }

            if(!bOver){
                FONScontext* fs = m_font->getContext();

                glfonsPushMatrix(fs);
                glfonsTranslate(fs, src.x, src.y);

                glfonsScale(fs, 1, -1);
                glfonsRotate(fs, rot * RAD_TO_DEG);

                if(angle < PI*0.5 && angle > -PI*0.5) {
                    glfonsScale(fs, -1, -1);
                    glfonsTranslate(fs, -m_label.width, 0);
                }

                glfonsTranslate(fs, 0.0, -m_label.height*0.5);
                m_font->drawString(m_fsid, mark.m_alpha);
                glfonsPopMatrix(fs);
            }
        }

    }
}

void glmFeatureLabelLine::drawLetterByLetter(glmAnchorLine &_anchorLine){
    for (auto &mark : _anchorLine.marks){
        glm::ivec4 viewport;
        glGetIntegerv(GL_VIEWPORT, &viewport[0]);
        glmRectangle screen = glmRectangle(viewport);

        //  Orientation
        //
        float angle = PI;
        glm::vec3 diff = _anchorLine[0]-_anchorLine[_anchorLine.size()-1];
        angle = atan2f(-diff.y, diff.x);
        float offset = mark.m_pct*_anchorLine.getLength();

        if(bVisible){
            mark.m_alpha = lerpValue(mark.m_alpha,m_alpha,0.1);
        } else {
            mark.m_alpha = lerpValue(mark.m_alpha,0.0,0.1);
        }

        if(angle < PI*0.5 && angle > -PI*0.5){
            for (int i = m_text.length()-1; i >=0 ; i--) {

                glm::vec3 src = _anchorLine.getPositionAt(offset);

                if(screen.inside(src)){
                    double rot = _anchorLine.getAngleAt(offset);

                    FONScontext* ctx = m_font->getContext();

                    glfonsPushMatrix(ctx);
                    glfonsTranslate(ctx, src.x, src.y);

                    glfonsScale(ctx, 1, -1);
                    glfonsRotate(ctx, rot * RAD_TO_DEG);

                    glfonsScale(ctx, -1, -1);
                    glfonsTranslate(ctx, -m_lettersWidth[i], 0);

                    glfonsTranslate(ctx, 0, -m_label.height*0.5);

                    m_font->drawSubString(m_fsid, i, false, mark.m_alpha);
                    glfonsPopMatrix(ctx);

                    offset += m_lettersWidth[i];
                } else {
                    break;
                }

            }
        } else {

            for (int i = 0; i < m_text.length(); i++) {
                glm::vec3 src = _anchorLine.getPositionAt(offset);
                if(screen.inside(src)){
                    double rot = _anchorLine.getAngleAt(offset);

                    FONScontext* ctx = m_font->getContext();

                    glfonsPushMatrix(ctx);
                    glfonsTranslate(ctx, src.x, src.y);

                    glfonsScale(ctx, 1, -1);
                    glfonsRotate(ctx, rot * RAD_TO_DEG);

                    glfonsTranslate(ctx, 0.0, -m_label.height * 0.5);

                    m_font->drawSubString(m_fsid, i, false, mark.m_alpha);

                    glfonsPopMatrix(ctx);
                    offset += m_lettersWidth[i];
                } else {
                    break;
                }
            }
        }
    }
}<commit_msg>minor update<commit_after>//
//  glmFeatureLabelLine.cpp
//  Labeling
//
//  Created by Patricio Gonzalez Vivo on 9/8/14.
//
//

#include "glmFeatureLabelLine.h"

glmFeatureLabelLine::glmFeatureLabelLine(){
}

glmFeatureLabelLine::glmFeatureLabelLine(const std::string &_text){
    setText(_text);
}

glmFeatureLabelLine::~glmFeatureLabelLine(){

}

void glmFeatureLabelLine::seedAnchorsEvery(glmAnchorLine &_anchorLine, float _minDistance, float _maxDistance){

    //  Update Fonts/Text cached values if something change
    //
    if(m_bChanged){
        updateCached();
    }

    float segmentLength = _anchorLine.getLength();

    //  How many times?
    int nTimes = segmentLength/(m_label.width+_maxDistance);

    //  At what distance between each other?
    float margin = (segmentLength-m_label.width*(float)nTimes)/((float)nTimes+1.0);

    //  Center the Labels
    float seed = margin;

    //  Add anchor points for seeds every _distance
    for (int i = 0; i < nTimes; i++) {
        _anchorLine.marks.push_back(AnchorMark(seed/_anchorLine.getLength()));
        seed += m_label.width+margin;
    }
}

void glmFeatureLabelLine::seedAnchorOnSegmentsAt(glmAnchorLine &_anchorLine, float _minDistance, float _maxDistance){

    //  Update Fonts/Text cached values if something change
    //
    if(m_bChanged){
        updateCached();
    }

    float lastSeed = 0.0;
    for (int i = 0; i < _anchorLine.size()-1; i++) {
        float offset = _anchorLine.getDistances()[i];

        float segmentLength = _anchorLine.getDistances()[i+1]-_anchorLine.getDistances()[i];//_anchorLine.getPolars()[i].r;

        //  Fits?
        //
        if( segmentLength >= (m_label.width+_maxDistance) ){

            //  How many times?
            int nTimes = segmentLength/(m_label.width+_maxDistance);

            //  At what distance between each other?
            float margin = (segmentLength-m_label.width*(float)nTimes)/((float)nTimes+1.0);

            //  Add anchors points for seeds
            float seed = margin;
            for (int i = 0; i < nTimes; i++) {
                float potentialSeed = offset + seed ;
                if( potentialSeed-lastSeed > _minDistance ){
                    lastSeed = potentialSeed;
                    _anchorLine.marks.push_back(AnchorMark(lastSeed/_anchorLine.getLength()));
                    seed += m_label.width+margin;
                }
            }

        } else if ( segmentLength >= m_label.width+_minDistance){

            //  Only one time
            //
            float margin = (segmentLength-m_label.width)*0.5;
            float potentialSeed = offset + margin ;
            if( potentialSeed-lastSeed > _minDistance){
                lastSeed = potentialSeed;
                _anchorLine.marks.push_back(AnchorMark(lastSeed/_anchorLine.getLength()));
            }
        }
    }
}

void glmFeatureLabelLine::updateCached(){
    if(m_font!=NULL&&m_text!="NONE"){

        m_lettersWidth.clear();
        m_wordsWidth.clear();

        FONScontext* ctx = m_font->getContext();
        std::string word = "";
        float wordWidth = 0.0f;

        for(int i = 0; i < m_text.size(); ++i) {
            float currentOffset = glfonsGetGlyphOffset(ctx, m_fsid, i);
            float nextOffset;
            float letterWidth;

            if(i < m_text.size() - 1) {
                nextOffset = glfonsGetGlyphOffset(ctx, m_fsid, i+1);
            } else {
                nextOffset = glfonsGetLength(ctx, m_fsid);
            }
            letterWidth = (nextOffset - currentOffset);

            float wordWidth = 0.0f;
            if( m_text[i] == ' '){
                m_lettersWidth.push_back(letterWidth);
                m_wordsWidth.push_back(wordWidth);
                wordWidth = 0.;
                word = "";
            } else {
                m_lettersWidth.push_back(letterWidth);
                wordWidth += letterWidth;
                word += &m_text[i];
            }
        }

        m_label = m_font->getStringBoundingBox(m_fsid);
        m_bChanged = false;
    } else {
        bVisible = false;
    }
}

void glmFeatureLabelLine::draw2D(){
    if(m_font!=NULL&&m_text!="NONE"&&bVisible){

        //  Global m_alpha
        //
        if(m_cameraPos!=0 && bVisible){
            float angle = glm::dot(glm::normalize( *m_cameraPos - shapes[0].getCentroid()),glm::vec3(0.,0.,1.));
            m_alpha = lerpValue(m_alpha,powf( CLAMP(angle,0.01,1.0), 0.6 ),0.1);
        } else {
            m_alpha = lerpValue(m_alpha,0.0, 0.1);
        }

        if(m_alpha > 0.1){
            for (auto &it: m_anchorLines) {
                drawTextOn(it);
            }
        }

    }
}

void glmFeatureLabelLine::drawDebug(){

    glEnable(GL_LINE_STIPPLE);
    glLineStipple(1, 0x1111);
    for (auto &it: m_anchorLines) {
        it.draw();
    }
    glDisable(GL_LINE_STIPPLE);

    for (auto &it: m_anchorLines) {
        for (int i = 0; i < it.size(); i++) {
            if(i == 0 ){
                glLineWidth(2);
                drawCross(it[i],5);
            } else {
                glLineWidth(1);
                drawCross(it[i]);

                //  Print distances
                //
//                glPushMatrix();
//                glTranslated(it[i].x, it[i].y, it[i].z);
//                glScalef(0.75,-0.75,1);
//                glRotated(it.getPolars()[i-1].a*RAD_TO_DEG, 0, 0, -1);
//                glTranslated(5.,3.,0.);
//                m_font->drawString( toString( (int)it.getDistances()[i]), m_alpha );
//                glPopMatrix();
            }
        }
    }
}

void glmFeatureLabelLine::drawTextOn( glmAnchorLine &_anchorLine){
    if(_anchorLine.bLetterByLetter){
        drawLetterByLetter(_anchorLine);
    } else {
        drawAllTextAtOnce(_anchorLine);
    }
}

void glmFeatureLabelLine::drawAllTextAtOnce( glmAnchorLine &_anchorLine){
    for (auto &mark : _anchorLine.marks){
        glm::ivec4 viewport;
        glGetIntegerv(GL_VIEWPORT, &viewport[0]);
        glmRectangle screen = glmRectangle(viewport);

        //  Orientation
        //
        float angle = PI;
        glm::vec3 diff = _anchorLine[0]-_anchorLine[_anchorLine.size()-1];
        angle = atan2f(-diff.y, diff.x);
        float offset = mark.m_pct*_anchorLine.getLength();
        glm::vec3 src = _anchorLine.getPositionAt(offset);

        if(bVisible){
            mark.m_alpha = lerpValue(mark.m_alpha,m_alpha,0.1);
        } else {
            mark.m_alpha = lerpValue(mark.m_alpha,0.0,0.1);
        }

        if(screen.inside(src)){
            double rot = _anchorLine.getAngleAt(offset);

            glmRectangle boundingBox = glmPolyline(m_label,angle).getBoundingBox();
            boundingBox.translate( _anchorLine.getPositionAt( offset + m_label.width*0.5) );

            // Draw boundign box for debug
            //
//            boundingBox.drawCorners();

            bool bOver = false;

            for (int i = 0; i < pointLabels->size(); i++ ){
                if(pointLabels->at(i)->bVisible){
                    if( boundingBox.intersects(pointLabels->at(i)->getLabel(0) ) ){
                        bOver = true;
                        break;
                    }
                }
            }

            if(!bOver){
                FONScontext* fs = m_font->getContext();

                glfonsPushMatrix(fs);
                glfonsTranslate(fs, src.x, src.y);

                glfonsScale(fs, 1, -1);
                glfonsRotate(fs, rot * RAD_TO_DEG);

                if(angle < PI*0.5 && angle > -PI*0.5) {
                    glfonsScale(fs, -1, -1);
                    glfonsTranslate(fs, -m_label.width, 0);
                }

                glfonsTranslate(fs, 0.0, -m_label.height*0.5);
                m_font->drawString(m_fsid, mark.m_alpha);
                glfonsPopMatrix(fs);
            }
        }

    }
}

void glmFeatureLabelLine::drawLetterByLetter(glmAnchorLine &_anchorLine){
    for (auto &mark : _anchorLine.marks){
        glm::ivec4 viewport;
        glGetIntegerv(GL_VIEWPORT, &viewport[0]);
        glmRectangle screen = glmRectangle(viewport);

        //  Orientation
        //
        float angle = PI;
        glm::vec3 diff = _anchorLine[0]-_anchorLine[_anchorLine.size()-1];
        angle = atan2f(-diff.y, diff.x);
        float offset = mark.m_pct*_anchorLine.getLength();

        if(bVisible){
            mark.m_alpha = lerpValue(mark.m_alpha,m_alpha,0.1);
        } else {
            mark.m_alpha = lerpValue(mark.m_alpha,0.0,0.1);
        }

        if(angle < PI*0.5 && angle > -PI*0.5){
            for (int i = m_text.length()-1; i >=0 ; i--) {

                glm::vec3 src = _anchorLine.getPositionAt(offset);

                if(screen.inside(src)){
                    double rot = _anchorLine.getAngleAt(offset);

                    FONScontext* ctx = m_font->getContext();

                    glfonsPushMatrix(ctx);
                    glfonsTranslate(ctx, src.x, src.y);

                    glfonsScale(ctx, 1, -1);
                    glfonsRotate(ctx, rot * RAD_TO_DEG);

                    glfonsScale(ctx, -1, -1);
                    glfonsTranslate(ctx, -m_lettersWidth[i], 0);

                    glfonsTranslate(ctx, 0, -m_label.height*0.5);

                    m_font->drawSubString(m_fsid, i, false, mark.m_alpha);
                    glfonsPopMatrix(ctx);

                    offset += m_lettersWidth[i];
                } else {
                    break;
                }

            }
        } else {

            for (int i = 0; i < m_text.length(); i++) {
                glm::vec3 src = _anchorLine.getPositionAt(offset);
                if(screen.inside(src)){
                    double rot = _anchorLine.getAngleAt(offset);

                    FONScontext* ctx = m_font->getContext();

                    glfonsPushMatrix(ctx);
                    glfonsTranslate(ctx, src.x, src.y);

                    glfonsScale(ctx, 1, -1);
                    glfonsRotate(ctx, rot * RAD_TO_DEG);

                    glfonsTranslate(ctx, 0.0, -m_label.height * 0.5);

                    m_font->drawSubString(m_fsid, i, false, mark.m_alpha);

                    glfonsPopMatrix(ctx);
                    offset += m_lettersWidth[i];
                } else {
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <cstdint>
#include <string>

#include <caf/actor_system_config.hpp>
#include <caf/deep_to_string.hpp>
#include <caf/meta/omittable_if_empty.hpp>
#include <caf/meta/type_name.hpp>

#include "vast/error.hpp"

#include "vast/detail/add_error_categories.hpp"

using namespace caf;

namespace vast::detail {

void add_error_categories(caf::actor_system_config& cfg) {
  auto vast_renderer = [](uint8_t x, atom_value, const message& msg) {
    return caf::deep_to_string(caf::meta::type_name("vast.ec"),
                               static_cast<ec>(x),
                               caf::meta::omittable_if_empty(), msg);
  };
  auto caf_renderer = [](uint8_t x, atom_value, const message& msg) {
    std::string result;
    result += "got caf::";
    result += to_string(static_cast<sec>(x));
    if (!msg.empty()) {
      result += ": ";
      result += deep_to_string(msg);
    }
    return result;
  };
  cfg.add_error_category(atom("vast"), vast_renderer);
  cfg.add_error_category(atom("system"), caf_renderer);
}

} // namespace vast::detail
<commit_msg>Do not override CAF's error renderer anymore<commit_after>/******************************************************************************
 *                    _   _____   __________                                  *
 *                   | | / / _ | / __/_  __/     Visibility                   *
 *                   | |/ / __ |_\ \  / /          Across                     *
 *                   |___/_/ |_/___/ /_/       Space and Time                 *
 *                                                                            *
 * This file is part of VAST. It is subject to the license terms in the       *
 * LICENSE file found in the top-level directory of this distribution and at  *
 * http://vast.io/license. No part of VAST, including this file, may be       *
 * copied, modified, propagated, or distributed except according to the terms *
 * contained in the LICENSE file.                                             *
 ******************************************************************************/

#include <cstdint>
#include <string>

#include <caf/actor_system_config.hpp>
#include <caf/deep_to_string.hpp>
#include <caf/meta/omittable_if_empty.hpp>
#include <caf/meta/type_name.hpp>

#include "vast/error.hpp"

#include "vast/detail/add_error_categories.hpp"

using namespace caf;

namespace vast::detail {

void add_error_categories(caf::actor_system_config& cfg) {
  auto vast_renderer = [](uint8_t x, atom_value, const message& msg) {
    return caf::deep_to_string(caf::meta::type_name("vast.ec"),
                               static_cast<ec>(x),
                               caf::meta::omittable_if_empty(), msg);
  };
  cfg.add_error_category(atom("vast"), vast_renderer);
}

} // namespace vast::detail
<|endoftext|>


<commit_before>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include <sstream>
#include <iostream>
#include <iomanip>
#include <atomic>
#include <thread>
#include <chrono>

#include "jimi/http_all.h"
#include "stop_watch.h"

using namespace jimi;
using namespace jimi::http;

#ifdef NDEBUG
static const std::size_t kIterations = 3000000;
#else
static const std::size_t kIterations = 10000;
#endif

#if 1
    static const char * http_header =
        "GET /cookies HTTP/1.1\r\n"
        "Host: 127.0.0.1:8090\r\n"
        "Connection: keep-alive\r\n"
        "Cache-Control: max-age=0\r\n"
        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
        "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\r\n"
        "Accept-Encoding: gzip,deflate,sdch\r\n"
        "Accept-Language: en-US,en;q=0.8\r\n"
        "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n"
        "Cookie: name=wookie\r\n"
        "\r\n";
#else
    // Reference from /h2o/picohttpparser/benchmark.c
    static const char * http_header =
        "GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n"
        "Host: www.kittyhell.com\r\n"
        "User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n"
        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
        "Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n"
        "Accept-Encoding: gzip,deflate\r\n"
        "Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n"
        "Keep-Alive: 115\r\n"
        "Connection: keep-alive\r\n"
        "Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; "
        "__utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; "
        "__utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral\r\n"
        "\r\n";
#endif

void stop_watch_test()
{
    StopWatch sw;
    getTickCountStopWatch swTickCount;
    static const std::size_t kSleepIterations = 20;

    StopWatch::time_stamp_t start_time, end_time;
    StopWatch::time_point_t start_point, end_point;
    start_time = StopWatch::timestamp();
    start_point = StopWatch::now();
    sw.start();
    swTickCount.start();
    for (std::size_t i = 0; i < kSleepIterations; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    swTickCount.stop();
    sw.stop();
    end_time = StopWatch::timestamp();
    end_point = StopWatch::now();

    std::cout << "Iterations:        " << kSleepIterations << std::endl;
    if (sw.getMillisec() != 0.0) {
        std::cout << "Time spent:        " << sw.getMillisec() << " ms" << std::endl;
        std::cout << "Time spent(*):     " << StopWatch::duration(end_time, start_time).millisecs() << " ms" << std::endl;
        std::cout << "Time spent(**):    " << StopWatch::duration(end_point, start_point).millisecs() << " ms" << std::endl;
        std::cout << "Time spent(Tick):  " << swTickCount.getMillisec() << " ms" << std::endl;
    }
    else {
        std::cout << "Time spent:        0.0 ms" << std::endl;
    }
    std::cout << std::endl;
}

void http_parser_test()
{
    StopWatch sw;
    int sum = 0;
    std::size_t request_len = ::strlen(http_header);

    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_test()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;

    sw.start();
    for (std::size_t i = 0; i < kIterations; ++i) {
        http::Parser<1024> http_parser;
        sum += http_parser.parseRequest(http_header, request_len);
    }
    sw.stop();

    std::cout << std::endl;
    std::cout << "Sum:               " << sum << std::endl;
    std::cout << "Length:            " << ::strlen(http_header) << std::endl;
    std::cout << "Iterations:        " << kIterations << std::endl;
    if (sw.getMillisec() != 0.0) {
        std::cout << "Time spent:        " << sw.getMillisec() << " ms" << std::endl;
        std::cout << "Parse speed:       " << (uint64_t)((double)kIterations / sw.getSecond()) << " Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  " << (double)(kIterations * request_len) / sw.getSecond() / (1024.0 * 1024.0) << " MB/Sec" << std::endl;
    }
    else {
        std::cout << "Time spent:        0.0 ms" << std::endl;
        std::cout << "Parse speed:       0   Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  0.0 MB/Sec" << std::endl;
    }
    std::cout << std::endl;
}

void http_parser_ref_test()
{
    StopWatch sw;
    int sum = 0;
    std::size_t request_len = ::strlen(http_header);

    StringRefHelper helper;
    static int mark = 0;

    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_ref_test()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    sw.start();
    for (std::size_t i = 0; i < kIterations; ++i) {
        http::ParserRef<1024> http_parser;
        sum += http_parser.parseRequest(http_header, request_len);
        if (mark < 3) {
            if (helper.attach(http_parser.getMethodStr())) {
                helper.truncate();
                std::cout << "method = " << http_parser.getMethodStr().c_str() << std::endl;
                helper.recover();
            }
            mark++;
        }
    }
    sw.stop();

    std::cout << std::endl;
    std::cout << "Sum:               " << sum << std::endl;
    std::cout << "Length:            " << ::strlen(http_header) << std::endl;
    std::cout << "Iterations:        " << kIterations << std::endl;
    if (sw.getMillisec() != 0.0) {
        std::cout << "Time spent:        " << sw.getMillisec() << " ms" << std::endl;
        std::cout << "Parse speed:       " << (uint64_t)((double)kIterations / sw.getSecond()) << " Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  " << (double)(kIterations * request_len) / sw.getSecond() / (1024.0 * 1024.0) << " MB/Sec" << std::endl;
    }
    else {
        std::cout << "Time spent:        0.0 ms" << std::endl;
        std::cout << "Parse speed:       0   Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  0.0 MB/Sec" << std::endl;
    }
    std::cout << std::endl;
}

void http_parser_benchmark()
{
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_benchmark()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    static const int kMaxLoop = 20;
    static std::atomic<int> loop_cnt(0);
	auto request_len = ::strlen(http_header);
	volatile int64_t count = 0;
    volatile int64_t dummy = 0;
	std::thread counter([&] {
		auto last_count = count;
		auto count_ = count;
        auto dummy_ = dummy;
		do {
            std::atomic_thread_fence(std::memory_order_acquire);
			count_ = count;
            dummy_ = dummy;
            std::atomic_thread_fence(std::memory_order_release);
#if 1
            std::cout << std::right << std::setw(10) << std::setfill(' ') << std::dec;
            std::cout << (count_ - last_count);
            std::cout << ", ";
			std::cout << std::right << std::setw(9) << std::setfill(' ') << std::fixed << std::setprecision(3);
            std::cout << (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0 << " MB/Sec";
            std::cout << ",  ";
            std::cout << std::left << std::dec << request_len;
            std::cout << " bytes,  dummy = ";
            std::cout << std::left << std::dec << dummy_;
            std::cout << std::endl;
#else
            printf("%lld,  %0.3f MB/Sec,  %llu bytes,  %lld\n", (count_ - last_count), (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0,
                ::strlen(http_header), dummy);
#endif
			last_count = count_;
			std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            loop_cnt++;
            if (loop_cnt > kMaxLoop) {
                break;
            }
		} while (1);
	});

    http::Parser<1024> http_parser;
	do {
        int64_t dummy_tmp = http_parser.parseRequest(http_header, request_len);
        dummy_tmp += (int64_t)http_parser.getEntrySize();
        http_parser.reset();
        std::atomic_thread_fence(std::memory_order_acquire);
        dummy += dummy_tmp;
		count++;
        if (loop_cnt > kMaxLoop) {
            std::atomic_thread_fence(std::memory_order_release);
            if (counter.joinable()) {
                counter.join();
            }
            break;
        }
        std::atomic_thread_fence(std::memory_order_release);
	} while (1);

    std::cout << std::endl;
}

void http_parser_ref_benchmark()
{
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_ref_benchmark()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    static const int kMaxLoop = 20;
    static std::atomic<int> loop_cnt(0);
	auto request_len = ::strlen(http_header);
	volatile int64_t count = 0;
    volatile int64_t dummy = 0;
	std::thread counter([&] {
		auto last_count = count;
		auto count_ = count;
        auto dummy_ = dummy;
		do {
            std::atomic_thread_fence(std::memory_order_acquire);
			count_ = count;
            dummy_ = dummy;
            std::atomic_thread_fence(std::memory_order_release);
#if 1
            std::cout << std::right << std::setw(10) << std::setfill(' ') << std::dec;
            std::cout << (count_ - last_count);
            std::cout << ", ";
			std::cout << std::right << std::setw(9) << std::setfill(' ') << std::fixed << std::setprecision(3);
            std::cout << (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0 << " MB/Sec";
            std::cout << ",  ";
            std::cout << std::left << std::dec << request_len;
            std::cout << " bytes,  dummy = ";
            std::cout << std::left << std::dec << dummy_;
            std::cout << std::endl;
#else
            printf("%lld,  %0.3f MB/Sec,  %llu bytes,  %lld\n", (count_ - last_count), (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0,
                ::strlen(http_header), dummy);
#endif
			last_count = count_;
			std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            loop_cnt++;
            if (loop_cnt > kMaxLoop) {
                break;
            }
		} while (1);
	});

    http::ParserRef<1024> http_parser;
	do {
        int64_t dummy_tmp = http_parser.parseRequest(http_header, request_len);
        dummy_tmp += (int64_t)http_parser.getEntrySize();
        http_parser.reset();
        std::atomic_thread_fence(std::memory_order_acquire);
        dummy += dummy_tmp;
		count++;
        if (loop_cnt > kMaxLoop) {
            std::atomic_thread_fence(std::memory_order_release);
            if (counter.joinable()) {
                counter.join();
            }
            break;
        }
        std::atomic_thread_fence(std::memory_order_release);
	} while (1);

    std::cout << std::endl;
}

int main(int argn, char * argv[])
{
    std::cout << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  Program: http_parser_test" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    http::Parser<1024> http_parser;
    http_parser.parseRequest(http_header, ::strlen(http_header));
    printf("http_parser.getVersion() = %s\n", http_parser.getVersionStr().c_str());
    printf("http_parser.getMethod() = %s\n", http_parser.getMethodStr().c_str());
    printf("http_parser.getURI() = %s\n", http_parser.getURI().c_str());
    printf("\n");
    http_parser.displayFields();
    printf("\n");

#if 1
    //stop_watch_test();
    http_parser_test();
    http_parser_ref_test();
#endif

    http_parser_benchmark();
    http_parser_ref_benchmark();

#ifdef _WIN32
    ::system("pause");
#endif
    return 0;
}
<commit_msg>小改动;<commit_after>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include <sstream>
#include <iostream>
#include <iomanip>
#include <atomic>
#include <thread>
#include <chrono>

#include "jimi/http_all.h"
#include "stop_watch.h"

using namespace jimi;
using namespace jimi::http;

#ifdef NDEBUG
static const std::size_t kIterations = 3000000;
#else
static const std::size_t kIterations = 10000;
#endif

#if 1
    static const char * http_header =
        "GET /cookies HTTP/1.1\r\n"
        "Host: 127.0.0.1:8090\r\n"
        "Connection: keep-alive\r\n"
        "Cache-Control: max-age=0\r\n"
        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
        "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\r\n"
        "Accept-Encoding: gzip,deflate,sdch\r\n"
        "Accept-Language: en-US,en;q=0.8\r\n"
        "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n"
        "Cookie: name=wookie\r\n"
        "\r\n";
#else
    // Reference from /h2o/picohttpparser/benchmark.c
    static const char * http_header =
        "GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n"
        "Host: www.kittyhell.com\r\n"
        "User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n"
        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
        "Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n"
        "Accept-Encoding: gzip,deflate\r\n"
        "Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n"
        "Keep-Alive: 115\r\n"
        "Connection: keep-alive\r\n"
        "Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; "
        "__utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; "
        "__utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral\r\n"
        "\r\n";
#endif

void stop_watch_test()
{
    StopWatch sw;
    getTickCountStopWatch swTickCount;
    static const std::size_t kSleepIterations = 20;

    StopWatch::time_stamp_t start_time, end_time;
    StopWatch::time_point_t start_point, end_point;
    start_time = StopWatch::timestamp();
    start_point = StopWatch::now();
    sw.start();
    swTickCount.start();
    for (std::size_t i = 0; i < kSleepIterations; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    swTickCount.stop();
    sw.stop();
    end_time = StopWatch::timestamp();
    end_point = StopWatch::now();

    std::cout << "Iterations:        " << kSleepIterations << std::endl;
    if (sw.getMillisec() != 0.0) {
        std::cout << "Time spent:        " << sw.getMillisec() << " ms" << std::endl;
        std::cout << "Time spent(*):     " << StopWatch::duration(end_time, start_time).millisecs() << " ms" << std::endl;
        std::cout << "Time spent(**):    " << StopWatch::duration(end_point, start_point).millisecs() << " ms" << std::endl;
        std::cout << "Time spent(Tick):  " << swTickCount.getMillisec() << " ms" << std::endl;
    }
    else {
        std::cout << "Time spent:        0.0 ms" << std::endl;
    }
    std::cout << std::endl;
}

void http_parser_test()
{
    StopWatch sw;
    int sum = 0;
    std::size_t request_len = ::strlen(http_header);

    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_test()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;

    sw.start();
    for (std::size_t i = 0; i < kIterations; ++i) {
        http::Parser<1024> http_parser;
        sum += http_parser.parseRequest(http_header, request_len);
    }
    sw.stop();

    std::cout << std::endl;
    std::cout << "Sum:               " << sum << std::endl;
    std::cout << "Length:            " << ::strlen(http_header) << std::endl;
    std::cout << "Iterations:        " << kIterations << std::endl;
    if (sw.getMillisec() != 0.0) {
        std::cout << "Time spent:        " << sw.getMillisec() << " ms" << std::endl;
        std::cout << "Parse speed:       " << (uint64_t)((double)kIterations / sw.getSecond()) << " Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  " << (double)(kIterations * request_len) / sw.getSecond() / (1024.0 * 1024.0) << " MB/Sec" << std::endl;
    }
    else {
        std::cout << "Time spent:        0.0 ms" << std::endl;
        std::cout << "Parse speed:       0   Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  0.0 MB/Sec" << std::endl;
    }
    std::cout << std::endl;
}

void http_parser_ref_test()
{
    StopWatch sw;
    int sum = 0;
    std::size_t request_len = ::strlen(http_header);

    StringRefHelper helper;
    static int mark = 0;

    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_ref_test()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    sw.start();
    for (std::size_t i = 0; i < kIterations; ++i) {
        http::ParserRef<1024> http_parser;
        sum += http_parser.parseRequest(http_header, request_len);
#if 0
        if (mark < 3) {
            if (helper.attach(http_parser.getMethodStr())) {
                helper.truncate();
                std::cout << "method = " << http_parser.getMethodStr().c_str() << std::endl;
                helper.recover();
            }
            mark++;
        }
#endif
    }
    sw.stop();

    std::cout << std::endl;
    std::cout << "Sum:               " << sum << std::endl;
    std::cout << "Length:            " << ::strlen(http_header) << std::endl;
    std::cout << "Iterations:        " << kIterations << std::endl;
    if (sw.getMillisec() != 0.0) {
        std::cout << "Time spent:        " << sw.getMillisec() << " ms" << std::endl;
        std::cout << "Parse speed:       " << (uint64_t)((double)kIterations / sw.getSecond()) << " Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  " << (double)(kIterations * request_len) / sw.getSecond() / (1024.0 * 1024.0) << " MB/Sec" << std::endl;
    }
    else {
        std::cout << "Time spent:        0.0 ms" << std::endl;
        std::cout << "Parse speed:       0   Parse/Sec" << std::endl;
        std::cout << "Parse throughput:  0.0 MB/Sec" << std::endl;
    }
    std::cout << std::endl;
}

void http_parser_benchmark()
{
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_benchmark()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    static const int kMaxLoop = 20;
    static std::atomic<int> loop_cnt(0);
	auto request_len = ::strlen(http_header);
	volatile int64_t count = 0;
    volatile int64_t dummy = 0;
	std::thread counter([&] {
		auto last_count = count;
		auto count_ = count;
        auto dummy_ = dummy;
		do {
            std::atomic_thread_fence(std::memory_order_acquire);
			count_ = count;
            dummy_ = dummy;
            std::atomic_thread_fence(std::memory_order_release);
#if 1
            std::cout << std::right << std::setw(10) << std::setfill(' ') << std::dec;
            std::cout << (count_ - last_count);
            std::cout << ", ";
			std::cout << std::right << std::setw(9) << std::setfill(' ') << std::fixed << std::setprecision(3);
            std::cout << (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0 << " MB/Sec";
            std::cout << ",  ";
            std::cout << std::left << std::dec << request_len;
            std::cout << " bytes,  dummy = ";
            std::cout << std::left << std::dec << dummy_;
            std::cout << std::endl;
#else
            printf("%lld,  %0.3f MB/Sec,  %llu bytes,  %lld\n", (count_ - last_count), (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0,
                ::strlen(http_header), dummy);
#endif
			last_count = count_;
			std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            loop_cnt++;
            if (loop_cnt > kMaxLoop) {
                break;
            }
		} while (1);
	});

    http::Parser<1024> http_parser;
	do {
        int64_t dummy_tmp = http_parser.parseRequest(http_header, request_len);
        dummy_tmp += (int64_t)http_parser.getEntrySize();
        http_parser.reset();
        std::atomic_thread_fence(std::memory_order_acquire);
        dummy += dummy_tmp;
		count++;
        if (loop_cnt > kMaxLoop) {
            std::atomic_thread_fence(std::memory_order_release);
            if (counter.joinable()) {
                counter.join();
            }
            break;
        }
        std::atomic_thread_fence(std::memory_order_release);
	} while (1);

    std::cout << std::endl;
}

void http_parser_ref_benchmark()
{
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  http_parser_ref_benchmark()" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    static const int kMaxLoop = 20;
    static std::atomic<int> loop_cnt(0);
	auto request_len = ::strlen(http_header);
	volatile int64_t count = 0;
    volatile int64_t dummy = 0;
	std::thread counter([&] {
		auto last_count = count;
		auto count_ = count;
        auto dummy_ = dummy;
		do {
            std::atomic_thread_fence(std::memory_order_acquire);
			count_ = count;
            dummy_ = dummy;
            std::atomic_thread_fence(std::memory_order_release);
#if 1
            std::cout << std::right << std::setw(10) << std::setfill(' ') << std::dec;
            std::cout << (count_ - last_count);
            std::cout << ", ";
			std::cout << std::right << std::setw(9) << std::setfill(' ') << std::fixed << std::setprecision(3);
            std::cout << (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0 << " MB/Sec";
            std::cout << ",  ";
            std::cout << std::left << std::dec << request_len;
            std::cout << " bytes,  dummy = ";
            std::cout << std::left << std::dec << dummy_;
            std::cout << std::endl;
#else
            printf("%lld,  %0.3f MB/Sec,  %llu bytes,  %lld\n", (count_ - last_count), (double)((count_ - last_count) * request_len) / 1024.0 / 1024.0,
                ::strlen(http_header), dummy);
#endif
			last_count = count_;
			std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            loop_cnt++;
            if (loop_cnt > kMaxLoop) {
                break;
            }
		} while (1);
	});

    http::ParserRef<1024> http_parser;
	do {
        int64_t dummy_tmp = http_parser.parseRequest(http_header, request_len);
        dummy_tmp += (int64_t)http_parser.getEntrySize();
        http_parser.reset();
        std::atomic_thread_fence(std::memory_order_acquire);
        dummy += dummy_tmp;
		count++;
        if (loop_cnt > kMaxLoop) {
            std::atomic_thread_fence(std::memory_order_release);
            if (counter.joinable()) {
                counter.join();
            }
            break;
        }
        std::atomic_thread_fence(std::memory_order_release);
	} while (1);

    std::cout << std::endl;
}

int main(int argn, char * argv[])
{
    std::cout << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << "  Program: http_parser_test" << std::endl;
    std::cout << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << std::endl;
    std::cout << std::endl;

    http::Parser<1024> http_parser;
    http_parser.parseRequest(http_header, ::strlen(http_header));
    printf("http_parser.getVersion() = %s\n", http_parser.getVersionStr().c_str());
    printf("http_parser.getMethod() = %s\n", http_parser.getMethodStr().c_str());
    printf("http_parser.getURI() = %s\n", http_parser.getURI().c_str());
    printf("\n");
    http_parser.displayFields();
    printf("\n");

#if 1
    //stop_watch_test();
    http_parser_test();
    http_parser_ref_test();
#endif

    http_parser_benchmark();
    http_parser_ref_benchmark();

#ifdef _WIN32
    ::system("pause");
#endif
    return 0;
}
<|endoftext|>


<commit_before>#include "Enemy.h"
#include "SDL.h"

Enemy::Enemy(const LoaderParams* pParams) : SDLGameObject(pParams) { }

void Enemy::draw()
{
	SDLGameObject::draw(); //now we use SDLGameObject
}

//Everything is same as Player, only update() characteristics differ
void Enemy::update()
{
	m_x += 1;
	m_y += 1;
	m_currentFrame = int((SDL_GetTicks() / 100) % 6);
}

void Enemy::clean()
{
	//blank clean() function
}<commit_msg>Update() of Enemy is now modified to handle m_position<commit_after>#include "Enemy.h"
#include "SDL.h"

Enemy::Enemy(const LoaderParams* pParams) : SDLGameObject(pParams) { }

void Enemy::draw()
{
	SDLGameObject::draw(); //now we use SDLGameObject
}

//Everything is same as Player, only update() characteristics differ
void Enemy::update()
{
	m_position.setX(m_position.getX() + 1);
	m_position.setY(m_position.getY() + 1);
	//m_currentFrame = int((SDL_GetTicks() / 100) % 6);
}

void Enemy::clean()
{
	//blank clean() function
}<|endoftext|>


<commit_before>#include "map/chart_generator.hpp"

#include "base/assert.hpp"
#include "base/math.hpp"

#include "std/algorithm.hpp"
#include "std/fstream.hpp"

#include "3party/agg/agg_conv_curve.h"
#include "3party/agg/agg_conv_stroke.h"
#include "3party/agg/agg_path_storage.h"
#include "3party/agg/agg_pixfmt_rgba.h"
#include "3party/agg/agg_rasterizer_scanline_aa.h"
#include "3party/agg/agg_renderer_primitives.h"
#include "3party/agg/agg_renderer_scanline.h"
#include "3party/agg/agg_scanline_p.h"

namespace
{
template <class Color, class Order>
struct BlendAdaptor
{
  using order_type = Order;
  using color_type = Color;
  using TValueType = typename color_type::value_type;
  using TCalcType = typename color_type::calc_type;

  enum
  {
    ScaleShift = color_type::base_shift,
    ScaleMask = color_type::base_mask,
  };

  static AGG_INLINE void blend_pix(unsigned op, TValueType * p, unsigned cr, unsigned cg,
                                   unsigned cb, unsigned ca, unsigned cover)
  {
    using TBlendTable = agg::comp_op_table_rgba<Color, Order>;
    if (p[Order::A])
    {
      TBlendTable::g_comp_op_func[op](p, (cr * ca + ScaleMask) >> ScaleShift,
                                      (cg * ca + ScaleMask) >> ScaleShift,
                                      (cb * ca + ScaleMask) >> ScaleShift, ca, cover);
    }
    else
    {
      TBlendTable::g_comp_op_func[op](p, cr, cg, cb, ca, cover);
    }
  }
};

agg::rgba8 GetLineColor(MapStyle mapStyle)
{
  switch (mapStyle)
  {
  case MapStyleCount:
    LOG(LERROR, ("Wrong map style param."));
    // No need break or return here.
  case MapStyleDark:
    return agg::rgba8(255, 230, 140, 255);
  case MapStyleLight:
  case MapStyleClear:
  case MapStyleMerged:
    return agg::rgba8(30, 150, 240, 255);
  }
}

agg::rgba8 GetCurveColor(MapStyle mapStyle)
{
  switch (mapStyle)
  {
  case MapStyleCount:
    LOG(LERROR, ("Wrong map style param."));
    // No need break or return here.
  case MapStyleDark:
    return agg::rgba8(255, 230, 140, 20);
  case MapStyleLight:
  case MapStyleClear:
  case MapStyleMerged:
    return agg::rgba8(30, 150, 240, 20);
  }
}
}  // namespace

namespace maps
{
void ScaleChartData(vector<double> & chartData, double scale)
{
  for (size_t i = 0; i < chartData.size(); ++i)
    chartData[i] *= scale;
}

void ShiftChartData(vector<double> & chartData, double shift)
{
  for (size_t i = 0; i < chartData.size(); ++i)
    chartData[i] += shift;
}

void ReflectChartData(vector<double> & chartData)
{
  for (size_t i = 0; i < chartData.size(); ++i)
    chartData[i] = -chartData[i];
}

bool NormalizeChartData(vector<double> const & distanceDataM,
                        feature::TAltitudes const & altitudeDataM, size_t resultPointCount,
                        vector<double> & uniformAltitudeDataM)
{
  double constexpr kEpsilon = 1e-6;

  if (distanceDataM.size() != altitudeDataM.size())
  {
    LOG(LERROR, ("Altitude and distance data have different size."));
    return false;
  }

  if (!is_sorted(distanceDataM.cbegin(), distanceDataM.cend()))
  {
    LOG(LERROR, ("Route segment distances are not sorted."));
    return false;
  }

  if (distanceDataM.empty() || resultPointCount == 0)
  {
    uniformAltitudeDataM.clear();
    return true;
  }

  auto const calculateAltitude = [&](double distFormStartM) {
    if (distFormStartM <= distanceDataM.front())
      return static_cast<double>(altitudeDataM.front());
    if (distFormStartM >= distanceDataM.back())
      return static_cast<double>(altitudeDataM.back());

    auto const lowerIt = lower_bound(distanceDataM.cbegin(), distanceDataM.cend(), distFormStartM);
    size_t const nextPointIdx = distance(distanceDataM.cbegin(), lowerIt);
    ASSERT_LESS(0, nextPointIdx, ("distFormStartM is greater than 0 but nextPointIdx == 0."));
    size_t const prevPointIdx = nextPointIdx - 1;

    if (my::AlmostEqualAbs(distanceDataM[prevPointIdx], distanceDataM[nextPointIdx], kEpsilon))
      return static_cast<double>(altitudeDataM[prevPointIdx]);

    double const k = (altitudeDataM[nextPointIdx] - altitudeDataM[prevPointIdx]) /
                     (distanceDataM[nextPointIdx] - distanceDataM[prevPointIdx]);
    return static_cast<double>(altitudeDataM[prevPointIdx]) +
           k * (distFormStartM - distanceDataM[prevPointIdx]);
  };

  double const routeLenM = distanceDataM.back();
  uniformAltitudeDataM.resize(resultPointCount);
  double const stepLenM = resultPointCount <= 1 ? 0.0 : routeLenM / (resultPointCount - 1);

  for (size_t i = 0; i < resultPointCount; ++i)
    uniformAltitudeDataM[i] = calculateAltitude(static_cast<double>(i) * stepLenM);

  return true;
}

bool GenerateYAxisChartData(uint32_t height, double minMetersPerPxl,
                            vector<double> const & altitudeDataM, vector<double> & yAxisDataPxl)
{
  if (altitudeDataM.empty())
  {
    yAxisDataPxl.clear();
    return true;
  }

  uint32_t constexpr kHeightIndentPxl = 2;
  uint32_t heightIndentPxl = kHeightIndentPxl;
  if (height <= 2 * kHeightIndentPxl)
  {
    LOG(LERROR, ("Chart height is less or equal than 2 * kHeightIndentPxl (", 2 * kHeightIndentPxl, ")"));
    heightIndentPxl = 0;
  }

  auto const minMaxAltitudeIt = minmax_element(altitudeDataM.begin(), altitudeDataM.end());
  double const minAltM = *minMaxAltitudeIt.first;
  double const maxAltM = *minMaxAltitudeIt.second;
  double const deltaAltM = maxAltM - minAltM;
  uint32_t const drawHeightPxl = height - 2 * heightIndentPxl;
  double const metersPerPxl = max(minMetersPerPxl, deltaAltM / static_cast<double>(drawHeightPxl));
  if (metersPerPxl == 0.0)
  {
    LOG(LERROR, ("metersPerPxl == 0.0"));
    return false;
  }

  double const deltaAltPxl = deltaAltM / metersPerPxl;
  double const freeHeightSpacePxl = drawHeightPxl - deltaAltPxl;
  if (freeHeightSpacePxl < 0 || freeHeightSpacePxl > drawHeightPxl)
  {
    LOG(LERROR, ("Number of pixels free of chart points (", freeHeightSpacePxl,
                 ") is below zero or greater number of pixels for the chart (", drawHeightPxl, ")."));
    return false;
  }

  double const maxAltPxl = maxAltM / metersPerPxl;
  yAxisDataPxl.assign(altitudeDataM.cbegin(), altitudeDataM.cend());
  ScaleChartData(yAxisDataPxl, 1.0 / metersPerPxl);
  ReflectChartData(yAxisDataPxl);
  ShiftChartData(yAxisDataPxl, maxAltPxl + heightIndentPxl + freeHeightSpacePxl / 2.0);

  return true;
}

bool GenerateChartByPoints(uint32_t width, uint32_t height, vector<m2::PointD> const & geometry,
                           MapStyle mapStyle, vector<uint8_t> & frameBuffer)
{
  frameBuffer.clear();
  if (width == 0 || height == 0)
    return false;

  agg::rgba8 const kBackgroundColor = agg::rgba8(255, 255, 255, 0);
  agg::rgba8 const kLineColor = GetLineColor(mapStyle);
  agg::rgba8 const kCurveColor = GetCurveColor(mapStyle);
  double constexpr kLineWidthPxl = 2.0;

  using TBlender = BlendAdaptor<agg::rgba8, agg::order_rgba>;
  using TPixelFormat = agg::pixfmt_custom_blend_rgba<TBlender, agg::rendering_buffer>;
  using TBaseRenderer = agg::renderer_base<TPixelFormat>;
  using TPrimitivesRenderer = agg::renderer_primitives<TBaseRenderer>;
  using TSolidRenderer = agg::renderer_scanline_aa_solid<TBaseRenderer>;
  using TPath = agg::poly_container_adaptor<vector<m2::PointD>>;
  using TStroke = agg::conv_stroke<TPath>;

  agg::rendering_buffer renderBuffer;
  TPixelFormat pixelFormat(renderBuffer, agg::comp_op_src_over);
  TBaseRenderer baseRenderer(pixelFormat);

  frameBuffer.assign(width * kAltitudeChartBPP * height, 0);
  renderBuffer.attach(&frameBuffer[0], static_cast<unsigned>(width),
                      static_cast<unsigned>(height), static_cast<int>(width * kAltitudeChartBPP));

  // Background.
  baseRenderer.reset_clipping(true);
  unsigned const op = pixelFormat.comp_op();
  pixelFormat.comp_op(agg::comp_op_src);
  baseRenderer.clear(kBackgroundColor);
  pixelFormat.comp_op(op);

  agg::rasterizer_scanline_aa<> rasterizer;
  rasterizer.clip_box(0, 0, width, height);

  if (geometry.empty())
    return true; /* No chart line to draw. */

  // Polygon under chart line.
  agg::path_storage underChartGeometryPath;
  underChartGeometryPath.move_to(geometry.front().x, static_cast<double>(height));
  for (auto const & p : geometry)
    underChartGeometryPath.line_to(p.x, p.y);
  underChartGeometryPath.line_to(geometry.back().x, static_cast<double>(height));
  underChartGeometryPath.close_polygon();

  agg::conv_curve<agg::path_storage> curve(underChartGeometryPath);
  rasterizer.add_path(curve);
  agg::scanline32_p8 scanline;
  agg::render_scanlines_aa_solid(rasterizer, scanline, baseRenderer, kCurveColor);

  // Chart line.
  TPath path_adaptor(geometry, false);
  TStroke stroke(path_adaptor);
  stroke.width(kLineWidthPxl);
  stroke.line_cap(agg::round_cap);
  stroke.line_join(agg::round_join);

  rasterizer.add_path(stroke);
  agg::render_scanlines_aa_solid(rasterizer, scanline, baseRenderer, kLineColor);
  return true;
}

bool GenerateChart(uint32_t width, uint32_t height, vector<double> const & distanceDataM,
                   feature::TAltitudes const & altitudeDataM, MapStyle mapStyle,
                   vector<uint8_t> & frameBuffer)
{
  if (distanceDataM.size() != altitudeDataM.size())
  {
    LOG(LERROR, ("The route is in inconsistent state. Size of altitudes is", altitudeDataM.size(),
                 ". Number of segment is", distanceDataM.size()));
    return false;
  }

  vector<double> uniformAltitudeDataM;
  if (!NormalizeChartData(distanceDataM, altitudeDataM, width, uniformAltitudeDataM))
    return false;

  vector<double> yAxisDataPxl;
  if (!GenerateYAxisChartData(height, 1.0 /* minMetersPerPxl */, uniformAltitudeDataM, yAxisDataPxl))
    return false;

  size_t const uniformAltitudeDataSize = yAxisDataPxl.size();
  vector<m2::PointD> geometry(uniformAltitudeDataSize);

  if (uniformAltitudeDataSize != 0)
  {
    double const oneSegLenPix =
        static_cast<double>(width) / (uniformAltitudeDataSize == 1 ? 1 : (uniformAltitudeDataSize - 1));
    for (size_t i = 0; i < uniformAltitudeDataSize; ++i)
      geometry[i] = m2::PointD(i * oneSegLenPix, yAxisDataPxl[i]);
  }

  return GenerateChartByPoints(width, height, geometry, mapStyle, frameBuffer);
}
}  // namespace maps
<commit_msg>Review fixes.<commit_after>#include "map/chart_generator.hpp"

#include "base/assert.hpp"
#include "base/math.hpp"

#include "std/algorithm.hpp"
#include "std/fstream.hpp"

#include "3party/agg/agg_conv_curve.h"
#include "3party/agg/agg_conv_stroke.h"
#include "3party/agg/agg_path_storage.h"
#include "3party/agg/agg_pixfmt_rgba.h"
#include "3party/agg/agg_rasterizer_scanline_aa.h"
#include "3party/agg/agg_renderer_primitives.h"
#include "3party/agg/agg_renderer_scanline.h"
#include "3party/agg/agg_scanline_p.h"

namespace
{
template <class Color, class Order>
struct BlendAdaptor
{
  using order_type = Order;
  using color_type = Color;
  using TValueType = typename color_type::value_type;
  using TCalcType = typename color_type::calc_type;

  enum
  {
    ScaleShift = color_type::base_shift,
    ScaleMask = color_type::base_mask,
  };

  static AGG_INLINE void blend_pix(unsigned op, TValueType * p, unsigned cr, unsigned cg,
                                   unsigned cb, unsigned ca, unsigned cover)
  {
    using TBlendTable = agg::comp_op_table_rgba<Color, Order>;
    if (p[Order::A])
    {
      TBlendTable::g_comp_op_func[op](p, (cr * ca + ScaleMask) >> ScaleShift,
                                      (cg * ca + ScaleMask) >> ScaleShift,
                                      (cb * ca + ScaleMask) >> ScaleShift, ca, cover);
    }
    else
    {
      TBlendTable::g_comp_op_func[op](p, cr, cg, cb, ca, cover);
    }
  }
};

agg::rgba8 GetLineColor(MapStyle mapStyle)
{
  switch (mapStyle)
  {
  case MapStyleCount:
    LOG(LERROR, ("Wrong map style param."));
    // No need break or return here.
  case MapStyleDark:
    return agg::rgba8(255, 230, 140, 255);
  case MapStyleLight:
  case MapStyleClear:
  case MapStyleMerged:
    return agg::rgba8(30, 150, 240, 255);
  }
}

agg::rgba8 GetCurveColor(MapStyle mapStyle)
{
  switch (mapStyle)
  {
  case MapStyleCount:
    LOG(LERROR, ("Wrong map style param."));
    // No need break or return here.
  case MapStyleDark:
    return agg::rgba8(255, 230, 140, 20);
  case MapStyleLight:
  case MapStyleClear:
  case MapStyleMerged:
    return agg::rgba8(30, 150, 240, 20);
  }
}
}  // namespace

namespace maps
{
void ScaleChartData(vector<double> & chartData, double scale)
{
  for (size_t i = 0; i < chartData.size(); ++i)
    chartData[i] *= scale;
}

void ShiftChartData(vector<double> & chartData, double shift)
{
  for (size_t i = 0; i < chartData.size(); ++i)
    chartData[i] += shift;
}

void ReflectChartData(vector<double> & chartData)
{
  for (size_t i = 0; i < chartData.size(); ++i)
    chartData[i] = -chartData[i];
}

bool NormalizeChartData(vector<double> const & distanceDataM,
                        feature::TAltitudes const & altitudeDataM, size_t resultPointCount,
                        vector<double> & uniformAltitudeDataM)
{
  double constexpr kEpsilon = 1e-6;

  if (distanceDataM.size() != altitudeDataM.size())
  {
    LOG(LERROR, ("Altitude and distance data have different size."));
    return false;
  }

  if (!is_sorted(distanceDataM.cbegin(), distanceDataM.cend()))
  {
    LOG(LERROR, ("Route segment distances are not sorted."));
    return false;
  }

  if (distanceDataM.empty() || resultPointCount == 0)
  {
    uniformAltitudeDataM.clear();
    return true;
  }

  auto const calculateAltitude = [&](double distFormStartM) {
    if (distFormStartM <= distanceDataM.front())
      return static_cast<double>(altitudeDataM.front());
    if (distFormStartM >= distanceDataM.back())
      return static_cast<double>(altitudeDataM.back());

    auto const lowerIt = lower_bound(distanceDataM.cbegin(), distanceDataM.cend(), distFormStartM);
    size_t const nextPointIdx = distance(distanceDataM.cbegin(), lowerIt);
    ASSERT_LESS(0, nextPointIdx, ("distFormStartM is greater than 0 but nextPointIdx == 0."));
    size_t const prevPointIdx = nextPointIdx - 1;

    if (my::AlmostEqualAbs(distanceDataM[prevPointIdx], distanceDataM[nextPointIdx], kEpsilon))
      return static_cast<double>(altitudeDataM[prevPointIdx]);

    double const k = (altitudeDataM[nextPointIdx] - altitudeDataM[prevPointIdx]) /
                     (distanceDataM[nextPointIdx] - distanceDataM[prevPointIdx]);
    return static_cast<double>(altitudeDataM[prevPointIdx]) +
           k * (distFormStartM - distanceDataM[prevPointIdx]);
  };

  double const routeLenM = distanceDataM.back();
  uniformAltitudeDataM.resize(resultPointCount);
  double const stepLenM = resultPointCount <= 1 ? 0.0 : routeLenM / (resultPointCount - 1);

  for (size_t i = 0; i < resultPointCount; ++i)
    uniformAltitudeDataM[i] = calculateAltitude(static_cast<double>(i) * stepLenM);

  return true;
}

bool GenerateYAxisChartData(uint32_t height, double minMetersPerPxl,
                            vector<double> const & altitudeDataM, vector<double> & yAxisDataPxl)
{
  if (altitudeDataM.empty())
  {
    yAxisDataPxl.clear();
    return true;
  }

  uint32_t constexpr kHeightIndentPxl = 2;
  uint32_t heightIndentPxl = kHeightIndentPxl;
  if (height <= 2 * kHeightIndentPxl)
  {
    LOG(LERROR, ("Chart height is less or equal than 2 * kHeightIndentPxl (", 2 * kHeightIndentPxl, ")"));
    heightIndentPxl = 0;
  }

  auto const minMaxAltitudeIt = minmax_element(altitudeDataM.begin(), altitudeDataM.end());
  double const minAltM = *minMaxAltitudeIt.first;
  double const maxAltM = *minMaxAltitudeIt.second;
  double const deltaAltM = maxAltM - minAltM;
  uint32_t const drawHeightPxl = height - 2 * heightIndentPxl;
  double const metersPerPxl = max(minMetersPerPxl, deltaAltM / static_cast<double>(drawHeightPxl));
  if (metersPerPxl == 0.0)
  {
    LOG(LERROR, ("metersPerPxl == 0.0"));
    return false;
  }

  double const deltaAltPxl = deltaAltM / metersPerPxl;
  double const freeHeightSpacePxl = drawHeightPxl - deltaAltPxl;
  if (freeHeightSpacePxl < 0 || freeHeightSpacePxl > drawHeightPxl)
  {
    LOG(LERROR, ("Number of pixels free of chart points (", freeHeightSpacePxl,
                 ") is below zero or greater than the number of pixels for the chart (", drawHeightPxl, ")."));
    return false;
  }

  double const maxAltPxl = maxAltM / metersPerPxl;
  yAxisDataPxl.assign(altitudeDataM.cbegin(), altitudeDataM.cend());
  ScaleChartData(yAxisDataPxl, 1.0 / metersPerPxl);
  ReflectChartData(yAxisDataPxl);
  ShiftChartData(yAxisDataPxl, maxAltPxl + heightIndentPxl + freeHeightSpacePxl / 2.0);

  return true;
}

bool GenerateChartByPoints(uint32_t width, uint32_t height, vector<m2::PointD> const & geometry,
                           MapStyle mapStyle, vector<uint8_t> & frameBuffer)
{
  frameBuffer.clear();
  if (width == 0 || height == 0)
    return false;

  agg::rgba8 const kBackgroundColor = agg::rgba8(255, 255, 255, 0);
  agg::rgba8 const kLineColor = GetLineColor(mapStyle);
  agg::rgba8 const kCurveColor = GetCurveColor(mapStyle);
  double constexpr kLineWidthPxl = 2.0;

  using TBlender = BlendAdaptor<agg::rgba8, agg::order_rgba>;
  using TPixelFormat = agg::pixfmt_custom_blend_rgba<TBlender, agg::rendering_buffer>;
  using TBaseRenderer = agg::renderer_base<TPixelFormat>;
  using TPrimitivesRenderer = agg::renderer_primitives<TBaseRenderer>;
  using TSolidRenderer = agg::renderer_scanline_aa_solid<TBaseRenderer>;
  using TPath = agg::poly_container_adaptor<vector<m2::PointD>>;
  using TStroke = agg::conv_stroke<TPath>;

  agg::rendering_buffer renderBuffer;
  TPixelFormat pixelFormat(renderBuffer, agg::comp_op_src_over);
  TBaseRenderer baseRenderer(pixelFormat);

  frameBuffer.assign(width * kAltitudeChartBPP * height, 0);
  renderBuffer.attach(&frameBuffer[0], static_cast<unsigned>(width),
                      static_cast<unsigned>(height), static_cast<int>(width * kAltitudeChartBPP));

  // Background.
  baseRenderer.reset_clipping(true);
  unsigned const op = pixelFormat.comp_op();
  pixelFormat.comp_op(agg::comp_op_src);
  baseRenderer.clear(kBackgroundColor);
  pixelFormat.comp_op(op);

  agg::rasterizer_scanline_aa<> rasterizer;
  rasterizer.clip_box(0, 0, width, height);

  if (geometry.empty())
    return true; /* No chart line to draw. */

  // Polygon under chart line.
  agg::path_storage underChartGeometryPath;
  underChartGeometryPath.move_to(geometry.front().x, static_cast<double>(height));
  for (auto const & p : geometry)
    underChartGeometryPath.line_to(p.x, p.y);
  underChartGeometryPath.line_to(geometry.back().x, static_cast<double>(height));
  underChartGeometryPath.close_polygon();

  agg::conv_curve<agg::path_storage> curve(underChartGeometryPath);
  rasterizer.add_path(curve);
  agg::scanline32_p8 scanline;
  agg::render_scanlines_aa_solid(rasterizer, scanline, baseRenderer, kCurveColor);

  // Chart line.
  TPath path_adaptor(geometry, false);
  TStroke stroke(path_adaptor);
  stroke.width(kLineWidthPxl);
  stroke.line_cap(agg::round_cap);
  stroke.line_join(agg::round_join);

  rasterizer.add_path(stroke);
  agg::render_scanlines_aa_solid(rasterizer, scanline, baseRenderer, kLineColor);
  return true;
}

bool GenerateChart(uint32_t width, uint32_t height, vector<double> const & distanceDataM,
                   feature::TAltitudes const & altitudeDataM, MapStyle mapStyle,
                   vector<uint8_t> & frameBuffer)
{
  if (distanceDataM.size() != altitudeDataM.size())
  {
    LOG(LERROR, ("The route is in inconsistent state. Size of altitudes is", altitudeDataM.size(),
                 ". Number of segment is", distanceDataM.size()));
    return false;
  }

  vector<double> uniformAltitudeDataM;
  if (!NormalizeChartData(distanceDataM, altitudeDataM, width, uniformAltitudeDataM))
    return false;

  vector<double> yAxisDataPxl;
  if (!GenerateYAxisChartData(height, 1.0 /* minMetersPerPxl */, uniformAltitudeDataM, yAxisDataPxl))
    return false;

  size_t const uniformAltitudeDataSize = yAxisDataPxl.size();
  vector<m2::PointD> geometry(uniformAltitudeDataSize);

  if (uniformAltitudeDataSize != 0)
  {
    double const oneSegLenPix =
        static_cast<double>(width) / (uniformAltitudeDataSize == 1 ? 1 : (uniformAltitudeDataSize - 1));
    for (size_t i = 0; i < uniformAltitudeDataSize; ++i)
      geometry[i] = m2::PointD(i * oneSegLenPix, yAxisDataPxl[i]);
  }

  return GenerateChartByPoints(width, height, geometry, mapStyle, frameBuffer);
}
}  // namespace maps
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: nodeimpl.cxx,v $
 *
 *  $Revision: 1.20 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 16:19:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc.,October,2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems,Inc.
 *  901 San Antonio Road,Palo Alto,CA 94303,USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1,as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not,write to the Free Software
 *  Foundation,Inc.,59 Temple Place,Suite 330,Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND,EITHER EXPRESSED OR IMPLIED,INCLUDING,
 *  WITHOUT LIMITATION,WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE,FIT FOR A PARTICULAR PURPOSE,OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems,Inc.
 *
 *  Copyright: 2000 by Sun Microsystems,Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <stdio.h>
#include "nodeimpl.hxx"

#ifndef CONFIGMGR_VALUENODEBEHAVIOR_HXX_
#include "valuenodeimpl.hxx"
#endif
#ifndef CONFIGMGR_GROUPNODEBEHAVIOR_HXX_
#include "groupnodeimpl.hxx"
#endif

#ifndef CONFIGMGR_NODEACCESS_HXX
#include "nodeaccess.hxx"
#endif
#ifndef CONFIGMGR_VALUENODEACCESS_HXX
#include "valuenodeaccess.hxx"
#endif
#ifndef CONFIGMGR_GROUPNODEACCESS_HXX
#include "groupnodeaccess.hxx"
#endif
#ifndef CONFIGMGR_NODEVISITOR_HXX
#include "nodevisitor.hxx"
#endif

#ifndef CONFIGMGR_CONFIGNODEIMPL_HXX_
#include "treeimpl.hxx"
#endif
#ifndef CONFIGMGR_CONFIGCHANGE_HXX_
#include "nodechange.hxx"
#endif
#ifndef CONFIGMGR_CONFIGCHANGEIMPL_HXX_
#include "nodechangeimpl.hxx"
#endif
#ifndef CONFIGMGR_CONFIGCHANGEINFO_HXX_
#include "nodechangeinfo.hxx"
#endif
#ifndef CONFIGMGR_CHANGE_HXX
#include "change.hxx"
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

namespace configmgr
{
    namespace configuration
    {

//-----------------------------------------------------------------------------
// class NodeImpl
//-----------------------------------------------------------------------------

/// provide access to the data of the underlying node
data::NodeAccess NodeImpl::getOriginalNodeAccess(data::Accessor const& _aAccessor) const
{
    return data::NodeAccess(_aAccessor,m_aNodeRef_);
}
//-----------------------------------------------------------------------------

// Specific types of nodes
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// class GroupNodeImpl
//-----------------------------------------------------------------------------

data::GroupNodeAccess GroupNodeImpl::getDataAccess(data::Accessor const& _aAccessor) const
{
    using namespace data;

    NodeAccess aNodeAccess = getOriginalNodeAccess(_aAccessor);
    OSL_ASSERT(GroupNodeAccess::isInstance(aNodeAccess));

    GroupNodeAccess aGroupAccess(aNodeAccess);
    OSL_ASSERT(aGroupAccess.isValid());

    return aGroupAccess;
}
//-----------------------------------------------------------------------------

GroupNodeImpl::GroupNodeImpl(data::GroupNodeAddress const& _aNodeRef)
: NodeImpl(_aNodeRef)
{
}
//-----------------------------------------------------------------------------

bool GroupNodeImpl::areValueDefaultsAvailable(data::Accessor const& _aAccessor) const
{
    data::GroupNodeAccess aGroupAccess = getDataAccess(_aAccessor);

    return aGroupAccess.data().hasDefaultsAvailable();
}
//-----------------------------------------------------------------------------

ValueMemberNode GroupNodeImpl::makeValueMember(data::ValueNodeAccess const& _aNodeAccess)
{
    return ValueMemberNode(_aNodeAccess);
}
//-----------------------------------------------------------------------------

data::ValueNodeAccess GroupNodeImpl::getOriginalValueNode(data::Accessor const& _aAccessor, Name const& _aName) const
{
    OSL_ENSURE( !_aName.isEmpty(), "Cannot get nameless child value");

    using namespace data;

    NodeAccess aChild = this->getDataAccess(_aAccessor).getChildNode(_aName);

    return ValueNodeAccess(aChild);
}

//-----------------------------------------------------------------------------
// class ValueElementNodeImpl
//-----------------------------------------------------------------------------

data::ValueNodeAccess ValueElementNodeImpl::getDataAccess(data::Accessor const& _aAccessor) const
{
    using namespace data;

    NodeAccess aNodeAccess = getOriginalNodeAccess(_aAccessor);
    OSL_ASSERT(ValueNodeAccess::isInstance(aNodeAccess));

    ValueNodeAccess aValueAccess(aNodeAccess);
    OSL_ASSERT(aValueAccess.isValid());

    return aValueAccess;
}
//-----------------------------------------------------------------------------

ValueElementNodeImpl::ValueElementNodeImpl(data::ValueNodeAddress const& _aNodeRef)
: NodeImpl(_aNodeRef)
{
}
//-----------------------------------------------------------------------------

UnoAny  ValueElementNodeImpl::getValue(data::Accessor const& _aAccessor) const
{
    return getDataAccess(_aAccessor).getValue();
}
//-----------------------------------------------------------------------------

UnoType ValueElementNodeImpl::getValueType(data::Accessor const& _aAccessor) const
{
    return getDataAccess(_aAccessor).getValueType();
}
//-----------------------------------------------------------------------------

namespace
{
    struct AbstractNodeCast : data::NodeVisitor
    {
        virtual Result handle( data::ValueNodeAccess const& rNode)
        {
            throw Exception( "INTERNAL ERROR: Node is not a value node. Cast failing." );
            return CONTINUE;
        }
        virtual Result handle( data::GroupNodeAccess const& rNode)
        {
            throw Exception( "INTERNAL ERROR: Node is not a group node. Cast failing." );
            return CONTINUE;
        }
        virtual Result handle( data::SetNodeAccess const& rNode)
        {
            return CONTINUE;
        }
    };

    template <class NodeType>
    class NodeCast : AbstractNodeCast
    {
    public:
        typedef typename NodeType::DataAccess DataNodeType;

        NodeCast(NodeImpl& rOriginalNode, data::Accessor const& _aAccessor)
        : m_pNode(0)
        {
            if (this->visitNode(rOriginalNode.getOriginalNodeAccess(_aAccessor)) == DONE)
                m_pNode = static_cast<NodeType*>(&rOriginalNode);
        }

        NodeType& get() const
        {
            OSL_ENSURE(m_pNode,"INTERNAL ERROR: Node not set after Cast." );
            return *m_pNode;
        }

        operator NodeType& () const { return get(); }
    private:
        virtual Result handle( DataNodeType& ) { return DONE; }

        NodeType* m_pNode;
    };
}
//-----------------------------------------------------------------------------
    }
}
<commit_msg>INTEGRATION: CWS cfg01 (1.19.10.1.4); FILE MERGED 2003/03/13 15:26:19 jb 1.19.10.1.4.1: #108154# Use NodeAccessRef to avoid copying Accessor objects<commit_after>/*************************************************************************
 *
 *  $RCSfile: nodeimpl.cxx,v $
 *
 *  $Revision: 1.21 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-01 13:40:44 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc.,October,2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems,Inc.
 *  901 San Antonio Road,Palo Alto,CA 94303,USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1,as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not,write to the Free Software
 *  Foundation,Inc.,59 Temple Place,Suite 330,Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND,EITHER EXPRESSED OR IMPLIED,INCLUDING,
 *  WITHOUT LIMITATION,WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE,FIT FOR A PARTICULAR PURPOSE,OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems,Inc.
 *
 *  Copyright: 2000 by Sun Microsystems,Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <stdio.h>
#include "nodeimpl.hxx"

#ifndef CONFIGMGR_VALUENODEBEHAVIOR_HXX_
#include "valuenodeimpl.hxx"
#endif
#ifndef CONFIGMGR_GROUPNODEBEHAVIOR_HXX_
#include "groupnodeimpl.hxx"
#endif

#ifndef CONFIGMGR_NODEACCESS_HXX
#include "nodeaccess.hxx"
#endif
#ifndef CONFIGMGR_VALUENODEACCESS_HXX
#include "valuenodeaccess.hxx"
#endif
#ifndef CONFIGMGR_GROUPNODEACCESS_HXX
#include "groupnodeaccess.hxx"
#endif
#ifndef CONFIGMGR_NODEVISITOR_HXX
#include "nodevisitor.hxx"
#endif

#ifndef CONFIGMGR_CONFIGNODEIMPL_HXX_
#include "treeimpl.hxx"
#endif
#ifndef CONFIGMGR_CONFIGCHANGE_HXX_
#include "nodechange.hxx"
#endif
#ifndef CONFIGMGR_CONFIGCHANGEIMPL_HXX_
#include "nodechangeimpl.hxx"
#endif
#ifndef CONFIGMGR_CONFIGCHANGEINFO_HXX_
#include "nodechangeinfo.hxx"
#endif
#ifndef CONFIGMGR_CHANGE_HXX
#include "change.hxx"
#endif

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

namespace configmgr
{
    namespace configuration
    {

//-----------------------------------------------------------------------------
// class NodeImpl
//-----------------------------------------------------------------------------

/// provide access to the data of the underlying node
data::NodeAccessRef NodeImpl::getOriginalNodeAccessRef(data::Accessor const * _pAccessor) const
{
    return data::NodeAccessRef(_pAccessor,m_aNodeRef_);
}
//-----------------------------------------------------------------------------

// Specific types of nodes
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// class GroupNodeImpl
//-----------------------------------------------------------------------------

data::GroupNodeAccess GroupNodeImpl::getDataAccess(data::Accessor const& _aAccessor) const
{
    using namespace data;

    NodeAccessRef aNodeAccess = getOriginalNodeAccessRef(&_aAccessor);
    OSL_ASSERT(GroupNodeAccess::isInstance(aNodeAccess));

    GroupNodeAccess aGroupAccess(aNodeAccess);
    OSL_ASSERT(aGroupAccess.isValid());

    return aGroupAccess;
}
//-----------------------------------------------------------------------------

GroupNodeImpl::GroupNodeImpl(data::GroupNodeAddress const& _aNodeRef)
: NodeImpl(_aNodeRef)
{
}
//-----------------------------------------------------------------------------

bool GroupNodeImpl::areValueDefaultsAvailable(data::Accessor const& _aAccessor) const
{
    data::GroupNodeAccess aGroupAccess = getDataAccess(_aAccessor);

    return aGroupAccess.data().hasDefaultsAvailable();
}
//-----------------------------------------------------------------------------

ValueMemberNode GroupNodeImpl::makeValueMember(data::ValueNodeAccess const& _aNodeAccess)
{
    return ValueMemberNode(_aNodeAccess);
}
//-----------------------------------------------------------------------------

data::ValueNodeAccess GroupNodeImpl::getOriginalValueNode(data::Accessor const& _aAccessor, Name const& _aName) const
{
    OSL_ENSURE( !_aName.isEmpty(), "Cannot get nameless child value");

    using namespace data;

    NodeAccessRef aChild = this->getDataAccess(_aAccessor).getChildNode(_aName);

    return ValueNodeAccess(aChild);
}

//-----------------------------------------------------------------------------
// class ValueElementNodeImpl
//-----------------------------------------------------------------------------

data::ValueNodeAccess ValueElementNodeImpl::getDataAccess(data::Accessor const& _aAccessor) const
{
    using namespace data;

    NodeAccessRef aNodeAccess = getOriginalNodeAccessRef(&_aAccessor);
    OSL_ASSERT(ValueNodeAccess::isInstance(aNodeAccess));

    ValueNodeAccess aValueAccess(aNodeAccess);
    OSL_ASSERT(aValueAccess.isValid());

    return aValueAccess;
}
//-----------------------------------------------------------------------------

ValueElementNodeImpl::ValueElementNodeImpl(data::ValueNodeAddress const& _aNodeRef)
: NodeImpl(_aNodeRef)
{
}
//-----------------------------------------------------------------------------

UnoAny  ValueElementNodeImpl::getValue(data::Accessor const& _aAccessor) const
{
    return getDataAccess(_aAccessor).getValue();
}
//-----------------------------------------------------------------------------

UnoType ValueElementNodeImpl::getValueType(data::Accessor const& _aAccessor) const
{
    return getDataAccess(_aAccessor).getValueType();
}
//-----------------------------------------------------------------------------

namespace
{
    struct AbstractNodeCast : data::NodeVisitor
    {
        virtual Result handle( data::ValueNodeAccess const& rNode)
        {
            throw Exception( "INTERNAL ERROR: Node is not a value node. Cast failing." );
            return CONTINUE;
        }
        virtual Result handle( data::GroupNodeAccess const& rNode)
        {
            throw Exception( "INTERNAL ERROR: Node is not a group node. Cast failing." );
            return CONTINUE;
        }
        virtual Result handle( data::SetNodeAccess const& rNode)
        {
            return CONTINUE;
        }
    };

    template <class NodeType>
    class NodeCast : AbstractNodeCast
    {
    public:
        typedef typename NodeType::DataAccess DataNodeType;

        NodeCast(NodeImpl& rOriginalNode, data::Accessor const& _aAccessor)
        : m_pNode(0)
        {
            if (this->visitNode(rOriginalNode.getOriginalNodeAccessRef(&_aAccessor)) == DONE)
                m_pNode = static_cast<NodeType*>(&rOriginalNode);
        }

        NodeType& get() const
        {
            OSL_ENSURE(m_pNode,"INTERNAL ERROR: Node not set after Cast." );
            return *m_pNode;
        }

        operator NodeType& () const { return get(); }
    private:
        virtual Result handle( DataNodeType& ) { return DONE; }

        NodeType* m_pNode;
    };
}
//-----------------------------------------------------------------------------
    }
}
<|endoftext|>