<commit_before>/*
    Copyright (C) 1999 by Andrew Zabolotny

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>

#define CS_SYSDEF_PROVIDE_PATH
#define CS_SYSDEF_PROVIDE_GETOPT
#include "cssysdef.h"
#include "cssys/csshlib.h"
#include "csutil/scf.h"
#include "csutil/cfgfile.h"

CS_IMPLEMENT_APPLICATION

char *programversion = "3";
char *programname;

static struct option long_options[] =
{
  {"help", no_argument, 0, 'h'},
  {"register", no_argument, 0, 'r'},
  {"unregister", no_argument, 0, 'u'},
  {"version", no_argument, 0, 'V'},
  {"verbose", no_argument, 0, 'v'},
  {0, no_argument, 0, 0}
};

static int display_help ()
{
  printf ("Crystal Space SCF object registration utility v%s\n", programversion);
  printf ("Copyright (C) 1999 by Andrew Zabolotny <bit@eltech.ru>\n\n");
  printf ("Usage: %s {option/s} [plug-in module] [...]\n\n", programname);
  printf ("By default the program will register the SCF components contained\n");
  printf ("in the plug-in module passed on command line. Registration occurs\n" );
  printf ("in the SCF registration file scf.cfg.\n\n");
  printf ("  -r   --register    Register SCF components contained in file #\n");
  printf ("  -u   --unregister  Unregister SCF components contained in file #\n");
  printf ("  -h   --help        Display this help text\n");
  printf ("  -v   --verbose     Comment on what's happening\n");
  printf ("  -V   --version     Display program version\n");
  return 1;
}

static bool verbose = false;

static bool RegisterServer (char *SharedLibraryFilename, csConfigFile &cfg,
  bool Register)
{
  static bool DisplayedHeader = false;
  if (!DisplayedHeader && !verbose)
  {
    DisplayedHeader = true;
    printf ("Library | Class ID                     | Description\n");
    printf ("--------+------------------------------+---------------------------------------\n");
  }

  if (verbose)
  {
    printf ("Loading shared library %s ...", SharedLibraryFilename);
    fflush (stdout);
  } /* endif */

  char name [200], base [200], filename[200];
  char *tmp, *tmp2;

  // copy file name
  strcpy (filename, SharedLibraryFilename);

  // find beginning of base file name
  tmp = filename + strlen (filename);
  while ((tmp > filename)
      && (tmp [-1] != '/')
      && (tmp [-1] != PATH_SEPARATOR))
    tmp--;
  if ((tmp [0] == 'l')
   && (tmp [1] == 'i')
   && (tmp [2] == 'b'))
    tmp += 3;

  // remove extension
  if ((tmp2 = strchr (tmp, '.')))
    *tmp2 = 0;

  // copy base file name and compute SCF function name
  strcpy (base, tmp);
  strcpy (name, base);
  strcat (name, "_scfInitialize");

  csLibraryHandle Handle = csFindLoadLibrary (filename);
  if (!Handle)
    Handle = csLoadLibrary (filename);

  if (!Handle)
  {
    if (verbose)
      printf (" FAILED\n");
    else
      printf ("ERROR: Failed to load library \"%s\"\n", SharedLibraryFilename);
    fflush (stdout);
    return false;
  } /* endif */

  if (verbose)
  {
    printf ("OK, handle = %08X\n", (int)Handle);
    fflush (stdout);
  } /* endif */

  if (verbose)
  {
    printf ("Looking for \"%s\" entry ...", name);
    fflush (stdout);
  } /* endif */

  // This is the prototype for the only function that
  // a shared library should export
  typedef scfClassInfo *(*scfInitializeFunc) (iSCF*);
  scfInitializeFunc func = (scfInitializeFunc)csGetLibrarySymbol (Handle, name);
  if (!func)
  {
    if (verbose)
      printf (" FAILED\n");
    else
      printf ("ERROR: Failed to find entry \"%s\" in library \"%s\"\n", name, SharedLibraryFilename);
    fflush (stdout);
    return false;
  } /* endif */

  if (verbose)
  {
    printf ("OK, address = %08lX\n", (unsigned long)func);
    fflush (stdout);
  } /* endif */

  scfClassInfo *ClassTable = func (NULL);
  while (ClassTable->ClassID)
  {
    if (verbose)
      printf ("Library:      %s\nClassID:      %s\nDescription:  %s\nDependencies: %s\n",
        SharedLibraryFilename, ClassTable->ClassID, ClassTable->Description,
        ClassTable->Dependencies ? ClassTable->Dependencies : "<none>");
    else
    {
      char lib [8+1], cls [30+1], desc [39+1];
      strncpy (lib, base, sizeof (lib) - 1);
      lib [sizeof (lib) - 1] = 0;
      strncpy (cls, ClassTable->ClassID, sizeof (cls) - 1);
      cls [sizeof (cls) - 1] = 0;
      strncpy (desc, ClassTable->Description, sizeof (desc) - 1);
      desc [sizeof (desc) - 1] = 0;

      printf ("%-8s|%-30s|%s\n", lib, cls, desc);
    }

    if (Register)
    {
      char text [1000];
      bool AddComment = !cfg.KeyExists (ClassTable->ClassID);
      strcpy (text, filename);
      if (ClassTable->Dependencies)
      {
        strcat (text, ":");
        strcat (text, ClassTable->Dependencies);
      }
      cfg.SetStr (ClassTable->ClassID, text);
      if (AddComment)
        cfg.SetComment (ClassTable->ClassID, ClassTable->Description);
    }
    else
      cfg.DeleteKey (ClassTable->ClassID);
    ClassTable++;
  }

  if (verbose)
  {
    printf ("Unloading library \"%s\"...", SharedLibraryFilename);
    fflush (stdout);
  }

  if (!csUnloadLibrary (Handle))
  {
    if (verbose)
      printf (" FAILED\n");
    else
      printf ("WARNING: Unable to unload library \"%s\"!\n", SharedLibraryFilename);
  }
  else if (verbose)
    printf ("OK\n");

  if (verbose)
    printf ("Library \"%s\" %sregistered.\n", SharedLibraryFilename,
      Register ? "" : "de");
  fflush (stdout);
  return true;
}

