<commit_before>/*
 * C S O U N D
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef CHORDLINDENMAYER_TO_SOUND_H
#define CHORDLINDENMAYER_TO_SOUND_H

#include "Platform.hpp"
#ifdef SWIG
%module CsoundAC
%include "std_string.i"
%include "std_vector.i"
%{
#include "Silence.hpp"
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
  %}
#else
#include "Silence.hpp"
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric;
#endif

namespace csound
{
  /**
   * This class implements a Lindenmayer system that generates a score
   * by moving a turtle around in various implicit music spaces.
   *
   * The turtle consists of a note (a vector representing a point in score space);
   * a step (a vector representing an increment in score space);
   * an orientation (a vector representing a direction in score space);
   * a modality (a vector of pitch-class sets in chord space);
   * a chord (a vector of pitch-class sets in chord space); a voicing number;
   * and a range (bass and size).
   *
   * The turtle may write either notes, chords, or voicings into the score.
   * When a chord is written, it is voiced by first transposing it to the pitch
   * of the turtle state, and then permuting it octavewise by the voicing number
   * modulo the range; or, it is voice-led from its predecessor.
   * When a voicing is written, that means that all notes in the score beginning
   * at that time, until the next voicing, are conformed to its pitch-class set,
   * or to its pitch-class set and voicing.
   *
   * Domains of operations: reals, octave equivalence, range equivalence.
   *
   * Commands (if ommitted, x defaults to 1; x is a real scalar;
   * for chords, x may also be a real vector x1,..,xn or a jazz-style chord name):
   *

   *
 [    = Push the turtle state onto a stack (start a branch).

   *
 ]    = Pop the turtle state from the stack (return to the branching point).

   *
 Fx   = Move the turtle "forward" x steps along its current orientation.

   *
 Tdox = Apply operation o to turtle note dimension d with operand x.

   *
 Sdox = Apply operation o to turtle step dimension d with operand x.

   *
 Vvox = Apply operation o to turtle chord voice v with operand x.

   *
 Rdex = Rotate the turtle orientation from dimension d to dimension e by angle x.

   *
 MCx  = Set the modality of the turtle to x (e.g. "C Major").
   *
 CCx  = Set the turtle chord to x (e.g. "0,4,7").
   *
 ICx  = Invert the turtle chord by reflecting it around pitch-class x.

   *
 KC   = Apply Neo-Riemannian inversion by exchange to the turtle chord.

   *
 QCx  = Apply Neo-Riemannian contextual transposition by x pitch-classes
   *             (with reference to the turtle's modality) to the turtle chord.

   *
 VC+  = Add a voice (doubling the root) to the turtle chord.

   *
 VC-  = Remove a voice from the turtle chord.

   *
 WN   = Write the turtle note to the score.

   *
 WC   = Write the turtle chord to the score, voiced from there within the range.

   *
 WCN  = Write the turtle chord to the score, transposed to the turtle note and voiced from there
   *             within the range.

   *

   * Dimensions of score space (rotatable):
   *

   *
i = instrument.

   *
t = time.

   *
d = duration.

   *
k = MIDI key number.

   *
v = MIDI velocity number.

   *
p = phase.

   *
x = pan.

   *
y = height.

   *
z = depth.

   *
s = pitch-class set as Mason number (deprecated here).

   *

   * Additional "dimensions" for operations (not rotatable):
   *

   *
V = voicing (octavewise permutation of a chord modulo its range).

   *
B = base of range.

   *
R = size of range.

   *

   * Operations:
   *

   *
 = Assign x to the dimension.

   *
 + Add x to the value of the dimension.

   *
 - Subtract x from the value of the dimension.

   *
 * Multiply the value of the dimension by x.

   *
 / Divide the value of the dimension by x.

   *

   */
  class ChordLindenmayer :
    public ScoreNode
  {
  protected:
    struct Turtle
    {
      Event note;
      Event step;
      Event orientation;
      std::vector<double> modality;
      std::vector<double> chord;
      int voicing;
      double rangeBase;
      double rangeSize;
    };
    int iterationCount;
    double angle;
    std::string axiom;
    Turtle turtle;
    std::map<std::string, std::string> rules;
    std::stack<Turtle> turtleStack;
    clock_t beganAt;
    clock_t endedAt;
    clock_t elapsed;
    virtual void interpret(std::string command, bool render);
    virtual int getDimension (char dimension) const;
    virtual void rewrite();
    virtual ublas::matrix<double> createRotation (int dimension1, int dimension2, double angle) const;
    virtual void updateActual(Event &event);
    virtual void initialize();
  public:
    ChordLindenmayer();
    virtual ~ChordLindenmayer();
    virtual int getIterationCount() const;
    virtual void setIterationCount(int count);
    virtual double getAngle() const;
    virtual void setAngle(double angle);
    virtual std::string getAxiom() const;
    virtual void setAxiom(std::string axiom);
    virtual void addRule(std::string command, std::string replacement);
    virtual std::string getReplacement(std::string command);
    virtual void generate();
    virtual void clear();
  };
}
#endif
<commit_msg>*** empty log message ***<commit_after>/*
 * C S O U N D
 *
 * L I C E N S E
 *
 * This software is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef CHORDLINDENMAYER_TO_SOUND_H
#define CHORDLINDENMAYER_TO_SOUND_H

#include "Platform.hpp"
#ifdef SWIG
%module CsoundAC
%include "std_string.i"
%include "std_vector.i"
%{
#include "Silence.hpp"
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
  %}
#else
#include "Silence.hpp"
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric;
#endif

namespace csound
{
  /**
   * This class implements a Lindenmayer system that generates a score
   * by moving a turtle around in various implicit music spaces.
   *
   * The turtle consists of:
   *

   *
 N, a note, i.e. a vector in score space.

   *
 S, a step, i.e. an increment by which to move N
   *      (also a vector in score space).

   *
 O, an orientation, i.e. a direction to move a note
   *      (also a  vector).

   *
 C, a chord, i.e. a vector of voices in chord space;
   *      if the turtle writes a chord into the score,
   *      the note is duplicated with each of the pitch-classes
   *      in the chord.

   *
 M, a modality used as a reference for neo-Riemannian
   *      operations upon chords (also a vector).

   *
 V, a chord voicing, i.e. the index of the octavewise
   *      permutation of C within a range.

   *
 B, the bass of the range.

   *
 R, the size of the range.

   *

   *
   * In accordance with both mathematical music theory and the practice
   * of composers, operations on elements of music take place in spaces
   * whose geometry changes fluidly depending upon the musical context.
   * A paradigmatic example is transposition, which may apply
   * to individual notes, or to chords, or to larger parts of scores;
   * as an even more indicative example, transposition may apply
   * to pitch under octave equivalence (pitch-classes), to pitch under
   * range equivalence (transposition on a staff), or simply to pitch
   * as a real number.
   *
   * Consequently, the independent parts of an operation in this
   * Lindenmayer system are specified by commands in the format
   * OTEDX, where:
   *

   *
O = the operation proper (e.g. sum or product).

   *
T = the target, or part of the turtle to which the
   *         operation applies, and which has an implicit rank
   *         (e.g. note or chord).

   *
E = its equivalence class (e.g. octave or range).

   *
D = the individual dimension of the operation
   *         (e.g. pitch or time).

   *
X = its operand (which defaults to 1).

   *

   *
   * Of course, some operations apply in all ranks, dimensions, and
   * equivalence classes; other operations, only to one class.
   *
   * The turtle may write either notes, chords, or voicings into the score.
   * When a chord is written, it is voiced by first transposing it to the pitch
   * of the turtle state, and then permuting it octavewise by the voicing number
   * modulo the range; or, it is voice-led from its predecessor.
   * When a voicing is written, that means that all notes in the score beginning
   * at that time, until the next voicing, are conformed to its pitch-class set,
   * or to its pitch-class set and voicing.
   *
   * Commands are as follows (if ommitted, x defaults to 1; x is a real scalar;
   * for chords, v is a real vector x1,..,xn or a jazz-style chord name):
   *

   *
 [    = Push the active turtle onto a stack (start a branch).

   *
 ]    = Pop the active turtle from the stack (return to the branching point).

   *
 Fx   = Move the turtle "forward" x steps along its current orientation:
   *             N := N + (S * O) * x.

   *
 oNdx = Apply algebraic operation o to turtle note dimension d with operand x:
   *             N[d] := N[d] + S[d] o x.

   *
 oSdx = Apply algebraic operation o to turtle step dimension d with operand x:
   *             S[d] := S[d] o x.

   *
 Rdex = Rotate the turtle orientation from dimension d to dimension e by angle x.

   *
 Mx   = Set the modality of the turtle to x (e.g. "C Major").
   *
 oCx  = Set the turtle chord to x (e.g. "0,4,7").
   *
 ICx  = Invert the turtle chord by reflecting it around pitch-class x.

   *
 KC   = Apply Neo-Riemannian inversion by exchange to the turtle chord.

   *
 QCx  = Apply Neo-Riemannian contextual transposition by x pitch-classes
   *             (with reference to the turtle's modality) to the turtle chord.

   *
 VC+  = Add a voice (doubling the root) to the turtle chord.

   *
 VC-  = Remove a voice from the turtle chord.

   *
 WN   = Write the turtle note to the score.

   *
 WC   = Write the turtle chord to the score, voiced from there within the range.

   *
 WCN  = Write the turtle chord to the score, transposed to the turtle note and voiced from there
   *             within the range.

   *

   * Dimensions of notes:
   *

   *
i = instrument.

   *
t = time.

   *
d = duration.

   *
k = MIDI key number.

   *
v = MIDI velocity number.

   *
p = phase.

   *
x = pan.

   *
y = height.

   *
z = depth.

   *
s = pitch-class set as Mason number (deprecated here).

   *

   * Algebraic operations:
   *

   *
= = Assign.

   *
+ = Add.

   *
- = Subtract.

   *
* = Multiply.

   *
/ = Divide.

   *

   */
  class ChordLindenmayer :
    public ScoreNode
  {
  protected:
    struct Turtle
    {
      Event note;
      Event step;
      Event orientation;
      std::vector<double> modality;
      std::vector<double> chord;
      int voicing;
      double rangeBase;
      double rangeSize;
    };
    int iterationCount;
    double angle;
    std::string axiom;
    Turtle turtle;
    std::map<std::string, std::string> rules;
    std::stack<Turtle> turtleStack;
    clock_t beganAt;
    clock_t endedAt;
    clock_t elapsed;
    virtual void interpret(std::string command, bool render);
    virtual int getDimension (char dimension) const;
    virtual void rewrite();
    virtual ublas::matrix<double> createRotation (int dimension1, int dimension2, double angle) const;
    virtual void updateActual(Event &event);
    virtual void initialize();
  public:
    ChordLindenmayer();
    virtual ~ChordLindenmayer();
    virtual int getIterationCount() const;
    virtual void setIterationCount(int count);
    virtual double getAngle() const;
    virtual void setAngle(double angle);
    virtual std::string getAxiom() const;
    virtual void setAxiom(std::string axiom);
    virtual void addRule(std::string command, std::string replacement);
    virtual std::string getReplacement(std::string command);
    virtual void generate();
    virtual void clear();
  };
}
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: edredln.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2004-08-12 12:23:32 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _DOCARY_HXX
#include <docary.hxx>
#endif
#ifndef _SV_WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif
#include "redline.hxx"
#include "doc.hxx"
#include "swundo.hxx"
#include "editsh.hxx"
#include "edimp.hxx"
#include "frmtool.hxx"

