<commit_before>#include <iostream>
#include <cmath>
#include <list>
#include <fstream>
#include <vector>
#include "gnuplot_i.hpp"

#define GNUPLOT_PATH "C:/gnuplot/bin"
#define M_PI 3.1415926

using namespace std;

double start, stop;
double h;
double (*funk)(double);
double (*funkCZ)(double);
bool metodaNewt = true;

double czebyszew(int n){
    double sum = 0;
    for(int k=1; k<=n;k++){
        sum += funkCZ(cos((2*k-1)/(2.0*n)*M_PI));
    }
    sum *= M_PI/n;

    return sum;
}

double simpson(double x1, double x2){ //Nie dziala
    double result;
    double I_Ti = h*(funk(x1)+funk(x2))/2;
    double I_Pi = h*funk(x1);
    result = (2.0/3.0)*I_Pi+(1.0/3.0)*I_Ti;
    cout << "Simpson " << result << endl;
    return result;
}

double newton(){

    double integral = 0;
    double d =start;
    double buf = start;
    while(d<stop){
        double buf = d;
        d+=h;
        if(d>stop) break;
        integral+=simpson(buf,d);
    }

    integral+=simpson(buf,stop);
    return integral;
}

void wypiszWektor(vector<double> w){
    for(int i=0; i< w.size(); i++){
        cout << w[i] << " ";
    }

    cout << endl;
}

void wypiszWektor(vector<double> w, string opis){
    cout << "\n" << opis << ": ";
    wypiszWektor(w);
}

double sinus(double x){
    return sin(x);
}

double power(double base, double exp){
    return pow(base, exp);
}

double horner(double wsp[],int st, double x)
{
  if(st==0){
    return wsp[0];}
  return x*horner(wsp,st-1,x)+wsp[st];
}

double wielomianprosty(double a, double b, double c, double d, double x){
    return a*x*x*x -b*x*x +c*x -d;
}

double *wspolczynniki;
int stopien;

double waga(double x){
    return sqrt(1-x*x);
}

void wybierzFunk(){
    cout << "Wybierz funkcje: \n1. Sinus\n2. Wykladnicza\n3. Wielomian \n4. Wielomian przykladowy \n> ";
    int wybor;

    cin >> wybor;

    switch(wybor){
    case 1:
        funk=sinus;
        break;
    case 2:
        funk=[](double x) -> double {return power(2,x);};
        break;
    case 3:
        cout<<"Podaj stopien wielomianu: ";
        cin>>stopien;
        wspolczynniki = new double [stopien+1];
        //wczytanie wspolczynnikow
        for(int i=0;i<=stopien;i++)
        {
          cout<<"Podaj wspolczynnik stojacy przy potedze "<<stopien-i<<": ";
          cin>>wspolczynniki[i];
        }
        funk=[](double x) -> double {return horner(wspolczynniki,stopien,x);};
        break;
    case 4:
        funk=[](double x) -> double {return wielomianprosty(2,3,2,1.05,x);};
        break;
    default:
        throw string("Function not found");
    }
}

int main()
{
    Gnuplot::set_GNUPlotPath( GNUPLOT_PATH );

    {
        cout << "Wybierz metode: \n1. Newtona-Cotesa\n2. Gaussa-Czebyszewa\n> ";
        int wybor;

        cin >> wybor;
        if (wybor == 2) metodaNewt = false;
        else if (wybor != 1)
        {
            cout << "Method not found\n";
            return 0;
        }
    }

    try{
        wybierzFunk();
    } catch (string s){
        cout << s << endl;
        return 0;
    }

    if (metodaNewt)
    {
        cout << "Podaj poczatek i koniec przedzialu: ";
        cin >> start >> stop;

        Gnuplot main_plot;

        main_plot.set_title( "Wykres" );
        main_plot.set_xlabel( "X" );
        main_plot.set_ylabel( "Y" );

        main_plot.set_grid();
        main_plot.set_xrange( start , stop ) ;
        main_plot.set_yrange(-2,2);
        main_plot.set_style( "lines" );
        int precyzja = 10000;
        double skok = (stop-start)/precyzja;
        vector<double> x;
        vector<double> y;
        for(double d=start; d<=stop;d+=skok){
            x.push_back(d);
            y.push_back(funk(d));
        }

        main_plot.plot_xy( x, y, "Wykres funkcji." );

        cout << "Podaj dokladnosc calkowania: ";
        cin >> h;

        cout << newton() << endl;

        getchar();
        getchar();
    }
    else
    {
        funkCZ = [](double x) -> double {return funk(x)*waga(x);};
        for(int i=2; i<=10; i++)
            cout << "Liczba wezlow: " << i <<"; wynik: " << czebyszew(i) << endl;
    }
    return 0;
}

<commit_msg>Prawidłowe sprawdzanie dokładności dla kwadratury Newtona-Cotesa.<commit_after>#include <iostream>
#include <cmath>
#include <list>
#include <fstream>
#include <vector>
#include "gnuplot_i.hpp"

#define GNUPLOT_PATH "C:/gnuplot/bin"
#define M_PI 3.1415926

using namespace std;

double start, stop;
double dokladnosc;
double h;
double (*funk)(double);
double (*funkCZ)(double);
bool metodaNewt = true;

double czebyszew(int n){
    double sum = 0;
    for(int k=1; k<=n;k++){
        sum += funkCZ(cos((2*k-1)/(2.0*n)*M_PI));
    }
    sum *= M_PI/n;

    return sum;
}

double simpson(double x1, double x2){ //Nie dziala
    double result;
    double I_Ti = h*(funk(x1)+funk(x2))/2;
    double I_Pi = h*funk(x1);
    result = (2.0/3.0)*I_Pi+(1.0/3.0)*I_Ti;
    //cout << "Simpson " << result << endl;
    return result;
}

double newton(){

    double integral = 0;
    double d =start;
    double buf = start;
    while(d<stop){
        double buf = d;
        d+=h;
        if(d>stop) break;
        integral+=simpson(buf,d);
    }

    integral+=simpson(buf,stop);
    return integral;
}

void wypiszWektor(vector<double> w){
    for(int i=0; i< w.size(); i++){
        cout << w[i] << " ";
    }

    cout << endl;
}

void wypiszWektor(vector<double> w, string opis){
    cout << "\n" << opis << ": ";
    wypiszWektor(w);
}

double sinus(double x){
    return sin(x);
}

double power(double base, double exp){
    return pow(base, exp);
}

double horner(double wsp[],int st, double x)
{
  if(st==0){
    return wsp[0];}
  return x*horner(wsp,st-1,x)+wsp[st];
}

double wielomianprosty(double a, double b, double c, double d, double x){
    return a*x*x*x -b*x*x +c*x -d;
}

double *wspolczynniki;
int stopien;

double waga(double x){
    return sqrt(1-x*x);
}

void wybierzFunk(){
    cout << "Wybierz funkcje: \n1. Sinus\n2. Wykladnicza\n3. Wielomian \n4. Wielomian przykladowy \n> ";
    int wybor;

    cin >> wybor;

    switch(wybor){
    case 1:
        funk=sinus;
        break;
    case 2:
        funk=[](double x) -> double {return power(2,x);};
        break;
    case 3:
        cout<<"Podaj stopien wielomianu: ";
        cin>>stopien;
        wspolczynniki = new double [stopien+1];
        //wczytanie wspolczynnikow
        for(int i=0;i<=stopien;i++)
        {
          cout<<"Podaj wspolczynnik stojacy przy potedze "<<stopien-i<<": ";
          cin>>wspolczynniki[i];
        }
        funk=[](double x) -> double {return horner(wspolczynniki,stopien,x);};
        break;
    case 4:
        funk=[](double x) -> double {return wielomianprosty(2,3,2,1.05,x);};
        break;
    default:
        throw string("Function not found");
    }
}

int main()
{
    Gnuplot::set_GNUPlotPath( GNUPLOT_PATH );

    {
        cout << "Wybierz metode: \n1. Newtona-Cotesa\n2. Gaussa-Czebyszewa\n> ";
        int wybor;

        cin >> wybor;
        if (wybor == 2) metodaNewt = false;
        else if (wybor != 1)
        {
            cout << "Method not found\n";
            return 0;
        }
    }

    try{
        wybierzFunk();
    } catch (string s){
        cout << s << endl;
        return 0;
    }

    if (metodaNewt)
    {
        cout << "Podaj poczatek i koniec przedzialu: ";
        cin >> start >> stop;

        Gnuplot main_plot;

        main_plot.set_title( "Wykres" );
        main_plot.set_xlabel( "X" );
        main_plot.set_ylabel( "Y" );

        main_plot.set_grid();
        main_plot.set_xrange( start , stop ) ;
        main_plot.set_yrange(-2,2);
        main_plot.set_style( "lines" );
        int precyzja = 10000;
        double skok = (stop-start)/precyzja;
        vector<double> x;
        vector<double> y;
        for(double d=start; d<=stop;d+=skok){
            x.push_back(d);
            y.push_back(funk(d));
        }

        main_plot.plot_xy( x, y, "Wykres funkcji." );

        cout << "Podaj dokladnosc calkowania: ";
        cin >> dokladnosc;

        h=abs(start-stop)/20.0;

        double prev, now;
        prev = newton();
        int j = 0;
        while(true){
            j++;
            h/=2;
            now = newton();
            if(abs(now-prev) < dokladnosc){
                cout << "WYNIK: " << newton() << " [" << j << " iteracja]\n";
                break;
            }
            else
                prev = now;
        }

        getchar();
        getchar();
    }
    else
    {
        funkCZ = [](double x) -> double {return funk(x)*waga(x);};
        for(int i=2; i<=10; i++)
            cout << "Liczba wezlow: " << i <<"; WYNIK: " << czebyszew(i) << endl;
    }
    return 0;
}

<|endoftext|>


<commit_before><commit_msg>more special tratment of scan values<commit_after><|endoftext|>


<commit_before>#ifndef GAMELIB_QPHYSICS_HPP
#define GAMELIB_QPHYSICS_HPP

#include "math/geometry/AABB.hpp"
#include "gamelib/core/ecs/UpdateComponent.hpp"

namespace gamelib
{
    class CollisionComponent;
    class Collidable;
    class TraceResult;

    // Provides properties for global settings (gravity, friction, etc)
    class QConfig : public Identifier<0xbfae3ffa, Component>
    {
        public:
            constexpr static const char* name = "QConfig";

        public:
            QConfig();
    };

    class QPhysics : public UpdateComponent
    {
        public:
            constexpr static const char* name = "QPhysicsComponent";

            enum State
            {
                Air,
                Ground,
                Stuck
            };

            struct GroundData;

        public:
            QPhysics(int interval = 1);
            QPhysics(const math::AABBf* box, int interval = 1);
            virtual ~QPhysics() {};

            virtual auto update(float elapsed) -> void;

            // Accelerate by a given amount of units/sec in a certain direction
            // Expects wishdir to be a normalized vector.
            // Accelerates in a 1 / accel second to the desired speed.
            auto accelerate(const math::Vec2f& wishdir, float wishspeed, float accel) -> void;

            auto moveToContact(const math::Vec2f& dist)    -> CollisionComponent*;
            auto moveIfContact(const math::Vec2f& dist)    -> CollisionComponent*;
            auto clipmove(math::Vec2f* vel, float elapsed) -> void;
            auto clipmove(math::Vec2f* vel)                -> void; // TODO
            auto nudge()                                   -> bool;

            auto isStuck(const math::AABBf& box) const -> bool;
            auto isStuck() const   -> bool;
            auto getHull() const   -> const math::AABBf*;
            auto getState() const  -> State;
            auto getGround() const -> const GroundData&;

            auto categorizePosition() -> void;
            auto setGround(CollisionComponent* ground, const math::Vec2f& normal) -> void;

        protected:
            virtual auto _refresh() -> void;

            auto _nudge(math::AABBf* box)       -> bool;
            auto _move(const math::Vec2f& dist) -> void;
            auto _snapToMovingGround()          -> void;

        public:
            static float gravity;
            static math::Vec2f gravityDirection;
            static float friction;
            static float stopFriction;
            static float stopSpeed;

        public:
            math::Vec2f vel;
            math::Vec2f basevel;
            float overbounce;
            float gravMultiplier;
            float fricMultiplier;
            float maxSlope;
            int movingPlatformSnapDist;
            bool keepMomentum;
            bool airFriction;
            // TODO: flags treated as solid