int main (int argc, char *argv[])
{
#if defined (__EMX__)	// Expand wildcards on OS/2+GCC+EMX
  _wildcard (&argc, &argv);
#endif

  int operation = 1;
  programname = argv [0];

#ifndef COMP_BC
  int c;
  while ((c = getopt_long (argc, argv, "ruhvV", long_options, NULL)) != EOF)
    switch (c)
    {
      case '?':
        // unknown option
        return -1;
      case 'r':
        operation = 1;
        break;
      case 'u':
        operation = 2;
        break;
      case 'h':
        return display_help ();
      case 'v':
        verbose = true;
        break;
      case 'V':
        printf ("%s version %s\n\n", programname, programversion);
        printf ("This program is distributed in the hope that it will be useful,\n");
        printf ("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
        printf ("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
        printf ("GNU Library General Public License for more details.\n");
        return 0;
    } /* endswitch */
#else
  int optind=1;
#endif

  csConfigFile cfg ("scf.cfg");

  // Interpret the non-option arguments as file names
  bool did_something = false;
  for (; optind < argc; ++optind)
    switch (operation)
    {
      case 1:
        did_something = true;
        RegisterServer (argv [optind], cfg, true);
        break;
      case 2:
        did_something = true;
        RegisterServer (argv [optind], cfg, false);
        break;
    } /* endswitch */

  if (!did_something)
    return display_help ();

  cfg.Save ("scf.cfg");

  return 0;
}
<commit_msg>reverted my latest change to scfreg<commit_after>/*
    Copyright (C) 1999 by Andrew Zabolotny

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>

#define CS_SYSDEF_PROVIDE_PATH
#define CS_SYSDEF_PROVIDE_GETOPT
#include "cssysdef.h"
#include "cssys/csshlib.h"
#include "csutil/scf.h"
#include "csutil/cfgfile.h"

CS_IMPLEMENT_APPLICATION

char *programversion = "3";
char *programname;

static struct option long_options[] =
{
  {"help", no_argument, 0, 'h'},
  {"register", no_argument, 0, 'r'},
  {"unregister", no_argument, 0, 'u'},
  {"version", no_argument, 0, 'V'},
  {"verbose", no_argument, 0, 'v'},
  {0, no_argument, 0, 0}
};

static int display_help ()
{
  printf ("Crystal Space SCF object registration utility v%s\n", programversion);
  printf ("Copyright (C) 1999 by Andrew Zabolotny <bit@eltech.ru>\n\n");
  printf ("Usage: %s {option/s} [plug-in module] [...]\n\n", programname);
  printf ("By default the program will register the SCF components contained\n");
  printf ("in the plug-in module passed on command line. Registration occurs\n" );
  printf ("in the SCF registration file scf.cfg.\n\n");
  printf ("  -r   --register    Register SCF components contained in file #\n");
  printf ("  -u   --unregister  Unregister SCF components contained in file #\n");
  printf ("  -h   --help        Display this help text\n");
  printf ("  -v   --verbose     Comment on what's happening\n");
  printf ("  -V   --version     Display program version\n");
  return 1;
}

static bool verbose = false;

static bool RegisterServer (char *SharedLibraryFilename, csConfigFile &cfg,
  bool Register)
{
  static bool DisplayedHeader = false;
  if (!DisplayedHeader && !verbose)
  {
    DisplayedHeader = true;
    printf ("Library | Class ID                     | Description\n");
    printf ("--------+------------------------------+---------------------------------------\n");
  }

  if (verbose)
  {
    printf ("Loading shared library %s ...", SharedLibraryFilename);
    fflush (stdout);
  } /* endif */

  char name [200], base [200];
  char *tmp = SharedLibraryFilename + strlen (SharedLibraryFilename);
  while ((tmp > SharedLibraryFilename)
      && (tmp [-1] != '/')
      && (tmp [-1] != PATH_SEPARATOR))
    tmp--;

  if ((tmp [0] == 'l')
   && (tmp [1] == 'i')
   && (tmp [2] == 'b'))
    tmp += 3;
  strcpy (base, tmp);
  if ((tmp = strchr (base, '.')))
    *tmp = 0;
  strcpy (name, base);
  strcat (name, "_scfInitialize");

  csLibraryHandle Handle = csFindLoadLibrary (base);
  if (!Handle)
    Handle = csLoadLibrary (base);

  if (!Handle)
  {
    if (verbose)
      printf (" FAILED\n");
    else
      printf ("ERROR: Failed to load library \"%s\"\n", SharedLibraryFilename);
    fflush (stdout);
    return false;
  } /* endif */

  if (verbose)
  {
    printf ("OK, handle = %08X\n", (int)Handle);
    fflush (stdout);
  } /* endif */

  if (verbose)
  {
    printf ("Looking for \"%s\" entry ...", name);
    fflush (stdout);
  } /* endif */

  // This is the prototype for the only function that
  // a shared library should export
  typedef scfClassInfo *(*scfInitializeFunc) (iSCF*);
  scfInitializeFunc func = (scfInitializeFunc)csGetLibrarySymbol (Handle, name);
  if (!func)
  {
    if (verbose)
      printf (" FAILED\n");
    else
      printf ("ERROR: Failed to find entry \"%s\" in library \"%s\"\n", name, SharedLibraryFilename);
    fflush (stdout);
    return false;
  } /* endif */

  if (verbose)
  {
    printf ("OK, address = %08lX\n", (unsigned long)func);
    fflush (stdout);
  } /* endif */

  scfClassInfo *ClassTable = func (NULL);
  while (ClassTable->ClassID)
  {
    if (verbose)
      printf ("Library:      %s\nClassID:      %s\nDescription:  %s\nDependencies: %s\n",
        SharedLibraryFilename, ClassTable->ClassID, ClassTable->Description,
        ClassTable->Dependencies ? ClassTable->Dependencies : "<none>");
    else
    {
      char lib [8+1], cls [30+1], desc [39+1];
      strncpy (lib, base, sizeof (lib) - 1);
      lib [sizeof (lib) - 1] = 0;
      strncpy (cls, ClassTable->ClassID, sizeof (cls) - 1);
      cls [sizeof (cls) - 1] = 0;
      strncpy (desc, ClassTable->Description, sizeof (desc) - 1);
      desc [sizeof (desc) - 1] = 0;

      printf ("%-8s|%-30s|%s\n", lib, cls, desc);
    }

    if (Register)
    {
      char text [1000];
      bool AddComment = !cfg.KeyExists (ClassTable->ClassID);
      strcpy (text, base);
      if (ClassTable->Dependencies)
      {
        strcat (text, ":");
        strcat (text, ClassTable->Dependencies);
      }
      cfg.SetStr (ClassTable->ClassID, text);
      if (AddComment)
        cfg.SetComment (ClassTable->ClassID, ClassTable->Description);
    }
    else
      cfg.DeleteKey (ClassTable->ClassID);
    ClassTable++;
  }

  if (verbose)
  {
    printf ("Unloading library \"%s\"...", SharedLibraryFilename);
    fflush (stdout);
  }

  if (!csUnloadLibrary (Handle))
  {
    if (verbose)
      printf (" FAILED\n");
    else
      printf ("WARNING: Unable to unload library \"%s\"!\n", SharedLibraryFilename);
  }
  else if (verbose)
    printf ("OK\n");

  if (verbose)
    printf ("Library \"%s\" %sregistered.\n", SharedLibraryFilename,
      Register ? "" : "de");
  fflush (stdout);
  return true;
}

int main (int argc, char *argv[])
{
#if defined (__EMX__)	// Expand wildcards on OS/2+GCC+EMX
  _wildcard (&argc, &argv);
#endif

  int operation = 1;
  programname = argv [0];

#ifndef COMP_BC
  int c;
  while ((c = getopt_long (argc, argv, "ruhvV", long_options, NULL)) != EOF)
    switch (c)
    {
      case '?':
        // unknown option
        return -1;
      case 'r':
        operation = 1;
        break;
      case 'u':
        operation = 2;
        break;
      case 'h':
        return display_help ();
      case 'v':
        verbose = true;
        break;
      case 'V':
        printf ("%s version %s\n\n", programname, programversion);
        printf ("This program is distributed in the hope that it will be useful,\n");
        printf ("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
        printf ("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
        printf ("GNU Library General Public License for more details.\n");
        return 0;
    } /* endswitch */
#else
  int optind=1;
#endif

  csConfigFile cfg ("scf.cfg");

  // Interpret the non-option arguments as file names
  bool did_something = false;
  for (; optind < argc; ++optind)
    switch (operation)
    {
      case 1:
        did_something = true;
        RegisterServer (argv [optind], cfg, true);
        break;
      case 2:
        did_something = true;
        RegisterServer (argv [optind], cfg, false);
        break;
    } /* endswitch */

  if (!did_something)
    return display_help ();

  cfg.Save ("scf.cfg");

  return 0;
}
<|endoftext|>


<commit_before>#include "hg.h"
#include "lazy.h"
#include "fdict.h"
#include "tdict.h"

#include "lm/enumerate_vocab.hh"
#include "lm/model.hh"
#include "search/config.hh"
#include "search/context.hh"
#include "search/edge.hh"
#include "search/edge_queue.hh"
#include "search/vertex.hh"
#include "search/vertex_generator.hh"
#include "util/exception.hh"

#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

#include <iostream>
#include <vector>

namespace {

struct MapVocab : public lm::EnumerateVocab {
  public:
    MapVocab() {}

    // Do not call after Lookup.
    void Add(lm::WordIndex index, const StringPiece &str) {
      const WordID cdec_id = TD::Convert(str.as_string());
      if (cdec_id >= out_.size()) out_.resize(cdec_id + 1);
      out_[cdec_id] = index;
    }

    // Assumes Add has been called and will never be called again.
    lm::WordIndex FromCDec(WordID id) const {
      return out_[out_.size() > id ? id : 0];
    }

  private:
    std::vector<lm::WordIndex> out_;
};

class LazyBase {
  public:
    LazyBase(const std::vector<weight_t> &weights) :
      cdec_weights_(weights),
      weights_(weights[FD::Convert("KLanguageModel")], weights[FD::Convert("KLanguageModel_OOV")], weights[FD::Convert("WordPenalty")]) {
      std::cerr << "Weights KLanguageModel " << weights_.LM() << " KLanguageModel_OOV " << weights_.OOV() << " WordPenalty " << weights_.WordPenalty() << std::endl;
    }

    virtual ~LazyBase() {}

    virtual void Search(unsigned int pop_limit, const Hypergraph &hg) const = 0;

    static LazyBase *Load(const char *model_file, const std::vector<weight_t> &weights);

  protected:
    lm::ngram::Config GetConfig() {
      lm::ngram::Config ret;
      ret.enumerate_vocab = &vocab_;
      return ret;
    }

    MapVocab vocab_;

    const std::vector<weight_t> &cdec_weights_;

    const search::Weights weights_;
};

template <class Model> class Lazy : public LazyBase {
  public:
    Lazy(const char *model_file, const std::vector<weight_t> &weights) : LazyBase(weights), m_(model_file, GetConfig()) {}

    void Search(unsigned int pop_limit, const Hypergraph &hg) const;

  private:
    unsigned char ConvertEdge(const search::Context<Model> &context, bool final, search::Vertex *vertices, const Hypergraph::Edge &in, search::PartialEdge &out) const;

    const Model m_;
};

LazyBase *LazyBase::Load(const char *model_file, const std::vector<weight_t> &weights) {
  lm::ngram::ModelType model_type;
  if (!lm::ngram::RecognizeBinary(model_file, model_type)) model_type = lm::ngram::PROBING;
  switch (model_type) {
    case lm::ngram::PROBING:
      return new Lazy<lm::ngram::ProbingModel>(model_file, weights);
    case lm::ngram::REST_PROBING:
      return new Lazy<lm::ngram::RestProbingModel>(model_file, weights);
    default:
      UTIL_THROW(util::Exception, "Sorry this lm type isn't supported yet.");
  }
}

void PrintFinal(const Hypergraph &hg, const search::Final &final) {
  const std::vector<WordID> &words = static_cast<const Hypergraph::Edge*>(final.GetNote().vp)->rule_->e();
  boost::array<const search::Final*, search::kMaxArity>::const_iterator child(final.Children().begin());
  for (std::vector<WordID>::const_iterator i = words.begin(); i != words.end(); ++i) {
    if (*i > 0) {
      std::cout << TD::Convert(*i) << ' ';
    } else {
      PrintFinal(hg, **child++);
    }
  }
}

template <class Model> void Lazy<Model>::Search(unsigned int pop_limit, const Hypergraph &hg) const {
  boost::scoped_array<search::Vertex> out_vertices(new search::Vertex[hg.nodes_.size()]);
  search::Config config(weights_, pop_limit);
  search::Context<Model> context(config, m_);

  for (unsigned int i = 0; i < hg.nodes_.size() - 1; ++i) {
    search::EdgeQueue queue(context.PopLimit());
    const Hypergraph::EdgesVector &down_edges = hg.nodes_[i].in_edges_;
    for (unsigned int j = 0; j < down_edges.size(); ++j) {
      unsigned int edge_index = down_edges[j];
      unsigned char arity = ConvertEdge(context, i == hg.nodes_.size() - 2, out_vertices.get(), hg.edges_[edge_index], queue.InitializeEdge());
      search::Note note;
      note.vp = &hg.edges_[edge_index];
      if (arity != 255) queue.AddEdge(arity, note);
    }
    search::VertexGenerator vertex_gen(context, out_vertices[i]);
    queue.Search(context, vertex_gen);
  }
  const search::Final *top = out_vertices[hg.nodes_.size() - 2].BestChild();
  if (!top) {
    std::cout << "NO PATH FOUND" << std::endl;
  } else {
    PrintFinal(hg, *top);
    std::cout << "||| " << top->Bound() << std::endl;
  }
}

template <class Model> unsigned char Lazy<Model>::ConvertEdge(const search::Context<Model> &context, bool final, search::Vertex *vertices, const Hypergraph::Edge &in, search::PartialEdge &out) const {
  const std::vector<WordID> &e = in.rule_->e();
  std::vector<lm::WordIndex> words;
  unsigned int terminals = 0;
  unsigned char nt = 0;
  for (std::vector<WordID>::const_iterator word = e.begin(); word != e.end(); ++word) {
    if (*word <= 0) {
      out.nt[nt] = vertices[in.tail_nodes_[-*word]].RootPartial();
      if (out.nt[nt].Empty()) return 255;
      ++nt;
      words.push_back(lm::kMaxWordIndex);
    } else {
      ++terminals;
      words.push_back(vocab_.FromCDec(*word));
    }
  }
  for (unsigned char fill = nt; fill < search::kMaxArity; ++fill) {
    out.nt[nt] = search::kBlankPartialVertex;
  }

  if (final) {
    words.push_back(m_.GetVocabulary().EndSentence());
  }

  out.score = in.rule_->GetFeatureValues().dot(cdec_weights_);
  out.score -= static_cast<float>(terminals) * context.GetWeights().WordPenalty() / M_LN10;
  out.score += search::ScoreRule(context, words, final, out.between);
  return nt;
}

boost::scoped_ptr<LazyBase> AwfulGlobalLazy;

} // namespace

void PassToLazy(const char *model_file, const std::vector<weight_t> &weights, unsigned int pop_limit, const Hypergraph &hg) {
  if (!AwfulGlobalLazy.get()) {
    std::cerr << "Pop limit " << pop_limit << std::endl;
    AwfulGlobalLazy.reset(LazyBase::Load(model_file, weights));
  }
  AwfulGlobalLazy->Search(pop_limit, hg);
}
<commit_msg>Fix segfault, accurate decoding<commit_after>#include "hg.h"
#include "lazy.h"
#include "fdict.h"
#include "tdict.h"

#include "lm/enumerate_vocab.hh"
#include "lm/model.hh"
#include "search/config.hh"
#include "search/context.hh"
#include "search/edge.hh"
#include "search/edge_queue.hh"
#include "search/vertex.hh"
#include "search/vertex_generator.hh"
#include "util/exception.hh"

#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

#include <iostream>
#include <vector>

namespace {

struct MapVocab : public lm::EnumerateVocab {
  public:
    MapVocab() {}

    // Do not call after Lookup.
    void Add(lm::WordIndex index, const StringPiece &str) {
      const WordID cdec_id = TD::Convert(str.as_string());
      if (cdec_id >= out_.size()) out_.resize(cdec_id + 1);
      out_[cdec_id] = index;
    }

    // Assumes Add has been called and will never be called again.
    lm::WordIndex FromCDec(WordID id) const {
      return out_[out_.size() > id ? id : 0];
    }

  private:
    std::vector<lm::WordIndex> out_;
};

class LazyBase {
  public:
    LazyBase(const std::vector<weight_t> &weights) :
      cdec_weights_(weights),
      weights_(weights[FD::Convert("KLanguageModel")], weights[FD::Convert("KLanguageModel_OOV")], weights[FD::Convert("WordPenalty")]) {
      std::cerr << "Weights KLanguageModel " << weights_.LM() << " KLanguageModel_OOV " << weights_.OOV() << " WordPenalty " << weights_.WordPenalty() << std::endl;
    }

    virtual ~LazyBase() {}

    virtual void Search(unsigned int pop_limit, const Hypergraph &hg) const = 0;

    static LazyBase *Load(const char *model_file, const std::vector<weight_t> &weights);

  protected:
    lm::ngram::Config GetConfig() {
      lm::ngram::Config ret;
      ret.enumerate_vocab = &vocab_;
      return ret;
    }

    MapVocab vocab_;

    const std::vector<weight_t> &cdec_weights_;

    const search::Weights weights_;
};

template <class Model> class Lazy : public LazyBase {
  public:
    Lazy(const char *model_file, const std::vector<weight_t> &weights) : LazyBase(weights), m_(model_file, GetConfig()) {}

    void Search(unsigned int pop_limit, const Hypergraph &hg) const;

  private:
    unsigned char ConvertEdge(const search::Context<Model> &context, bool final, search::Vertex *vertices, const Hypergraph::Edge &in, search::PartialEdge &out) const;

    const Model m_;
};

LazyBase *LazyBase::Load(const char *model_file, const std::vector<weight_t> &weights) {
  lm::ngram::ModelType model_type;
  if (!lm::ngram::RecognizeBinary(model_file, model_type)) model_type = lm::ngram::PROBING;
  switch (model_type) {
    case lm::ngram::PROBING:
      return new Lazy<lm::ngram::ProbingModel>(model_file, weights);
    case lm::ngram::REST_PROBING:
      return new Lazy<lm::ngram::RestProbingModel>(model_file, weights);
    default:
      UTIL_THROW(util::Exception, "Sorry this lm type isn't supported yet.");
  }
}

void PrintFinal(const Hypergraph &hg, const search::Final &final) {
  const std::vector<WordID> &words = static_cast<const Hypergraph::Edge*>(final.GetNote().vp)->rule_->e();
  boost::array<const search::Final*, search::kMaxArity>::const_iterator child(final.Children().begin());
  for (std::vector<WordID>::const_iterator i = words.begin(); i != words.end(); ++i) {
    if (*i > 0) {
      std::cout << TD::Convert(*i) << ' ';
    } else {
      PrintFinal(hg, **child++);
    }
  }
}

template <class Model> void Lazy<Model>::Search(unsigned int pop_limit, const Hypergraph &hg) const {
  boost::scoped_array<search::Vertex> out_vertices(new search::Vertex[hg.nodes_.size()]);
  search::Config config(weights_, pop_limit);
  search::Context<Model> context(config, m_);

  for (unsigned int i = 0; i < hg.nodes_.size() - 1; ++i) {
    search::EdgeQueue queue(context.PopLimit());
    const Hypergraph::EdgesVector &down_edges = hg.nodes_[i].in_edges_;
    for (unsigned int j = 0; j < down_edges.size(); ++j) {
      unsigned int edge_index = down_edges[j];
      unsigned char arity = ConvertEdge(context, i == hg.nodes_.size() - 2, out_vertices.get(), hg.edges_[edge_index], queue.InitializeEdge());
      search::Note note;
      note.vp = &hg.edges_[edge_index];
      if (arity != 255) queue.AddEdge(arity, note);
    }
    search::VertexGenerator vertex_gen(context, out_vertices[i]);
    queue.Search(context, vertex_gen);
  }
  const search::Final *top = out_vertices[hg.nodes_.size() - 2].BestChild();
  if (!top) {
    std::cout << "NO PATH FOUND" << std::endl;
  } else {
    PrintFinal(hg, *top);
    std::cout << "||| " << top->Bound() << std::endl;
  }
}

template <class Model> unsigned char Lazy<Model>::ConvertEdge(const search::Context<Model> &context, bool final, search::Vertex *vertices, const Hypergraph::Edge &in, search::PartialEdge &out) const {
  const std::vector<WordID> &e = in.rule_->e();
  std::vector<lm::WordIndex> words;
  unsigned int terminals = 0;
  unsigned char nt = 0;
  out.score = 0.0;
  for (std::vector<WordID>::const_iterator word = e.begin(); word != e.end(); ++word) {
    if (*word <= 0) {
      out.nt[nt] = vertices[in.tail_nodes_[-*word]].RootPartial();
      if (out.nt[nt].Empty()) return 255;
      out.score += out.nt[nt].Bound();
      ++nt;
      words.push_back(lm::kMaxWordIndex);
    } else {
      ++terminals;
      words.push_back(vocab_.FromCDec(*word));
    }
  }
  for (unsigned char fill = nt; fill < search::kMaxArity; ++fill) {
    out.nt[fill] = search::kBlankPartialVertex;
  }

  if (final) {
    words.push_back(m_.GetVocabulary().EndSentence());
  }

  out.score += in.rule_->GetFeatureValues().dot(cdec_weights_);
  out.score -= static_cast<float>(terminals) * context.GetWeights().WordPenalty() / M_LN10;
  out.score += search::ScoreRule(context, words, final, out.between);
  return nt;
}

boost::scoped_ptr<LazyBase> AwfulGlobalLazy;

} // namespace

void PassToLazy(const char *model_file, const std::vector<weight_t> &weights, unsigned int pop_limit, const Hypergraph &hg) {
  if (!AwfulGlobalLazy.get()) {
    std::cerr << "Pop limit " << pop_limit << std::endl;
    AwfulGlobalLazy.reset(LazyBase::Load(model_file, weights));
  }
  AwfulGlobalLazy->Search(pop_limit, hg);
}
<|endoftext|>


<commit_before>#ifndef WORKERS_H
#define WORKERS_H

#include"lockeds.hpp"
#include"mutexes.hpp"

#include<vector>
#include<set>
#include<queue>

#include<boost/thread/barrier.hpp>
#include<boost/thread/mutex.hpp>
#include<boost/thread/thread.hpp>

class Worker;
class Process;

class AllWorkers {
	bool exit_condition;

	bool soft_stop_condition;
	boost::barrier soft_stop_barrier;

	/*When performing a process collection, this specifies the
	number of workers that haven't consumed their gray set yet.
	In the document doc/process-gc.txt, this is the "N" variable
	*/
	AtomicCounter gray_workers;

	/*set of all workers*/
	size_t total_workers;
	std::vector<Worker*> Ws;

	/*set of known processes*/
	std::vector<Process*> U;

	std::queue<Process*> workqueue;
	AppMutex workqueue_mutex;

	/*default timeslice for processes*/
	size_t default_timeslice;

	/*atomically register a worker into Ws*/
	void register_worker(Worker*);

	/*pushes a process onto the workqueue, then pops a process*/
	void workqueue_push_and_pop(Process*&);

	/*pops a process from the workqueue.
	blocks if no process is available yet.
	returns 0 if all worker threads have blocked
		(meaning all work has ended)
	returns 1 if a process was successfully popped
	*/
	bool workqueue_pop(Process*&);

public:
	/*initiates the specified number of worker threads
	This function will return only when workers run out
	of work, or if someone signals an exit condition
	*/
	void initiate(void);

	/*atomically register a process into U*/
	void register_process(Process*);

	/*pushes a process onto the workqueue*/
	void workqueue_push(Process*);

	AllWorkers(unsigned int nworkers)
		: exit_condition(0),
		  soft_stop_condition(0),
		  soft_stop_barrier(nworkers),
		  gray_workers(0),
		  total_workers(nworkers),
		  workqueue(),
		  workqueue_mutex(),
		  default_timeslice(nworkers > 1 ? 256 : 64)
	{ }

	friend class Worker;
};

class Worker {
	std::set<Process*> gray_set;
	bool gray_done;
	bool scanning_mode;

	AllWorkers* parent;

	/*worker core*/
	void work(void);

	/*process marking*/
	void mark_process(Process*);

public:
	/*process-level GC triggering*/
	size_t T;

	/*callable, used to launch a thread*/
	void operator()(void);

	explicit Worker(AllWorkers* nparent)
		: parent(nparent),
		gray_set(),
		gray_done(1),
		scanning_mode(0),
		T(0)
	{ }
};

#endif // WORKERS_H

<commit_msg>inc/workers.hpp: made AllWorkers noncopyable<commit_after>#ifndef WORKERS_H
#define WORKERS_H

#include"lockeds.hpp"
#include"mutexes.hpp"

#include<vector>
#include<set>
#include<queue>

#include<boost/thread/barrier.hpp>
#include<boost/thread/mutex.hpp>
#include<boost/thread/thread.hpp>
#include<boost/noncopyable.hpp>

class Worker;
class Process;

class AllWorkers : boost::noncopyable {
	bool exit_condition;

	bool soft_stop_condition;
	boost::barrier soft_stop_barrier;

	/*When performing a process collection, this specifies the
	number of workers that haven't consumed their gray set yet.
	In the document doc/process-gc.txt, this is the "N" variable
	*/
	AtomicCounter gray_workers;

	/*set of all workers*/
	size_t total_workers;
	std::vector<Worker*> Ws;

	/*set of known processes*/
	std::vector<Process*> U;

	std::queue<Process*> workqueue;
	AppMutex workqueue_mutex;

	/*default timeslice for processes*/
	size_t default_timeslice;

	/*atomically register a worker into Ws*/
	void register_worker(Worker*);

	/*pushes a process onto the workqueue, then pops a process*/
	void workqueue_push_and_pop(Process*&);

	/*pops a process from the workqueue.
	blocks if no process is available yet.
	returns 0 if all worker threads have blocked
		(meaning all work has ended)
	returns 1 if a process was successfully popped
	*/
	bool workqueue_pop(Process*&);

public:
	/*initiates the specified number of worker threads
	This function will return only when workers run out
	of work, or if someone signals an exit condition
	*/
	void initiate(void);

	/*atomically register a process into U*/
	void register_process(Process*);

	/*pushes a process onto the workqueue*/
	void workqueue_push(Process*);

	AllWorkers(unsigned int nworkers)
		: exit_condition(0),
		  soft_stop_condition(0),
		  soft_stop_barrier(nworkers),
		  gray_workers(0),
		  total_workers(nworkers),
		  workqueue(),
		  workqueue_mutex(),
		  default_timeslice(nworkers > 1 ? 256 : 64)
	{ }

	friend class Worker;
};

class Worker {
	std::set<Process*> gray_set;
	bool gray_done;
	bool scanning_mode;

	AllWorkers* parent;

	/*worker core*/
	void work(void);

	/*process marking*/
	void mark_process(Process*);

public:
	/*process-level GC triggering*/
	size_t T;

	/*callable, used to launch a thread*/
	void operator()(void);

	explicit Worker(AllWorkers* nparent)
		: parent(nparent),
		gray_set(),
		gray_done(1),
		scanning_mode(0),
		T(0)
	{ }
};

#endif // WORKERS_H

<|endoftext|>


<commit_before>#include "engine/world/Room.h"
#include "engine/math/random.h"

namespace engine {
namespace world {

	Room::Room(){
		//Initialize empty room
		roomType = ROOM_TYPE_EMPTY;

		Tile tempTile;
		tempTile.setType(TILE_VOID);

		for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
			tiles[i] = tempTile;
		}
	}

	Tile* Room::getTile(vec2 pos){
		return getTile(pos.x,pos.y);
	}

	Tile* Room::getTile(int x,int y){
		ASSERT_TILE_XY(x,y);

		return &tiles[(x * ROOM_HEIGHT) + y];
	}

	void Room::setTile(vec2 pos,Tile tile){
		setTile(pos.x,pos.y,tile);
	}

	void Room::setTile(int x,int y,Tile tile){
		ASSERT_TILE_XY(x,y);
		tiles[(x * ROOM_HEIGHT) + y] = tile;
	}

	/**
	 * Regenerate the room.
	 *
	 * Input: Reads roomType and builds on top of that.
	 */
	void Room::generate(){
		//Lets get the simple types out from the way first... air and water...

		Tile tempTile;

		switch(roomType){
		case ROOM_TYPE_EMPTY:
			//Loop trough all tiles and set them to void
			tempTile.setType(TILE_VOID);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_WATER:
			tempTile.setType(TILE_WATER);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_GROUND:
			tempTile.setType(TILE_GRASS);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				if(randomRange(0,10) > 8){
					tiles[i] = Tile(TILE_TREE);
				}
			}

			break;
		case ROOM_TYPE_DUNGEON:
			tempTile.setType(TILE_ROCK_FLOOR);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				if(randomRange(0,1)){
					tiles[i] = Tile(TILE_SOLID_ROCK);
				}
			}

			break;
		}
	}

	/**
	 * Returns direct access to the tile array, useful when raw access needed to the array.
	 */
	Tile* Room::getTileArray(){
		return tiles;
	}

	/**
	 * Prints the room layout to the cmd. Used for debugging.
	 */
	void Room::printLayout(){
		for(int y = 0;y < ROOM_HEIGHT;++y){
			for(int x = 0;x < ROOM_WIDTH;++x){
				printf("%c",getTile(x,y)->visual);
			}
			printf("\n");
		}
	}

}
}
<commit_msg>Modifying the world generator<commit_after>#include "engine/world/Room.h"
#include "engine/math/random.h"
#include "engine/math/AABB.h"