USHORT SwEditShell::GetRedlineMode() const
{
    return GetDoc()->GetRedlineMode();
}

void SwEditShell::SetRedlineMode( USHORT eMode )
{
    if( eMode != GetDoc()->GetRedlineMode() )
    {
        SET_CURR_SHELL( this );
        StartAllAction();
        GetDoc()->SetRedlineMode( eMode );
        EndAllAction();
    }
}

BOOL SwEditShell::IsRedlineOn() const
{
    return GetDoc()->IsRedlineOn();
}

USHORT SwEditShell::GetRedlineCount() const
{
    return GetDoc()->GetRedlineTbl().Count();
}

const SwRedline& SwEditShell::GetRedline( USHORT nPos ) const
{
    return *GetDoc()->GetRedlineTbl()[ nPos ];
}

void lcl_InvalidateAll( ViewShell* pSh )
{
    ViewShell *pStop = pSh;
    do
    {
        if ( pSh->GetWin() )
            pSh->GetWin()->Invalidate();
        pSh = (ViewShell*)pSh->GetNext();

    } while ( pSh != pStop );
}

BOOL SwEditShell::AcceptRedline( USHORT nPos )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    BOOL bRet = GetDoc()->AcceptRedline( nPos );
    if( !nPos && !::IsExtraData( GetDoc() ) )
        lcl_InvalidateAll( this );
    EndAllAction();
    return bRet;
}

BOOL SwEditShell::RejectRedline( USHORT nPos )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    BOOL bRet = GetDoc()->RejectRedline( nPos );
    if( !nPos && !::IsExtraData( GetDoc() ) )
        lcl_InvalidateAll( this );
    EndAllAction();
    return bRet;
}

// Kommentar am Redline setzen
BOOL SwEditShell::SetRedlineComment( const String& rS )
{
    BOOL bRet = FALSE;
    FOREACHPAM_START(this)
        bRet = bRet || GetDoc()->SetRedlineComment( *PCURCRSR, rS );
    FOREACHPAM_END()

    return bRet;
}

const SwRedline* SwEditShell::GetCurrRedline() const
{
    return GetDoc()->GetRedline( *GetCrsr()->GetPoint() );
}

void SwEditShell::UpdateRedlineAttr()
{
    if( ( REDLINE_SHOW_INSERT | REDLINE_SHOW_DELETE ) ==
        ( REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() ))
    {
        SET_CURR_SHELL( this );
        StartAllAction();

        GetDoc()->UpdateRedlineAttr();

        EndAllAction();
    }
}

    // suche das Redline zu diesem Data und returne die Pos im Array
    // USHRT_MAX wird returnt, falls nicht vorhanden
USHORT SwEditShell::FindRedlineOfData( const SwRedlineData& rData ) const
{
    const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();

    for( USHORT i = 0, nCnt = rTbl.Count(); i < nCnt; ++i )
        if( &rTbl[ i ]->GetRedlineData() == &rData )
            return i;
    return USHRT_MAX;
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.3.600); FILE MERGED 2005/09/05 13:39:33 rt 1.3.600.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: edredln.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 03:28:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _DOCARY_HXX
#include <docary.hxx>
#endif
#ifndef _SV_WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif
#include "redline.hxx"
#include "doc.hxx"
#include "swundo.hxx"
#include "editsh.hxx"
#include "edimp.hxx"
#include "frmtool.hxx"

USHORT SwEditShell::GetRedlineMode() const
{
    return GetDoc()->GetRedlineMode();
}

void SwEditShell::SetRedlineMode( USHORT eMode )
{
    if( eMode != GetDoc()->GetRedlineMode() )
    {
        SET_CURR_SHELL( this );
        StartAllAction();
        GetDoc()->SetRedlineMode( eMode );
        EndAllAction();
    }
}

BOOL SwEditShell::IsRedlineOn() const
{
    return GetDoc()->IsRedlineOn();
}

USHORT SwEditShell::GetRedlineCount() const
{
    return GetDoc()->GetRedlineTbl().Count();
}

const SwRedline& SwEditShell::GetRedline( USHORT nPos ) const
{
    return *GetDoc()->GetRedlineTbl()[ nPos ];
}

void lcl_InvalidateAll( ViewShell* pSh )
{
    ViewShell *pStop = pSh;
    do
    {
        if ( pSh->GetWin() )
            pSh->GetWin()->Invalidate();
        pSh = (ViewShell*)pSh->GetNext();

    } while ( pSh != pStop );
}

BOOL SwEditShell::AcceptRedline( USHORT nPos )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    BOOL bRet = GetDoc()->AcceptRedline( nPos );
    if( !nPos && !::IsExtraData( GetDoc() ) )
        lcl_InvalidateAll( this );
    EndAllAction();
    return bRet;
}

BOOL SwEditShell::RejectRedline( USHORT nPos )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    BOOL bRet = GetDoc()->RejectRedline( nPos );
    if( !nPos && !::IsExtraData( GetDoc() ) )
        lcl_InvalidateAll( this );
    EndAllAction();
    return bRet;
}

// Kommentar am Redline setzen
BOOL SwEditShell::SetRedlineComment( const String& rS )
{
    BOOL bRet = FALSE;
    FOREACHPAM_START(this)
        bRet = bRet || GetDoc()->SetRedlineComment( *PCURCRSR, rS );
    FOREACHPAM_END()

    return bRet;
}

const SwRedline* SwEditShell::GetCurrRedline() const
{
    return GetDoc()->GetRedline( *GetCrsr()->GetPoint() );
}

void SwEditShell::UpdateRedlineAttr()
{
    if( ( REDLINE_SHOW_INSERT | REDLINE_SHOW_DELETE ) ==
        ( REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() ))
    {
        SET_CURR_SHELL( this );
        StartAllAction();

        GetDoc()->UpdateRedlineAttr();

        EndAllAction();
    }
}

    // suche das Redline zu diesem Data und returne die Pos im Array
    // USHRT_MAX wird returnt, falls nicht vorhanden
USHORT SwEditShell::FindRedlineOfData( const SwRedlineData& rData ) const
{
    const SwRedlineTbl& rTbl = GetDoc()->GetRedlineTbl();

    for( USHORT i = 0, nCnt = rTbl.Count(); i < nCnt; ++i )
        if( &rTbl[ i ]->GetRedlineData() == &rData )
            return i;
    return USHRT_MAX;
}

<|endoftext|>


<commit_before>// Copyright 2012 Intel Corporation
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// - Redistributions 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.
//
// 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 COPYRIGHT HOLDER 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.

#if WAFFLE_ANDROID_MAJOR_VERSION >= 4 && \
	WAFFLE_ANDROID_MINOR_VERSION >= 1
#	include <gui/SurfaceComposerClient.h>
#elif WAFFLE_ANROID_MAJOR_VERSION >= 4 && \
	  WAFFLE_ANDROID_MINOR_VERSION == 0
#	include <surfaceflinger/SurfaceComposerClient.h>
#else
#	error "android >= 4.0 is required"
#endif

#include "droid_surfaceflingerlink.h"

extern "C" {
#include "wcore_util.h"
#include "wcore_error.h"
};

using namespace android;

namespace waffle {

struct droid_surfaceflinger_container {
    sp<SurfaceComposerClient> composer_client;
};

struct droid_ANativeWindow_container {
    // it is important ANativeWindow* is the first element in this structure
    ANativeWindow* native_window;
    sp<SurfaceControl> surface_control;
    sp<ANativeWindow> window;
};

const uint32_t droid_magic_surface_width = 32;
const uint32_t droid_magic_surface_height = 32;
const int32_t  droid_magic_surface_z = 0x7FFFFFFF;

void droid_tear_down_surfaceflinger_link(
    droid_surfaceflinger_container* pSFContainer);

droid_surfaceflinger_container*
droid_setup_surfaceflinger_link()
{
    bool bRVal;
    EGLint iRVal;
    droid_surfaceflinger_container* pSFContainer;

    pSFContainer = reinterpret_cast <droid_surfaceflinger_container*>(
       wcore_malloc( size_t(sizeof(droid_surfaceflinger_container))));

    if (pSFContainer == NULL)
        goto error;

    pSFContainer->composer_client = new SurfaceComposerClient;
    iRVal = pSFContainer->composer_client->initCheck();
    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "android::SurfaceComposerClient->initCheck != NO_ERROR");
        goto error;
    }

    return pSFContainer;
error:
    droid_tear_down_surfaceflinger_link(pSFContainer);
    return NULL;
}

droid_ANativeWindow_container*
droid_setup_surface(
    int width,
    int height,
    droid_surfaceflinger_container* pSFContainer)
{
    bool bRVal;
    EGLint iRVal;

    droid_ANativeWindow_container* pANWContainer;

    pANWContainer = reinterpret_cast <droid_ANativeWindow_container*>(
       wcore_malloc( size_t(sizeof(droid_ANativeWindow_container))));

    if (pANWContainer == NULL)
        goto error;

    pANWContainer->surface_control =
            pSFContainer->composer_client->createSurface(
            String8("Waffle Surface"), 0,
            droid_magic_surface_width, droid_magic_surface_height,
            PIXEL_FORMAT_RGB_888, 0);

    if (pANWContainer->surface_control == NULL) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Unable to get android::SurfaceControl");
        free(static_cast <void*>(pANWContainer));
        goto error;
    }

    bRVal = pANWContainer->surface_control->isValid();
    if (bRVal != true) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Acquired android::SurfaceControl is invalid");
        free(static_cast <void*>(pANWContainer));
        goto error;
    }

    pSFContainer->composer_client->openGlobalTransaction();
    iRVal = pANWContainer->surface_control->setLayer(droid_magic_surface_z);
    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Error in android::SurfaceControl->setLayer");
        free(static_cast <void*>(pANWContainer));
        goto error_closeTransaction;
    }

    pSFContainer->composer_client->closeGlobalTransaction();

    pANWContainer->window = pANWContainer->surface_control->getSurface();

    pSFContainer->composer_client->openGlobalTransaction();
    iRVal = pANWContainer->surface_control->setSize(width, height);
    pSFContainer->composer_client->closeGlobalTransaction();

    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "error in android::SurfaceControl->setSize");
        free(static_cast <void*>(pANWContainer));
        goto error;
    }

    pANWContainer->native_window = pANWContainer->window.get();

    return pANWContainer;