        protected:
            const math::AABBf* _bbox;
            Collidable* _self;
            State _state;

            struct GroundData {
                CollisionComponent* hull;
                math::Vec2f normal;
                float slope;
            } _ground;
    };

}

#endif
<commit_msg>Fix redeclaring struct with different visibility<commit_after>#ifndef GAMELIB_QPHYSICS_HPP
#define GAMELIB_QPHYSICS_HPP

#include "math/geometry/AABB.hpp"
#include "gamelib/core/ecs/UpdateComponent.hpp"

namespace gamelib
{
    class CollisionComponent;
    class Collidable;
    class TraceResult;

    // Provides properties for global settings (gravity, friction, etc)
    class QConfig : public Identifier<0xbfae3ffa, Component>
    {
        public:
            constexpr static const char* name = "QConfig";

        public:
            QConfig();
    };

    class QPhysics : public UpdateComponent
    {
        public:
            constexpr static const char* name = "QPhysicsComponent";

            enum State
            {
                Air,
                Ground,
                Stuck
            };

            struct GroundData
            {
                CollisionComponent* hull;
                math::Vec2f normal;
                float slope;
            };

        public:
            QPhysics(int interval = 1);
            QPhysics(const math::AABBf* box, int interval = 1);
            virtual ~QPhysics() {};

            virtual auto update(float elapsed) -> void;

            // Accelerate by a given amount of units/sec in a certain direction
            // Expects wishdir to be a normalized vector.
            // Accelerates in a 1 / accel second to the desired speed.
            auto accelerate(const math::Vec2f& wishdir, float wishspeed, float accel) -> void;

            auto moveToContact(const math::Vec2f& dist)    -> CollisionComponent*;
            auto moveIfContact(const math::Vec2f& dist)    -> CollisionComponent*;
            auto clipmove(math::Vec2f* vel, float elapsed) -> void;
            auto clipmove(math::Vec2f* vel)                -> void; // TODO
            auto nudge()                                   -> bool;

            auto isStuck(const math::AABBf& box) const -> bool;
            auto isStuck() const   -> bool;
            auto getHull() const   -> const math::AABBf*;
            auto getState() const  -> State;
            auto getGround() const -> const GroundData&;

            auto categorizePosition() -> void;
            auto setGround(CollisionComponent* ground, const math::Vec2f& normal) -> void;

        protected:
            virtual auto _refresh() -> void;

            auto _nudge(math::AABBf* box)       -> bool;
            auto _move(const math::Vec2f& dist) -> void;
            auto _snapToMovingGround()          -> void;

        public:
            static float gravity;
            static math::Vec2f gravityDirection;
            static float friction;
            static float stopFriction;
            static float stopSpeed;

        public:
            math::Vec2f vel;
            math::Vec2f basevel;
            float overbounce;
            float gravMultiplier;
            float fricMultiplier;
            float maxSlope;
            int movingPlatformSnapDist;
            bool keepMomentum;
            bool airFriction;
            // TODO: flags treated as solid

        protected:
            const math::AABBf* _bbox;
            Collidable* _self;
            State _state;
            GroundData _ground;
    };

}

#endif
<|endoftext|>


<commit_before>#pragma once

#include <chrono>
#include <sstream>

namespace std
{

namespace chrono
{

using days = duration<int, ratio_multiply<hours::period, ratio<24>>::type>;

using years = duration<int, ratio_multiply<days::period, ratio<365>>::type>;

using months = duration<int, ratio_divide<years::period, ratio<12>>::type>;

inline constexpr tuple<years,months,days> split(const days& ds) noexcept
{
    static_assert(std::numeric_limits<unsigned>::digits >= 18,
             "This algorithm has not been ported to a 16 bit unsigned integer");
    static_assert(std::numeric_limits<int>::digits >= 20,
             "This algorithm has not been ported to a 16 bit signed integer");
    auto const z = ds.count() + 719468;
    auto const era = (z >= 0 ? z : z - 146096) / 146097;
    auto const doe = static_cast<unsigned>(z - era * 146097);          // [0, 146096]
    auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;  // [0, 399]
    auto const y = static_cast<int>(yoe) + era * 400;
    auto const doy = doe - (365*yoe + yoe/4 - yoe/100);                // [0, 365]
    auto const mp = (5*doy + 2)/153;                                   // [0, 11]
    auto const d = doy - (153*mp+2)/5 + 1;                             // [1, 31]
    auto const m = mp + (mp < 10 ? 3 : -9u);                           // [1, 12]
    return make_tuple(years{y + (m <= 2)}, months{m}, days{d});
}

} // namespace chrono

std::string to_string(chrono::system_clock::time_point tp)
{
	using namespace chrono;

    auto dd = duration_cast<days>(tp.time_since_epoch());
    years YY;
    months MM;
    days DD;
    std::tie(YY,MM,DD) = split(dd);
    tp -= dd;
    auto hh = duration_cast<hours>(tp.time_since_epoch());
    tp -= hh;
    auto mm = duration_cast<minutes>(tp.time_since_epoch());
    tp -= mm;
    auto ss = duration_cast<seconds>(tp.time_since_epoch());
    tp -= ss;
    auto ff = duration_cast<milliseconds>(tp.time_since_epoch());

	std::ostringstream os;
    os << YY.count()
       << '-' << std::setw(2) << std::setfill('0')
       << MM.count()
       << '-' << std::setw(2) << std::setfill('0')
       << DD.count()
	   << 'T'
       << hh.count()
       << ':' << std::setw(2) << std::setfill('0')
       << mm.count()
       << ':' << std::setw(2) << std::setfill('0')
       << ss.count()
       << '.' << std::setw(3) << std::setfill('0')
       << ff.count();

	return os.str();
}

inline std::string to_string(bool b)
{
	std::stringstream ss;
	ss << std::boolalpha << b;
	return ss.str();
}

inline std::string to_string(std::nullptr_t n)
{
	return "null";
}

} // namespace std
<commit_msg>Minor fix<commit_after>#pragma once

#include <chrono>
#include <sstream>

namespace std
{

namespace chrono
{

using days = duration<int, ratio_multiply<hours::period, ratio<24>>::type>;

using years = duration<int, ratio_multiply<days::period, ratio<365>>::type>;

using months = duration<int, ratio_divide<years::period, ratio<12>>::type>;

inline constexpr tuple<years,months,days> split(const days& ds) noexcept
{
    static_assert(std::numeric_limits<unsigned>::digits >= 18,
             "This algorithm has not been ported to a 16 bit unsigned integer");
    static_assert(std::numeric_limits<int>::digits >= 20,
             "This algorithm has not been ported to a 16 bit signed integer");
    auto const z = ds.count() + 719468;
    auto const era = (z >= 0 ? z : z - 146096) / 146097;
    auto const doe = static_cast<unsigned>(z - era * 146097);          // [0, 146096]
    auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;  // [0, 399]
    auto const y = static_cast<int>(yoe) + era * 400;
    auto const doy = doe - (365*yoe + yoe/4 - yoe/100);                // [0, 365]
    auto const mp = (5*doy + 2)/153;                                   // [0, 11]
    auto const d = doy - (153*mp+2)/5 + 1;                             // [1, 31]
    auto const m = mp + (mp < 10 ? 3 : -9u);                           // [1, 12]
    return make_tuple(years{y + (m <= 2)}, months{m}, days{d});
}

} // namespace chrono

std::string to_string(chrono::system_clock::time_point tp)
{
	using namespace chrono;

    auto dd = duration_cast<days>(tp.time_since_epoch());
    years YY;
    months MM;
    days DD;
    tie(YY,MM,DD) = split(dd);
    tp -= dd;
    auto hh = duration_cast<hours>(tp.time_since_epoch());
    tp -= hh;
    auto mm = duration_cast<minutes>(tp.time_since_epoch());
    tp -= mm;
    auto ss = duration_cast<seconds>(tp.time_since_epoch());
    tp -= ss;
    auto ff = duration_cast<milliseconds>(tp.time_since_epoch());

	std::ostringstream os;
    os << YY.count()
       << '-' << std::setw(2) << std::setfill('0')
       << MM.count()
       << '-' << std::setw(2) << std::setfill('0')
       << DD.count()
	   << 'T'
       << hh.count()
       << ':' << std::setw(2) << std::setfill('0')
       << mm.count()
       << ':' << std::setw(2) << std::setfill('0')
       << ss.count()
       << '.' << std::setw(3) << std::setfill('0')
       << ff.count();

    return os.str();
}

inline std::string to_string(bool b)
{
	std::stringstream ss;
	ss << std::boolalpha << b;
	return ss.str();
}

inline std::string to_string(std::nullptr_t n)
{
	return "null";
}

} // namespace std
<|endoftext|>


<commit_before>#include <gst/gst.h>
#include "MediaPipeline.hpp"
#include <WebRtcEndpointImplFactory.hpp>
#include "WebRtcEndpointImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <boost/filesystem.hpp>
#include <IceCandidate.hpp>
#include <webrtcendpoint/kmsicecandidate.h>
#include <IceComponentState.hpp>
#include <SignalHandler.hpp>

#define GST_CAT_DEFAULT kurento_web_rtc_endpoint_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoWebRtcEndpointImpl"

#define FACTORY_NAME "webrtcendpoint"

namespace kurento
{

static const std::string CERTTOOL_TEMPLATE = "autoCerttool.tmpl";
static const std::string CERT_KEY_PEM_FILE = "autoCertkey.pem";

static const uint DEFAULT_STUN_PORT = 3478;

static std::shared_ptr<std::string> pemCertificate;
std::mutex WebRtcEndpointImpl::certificateMutex;

class TemporalDirectory
{

public:
  ~TemporalDirectory()
  {
    if (!dir.string ().empty() ) {
      boost::filesystem::remove_all (dir);
    }
  }