namespace engine {
namespace world {

	Room::Room(){
		//Initialize empty room
		roomType = ROOM_TYPE_EMPTY;

		Tile tempTile;
		tempTile.setType(TILE_VOID);

		for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
			tiles[i] = tempTile;
		}
	}

	Tile* Room::getTile(vec2 pos){
		return getTile(pos.x,pos.y);
	}

	Tile* Room::getTile(int x,int y){
		ASSERT_TILE_XY(x,y);

		return &tiles[(x * ROOM_HEIGHT) + y];
	}

	void Room::setTile(vec2 pos,Tile tile){
		setTile(pos.x,pos.y,tile);
	}

	void Room::setTile(int x,int y,Tile tile){
		ASSERT_TILE_XY(x,y);
		tiles[(x * ROOM_HEIGHT) + y] = tile;
	}

	/**
	 * Regenerate the room.
	 *
	 * Input: Reads roomType and builds on top of that.
	 */
	void Room::generate(){
		//Lets get the simple types out from the way first... air and water...

		Tile tempTile;

		switch(roomType){
		case ROOM_TYPE_EMPTY:
			//Loop trough all tiles and set them to void
			tempTile.setType(TILE_VOID);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_WATER:
			tempTile.setType(TILE_WATER);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			break;
		case ROOM_TYPE_GROUND:
			tempTile.setType(TILE_GRASS);

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				if(randomRange(0,10) > 8){
					tiles[i] = Tile(TILE_TREE);
				}
			}

			break;
		case ROOM_TYPE_DUNGEON:
			tempTile.setType(TILE_ROCK_FLOOR);

			//reset room
			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				tiles[i] = tempTile;
			}