error_closeTransaction:
    pSFContainer->composer_client->closeGlobalTransaction();

error:
    droid_tear_down_surfaceflinger_link(pSFContainer);
    return NULL;
}

bool
droid_show_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    int iRVal;

    pSFContainer->composer_client->openGlobalTransaction();
    iRVal = pANWContainer->surface_control->show();
    pSFContainer->composer_client->closeGlobalTransaction();

    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Error in android::SurfaceControl->show");
        return false;
    }
    return true;
}

void
droid_destroy_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    pSFContainer->composer_client->openGlobalTransaction();
    pANWContainer->surface_control->clear();
    pSFContainer->composer_client->closeGlobalTransaction();
    free(static_cast <void*>(pANWContainer));
}

void
droid_tear_down_surfaceflinger_link(
                waffle::droid_surfaceflinger_container* pSFContainer)
{
    if( pSFContainer == NULL)
        return;

    if (pSFContainer->composer_client != NULL) {
        pSFContainer->composer_client->dispose();
        pSFContainer->composer_client = NULL;
    }

    free(static_cast<void*>(pSFContainer));
}

}; // namespace waffle

extern "C" struct droid_surfaceflinger_container*
droid_init_gl()
{
    return reinterpret_cast<droid_surfaceflinger_container*>(
                waffle::droid_setup_surfaceflinger_link());
}
extern "C" bool
droid_deinit_gl(droid_surfaceflinger_container* pSFContainer)
{
    waffle::droid_tear_down_surfaceflinger_link(
                reinterpret_cast<waffle::droid_surfaceflinger_container*>
                (pSFContainer));
    return true;
}

extern "C" droid_ANativeWindow_container*
droid_create_surface(
    int width,
    int height,
    droid_surfaceflinger_container* pSFContainer)
{
    waffle::droid_ANativeWindow_container* container =
        waffle::droid_setup_surface(
            width, height,
            reinterpret_cast<waffle::droid_surfaceflinger_container*> (pSFContainer));
    return reinterpret_cast<droid_ANativeWindow_container*>(container);
}

extern "C" bool
droid_show_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    return waffle::droid_show_surface(
            reinterpret_cast<waffle::droid_surfaceflinger_container*>
            (pSFContainer),
            reinterpret_cast<waffle::droid_ANativeWindow_container*>
            (pANWContainer));
}

extern "C" void
droid_destroy_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    return waffle::droid_destroy_surface(
            reinterpret_cast<waffle::droid_surfaceflinger_container*>
            (pSFContainer),
            reinterpret_cast<waffle::droid_ANativeWindow_container*>
            (pANWContainer));
}
<commit_msg>android: Fix createSurface compiler error<commit_after>// Copyright 2012 Intel Corporation
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// - Redistributions 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.
//
// 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 COPYRIGHT HOLDER 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.

#if WAFFLE_ANDROID_MAJOR_VERSION >= 4 && \
	WAFFLE_ANDROID_MINOR_VERSION >= 1
#	include <gui/SurfaceComposerClient.h>
#elif WAFFLE_ANROID_MAJOR_VERSION >= 4 && \
	  WAFFLE_ANDROID_MINOR_VERSION == 0
#	include <surfaceflinger/SurfaceComposerClient.h>
#else
#	error "android >= 4.0 is required"
#endif

#include "droid_surfaceflingerlink.h"

extern "C" {
#include "wcore_util.h"
#include "wcore_error.h"
};

using namespace android;

namespace waffle {

struct droid_surfaceflinger_container {
    sp<SurfaceComposerClient> composer_client;
};

struct droid_ANativeWindow_container {
    // it is important ANativeWindow* is the first element in this structure
    ANativeWindow* native_window;
    sp<SurfaceControl> surface_control;
    sp<ANativeWindow> window;
};

const uint32_t droid_magic_surface_width = 32;
const uint32_t droid_magic_surface_height = 32;
const int32_t  droid_magic_surface_z = 0x7FFFFFFF;

void droid_tear_down_surfaceflinger_link(
    droid_surfaceflinger_container* pSFContainer);

droid_surfaceflinger_container*
droid_setup_surfaceflinger_link()
{
    bool bRVal;
    EGLint iRVal;
    droid_surfaceflinger_container* pSFContainer;

    pSFContainer = reinterpret_cast <droid_surfaceflinger_container*>(
       wcore_malloc( size_t(sizeof(droid_surfaceflinger_container))));

    if (pSFContainer == NULL)
        goto error;

    pSFContainer->composer_client = new SurfaceComposerClient;
    iRVal = pSFContainer->composer_client->initCheck();
    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "android::SurfaceComposerClient->initCheck != NO_ERROR");
        goto error;
    }

    return pSFContainer;
error:
    droid_tear_down_surfaceflinger_link(pSFContainer);
    return NULL;
}

droid_ANativeWindow_container*
droid_setup_surface(
    int width,
    int height,
    droid_surfaceflinger_container* pSFContainer)
{
    bool bRVal;
    EGLint iRVal;

    droid_ANativeWindow_container* pANWContainer;

    pANWContainer = reinterpret_cast <droid_ANativeWindow_container*>(
       wcore_malloc( size_t(sizeof(droid_ANativeWindow_container))));

    if (pANWContainer == NULL)
        goto error;

    pANWContainer->surface_control =
            pSFContainer->composer_client->createSurface(
            String8("Waffle Surface"),
            droid_magic_surface_width, droid_magic_surface_height,
            PIXEL_FORMAT_RGB_888, 0);

    if (pANWContainer->surface_control == NULL) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Unable to get android::SurfaceControl");
        free(static_cast <void*>(pANWContainer));
        goto error;
    }

    bRVal = pANWContainer->surface_control->isValid();
    if (bRVal != true) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Acquired android::SurfaceControl is invalid");
        free(static_cast <void*>(pANWContainer));
        goto error;
    }

    pSFContainer->composer_client->openGlobalTransaction();
    iRVal = pANWContainer->surface_control->setLayer(droid_magic_surface_z);
    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Error in android::SurfaceControl->setLayer");
        free(static_cast <void*>(pANWContainer));
        goto error_closeTransaction;
    }

    pSFContainer->composer_client->closeGlobalTransaction();

    pANWContainer->window = pANWContainer->surface_control->getSurface();

    pSFContainer->composer_client->openGlobalTransaction();
    iRVal = pANWContainer->surface_control->setSize(width, height);
    pSFContainer->composer_client->closeGlobalTransaction();

    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "error in android::SurfaceControl->setSize");
        free(static_cast <void*>(pANWContainer));
        goto error;
    }

    pANWContainer->native_window = pANWContainer->window.get();

    return pANWContainer;

error_closeTransaction:
    pSFContainer->composer_client->closeGlobalTransaction();

error:
    droid_tear_down_surfaceflinger_link(pSFContainer);
    return NULL;
}

bool
droid_show_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    int iRVal;

    pSFContainer->composer_client->openGlobalTransaction();
    iRVal = pANWContainer->surface_control->show();
    pSFContainer->composer_client->closeGlobalTransaction();

    if (iRVal != NO_ERROR) {
        wcore_errorf(WAFFLE_ERROR_UNKNOWN,
                     "Error in android::SurfaceControl->show");
        return false;
    }
    return true;
}

void
droid_destroy_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    pSFContainer->composer_client->openGlobalTransaction();
    pANWContainer->surface_control->clear();
    pSFContainer->composer_client->closeGlobalTransaction();
    free(static_cast <void*>(pANWContainer));
}

void
droid_tear_down_surfaceflinger_link(
                waffle::droid_surfaceflinger_container* pSFContainer)
{
    if( pSFContainer == NULL)
        return;

    if (pSFContainer->composer_client != NULL) {
        pSFContainer->composer_client->dispose();
        pSFContainer->composer_client = NULL;
    }

    free(static_cast<void*>(pSFContainer));
}

}; // namespace waffle

extern "C" struct droid_surfaceflinger_container*
droid_init_gl()
{
    return reinterpret_cast<droid_surfaceflinger_container*>(
                waffle::droid_setup_surfaceflinger_link());
}
extern "C" bool
droid_deinit_gl(droid_surfaceflinger_container* pSFContainer)
{
    waffle::droid_tear_down_surfaceflinger_link(
                reinterpret_cast<waffle::droid_surfaceflinger_container*>
                (pSFContainer));
    return true;
}

extern "C" droid_ANativeWindow_container*
droid_create_surface(
    int width,
    int height,
    droid_surfaceflinger_container* pSFContainer)
{
    waffle::droid_ANativeWindow_container* container =
        waffle::droid_setup_surface(
            width, height,
            reinterpret_cast<waffle::droid_surfaceflinger_container*> (pSFContainer));
    return reinterpret_cast<droid_ANativeWindow_container*>(container);
}

extern "C" bool
droid_show_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    return waffle::droid_show_surface(
            reinterpret_cast<waffle::droid_surfaceflinger_container*>
            (pSFContainer),
            reinterpret_cast<waffle::droid_ANativeWindow_container*>
            (pANWContainer));
}

extern "C" void
droid_destroy_surface(
    droid_surfaceflinger_container* pSFContainer,
    droid_ANativeWindow_container* pANWContainer)
{
    return waffle::droid_destroy_surface(
            reinterpret_cast<waffle::droid_surfaceflinger_container*>
            (pSFContainer),
            reinterpret_cast<waffle::droid_ANativeWindow_container*>
            (pANWContainer));
}
<|endoftext|>


<commit_before>#include "image-util.hpp"
#include "include-opencv.hpp"
#include "include-simd.hpp"
#include <fmo/differentiator.hpp>
#include <fmo/processing.hpp>