  void setDir (boost::filesystem::path &dir)
  {
    this->dir = dir;
  }
private:
  boost::filesystem::path dir;
};

static TemporalDirectory tmpDir;

static void
create_pem_certificate ()
{
  int ret;
  boost::filesystem::path temporalDirectory = boost::filesystem::unique_path (
        boost::filesystem::temp_directory_path() / "WebRtcEndpoint_%%%%%%%%" );
  boost::filesystem::create_directories (temporalDirectory);
  tmpDir.setDir (temporalDirectory);

  boost::filesystem::path pemFile = temporalDirectory / CERT_KEY_PEM_FILE;
  std::string pemGenerationCommand =
    "/bin/sh -c \"certtool --generate-privkey --outfile " + pemFile .string()  +
    "\"";

  ret = system (pemGenerationCommand.c_str() );

  if (ret == -1) {
    return;
  }

  boost::filesystem::path templateFile = temporalDirectory / CERTTOOL_TEMPLATE;
  std::string certtoolCommand = "/bin/sh -c \"echo 'organization = kurento' > " +
                                templateFile.string() + " && certtool --generate-self-signed --load-privkey " +
                                pemFile.string() + " --template " + templateFile.string() +  " >> " +
                                pemFile.string() + " 2>/dev/null\"";

  ret = system (certtoolCommand.c_str() );

  if (ret == -1) {
    return;
  }

  pemCertificate = std::shared_ptr <std::string> (new std::string (
                     pemFile.string() ) );
}

std::shared_ptr<std::string>
WebRtcEndpointImpl::getPemCertificate ()
{
  std::unique_lock<std::mutex> lock (certificateMutex);

  if (pemCertificate) {
    return pemCertificate;
  }

  try {
    boost::filesystem::path pem_certificate_file_name (
      getConfigValue<std::string, WebRtcEndpoint> ("pemCertificate") );

    if (pem_certificate_file_name.is_relative() ) {
      pem_certificate_file_name = boost::filesystem::path (
                                    config.get<std::string> ("configPath") ) / pem_certificate_file_name;
    }

    pemCertificate = std::shared_ptr <std::string> (new std::string (
                       pem_certificate_file_name.string() ) );

    return pemCertificate;
  } catch (boost::property_tree::ptree_error &e) {

  }

  create_pem_certificate();

  return pemCertificate;
}

static const std::string supported_codecs[] = {"VP8", "OPUS", "PCMU"};
static const int n_codecs = sizeof (supported_codecs) / sizeof (std::string);

static void
remove_not_supported_codecs_from_pattern (GstElement *element)
{

  GstSDPMessage *old_pattern = NULL, *pattern;
  guint medias_len, i;

  g_object_get (element, "pattern-sdp", &old_pattern, NULL);

  if (old_pattern == NULL) {
    return;
  }

  if (gst_sdp_message_copy (old_pattern, &pattern) != GST_SDP_OK) {
    goto end;
  }

  medias_len = gst_sdp_message_medias_len (pattern);

  for (i = 0; i < medias_len; i ++) {
    const GstSDPMedia *media = gst_sdp_message_get_media (pattern, i);
    guint attributes_len, j, formats_len;

    attributes_len = gst_sdp_media_attributes_len (media);
    std::list <std::string> to_remove_formats;

    for (j = 0; j < attributes_len; j++) {
      const GstSDPAttribute *attribute = gst_sdp_media_get_attribute (media, j);

      if (g_ascii_strcasecmp ("rtpmap", attribute->key) == 0) {
        gchar *rtpmap = g_strstr_len (attribute->value, -1, " ");
        bool supported = false;

        if (rtpmap != NULL) {
          rtpmap = rtpmap + 1;

          for (int k = 0; k < n_codecs; k++) {
            if (g_strstr_len (rtpmap, -1, supported_codecs[k].c_str() ) == rtpmap) {
              supported = true;
              break;
            }
          }
        }

        if (!supported) {
          GST_INFO ("Removing not supported codec from pattern: '%s'", attribute->value);

          * (rtpmap - 1) = '\0';
          to_remove_formats.push_back (std::string (attribute->value) );

          gst_sdp_media_remove_attribute ( (GstSDPMedia *) media, j);
          attributes_len --;
          j--;
        }
      }
    }

    formats_len = gst_sdp_media_formats_len (media);

    for (j = 0; j < formats_len; j++) {
      bool to_remove = false;

      for (std::string format : to_remove_formats) {
        if (format == std::string (gst_sdp_media_get_format (media, j) ) ) {
          to_remove = true;
          break;
        }
      }

      if (to_remove) {
        gst_sdp_media_remove_format ( (GstSDPMedia *) media, j);
        formats_len --;
        j--;
      }
    }
  }

  g_object_set (element, "pattern-sdp", pattern, NULL);

  gst_sdp_message_free (pattern);

end:
  gst_sdp_message_free (old_pattern);
}

void WebRtcEndpointImpl::onIceCandidate (KmsIceCandidate *candidate)
{
  try {
    std::string cand_str (kms_ice_candidate_get_candidate (candidate) );
    std::string mid_str (kms_ice_candidate_get_sdp_mid (candidate) );
    int sdp_m_line_index = kms_ice_candidate_get_sdp_m_line_index (candidate);
    std::shared_ptr <IceCandidate> cand ( new  IceCandidate
                                          (cand_str, mid_str, sdp_m_line_index) );
    OnIceCandidate event (shared_from_this(), OnIceCandidate::getName(), cand);

    signalOnIceCandidate (event);
  } catch (std::bad_weak_ptr &e) {
  }
}

void WebRtcEndpointImpl::onIceGatheringDone ()
{
  try {
    OnIceGatheringDone event (shared_from_this(), OnIceGatheringDone::getName() );

    signalOnIceGatheringDone (event);
  } catch (std::bad_weak_ptr &e) {
  }
}

void WebRtcEndpointImpl::onIceComponentStateChanged (guint streamId,
    guint componentId, guint state)
{
  try {
    IceComponentState::type type;

    switch (state) {
    case NICE_COMPONENT_STATE_DISCONNECTED:
      type = IceComponentState::DISCONNECTED;
      break;

    case NICE_COMPONENT_STATE_GATHERING:
      type = IceComponentState::GATHERING;
      break;

    case NICE_COMPONENT_STATE_CONNECTING:
      type = IceComponentState::CONNECTING;
      break;

    case NICE_COMPONENT_STATE_CONNECTED:
      type = IceComponentState::CONNECTED;
      break;

    case NICE_COMPONENT_STATE_READY:
      type = IceComponentState::READY;
      break;

    case NICE_COMPONENT_STATE_FAILED:
      type = IceComponentState::FAILED;
      break;

    default:
      type = IceComponentState::FAILED;
      break;
    }

    IceComponentState *componentState = new IceComponentState (type);
    OnIceComponentStateChanged event (shared_from_this(),
                                      OnIceComponentStateChanged::getName(),
                                      streamId, componentId,  std::shared_ptr<IceComponentState> (componentState) );

    signalOnIceComponentStateChanged (event);
  } catch (std::bad_weak_ptr &e) {
  }
}

void WebRtcEndpointImpl::postConstructor ()
{
  BaseRtpEndpointImpl::postConstructor ();

  handlerOnIceCandidate = register_signal_handler (G_OBJECT (element),
                          "on-ice-candidate",
                          std::function <void (GstElement *, KmsIceCandidate *) >
                          (std::bind (&WebRtcEndpointImpl::onIceCandidate, this,
                                      std::placeholders::_2) ),
                          std::dynamic_pointer_cast<WebRtcEndpointImpl>
                          (shared_from_this() ) );

  handlerOnIceGatheringDone = register_signal_handler (G_OBJECT (element),
                              "on-ice-gathering-done",
                              std::function <void (GstElement *) >
                              (std::bind (&WebRtcEndpointImpl::onIceGatheringDone, this) ),
                              std::dynamic_pointer_cast<WebRtcEndpointImpl>
                              (shared_from_this() ) );

  handlerOnIceComponentStateChanged = register_signal_handler (G_OBJECT (element),
                                      "on-ice-component-state-changed",
                                      std::function <void (GstElement *, guint, guint, guint) >
                                      (std::bind (&WebRtcEndpointImpl::onIceComponentStateChanged, this,
                                          std::placeholders::_2, std::placeholders::_3, std::placeholders::_4) ),
                                      std::dynamic_pointer_cast<WebRtcEndpointImpl>
                                      (shared_from_this() ) );
}

WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
                                        std::shared_ptr<MediaPipeline>
                                        mediaPipeline) : BaseRtpEndpointImpl (conf,
                                              std::dynamic_pointer_cast<MediaObjectImpl>
                                              (mediaPipeline), FACTORY_NAME)
{
  uint stunPort;
  std::string stunAddress;
  std::string turnURL;

  remove_not_supported_codecs_from_pattern (element);

  //set properties
  try {
    stunPort = getConfigValue <uint, WebRtcEndpoint> ("stunServerPort");
  } catch (boost::property_tree::ptree_error &e) {
    GST_INFO ("Setting default port %d to stun server",
              DEFAULT_STUN_PORT);
    stunPort = DEFAULT_STUN_PORT;
  }

  if (stunPort != 0) {
    try {
      stunAddress = getConfigValue
                    <std::string, WebRtcEndpoint> ("stunServerAddress");
    } catch (boost::property_tree::ptree_error &e) {
      GST_INFO ("Stun address not found in config, cannot operate behind a NAT" );
    }

    if (!stunAddress.empty() ) {
      GST_INFO ("stun port %d\n", stunPort );
      g_object_set ( G_OBJECT (element), "stun-server-port",
                     stunPort, NULL);

      GST_INFO ("stun address %s\n", stunAddress.c_str() );
      g_object_set ( G_OBJECT (element), "stun-server",
                     stunAddress.c_str(),
                     NULL);
    }
  }

  try {
    turnURL = getConfigValue <std::string, WebRtcEndpoint> ("turnURL");
    GST_INFO ("turn info: %s\n", turnURL.c_str() );
    g_object_set ( G_OBJECT (element), "turn-url", turnURL.c_str(),
                   NULL);
  } catch (boost::property_tree::ptree_error &e) {

  }

  g_object_set ( G_OBJECT (element), "certificate-pem-file",
                 getPemCertificate ()->c_str(), NULL);
}

WebRtcEndpointImpl::~WebRtcEndpointImpl()
{
  if (handlerOnIceCandidate > 0) {
    unregister_signal_handler (element, handlerOnIceCandidate);
  }

  if (handlerOnIceGatheringDone > 0) {
    unregister_signal_handler (element, handlerOnIceGatheringDone);
  }

  if (handlerOnIceComponentStateChanged > 0) {
    unregister_signal_handler (element, handlerOnIceComponentStateChanged);
  }
}

std::string
WebRtcEndpointImpl::getStunServerAddress ()
{
  gchar *ret;

  g_object_get ( G_OBJECT (element), "stun-server", &ret, NULL);

  std::string stunServerAddress (ret);
  g_free (ret);

  return stunServerAddress;
}

void
WebRtcEndpointImpl::setStunServerAddress (const std::string &stunServerAddress)
{
  g_object_set ( G_OBJECT (element), "stun-server",
                 stunServerAddress.c_str(),
                 NULL);
}

int
WebRtcEndpointImpl::getStunServerPort ()
{
  int ret;

  g_object_get ( G_OBJECT (element), "stun-server-port", &ret, NULL);

  return ret;
}

void
WebRtcEndpointImpl::setStunServerPort (int stunServerPort)
{
  g_object_set ( G_OBJECT (element), "stun-server-port",
                 stunServerPort, NULL);
}

std::string
WebRtcEndpointImpl::getTurnUrl ()
{
  gchar *ret;

  g_object_get ( G_OBJECT (element), "turn-url", &ret, NULL);

  std::string turnUrl (ret);
  g_free (ret);

  return turnUrl;
}

void
WebRtcEndpointImpl::setTurnUrl (const std::string &turnUrl)
{
  g_object_set ( G_OBJECT (element), "turn-url",
                 turnUrl.c_str(),
                 NULL);
}

void
WebRtcEndpointImpl::gatherCandidates ()
{
  gboolean ret;

  g_signal_emit_by_name (element, "gather-candidates", &ret);

  if (!ret) {
    throw KurentoException (ICE_GATHER_CANDIDATES_ERROR,
                            "Error gathering candidates");
  }
}

void
WebRtcEndpointImpl::addIceCandidate (std::shared_ptr<IceCandidate> candidate)
{
  gboolean ret;
  const char *cand_str = candidate->getCandidate().c_str ();
  const char *mid_str = candidate->getSdpMid().c_str ();
  guint8 sdp_m_line_index = candidate->getSdpMLineIndex ();
  KmsIceCandidate *cand = kms_ice_candidate_new (cand_str, mid_str,
                          sdp_m_line_index);

  g_signal_emit_by_name (element, "add-ice-candidate", cand, &ret);

  g_object_unref (cand);

  if (!ret) {
    throw KurentoException (ICE_ADD_CANDIDATE_ERROR, "Error adding candidate");
  }
}

MediaObjectImpl *
WebRtcEndpointImplFactory::createObject (const boost::property_tree::ptree
    &conf, std::shared_ptr<MediaPipeline>
    mediaPipeline) const
{
  return new WebRtcEndpointImpl (conf, mediaPipeline);
}

WebRtcEndpointImpl::StaticConstructor WebRtcEndpointImpl::staticConstructor;

WebRtcEndpointImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<commit_msg>WebRtcEndpoint: remove unsupported codecs from codecs lists<commit_after>#include <gst/gst.h>
#include "MediaPipeline.hpp"
#include <WebRtcEndpointImplFactory.hpp>
#include "WebRtcEndpointImpl.hpp"
#include <jsonrpc/JsonSerializer.hpp>
#include <KurentoException.hpp>
#include <gst/gst.h>
#include <boost/filesystem.hpp>
#include <IceCandidate.hpp>
#include <webrtcendpoint/kmsicecandidate.h>
#include <IceComponentState.hpp>
#include <SignalHandler.hpp>

#define GST_CAT_DEFAULT kurento_web_rtc_endpoint_impl
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "KurentoWebRtcEndpointImpl"

#define FACTORY_NAME "webrtcendpoint"

namespace kurento
{

static const std::string CERTTOOL_TEMPLATE = "autoCerttool.tmpl";
static const std::string CERT_KEY_PEM_FILE = "autoCertkey.pem";

static const uint DEFAULT_STUN_PORT = 3478;

static std::shared_ptr<std::string> pemCertificate;
std::mutex WebRtcEndpointImpl::certificateMutex;

class TemporalDirectory
{

public:
  ~TemporalDirectory() {
    if (!dir.string ().empty() ) {
      boost::filesystem::remove_all (dir);
    }
  }