			//Base with random amounts of rock
			for(int i = 0;i < (ROOM_WIDTH * ROOM_HEIGHT);++i){
				if(randomRange(0,10) > 1){
					tiles[i] = Tile(TILE_SOLID_ROCK);
				}
			}

			//Insert the random rooms
			int roomCount = randomRange(2,6);

			while(roomCount > 0){
				AABB room;
				//first size, then position, so we are sure it wont go over the limits
				LOG_INFO("Room");

				room.size.x = randomRange(2,5);
				room.size.y = randomRange(2,5);

				room.pos.x = randomRange(0,(ROOM_WIDTH  - room.size.x));
				room.pos.y = randomRange(0,(ROOM_HEIGHT - room.size.y));

				//Room stuff is ok, lets draw it in
				for(int x = room.pos.x;x < room.size.x;++x){
					for(int y = room.pos.y;y < room.size.y;++y){
						setTile(x,y,Tile(TILE_ROCK_FLOOR));
					}
				}

				--roomCount;
			}

			break;
		}
	}

	/**
	 * Returns direct access to the tile array, useful when raw access needed to the array.
	 */
	Tile* Room::getTileArray(){
		return tiles;
	}

	/**
	 * Prints the room layout to the cmd. Used for debugging.
	 */
	void Room::printLayout(){
		for(int y = 0;y < ROOM_HEIGHT;++y){
			for(int x = 0;x < ROOM_WIDTH;++x){
				printf("%c",getTile(x,y)->visual);
			}
			printf("\n");
		}
	}

}
}
<|endoftext|>


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

using namespace std;

template <class T>
struct Node
{
	T element;
	Node<T> *left, *right, *pparent;
};

template <class T>
class BST {
private:
	Node<T> *root;
	int count;
public:
	BST();
	void show(ostream&cout, Node<T> *Tree);
	void add(const T&);
	bool search(const T&, Node<T> *Tree);
	void input(const string file);
	void output(const string file);
	Node<T>* MinElement(Node<T>* min);
	Node<T>* getroot();
	int getcount() const;
	Node<T>* del(Node<T> *Tree, T el);

};

int main() {
	system("chcp 1251");

	BST<int> MyTree;
	char file1[20] = "File1.txt";
	char file2[20] = "File2.txt";
	MyTree.input(file1);
	MyTree.show(cout, MyTree.getroot());
	MyTree.output(file2);
	if (MyTree.search(10, MyTree.getroot()) == true) {
		cout << "Элемент найден" << endl;
	}
	else cout << "Элемент не найден" << endl;
	MyTree.del(MyTree.getroot(), 4);
	MyTree.show(cout, MyTree.getroot());

	system("pause");

	return 0;
}

template <typename T> BST<T>::BST() {
	root = NULL;
	count = 0;
}

template <typename T> void BST<T>::show(ostream&cout, Node<T> *Tree) {
	if (Tree != NULL) {

		cout << Tree->element << endl;;
		show(cout, Tree->left);
		show(cout, Tree->right);

	}
}

template <typename T> void BST<T>::add(const T &x) {
	Node<T>* daughter = new Node<T>;
	daughter->element = x;
	daughter->left = daughter->right = nullptr;
	Node<T>* parent = root;
	Node<T>* temp = root;

	while (temp)
	{
		parent = temp;
		if (x < temp->element)
			temp = temp->left;
		else temp = temp->right;
	}

	if (!parent)
		root = daughter;
	else {
		if (x < parent->element)
			parent->left = daughter;
		else
			parent->right = daughter;
	}
	count++;
}

template <typename T> Node<T>* BST<T>::getroot() {
	return root;
}

template <typename T> int BST<T>::getcount() const {
	return count;
}

template <typename T> void BST<T>::input(const string file) {
	ifstream fin(file);
	try
	{
		int temp;
		while (!fin.eof())
		{

			fin >> temp;
			add(temp);

		}
		fin.close();
	}
	catch (int i)
	{
		cout << "This file don't find" << endl;
	}

}

template <typename T> void BST<T>::output(const string file) {
	ofstream fout(file);
	show(fout, root);
	fout.close();
}

template <typename T> bool BST<T>::search(const T&x, Node<T>* Tree) {
	if (Tree == nullptr)
		return false;
	if (x == Tree->element) {
		return true;
	}
	else if (x < Tree->element) {
		search(x, Tree->left);
	}
	else search(x, Tree->right);
}

template <typename T> Node<T>* BST<T>::MinElement(Node<T>* min) {
	if (min->left == nullptr)
		return min;
	else
		return MinElement(min->left);

}

template <typename T>
Node<T>* BST<T>::del(Node<T> *Tree, T el) {
	if (Tree == nullptr) return Tree;
	if (el < Tree->element) Tree->left = del(Tree->left, el);
	else if (el > Tree->element) Tree->right = del(Tree->right, el);
	else if ((Tree->left != nullptr) && (Tree->right != nullptr)) {
		Tree->element = MinElement(Tree->right)->element;
		Tree->right = del(Tree->right, Tree->element);
	}
	else {
		if (Tree->left != nullptr) Tree = Tree->left;
		else Tree = Tree->right;
	}
	count--;
	return Tree;
}
<commit_msg>Update BST.hpp<commit_after>#include <iostream>
#include <fstream>

using namespace std;

template <class T>
struct Node
{
	T element;
	Node<T> *left, *right, *pparent;
};

template <class T>
class BST {
private:
	Node<T> *root;
	int count;
public:
	BST();
	void show(ostream&cout, Node<T> *Tree);
	void add(const T&);
	bool search(const T&, Node<T> *Tree);
	void input(const string file);
	void output(const string file);
	Node<T>* MinElement(Node<T>* min);
	Node<T>* getroot();
	int getcount() const;
	Node<T>* del(Node<T> *Tree, T el);

};

template <typename T> BST<T>::BST() {
	root = NULL;
	count = 0;
}

template <typename T> void BST<T>::show(ostream&cout, Node<T> *Tree) {
	if (Tree != NULL) {

		cout << Tree->element << endl;;
		show(cout, Tree->left);
		show(cout, Tree->right);

	}
}