namespace fmo {
    namespace {
        constexpr uint8_t threshDecrement = 1;
        constexpr uint8_t threshIncrement = 1;
        constexpr uint8_t threshMin = 10;
        constexpr uint8_t threshMax = 254;
        constexpr size_t threshAdjustPeriod = 4;
        constexpr size_t noiseCapacity = 2 * threshAdjustPeriod + 1;

        template <typename T>
        void vectorDecimate(T& vec) {
            auto halfSize = (vec.size() + 1) / 2;
            auto iter1 = begin(vec);
            auto iter2 = iter1 + halfSize;
            auto iterEnd = end(vec);

            while (iter2 != iterEnd) {
                iter1++;
                iter2++;
                if (iter2 == iterEnd) break;
                *iter1 = *iter2;
                iter1++;
                iter2++;
            }

            vec.resize(halfSize);
        }
    }

    Differentiator::Config::Config() : thresh(23), noiseMin(0.003), noiseMax(0.004) {}

    Differentiator::Differentiator(const Config& cfg)
        : mCfg(cfg), mThresh(std::min(std::max(cfg.thresh, threshMin), threshMax)) {
        mNoise.reserve(noiseCapacity);
    }

    struct AddAndThreshJob : public cv::ParallelLoopBody {

#if defined(FMO_HAVE_NEON)
        using batch_t = uint8x16_t;
        using batch3_t = uint8x16x3_t;

        static void impl(const uint8_t* src, const uint8_t* srcEnd, uint8_t* dst, uint8_t thresh) {
            batch_t threshVec = vld1q_dup_u8(&thresh);

            for (; src < srcEnd; src += SRC_BATCH_SIZE, dst += DST_BATCH_SIZE) {
                batch3_t v = vld3q_u8(src);
                batch_t sum = vqaddq_u8(vqaddq_u8(v.val[0], v.val[1]), v.val[2]);
                sum = vcgtq_u8(sum, threshVec);
                vst1q_u8(dst, sum);
            }
        }
#else
        using batch_t = uint8_t;

        static void impl(const uint8_t* src, const uint8_t* srcEnd, uint8_t* dst, uint8_t thresh) {
            int t = int(thresh);
            for (; src < srcEnd; src += SRC_BATCH_SIZE, dst += DST_BATCH_SIZE) {
                *dst = ((src[0] + src[1] + src[2]) > t) ? uint8_t(0xFF) : uint8_t(0);
            }
        }
#endif

        enum : size_t {
            SRC_BATCH_SIZE = sizeof(batch_t) * 3,
            DST_BATCH_SIZE = sizeof(batch_t),
        };

        AddAndThreshJob(const uint8_t* src, uint8_t* dst, uint8_t thresh)
            : mSrc(src), mDst(dst), mThresh(thresh) {}

        virtual void operator()(const cv::Range& pieces) const override {
            size_t firstSrc = size_t(pieces.start) * SRC_BATCH_SIZE;
            size_t lastSrc = size_t(pieces.end) * SRC_BATCH_SIZE;
            size_t firstDst = size_t(pieces.start) * DST_BATCH_SIZE;
            const uint8_t* src = mSrc + firstSrc;
            const uint8_t* srcEnd = mSrc + lastSrc;
            uint8_t* dst = mDst + firstDst;
            impl(src, srcEnd, dst, mThresh);
        }

    private:
        const uint8_t* const mSrc;
        uint8_t* const mDst;
        uint8_t mThresh;
    };

    void addAndThresh(const Image& src, Image& dst, uint8_t thresh) {
        const Format format = src.format();
        const Dims dims = src.dims();
        const size_t pixels = size_t(dims.width) * size_t(dims.height);
        const size_t pieces = pixels / AddAndThreshJob::DST_BATCH_SIZE;

        if (getPixelStep(format) != 3) { throw std::runtime_error("addAndThresh(): bad format"); }

        // run the job in parallel
        dst.resize(Format::GRAY, dims);
        AddAndThreshJob job{src.data(), dst.data(), thresh};
        cv::parallel_for_(cv::Range{0, int(pieces)}, job, cv::getNumThreads());

        // process the last few bytes individually
        size_t lastIndex = pieces * AddAndThreshJob::DST_BATCH_SIZE;
        const uint8_t* data = src.data() + (lastIndex * 3);
        uint8_t* out = dst.data() + lastIndex;
        uint8_t* outEnd = dst.data() + pixels;
        int t = int(thresh);
        for (; out < outEnd; out++, data += 3) {
            *out = ((data[0] + data[1] + data[2]) > t) ? uint8_t(0xFF) : uint8_t(0);
        }
    }

    void Differentiator::operator()(const Mat& src1, const Mat& src2, Image& dst) {
        // calibrate threshold based on measured noise
        if (mNoise.size() >= noiseCapacity) {
            auto median = begin(mNoise) + (mNoise.size() / 2);
            std::nth_element(begin(mNoise), median, end(mNoise));
            int noiseMedian = *median;
            vectorDecimate(mNoise);

            int numPixels = src1.dims().width * src1.dims().height;
            double noiseFrac = double(noiseMedian) / double(numPixels);

            if (noiseFrac > mCfg.noiseMax) {
                mThresh += threshIncrement;
                mThresh = std::min(mThresh, threshMax);
            }

            if (noiseFrac < mCfg.noiseMin) {
                mThresh -= threshDecrement;
                mThresh = std::max(mThresh, threshMin);
            }
        }

        // calculate absolute differences
        absdiff(src1, src2, mAbsDiff);

        // threshold
        switch (mAbsDiff.format()) {
        case Format::GRAY: {
            greater_than(mAbsDiff, dst, mThresh);
            return;
        }
        case Format::BGR:
        case Format::YUV: {
            addAndThresh(mAbsDiff, dst, mThresh);
            return;
        }
        default:
            throw std::runtime_error("Differentiator: unsupported format");
        }
    }

    void Differentiator::reportAmountOfNoise(int noise) { mNoise.push_back(noise); }
}
<commit_msg>Fix differentiator not deterministic<commit_after>#include "image-util.hpp"
#include "include-opencv.hpp"
#include "include-simd.hpp"
#include <fmo/differentiator.hpp>
#include <fmo/processing.hpp>

namespace fmo {
    namespace {
        constexpr uint8_t threshDecrement = 1;
        constexpr uint8_t threshIncrement = 1;
        constexpr uint8_t threshMin = 10;
        constexpr uint8_t threshMax = 254;
        constexpr size_t threshAdjustPeriod = 4;
        constexpr size_t noiseCapacity = 2 * threshAdjustPeriod + 1;

        template <typename T>
        void vectorDecimate(T& vec) {
            auto halfSize = (vec.size() + 1) / 2;
            auto iter1 = begin(vec);
            auto iter2 = iter1 + halfSize;
            auto iterEnd = end(vec);

            while (iter2 != iterEnd) {
                iter1++;
                iter2++;
                if (iter2 == iterEnd) break;
                *iter1 = *iter2;
                iter1++;
                iter2++;
            }

            vec.resize(halfSize);
        }
    }

    Differentiator::Config::Config() : thresh(23), noiseMin(0.003), noiseMax(0.004) {}

    Differentiator::Differentiator(const Config& cfg)
        : mCfg(cfg), mThresh(std::min(std::max(cfg.thresh, threshMin), threshMax)) {
        mNoise.reserve(noiseCapacity);
    }

    struct AddAndThreshJob : public cv::ParallelLoopBody {

#if defined(FMO_HAVE_NEON)
        using batch_t = uint8x16_t;
        using batch3_t = uint8x16x3_t;

        static void impl(const uint8_t* src, const uint8_t* srcEnd, uint8_t* dst, uint8_t thresh) {
            batch_t threshVec = vld1q_dup_u8(&thresh);

            for (; src < srcEnd; src += SRC_BATCH_SIZE, dst += DST_BATCH_SIZE) {
                batch3_t v = vld3q_u8(src);
                batch_t sum = vqaddq_u8(vqaddq_u8(v.val[0], v.val[1]), v.val[2]);
                sum = vcgtq_u8(sum, threshVec);
                vst1q_u8(dst, sum);
            }
        }
#else
        using batch_t = uint8_t;

        static void impl(const uint8_t* src, const uint8_t* srcEnd, uint8_t* dst, uint8_t thresh) {
            int t = int(thresh);
            for (; src < srcEnd; src += SRC_BATCH_SIZE, dst += DST_BATCH_SIZE) {
                *dst = ((src[0] + src[1] + src[2]) > t) ? uint8_t(0xFF) : uint8_t(0);
            }
        }
#endif

        enum : size_t {
            SRC_BATCH_SIZE = sizeof(batch_t) * 3,
            DST_BATCH_SIZE = sizeof(batch_t),
        };

        AddAndThreshJob(const uint8_t* src, uint8_t* dst, uint8_t thresh)
            : mSrc(src), mDst(dst), mThresh(thresh) {}

        virtual void operator()(const cv::Range& pieces) const override {
            size_t firstSrc = size_t(pieces.start) * SRC_BATCH_SIZE;
            size_t lastSrc = size_t(pieces.end) * SRC_BATCH_SIZE;
            size_t firstDst = size_t(pieces.start) * DST_BATCH_SIZE;
            const uint8_t* src = mSrc + firstSrc;
            const uint8_t* srcEnd = mSrc + lastSrc;
            uint8_t* dst = mDst + firstDst;
            impl(src, srcEnd, dst, mThresh);
        }

    private:
        const uint8_t* const mSrc;
        uint8_t* const mDst;
        uint8_t mThresh;
    };

    void addAndThresh(const Image& src, Image& dst, uint8_t thresh) {
        const Format format = src.format();
        const Dims dims = src.dims();
        const size_t pixels = size_t(dims.width) * size_t(dims.height);
        const size_t pieces = pixels / AddAndThreshJob::DST_BATCH_SIZE;

        if (getPixelStep(format) != 3) { throw std::runtime_error("addAndThresh(): bad format"); }

        // run the job in parallel
        dst.resize(Format::GRAY, dims);
        AddAndThreshJob job{src.data(), dst.data(), thresh};
        cv::parallel_for_(cv::Range{0, int(pieces)}, job, cv::getNumThreads());

        // process the last few bytes individually
        size_t lastIndex = pieces * AddAndThreshJob::DST_BATCH_SIZE;
        const uint8_t* data = src.data() + (lastIndex * 3);
        uint8_t* out = dst.data() + lastIndex;
        uint8_t* outEnd = dst.data() + pixels;
        int t = int(thresh);
        for (; out < outEnd; out++, data += 3) {
            *out = ((data[0] + data[1] + data[2]) > t) ? uint8_t(0xFF) : uint8_t(0);
        }
    }