  void setDir (boost::filesystem::path &dir) {
    this->dir = dir;
  }
private:
  boost::filesystem::path dir;
};

static TemporalDirectory tmpDir;

static void
create_pem_certificate ()
{
  int ret;
  boost::filesystem::path temporalDirectory = boost::filesystem::unique_path (
        boost::filesystem::temp_directory_path() / "WebRtcEndpoint_%%%%%%%%" );
  boost::filesystem::create_directories (temporalDirectory);
  tmpDir.setDir (temporalDirectory);

  boost::filesystem::path pemFile = temporalDirectory / CERT_KEY_PEM_FILE;
  std::string pemGenerationCommand =
    "/bin/sh -c \"certtool --generate-privkey --outfile " + pemFile .string()  +
    "\"";

  ret = system (pemGenerationCommand.c_str() );

  if (ret == -1) {
    return;
  }

  boost::filesystem::path templateFile = temporalDirectory / CERTTOOL_TEMPLATE;
  std::string certtoolCommand = "/bin/sh -c \"echo 'organization = kurento' > " +
                                templateFile.string() + " && certtool --generate-self-signed --load-privkey " +
                                pemFile.string() + " --template " + templateFile.string() +  " >> " +
                                pemFile.string() + " 2>/dev/null\"";

  ret = system (certtoolCommand.c_str() );

  if (ret == -1) {
    return;
  }

  pemCertificate = std::shared_ptr <std::string> (new std::string (
                     pemFile.string() ) );
}

std::shared_ptr<std::string>
WebRtcEndpointImpl::getPemCertificate ()
{
  std::unique_lock<std::mutex> lock (certificateMutex);

  if (pemCertificate) {
    return pemCertificate;
  }

  try {
    boost::filesystem::path pem_certificate_file_name (
      getConfigValue<std::string, WebRtcEndpoint> ("pemCertificate") );

    if (pem_certificate_file_name.is_relative() ) {
      pem_certificate_file_name = boost::filesystem::path (
                                    config.get<std::string> ("configPath") ) / pem_certificate_file_name;
    }

    pemCertificate = std::shared_ptr <std::string> (new std::string (
                       pem_certificate_file_name.string() ) );

    return pemCertificate;
  } catch (boost::property_tree::ptree_error &e) {

  }

  create_pem_certificate();

  return pemCertificate;
}

static const gchar *supported_codecs[] = { "VP8", "opus", "PCMU" };

static void
remove_not_supported_codecs_from_array (GstElement *element, GArray *codecs)
{
  guint i;

  if (codecs == NULL) {
    return;
  }

  for (i = 0; i < codecs->len; i++) {
    GValue *v = &g_array_index (codecs, GValue, i);
    const GstStructure *s;
    const gchar *codec_name;
    gboolean supported = FALSE;
    guint j;

    if (!GST_VALUE_HOLDS_STRUCTURE (v) ) {
      GST_WARNING_OBJECT (element, "Value into array is not a GstStructure");
      continue;
    }

    s = gst_value_get_structure (v);
    codec_name = gst_structure_get_name (s);

    for (j = 0; j < G_N_ELEMENTS (supported_codecs); j++) {
      if (g_str_has_prefix (codec_name, supported_codecs[j]) ) {
        supported = TRUE;
        break;
      }
    }

    if (!supported) {
      GST_INFO_OBJECT (element, "Removing not supported codec '%s'", codec_name);
      g_array_remove_index (codecs, i);
      i--;
    }
  }
}

static void
remove_not_supported_codecs (GstElement *element)
{
  GArray *codecs;

  g_object_get (element, "audio-codecs", &codecs, NULL);
  remove_not_supported_codecs_from_array (element, codecs);

  g_object_get (element, "video-codecs", &codecs, NULL);
  remove_not_supported_codecs_from_array (element, codecs);
}

void WebRtcEndpointImpl::onIceCandidate (KmsIceCandidate *candidate)
{
  try {
    std::string cand_str (kms_ice_candidate_get_candidate (candidate) );
    std::string mid_str (kms_ice_candidate_get_sdp_mid (candidate) );
    int sdp_m_line_index = kms_ice_candidate_get_sdp_m_line_index (candidate);
    std::shared_ptr <IceCandidate> cand ( new  IceCandidate
                                          (cand_str, mid_str, sdp_m_line_index) );
    OnIceCandidate event (shared_from_this(), OnIceCandidate::getName(), cand);

    signalOnIceCandidate (event);
  } catch (std::bad_weak_ptr &e) {
  }
}

void WebRtcEndpointImpl::onIceGatheringDone ()
{
  try {
    OnIceGatheringDone event (shared_from_this(), OnIceGatheringDone::getName() );

    signalOnIceGatheringDone (event);
  } catch (std::bad_weak_ptr &e) {
  }
}

void WebRtcEndpointImpl::onIceComponentStateChanged (guint streamId,
    guint componentId, guint state)
{
  try {
    IceComponentState::type type;

    switch (state) {
    case NICE_COMPONENT_STATE_DISCONNECTED:
      type = IceComponentState::DISCONNECTED;
      break;

    case NICE_COMPONENT_STATE_GATHERING:
      type = IceComponentState::GATHERING;
      break;

    case NICE_COMPONENT_STATE_CONNECTING:
      type = IceComponentState::CONNECTING;
      break;

    case NICE_COMPONENT_STATE_CONNECTED:
      type = IceComponentState::CONNECTED;
      break;

    case NICE_COMPONENT_STATE_READY:
      type = IceComponentState::READY;
      break;

    case NICE_COMPONENT_STATE_FAILED:
      type = IceComponentState::FAILED;
      break;

    default:
      type = IceComponentState::FAILED;
      break;
    }

    IceComponentState *componentState = new IceComponentState (type);
    OnIceComponentStateChanged event (shared_from_this(),
                                      OnIceComponentStateChanged::getName(),
                                      streamId, componentId,  std::shared_ptr<IceComponentState> (componentState) );

    signalOnIceComponentStateChanged (event);
  } catch (std::bad_weak_ptr &e) {
  }
}

void WebRtcEndpointImpl::postConstructor ()
{
  BaseRtpEndpointImpl::postConstructor ();

  handlerOnIceCandidate = register_signal_handler (G_OBJECT (element),
                          "on-ice-candidate",
                          std::function <void (GstElement *, KmsIceCandidate *) >
                          (std::bind (&WebRtcEndpointImpl::onIceCandidate, this,
                                      std::placeholders::_2) ),
                          std::dynamic_pointer_cast<WebRtcEndpointImpl>
                          (shared_from_this() ) );

  handlerOnIceGatheringDone = register_signal_handler (G_OBJECT (element),
                              "on-ice-gathering-done",
                              std::function <void (GstElement *) >
                              (std::bind (&WebRtcEndpointImpl::onIceGatheringDone, this) ),
                              std::dynamic_pointer_cast<WebRtcEndpointImpl>
                              (shared_from_this() ) );

  handlerOnIceComponentStateChanged = register_signal_handler (G_OBJECT (element),
                                      "on-ice-component-state-changed",
                                      std::function <void (GstElement *, guint, guint, guint) >
                                      (std::bind (&WebRtcEndpointImpl::onIceComponentStateChanged, this,
                                          std::placeholders::_2, std::placeholders::_3, std::placeholders::_4) ),
                                      std::dynamic_pointer_cast<WebRtcEndpointImpl>
                                      (shared_from_this() ) );
}

WebRtcEndpointImpl::WebRtcEndpointImpl (const boost::property_tree::ptree &conf,
                                        std::shared_ptr<MediaPipeline>
                                        mediaPipeline) : BaseRtpEndpointImpl (conf,
                                              std::dynamic_pointer_cast<MediaObjectImpl>
                                              (mediaPipeline), FACTORY_NAME)
{
  uint stunPort;
  std::string stunAddress;
  std::string turnURL;

  remove_not_supported_codecs (element);

  //set properties
  try {
    stunPort = getConfigValue <uint, WebRtcEndpoint> ("stunServerPort");
  } catch (boost::property_tree::ptree_error &e) {
    GST_INFO ("Setting default port %d to stun server",
              DEFAULT_STUN_PORT);
    stunPort = DEFAULT_STUN_PORT;
  }

  if (stunPort != 0) {
    try {
      stunAddress = getConfigValue
                    <std::string, WebRtcEndpoint> ("stunServerAddress");
    } catch (boost::property_tree::ptree_error &e) {
      GST_INFO ("Stun address not found in config, cannot operate behind a NAT" );
    }

    if (!stunAddress.empty() ) {
      GST_INFO ("stun port %d\n", stunPort );
      g_object_set ( G_OBJECT (element), "stun-server-port",
                     stunPort, NULL);

      GST_INFO ("stun address %s\n", stunAddress.c_str() );
      g_object_set ( G_OBJECT (element), "stun-server",
                     stunAddress.c_str(),
                     NULL);
    }
  }

  try {
    turnURL = getConfigValue <std::string, WebRtcEndpoint> ("turnURL");
    GST_INFO ("turn info: %s\n", turnURL.c_str() );
    g_object_set ( G_OBJECT (element), "turn-url", turnURL.c_str(),
                   NULL);
  } catch (boost::property_tree::ptree_error &e) {

  }

  g_object_set ( G_OBJECT (element), "certificate-pem-file",
                 getPemCertificate ()->c_str(), NULL);
}

WebRtcEndpointImpl::~WebRtcEndpointImpl()
{
  if (handlerOnIceCandidate > 0) {
    unregister_signal_handler (element, handlerOnIceCandidate);
  }

  if (handlerOnIceGatheringDone > 0) {
    unregister_signal_handler (element, handlerOnIceGatheringDone);
  }

  if (handlerOnIceComponentStateChanged > 0) {
    unregister_signal_handler (element, handlerOnIceComponentStateChanged);
  }
}

std::string
WebRtcEndpointImpl::getStunServerAddress ()
{
  gchar *ret;

  g_object_get ( G_OBJECT (element), "stun-server", &ret, NULL);

  std::string stunServerAddress (ret);
  g_free (ret);

  return stunServerAddress;
}

void
WebRtcEndpointImpl::setStunServerAddress (const std::string &stunServerAddress)
{
  g_object_set ( G_OBJECT (element), "stun-server",
                 stunServerAddress.c_str(),
                 NULL);
}

int
WebRtcEndpointImpl::getStunServerPort ()
{
  int ret;

  g_object_get ( G_OBJECT (element), "stun-server-port", &ret, NULL);

  return ret;
}

void
WebRtcEndpointImpl::setStunServerPort (int stunServerPort)
{
  g_object_set ( G_OBJECT (element), "stun-server-port",
                 stunServerPort, NULL);
}

std::string
WebRtcEndpointImpl::getTurnUrl ()
{
  gchar *ret;

  g_object_get ( G_OBJECT (element), "turn-url", &ret, NULL);

  std::string turnUrl (ret);
  g_free (ret);

  return turnUrl;
}

void
WebRtcEndpointImpl::setTurnUrl (const std::string &turnUrl)
{
  g_object_set ( G_OBJECT (element), "turn-url",
                 turnUrl.c_str(),
                 NULL);
}

void
WebRtcEndpointImpl::gatherCandidates ()
{
  gboolean ret;

  g_signal_emit_by_name (element, "gather-candidates", &ret);

  if (!ret) {
    throw KurentoException (ICE_GATHER_CANDIDATES_ERROR,
                            "Error gathering candidates");
  }
}

void
WebRtcEndpointImpl::addIceCandidate (std::shared_ptr<IceCandidate> candidate)
{
  gboolean ret;
  const char *cand_str = candidate->getCandidate().c_str ();
  const char *mid_str = candidate->getSdpMid().c_str ();
  guint8 sdp_m_line_index = candidate->getSdpMLineIndex ();
  KmsIceCandidate *cand = kms_ice_candidate_new (cand_str, mid_str,
                          sdp_m_line_index);

  g_signal_emit_by_name (element, "add-ice-candidate", cand, &ret);

  g_object_unref (cand);

  if (!ret) {
    throw KurentoException (ICE_ADD_CANDIDATE_ERROR, "Error adding candidate");
  }
}

MediaObjectImpl *
WebRtcEndpointImplFactory::createObject (const boost::property_tree::ptree
    &conf, std::shared_ptr<MediaPipeline>
    mediaPipeline) const
{
  return new WebRtcEndpointImpl (conf, mediaPipeline);
}

WebRtcEndpointImpl::StaticConstructor WebRtcEndpointImpl::staticConstructor;

WebRtcEndpointImpl::StaticConstructor::StaticConstructor()
{
  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                           GST_DEFAULT_NAME);
}

} /* kurento */
<|endoftext|>