template <typename T> void BST<T>::add(const T &x) {
	Node<T>* daughter = new Node<T>;
	daughter->element = x;
	daughter->left = daughter->right = nullptr;
	Node<T>* parent = root;
	Node<T>* temp = root;

	while (temp)
	{
		parent = temp;
		if (x < temp->element)
			temp = temp->left;
		else temp = temp->right;
	}

	if (!parent)
		root = daughter;
	else {
		if (x < parent->element)
			parent->left = daughter;
		else
			parent->right = daughter;
	}
	count++;
}

template <typename T> Node<T>* BST<T>::getroot() {
	return root;
}

template <typename T> int BST<T>::getcount() const {
	return count;
}

template <typename T> void BST<T>::input(const string file) {
	ifstream fin(file);
	try
	{
		int temp;
		while (!fin.eof())
		{

			fin >> temp;
			add(temp);

		}
		fin.close();
	}
	catch (int i)
	{
		cout << "This file don't find" << endl;
	}

}

template <typename T> void BST<T>::output(const string file) {
	ofstream fout(file);
	show(fout, root);
	fout.close();
}

template <typename T> bool BST<T>::search(const T&x, Node<T>* Tree) {
	if (Tree == nullptr)
		return false;
	if (x == Tree->element) {
		return true;
	}
	else if (x < Tree->element) {
		search(x, Tree->left);
	}
	else search(x, Tree->right);
}

template <typename T> Node<T>* BST<T>::MinElement(Node<T>* min) {
	if (min->left == nullptr)
		return min;
	else
		return MinElement(min->left);

}

template <typename T>
Node<T>* BST<T>::del(Node<T> *Tree, T el) {
	if (Tree == nullptr) return Tree;
	if (el < Tree->element) Tree->left = del(Tree->left, el);
	else if (el > Tree->element) Tree->right = del(Tree->right, el);
	else if ((Tree->left != nullptr) && (Tree->right != nullptr)) {
		Tree->element = MinElement(Tree->right)->element;
		Tree->right = del(Tree->right, Tree->element);
	}
	else {
		if (Tree->left != nullptr) Tree = Tree->left;
		else Tree = Tree->right;
	}
	count--;
	return Tree;
}
<|endoftext|>


<commit_before>#pragma once

#include <vector>

namespace helene
{
template <class NodeType, class EdgeType> class dag
{
public:
    ////////////////////////////////////////////////////////////////////////////
    // public typedefs

    typedef NodeType value_type;
    typedef NodeType& reference;
    typedef const NodeType& const_reference;

    typedef typename std::vector<NodeType>::difference_type difference_type;
    typedef typename std::vector<NodeType>::size_type size_type;

    typedef EdgeType edge_value_type;
    typedef EdgeType& edge_reference;
    typedef const EdgeType& const_edge_reference;

    typedef typename std::vector<EdgeType>::size_type edge_size_type;
    typedef
        typename std::vector<EdgeType>::difference_type edge_difference_type;

private:
    ////////////////////////////////////////////////////////////////////////////
    // internal classes

    // indices to properties of the associated edge
    struct edge
    {
        size_type from_property;
        size_type to_property;
        edge_size_type edge_property;
    };

public:
    dag() = default;

private:
    std::vector<NodeType> node_properties_;
    std::vector<EdgeType> edge_properties_;
};
}
<commit_msg>Add edges_ member variable. 	modified:   include/dag.hpp<commit_after>#pragma once

#include <vector>