    void Differentiator::operator()(const Mat& src1, const Mat& src2, Image& dst) {
        // calibrate threshold based on measured noise
        if (mNoise.size() >= noiseCapacity) {
            // note: do not use std::nth_element here
            // the result of vectorDecimate() would not be deterministic
            std::sort(begin(mNoise), end(mNoise));
            auto median = begin(mNoise) + (mNoise.size() / 2);
            int noiseMedian = *median;
            vectorDecimate(mNoise);

            int numPixels = src1.dims().width * src1.dims().height;
            double noiseFrac = double(noiseMedian) / double(numPixels);

            if (noiseFrac > mCfg.noiseMax) {
                mThresh += threshIncrement;
                mThresh = std::min(mThresh, threshMax);
            }

            if (noiseFrac < mCfg.noiseMin) {
                mThresh -= threshDecrement;
                mThresh = std::max(mThresh, threshMin);
            }
        }

        // calculate absolute differences
        absdiff(src1, src2, mAbsDiff);

        // threshold
        switch (mAbsDiff.format()) {
        case Format::GRAY: {
            greater_than(mAbsDiff, dst, mThresh);
            return;
        }
        case Format::BGR:
        case Format::YUV: {
            addAndThresh(mAbsDiff, dst, mThresh);
            return;
        }
        default:
            throw std::runtime_error("Differentiator: unsupported format");
        }
    }

    void Differentiator::reportAmountOfNoise(int noise) { mNoise.push_back(noise); }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: swfntcch.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: ama $ $Date: 2001-03-19 15:50:37 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SWFNTCCH_HXX
#define _SWFNTCCH_HXX

#ifndef _SVMEMPOOL_HXX //autogen
#include <tools/mempool.hxx>
#endif

#define NUM_DEFAULT_VALUES 34

#include "swcache.hxx"
#include "swfont.hxx"

class ViewShell;
class SfxPoolItem;

/*************************************************************************
 *                      class SwFontCache
 *************************************************************************/

class SwFontCache : public SwCache
{
public:

    inline SwFontCache() : SwCache(50,50
#ifndef PRODUCT
    , "Globaler AttributSet/Font-Cache pSwFontCache"
#endif
    ) {}

};

// AttributSet/Font-Cache, globale Variable, in FontCache.Cxx angelegt
extern SwFontCache *pSwFontCache;

/*************************************************************************
 *                      class SwFontObj
 *************************************************************************/

class SwFontObj : public SwCacheObj
{
    friend class SwFontAccess;

private:
    SwFont aSwFont;
    const SfxPoolItem* pDefaultArray[ NUM_DEFAULT_VALUES ];

public:
    DECL_FIXEDMEMPOOL_NEWDEL(SwFontObj)

    SwFontObj( const void* pOwner, ViewShell *pSh );

    virtual ~SwFontObj();

    inline       SwFont *GetFont()      { return &aSwFont; }
    inline const SwFont *GetFont() const  { return &aSwFont; }
    inline const SfxPoolItem** GetDefault() { return pDefaultArray; }
};

/*************************************************************************
 *                      class SwFontAccess
 *************************************************************************/

class SwFontAccess : public SwCacheAccess
{
    ViewShell *pShell;
protected:
    virtual SwCacheObj *NewObj( );

public:
    SwFontAccess( const void *pOwner, ViewShell *pSh );
    SwFontObj *Get();
};

#endif
<commit_msg>INTEGRATION: CWS hiddentext (1.4.506); FILE MERGED 2004/01/05 14:30:07 fme 1.4.506.1: #i23660# Feature - Hidden character attribute<commit_after>/*************************************************************************
 *
 *  $RCSfile: swfntcch.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2004-02-26 15:28:39 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SWFNTCCH_HXX
#define _SWFNTCCH_HXX

#ifndef _SVMEMPOOL_HXX //autogen
#include <tools/mempool.hxx>
#endif

#define NUM_DEFAULT_VALUES 35

#include "swcache.hxx"
#include "swfont.hxx"

class ViewShell;
class SfxPoolItem;

/*************************************************************************
 *                      class SwFontCache
 *************************************************************************/

class SwFontCache : public SwCache
{
public:

    inline SwFontCache() : SwCache(50,50
#ifndef PRODUCT
    , "Globaler AttributSet/Font-Cache pSwFontCache"
#endif
    ) {}

};

// AttributSet/Font-Cache, globale Variable, in FontCache.Cxx angelegt
extern SwFontCache *pSwFontCache;

/*************************************************************************
 *                      class SwFontObj
 *************************************************************************/

class SwFontObj : public SwCacheObj
{
    friend class SwFontAccess;

private:
    SwFont aSwFont;
    const SfxPoolItem* pDefaultArray[ NUM_DEFAULT_VALUES ];

public:
    DECL_FIXEDMEMPOOL_NEWDEL(SwFontObj)

    SwFontObj( const void* pOwner, ViewShell *pSh );

    virtual ~SwFontObj();