<commit_before>// enveomics/sequence.h - Library for sequences on enve-omics software
// @author Luis M. Rodriguez-R <lmrodriguezr at gmail dot com>
// @license artistic 2.0
// @version 1.0

#include <iostream>
#include <unistd.h>
#include <fstream>
#include <string>
#include <bitset>
#include <stdio.h>
#include <sys/types.h>

#include "universal.h"
#include "sequence.h"

using namespace std;

size_t count_seqs(char *file, const char *format, int &largest_line, double &avg_seq){
   // Vars
   ifstream	fileh;
   unsigned int	N=0, nline=0, totlen=0, lastn=0;
   int		maxlen=0;
   char		start;
   bool		isFastQ=false;

   avg_seq = 0.0;

   // Format
   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "fastq")==0) {start = '@'; isFastQ=true;}
   else if(strcmp(format, "enveomics-seq")==0){start = '>';}
   else {error("Unsupported format", format);}

   // Count
   fileh.open(file, ios::in);
   if(!fileh.is_open()) error("Impossible to open the file", file);
   while(fileh.good()){
      string line;
      getline(fileh, line);
      if(line.length() > (size_t)maxlen) maxlen = line.length();
      if((isFastQ & (nline%4==0)) | (!isFastQ & (line[0]==start))) N++;
      else totlen += line.length();
      if(totlen > UINT_MAX/10){
         lastn = N - lastn;
	 avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
	 cerr << "Partial average length: " << avg_seq << endl;
      }
      nline++;
   }
   fileh.close();

   largest_line = maxlen;
   lastn = N - lastn;
   avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
   return N;
}

size_t count_seqs(char *file, const char *format, int &largest_line){
   double dummy;
   return count_seqs(file, format, largest_line, dummy);
}

size_t count_seqs(char *file, const char *format){
   int   dummy1;
   double dummy2;
   return count_seqs(file, format, dummy1, dummy2);
}

size_t count_seqs(char *file, int &largest_line, double &avg_seq){
   return count_seqs(file, "fasta", largest_line, avg_seq);
}

size_t count_seqs(char *file, int &largest_line){
   double dummy;
   return count_seqs(file, largest_line, dummy);
}

size_t count_seqs(char *file){
   int   dummy1;
   double dummy2;
   return count_seqs(file, dummy1, dummy2);
}

size_t build_index(char *sourceFile, char* format, char *&namFileOut, char *&seqFileOut, int &largest_seq, double &avg_seq){
   // Vars
   unsigned int	N=0, nline=0, totlen=0, lastn=0;
   int		maxlen=0;
   char		start, *namFile, *seqFile;
   bool		inSeq=false, isFastQ=false;
   string	seq, name;
   ifstream	infileh, testseq, testnam;
   ofstream	seqfileh, namfileh;

   // Format
   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "fastq")==0) {start = '@'; isFastQ=true;}
   else {error("Unsupported format", format);}

   // Files
   seqFile = new char[strlen(sourceFile)+20];
   sprintf(seqFile, "%s.enve-seq.%d", sourceFile, getpid());
   namFile = new char[strlen(sourceFile)+20];
   sprintf(namFile, "%s.enve-nam.%d", sourceFile, getpid());
   namFileOut = namFile;
   seqFileOut = seqFile;

   // Check if I need to do it
   testseq.open(seqFile, ios::in);
   if(testseq.is_open()){
      testseq.close();
      testnam.open(namFile, ios::in);
      if(testnam.is_open()){
	 testnam.close();
         N = count_seqs(seqFile, "enveomics-seq", largest_seq, avg_seq);
	 return N;
      }
   }

   // Open file streams
   infileh.open(sourceFile, ios::in);
   if(!infileh.is_open()) error("Cannot open the file", sourceFile);
   seqfileh.open(seqFile, ios::out);
   if(!seqfileh.is_open()) error("Cannot open the file", seqFile);
   namfileh.open(namFile, ios::out);
   if(!namfileh.is_open()) error("Cannot open the file", namFile);

   // Run
   avg_seq = 0.0;
   while(!infileh.eof()){
      string line;
      getline(infileh, line);
      if((isFastQ & (nline%4==0)) | (!isFastQ & (line[0]==start))){
         if(seq.length()>0){
	    namfileh << ">" << ++N << endl << name << endl;
	    seqfileh << ">" <<   N << endl <<  seq << endl;
	    if(seq.length() > (size_t)maxlen) maxlen = seq.length();
	    totlen += seq.length();
	    if(totlen > UINT_MAX/10){
	       lastn = N - lastn;
	       avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
	       cerr << "Partial average length: " << avg_seq << endl;
	    }
	 }
         name = line.length()>1 ? line.substr(1) : "";
	 seq = (string)"";
	 inSeq = true;
      }else{
	 if(inSeq) seq.append(line);
	 if(isFastQ) inSeq = false;
      }
      nline++;
   }
   if(seq.length()>0){
      //namfileh << ">" << ++N << endl << name << endl;
      //seqfileh << ">" <<   N << endl <<  seq << endl;
      if(seq.length() > (size_t)maxlen) maxlen = seq.length();
      totlen += seq.length();
   }

   // Close file streams
   infileh.close();
   seqfileh.close();
   namfileh.close();

   largest_seq = maxlen;
   lastn = N - lastn;
   avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
   return N;
}

size_t build_index(char *sourceFile, char* format, char *&namFileOut, char *&seqFileOut, int &largest_seq){
   double dummy;
   return build_index(sourceFile, format, namFileOut, seqFileOut, largest_seq, dummy);
}

size_t build_index(char *sourceFile, char* format, char *&namFileOut, char *&seqFileOut){
   int dummy1;
   double dummy2;
   return build_index(sourceFile, format, namFileOut, seqFileOut, dummy1, dummy2);
}

size_t sub_sample_seqs(char *sourceFile, char *destFile, double portion, char *format){
   ifstream	filein;
   ofstream	fileout;
   char		start;
   size_t	n=0;
   string	entry;

   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "enveomics-seq")==0) {start = '>';}
   else if(strcmp(format, "fastq")==0) {start = '@';}
   else {error("Unsupported format", format);}

   filein.open(sourceFile, ios::in);
   if(!filein.is_open()) error("Impossible to open the input file", sourceFile);
   fileout.open(destFile, ios::out);
   if(!fileout.is_open()) error("Impossible to open the output file", destFile);

   while(filein.good()){
      string line;
      getline(filein, line);
      if((line[0]==start) | !filein.good()){
	 if((entry.size()>0) && (portion>=1 || ((double)rand()/RAND_MAX <= portion))){
	    n++;
	    fileout << entry;
	 }
         entry = (string)"";
      }
      entry.append(line);
      entry.append((char *)"\n");
   }

   fileout.close();
   filein.close();

   return n;
}

size_t sub_sample_seqs(char *sourceFile, char *destFile, double portion){
   return sub_sample_seqs(sourceFile, destFile, portion, (char *)"fasta");
}

int get_seqs(char **&seqs, char *file, int from, int number, int largest_seq, char *format){
   //  Vars
   ifstream	filein;
   char		start;
   int		n=0, i=0;
   string	entry;

   // Init
   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "enveomics-seq")==0) {start = '>';}
   else {error("Unsupported format", format);}

   // Open file
   filein.open(file, ios::in);
   if(!filein.is_open()) error("Impossible to open the input file", file);

   // Memory allocation
   seqs = new char*[number];
   if(!seqs) error("Impossible to allocate memory for that many sequences", number);
   for(size_t a=0; a<(size_t)number; a++){
      seqs[a] = new char[largest_seq+1];
      if(!seqs[a]) error("Impossible to allocate memory for another sequence", (unsigned int)a);
   }

   // Read the file
   while(filein.good()){
      string line;
      getline(filein, line);
      if((line[0]==start) | !filein.good()){
	 if(entry.size()>0){
	    i++;
	    if(i>=from){
	       if(entry.length() > (size_t)largest_seq) error("Found a sequences largest than expected", (int)entry.length());
	       for(size_t a=0; a<=entry.length(); a++) seqs[n][a] = entry[a];
	       n++;
	       if(n >= number) break;
	    }
	 }
	 entry = (string)"";
      }else{
         entry.append(line);
         //entry.append((char *)"\n");
      }
   }

   // Finalize
   filein.close();
   return n;
}

int get_seqs(char **&seqs, char *file, int from, int number, int largest_seq){
   return get_seqs(seqs, file, from, number, largest_seq, (char *)"fasta");
}

int reverse_complement(char *&out, char *in){
   int	len = strlen(in);
   for(int i=len; i>0; i--)
      out[len-i] = in[i]=='A'?'T':
		   in[i]=='C'?'G':
		   in[i]=='G'?'C':
		   in[i]=='T'?'A':
			      'N';
   out[len]=(char)NULL;
   return len;
}

#ifdef ENVEOMICS_NUC_T
// The bitset representation of nucleotides (in 2 bits)
nuc_t ctonuc(char c){
   nuc_t nuc;
   nuc.set(); // 11
   if(c=='A') return (~nuc);	// 00
   if(c=='C') return (nuc>>1);	// 01
   if(c=='G') return (nuc<<1);	// 10
   if(c=='T') return nuc;	// 11

   char	letter[] = {c, (char)NULL};
   error("Impossible to interpret char as nucleotide", letter);
}

char nuctoc(nuc_t nuc){
   char c;
   nuc_t nucA = ctonuc('A');
   if(nuc==nucA)	return 'A';
   if(nuc==(nucA>>1))	return 'C';
   if(nuc==(nucA<<1))	return 'G';
   			return 'T';
}

int atonucseq(nucseq_t &nucseq, char *charseq){
   int	len = strlen(charseq);
   for(size_t a=0; a<len; a++) nucseq.seq[a] = ctonuc(charseq[a]);
   nucseq.len=len;
   return nucseq.len;
}

int nucseqtoa(char *&charseq, nucseq_t nucseq){
   for(size_t a=0; a<nucseq.len; a++) charseq[a] = nuctoc(nucseq.seq[a]);
   charseq[nucseq.len] = (char)NULL;
   return nucseq.len;
}

int reverse_complement(nucseq_t &out, nucseq_t in){
   for(size_t i=in.len; i>0; i--) out.seq[in.len-i] = (~in.seq[i]);
   out.len = in.len;
   return in.len;
}

int seqtoa(char *&charseq, nucseq_t nucseq){
   for(size_t i=0; i<nucseq.len; i++) charseq[i] = nuctoc(nucseq.seq[i]);
   charseq[nucseq.len] = (char)NULL;
}

#endif

<commit_msg>Solved #6<commit_after>// enveomics/sequence.h - Library for sequences on enve-omics software
// @author Luis M. Rodriguez-R <lmrodriguezr at gmail dot com>
// @license artistic 2.0
// @version 1.0

#include <iostream>
#include <unistd.h>
#include <fstream>
#include <string>
#include <bitset>
#include <stdio.h>
#include <sys/types.h>

#include "universal.h"
#include "sequence.h"

using namespace std;

size_t count_seqs(char *file, const char *format, int &largest_line, double &avg_seq){
   // Vars
   ifstream	fileh;
   unsigned int	N=0, nline=0, totlen=0, lastn=0;
   int		maxlen=0;
   char		start;
   bool		isFastQ=false;

   avg_seq = 0.0;

   // Format
   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "fastq")==0) {start = '@'; isFastQ=true;}
   else if(strcmp(format, "enveomics-seq")==0){start = '>';}
   else {error("Unsupported format", format);}

   // Count
   fileh.open(file, ios::in);
   if(!fileh.is_open()) error("Impossible to open the file", file);
   while(fileh.good()){
      string line;
      getline(fileh, line);
      if(line.length() > (size_t)maxlen) maxlen = line.length();
      if((isFastQ & (nline%4==0)) | (!isFastQ & (line[0]==start))) N++;
      else totlen += line.length();
      if(totlen > UINT_MAX/1000){
	 avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
	 totlen = 0;
	 lastn = N;
      }
      nline++;
   }
   fileh.close();

   largest_line = maxlen;
   avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
   return N;
}

size_t count_seqs(char *file, const char *format, int &largest_line){
   double dummy;
   return count_seqs(file, format, largest_line, dummy);
}