namespace helene
{
template <class NodeType, class EdgeType> class dag
{
public:
    ////////////////////////////////////////////////////////////////////////////
    // public typedefs

    typedef NodeType value_type;
    typedef NodeType& reference;
    typedef const NodeType& const_reference;

    typedef typename std::vector<NodeType>::difference_type difference_type;
    typedef typename std::vector<NodeType>::size_type size_type;

    typedef EdgeType edge_value_type;
    typedef EdgeType& edge_reference;
    typedef const EdgeType& const_edge_reference;

    typedef typename std::vector<EdgeType>::size_type edge_size_type;
    typedef
        typename std::vector<EdgeType>::difference_type edge_difference_type;

private:
    ////////////////////////////////////////////////////////////////////////////
    // internal classes

    // indices to properties of the associated edge
    struct edge
    {
        size_type from_property;
        size_type to_property;
        edge_size_type edge_property;
    };

public:
    ////////////////////////////////////////////////////////////////////////////
    // Container concept member functions

    dag() = default;

private:
    std::vector<NodeType> node_properties_;
    std::vector<EdgeType> edge_properties_;

    std::vector<edge> edges_;
};
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <uint256.h>
#include <arith_uint256.h>
#include <ethereum/ethereum.h>
#include <ethereum/sha3.h>
#include <services/witnessaddress.h>
#include <logging.h>
#include <util/strencodings.h>

int nibblesToTraverse(const std::string &encodedPartialPath, const std::string &path, int pathPtr) {
  std::string partialPath;
  char pathPtrInt[2] = {encodedPartialPath[0], '\0'};
  int partialPathInt = strtol(pathPtrInt, NULL, 10);
  if(partialPathInt == 0 || partialPathInt == 2){
    partialPath = encodedPartialPath.substr(2);
  }else{
    partialPath = encodedPartialPath.substr(1);
  }
  if(partialPath == path.substr(pathPtr, partialPath.size())){
    return partialPath.size();
  }else{
    return -1;
  }
}
bool VerifyProof(dev::bytesConstRef path, const dev::RLP& value, const dev::RLP& parentNodes, const dev::RLP& root) {
    try{
        dev::RLP currentNode;
        const int len = parentNodes.itemCount();
        dev::RLP nodeKey = root;
        int pathPtr = 0;

    	const std::string pathString = dev::toHex(path);

        int nibbles;
        char pathPtrInt[2];
        for (int i = 0 ; i < len ; i++) {
          currentNode = parentNodes[i];
          if(!nodeKey.payload().contentsEqual(sha3(currentNode.data()).ref().toVector())){
            return false;
          }

          if(pathPtr > (int)pathString.size()){
            return false;
          }

          switch(currentNode.itemCount()){
            case 17://branch node
              if(pathPtr == (int)pathString.size()){
                if(currentNode[16].payload().contentsEqual(value.data().toVector())){

                  return true;
                }else{
                  return false;
                }
              }

              pathPtrInt[0] = pathString[pathPtr];
              pathPtrInt[1] = '\0';

              nodeKey = currentNode[strtol(pathPtrInt, NULL, 16)]; //must == sha3(rlp.encode(currentNode[path[pathptr]]))
              pathPtr += 1;
              break;
            case 2:
              nibbles = nibblesToTraverse(toHex(currentNode[0].payload()), pathString, pathPtr);

              if(nibbles <= -1)
                return false;
              pathPtr += nibbles;

              if(pathPtr == (int)pathString.size()) { //leaf node
                if(currentNode[1].payload().contentsEqual(value.data().toVector())){

                  return true;
                } else {
                  return false;
                }
              } else {//extension node
                nodeKey = currentNode[1];
              }
              break;
            default:
              return false;
          }
        }
    }
    catch(...){
        return false;
    }
  return false;
}

/**
 * Parse eth input string expected to contain smart contract method call data. If the method call is not what we
 * expected, or the length of the expected string is not what we expect then return false.
 *
 * @param vchInputExpectedMethodHash The expected method hash
 * @param vchInputData The input to parse
 * @param vchAssetContract The ERC20 contract address of the token involved in moving over
 * @param outputAmount The amount burned
 * @param nAsset The asset burned
 * @param nLocalPrecision The local precision to know how to convert ethereum's uint256 to a CAmount (int64) with truncation of insignifficant bits
 * @param witnessAddress The destination witness address for the minting
 * @return true if everything is valid
 */
bool parseEthMethodInputData(const std::vector<unsigned char>& vchInputExpectedMethodHash, const std::vector<unsigned char>& vchInputData, const std::vector<unsigned char>& vchAssetContract, CAmount& outputAmount, uint32_t& nAsset, const uint8_t& nLocalPrecision, CWitnessAddress& witnessAddress) {
    if(vchAssetContract.empty()){
      return false;
    }
    // total 7 or 8 fields are expected @ 32 bytes each field, 8 fields if witness > 32 bytes
    if(vchInputData.size() < 196 || vchInputData.size() > 260) {
      return false;
    }
    // method hash is 4 bytes
    std::vector<unsigned char>::const_iterator firstMethod = vchInputData.begin();
    std::vector<unsigned char>::const_iterator lastMethod = firstMethod + 4;
    const std::vector<unsigned char> vchMethodHash(firstMethod,lastMethod);
    // if the method hash doesn't match the expected method hash then return false
    if(vchMethodHash != vchInputExpectedMethodHash) {
      return false;
    }

    std::vector<unsigned char> vchAmount(lastMethod,lastMethod + 32);
    // reverse endian
    std::reverse(vchAmount.begin(), vchAmount.end());
    arith_uint256 outputAmountArith = UintToArith256(uint256(vchAmount));

    // convert the vch into a uint32_t (nAsset)
    // should be in position 68 walking backwards
    nAsset = static_cast<uint32_t>(vchInputData[67]);
    nAsset |= static_cast<uint32_t>(vchInputData[66]) << 8;
    nAsset |= static_cast<uint32_t>(vchInputData[65]) << 16;
    nAsset |= static_cast<uint32_t>(vchInputData[64]) << 24;
    // start from 100 offset (96 for 3rd field + 4 bytes for function signature) and subtract 20
    std::vector<unsigned char>::const_iterator firstContractAddress = vchInputData.begin() + 80;
    std::vector<unsigned char>::const_iterator lastContractAddress = firstContractAddress + 20;
    const std::vector<unsigned char> vchERC20ContractAddress(firstContractAddress,lastContractAddress);
    if(vchERC20ContractAddress != vchAssetContract)
    {
      return false;
    }
    // skip data position field of 32 bytes + 100 offset + 31 (offset to the varint _byte)
    int dataPos = 163;
    const unsigned char &dataLength = vchInputData[dataPos++] - 1; // // - 1 to account for the version byte
    // witness programs can extend to 40 bytes, min length is 2 for min witness program
    if(dataLength > 40 || dataLength < 2){
      return false;
    }
    // get precision
    dataPos += 31;
    const int8_t &nPrecision = static_cast<uint8_t>(vchInputData[dataPos++]);
    // ensure we truncate decimals to fit within int64 if erc20's precision is more than our asset precision
    // local precision can range between 0 and 8 decimal places, so it should fit within a CAmount
    if(nLocalPrecision > nPrecision){
      outputAmountArith /= pow(10, nLocalPrecision-nPrecision);
    // or we pad zero's if erc20's precision is less than ours so we can accurately get the whole value of the amount transferred
    } else if(nLocalPrecision < nPrecision){
      outputAmountArith *= pow(10, nPrecision-nLocalPrecision);
    }
    // once we have truncated it is safe to get low 64 bits of the uint256 which should encapsulate the entire value
    outputAmount = outputAmountArith.GetLow64();

    // witness address information starting at position dataPos till the end
    // get version proceeded by witness program bytes
    const unsigned char& nVersion = vchInputData[dataPos++];
    std::vector<unsigned char>::const_iterator firstWitness = vchInputData.begin()+dataPos;
    std::vector<unsigned char>::const_iterator lastWitness = firstWitness + dataLength;
    witnessAddress = CWitnessAddress(nVersion, std::vector<unsigned char>(firstWitness,lastWitness));
    return witnessAddress.IsValid();
}<commit_msg>fix input data size check<commit_after>// Copyright (c) 2019 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <uint256.h>
#include <arith_uint256.h>
#include <ethereum/ethereum.h>
#include <ethereum/sha3.h>
#include <services/witnessaddress.h>
#include <logging.h>
#include <util/strencodings.h>

int nibblesToTraverse(const std::string &encodedPartialPath, const std::string &path, int pathPtr) {
  std::string partialPath;
  char pathPtrInt[2] = {encodedPartialPath[0], '\0'};
  int partialPathInt = strtol(pathPtrInt, NULL, 10);
  if(partialPathInt == 0 || partialPathInt == 2){
    partialPath = encodedPartialPath.substr(2);
  }else{
    partialPath = encodedPartialPath.substr(1);
  }
  if(partialPath == path.substr(pathPtr, partialPath.size())){
    return partialPath.size();
  }else{
    return -1;
  }
}
bool VerifyProof(dev::bytesConstRef path, const dev::RLP& value, const dev::RLP& parentNodes, const dev::RLP& root) {
    try{
        dev::RLP currentNode;
        const int len = parentNodes.itemCount();
        dev::RLP nodeKey = root;
        int pathPtr = 0;

    	const std::string pathString = dev::toHex(path);

        int nibbles;
        char pathPtrInt[2];
        for (int i = 0 ; i < len ; i++) {
          currentNode = parentNodes[i];
          if(!nodeKey.payload().contentsEqual(sha3(currentNode.data()).ref().toVector())){
            return false;
          }

          if(pathPtr > (int)pathString.size()){
            return false;
          }

          switch(currentNode.itemCount()){
            case 17://branch node
              if(pathPtr == (int)pathString.size()){
                if(currentNode[16].payload().contentsEqual(value.data().toVector())){

                  return true;
                }else{
                  return false;
                }
              }

              pathPtrInt[0] = pathString[pathPtr];
              pathPtrInt[1] = '\0';

              nodeKey = currentNode[strtol(pathPtrInt, NULL, 16)]; //must == sha3(rlp.encode(currentNode[path[pathptr]]))
              pathPtr += 1;
              break;
            case 2:
              nibbles = nibblesToTraverse(toHex(currentNode[0].payload()), pathString, pathPtr);

              if(nibbles <= -1)
                return false;
              pathPtr += nibbles;

              if(pathPtr == (int)pathString.size()) { //leaf node
                if(currentNode[1].payload().contentsEqual(value.data().toVector())){

                  return true;
                } else {
                  return false;
                }
              } else {//extension node
                nodeKey = currentNode[1];
              }
              break;
            default:
              return false;
          }
        }
    }
    catch(...){
        return false;
    }
  return false;
}

/**
 * Parse eth input string expected to contain smart contract method call data. If the method call is not what we
 * expected, or the length of the expected string is not what we expect then return false.
 *
 * @param vchInputExpectedMethodHash The expected method hash
 * @param vchInputData The input to parse
 * @param vchAssetContract The ERC20 contract address of the token involved in moving over
 * @param outputAmount The amount burned
 * @param nAsset The asset burned
 * @param nLocalPrecision The local precision to know how to convert ethereum's uint256 to a CAmount (int64) with truncation of insignifficant bits
 * @param witnessAddress The destination witness address for the minting
 * @return true if everything is valid
 */
bool parseEthMethodInputData(const std::vector<unsigned char>& vchInputExpectedMethodHash, const std::vector<unsigned char>& vchInputData, const std::vector<unsigned char>& vchAssetContract, CAmount& outputAmount, uint32_t& nAsset, const uint8_t& nLocalPrecision, CWitnessAddress& witnessAddress) {
    if(vchAssetContract.empty()){
      return false;
    }
    // total 7 or 8 fields are expected @ 32 bytes each field, 8 fields if witness > 32 bytes
    if(vchInputData.size() < 228 || vchInputData.size() > 260) {
      return false;
    }
    // method hash is 4 bytes
    std::vector<unsigned char>::const_iterator firstMethod = vchInputData.begin();
    std::vector<unsigned char>::const_iterator lastMethod = firstMethod + 4;
    const std::vector<unsigned char> vchMethodHash(firstMethod,lastMethod);
    // if the method hash doesn't match the expected method hash then return false
    if(vchMethodHash != vchInputExpectedMethodHash) {
      return false;
    }

    std::vector<unsigned char> vchAmount(lastMethod,lastMethod + 32);
    // reverse endian
    std::reverse(vchAmount.begin(), vchAmount.end());
    arith_uint256 outputAmountArith = UintToArith256(uint256(vchAmount));

    // convert the vch into a uint32_t (nAsset)
    // should be in position 68 walking backwards
    nAsset = static_cast<uint32_t>(vchInputData[67]);
    nAsset |= static_cast<uint32_t>(vchInputData[66]) << 8;
    nAsset |= static_cast<uint32_t>(vchInputData[65]) << 16;
    nAsset |= static_cast<uint32_t>(vchInputData[64]) << 24;
    // start from 100 offset (96 for 3rd field + 4 bytes for function signature) and subtract 20
    std::vector<unsigned char>::const_iterator firstContractAddress = vchInputData.begin() + 80;
    std::vector<unsigned char>::const_iterator lastContractAddress = firstContractAddress + 20;
    const std::vector<unsigned char> vchERC20ContractAddress(firstContractAddress,lastContractAddress);
    if(vchERC20ContractAddress != vchAssetContract)
    {
      return false;
    }
    // skip data position field of 32 bytes + 100 offset + 31 (offset to the varint _byte)
    int dataPos = 163;
    const unsigned char &dataLength = vchInputData[dataPos++] - 1; // // - 1 to account for the version byte
    // witness programs can extend to 40 bytes, min length is 2 for min witness program
    if(dataLength > 40 || dataLength < 2){
      return false;
    }
    // get precision
    dataPos += 31;
    const int8_t &nPrecision = static_cast<uint8_t>(vchInputData[dataPos++]);
    // ensure we truncate decimals to fit within int64 if erc20's precision is more than our asset precision
    // local precision can range between 0 and 8 decimal places, so it should fit within a CAmount
    if(nLocalPrecision > nPrecision){
      outputAmountArith /= pow(10, nLocalPrecision-nPrecision);
    // or we pad zero's if erc20's precision is less than ours so we can accurately get the whole value of the amount transferred
    } else if(nLocalPrecision < nPrecision){
      outputAmountArith *= pow(10, nPrecision-nLocalPrecision);
    }
    // once we have truncated it is safe to get low 64 bits of the uint256 which should encapsulate the entire value
    outputAmount = outputAmountArith.GetLow64();

    // witness address information starting at position dataPos till the end
    // get version proceeded by witness program bytes
    const unsigned char& nVersion = vchInputData[dataPos++];
    std::vector<unsigned char>::const_iterator firstWitness = vchInputData.begin()+dataPos;
    std::vector<unsigned char>::const_iterator lastWitness = firstWitness + dataLength;
    witnessAddress = CWitnessAddress(nVersion, std::vector<unsigned char>(firstWitness,lastWitness));
    return witnessAddress.IsValid();
}<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperChoiceParameter.h"

namespace otb
{
namespace Wrapper
{

ChoiceParameter::ChoiceParameter()
  : m_CurrentChoice(0)
{
}

ChoiceParameter::~ChoiceParameter()
{
}

void
ChoiceParameter::AddChoice( std::string choicekey, std::string choiceName )
{
  Choice choice;
  choice.m_Key = choicekey;
  choice.m_Name = choiceName;
  choice.m_AssociatedParameter = ParameterGroup::New();
  m_ChoiceList.push_back(choice);
}

std::string
ChoiceParameter::GetChoiceKey( int i )
{
  return m_ChoiceList[i].m_Key;
}

std::vector<std::string>
ChoiceParameter::GetChoiceKeys( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Key);
    }

  return ret;
}

std::string
ChoiceParameter::GetChoiceName( int i )
{
  return m_ChoiceList[i].m_Name;
}

std::vector<std::string>
ChoiceParameter::GetChoiceNames( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Name);
    }
  return ret;
}

ParameterGroup::Pointer
ChoiceParameter::GetChoiceParameterGroupByIndex( int i )
{
  return m_ChoiceList[i].m_AssociatedParameter;
}

ParameterGroup::Pointer
ChoiceParameter::GetChoiceParameterGroupByKey( std::string choiceKey )
{
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    if ( it->m_Key == choiceKey )
      {
      return it->m_AssociatedParameter;
      }
    }

  itkExceptionMacro(<< "Cannot find " << choiceKey);
}

unsigned int
ChoiceParameter::GetNbChoices( void )
{
  return m_ChoiceList.size();
}

void
ChoiceParameter::SetValue(unsigned int v)
{
  m_CurrentChoice = v;
  SetActive(true);
  // Call Modified();
  this->Modified();
}

void
ChoiceParameter::SetValue(std::string choiceKey)
{
  ChoiceList::iterator it = m_ChoiceList.begin();

  unsigned int i = 0;
  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    if ( it->m_Key == choiceKey )
      {
      SetValue(i);
      return;
      }
    ++i;
    }

  itkExceptionMacro(<< "Cannot find " << choiceKey);
}

unsigned int
ChoiceParameter::GetValue()
{
  return m_CurrentChoice;
}

/** Return any value */
std::vector<std::string>
ChoiceParameter::GetParametersKeys()
{
  std::vector<std::string> parameters;

  ChoiceList::iterator cit = m_ChoiceList.begin();

  for (cit = m_ChoiceList.begin(); cit != m_ChoiceList.end(); ++cit)
    {
    if (cit->m_AssociatedParameter)
      {
      std::vector<std::string> subparams = cit->m_AssociatedParameter->GetParametersKeys();
      for (std::vector<std::string>::const_iterator it = subparams.begin();
           it != subparams.end(); ++it)
        {
        parameters.push_back( cit->m_Key + "."  + *it );
        }
      }
    }
  return parameters;
}

}
}

<commit_msg>ENH: add the associated GroupParameter created when adding a choice to the ChoiceParameter      children list to avoid creating a gap between the ChoiceParameter and the Parameter created      later in the QtGUI<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbWrapperChoiceParameter.h"

namespace otb
{
namespace Wrapper
{

ChoiceParameter::ChoiceParameter()
  : m_CurrentChoice(0)
{
}

ChoiceParameter::~ChoiceParameter()
{
}

void
ChoiceParameter::AddChoice( std::string choicekey, std::string choiceName )
{
  Choice choice;
  choice.m_Key = choicekey;
  choice.m_Name = choiceName;
  choice.m_AssociatedParameter = ParameterGroup::New();
  m_ChoiceList.push_back(choice);

  // Add the associated parameter as a child
  // in order to not have a gap in the children hierarchy
  this->AddChild(choice.m_AssociatedParameter.GetPointer());
}

std::string
ChoiceParameter::GetChoiceKey( int i )
{
  return m_ChoiceList[i].m_Key;
}

std::vector<std::string>
ChoiceParameter::GetChoiceKeys( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Key);
    }