    inline       SwFont *GetFont()      { return &aSwFont; }
    inline const SwFont *GetFont() const  { return &aSwFont; }
    inline const SfxPoolItem** GetDefault() { return pDefaultArray; }
};

/*************************************************************************
 *                      class SwFontAccess
 *************************************************************************/

class SwFontAccess : public SwCacheAccess
{
    ViewShell *pShell;
protected:
    virtual SwCacheObj *NewObj( );

public:
    SwFontAccess( const void *pOwner, ViewShell *pSh );
    SwFontObj *Get();
};

#endif
<|endoftext|>


<commit_before>#include "Timer.h"

using fei::Timer;

Timer::Timer()
: _interval(0.0),
  _remainTime(0.0)
{
	stop();
	setTickCallback(std::bind(&Timer::timerUpdate, this));
}

void Timer::setInterval(double interval)
{
	_interval = interval;
}

double Timer::getRemainTimePercentage()
{
	return getRemainTime() / getInterval();
}

void Timer::timerUpdate()
{
	setRemainTime(getInterval() - getClock()->getTime());
	if (getRemainTime() < 0.0) {
		stop();
	}
}
<commit_msg>fix a Timer bug<commit_after>#include "Timer.h"

using fei::Timer;

Timer::Timer()
: _interval(0.0),
  _remainTime(0.0)
{
	stop();
	setTickCallback(std::bind(&Timer::timerUpdate, this));
}

void Timer::setInterval(double interval)
{
	_interval = interval;
}

double Timer::getRemainTimePercentage()
{
	return getRemainTime() / getInterval();
}

void Timer::timerUpdate()
{
	setRemainTime(getInterval() - getClock()->getTime());
	if (getRemainTime() < 0.0) {
		setRemainTime(0.0f);
		stop();
	}
}
<|endoftext|>


<commit_before>/*
 * Workaround dummy file to obtain the examples present in the IDE menu File->Examples
 */
<commit_msg>Adding missing license<commit_after>/*
  Copyright (c) 2015 Atmel Corp./Thibaut VIARD. All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*
 * Workaround dummy file to obtain the examples present in the IDE menu File->Examples
 */
<|endoftext|>


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

#include "tgbot/net/HttpParser.h"

#include <boost/algorithm/string.hpp>

#include "tgbot/tools/StringTools.h"

using namespace std;
using namespace boost;

namespace TgBot {

HttpParser& HttpParser::getInstance() {
	static HttpParser result;
	return result;
}

string HttpParser::generateRequest(const Url& url, const vector<HttpReqArg>& args, bool isKeepAlive) {
	string result;
	if (args.empty()) {
		result += "GET ";
	} else {
		result += "POST ";
	}
	result += url.path;
	result += url.query.empty() ? "" : "?" + url.query;
	result += " HTTP/1.1\r\n";
	result += "Host: ";
	result += url.host;
	result += "\r\nConnection: ";
	if (isKeepAlive) {
		result += "keep-alive";
	} else {
		result += "close";
	}
	result += "\r\n";
	if (args.empty()) {
		result += "\r\n";
	} else {
		string requestData;

		string bondary = generateMultipartBoundary(args);
		if (bondary.empty()) {
			result += "Content-Type: application/x-www-form-urlencoded\r\n";
			requestData = generateWwwFormUrlencoded(args);
		} else {
			result += "Content-Type: multipart/form-data; boundary=";
			result += bondary;
			result += "\r\n";
			requestData = generateMultipartFormData(args, bondary);
		}

		result += "Content-Length: ";
		result += lexical_cast<string>(requestData.length());
		result += "\r\n\r\n";
		result += requestData;
	}
	return result;
}

string HttpParser::generateMultipartFormData(const vector<HttpReqArg>& args, const string& bondary) {
	string result;
	for (const HttpReqArg& item : args) {
		result += "--";
		result += bondary;
		result += "\r\nContent-Disposition: form-data; name=\"";
		result += item.name;
		if (item.isFile) {
			result += "\"; filename=\"" + item.fileName;
		}
		result += "\"\r\n";
		if (item.isFile) {
			result += "Content-Type: ";
			result += item.mimeType;
			result += "\r\n";
		}
		result += "\r\n";
		result += item.value;
		result += "\r\n";
	}
	result += "--" + bondary + "--";
	return result;
}

string HttpParser::generateMultipartBoundary(const vector<HttpReqArg>& args) {
	string result;
	srand((unsigned int) time(nullptr));
	for (const HttpReqArg& item : args) {
		if (item.isFile) {
			while (result.empty() || item.value.find(result) != item.value.npos) {
				result += StringTools::generateRandomString(4);
			}
		}
	}
	return result;
}

string HttpParser::generateWwwFormUrlencoded(const vector<HttpReqArg>& args) {
	string result;

	bool firstRun = true;
	for (const HttpReqArg& item : args) {
		if (firstRun) {
			firstRun = false;
		} else {
			result += '&';
		}
		result += StringTools::urlEncode(item.name);
		result += '=';
		result += StringTools::urlEncode(item.value);
	}

	return result;
}

string HttpParser::generateResponse(const string& data, const string& mimeType, unsigned short statusCode, const string& statusStr, bool isKeepAlive) {
	string result;
	result += "HTTP/1.1 ";
	result += lexical_cast<string>(statusCode);
	result += ' ';
	result += statusStr;
	result += "\r\nContent-Type: ";
	result += mimeType;
	result += "\r\nContent-Length: ";
	result += lexical_cast<string>(data.length());
	result += "\r\n\r\n";
	result += data;
	return result;
}

string HttpParser::parseHttp(bool isRequest, const string& data, map<string, string>& headers) {
	bool onlyNewLineChar = false;
	size_t headerEnd = data.find("\r\n\r\n");
	if (headerEnd == data.npos) {
		headerEnd = data.find("\n\n");
		if (headerEnd != data.npos) {
			onlyNewLineChar = true;
			headerEnd += 2;
		}
	} else {
		headerEnd += 4;
	}

	size_t lineStart = 0;
	size_t lineEnd = 0;
	size_t lineSepPos = 0;
	size_t lastLineEnd = data.npos;
	while (lastLineEnd != lineEnd) {
		lastLineEnd = lineEnd;
		if (lineEnd == 0) {
			if (isRequest) {
				lineSepPos = data.find(' ');
				lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
				headers["method"] = data.substr(0, lineSepPos);
				headers["path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
			} else {
				lineSepPos = data.find(' ');
				lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
				headers["status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
			}
		} else {
			lineStart = lineEnd;
			lineStart += onlyNewLineChar ? 1 : 2;
			lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n", lineStart);
			lineSepPos = data.find(':', lineStart);
			if (lineEnd >= headerEnd || lastLineEnd == lineEnd || lineSepPos >= headerEnd) {
				break;
			}
			headers[to_lower_copy(data.substr(lineStart, lineSepPos - lineStart))] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
		}
	}

	return headerEnd == data.npos ? "" : data.substr(headerEnd);
}

string HttpParser::parseHttp(bool isRequest, const string& data) {
	size_t headerEnd = data.find("\r\n\r\n");
	if (headerEnd == data.npos) {
		headerEnd = data.find("\n\n");
	}
	if (headerEnd == data.npos) {
		headerEnd = 0;
	}
	return data.substr(headerEnd);
}

}
<commit_msg>Remove leading \r\n\r\n before actual json string<commit_after>/*
 * Copyright (c) 2015 Oleg Morozenkov
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "tgbot/net/HttpParser.h"

#include <boost/algorithm/string.hpp>

#include "tgbot/tools/StringTools.h"

using namespace std;
using namespace boost;

namespace TgBot {

HttpParser& HttpParser::getInstance() {
	static HttpParser result;
	return result;
}

string HttpParser::generateRequest(const Url& url, const vector<HttpReqArg>& args, bool isKeepAlive) {
	string result;
	if (args.empty()) {
		result += "GET ";
	} else {
		result += "POST ";
	}
	result += url.path;
	result += url.query.empty() ? "" : "?" + url.query;
	result += " HTTP/1.1\r\n";
	result += "Host: ";
	result += url.host;
	result += "\r\nConnection: ";
	if (isKeepAlive) {
		result += "keep-alive";
	} else {
		result += "close";
	}
	result += "\r\n";
	if (args.empty()) {
		result += "\r\n";
	} else {
		string requestData;

		string bondary = generateMultipartBoundary(args);
		if (bondary.empty()) {
			result += "Content-Type: application/x-www-form-urlencoded\r\n";
			requestData = generateWwwFormUrlencoded(args);
		} else {
			result += "Content-Type: multipart/form-data; boundary=";
			result += bondary;
			result += "\r\n";
			requestData = generateMultipartFormData(args, bondary);
		}

		result += "Content-Length: ";
		result += lexical_cast<string>(requestData.length());
		result += "\r\n\r\n";
		result += requestData;
	}
	return result;
}

string HttpParser::generateMultipartFormData(const vector<HttpReqArg>& args, const string& bondary) {
	string result;
	for (const HttpReqArg& item : args) {
		result += "--";
		result += bondary;
		result += "\r\nContent-Disposition: form-data; name=\"";
		result += item.name;
		if (item.isFile) {
			result += "\"; filename=\"" + item.fileName;
		}
		result += "\"\r\n";
		if (item.isFile) {
			result += "Content-Type: ";
			result += item.mimeType;
			result += "\r\n";
		}
		result += "\r\n";
		result += item.value;
		result += "\r\n";
	}
	result += "--" + bondary + "--";
	return result;
}

string HttpParser::generateMultipartBoundary(const vector<HttpReqArg>& args) {
	string result;
	srand((unsigned int) time(nullptr));
	for (const HttpReqArg& item : args) {
		if (item.isFile) {
			while (result.empty() || item.value.find(result) != item.value.npos) {
				result += StringTools::generateRandomString(4);
			}
		}
	}
	return result;
}

string HttpParser::generateWwwFormUrlencoded(const vector<HttpReqArg>& args) {
	string result;

	bool firstRun = true;
	for (const HttpReqArg& item : args) {
		if (firstRun) {
			firstRun = false;
		} else {
			result += '&';
		}
		result += StringTools::urlEncode(item.name);
		result += '=';
		result += StringTools::urlEncode(item.value);
	}

	return result;
}

string HttpParser::generateResponse(const string& data, const string& mimeType, unsigned short statusCode, const string& statusStr, bool isKeepAlive) {
	string result;
	result += "HTTP/1.1 ";
	result += lexical_cast<string>(statusCode);
	result += ' ';
	result += statusStr;
	result += "\r\nContent-Type: ";
	result += mimeType;
	result += "\r\nContent-Length: ";
	result += lexical_cast<string>(data.length());
	result += "\r\n\r\n";
	result += data;
	return result;
}

string HttpParser::parseHttp(bool isRequest, const string& data, map<string, string>& headers) {
	bool onlyNewLineChar = false;
	size_t headerEnd = data.find("\r\n\r\n");
	if (headerEnd == data.npos) {
		headerEnd = data.find("\n\n");
		if (headerEnd != data.npos) {
			onlyNewLineChar = true;
			headerEnd += 2;
		}
	} else {
		headerEnd += 4;
	}

	size_t lineStart = 0;
	size_t lineEnd = 0;
	size_t lineSepPos = 0;
	size_t lastLineEnd = data.npos;
	while (lastLineEnd != lineEnd) {
		lastLineEnd = lineEnd;
		if (lineEnd == 0) {
			if (isRequest) {
				lineSepPos = data.find(' ');
				lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
				headers["method"] = data.substr(0, lineSepPos);
				headers["path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
			} else {
				lineSepPos = data.find(' ');
				lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
				headers["status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
			}
		} else {
			lineStart = lineEnd;
			lineStart += onlyNewLineChar ? 1 : 2;
			lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n", lineStart);
			lineSepPos = data.find(':', lineStart);
			if (lineEnd >= headerEnd || lastLineEnd == lineEnd || lineSepPos >= headerEnd) {
				break;
			}
			headers[to_lower_copy(data.substr(lineStart, lineSepPos - lineStart))] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
		}
	}

	return headerEnd == data.npos ? "" : data.substr(headerEnd);
}

string HttpParser::parseHttp(bool isRequest, const string& data) {
	size_t headerEnd = data.find("\r\n\r\n");
	if (headerEnd != data.npos) {
		headerEnd += 4;
	} else {
		headerEnd = data.find("\n\n");
		if (headerEnd != data.npos) {
			headerEnd += 2;
		} else {
			headerEnd = 0;
		}
	}
	return data.substr(headerEnd);
}

}
<|endoftext|>


<commit_before>
#include "webgetter.h"
#include "net.h"

#include "asio/asio.hpp"

#include <coreutils/utils.h>
#include <coreutils/log.h>
#include <coreutils/file.h>

#include <vector>
#include <functional>
#include <cstdint>
#include <unordered_map>

using asio::ip::tcp;
using namespace std;
using namespace utils;

namespace net {

struct HttpSession::State {

	int chunkSize = 1024;
	int total;
	bool oneShot = false;
	std::string url;
	std::string host;
	std::string path;
	int port;
	std::function<void(const asio::error_code &e, size_t n)> handler;
	Callback callback;
	//std::vector<uint8_t> buffer;
	//std::shared_ptr<utils::File> file;
	Connection c;
	asio::streambuf data;
	std::unordered_map<std::string, std::string> header;
	int code;
	int headerSize;
	int cntSize;
	enum { NONE, CONNECT, HEADERS, DONE, EMPTY } state = NONE;

};

HttpSession::HttpSession(const string &url) : impl(make_shared<State>()) {

	int hostStart = 0;
	impl->port = 80;

	impl->url = url;

	LOGD("URL:%s", url);

	auto parts = split(url, "://");

	if(parts.size() == 2) {

	}

	if(startsWith(url, "http://"))
		hostStart = 7;

	int firstSlash = url.find_first_of('/', hostStart);
	impl->host = url.substr(hostStart, firstSlash - hostStart);
	impl->path = url.substr(firstSlash);
	int lastColon = impl->host.find_last_of(':');
	if(lastColon != string::npos) {
		impl->port = stol(impl->host.substr(lastColon+1));
		impl->host = impl->host.substr(0, lastColon);
	}

	LOGD("CONNECT %s %d", impl->host, impl->port);
	impl->c.connect(impl->host, impl->port);
	sendRequest(impl->path, impl->host);
}

HttpSession::HttpSession(HttpSession &&h) : impl(std::move(h.impl)) {
}

HttpSession& HttpSession::operator=(HttpSession &&h) {
	impl = std::move(h.impl);
	return *this;
}

void HttpSession::sendRequest(const string &path, const string &host) {
	string req = utils::format("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", urlencode(path, ":\\?;+ "), host);
	LOGD("REQ %p:\n%s", this, req);
	LOGD("%d", impl->data.size());
	impl->c.write(req);
	impl->state = State::CONNECT;
	asio::async_read_until(impl->c.getSocket(), impl->data, "\r\n\r\n", [=](const asio::error_code &e, size_t n) {
		//LOGD("Read %d bytes", n);
		parseHeader();
		impl->state = State::HEADERS;
		//if(impl->code == 200)
		readContent();
		//else
		//	impl->state = State::ERROR;
	});
}

void HttpSession::parseHeader() {
	istream is(&impl->data);
	string line;
	getline(is, line);
	auto rc = split(line, " ");
	impl->code = stol(rc[1]);
	LOGD(">>%s", line);
	while(!is.eof()) {
		getline(is, line);
		if(line == "" || line == "\r")
			break;
		LOGD("%s", line);
		auto parts = split(line, ": ", 2);
		if(parts.size() == 2) {
			parts[1] = rstrip(rstrip(parts[1], '\n'), '\r');
			impl->header[parts[0]] = parts[1];
		}
	}
	auto cl = impl->header["Content-Length"];
	impl->cntSize = cl != "" ? stol(impl->header["Content-Length"]) : 0;
	if(isRedirect()) {
		LOGD("Should redirect to '%s'", impl->header["Location"]);
		//sleepms(500);
	}
}

int HttpSession::contentSize() const { return impl->cntSize; }

void HttpSession::stream(const Callback &cb) {
	impl->callback = cb;
}

void HttpSession::getData(const Callback &cb) {
	impl->oneShot = true;
	impl->callback = cb;
}

HttpSession::Callback HttpSession::getCallback() const {
	return impl->callback;
}

bool HttpSession::isRedirect() const { return impl->code == 303 || impl->code == 302 || impl->code == 307; }

int HttpSession::returnCode() const { return impl->code; }

int HttpSession::getPort() const { return impl->port; }
string HttpSession::getHost() const { return impl->host; }

bool HttpSession::gotHeaders() const { return impl->state == State::HEADERS || impl->state == State::DONE || impl->state == State::EMPTY; }
bool HttpSession::done() const { return impl->state == State::DONE || impl->state == State::EMPTY; }

std::string HttpSession::getUrl() const { return impl->url; }

void HttpSession::stop() { impl->state = State::DONE; }

void HttpSession::readContent() {
	int size = impl->cntSize - impl->data.in_avail();
	if(size <= 0) {
		LOGD("EMPTY");
		impl->state = State::EMPTY;
		if(!isRedirect()) {
			vector<uint8_t> v;
			impl->callback(*this, v);
		}
		return;
	}

	if(!impl->callback || impl->oneShot) {
		LOGD("ALL AT ONCE");
		asio::async_read(impl->c.getSocket(), impl->data, asio::transfer_exactly(size), [&](const asio::error_code &e, size_t n) {
			impl->state = State::DONE;
			if(impl->oneShot) {
				auto v8 = getContent();
				impl->callback(*this, v8);
			}
		});
		return;
	}

	//filled = data.in_avail();
	impl->total = 0;
	//buffer.reserve(chunkSize);

	impl->handler = [=](const asio::error_code &e, size_t n) {
		impl->data.commit(n);
		//LOGD("Read %d bytes, avail %d", n, impl->data.size());
		//n += filled;
		vector<uint8_t> buffer(impl->data.size());
		auto bufs = impl->data.data();
		copy(asio::buffers_begin(bufs), asio::buffers_end(bufs), buffer.begin());
		impl->total += impl->data.size();
		//LOGD("Total %d", impl->total);

		if(n == 0 || impl->total == impl->cntSize) {
			impl->state = State::DONE;
			LOGD("Done reading");
		}

		impl->callback(*this, buffer);

		if(impl->state == State::DONE) {
			LOGD("Request stop");
			return;
		}

		impl->data.consume(impl->data.size());
		auto mutableBuffer = impl->data.prepare(16384);
		impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
	};

	auto mutableBuffer = impl->data.prepare(16384);
	impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
}

vector<uint8_t> HttpSession::getContent() {
	auto sz = contentSize();
	vector<uint8_t> v8(sz);
	istream is(&impl->data);
	is.read((char*)&v8[0], sz);
	return v8;
}

string HttpSession::getHeader(const string &what) const {
	return impl->header[what];
}

void WebGetter::update() {

	lock_guard<mutex>{m};

	Connection::run();
	auto it = sessions.begin();
	while(it != sessions.end()) {
		auto s = *it;
		if(s->gotHeaders() && s->isRedirect()) {
			auto location = s->getHeader("Location");
			if(!startsWith(location, "http://")) {
				location = format("http://%s:%d%s", s->getHost(), s->getPort(), urlencode(location, ":\\?;+ "));
			}
			LOGD("Redirecting to '%s'", location);
			auto callback = s->getCallback();
			it = sessions.erase(it);
			sessions.emplace_back(make_shared<HttpSession>(location));
			sessions.back()->stream(callback);
			it = sessions.end();
			continue;
		}
		if(s->done()) {
			it = sessions.erase(it);
			LOGD("Session done");
		} else
			it++;
	}
}

WebGetter::WebGetter(const string &cacheDir) : cacheDir(cacheDir) {
	sessions.reserve(4);
	quit = false;
	workerThread = thread([&]() {
		while(!quit) {
			sleepms(50);
			update();
		}
	});
}

void WebGetter::getFile(const string &url, function<void(const File&)> callback) {

	string u = url;
	auto target = make_shared<File>(cacheDir + "/" + urlencode(url, ":/\\?;"));
	if(target->exists() && target->getSize() > 0) {
		callback(*target);
		return;
	}
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) {
		target->write(v);
		if(session.done()) {
			auto finalUrl = session.getUrl();
			target->close();
			if(session.returnCode() != 200) {
				target->remove();
				callback(File::NO_FILE);
			} else
			if(finalUrl != url) {
				auto finalTarget = make_shared<File>(cacheDir + "/" + urlencode(finalUrl, ":/\\?;"));
				std::rename(target->getName().c_str(), finalTarget->getName().c_str());
				symlink(finalTarget->getName().c_str(), target->getName().c_str());
				callback(*finalTarget);
			} else
				callback(*target);
		}

	});
}

WebGetter::~WebGetter() {
	quit = true;
	workerThread.join();
}

void WebGetter::streamData(const string &url, function<bool(const uint8_t *data, int size)> callback) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	bool sizeReported = false;
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) mutable {
		if(!sizeReported) {
			sizeReported = true;
			LOGD("SIZE:%d", session.contentSize());
			if(!callback(nullptr, session.contentSize())) {
				session.stop();
				return;
			}
		}
		if(!callback(&v[0], v.size()))
			session.stop();
		else
		if(session.done())
			callback(nullptr, 0);
	});
}

int WebGetter::inProgress() { return 0; }

bool WebGetter::inCache(const std::string &url) const {
	auto target = File(cacheDir + "/" + urlencode(url, ":/\\?;"));
	return target.exists();
}

void WebGetter::getData(const std::string &url, std::function<void(const std::vector<uint8_t> &data)> cb) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->getData([=](HttpSession &session, const vector<uint8_t> &v) {
		cb(v);
	});

}

}
<commit_msg>Handle small web gets<commit_after>
#include "webgetter.h"
#include "net.h"

#include "asio/asio.hpp"

#include <coreutils/utils.h>
#include <coreutils/log.h>
#include <coreutils/file.h>

#include <vector>
#include <functional>
#include <cstdint>
#include <unordered_map>

using asio::ip::tcp;
using namespace std;
using namespace utils;

namespace net {

struct HttpSession::State {

	int chunkSize = 1024;
	int total;
	bool oneShot = false;
	std::string url;
	std::string host;
	std::string path;
	int port;
	std::function<void(const asio::error_code &e, size_t n)> handler;
	Callback callback;
	//std::vector<uint8_t> buffer;
	//std::shared_ptr<utils::File> file;
	Connection c;
	asio::streambuf data;
	std::unordered_map<std::string, std::string> header;
	int code;
	int headerSize;
	int cntSize;
	enum { NONE, CONNECT, HEADERS, DONE, EMPTY } state = NONE;

};

HttpSession::HttpSession(const string &url) : impl(make_shared<State>()) {

	int hostStart = 0;
	impl->port = 80;

	impl->url = url;

	LOGD("URL:%s", url);

	auto parts = split(url, "://");

	if(parts.size() == 2) {

	}

	if(startsWith(url, "http://"))
		hostStart = 7;

	int firstSlash = url.find_first_of('/', hostStart);
	impl->host = url.substr(hostStart, firstSlash - hostStart);
	impl->path = url.substr(firstSlash);
	int lastColon = impl->host.find_last_of(':');
	if(lastColon != string::npos) {
		impl->port = stol(impl->host.substr(lastColon+1));
		impl->host = impl->host.substr(0, lastColon);
	}

	LOGD("CONNECT %s %d", impl->host, impl->port);
	impl->c.connect(impl->host, impl->port);
	sendRequest(impl->path, impl->host);
}

HttpSession::HttpSession(HttpSession &&h) : impl(std::move(h.impl)) {
}

HttpSession& HttpSession::operator=(HttpSession &&h) {
	impl = std::move(h.impl);
	return *this;
}

void HttpSession::sendRequest(const string &path, const string &host) {
	string req = utils::format("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", urlencode(path, ":\\?;+ "), host);
	LOGD("REQ %p:\n%s", this, req);
	LOGD("%d", impl->data.size());
	impl->c.write(req);
	impl->state = State::CONNECT;
	asio::async_read_until(impl->c.getSocket(), impl->data, "\r\n\r\n", [=](const asio::error_code &e, size_t n) {
		//LOGD("Read %d bytes", n);
		parseHeader();
		impl->state = State::HEADERS;
		//if(impl->code == 200)
		readContent();
		//else
		//	impl->state = State::ERROR;
	});
}

void HttpSession::parseHeader() {
	istream is(&impl->data);
	string line;
	getline(is, line);
	auto rc = split(line, " ");
	impl->code = stol(rc[1]);
	LOGD(">>%s", line);
	while(!is.eof()) {
		getline(is, line);
		if(line == "" || line == "\r")
			break;
		LOGD("%s", line);
		auto parts = split(line, ": ", 2);
		if(parts.size() == 2) {
			parts[1] = rstrip(rstrip(parts[1], '\n'), '\r');
			impl->header[parts[0]] = parts[1];
		}
	}
	auto cl = impl->header["Content-Length"];
	impl->cntSize = cl != "" ? stol(impl->header["Content-Length"]) : 0;
	if(isRedirect()) {
		LOGD("Should redirect to '%s'", impl->header["Location"]);
		//sleepms(500);
	}
}

int HttpSession::contentSize() const { return impl->cntSize; }

void HttpSession::stream(const Callback &cb) {
	impl->callback = cb;
}

void HttpSession::getData(const Callback &cb) {
	impl->oneShot = true;
	impl->callback = cb;
}

HttpSession::Callback HttpSession::getCallback() const {
	return impl->callback;
}

bool HttpSession::isRedirect() const { return impl->code == 303 || impl->code == 302 || impl->code == 307; }

int HttpSession::returnCode() const { return impl->code; }

int HttpSession::getPort() const { return impl->port; }
string HttpSession::getHost() const { return impl->host; }

bool HttpSession::gotHeaders() const { return impl->state == State::HEADERS || impl->state == State::DONE || impl->state == State::EMPTY; }
bool HttpSession::done() const { return impl->state == State::DONE || impl->state == State::EMPTY; }

std::string HttpSession::getUrl() const { return impl->url; }

void HttpSession::stop() { impl->state = State::DONE; }

void HttpSession::readContent() {
	int size = impl->cntSize - impl->data.in_avail();
	if(size <= 0) {

		if(impl->data.in_avail() > 0) {
			LOGD("ALL IN BUFFER");
			vector<uint8_t> buffer(impl->data.size());
			auto bufs = impl->data.data();
			copy(asio::buffers_begin(bufs), asio::buffers_end(bufs), buffer.begin());
			impl->total = impl->data.size();
			impl->state = State::DONE;
			impl->callback(*this, buffer);
		} else {
			LOGD("EMPTY");
			impl->state = State::EMPTY;
			if(!isRedirect()) {
				vector<uint8_t> v;
				impl->callback(*this, v);
			}
		}
		return;
	}

	if(!impl->callback || impl->oneShot) {
		LOGD("ALL AT ONCE");
		asio::async_read(impl->c.getSocket(), impl->data, asio::transfer_exactly(size), [&](const asio::error_code &e, size_t n) {
			impl->state = State::DONE;
			if(impl->oneShot) {
				auto v8 = getContent();
				impl->callback(*this, v8);
			}
		});
		return;
	}

	//filled = data.in_avail();
	impl->total = 0;
	//buffer.reserve(chunkSize);

	impl->handler = [=](const asio::error_code &e, size_t n) {
		impl->data.commit(n);
		//LOGD("Read %d bytes, avail %d", n, impl->data.size());
		//n += filled;
		vector<uint8_t> buffer(impl->data.size());
		auto bufs = impl->data.data();
		copy(asio::buffers_begin(bufs), asio::buffers_end(bufs), buffer.begin());
		impl->total += impl->data.size();
		//LOGD("Total %d", impl->total);

		if(n == 0 || impl->total == impl->cntSize) {
			impl->state = State::DONE;
			LOGD("Done reading");
		}

		impl->callback(*this, buffer);

		if(impl->state == State::DONE) {
			LOGD("Request stop");
			return;
		}

		impl->data.consume(impl->data.size());
		auto mutableBuffer = impl->data.prepare(16384);
		impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
	};

	auto mutableBuffer = impl->data.prepare(16384);
	impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
}

vector<uint8_t> HttpSession::getContent() {
	auto sz = contentSize();
	vector<uint8_t> v8(sz);
	istream is(&impl->data);
	is.read((char*)&v8[0], sz);
	return v8;
}

string HttpSession::getHeader(const string &what) const {
	return impl->header[what];
}

void WebGetter::update() {

	lock_guard<mutex>{m};

	Connection::run();
	auto it = sessions.begin();
	while(it != sessions.end()) {
		auto s = *it;
		if(s->gotHeaders() && s->isRedirect()) {
			auto location = s->getHeader("Location");
			if(!startsWith(location, "http://")) {
				location = format("http://%s:%d%s", s->getHost(), s->getPort(), urlencode(location, ":\\?;+ "));
			}
			LOGD("Redirecting to '%s'", location);
			auto callback = s->getCallback();
			it = sessions.erase(it);
			sessions.emplace_back(make_shared<HttpSession>(location));
			sessions.back()->stream(callback);
			it = sessions.end();
			continue;
		}
		if(s->done()) {
			it = sessions.erase(it);
			LOGD("Session done");
		} else
			it++;
	}
}

WebGetter::WebGetter(const string &cacheDir) : cacheDir(cacheDir) {
	sessions.reserve(4);
	quit = false;
	workerThread = thread([&]() {
		while(!quit) {
			sleepms(50);
			update();
		}
	});
}

void WebGetter::getFile(const string &url, function<void(const File&)> callback) {

	string u = url;
	auto target = make_shared<File>(cacheDir + "/" + urlencode(url, ":/\\?;"));
	if(target->exists() && target->getSize() > 0) {
		callback(*target);
		return;
	}
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) {
		target->write(v);
		if(session.done()) {
			auto finalUrl = session.getUrl();
			target->close();
			if(session.returnCode() != 200) {
				target->remove();
				callback(File::NO_FILE);
			} else
			if(finalUrl != url) {
				auto finalTarget = make_shared<File>(cacheDir + "/" + urlencode(finalUrl, ":/\\?;"));
				std::rename(target->getName().c_str(), finalTarget->getName().c_str());
				symlink(finalTarget->getName().c_str(), target->getName().c_str());
				callback(*finalTarget);
			} else
				callback(*target);
		}

	});
}

WebGetter::~WebGetter() {
	quit = true;
	workerThread.join();
}

void WebGetter::streamData(const string &url, function<bool(const uint8_t *data, int size)> callback) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	bool sizeReported = false;
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) mutable {
		if(!sizeReported) {
			sizeReported = true;
			LOGD("SIZE:%d", session.contentSize());
			if(!callback(nullptr, session.contentSize())) {
				session.stop();
				return;
			}
		}
		if(!callback(&v[0], v.size()))
			session.stop();
		else
		if(session.done())
			callback(nullptr, 0);
	});
}

int WebGetter::inProgress() { return 0; }

bool WebGetter::inCache(const std::string &url) const {
	auto target = File(cacheDir + "/" + urlencode(url, ":/\\?;"));
	return target.exists();
}

void WebGetter::getData(const std::string &url, std::function<void(const std::vector<uint8_t> &data)> cb) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->getData([=](HttpSession &session, const vector<uint8_t> &v) {
		cb(v);
	});

}

}
<|endoftext|>


<commit_before>// Copyright (c) 2022 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// 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
// COPYRIGHT HOLDER 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.
#include "errors.hh"
#include "scanner.hh"

namespace loxpp {

Scanner::Scanner(ErrorReporter& error_repoter, const str_t& source_bytes, const str_t& filename) noexcept
  : error_repoter_(error_repoter)
  , source_bytes_(source_bytes)
  , filename_(filename) {
}

std::vector<Token>& Scanner::scan_tokens() noexcept {
  while (!is_at_end()) {
    // TODO:

    start_pos_ = current_pos_;
    scan_token();
  }

  tokens_.push_back(Token::make_from_details(TokenType::TK_EOF, "", lineno_));
  return tokens_;
}

void Scanner::scan_token() noexcept {
  char c = advance();
  switch (c) {
  case '(': add_token(TokenType::TK_LPAREN); break;
  case ')': add_token(TokenType::TK_RPAREN); break;
  case '{': add_token(TokenType::TK_LBRACE); break;
  case '}': add_token(TokenType::TK_RBRACE); break;
  case ',': add_token(TokenType::TK_COMMA); break;
  case '.': add_token(TokenType::TK_DOT); break;
  case '-': add_token(TokenType::TK_MINUS); break;
  case '+': add_token(TokenType::TK_PLUS); break;
  case ';': add_token(TokenType::TK_SEMI); break;
  case '*': add_token(TokenType::TK_STAR); break;
  case '!': add_token(match('=') ? TokenType::TK_NE : TokenType::TK_NOT); break;
  case '=': add_token(match('=') ? TokenType::TK_EQEQ : TokenType::TK_EQ); break;
  case '<': add_token(match('=') ? TokenType::TK_LE : TokenType::TK_LT); break;
  case '>': add_token(match('=') ? TokenType::TK_GE : TokenType::TK_GT); break;
  default:
    error_repoter_.error("", lineno_, "Unexpected character.");
    break;
  }
}

}
<commit_msg>:construction: chore(scanner): updated the scanner module<commit_after>// Copyright (c) 2022 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// 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
// COPYRIGHT HOLDER 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.
#include "errors.hh"
#include "scanner.hh"

namespace loxpp {

Scanner::Scanner(ErrorReporter& error_repoter, const str_t& source_bytes, const str_t& filename) noexcept
  : error_repoter_(error_repoter)
  , source_bytes_(source_bytes)
  , filename_(filename) {
}

std::vector<Token>& Scanner::scan_tokens() noexcept {
  while (!is_at_end()) {
    // TODO:

    start_pos_ = current_pos_;
    scan_token();
  }

  tokens_.push_back(Token::make_from_details(TokenType::TK_EOF, "", lineno_));
  return tokens_;
}

void Scanner::scan_token() noexcept {
  char c = advance();
  switch (c) {
  case '(': add_token(TokenType::TK_LPAREN); break;
  case ')': add_token(TokenType::TK_RPAREN); break;
  case '{': add_token(TokenType::TK_LBRACE); break;
  case '}': add_token(TokenType::TK_RBRACE); break;
  case ',': add_token(TokenType::TK_COMMA); break;
  case '.': add_token(TokenType::TK_DOT); break;
  case '-': add_token(TokenType::TK_MINUS); break;
  case '+': add_token(TokenType::TK_PLUS); break;
  case ';': add_token(TokenType::TK_SEMI); break;
  case '*': add_token(TokenType::TK_STAR); break;
  case '!': add_token(match('=') ? TokenType::TK_NE : TokenType::TK_NOT); break;
  case '=': add_token(match('=') ? TokenType::TK_EQEQ : TokenType::TK_EQ); break;
  case '<': add_token(match('=') ? TokenType::TK_LE : TokenType::TK_LT); break;
  case '>': add_token(match('=') ? TokenType::TK_GE : TokenType::TK_GT); break;
  case '/':
    if (match('/')) {
      // a comment goes until the end of the line.
      while (!is_at_end() && peek() != '\n')
        advance();
    }
    else {
      add_token(TokenType::TK_SLASH);
    }
    break;
  default:
    error_repoter_.error("", lineno_, "Unexpected character.");
    break;
  }
}

}
<|endoftext|>


<commit_before>
#include "MainWidget1.h"
#include <QApplication>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>

#include "stbtest.h"

namespace fs = std::filesystem;

//export DISPLAY=localhost:10.0

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    MainWidget1 w;
    w.show();
    std::cout << fs::current_path().c_str() << std::endl;
    return app.exec();
}
<commit_msg>linux cpp qt5 fix win remove stbtest.h<commit_after>
#include "MainWidget1.h"
#include <QApplication>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>

// #include "stbtest.h"

namespace fs = std::filesystem;

//export DISPLAY=localhost:10.0

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    MainWidget1 w;
    w.show();
    std::cout << fs::current_path().c_str() << std::endl;
    return app.exec();
}
<|endoftext|>


<commit_before><commit_msg>:sparkles: feat(nonblock-server): add nonblocking boring server<commit_after><|endoftext|>