size_t count_seqs(char *file, const char *format){
   int   dummy1;
   double dummy2;
   return count_seqs(file, format, dummy1, dummy2);
}

size_t count_seqs(char *file, int &largest_line, double &avg_seq){
   return count_seqs(file, "fasta", largest_line, avg_seq);
}

size_t count_seqs(char *file, int &largest_line){
   double dummy;
   return count_seqs(file, largest_line, dummy);
}

size_t count_seqs(char *file){
   int   dummy1;
   double dummy2;
   return count_seqs(file, dummy1, dummy2);
}

size_t build_index(char *sourceFile, char* format, char *&namFileOut, char *&seqFileOut, int &largest_seq, double &avg_seq){
   // Vars
   unsigned int	N=0, nline=0, totlen=0, lastn=0;
   int		maxlen=0;
   char		start, *namFile, *seqFile;
   bool		inSeq=false, isFastQ=false;
   string	seq, name;
   ifstream	infileh, testseq, testnam;
   ofstream	seqfileh, namfileh;

   // Format
   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "fastq")==0) {start = '@'; isFastQ=true;}
   else {error("Unsupported format", format);}

   // Files
   seqFile = new char[strlen(sourceFile)+20];
   sprintf(seqFile, "%s.enve-seq.%d", sourceFile, getpid());
   namFile = new char[strlen(sourceFile)+20];
   sprintf(namFile, "%s.enve-nam.%d", sourceFile, getpid());
   namFileOut = namFile;
   seqFileOut = seqFile;

   // Check if I need to do it
   testseq.open(seqFile, ios::in);
   if(testseq.is_open()){
      testseq.close();
      testnam.open(namFile, ios::in);
      if(testnam.is_open()){
	 testnam.close();
         N = count_seqs(seqFile, "enveomics-seq", largest_seq, avg_seq);
	 return N;
      }
   }

   // Open file streams
   infileh.open(sourceFile, ios::in);
   if(!infileh.is_open()) error("Cannot open the file", sourceFile);
   seqfileh.open(seqFile, ios::out);
   if(!seqfileh.is_open()) error("Cannot open the file", seqFile);
   namfileh.open(namFile, ios::out);
   if(!namfileh.is_open()) error("Cannot open the file", namFile);

   // Run
   avg_seq = 0.0;
   while(!infileh.eof()){
      string line;
      getline(infileh, line);
      if((isFastQ & (nline%4==0)) | (!isFastQ & (line[0]==start))){
         if(seq.length()>0){
	    namfileh << ">" << ++N << endl << name << endl;
	    seqfileh << ">" <<   N << endl <<  seq << endl;
	    if(seq.length() > (size_t)maxlen) maxlen = seq.length();
	    totlen += seq.length();
	    if(totlen > UINT_MAX/10){
	       avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
	       totlen = 0;
	       lastn = N;
	    }
	 }
         name = line.length()>1 ? line.substr(1) : "";
	 seq = (string)"";
	 inSeq = true;
      }else{
	 if(inSeq) seq.append(line);
	 if(isFastQ) inSeq = false;
      }
      nline++;
   }
   if(seq.length()>0){
      //namfileh << ">" << ++N << endl << name << endl;
      //seqfileh << ">" <<   N << endl <<  seq << endl;
      if(seq.length() > (size_t)maxlen) maxlen = seq.length();
      totlen += seq.length();
   }

   // Close file streams
   infileh.close();
   seqfileh.close();
   namfileh.close();

   largest_seq = maxlen;
   avg_seq = ( ( avg_seq/N )*lastn ) + ((double)totlen/N);
   return N;
}

size_t build_index(char *sourceFile, char* format, char *&namFileOut, char *&seqFileOut, int &largest_seq){
   double dummy;
   return build_index(sourceFile, format, namFileOut, seqFileOut, largest_seq, dummy);
}

size_t build_index(char *sourceFile, char* format, char *&namFileOut, char *&seqFileOut){
   int dummy1;
   double dummy2;
   return build_index(sourceFile, format, namFileOut, seqFileOut, dummy1, dummy2);
}

size_t sub_sample_seqs(char *sourceFile, char *destFile, double portion, char *format){
   ifstream	filein;
   ofstream	fileout;
   char		start;
   size_t	n=0;
   string	entry;

   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "enveomics-seq")==0) {start = '>';}
   else if(strcmp(format, "fastq")==0) {start = '@';}
   else {error("Unsupported format", format);}

   filein.open(sourceFile, ios::in);
   if(!filein.is_open()) error("Impossible to open the input file", sourceFile);
   fileout.open(destFile, ios::out);
   if(!fileout.is_open()) error("Impossible to open the output file", destFile);

   while(filein.good()){
      string line;
      getline(filein, line);
      if((line[0]==start) | !filein.good()){
	 if((entry.size()>0) && (portion>=1 || ((double)rand()/RAND_MAX <= portion))){
	    n++;
	    fileout << entry;
	 }
         entry = (string)"";
      }
      entry.append(line);
      entry.append((char *)"\n");
   }

   fileout.close();
   filein.close();

   return n;
}

size_t sub_sample_seqs(char *sourceFile, char *destFile, double portion){
   return sub_sample_seqs(sourceFile, destFile, portion, (char *)"fasta");
}

int get_seqs(char **&seqs, char *file, int from, int number, int largest_seq, char *format){
   //  Vars
   ifstream	filein;
   char		start;
   int		n=0, i=0;
   string	entry;

   // Init
   if(strcmp(format, "fasta")==0) {start = '>';}
   else if(strcmp(format, "enveomics-seq")==0) {start = '>';}
   else {error("Unsupported format", format);}

   // Open file
   filein.open(file, ios::in);
   if(!filein.is_open()) error("Impossible to open the input file", file);

   // Memory allocation
   seqs = new char*[number];
   if(!seqs) error("Impossible to allocate memory for that many sequences", number);
   for(size_t a=0; a<(size_t)number; a++){
      seqs[a] = new char[largest_seq+1];
      if(!seqs[a]) error("Impossible to allocate memory for another sequence", (unsigned int)a);
   }

   // Read the file
   while(filein.good()){
      string line;
      getline(filein, line);
      if((line[0]==start) | !filein.good()){
	 if(entry.size()>0){
	    i++;
	    if(i>=from){
	       if(entry.length() > (size_t)largest_seq) error("Found a sequences largest than expected", (int)entry.length());
	       for(size_t a=0; a<=entry.length(); a++) seqs[n][a] = entry[a];
	       n++;
	       if(n >= number) break;
	    }
	 }
	 entry = (string)"";
      }else{
         entry.append(line);
         //entry.append((char *)"\n");
      }
   }

   // Finalize
   filein.close();
   return n;
}

int get_seqs(char **&seqs, char *file, int from, int number, int largest_seq){
   return get_seqs(seqs, file, from, number, largest_seq, (char *)"fasta");
}

int reverse_complement(char *&out, char *in){
   int	len = strlen(in);
   for(int i=len; i>0; i--)
      out[len-i] = in[i]=='A'?'T':
		   in[i]=='C'?'G':
		   in[i]=='G'?'C':
		   in[i]=='T'?'A':
			      'N';
   out[len]=(char)NULL;
   return len;
}

#ifdef ENVEOMICS_NUC_T
// The bitset representation of nucleotides (in 2 bits)
nuc_t ctonuc(char c){
   nuc_t nuc;
   nuc.set(); // 11
   if(c=='A') return (~nuc);	// 00
   if(c=='C') return (nuc>>1);	// 01
   if(c=='G') return (nuc<<1);	// 10
   if(c=='T') return nuc;	// 11

   char	letter[] = {c, (char)NULL};
   error("Impossible to interpret char as nucleotide", letter);
}

char nuctoc(nuc_t nuc){
   char c;
   nuc_t nucA = ctonuc('A');
   if(nuc==nucA)	return 'A';
   if(nuc==(nucA>>1))	return 'C';
   if(nuc==(nucA<<1))	return 'G';
   			return 'T';
}

int atonucseq(nucseq_t &nucseq, char *charseq){
   int	len = strlen(charseq);
   for(size_t a=0; a<len; a++) nucseq.seq[a] = ctonuc(charseq[a]);
   nucseq.len=len;
   return nucseq.len;
}

int nucseqtoa(char *&charseq, nucseq_t nucseq){
   for(size_t a=0; a<nucseq.len; a++) charseq[a] = nuctoc(nucseq.seq[a]);
   charseq[nucseq.len] = (char)NULL;
   return nucseq.len;
}

int reverse_complement(nucseq_t &out, nucseq_t in){
   for(size_t i=in.len; i>0; i--) out.seq[in.len-i] = (~in.seq[i]);
   out.len = in.len;
   return in.len;
}

int seqtoa(char *&charseq, nucseq_t nucseq){
   for(size_t i=0; i<nucseq.len; i++) charseq[i] = nuctoc(nucseq.seq[i]);
   charseq[nucseq.len] = (char)NULL;
}

#endif

<|endoftext|>


<commit_before>// Copyright (c) 2015 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "steam_client.h"

#include <algorithm>

#include "nan.h"

namespace greenworks {

namespace {

SteamClient* g_steam_client = NULL;
uv_timer_t* g_steam_timer = NULL;

void on_timer_close_complete(uv_handle_t* handle) {
  delete reinterpret_cast<uv_timer_t*>(handle);
}

// uv v0.11.23 has changed uv_timer_cb interface by removing status_code.
#if NAUV_UVVERSION < 0x000b17
void RunSteamAPICallback(uv_timer_t* handle, int status_code) {
#else
void RunSteamAPICallback(uv_timer_t* handle) {
#endif
  SteamAPI_RunCallbacks();
}

}  // namespace

SteamClient::SteamClient()
    : game_overlay_activated_(this, &SteamClient::OnGameOverlayActivated),
      steam_servers_connected_(this, &SteamClient::OnSteamServersConnected),
      steam_servers_disconnected_(this,
                                  &SteamClient::OnSteamServersDisconnected),
      steam_server_connect_failure_(this,
                                    &SteamClient::OnSteamServerConnectFailure),
      steam_shutdown_(this, &SteamClient::OnSteamShutdown),
      steam_persona_state_change_(this, &SteamClient::OnPeronaStateChange),
      avatar_image_loaded_(this, &SteamClient::OnAvatarImageLoaded),
      game_connected_friend_chat_msg_(
          this,
          &SteamClient::OnGameConnectedFriendChatMessage),
      dlc_installed_(this, &SteamClient::OnDLCInstalled) {}

SteamClient::~SteamClient() {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    delete observer_list_[i];
  }
  if (g_steam_client) {
    uv_timer_stop(g_steam_timer);
    uv_close(reinterpret_cast<uv_handle_t*>(g_steam_timer),
             on_timer_close_complete);
  }
}

SteamClient* SteamClient::GetInstance() {
  if (!g_steam_client) {
    g_steam_client = new SteamClient();
  }
  return g_steam_client;
}

void SteamClient::OnGameOverlayActivated(GameOverlayActivated_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnGameOverlayActivated(
        static_cast<bool>(callback->m_bActive));
  }
}

void SteamClient::OnSteamServersConnected(SteamServersConnected_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamServersConnected();
  }
}

void SteamClient::OnSteamServersDisconnected(
    SteamServersDisconnected_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamServersDisconnected();
  }
}

void SteamClient::OnSteamServerConnectFailure(
    SteamServerConnectFailure_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamServerConnectFailure(
        static_cast<int>(callback->m_eResult));
  }
}

void SteamClient::OnSteamShutdown(SteamShutdown_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamShutdown();
  }
}

void SteamClient::OnPeronaStateChange(PersonaStateChange_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnPersonaStateChange(callback->m_ulSteamID,
                                            callback->m_nChangeFlags);
  }
}

void SteamClient::OnAvatarImageLoaded(AvatarImageLoaded_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnAvatarImageLoaded(
        callback->m_steamID.ConvertToUint64(), callback->m_iImage,
        callback->m_iTall, callback->m_iWide);
  }
}

void SteamClient::OnGameConnectedFriendChatMessage(
    GameConnectedFriendChatMsg_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnGameConnectedFriendChatMessage(
        callback->m_steamIDUser.ConvertToUint64(), callback->m_iMessageID);
  }
}

void SteamClient::OnDLCInstalled(DlcInstalled_t *callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnDLCInstalled(
        callback->m_nAppID);
  }
}