  return ret;
}

std::string
ChoiceParameter::GetChoiceName( int i )
{
  return m_ChoiceList[i].m_Name;
}

std::vector<std::string>
ChoiceParameter::GetChoiceNames( )
{
  std::vector<std::string> ret;
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    ret.push_back(it->m_Name);
    }
  return ret;
}

ParameterGroup::Pointer
ChoiceParameter::GetChoiceParameterGroupByIndex( int i )
{
  return m_ChoiceList[i].m_AssociatedParameter;
}

ParameterGroup::Pointer
ChoiceParameter::GetChoiceParameterGroupByKey( std::string choiceKey )
{
  ChoiceList::iterator it = m_ChoiceList.begin();

  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    if ( it->m_Key == choiceKey )
      {
      return it->m_AssociatedParameter;
      }
    }

  itkExceptionMacro(<< "Cannot find " << choiceKey);
}

unsigned int
ChoiceParameter::GetNbChoices( void )
{
  return m_ChoiceList.size();
}

void
ChoiceParameter::SetValue(unsigned int v)
{
  m_CurrentChoice = v;
  SetActive(true);
  // Call Modified();
  this->Modified();
}

void
ChoiceParameter::SetValue(std::string choiceKey)
{
  ChoiceList::iterator it = m_ChoiceList.begin();

  unsigned int i = 0;
  for (it = m_ChoiceList.begin(); it != m_ChoiceList.end(); ++it)
    {
    if ( it->m_Key == choiceKey )
      {
      SetValue(i);
      return;
      }
    ++i;
    }

  itkExceptionMacro(<< "Cannot find " << choiceKey);
}

unsigned int
ChoiceParameter::GetValue()
{
  return m_CurrentChoice;
}

/** Return any value */
std::vector<std::string>
ChoiceParameter::GetParametersKeys()
{
  std::vector<std::string> parameters;

  ChoiceList::iterator cit = m_ChoiceList.begin();

  for (cit = m_ChoiceList.begin(); cit != m_ChoiceList.end(); ++cit)
    {
    if (cit->m_AssociatedParameter)
      {
      std::vector<std::string> subparams = cit->m_AssociatedParameter->GetParametersKeys();
      for (std::vector<std::string>::const_iterator it = subparams.begin();
           it != subparams.end(); ++it)
        {
        parameters.push_back( cit->m_Key + "."  + *it );
        }
      }
    }
  return parameters;
}

}
}

<|endoftext|>


<commit_before>/*
 Flexisip, a flexible SIP proxy server with media capabilities.
 Copyright (C) 2012  Belledonne Communications SARL.

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

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "forkmessagecontext.hh"
#include "registrardb.hh"
#include "common.hh"
#include <algorithm>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/msg_types.h>
#include "xml/fthttp.hxx"
#include <xercesc/util/PlatformUtils.hpp>

using namespace ::std;
using namespace fthttp;

static bool needsDelivery(int code){
	return code<200 || code==503 || code==408;
}

ForkMessageContext::ForkMessageContext(Agent *agent, const std::shared_ptr<RequestSipEvent> &event, shared_ptr<ForkContextConfig> cfg, ForkContextListener* listener) :
		ForkContext(agent, event,cfg,listener) {
	LOGD("New ForkMessageContext %p", this);
	mAcceptanceTimer=NULL;
	//start the acceptance timer immediately
	if (mCfg->mForkLate && mCfg->mDeliveryTimeout>30){
		mAcceptanceTimer=su_timer_create(su_root_task(mAgent->getRoot()), 0);
		su_timer_set_interval(mAcceptanceTimer, &ForkMessageContext::sOnAcceptanceTimer, this, (su_duration_t)mCfg->mUrgentTimeout*1000);
	}
	mDeliveredCount=0;
}

ForkMessageContext::~ForkMessageContext() {
	if (mAcceptanceTimer)
		su_timer_destroy(mAcceptanceTimer);
	LOGD("Destroy ForkMessageContext %p", this);
}

bool ForkMessageContext::shouldFinish() {
	return false; //the messaging fork context controls its termination.
}

void ForkMessageContext::checkFinished(){
	if (mIncoming==NULL && !mCfg->mForkLate){
		setFinished();
		return;
	}

	auto branches=getBranches();
	bool awaiting_responses=false;

	if (!mCfg->mForkLate){
		awaiting_responses=!allBranchesAnswered();
	}else{
		for(auto it=branches.begin();it!=branches.end();++it){
			if (needsDelivery((*it)->getStatus())) {
				awaiting_responses=true;
				break;
			}
		}
	}
	if (!awaiting_responses){
		shared_ptr<BranchInfo> br=findBestBranch(sUrgentCodes);
		if (br){
			forwardResponse(br);
		}
		setFinished();
	}
}

void ForkMessageContext::logDeliveryEvent(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event){
	sip_t *sip = event->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Delivery,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setDestination(br->mRequest->getMsgSip()->getSip()->sip_request->rq_url);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	event->setEventLog(log);
	event->flushLog();
}

void ForkMessageContext::onResponse(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event) {
	sip_t *sip = event->getMsgSip()->getSip();
	int code=sip->sip_status->st_status;
	LOGD("ForkMessageContext::onResponse()");

	if (code > 100 && code < 300) {
		if (code>=200){
			mDeliveredCount++;
			if (mAcceptanceTimer) {
				if (mIncoming) logReceptionEvent(event); /*in the sender's log will appear the status code from the receiver*/
				su_timer_destroy(mAcceptanceTimer);
				mAcceptanceTimer=NULL;
			}
		}
		logDeliveryEvent(br,event);
		forwardResponse(br);
	}else logDeliveryEvent(br,event);
	checkFinished();
}

void ForkMessageContext::logReceptionEvent(const shared_ptr<ResponseSipEvent> &ev){
	sip_t *sip=ev->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Reception,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	ev->setEventLog(log);
	ev->flushLog();
}

/*we are called here if no good response has been received from any branch, in fork-late mode only */
void ForkMessageContext::acceptMessage(){
	if (mIncoming==NULL) return;

	/*in fork late mode, never answer a service unavailable*/
	shared_ptr<MsgSip> msgsip(mIncoming->createResponse(SIP_202_ACCEPTED));
	shared_ptr<ResponseSipEvent> ev(new ResponseSipEvent(dynamic_pointer_cast<OutgoingAgent>(mAgent->shared_from_this()), msgsip));
	forwardResponse(ev);
	logReceptionEvent(ev); /*in the sender's log will appear the 202 accepted from flexisip server*/
}

void ForkMessageContext::onAcceptanceTimer(){
	LOGD("ForkMessageContext::onAcceptanceTimer()");
	acceptMessage();
	su_timer_destroy(mAcceptanceTimer);
	mAcceptanceTimer=NULL;
}

void ForkMessageContext::sOnAcceptanceTimer(su_root_magic_t* magic, su_timer_t* t, su_timer_arg_t* arg){
	static_cast<ForkMessageContext*>(arg)->onAcceptanceTimer();
}

bool isMessageARCSFileTransferMessage(shared_ptr<RequestSipEvent> &ev) {
	sip_t* sip = ev->getSip();
	if (strncasecmp(sip->sip_request->rq_method_name, "MESSAGE", strlen(sip->sip_request->rq_method_name)) == 0) {
		SLOGD << "Found message with c_type " << sip->sip_content_type->c_type;
		if (sip->sip_content_type->c_type && strcasecmp (sip->sip_content_type->c_type, "application/vnd.gsma.rcs-ft-http+xml")==0) {
			return true;
		}
	}
	return false;
}

bool isConversionFromRcsToExternalBodyUrlNeeded(shared_ptr<ExtendedContact> &ec) {
	list<string> acceptHeaders = ec->mAcceptHeader;
	if (acceptHeaders.size() == 0) {
		SLOGD << "No accept header found for contact";
		return true;
	}

	for (auto it = acceptHeaders.begin(); it != acceptHeaders.end(); ++it) {
		string header = *it;
		if (header.compare("application/vnd.gsma.rcs-ft-http+xml") == 0) {
			return false;
		}
	}
	SLOGD << "No accept header for RCS file transfer found for contact";
	return true;
}

void ForkMessageContext::onNewBranch(const shared_ptr<BranchInfo> &br) {
	SLOGD << "Fork message context onNewBranch";
	if (br->mUid.size()>0){
		/*check for a branch already existing with this uid, and eventually clean it*/
		shared_ptr<BranchInfo> tmp=findBranchByUid(br->mUid);
		if (tmp){
			removeBranch(tmp);
		}
	} else SLOGE << "No unique id found for contact";

	// Convert a RCS file transfer message to an external body url message if contact doesn't support it
	shared_ptr<RequestSipEvent> &ev = br->mRequest;
	if (ev && isMessageARCSFileTransferMessage(ev)) {
		SLOGD << "Found RCS file transfer message";
		shared_ptr<ExtendedContact> &ec = br->mContact;
		if (ec && isConversionFromRcsToExternalBodyUrlNeeded(ec)) {
			SLOGD << "Found RCS file transfer message sent to a client that doesn't support RCS, let's rewrite it";
			sip_t *sip = ev->getSip();
			if (sip) {
				sip_payload_t *payload = sip->sip_payload;

				xercesc::XMLPlatformUtils::Initialize();
				if (payload) {
					std::unique_ptr<fthttp::File> file_transfer_infos = NULL;
					char *file_url = NULL;

					try {
						istringstream data(payload->pl_data);
						file_transfer_infos = parseFile(data, xml_schema::Flags::dont_validate);
					} catch (const xml_schema::Exception& e) {
						SLOGE << "Can't parse the content of the message";
					}

					if (file_transfer_infos != NULL) {
						File::File_infoSequence &infos = file_transfer_infos->getFile_info();
						if (infos.size() >= 1) {
							for (File::File_infoConstIterator i (infos.begin()); i != infos.end(); ++i) {
								const File::File_infoType &info = (*i);
								const File_info::DataType &data = info.getData();
								const Data::UrlType &url = data.getUrl();
								file_url = (char *)url.c_str();
								break;
							}
						}
					}

					if (file_url) {
						char new_content_type[256];
						sip->sip_payload = sip_payload_make(ev->getHome(), NULL);
						sip->sip_content_length = sip_content_length_make(ev->getHome(), 0);
						sprintf(new_content_type, "message/external-body;access-type=URL;URL=\"%s\"", file_url);
						sip->sip_content_type = sip_content_type_make(ev->getHome(), new_content_type);
					}
				}
				xercesc::XMLPlatformUtils::Terminate();
			}
		}
	}
}

bool ForkMessageContext::onNewRegister(const url_t *dest, const string &uid){
	bool already_have_transaction=!ForkContext::onNewRegister(dest,uid);
	if (already_have_transaction) return false;
	if (uid.size()>0){
		shared_ptr<BranchInfo> br=findBranchByUid(uid);
		if (br==NULL){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this is a new client instance.");
			return true;
		}else if (needsDelivery(br->getStatus())){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this client is reconnecting but was not delivered before.");
			return true;
		}
	}
	//in all other case we can accept a new transaction only if the message hasn't been delivered already.
	LOGD("Message has been delivered %i times.",mDeliveredCount);
	return mDeliveredCount==0;
}