void SteamClient::StartSteamLoop() {
  if (g_steam_timer)
    return;
  SteamClient::GetInstance();
  g_steam_timer = new uv_timer_t();
  uv_timer_init(uv_default_loop(), g_steam_timer);
  uv_timer_start(g_steam_timer, &RunSteamAPICallback, 0, 100);
}

void SteamClient::AddObserver(Observer* observer) {
  if (std::find(observer_list_.begin(), observer_list_.end(), observer) ==
      observer_list_.end()) {
    observer_list_.push_back(observer);
  }
}

}  // namespace greenworks
<commit_msg>Add MicroTxnAuthorizationResponse_t<commit_after>// Copyright (c) 2015 Greenheart Games Pty. Ltd. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "steam_client.h"

#include <algorithm>

#include "nan.h"

namespace greenworks {

namespace {

SteamClient* g_steam_client = NULL;
uv_timer_t* g_steam_timer = NULL;

void on_timer_close_complete(uv_handle_t* handle) {
  delete reinterpret_cast<uv_timer_t*>(handle);
}

// uv v0.11.23 has changed uv_timer_cb interface by removing status_code.
#if NAUV_UVVERSION < 0x000b17
void RunSteamAPICallback(uv_timer_t* handle, int status_code) {
#else
void RunSteamAPICallback(uv_timer_t* handle) {
#endif
  SteamAPI_RunCallbacks();
}

}  // namespace

SteamClient::SteamClient()
    : game_overlay_activated_(this, &SteamClient::OnGameOverlayActivated),
      steam_servers_connected_(this, &SteamClient::OnSteamServersConnected),
      steam_servers_disconnected_(this,
                                  &SteamClient::OnSteamServersDisconnected),
      steam_server_connect_failure_(this,
                                    &SteamClient::OnSteamServerConnectFailure),
      steam_shutdown_(this, &SteamClient::OnSteamShutdown),
      steam_persona_state_change_(this, &SteamClient::OnPeronaStateChange),
      avatar_image_loaded_(this, &SteamClient::OnAvatarImageLoaded),
      game_connected_friend_chat_msg_(
          this,
          &SteamClient::OnGameConnectedFriendChatMessage),
      dlc_installed_(this, &SteamClient::OnDLCInstalled),
      MicroTxnAuthorizationResponse_(this, &SteamClient::OnMicroTxnAuthorizationResponse) {}

SteamClient::~SteamClient() {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    delete observer_list_[i];
  }
  if (g_steam_client) {
    uv_timer_stop(g_steam_timer);
    uv_close(reinterpret_cast<uv_handle_t*>(g_steam_timer),
             on_timer_close_complete);
  }
}

SteamClient* SteamClient::GetInstance() {
  if (!g_steam_client) {
    g_steam_client = new SteamClient();
  }
  return g_steam_client;
}

void SteamClient::OnGameOverlayActivated(GameOverlayActivated_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnGameOverlayActivated(
        static_cast<bool>(callback->m_bActive));
  }
}

void SteamClient::OnSteamServersConnected(SteamServersConnected_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamServersConnected();
  }
}

void SteamClient::OnSteamServersDisconnected(
    SteamServersDisconnected_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamServersDisconnected();
  }
}

void SteamClient::OnSteamServerConnectFailure(
    SteamServerConnectFailure_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamServerConnectFailure(
        static_cast<int>(callback->m_eResult));
  }
}

void SteamClient::OnSteamShutdown(SteamShutdown_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnSteamShutdown();
  }
}

void SteamClient::OnPeronaStateChange(PersonaStateChange_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnPersonaStateChange(callback->m_ulSteamID,
                                            callback->m_nChangeFlags);
  }
}

void SteamClient::OnAvatarImageLoaded(AvatarImageLoaded_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnAvatarImageLoaded(
        callback->m_steamID.ConvertToUint64(), callback->m_iImage,
        callback->m_iTall, callback->m_iWide);
  }
}

void SteamClient::OnGameConnectedFriendChatMessage(
    GameConnectedFriendChatMsg_t* callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnGameConnectedFriendChatMessage(
        callback->m_steamIDUser.ConvertToUint64(), callback->m_iMessageID);
  }
}

void SteamClient::OnDLCInstalled(DlcInstalled_t *callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnDLCInstalled(
        callback->m_nAppID);
  }
}

void SteamClient::OnMicroTxnAuthorizationResponse(
                          MicroTxnAuthorizationResponse_t *callback) {
  for (size_t i = 0; i < observer_list_.size(); ++i) {
    observer_list_[i]->OnMicroTxnAuthorizationResponse(
        callback->m_unAppID, callback->m_ulOrderID,
        callback->m_bAuthorized);
  }
}

void SteamClient::StartSteamLoop() {
  if (g_steam_timer)
    return;
  SteamClient::GetInstance();
  g_steam_timer = new uv_timer_t();
  uv_timer_init(uv_default_loop(), g_steam_timer);
  uv_timer_start(g_steam_timer, &RunSteamAPICallback, 0, 100);
}

void SteamClient::AddObserver(Observer* observer) {
  if (std::find(observer_list_.begin(), observer_list_.end(), observer) ==
      observer_list_.end()) {
    observer_list_.push_back(observer);
  }
}

}  // namespace greenworks
<|endoftext|>


<commit_before>//
// Copyright (c) 2013 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_COMPONENTS_TRIANGLE_HPP
#define RJ_GAME_COMPONENTS_TRIANGLE_HPP

#include <rectojump/game/basic_entity.hpp>

#include <SFML/Graphics.hpp>

namespace rj
{
	class triangle : public basic_entity<sf::CircleShape>
	{

	public:
		triangle(const vec2f& pos) :
			basic_entity{pos, {-0.3f, 0.f}}
		{
			m_render_object.setPointCount(3);
			m_render_object.setRadius(15.f);
			m_render_object.setOrigin(7.5f, 7.5f);
		}

		float top_out() const noexcept override
		{return this->pos_y() - m_render_object.getRadius();}

		float bottom_out() const noexcept override
		{return this->pos_y() + m_render_object.getRadius();}

		float left_out() const noexcept override
		{return this->pos_x() - m_render_object.getRadius();}

		float right_out() const noexcept override
		{return this->pos_x() + m_render_object.getRadius();}

	private:
		void update(dur duration) override
		{m_render_object.move(m_velocity * duration);}
	};
}

#endif // RJ_GAME_COMPONENTS_TRIANGLE_HPP
<commit_msg>triangle is alway a deathtile<commit_after>//
// Copyright (c) 2013 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_COMPONENTS_TRIANGLE_HPP
#define RJ_GAME_COMPONENTS_TRIANGLE_HPP

#include <rectojump/game/basic_entity.hpp>

#include <SFML/Graphics.hpp>

namespace rj
{
	class triangle : public basic_entity<sf::CircleShape>
	{

	public:
		triangle(const vec2f& pos) :
			basic_entity{pos, {-0.3f, 0.f}}
		{
			m_render_object.setPointCount(3);
			m_render_object.setRadius(15.f);
			m_render_object.setOrigin(7.5f, 7.5f);
			this->set_propertie(entity_properties::death);
		}

		float top_out() const noexcept override
		{return this->pos_y() - m_render_object.getRadius();}

		float bottom_out() const noexcept override
		{return this->pos_y() + m_render_object.getRadius();}

		float left_out() const noexcept override
		{return this->pos_x() - m_render_object.getRadius();}

		float right_out() const noexcept override
		{return this->pos_x() + m_render_object.getRadius();}

	private:
		void update(dur duration) override
		{m_render_object.move(m_velocity * duration);}
	};
}

#endif // RJ_GAME_COMPONENTS_TRIANGLE_HPP
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*!
 * \file tvm/relay/backend/vm/inline_primitives.cc
 * \brief Ensure that primitives only appear in the call position.
 */

#include <tvm/relay/expr.h>
#include <tvm/relay/expr_functor.h>
#include <tvm/support/logging.h>
#include <tvm/relay/transform.h>
#include <tvm/runtime/vm.h>
#include <iostream>
#include <vector>

using namespace tvm::runtime;

namespace tvm {
namespace relay {
namespace vm {

// TODO(@jroesch): write verifier

/* This pass will eliminate primitives which have been lifted by the ANF
 * transform inlining them directly into call sites.
 *
 * This makes VM related code generation easier as the call target is always
 * a primitive function.
 *
 * let prim = fn(...) { ... };
 * prim(...)
 *
 * will become:
 *
 * (fn(...) { ... })(...)
 */
struct PrimitiveInliner : ExprMutator {
  IRModule module_;
  std::unordered_map<Var, Expr, ObjectHash, ObjectEqual> var_map;

  explicit PrimitiveInliner(const IRModule& module) : module_(module) {}

  Expr VisitExpr_(const LetNode* let_node) {
    var_map.insert({let_node->var, VisitExpr(let_node->value)});
    return ExprMutator::VisitExpr_(let_node);
  }

  Expr VisitExpr_(const CallNode* call) {
    Expr op = call->op;
    // For now just collapse the chain of variables to see if
    // they point to a primitive function.
    const VarNode* var_node;

    // Collapse a chain of let bindings
    //
    // let x = fn (..) { .. };
    // let y = x
    // let w = y
    // in w(...)
    while ((var_node = op.as<VarNode>())) {
      auto var = GetRef<Var>(var_node);
      DLOG(INFO) << "Var: " << var << std::endl;
      auto it = var_map.find(GetRef<Var>(var_node));
      if (it != var_map.end()) {
        op = it->second;
      } else {
        return ExprMutator::VisitExpr_(call);
      }
    }

    if (auto func = op.as<FunctionNode>()) {
      if (func->IsPrimitive()) {
        return CallNode::make(GetRef<Function>(func), call->args, call->attrs, call->type_args);
      }
    }

    if (auto global = op.as<GlobalVarNode>()) {
      return CallNode::make(GetRef<GlobalVar>(global), call->args, call->attrs, call->type_args);
    }

    return ExprMutator::VisitExpr_(call);
  }

  Expr VisitExpr_(const FunctionNode* func) {
    if (func->IsPrimitive()) {
      return GetRef<Function>(func);
    } else {
      return ExprMutator::VisitExpr_(func);
    }
  }