<commit_msg>Revert "Added logs to check if everything behave as expected"<commit_after>/*
 Flexisip, a flexible SIP proxy server with media capabilities.
 Copyright (C) 2012  Belledonne Communications SARL.

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

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "forkmessagecontext.hh"
#include "registrardb.hh"
#include "common.hh"
#include <algorithm>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/msg_types.h>
#include "xml/fthttp.hxx"
#include <xercesc/util/PlatformUtils.hpp>

using namespace ::std;
using namespace fthttp;

static bool needsDelivery(int code){
	return code<200 || code==503 || code==408;
}

ForkMessageContext::ForkMessageContext(Agent *agent, const std::shared_ptr<RequestSipEvent> &event, shared_ptr<ForkContextConfig> cfg, ForkContextListener* listener) :
		ForkContext(agent, event,cfg,listener) {
	LOGD("New ForkMessageContext %p", this);
	mAcceptanceTimer=NULL;
	//start the acceptance timer immediately
	if (mCfg->mForkLate && mCfg->mDeliveryTimeout>30){
		mAcceptanceTimer=su_timer_create(su_root_task(mAgent->getRoot()), 0);
		su_timer_set_interval(mAcceptanceTimer, &ForkMessageContext::sOnAcceptanceTimer, this, (su_duration_t)mCfg->mUrgentTimeout*1000);
	}
	mDeliveredCount=0;
}

ForkMessageContext::~ForkMessageContext() {
	if (mAcceptanceTimer)
		su_timer_destroy(mAcceptanceTimer);
	LOGD("Destroy ForkMessageContext %p", this);
}

bool ForkMessageContext::shouldFinish() {
	return false; //the messaging fork context controls its termination.
}

void ForkMessageContext::checkFinished(){
	if (mIncoming==NULL && !mCfg->mForkLate){
		setFinished();
		return;
	}

	auto branches=getBranches();
	bool awaiting_responses=false;

	if (!mCfg->mForkLate){
		awaiting_responses=!allBranchesAnswered();
	}else{
		for(auto it=branches.begin();it!=branches.end();++it){
			if (needsDelivery((*it)->getStatus())) {
				awaiting_responses=true;
				break;
			}
		}
	}
	if (!awaiting_responses){
		shared_ptr<BranchInfo> br=findBestBranch(sUrgentCodes);
		if (br){
			forwardResponse(br);
		}
		setFinished();
	}
}

void ForkMessageContext::logDeliveryEvent(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event){
	sip_t *sip = event->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Delivery,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setDestination(br->mRequest->getMsgSip()->getSip()->sip_request->rq_url);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	event->setEventLog(log);
	event->flushLog();
}

void ForkMessageContext::onResponse(const std::shared_ptr<BranchInfo> &br, const shared_ptr<ResponseSipEvent> &event) {
	sip_t *sip = event->getMsgSip()->getSip();
	int code=sip->sip_status->st_status;
	LOGD("ForkMessageContext::onResponse()");

	if (code > 100 && code < 300) {
		if (code>=200){
			mDeliveredCount++;
			if (mAcceptanceTimer) {
				if (mIncoming) logReceptionEvent(event); /*in the sender's log will appear the status code from the receiver*/
				su_timer_destroy(mAcceptanceTimer);
				mAcceptanceTimer=NULL;
			}
		}
		logDeliveryEvent(br,event);
		forwardResponse(br);
	}else logDeliveryEvent(br,event);
	checkFinished();
}

void ForkMessageContext::logReceptionEvent(const shared_ptr<ResponseSipEvent> &ev){
	sip_t *sip=ev->getMsgSip()->getSip();
	auto log=make_shared<MessageLog>(MessageLog::Reception,sip->sip_from,sip->sip_to,sip->sip_call_id);
	log->setStatusCode(sip->sip_status->st_status,sip->sip_status->st_phrase);
	log->setCompleted();
	ev->setEventLog(log);
	ev->flushLog();
}

/*we are called here if no good response has been received from any branch, in fork-late mode only */
void ForkMessageContext::acceptMessage(){
	if (mIncoming==NULL) return;

	/*in fork late mode, never answer a service unavailable*/
	shared_ptr<MsgSip> msgsip(mIncoming->createResponse(SIP_202_ACCEPTED));
	shared_ptr<ResponseSipEvent> ev(new ResponseSipEvent(dynamic_pointer_cast<OutgoingAgent>(mAgent->shared_from_this()), msgsip));
	forwardResponse(ev);
	logReceptionEvent(ev); /*in the sender's log will appear the 202 accepted from flexisip server*/
}

void ForkMessageContext::onAcceptanceTimer(){
	LOGD("ForkMessageContext::onAcceptanceTimer()");
	acceptMessage();
	su_timer_destroy(mAcceptanceTimer);
	mAcceptanceTimer=NULL;
}

void ForkMessageContext::sOnAcceptanceTimer(su_root_magic_t* magic, su_timer_t* t, su_timer_arg_t* arg){
	static_cast<ForkMessageContext*>(arg)->onAcceptanceTimer();
}

bool isMessageARCSFileTransferMessage(shared_ptr<RequestSipEvent> &ev) {
	sip_t* sip = ev->getSip();
	if (strncasecmp(sip->sip_request->rq_method_name, "MESSAGE", strlen(sip->sip_request->rq_method_name)) == 0) {
		if (sip->sip_content_type->c_type && strcasecmp (sip->sip_content_type->c_type, "application/vnd.gsma.rcs-ft-http+xml")==0) {
			return true;
		}
	}
	return false;
}

bool isConversionFromRcsToExternalBodyUrlNeeded(shared_ptr<ExtendedContact> &ec) {
	list<string> acceptHeaders = ec->mAcceptHeader;
	if (acceptHeaders.size() == 0) {
		return true;
	}

	for (auto it = acceptHeaders.begin(); it != acceptHeaders.end(); ++it) {
		string header = *it;
		if (header.compare("application/vnd.gsma.rcs-ft-http+xml") == 0) {
			return false;
		}
	}
	return true;
}

void ForkMessageContext::onNewBranch(const shared_ptr<BranchInfo> &br) {
	if (br->mUid.size()>0){
		/*check for a branch already existing with this uid, and eventually clean it*/
		shared_ptr<BranchInfo> tmp=findBranchByUid(br->mUid);
		if (tmp){
			removeBranch(tmp);
		}
	} else SLOGE << "No unique id found for contact";

	// Convert a RCS file transfer message to an external body url message if contact doesn't support it
	shared_ptr<RequestSipEvent> &ev = br->mRequest;
	if (ev && isMessageARCSFileTransferMessage(ev)) {
		shared_ptr<ExtendedContact> &ec = br->mContact;
		if (ec && isConversionFromRcsToExternalBodyUrlNeeded(ec)) {
			sip_t *sip = ev->getSip();
			if (sip) {
				sip_payload_t *payload = sip->sip_payload;

				xercesc::XMLPlatformUtils::Initialize();
				if (payload) {
					std::unique_ptr<fthttp::File> file_transfer_infos = NULL;
					char *file_url = NULL;

					try {
						istringstream data(payload->pl_data);
						file_transfer_infos = parseFile(data, xml_schema::Flags::dont_validate);
					} catch (const xml_schema::Exception& e) {
						SLOGE << "Can't parse the content of the message";
					}

					if (file_transfer_infos != NULL) {
						File::File_infoSequence &infos = file_transfer_infos->getFile_info();
						if (infos.size() >= 1) {
							for (File::File_infoConstIterator i (infos.begin()); i != infos.end(); ++i) {
								const File::File_infoType &info = (*i);
								const File_info::DataType &data = info.getData();
								const Data::UrlType &url = data.getUrl();
								file_url = (char *)url.c_str();
								break;
							}
						}
					}

					if (file_url) {
						char new_content_type[256];
						sip->sip_payload = sip_payload_make(ev->getHome(), NULL);
						sip->sip_content_length = sip_content_length_make(ev->getHome(), 0);
						sprintf(new_content_type, "message/external-body;access-type=URL;URL=\"%s\"", file_url);
						sip->sip_content_type = sip_content_type_make(ev->getHome(), new_content_type);
					}
				}
				xercesc::XMLPlatformUtils::Terminate();
			}
		}
	}
}

bool ForkMessageContext::onNewRegister(const url_t *dest, const string &uid){
	bool already_have_transaction=!ForkContext::onNewRegister(dest,uid);
	if (already_have_transaction) return false;
	if (uid.size()>0){
		shared_ptr<BranchInfo> br=findBranchByUid(uid);
		if (br==NULL){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this is a new client instance.");
			return true;
		}else if (needsDelivery(br->getStatus())){
			//this is a new client instance or a client for which the message wasn't delivered yet. The message needs to be delivered.
			LOGD("ForkMessageContext::onNewRegister(): this client is reconnecting but was not delivered before.");
			return true;
		}
	}
	//in all other case we can accept a new transaction only if the message hasn't been delivered already.
	LOGD("Message has been delivered %i times.",mDeliveredCount);
	return mDeliveredCount==0;
}

<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file main.cxx
 *
 * An application which acts as an openlcb hub with the GC protocol.
 *
 * @author Balazs Racz
 * @date 3 Aug 2013
 */

#include <stdio.h>
#include <unistd.h>

#include <memory>

#include "os/os.h"
#include "utils/Hub.hxx"
#include "utils/GridConnectHub.hxx"
#include "utils/GcTcpHub.hxx"
#include "executor/Executor.hxx"
#include "executor/Service.hxx"

Executor<1> g_executor("g_executor", 0, 1024);
Service g_service(&g_executor);
CanHubFlow can_hub0(&g_service);
GcPacketPrinter packet_printer(&can_hub0);

extern "C" {
extern int GC_GENERATE_NEWLINES;
int GC_GENERATE_NEWLINES = 1;
}

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char *argv[])
{
    GcTcpHub hub(&can_hub0, 12021);
    while (1)
    {
        sleep(1);
    }
    return 0;
}
<commit_msg>Fixes override to gridconnect-generate-newlines.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file main.cxx
 *
 * An application which acts as an openlcb hub with the GC protocol.
 *
 * @author Balazs Racz
 * @date 3 Aug 2013
 */

#include <stdio.h>
#include <unistd.h>

#include <memory>

#include "os/os.h"
#include "utils/constants.hxx"
#include "utils/Hub.hxx"
#include "utils/GridConnectHub.hxx"
#include "utils/GcTcpHub.hxx"
#include "executor/Executor.hxx"
#include "executor/Service.hxx"

Executor<1> g_executor("g_executor", 0, 1024);
Service g_service(&g_executor);
CanHubFlow can_hub0(&g_service);
GcPacketPrinter packet_printer(&can_hub0);

OVERRIDE_CONST(gc_generate_newlines, 1);

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char *argv[])
{
    GcTcpHub hub(&can_hub0, 12021);
    while (1)
    {
        sleep(1);
    }
    return 0;
}
<|endoftext|>