  IRModule Inline() {
    auto gvar_funcs = module_->functions;
    for (auto pair : gvar_funcs) {
      auto global = pair.first;
      auto base_func = pair.second;
      if (auto* n = base_func.as<FunctionNode>()) {
        auto func = GetRef<Function>(n);

        DLOG(INFO) << "Before inlining primitives: " << global
                   << std::endl << AsText(func, false);

        func = FunctionNode::make(func->params,
                                  VisitExpr(func->body),
                                  func->ret_type,
                                  func->type_params,
                                  func->attrs);
        module_->Add(global, func, true);

        DLOG(INFO) << "After inlining primitives: " << global
                   << std::endl << AsText(func, false);
      }
    }
    return module_;
  }
};

}  // namespace vm

namespace transform {

Pass InlinePrimitives() {
  runtime::TypedPackedFunc<IRModule(IRModule, PassContext)> pass_func =
    [=](IRModule m, PassContext pc) {
      return relay::vm::PrimitiveInliner(m).Inline();
  };
  auto inline_pass = CreateModulePass(pass_func, 1, "Inline", {});
  // Eliminate dead code for each function after inlining.
  return Sequential({inline_pass, DeadCodeElimination()}, "InlinePrimitives");
}

TVM_REGISTER_GLOBAL("relay._transform.InlinePrimitives")
.set_body_typed(InlinePrimitives);

}  // namespace transform

}  // namespace relay
}  // namespace tvm
<commit_msg>Make sure to visit the arguments of inlined functions (#4783)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*!
 * \file tvm/relay/backend/vm/inline_primitives.cc
 * \brief Ensure that primitives only appear in the call position.
 */

#include <tvm/relay/expr.h>
#include <tvm/relay/expr_functor.h>
#include <tvm/support/logging.h>
#include <tvm/relay/transform.h>
#include <tvm/runtime/vm.h>
#include <iostream>
#include <vector>

using namespace tvm::runtime;

namespace tvm {
namespace relay {
namespace vm {

// TODO(@jroesch): write verifier

/* This pass will eliminate primitives which have been lifted by the ANF
 * transform inlining them directly into call sites.
 *
 * This makes VM related code generation easier as the call target is always
 * a primitive function.
 *
 * let prim = fn(...) { ... };
 * prim(...)
 *
 * will become:
 *
 * (fn(...) { ... })(...)
 */
struct PrimitiveInliner : ExprMutator {
  IRModule module_;
  std::unordered_map<Var, Expr, ObjectHash, ObjectEqual> var_map;

  explicit PrimitiveInliner(const IRModule& module) : module_(module) {}

  Expr VisitExpr_(const LetNode* let_node) {
    var_map.insert({let_node->var, VisitExpr(let_node->value)});
    return ExprMutator::VisitExpr_(let_node);
  }

  Expr VisitExpr_(const CallNode* call) {
    Expr op = call->op;
    // For now just collapse the chain of variables to see if
    // they point to a primitive function.
    const VarNode* var_node;

    // Collapse a chain of let bindings
    //
    // let x = fn (..) { .. };
    // let y = x
    // let w = y
    // in w(...)
    while ((var_node = op.as<VarNode>())) {
      auto var = GetRef<Var>(var_node);
      DLOG(INFO) << "Var: " << var << std::endl;
      auto it = var_map.find(GetRef<Var>(var_node));
      if (it != var_map.end()) {
        op = it->second;
      } else {
        return ExprMutator::VisitExpr_(call);
      }
    }

    if (auto func = op.as<FunctionNode>()) {
      if (func->IsPrimitive()) {
        tvm::Array<Expr> call_args;
        for (auto arg : call->args) {
          auto new_arg = VisitExpr(arg);
          call_args.push_back(new_arg);
        }
        return CallNode::make(GetRef<Function>(func), call_args, call->attrs, call->type_args);
      }
    }

    if (auto global = op.as<GlobalVarNode>()) {
      tvm::Array<Expr> call_args;
      for (auto arg : call->args) {
        auto new_arg = VisitExpr(arg);
        call_args.push_back(new_arg);
      }
      return CallNode::make(GetRef<GlobalVar>(global), call_args, call->attrs, call->type_args);
    }

    return ExprMutator::VisitExpr_(call);
  }

  Expr VisitExpr_(const FunctionNode* func) {
    if (func->IsPrimitive()) {
      return GetRef<Function>(func);
    } else {
      return ExprMutator::VisitExpr_(func);
    }
  }

  IRModule Inline() {
    auto gvar_funcs = module_->functions;
    for (auto pair : gvar_funcs) {
      auto global = pair.first;
      auto base_func = pair.second;
      if (auto* n = base_func.as<FunctionNode>()) {
        auto func = GetRef<Function>(n);

        DLOG(INFO) << "Before inlining primitives: " << global
                   << std::endl << AsText(func, false);

        func = FunctionNode::make(func->params,
                                  VisitExpr(func->body),
                                  func->ret_type,
                                  func->type_params,
                                  func->attrs);
        module_->Add(global, func, true);

        DLOG(INFO) << "After inlining primitives: " << global
                   << std::endl << AsText(func, false);
      }
    }
    return module_;
  }
};

}  // namespace vm

namespace transform {

Pass InlinePrimitives() {
  runtime::TypedPackedFunc<IRModule(IRModule, PassContext)> pass_func =
    [=](IRModule m, PassContext pc) {
      return relay::vm::PrimitiveInliner(m).Inline();
  };
  auto inline_pass = CreateModulePass(pass_func, 1, "Inline", {});
  // Eliminate dead code for each function after inlining.
  return Sequential({inline_pass, DeadCodeElimination()}, "InlinePrimitives");
}

TVM_REGISTER_GLOBAL("relay._transform.InlinePrimitives")
.set_body_typed(InlinePrimitives);

}  // namespace transform

}  // namespace relay
}  // namespace tvm
<|endoftext|>


<commit_before>#include <coap/decoder.h>
#include <coap/decoder/streambuf.hpp>
#include <coap/decoder/subject-core.hpp>

#include "unit-test.h"

using namespace moducom;

static estd::span<const uint8_t> in(buffer_16bit_delta, sizeof(buffer_16bit_delta));
typedef estd::experimental::ispanbuf streambuf_type;

static void test_basic_decode()
{
    coap::Decoder decoder;
    coap::Decoder::Context context(in, true);

    // This one's a bit tricky because VisualDSP won't let a 2nd "decoder.cpp"
    // into the project, even at different folder levels
    //decoder.process_iterate(context);
}

static void test_streambuf_decode()
{
    // DEBT: Quite clumsy streambuf char requirement vs coap uint8_t requirement.
    estd::span<char> in((char*)buffer_16bit_delta, sizeof(buffer_16bit_delta));
    coap::StreambufDecoder<streambuf_type> decoder(in);

    bool eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::Header, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::HeaderDone, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::TokenDone, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::OptionsStart, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    // DEBT: Don't like repeatedly kicking top-level CoAP parser to do clicky decode of
    // option.  Would be better to know to use option decoder and otherwise fast-forward option.
    // Both are non-obvious, but at least the latter is more organized
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());

    TEST_ASSERT_EQUAL(1, decoder.option_length());

#if !FEATURE_MCCOAP_SUCCINCT_OPTIONDECODE
    TEST_ASSERT_EQUAL(0, decoder.option_number());

    TEST_ASSERT_EQUAL(coap::OptionDecoder::OptionLengthDone, decoder.option_decoder().state());
    //decoder.option();
    //TEST_ASSERT_EQUAL(3, decoder.option()[0]);

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());
#endif
    TEST_ASSERT_EQUAL(coap::OptionDecoder::ValueStart, decoder.option_decoder().state());

    TEST_ASSERT_EQUAL(270, decoder.option_number());
    TEST_ASSERT_EQUAL(3, decoder.option()[0]);

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::OptionDecoder::OptionValueDone, decoder.option_decoder().state());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());
    TEST_ASSERT_EQUAL(coap::OptionDecoder::ValueStart, decoder.option_decoder().state());
    TEST_ASSERT_EQUAL(271, decoder.option_number());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());
    TEST_ASSERT_EQUAL(coap::OptionDecoder::OptionValueDone, decoder.option_decoder().state());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::OptionsDone, decoder.state());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::Payload, decoder.state());
}

struct Context
{
    int counter;
};

struct Listener
{
    void notify(coap::event::header e, Context& context)
    {
        context.counter++;
    }

    void notify(coap::event::token e, Context& context)
    {
        context.counter++;
    }

    void notify(coap::event::option_start, Context&) {}
    void notify(coap::event::option_completed, Context&) {}

    void notify(coap::event::option e, Context& context)
    {
        if(context.counter++ == 2)
            TEST_ASSERT_EQUAL(270, e.option_number);
        else
            TEST_ASSERT_EQUAL(271, e.option_number);
    }

    void notify(coap::event::streambuf_payload<streambuf_type> e, Context& context)
    {
        context.counter++;
    }

    void notify(coap::event::completed e, Context& context)
    {
        context.counter++;
    }
};

static void test_decode_and_notify()
{
    // DEBT: Quite clumsy streambuf char requirement vs coap uint8_t requirement.
    estd::span<char> in((char*)buffer_16bit_delta, sizeof(buffer_16bit_delta));
    coap::StreambufDecoder<streambuf_type> decoder(in);
    Listener l;
    Context context;

    context.counter = 0;

    while(!coap::decode_and_notify(decoder, l, context));

    // runs once more at end to trigger completed event, don't remember
    // exactly why we have to do it that way - it has something to do with
    // giving consumer chance to fully consume payload
    coap::decode_and_notify(decoder, l, context);

    TEST_ASSERT_EQUAL_INT(6, context.counter);
}

#ifdef ESP_IDF_TESTING
TEST_CASE("decoder tests", "[decoder]")
#else
void test_decoder()
#endif
{
    RUN_TEST(test_basic_decode);
    RUN_TEST(test_streambuf_decode);
    RUN_TEST(test_decode_and_notify);
}<commit_msg>Ensuring token and header at least get remembered<commit_after>#include <coap/decoder.h>
#include <coap/decoder/streambuf.hpp>
#include <coap/decoder/subject-core.hpp>

#include "unit-test.h"

using namespace moducom;

static estd::span<const uint8_t> in(buffer_16bit_delta, sizeof(buffer_16bit_delta));
typedef estd::experimental::ispanbuf streambuf_type;

static void test_basic_decode()
{
    coap::Decoder decoder;
    coap::Decoder::Context context(in, true);

    // This one's a bit tricky because VisualDSP won't let a 2nd "decoder.cpp"
    // into the project, even at different folder levels
    //decoder.process_iterate(context);
}

static void test_streambuf_decode()
{
    // DEBT: Quite clumsy streambuf char requirement vs coap uint8_t requirement.
    estd::span<char> in((char*)buffer_16bit_delta, sizeof(buffer_16bit_delta));
    coap::StreambufDecoder<streambuf_type> decoder(in);

    bool eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::Header, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::HeaderDone, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::TokenDone, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::OptionsStart, decoder.state());

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    // DEBT: Don't like repeatedly kicking top-level CoAP parser to do clicky decode of
    // option.  Would be better to know to use option decoder and otherwise fast-forward option.
    // Both are non-obvious, but at least the latter is more organized
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());

    TEST_ASSERT_EQUAL(1, decoder.option_length());

#if !FEATURE_MCCOAP_SUCCINCT_OPTIONDECODE
    TEST_ASSERT_EQUAL(0, decoder.option_number());

    TEST_ASSERT_EQUAL(coap::OptionDecoder::OptionLengthDone, decoder.option_decoder().state());
    //decoder.option();
    //TEST_ASSERT_EQUAL(3, decoder.option()[0]);

    eol = decoder.process_iterate_streambuf();

    TEST_ASSERT(!eol);
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());
#endif
    TEST_ASSERT_EQUAL(coap::OptionDecoder::ValueStart, decoder.option_decoder().state());

    TEST_ASSERT_EQUAL(270, decoder.option_number());
    TEST_ASSERT_EQUAL(3, decoder.option()[0]);

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::OptionDecoder::OptionValueDone, decoder.option_decoder().state());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());
    TEST_ASSERT_EQUAL(coap::OptionDecoder::ValueStart, decoder.option_decoder().state());
    TEST_ASSERT_EQUAL(271, decoder.option_number());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::Options, decoder.state());
    TEST_ASSERT_EQUAL(coap::OptionDecoder::OptionValueDone, decoder.option_decoder().state());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::OptionsDone, decoder.state());

    TEST_ASSERT(!decoder.process_iterate_streambuf());
    TEST_ASSERT_EQUAL(coap::Decoder::Payload, decoder.state());
}

struct Context : coap::TokenAndHeaderContext<true>
{
    int counter;
};

struct Listener
{
    void notify(coap::event::header e, Context& context)
    {
        context.header(e.h);
        context.counter++;
    }

    void notify(coap::event::token e, Context& context)
    {
        context.token(e.chunk);
        context.counter++;
    }

    void notify(coap::event::option_start, Context&) {}
    void notify(coap::event::option_completed, Context&) {}

    void notify(coap::event::option e, Context& context)
    {
        if(context.counter++ == 2)
            TEST_ASSERT_EQUAL(270, e.option_number);
        else
            TEST_ASSERT_EQUAL(271, e.option_number);
    }

    void notify(coap::event::streambuf_payload<streambuf_type> e, Context& context)
    {
        context.counter++;
    }

    void notify(coap::event::completed e, Context& context)
    {
        context.counter++;
    }
};

static void test_decode_and_notify()
{
    // DEBT: Quite clumsy streambuf char requirement vs coap uint8_t requirement.
    estd::span<char> in((char*)buffer_16bit_delta, sizeof(buffer_16bit_delta));
    coap::StreambufDecoder<streambuf_type> decoder(in);
    Listener l;
    Context context;

    context.counter = 0;

    while(!coap::decode_and_notify(decoder, l, context));

    // runs once more at end to trigger completed event, don't remember
    // exactly why we have to do it that way - it has something to do with
    // giving consumer chance to fully consume payload
    coap::decode_and_notify(decoder, l, context);

    TEST_ASSERT_EQUAL_INT(6, context.counter);
}

#ifdef ESP_IDF_TESTING
TEST_CASE("decoder tests", "[decoder]")
#else
void test_decoder()
#endif
{
    RUN_TEST(test_basic_decode);
    RUN_TEST(test_streambuf_decode);
    RUN_TEST(test_decode_and_notify);
}<|endoftext|>