<commit_before>#include "astutil.h"
#include "expr.h"
#include "passes.h"
#include "stmt.h"
#include "symbol.h"
#include "type.h"
#include "symscope.h"
#include "stringutil.h"

static void
check_redefinition(Symbol* sym) {
  if (sym->isCompilerTemp)
    return;
  if (sym->parentScope == rootScope)
    return;
  if (sym->overloadNext) {
    int count = 0;
    for (Symbol* tmp = sym; tmp; tmp = tmp->overloadNext) {
      if (!tmp->getFnSymbol()) {
        count++;
      }
    }
    if (count >= 2) {
      char* redefinitionLocations = "";
      for (Symbol* tmp = sym->overloadNext; tmp; tmp = tmp->overloadNext) {
        if (!tmp->getFnSymbol()) {
          redefinitionLocations =
            stringcat(redefinitionLocations, "\n  ", tmp->stringLoc());
        }
      }
      USR_FATAL(sym, "'%s' has multiple definitions, redefined at:%s",
                sym->name, redefinitionLocations);
    }
  }
}

static void
check_functions(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  Vec<CallExpr*> rets;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (CallExpr* ret = dynamic_cast<CallExpr*>(ast))
      if (ret->isPrimitive(PRIMITIVE_RETURN) && ret->parentSymbol == fn)
        rets.add(ret);
  }
  if (rets.n == 0)
    return;
  bool returns_void = false;
  forv_Vec(CallExpr, ret, rets) {
    if (SymExpr* sym = dynamic_cast<SymExpr*>(ret->get(1)))
      if (sym->var == gVoid)
        returns_void = true;
  }
  forv_Vec(CallExpr, ret, rets) {
    if (returns_void && ret->typeInfo() != dtVoid)
      if (fn->getModule()->initFn == fn)
        USR_FATAL(ret, "return statement is not in a function");
      else
        USR_FATAL(fn, "Not all function returns return a value");
  }
}

static void
check_parsed_vars(VarSymbol* var) {
  if (var->isParam() && !var->immediate)
    if (!var->defPoint->init &&
        (dynamic_cast<FnSymbol*>(var->defPoint->parentSymbol) ||
         dynamic_cast<ModuleSymbol*>(var->defPoint->parentSymbol)) &&
        !dynamic_cast<FnSymbol*>(var->defPoint->parentScope->astParent))
      USR_FATAL(var, "Top-level params must be initialized.");
  if (var->varClass == VAR_CONFIG &&
      var->defPoint->parentSymbol != var->getModule()->initFn) {
    char *varType = NULL;
    switch (var->consClass) {
      case VAR_VAR:   varType = "variables"; break;
      case VAR_CONST: varType = "constants"; break;
      case VAR_PARAM: varType = "parameters"; break;
      default: INT_FATAL("Illegal constant class.");
    }
    USR_FATAL_CONT(var->defPoint,
                   "Configuration %s only allowed at module scope.", varType);
  }
}

static void
check_named_arguments(CallExpr* call) {
  Vec<char*> names;
  for_actuals(expr, call) {
    if (NamedExpr* named = dynamic_cast<NamedExpr*>(expr)) {
      forv_Vec(char, name, names) {
        if (!strcmp(name, named->name))
          USR_FATAL(named, "The named argument '%s' is used more "
                    "than once in the same function call.", name);
      }
      names.add(named->name);
    }
  }
}

void
checkParsed(void) {
  Vec<BaseAST*> asts;
  collect_asts(&asts);
  forv_Vec(BaseAST, ast, asts) {

    if (CallExpr* call = dynamic_cast<CallExpr*>(ast))
      check_named_arguments(call);

    if (DefExpr* def = dynamic_cast<DefExpr*>(ast)) {
      if (!strcmp(def->sym->name, "_")) {
        USR_FATAL("Symbol cannot be named \"_\"");
      } else if (dynamic_cast<VarSymbol*>(def->sym)) {
        if (def->sym->hasPragma("internal var"))
          def->sym->isCompilerTemp = true;
        if (!def->init && !def->exprType && !def->sym->isCompilerTemp)
          if (dynamic_cast<BlockStmt*>(def->parentExpr))
            USR_FATAL_CONT(def->sym,
                           "Variable '%s' is not initialized or has no type",
                           def->sym->name);
      }
    }

    if (Symbol* sym = dynamic_cast<Symbol*>(ast))
      check_redefinition(sym);

    if (VarSymbol* a = dynamic_cast<VarSymbol*>(ast))
      check_parsed_vars(a);
    else if (FnSymbol* fn = dynamic_cast<FnSymbol*>(ast))
      check_functions(fn);
  }
}

void
checkNormalized(void) {
  forv_Vec(FnSymbol, fn, gFns) {
    if (fn->fnClass == FN_ITERATOR) {
      for_formals(formal, fn) {
        if (formal->intent == INTENT_IN ||
            formal->intent == INTENT_INOUT ||
            formal->intent == INTENT_OUT ||
            formal->intent == INTENT_REF) {
          USR_FATAL(formal, "formal argument of iterator cannot have intent");
        }
      }
    }

    // do not check body of nested function (would be again)
    if (fn->defPoint->parentSymbol->astType == SYMBOL_FN)
      continue;

    ModuleSymbol* mod = fn->getModule();
    Vec<char*> reported;
    Vec<BaseAST*> asts;
    Vec<Symbol*> defined;
    collect_asts_postorder(&asts, fn);
    forv_Vec(BaseAST, ast, asts) {
      if (CallExpr* call = dynamic_cast<CallExpr*>(ast)) {
        if (SymExpr* base = dynamic_cast<SymExpr*>(call->baseExpr))
          if (dynamic_cast<ModuleSymbol*>(base->var))
            USR_FATAL_CONT(call, "illegal use of module '%s'", base->var->name);
        if (call->isPrimitive(PRIMITIVE_MOVE))
          defined.set_add(dynamic_cast<SymExpr*>(call->get(1))->var);
      } else if (SymExpr* sym = dynamic_cast<SymExpr*>(ast)) {
        if (CallExpr* call = dynamic_cast<CallExpr*>(sym->parentExpr))
          if (call->isPrimitive(PRIMITIVE_MOVE) && call->get(1) == sym)
            continue;
        if (dynamic_cast<VarSymbol*>(sym->var))
          if (sym->var->defPoint &&
              (sym->var->defPoint->parentSymbol == fn ||
               (sym->var->defPoint->parentSymbol == mod && mod->initFn == fn)))
            if (!defined.set_in(sym->var))
              if (sym->var != fn->_this)
                USR_FATAL(sym, "'%s' used before defined", sym->var->name);
        CallExpr* parent = dynamic_cast<CallExpr*>(sym->parentExpr);
        if (!(parent && parent->baseExpr == sym))
          if (dynamic_cast<UnresolvedSymbol*>(sym->var)) {
            if (!reported.set_in(sym->var->name)) {
              USR_FATAL_CONT(sym, "'%s' undeclared (first use this function)",
                             sym->var->name);
              reported.set_add(sym->var->name);
            }
          }
      }
    }
  }
}

static void
check_resolved_syms(Symbol* var) {
  if (!var->isConst() && !var->isParam())
    return;
  if (VarSymbol* vs = dynamic_cast<VarSymbol*>(var))
    if (vs->immediate)
      return;
  if (var->defs.n > 1)
    USR_FATAL_CONT(var->defs.v[var->defs.n-1],
                   "Assigning to a constant expression");
  // need something like below to check constant assignment via refs
  forv_Vec(SymExpr, use, var->uses) {
    if (CallExpr* call = dynamic_cast<CallExpr*>(use->parentExpr))
      if (call->isPrimitive(PRIMITIVE_SET_REF))
        if (CallExpr* move = dynamic_cast<CallExpr*>(call->parentExpr))
          if (move->isPrimitive(PRIMITIVE_MOVE))
            if (SymExpr* lhs = dynamic_cast<SymExpr*>(move->get(1)))
              if (lhs->var->defs.n > 1)
                USR_FATAL_CONT(lhs->var->defs.v[lhs->var->defs.n-1], "Assigning to a constant expression");
  }
}

void
checkResolved(void) {
  compute_sym_uses();
  Vec<BaseAST*> asts;
  collect_asts(&asts);
  forv_Vec(BaseAST, ast, asts) {
    if (dynamic_cast<VarSymbol*>(ast) || dynamic_cast<ArgSymbol*>(ast))
      check_resolved_syms(dynamic_cast<Symbol*>(ast));
  }

  forv_Vec(TypeSymbol, type, gTypes) {
    if (EnumType* et = dynamic_cast<EnumType*>(type->type)) {
      for_alist(DefExpr, def, et->constants) {
        if (def->init) {
          SymExpr* sym = dynamic_cast<SymExpr*>(def->init);
          if (!sym || (dynamic_cast<VarSymbol*>(sym->var)->consClass != VAR_PARAM &&
                       !dynamic_cast<VarSymbol*>(sym->var)->immediate))
            USR_FATAL(def, "enumerator '%s' is not an int parameter", def->sym->name);
        }
      }
    }
  }
}
<commit_msg>Fixed braces around USR_FATAL in conditional.<commit_after>#include "astutil.h"
#include "expr.h"
#include "passes.h"
#include "stmt.h"
#include "symbol.h"
#include "type.h"
#include "symscope.h"
#include "stringutil.h"

static void
check_redefinition(Symbol* sym) {
  if (sym->isCompilerTemp)
    return;
  if (sym->parentScope == rootScope)
    return;
  if (sym->overloadNext) {
    int count = 0;
    for (Symbol* tmp = sym; tmp; tmp = tmp->overloadNext) {
      if (!tmp->getFnSymbol()) {
        count++;
      }
    }
    if (count >= 2) {
      char* redefinitionLocations = "";
      for (Symbol* tmp = sym->overloadNext; tmp; tmp = tmp->overloadNext) {
        if (!tmp->getFnSymbol()) {
          redefinitionLocations =
            stringcat(redefinitionLocations, "\n  ", tmp->stringLoc());
        }
      }
      USR_FATAL(sym, "'%s' has multiple definitions, redefined at:%s",
                sym->name, redefinitionLocations);
    }
  }
}

static void
check_functions(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  Vec<CallExpr*> rets;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (CallExpr* ret = dynamic_cast<CallExpr*>(ast))
      if (ret->isPrimitive(PRIMITIVE_RETURN) && ret->parentSymbol == fn)
        rets.add(ret);
  }
  if (rets.n == 0)
    return;
  bool returns_void = false;
  forv_Vec(CallExpr, ret, rets) {
    if (SymExpr* sym = dynamic_cast<SymExpr*>(ret->get(1)))
      if (sym->var == gVoid)
        returns_void = true;
  }
  forv_Vec(CallExpr, ret, rets) {
    if (returns_void && ret->typeInfo() != dtVoid) {
      if (fn->getModule()->initFn == fn) {
        USR_FATAL(ret, "return statement is not in a function");
      } else {
        USR_FATAL(fn, "Not all function returns return a value");
      }
    }
  }
}

static void
check_parsed_vars(VarSymbol* var) {
  if (var->isParam() && !var->immediate)
    if (!var->defPoint->init &&
        (dynamic_cast<FnSymbol*>(var->defPoint->parentSymbol) ||
         dynamic_cast<ModuleSymbol*>(var->defPoint->parentSymbol)) &&
        !dynamic_cast<FnSymbol*>(var->defPoint->parentScope->astParent))
      USR_FATAL(var, "Top-level params must be initialized.");
  if (var->varClass == VAR_CONFIG &&
      var->defPoint->parentSymbol != var->getModule()->initFn) {
    char *varType = NULL;
    switch (var->consClass) {
      case VAR_VAR:   varType = "variables"; break;
      case VAR_CONST: varType = "constants"; break;
      case VAR_PARAM: varType = "parameters"; break;
      default: INT_FATAL("Illegal constant class.");
    }
    USR_FATAL_CONT(var->defPoint,
                   "Configuration %s only allowed at module scope.", varType);
  }
}

static void
check_named_arguments(CallExpr* call) {
  Vec<char*> names;
  for_actuals(expr, call) {
    if (NamedExpr* named = dynamic_cast<NamedExpr*>(expr)) {
      forv_Vec(char, name, names) {
        if (!strcmp(name, named->name))
          USR_FATAL(named, "The named argument '%s' is used more "
                    "than once in the same function call.", name);
      }
      names.add(named->name);
    }
  }
}

void
checkParsed(void) {
  Vec<BaseAST*> asts;
  collect_asts(&asts);
  forv_Vec(BaseAST, ast, asts) {

    if (CallExpr* call = dynamic_cast<CallExpr*>(ast))
      check_named_arguments(call);

    if (DefExpr* def = dynamic_cast<DefExpr*>(ast)) {
      if (!strcmp(def->sym->name, "_")) {
        USR_FATAL("Symbol cannot be named \"_\"");
      } else if (dynamic_cast<VarSymbol*>(def->sym)) {
        if (def->sym->hasPragma("internal var"))
          def->sym->isCompilerTemp = true;
        if (!def->init && !def->exprType && !def->sym->isCompilerTemp)
          if (dynamic_cast<BlockStmt*>(def->parentExpr))
            USR_FATAL_CONT(def->sym,
                           "Variable '%s' is not initialized or has no type",
                           def->sym->name);
      }
    }

    if (Symbol* sym = dynamic_cast<Symbol*>(ast))
      check_redefinition(sym);

    if (VarSymbol* a = dynamic_cast<VarSymbol*>(ast))
      check_parsed_vars(a);
    else if (FnSymbol* fn = dynamic_cast<FnSymbol*>(ast))
      check_functions(fn);
  }
}

void
checkNormalized(void) {
  forv_Vec(FnSymbol, fn, gFns) {
    if (fn->fnClass == FN_ITERATOR) {
      for_formals(formal, fn) {
        if (formal->intent == INTENT_IN ||
            formal->intent == INTENT_INOUT ||
            formal->intent == INTENT_OUT ||
            formal->intent == INTENT_REF) {
          USR_FATAL(formal, "formal argument of iterator cannot have intent");
        }
      }
    }

    // do not check body of nested function (would be again)
    if (fn->defPoint->parentSymbol->astType == SYMBOL_FN)
      continue;

    ModuleSymbol* mod = fn->getModule();
    Vec<char*> reported;
    Vec<BaseAST*> asts;
    Vec<Symbol*> defined;
    collect_asts_postorder(&asts, fn);
    forv_Vec(BaseAST, ast, asts) {
      if (CallExpr* call = dynamic_cast<CallExpr*>(ast)) {
        if (SymExpr* base = dynamic_cast<SymExpr*>(call->baseExpr))
          if (dynamic_cast<ModuleSymbol*>(base->var))
            USR_FATAL_CONT(call, "illegal use of module '%s'", base->var->name);
        if (call->isPrimitive(PRIMITIVE_MOVE))
          defined.set_add(dynamic_cast<SymExpr*>(call->get(1))->var);
      } else if (SymExpr* sym = dynamic_cast<SymExpr*>(ast)) {
        if (CallExpr* call = dynamic_cast<CallExpr*>(sym->parentExpr))
          if (call->isPrimitive(PRIMITIVE_MOVE) && call->get(1) == sym)
            continue;
        if (dynamic_cast<VarSymbol*>(sym->var))
          if (sym->var->defPoint &&
              (sym->var->defPoint->parentSymbol == fn ||
               (sym->var->defPoint->parentSymbol == mod && mod->initFn == fn)))
            if (!defined.set_in(sym->var))
              if (sym->var != fn->_this)
                USR_FATAL(sym, "'%s' used before defined", sym->var->name);
        CallExpr* parent = dynamic_cast<CallExpr*>(sym->parentExpr);
        if (!(parent && parent->baseExpr == sym))
          if (dynamic_cast<UnresolvedSymbol*>(sym->var)) {
            if (!reported.set_in(sym->var->name)) {
              USR_FATAL_CONT(sym, "'%s' undeclared (first use this function)",
                             sym->var->name);
              reported.set_add(sym->var->name);
            }
          }
      }
    }
  }
}

static void
check_resolved_syms(Symbol* var) {
  if (!var->isConst() && !var->isParam())
    return;
  if (VarSymbol* vs = dynamic_cast<VarSymbol*>(var))
    if (vs->immediate)
      return;
  if (var->defs.n > 1)
    USR_FATAL_CONT(var->defs.v[var->defs.n-1],
                   "Assigning to a constant expression");
  // need something like below to check constant assignment via refs
  forv_Vec(SymExpr, use, var->uses) {
    if (CallExpr* call = dynamic_cast<CallExpr*>(use->parentExpr))
      if (call->isPrimitive(PRIMITIVE_SET_REF))
        if (CallExpr* move = dynamic_cast<CallExpr*>(call->parentExpr))
          if (move->isPrimitive(PRIMITIVE_MOVE))
            if (SymExpr* lhs = dynamic_cast<SymExpr*>(move->get(1)))
              if (lhs->var->defs.n > 1)
                USR_FATAL_CONT(lhs->var->defs.v[lhs->var->defs.n-1], "Assigning to a constant expression");
  }
}

void
checkResolved(void) {
  compute_sym_uses();
  Vec<BaseAST*> asts;
  collect_asts(&asts);
  forv_Vec(BaseAST, ast, asts) {
    if (dynamic_cast<VarSymbol*>(ast) || dynamic_cast<ArgSymbol*>(ast))
      check_resolved_syms(dynamic_cast<Symbol*>(ast));
  }

  forv_Vec(TypeSymbol, type, gTypes) {
    if (EnumType* et = dynamic_cast<EnumType*>(type->type)) {
      for_alist(DefExpr, def, et->constants) {
        if (def->init) {
          SymExpr* sym = dynamic_cast<SymExpr*>(def->init);
          if (!sym || (dynamic_cast<VarSymbol*>(sym->var)->consClass != VAR_PARAM &&
                       !dynamic_cast<VarSymbol*>(sym->var)->immediate))
            USR_FATAL(def, "enumerator '%s' is not an int parameter", def->sym->name);
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>#ifndef AFFINE_INVARIANT_FEATURES_FEATURE_PARAMETERS
#define AFFINE_INVARIANT_FEATURES_FEATURE_PARAMETERS

#include <string>

#include <affine_invariant_features/cv_serializable.hpp>

#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>

namespace affine_invariant_features {

//
// A base class for parameter sets of feature detectors and descriptor extractors
//

struct FeatureParameters : public CvSerializable {
public:
  FeatureParameters() {}

  virtual ~FeatureParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const = 0;
};

//
// SIFT
//

struct SIFTParameters : public FeatureParameters {
public:
  // opencv does not provide interfaces to access default SIFT parameters.
  // thus values below are copied from online reference.
  SIFTParameters()
      : nfeatures(0), nOctaveLayers(3), contrastThreshold(0.04), edgeThreshold(10.), sigma(1.6) {}

  virtual ~SIFTParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    return cv::xfeatures2d::SIFT::create(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold,
                                         sigma);
  }

  virtual void read(const cv::FileNode &fn) {
    fn["nfeatures"] >> nfeatures;
    fn["nOctaveLayers"] >> nOctaveLayers;
    fn["contrastThreshold"] >> contrastThreshold;
    fn["edgeThreshold"] >> edgeThreshold;
    fn["sigma"] >> sigma;
  }

  virtual void write(cv::FileStorage &fs) const {
    fs << "nfeatures" << nfeatures;
    fs << "nOctaveLayers" << nOctaveLayers;
    fs << "contrastThreshold" << contrastThreshold;
    fs << "edgeThreshold" << edgeThreshold;
    fs << "sigma" << sigma;
  }

  virtual std::string getDefaultName() const { return "SIFTParameters"; }

public:
  int nfeatures;
  int nOctaveLayers;
  double contrastThreshold;
  double edgeThreshold;
  double sigma;
};

//
// AKAZE
//

struct AKAZEParameters : public FeatureParameters {
public:
  AKAZEParameters()
      : descriptorType(defaultAKAZE().getDescriptorType()),
        descriptorSize(defaultAKAZE().getDescriptorSize()),
        descriptorChannels(defaultAKAZE().getDescriptorChannels()),
        threshold(defaultAKAZE().getThreshold()), nOctaves(defaultAKAZE().getNOctaves()),
        nOctaveLayers(defaultAKAZE().getNOctaveLayers()),
        diffusivity(defaultAKAZE().getDiffusivity()) {}

  virtual ~AKAZEParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    return cv::AKAZE::create(descriptorType, descriptorSize, descriptorChannels, threshold,
                             nOctaves, nOctaveLayers, diffusivity);
  }

  virtual void read(const cv::FileNode &fn) {
    fn["descriptorType"] >> descriptorType;
    fn["descriptorSize"] >> descriptorSize;
    fn["descriptorChannels"] >> descriptorChannels;
    fn["threshold"] >> threshold;
    fn["nOctaves"] >> nOctaves;
    fn["nOctaveLayers"] >> nOctaveLayers;
    fn["diffusivity"] >> diffusivity;
  }

  virtual void write(cv::FileStorage &fs) const {
    fs << "descriptorType" << descriptorType;
    fs << "descriptorSize" << descriptorSize;
    fs << "descriptorChannels" << descriptorChannels;
    fs << "threshold" << threshold;
    fs << "nOctaves" << nOctaves;
    fs << "nOctaveLayers" << nOctaveLayers;
    fs << "diffusivity" << diffusivity;
  }

  virtual std::string getDefaultName() const { return "AKAZEParameters"; }

protected:
  static const cv::AKAZE &defaultAKAZE() {
    static cv::Ptr< cv::AKAZE > default_akaze(cv::AKAZE::create());
    CV_Assert(default_akaze);
    return *default_akaze;
  }

public:
  int descriptorType;
  int descriptorSize;
  int descriptorChannels;
  float threshold;
  int nOctaves;
  int nOctaveLayers;
  int diffusivity;
};

//
// BRISK
//

struct BRISKParameters : public FeatureParameters {
public:
  // Note: like SIFT, no interface to access default BRISK parameters
  BRISKParameters() : threshold(30), nOctaves(3), patternScale(1.0f) {}

  virtual ~BRISKParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    return cv::BRISK::create(threshold, nOctaves, patternScale);
  }

  virtual void read(const cv::FileNode &fn) {
    fn["threshold"] >> threshold;
    fn["nOctaves"] >> nOctaves;
    fn["patternScale"] >> patternScale;
  }

  virtual void write(cv::FileStorage &fs) const {
    fs << "threshold" << threshold;
    fs << "nOctaves" << nOctaves;
    fs << "patternScale" << patternScale;
  }

  virtual std::string getDefaultName() const { return "BRISKParameters"; }

public:
  int threshold;
  int nOctaves;
  float patternScale;
};

//
// Utility functions to create or read variants of FeatureParameters
//

#define AIF_RETURN_IF_CREATE(type)                                                                 \
  do {                                                                                \
    const cv::Ptr< type > params(new type());                                                      \
    if (type_name == params->getDefaultName()) {                                                   \
      return params;                                                                               \
    }                                                                                \
  } while (false)

static inline cv::Ptr< FeatureParameters > createFeatureParameters(const std::string &type_name) {
  AIF_RETURN_IF_CREATE(AKAZEParameters);
  AIF_RETURN_IF_CREATE(BRISKParameters);
  AIF_RETURN_IF_CREATE(SIFTParameters);
  return cv::Ptr< FeatureParameters >();
}

#define AIF_RETURN_IF_LOAD(type)                                                                   \
  do {                                                                                \
    const cv::Ptr< type > params(load< type >(fn));                                                \
    if (params) {                                                                                \
      return params;                                                                               \
    }                                                                                \
  } while (false)

template <> cv::Ptr< FeatureParameters > load< FeatureParameters >(const cv::FileNode &fn) {
  AIF_RETURN_IF_LOAD(AKAZEParameters);
  AIF_RETURN_IF_LOAD(BRISKParameters);
  AIF_RETURN_IF_LOAD(SIFTParameters);
  return cv::Ptr< FeatureParameters >();
}
}

#endif<commit_msg>add a meta parameter set AIFParameters<commit_after>#ifndef AFFINE_INVARIANT_FEATURES_FEATURE_PARAMETERS
#define AFFINE_INVARIANT_FEATURES_FEATURE_PARAMETERS

#include <string>

#include <affine_invariant_features/affine_invariant_feature.hpp>
#include <affine_invariant_features/cv_serializable.hpp>

#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/xfeatures2d.hpp>

namespace affine_invariant_features {

//
// A base class for parameter sets of feature detectors and descriptor extractors
//

struct FeatureParameters : public CvSerializable {
public:
  FeatureParameters() {}

  virtual ~FeatureParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const = 0;
};

//
// Affine invariant sampled feature
//

static cv::Ptr< FeatureParameters > createFeatureParameters(const std::string &);

struct AIFParameters : public std::vector< cv::Ptr< FeatureParameters > >,
                       public FeatureParameters {
public:
  AIFParameters() {}

  virtual ~AIFParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    switch (size()) {
    case 0:
      return cv::Ptr< cv::Feature2D >();
    case 1:
      return AffineInvariantFeature::create(at(0) ? at(0)->createFeature()
                                                  : cv::Ptr< cv::Feature2D >());
    default:
      return AffineInvariantFeature::create(
          at(0) ? at(0)->createFeature() : cv::Ptr< cv::Feature2D >(),
          at(1) ? at(1)->createFeature() : cv::Ptr< cv::Feature2D >());
    }
  }

  virtual void read(const cv::FileNode &fn) {
    clear();
    for (cv::FileNodeIterator node = fn.begin(); node != fn.end(); ++node) {
      if (!(*node).isNamed()) { // operator-> did not work
        continue;
      }
      const cv::Ptr< FeatureParameters > p(createFeatureParameters((*node).name()));
      if (!p) {
        continue;
      }
      p->read(*node);
      push_back(p);
    }
  }

  virtual void write(cv::FileStorage &fs) const {
    for (std::vector< cv::Ptr< FeatureParameters > >::const_iterator p = begin(); p != end(); ++p) {
      if (!(*p)) {
        continue;
      }
      fs << (*p)->getDefaultName() << "{";
      (*p)->write(fs);
      fs << "}";
    }
  }

  virtual std::string getDefaultName() const { return "AIFParameters"; }
};

//
// SIFT
//

struct SIFTParameters : public FeatureParameters {
public:
  // opencv does not provide interfaces to access default SIFT parameters.
  // thus values below are copied from online reference.
  SIFTParameters()
      : nfeatures(0), nOctaveLayers(3), contrastThreshold(0.04), edgeThreshold(10.), sigma(1.6) {}

  virtual ~SIFTParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    return cv::xfeatures2d::SIFT::create(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold,
                                         sigma);
  }

  virtual void read(const cv::FileNode &fn) {
    fn["nfeatures"] >> nfeatures;
    fn["nOctaveLayers"] >> nOctaveLayers;
    fn["contrastThreshold"] >> contrastThreshold;
    fn["edgeThreshold"] >> edgeThreshold;
    fn["sigma"] >> sigma;
  }

  virtual void write(cv::FileStorage &fs) const {
    fs << "nfeatures" << nfeatures;
    fs << "nOctaveLayers" << nOctaveLayers;
    fs << "contrastThreshold" << contrastThreshold;
    fs << "edgeThreshold" << edgeThreshold;
    fs << "sigma" << sigma;
  }

  virtual std::string getDefaultName() const { return "SIFTParameters"; }

public:
  int nfeatures;
  int nOctaveLayers;
  double contrastThreshold;
  double edgeThreshold;
  double sigma;
};

//
// AKAZE
//

struct AKAZEParameters : public FeatureParameters {
public:
  AKAZEParameters()
      : descriptorType(defaultAKAZE().getDescriptorType()),
        descriptorSize(defaultAKAZE().getDescriptorSize()),
        descriptorChannels(defaultAKAZE().getDescriptorChannels()),
        threshold(defaultAKAZE().getThreshold()), nOctaves(defaultAKAZE().getNOctaves()),
        nOctaveLayers(defaultAKAZE().getNOctaveLayers()),
        diffusivity(defaultAKAZE().getDiffusivity()) {}

  virtual ~AKAZEParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    return cv::AKAZE::create(descriptorType, descriptorSize, descriptorChannels, threshold,
                             nOctaves, nOctaveLayers, diffusivity);
  }

  virtual void read(const cv::FileNode &fn) {
    fn["descriptorType"] >> descriptorType;
    fn["descriptorSize"] >> descriptorSize;
    fn["descriptorChannels"] >> descriptorChannels;
    fn["threshold"] >> threshold;
    fn["nOctaves"] >> nOctaves;
    fn["nOctaveLayers"] >> nOctaveLayers;
    fn["diffusivity"] >> diffusivity;
  }

  virtual void write(cv::FileStorage &fs) const {
    fs << "descriptorType" << descriptorType;
    fs << "descriptorSize" << descriptorSize;
    fs << "descriptorChannels" << descriptorChannels;
    fs << "threshold" << threshold;
    fs << "nOctaves" << nOctaves;
    fs << "nOctaveLayers" << nOctaveLayers;
    fs << "diffusivity" << diffusivity;
  }

  virtual std::string getDefaultName() const { return "AKAZEParameters"; }

protected:
  static const cv::AKAZE &defaultAKAZE() {
    static cv::Ptr< cv::AKAZE > default_akaze(cv::AKAZE::create());
    CV_Assert(default_akaze);
    return *default_akaze;
  }

public:
  int descriptorType;
  int descriptorSize;
  int descriptorChannels;
  float threshold;
  int nOctaves;
  int nOctaveLayers;
  int diffusivity;
};

//
// BRISK
//

struct BRISKParameters : public FeatureParameters {
public:
  // Note: like SIFT, no interface to access default BRISK parameters
  BRISKParameters() : threshold(30), nOctaves(3), patternScale(1.0f) {}

  virtual ~BRISKParameters() {}

  virtual cv::Ptr< cv::Feature2D > createFeature() const {
    return cv::BRISK::create(threshold, nOctaves, patternScale);
  }

  virtual void read(const cv::FileNode &fn) {
    fn["threshold"] >> threshold;
    fn["nOctaves"] >> nOctaves;
    fn["patternScale"] >> patternScale;
  }

  virtual void write(cv::FileStorage &fs) const {
    fs << "threshold" << threshold;
    fs << "nOctaves" << nOctaves;
    fs << "patternScale" << patternScale;
  }

  virtual std::string getDefaultName() const { return "BRISKParameters"; }

public:
  int threshold;
  int nOctaves;
  float patternScale;
};

//
// Utility functions to create or read variants of FeatureParameters
//

#define AIF_RETURN_IF_CREATE(type)                                                                 \
  do {                                                                                \
    const cv::Ptr< type > params(new type());                                                      \
    if (type_name == params->getDefaultName()) {                                                   \
      return params;                                                                               \
    }                                                                                \
  } while (false)

static inline cv::Ptr< FeatureParameters > createFeatureParameters(const std::string &type_name) {
  AIF_RETURN_IF_CREATE(AIFParameters);
  AIF_RETURN_IF_CREATE(AKAZEParameters);
  AIF_RETURN_IF_CREATE(BRISKParameters);
  AIF_RETURN_IF_CREATE(SIFTParameters);
  return cv::Ptr< FeatureParameters >();
}

#define AIF_RETURN_IF_LOAD(type)                                                                   \
  do {                                                                                \
    const cv::Ptr< type > params(load< type >(fn));                                                \
    if (params) {                                                                                \
      return params;                                                                               \
    }                                                                                \
  } while (false)

template <> cv::Ptr< FeatureParameters > load< FeatureParameters >(const cv::FileNode &fn) {
  AIF_RETURN_IF_LOAD(AIFParameters);
  AIF_RETURN_IF_LOAD(AKAZEParameters);
  AIF_RETURN_IF_LOAD(BRISKParameters);
  AIF_RETURN_IF_LOAD(SIFTParameters);
  return cv::Ptr< FeatureParameters >();
}
}

#endif<|endoftext|>


<commit_before>// Copyright (c) 2016 Pierre Fourgeaud
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "./core/fileaccess.h"
#include <logger.h>

namespace CodeHero {

FileAccess::FileAccess() {}

FileAccess::~FileAccess() {
    Close();
}

Error FileAccess::Open(const std::string& iFilename, Flags iFlags) {
    Close();

    std::string modeString;
    switch (iFlags) {
    case READ:       modeString = "rb"; break;
    case WRITE:      modeString = "wb"; break;
    case READ_WRITE: modeString = "rb+"; break;
    default: return ERR_INVALID_PARAMETER;
    };

    LOGD2 << "[FileAccess::Open]: Opening " << iFilename << " with mode " << modeString << std::endl;

    m_pFile = std::fopen(iFilename.c_str(), modeString.c_str());
    m_Name = iFilename;

    return !IsOpen() ? ERR_FILE_NOT_FOUND : OK;
}

void FileAccess::Close() {
    if (!IsOpen()) { return; }

    LOGD2 << "[FileAccess::Close]: Closing " << m_Name << "." << std::endl;

    fclose(m_pFile);
    m_pFile = nullptr;
}

int FileAccess::Read(uint8_t* oData, int iLength) {
    if (!IsOpen()) {
        m_LastError = ERR_NO_FILE_OPENED;
        return 0;
    }

    int res = std::fread(oData, sizeof(uint8_t), iLength, m_pFile);
    _CheckErrors();
    return res;
}

uint8_t FileAccess::Read8() {
    uint8_t byte = 0;

    Read(&byte, 1);
    return byte;
}

uint16_t FileAccess::Read16() {
    uint16_t res = 0;

    uint8_t a = Read8();
    uint8_t b = Read8();

    res = b;
    res <<= 8;
    res |= a;

    return res;
}

uint32_t FileAccess::Read32() {
    uint32_t res = 0;

    uint16_t a = Read16();
    uint16_t b = Read16();

    res = b;
    res <<= 16;
    res |= a;

    return res;
}

std::string FileAccess::ReadAll() {
    size_t size = GetSize();

    std::string out(size, '\0');
    Read((uint8_t*)&out[0], size);
    return std::move(out);
}

int32_t FileAccess::GetPos() {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    int32_t pos = std::ftell(m_pFile);
    return pos;
}

bool FileAccess::IsEOF() const {
    return IsOpen() && feof(m_pFile);
}

Error FileAccess::SeekTop() {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    std::rewind(m_pFile);
    return OK;
}

Error FileAccess::Seek(int64_t iPosition) {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    if (std::fseek(m_pFile, iPosition, SEEK_SET) != 0) {
        return FAILED;
    }

    return OK;
}

Error FileAccess::SeekEnd() {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    if (std::fseek(m_pFile, 0, SEEK_END) != 0) {
        return FAILED;
    }

    return OK;
}

int32_t FileAccess::GetSize() {
    if (m_Size < 0) {
        int32_t pos = std::ftell(m_pFile);
        SeekEnd();
        m_Size = std::ftell(m_pFile);
        Seek(pos);
    }

    return m_Size;
}

bool FileAccess::IsOpen() const {
    return m_pFile != nullptr;
}

bool FileAccess::Exists(const std::string& iFilename) {
    // TODO use new C++ features
    FILE* fp;
    fp = fopen(iFilename.c_str(), "rb");

    if (fp == nullptr) { return false; }

    fclose(fp);
    return true;
}

void FileAccess::_CheckErrors() {
    if (!IsOpen()) { return; }

    if (feof(m_pFile)) {
        m_LastError = ERR_FILE_EOF;
    }
}

}  // namespace CodeHero
<commit_msg>Make FileAccess::GetPos return 0 on error instead of '6'<commit_after>// Copyright (c) 2016 Pierre Fourgeaud
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "./core/fileaccess.h"
#include <logger.h>

namespace CodeHero {

FileAccess::FileAccess() {}

FileAccess::~FileAccess() {
    Close();
}

Error FileAccess::Open(const std::string& iFilename, Flags iFlags) {
    Close();

    std::string modeString;
    switch (iFlags) {
    case READ:       modeString = "rb"; break;
    case WRITE:      modeString = "wb"; break;
    case READ_WRITE: modeString = "rb+"; break;
    default: return ERR_INVALID_PARAMETER;
    };

    LOGD2 << "[FileAccess::Open]: Opening " << iFilename << " with mode " << modeString << std::endl;

    m_pFile = std::fopen(iFilename.c_str(), modeString.c_str());
    m_Name = iFilename;

    return !IsOpen() ? ERR_FILE_NOT_FOUND : OK;
}

void FileAccess::Close() {
    if (!IsOpen()) { return; }

    LOGD2 << "[FileAccess::Close]: Closing " << m_Name << "." << std::endl;

    fclose(m_pFile);
    m_pFile = nullptr;
}

int FileAccess::Read(uint8_t* oData, int iLength) {
    if (!IsOpen()) {
        m_LastError = ERR_NO_FILE_OPENED;
        return 0;
    }

    int res = std::fread(oData, sizeof(uint8_t), iLength, m_pFile);
    _CheckErrors();
    return res;
}

uint8_t FileAccess::Read8() {
    uint8_t byte = 0;

    Read(&byte, 1);
    return byte;
}

uint16_t FileAccess::Read16() {
    uint16_t res = 0;

    uint8_t a = Read8();
    uint8_t b = Read8();

    res = b;
    res <<= 8;
    res |= a;

    return res;
}

uint32_t FileAccess::Read32() {
    uint32_t res = 0;

    uint16_t a = Read16();
    uint16_t b = Read16();

    res = b;
    res <<= 16;
    res |= a;

    return res;
}

std::string FileAccess::ReadAll() {
    size_t size = GetSize();

    std::string out(size, '\0');
    Read((uint8_t*)&out[0], size);
    return std::move(out);
}

int32_t FileAccess::GetPos() {
    if (!IsOpen()) {
        return 0;
    }

    int32_t pos = std::ftell(m_pFile);
    return pos;
}

bool FileAccess::IsEOF() const {
    return IsOpen() && feof(m_pFile);
}

Error FileAccess::SeekTop() {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    std::rewind(m_pFile);
    return OK;
}

Error FileAccess::Seek(int64_t iPosition) {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    if (std::fseek(m_pFile, iPosition, SEEK_SET) != 0) {
        return FAILED;
    }

    return OK;
}

Error FileAccess::SeekEnd() {
    if (!IsOpen()) { return ERR_NO_FILE_OPENED; }

    if (std::fseek(m_pFile, 0, SEEK_END) != 0) {
        return FAILED;
    }

    return OK;
}

int32_t FileAccess::GetSize() {
    if (m_Size < 0) {
        int32_t pos = std::ftell(m_pFile);
        SeekEnd();
        m_Size = std::ftell(m_pFile);
        Seek(pos);
    }

    return m_Size;
}

bool FileAccess::IsOpen() const {
    return m_pFile != nullptr;
}

bool FileAccess::Exists(const std::string& iFilename) {
    // TODO use new C++ features
    FILE* fp;
    fp = fopen(iFilename.c_str(), "rb");

    if (fp == nullptr) { return false; }

    fclose(fp);
    return true;
}

void FileAccess::_CheckErrors() {
    if (!IsOpen()) { return; }

    if (feof(m_pFile)) {
        m_LastError = ERR_FILE_EOF;
    }
}

}  // namespace CodeHero
<|endoftext|>


<commit_before>/**************************************************************************
* @licence app begin@
*
* SPDX-License-Identifier: MPL-2.0
*
* \brief Test program for GNSS+SNS logging
*
*
* \author Helmut Schmidt <https://github.com/huirad>
*
* \copyright Copyright (C) 2015, Helmut Schmidt
*
* \license
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
* this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @licence end@
**************************************************************************/

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#include "poslog.h"
#include "gnsslog.h"
#include "snslog.h"
#if (DLT_ENABLED)
#include "dlt.h"
#endif

#include <syslog.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <inttypes.h>

#include "gnss-init.h"
#include "gnss.h"
#include "gnss-status.h"
#include "sns-init.h"

/**
 * Double buffer for log strings
 * Purpose: avoid blocking of callback functions by I/O
 * Multiple writer threads are allowed but only on reader thread
 */
class DBuf {

#define DBUF_STRING_SIZE 256
#define DBUF_NUM_LINES 512

    struct SBuf {
    public:
        char strings [DBUF_STRING_SIZE] [DBUF_NUM_LINES];
        uint16_t rnext;
        uint16_t wnext;
        SBuf(): rnext(0), wnext(0) {};
    };

    SBuf* wbuf;
    SBuf* rbuf;
    pthread_mutex_t wmutex;
    pthread_mutex_t rmutex;
public:

    DBuf()
    {
        pthread_mutex_init(&wmutex, NULL);
        pthread_mutex_init(&rmutex, NULL);
        wbuf = new(SBuf);
        rbuf = new(SBuf);
    }

    /**
     * Add a string to the buffer.
     * Return true on success, false on failure (e.g. buffer full).
     */
    bool write(const char* s)
    {
        bool retval = false;
        pthread_mutex_lock(&wmutex);
        if (s && wbuf && (wbuf->wnext < DBUF_NUM_LINES))
        {
            strncpy(wbuf->strings[wbuf->wnext], s, DBUF_STRING_SIZE-1);
            wbuf->strings[wbuf->wnext][DBUF_STRING_SIZE-1] = 0;
            wbuf->wnext++;
            retval = true;
        }
        pthread_mutex_unlock(&wmutex);
        return retval;
    }

    /**
     * Read next string from the buffer
     * Return NULL, if no more string available
     */
    const char* read()
    {
        const char* ret = NULL;
        pthread_mutex_lock(&rmutex);
        if (rbuf && (rbuf->rnext < rbuf->wnext) && (rbuf->rnext < DBUF_NUM_LINES) )
        {
            ret = rbuf->strings[rbuf->rnext];
            rbuf->rnext++;
        }
        pthread_mutex_unlock(&rmutex);
        return ret;
    }

    /**
     * Swap read and write buffers.
     * Clears read buffer before to ensure that new write buffer is empty.
     * Shall only be called by reader thread when read buffer has been
     * completely processed.
     */
    void swap()
    {
        SBuf* tmp;
        pthread_mutex_lock(&rmutex);
        rbuf->rnext = 0;
        rbuf->wnext = 0;
        pthread_mutex_lock(&wmutex);
        tmp = wbuf;
        wbuf = rbuf;
        rbuf = tmp;
        pthread_mutex_unlock(&wmutex);
        pthread_mutex_unlock(&rmutex);
    }

};

#define GNSS_INIT_MAX_RETRIES 30

//global variable to control the main loop - will be set by signal handlers or status callback
enum EExitCondition {
    eExitNone = 0,
    eExitSigInt,
    eExitGnssFailure
};

static volatile bool g_sigterm = false;
static volatile EExitCondition g_exit = eExitNone;
static volatile bool g_gnss_failure = false;
//global pointer to the double buffer
DBuf* g_dbuf = 0;
pthread_t g_logthread;
uint32_t g_write_failures = 0;
FILE* g_logfile = 0;

/**
 * Logger callback to add string to the double buffer.
 */
void dbufCb(const char* string)
{
    if (g_dbuf)
    {
        bool write_success = g_dbuf->write(string);
        if (!write_success)
        {
            g_write_failures++;
        }
        //printf("WBUF %s\n", string);
    }
}

/**
 * Background thread to write double buffer to a file.
 *
 */
void* loop_log_writer(void*)
{
    bool stop = false;
    //printf("LOGWRITER\n");
    while (g_dbuf && !stop && !g_sigterm)
    {
        const char* s = 0;
        //process read buffer - should always be empty
        while (s = g_dbuf->read())
        {
            printf("BUF1 %s\n", s);
        }
        //swap and process previous write buffer
        g_dbuf->swap();
        while (s = g_dbuf->read())
        {
            fprintf(g_logfile, "%s\n", s);
        }
        fflush(g_logfile);
        //printf("LOGWRITER SLEEP\n");
        if (g_exit == eExitNone)
        {
            sleep(2);
            //TODO it seems that only the main thread will be interrupted by the signal???
            //TODO CHECK how to force faster reaction
        }
        else
        {
            stop = true;
        }
        //printf("LOGWRITER WAKEUP\n");
    }
    //printf("LOGWRITER END\n");
}

static void sigHandler (int sig, siginfo_t *siginfo, void *context)
{
    if (sig == SIGINT)
    {
        g_exit = eExitSigInt;
        if (g_logfile)
        {
            //ensure that also the logger thread is interrupted
            //pthread_kill(g_logthread, sig);  //seems not to work somehow
        }
    }
    else
    if (sig == SIGTERM)
    {
        g_sigterm = true;
    }
}

static bool registerSigHandlers()
{
    bool is_success = true;

    struct sigaction action;
    memset (&action, '\0', sizeof(action));
    action.sa_sigaction = &sigHandler;
    action.sa_flags = SA_SIGINFO;

    if (sigaction(SIGINT, &action, NULL) < 0)
    {
        is_success = false;
    }
    if (sigaction(SIGTERM, &action, NULL) < 0)
    {
        is_success = false;
    }
    return is_success;
}

static void cbTime(const TGNSSTime time[], uint16_t numElements)
{
    gnssTimeLog(gnsslogGetTimestamp(), time, numElements);
}

static void cbPosition(const TGNSSPosition position[], uint16_t numElements)
{
    gnssPositionLog(gnsslogGetTimestamp(), position, numElements);
}

static void cbGNSSStatus(const TGNSSStatus *status)
{
    if (status && (status->validityBits & GNSS_STATUS_STATUS_VALID))
    {
        char status_string[64];
        sprintf(status_string, "#GNSS Status: %d", status->status);
        poslogAddString(status_string);
        if (status->status == GNSS_STATUS_FAILURE)
        {
            g_exit = eExitGnssFailure;
        }
    }
}

static void cbAccel(const TAccelerationData accelerationData[], uint16_t numElements)
{
    accelerationDataLog(snslogGetTimestamp(), accelerationData, numElements);
}

static void cbGyro(const TGyroscopeData gyroData[], uint16_t numElements)
{
    gyroscopeDataLog(snslogGetTimestamp(), gyroData, numElements);
}

int main (int argc, char *argv[])
{
    int major;
    int minor;
    int micro;
    char version_string[64];

    bool is_poslog_init_ok = false;
    bool is_sns_init_ok = false;
    bool is_sns_gyro_init_ok = false;
    bool is_sns_accel_init_ok = false;
    bool is_gnss_init_ok = false;
    int gnss_init_tries = 0;

    registerSigHandlers();

#if (DLT_ENABLED)
    DLT_REGISTER_APP("GLT","GNSS/SNS Logger");
#endif
    poslogSetFD(STDOUT_FILENO);
    is_poslog_init_ok = poslogInit();

    if (is_poslog_init_ok)
    {

        if(argv[1] && (g_logfile = fopen(argv[1], "a")))
        {
            g_dbuf = new(DBuf);
            poslogSetCB(dbufCb);
            pthread_create(&g_logthread, NULL, loop_log_writer, NULL);
            poslogSetActiveSinks(POSLOG_SINK_DLT|POSLOG_SINK_CB);
        }
        else
        {
            poslogSetActiveSinks(POSLOG_SINK_DLT|POSLOG_SINK_FD|POSLOG_SINK_CB);
        }

        gnssGetVersion(&major, &minor, &micro);
        sprintf(version_string, "0,0$GVGNSVER,%d,%d,%d", major, minor, micro);
        poslogAddString(version_string);
        snsGetVersion(&major, &minor, &micro);
        sprintf(version_string, "0,0$GVSNSVER,%d,%d,%d", major, minor, micro);
        poslogAddString(version_string);

        is_sns_init_ok = snsInit();
        if (is_sns_init_ok)
        {
            is_sns_gyro_init_ok = snsGyroscopeInit();
            if(is_sns_gyro_init_ok)
            {
                poslogAddString("#INF snsGyroscopeInit() success");
                snsGyroscopeRegisterCallback(&cbGyro);
            }
            is_sns_accel_init_ok = snsAccelerationInit();
            if (is_sns_accel_init_ok)
            {
                poslogAddString("#INF snsAccelerationInit() success");
                snsAccelerationRegisterCallback(&cbAccel);
            }
            if (!is_sns_gyro_init_ok && !is_sns_accel_init_ok)
            {
                is_sns_init_ok = false;
                snsDestroy();
            }
            else
            {
                poslogAddString("#INF snsInit() success");
            }
        }

        //GNSS device may be available a bit late after startup
        is_gnss_init_ok = gnssInit();
        while (!is_gnss_init_ok && (gnss_init_tries < GNSS_INIT_MAX_RETRIES) && (g_exit == eExitNone) && !g_sigterm)
        {
            sleep(1);
            is_gnss_init_ok = gnssInit();
            gnss_init_tries += 1;
        }
        if (is_gnss_init_ok)
        {
            poslogAddString("#INF gnssInit() success");
            gnssRegisterTimeCallback(&cbTime);
            gnssRegisterPositionCallback(&cbPosition);
            gnssRegisterStatusCallback(&cbGNSSStatus);
        }

        if (is_sns_init_ok || is_gnss_init_ok)
        {
            while(!g_sigterm && (g_exit == eExitNone))
            {
                sleep(1);
            }
        }
        else
        {
            poslogAddString("#ERR snsInit() or gnssInit() failure - terminating");
        }

        //if not interrupted by SIGTERM then we have time to cleanup
        if (!g_sigterm)
        {
            if (g_exit == eExitSigInt)
            {
                poslogAddString("#SIGINT");
            }
            if (g_exit == eExitGnssFailure)
            {
                poslogAddString("#GNSS_STATUS_FAILURE");
            }
            if (is_sns_init_ok)
            {
                if (is_sns_accel_init_ok)
                {
                    snsAccelerationDeregisterCallback(&cbAccel);
                    snsAccelerationDestroy();
                }
                if (is_sns_gyro_init_ok)
                {
                    snsGyroscopeRegisterCallback(&cbGyro);
                    snsGyroscopeDestroy();
                }
                snsDestroy();
            }
            if (is_gnss_init_ok)
            {
                gnssDeregisterStatusCallback(&cbGNSSStatus);
                gnssDeregisterPositionCallback(&cbPosition);
                gnssDeregisterTimeCallback(&cbTime);
                gnssDestroy();
            }
        }
        if (g_logfile)
        {
            pthread_join(g_logthread, NULL);
            fclose(g_logfile);
            printf("#Write Failures: %"PRIu64"\n", g_write_failures);
        }
        poslogDestroy();
    }

#if (DLT_ENABLED)
    DLT_UNREGISTER_APP();
#endif
}
<commit_msg>UDP log<commit_after>/**************************************************************************
* @licence app begin@
*
* SPDX-License-Identifier: MPL-2.0
*
* \brief Test program for GNSS+SNS logging
*
*
* \author Helmut Schmidt <https://github.com/huirad>
*
* \copyright Copyright (C) 2015, Helmut Schmidt
*
* \license
* This Source Code Form is subject to the terms of the
* Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
* this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @licence end@
**************************************************************************/

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#include "poslog.h"
#include "gnsslog.h"
#include "snslog.h"
#if (DLT_ENABLED)
#include "dlt.h"
#endif

#include <syslog.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <inttypes.h>

#include "gnss-init.h"
#include "gnss.h"
#include "gnss-status.h"
#include "sns-init.h"

/**
 * Double buffer for log strings
 * Purpose: avoid blocking of callback functions by I/O
 * Multiple writer threads are allowed but only on reader thread
 */
class DBuf {

#define DBUF_STRING_SIZE 256
#define DBUF_NUM_LINES 512

    struct SBuf {
    public:
        char strings [DBUF_STRING_SIZE] [DBUF_NUM_LINES];
        uint16_t rnext;
        uint16_t wnext;
        SBuf(): rnext(0), wnext(0) {};
    };

    SBuf* wbuf;
    SBuf* rbuf;
    pthread_mutex_t wmutex;
    pthread_mutex_t rmutex;
public:

    DBuf()
    {
        pthread_mutex_init(&wmutex, NULL);
        pthread_mutex_init(&rmutex, NULL);
        wbuf = new(SBuf);
        rbuf = new(SBuf);
    }

    /**
     * Add a string to the buffer.
     * Return true on success, false on failure (e.g. buffer full).
     */
    bool write(const char* s)
    {
        bool retval = false;
        pthread_mutex_lock(&wmutex);
        if (s && wbuf && (wbuf->wnext < DBUF_NUM_LINES))
        {
            strncpy(wbuf->strings[wbuf->wnext], s, DBUF_STRING_SIZE-1);
            wbuf->strings[wbuf->wnext][DBUF_STRING_SIZE-1] = 0;
            wbuf->wnext++;
            retval = true;
        }
        pthread_mutex_unlock(&wmutex);
        return retval;
    }

    /**
     * Read next string from the buffer
     * Return NULL, if no more string available
     */
    const char* read()
    {
        const char* ret = NULL;
        pthread_mutex_lock(&rmutex);
        if (rbuf && (rbuf->rnext < rbuf->wnext) && (rbuf->rnext < DBUF_NUM_LINES) )
        {
            ret = rbuf->strings[rbuf->rnext];
            rbuf->rnext++;
        }
        pthread_mutex_unlock(&rmutex);
        return ret;
    }

    /**
     * Swap read and write buffers.
     * Clears read buffer before to ensure that new write buffer is empty.
     * Shall only be called by reader thread when read buffer has been
     * completely processed.
     */
    void swap()
    {
        SBuf* tmp;
        pthread_mutex_lock(&rmutex);
        rbuf->rnext = 0;
        rbuf->wnext = 0;
        pthread_mutex_lock(&wmutex);
        tmp = wbuf;
        wbuf = rbuf;
        rbuf = tmp;
        pthread_mutex_unlock(&wmutex);
        pthread_mutex_unlock(&rmutex);
    }

};

#define GNSS_INIT_MAX_RETRIES 30

//global variable to control the main loop - will be set by signal handlers or status callback
enum EExitCondition {
    eExitNone = 0,
    eExitSigInt,
    eExitGnssFailure
};

static volatile bool g_sigterm = false;
static volatile EExitCondition g_exit = eExitNone;
static volatile bool g_gnss_failure = false;
//global pointer to the double buffer
DBuf* g_dbuf = 0;
pthread_t g_logthread;
uint32_t g_write_failures = 0;
FILE* g_logfile = 0;

/**
 * Logger callback to add string to the double buffer.
 */
void dbufCb(const char* string)
{
    if (g_dbuf)
    {
        bool write_success = g_dbuf->write(string);
        if (!write_success)
        {
            g_write_failures++;
        }
        //printf("WBUF %s\n", string);
    }
}

/**
 * Background thread to write double buffer to a file.
 *
 */
void* loop_log_writer(void*)
{
    bool stop = false;
    //printf("LOGWRITER\n");
    while (g_dbuf && !stop && !g_sigterm)
    {
        const char* s = 0;
        //process read buffer - should always be empty
        while (s = g_dbuf->read())
        {
            printf("BUF1 %s\n", s);
        }
        //swap and process previous write buffer
        g_dbuf->swap();
        while (s = g_dbuf->read())
        {
            fprintf(g_logfile, "%s\n", s);
        }
        fflush(g_logfile);
        //printf("LOGWRITER SLEEP\n");
        if (g_exit == eExitNone)
        {
            sleep(2);
            //TODO it seems that only the main thread will be interrupted by the signal???
            //TODO CHECK how to force faster reaction
        }
        else
        {
            stop = true;
        }
        //printf("LOGWRITER WAKEUP\n");
    }
    //printf("LOGWRITER END\n");
}

static void sigHandler (int sig, siginfo_t *siginfo, void *context)
{
    if (sig == SIGINT)
    {
        g_exit = eExitSigInt;
        if (g_logfile)
        {
            //ensure that also the logger thread is interrupted
            //pthread_kill(g_logthread, sig);  //seems not to work somehow
        }
    }
    else
    if (sig == SIGTERM)
    {
        g_sigterm = true;
    }
}

static bool registerSigHandlers()
{
    bool is_success = true;

    struct sigaction action;
    memset (&action, '\0', sizeof(action));
    action.sa_sigaction = &sigHandler;
    action.sa_flags = SA_SIGINFO;

    if (sigaction(SIGINT, &action, NULL) < 0)
    {
        is_success = false;
    }
    if (sigaction(SIGTERM, &action, NULL) < 0)
    {
        is_success = false;
    }
    return is_success;
}

static void cbTime(const TGNSSTime time[], uint16_t numElements)
{
    gnssTimeLog(gnsslogGetTimestamp(), time, numElements);
}

static void cbPosition(const TGNSSPosition position[], uint16_t numElements)
{
    gnssPositionLog(gnsslogGetTimestamp(), position, numElements);
}

static void cbGNSSStatus(const TGNSSStatus *status)
{
    if (status && (status->validityBits & GNSS_STATUS_STATUS_VALID))
    {
        char status_string[64];
        sprintf(status_string, "#GNSS Status: %d", status->status);
        poslogAddString(status_string);
        if (status->status == GNSS_STATUS_FAILURE)
        {
            g_exit = eExitGnssFailure;
        }
    }
}

static void cbAccel(const TAccelerationData accelerationData[], uint16_t numElements)
{
    accelerationDataLog(snslogGetTimestamp(), accelerationData, numElements);
}

static void cbGyro(const TGyroscopeData gyroData[], uint16_t numElements)
{
    gyroscopeDataLog(snslogGetTimestamp(), gyroData, numElements);
}

#define UDP_LOG
#ifdef UDP_LOG
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#define UDP_BUFLEN  128 //Max length of buffer
#define UDP_PORT 5701   //The port on which to listen for incoming data
#define UDP_LOGLEN  256

pthread_t g_udpthread;

void* loop_udp_log(void*)
{
    struct sockaddr_in si_me, si_other;
    int s;
    socklen_t slen = sizeof(si_other);
    ssize_t recv_len;
    char buf[UDP_BUFLEN];
    char log_string[UDP_LOGLEN];
    bool ok = true;

    //create a UDP socket
    if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        ok = false;
    }

    if (ok)
    {
        // zero out the structure
        memset((char *) &si_me, 0, sizeof(si_me));
        si_me.sin_family = AF_INET;
        si_me.sin_port = htons(UDP_PORT);
        si_me.sin_addr.s_addr = htonl(INADDR_ANY);

        //bind socket to port
        if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
        {
            ok = false;
        }
    }

    //keep listening for data
    while(ok)
    {
        //try to receive some data, this is a blocking call
        if ((recv_len = recvfrom(s, buf, UDP_BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1)
        {
            ok = false;
        }
        else
        {
            snprintf(log_string, UDP_LOGLEN-1, "%"PRIu64",0,$UDP,%s,%d,%s",
                snslogGetTimestamp(),
                inet_ntoa(si_other.sin_addr),
                ntohs(si_other.sin_port),
                buf
            );
            log_string[UDP_LOGLEN-1] = 0; //ensure that string is null-terminated
            poslogAddString(log_string);
        }
    }
    close(s);
}
#endif

int main (int argc, char *argv[])
{
    int major;
    int minor;
    int micro;
    char version_string[64];

    bool is_poslog_init_ok = false;
    bool is_sns_init_ok = false;
    bool is_sns_gyro_init_ok = false;
    bool is_sns_accel_init_ok = false;
    bool is_gnss_init_ok = false;
    int gnss_init_tries = 0;

    registerSigHandlers();

#if (DLT_ENABLED)
    DLT_REGISTER_APP("GLT","GNSS/SNS Logger");
#endif
    poslogSetFD(STDOUT_FILENO);
    is_poslog_init_ok = poslogInit();

    if (is_poslog_init_ok)
    {

        if(argv[1] && (g_logfile = fopen(argv[1], "a")))
        {
            g_dbuf = new(DBuf);
            poslogSetCB(dbufCb);
            pthread_create(&g_logthread, NULL, loop_log_writer, NULL);
            poslogSetActiveSinks(POSLOG_SINK_DLT|POSLOG_SINK_CB);
        }
        else
        {
            poslogSetActiveSinks(POSLOG_SINK_DLT|POSLOG_SINK_FD|POSLOG_SINK_CB);
        }

        gnssGetVersion(&major, &minor, &micro);
        sprintf(version_string, "0,0$GVGNSVER,%d,%d,%d", major, minor, micro);
        poslogAddString(version_string);
        snsGetVersion(&major, &minor, &micro);
        sprintf(version_string, "0,0$GVSNSVER,%d,%d,%d", major, minor, micro);
        poslogAddString(version_string);

#ifdef UDP_LOG
        pthread_create(&g_udpthread, NULL, loop_udp_log, NULL);
#endif
        is_sns_init_ok = snsInit();
        if (is_sns_init_ok)
        {
            is_sns_gyro_init_ok = snsGyroscopeInit();
            if(is_sns_gyro_init_ok)
            {
                poslogAddString("#INF snsGyroscopeInit() success");
                snsGyroscopeRegisterCallback(&cbGyro);
            }
            is_sns_accel_init_ok = snsAccelerationInit();
            if (is_sns_accel_init_ok)
            {
                poslogAddString("#INF snsAccelerationInit() success");
                snsAccelerationRegisterCallback(&cbAccel);
            }
            if (!is_sns_gyro_init_ok && !is_sns_accel_init_ok)
            {
                is_sns_init_ok = false;
                snsDestroy();
            }
            else
            {
                poslogAddString("#INF snsInit() success");
            }
        }

        //GNSS device may be available a bit late after startup
        is_gnss_init_ok = gnssInit();
        while (!is_gnss_init_ok && (gnss_init_tries < GNSS_INIT_MAX_RETRIES) && (g_exit == eExitNone) && !g_sigterm)
        {
            sleep(1);
            is_gnss_init_ok = gnssInit();
            gnss_init_tries += 1;
        }
        if (is_gnss_init_ok)
        {
            poslogAddString("#INF gnssInit() success");
            gnssRegisterTimeCallback(&cbTime);
            gnssRegisterPositionCallback(&cbPosition);
            gnssRegisterStatusCallback(&cbGNSSStatus);
        }

        if (is_sns_init_ok || is_gnss_init_ok)
        {
            while(!g_sigterm && (g_exit == eExitNone))
            {
                sleep(1);
            }
        }
        else
        {
            poslogAddString("#ERR snsInit() or gnssInit() failure - terminating");
        }

        //if not interrupted by SIGTERM then we have time to cleanup
        if (!g_sigterm)
        {
            if (g_exit == eExitSigInt)
            {
                poslogAddString("#SIGINT");
            }
            if (g_exit == eExitGnssFailure)
            {
                poslogAddString("#GNSS_STATUS_FAILURE");
            }
            if (is_sns_init_ok)
            {
                if (is_sns_accel_init_ok)
                {
                    snsAccelerationDeregisterCallback(&cbAccel);
                    snsAccelerationDestroy();
                }
                if (is_sns_gyro_init_ok)
                {
                    snsGyroscopeRegisterCallback(&cbGyro);
                    snsGyroscopeDestroy();
                }
                snsDestroy();
            }
            if (is_gnss_init_ok)
            {
                gnssDeregisterStatusCallback(&cbGNSSStatus);
                gnssDeregisterPositionCallback(&cbPosition);
                gnssDeregisterTimeCallback(&cbTime);
                gnssDestroy();
            }
        }
        if (g_logfile)
        {
            pthread_join(g_logthread, NULL);
            fclose(g_logfile);
            printf("#Write Failures: %"PRIu64"\n", g_write_failures);
        }
        poslogDestroy();
    }

#if (DLT_ENABLED)
    DLT_UNREGISTER_APP();
#endif
}
<|endoftext|>


<commit_before>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED
#define LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED

#include <luabind/config.hpp>
#include <luabind/detail/policy.hpp>    // for find_conversion_policy, etc
#include <luabind/detail/decorate_type.hpp>  // for decorated_type
#include <luabind/detail/primitives.hpp>  // for by_pointer, by_reference, etc
#include <luabind/detail/typetraits.hpp>  // for is_nonconst_pointer, is_nonconst_reference, etc
#include <new>                          // for operator new

namespace luabind { namespace detail
{
	template<int N>
	struct char_array
	{
		char storage[N];
	};

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_reference<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_const_reference<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_pointer<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_const_pointer<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_value<U>);

	template<class T>
	struct indirect_sizeof
	{
		static const int value = sizeof(indirect_sizeof_test(decorated_type<T>()));
	};

	namespace out_value_detail {

		template< int Size >
		struct temporary_storage_size {

			template< typename T, typename... Args >
			void construct(Args&&... args)
			{
				new (&m_storage) T(std::forward<Args>(args)...);
			}

			template<typename T>
			T& get() {
				return *reinterpret_cast<T*>(&m_storage);
			}

			template<typename T>
			const T& get() const {
				return *reinterpret_cast<T*>(&m_storage);
			}

			template<typename T>
			void destroy()
			{
				get<T>().~T();
			}

			typename std::aligned_storage<Size>::type m_storage;

		};

		template< typename T >
		struct temporary_storage_type {

			template< typename... Args >
			void construct(Args&&... args)
			{
				new (&m_storage) T(std::forward<Args>(args)...);
			}

			T& get() {
				return *reinterpret_cast<T*>(&m_storage);
			}

			const T& get() const {
				return *reinterpret_cast<T*>(&m_storage);
			}

			void destroy()
			{
				get().~T();
			}

			typename std::aligned_storage<sizeof(T),alignof(T)>::type m_storage;

		};

	}

	// See note in out_value_policy about why we're not templating
	// for the parameter type.
	template<typename T, class Policies = no_policies>
	struct out_value_converter
	{
		enum { consumed_args = 1 };

		T& to_cpp(lua_State* L, by_reference<T>, int index)
		{
			//specialized_converter_policy_n<1, Policies, T, lua_to_cpp> converter;
			storage_.construct(converter_.to_cpp(L, decorated_type<T>(), index));
			return storage_.get();
		}

		int match(lua_State* L, by_reference<T>, int index)
		{
			return converter_.match(L, decorated_type<T>(), index);
		}

		void converter_postcall(lua_State* L, by_reference<T>, int)
		{
			//specialized_converter_policy_n<2,Policies,T,cpp_to_lua> converter;
			converter_.to_lua(L, storage_.get());
			storage_.destroy();
		}

		T* to_cpp(lua_State* L, by_pointer<T>, int index)
		{
			storage_.construct(converter_.to_cpp(L, decorated_type<T>(), index));
			return &storage_.get();
		}

		int match(lua_State* L, by_pointer<T>, int index)
		{
			return converter_.match(L, decorated_type<T>(), index);
		}

		void converter_postcall(lua_State* L, by_pointer<T>, int)
		{
			//specialized_converter_policy_n<2, Policies, T, cpp_to_lua> converter;
			converter_.to_lua(L, storage_.get());
			storage_.destroy();
		}

	private:
		specialized_converter_policy_n<1, Policies, T, lua_to_cpp > converter_;
		out_value_detail::temporary_storage_type<T> storage_;
	};

	template<class Policies = no_policies>
	struct out_value_policy
	{
		struct only_accepts_nonconst_references_or_pointers {};
		struct can_only_convert_from_lua_to_cpp {};

		template<class T, class Direction>
		struct specialize
		{
			static_assert(std::is_same< Direction, lua_to_cpp >::value, "Out value policy can only convert from lua to cpp");
			static_assert(meta::or_< is_nonconst_reference<T>, is_nonconst_pointer<T> >::value, "Out value policy only accepts non const references or pointers");

			// Note to myself:
			// Using the size and template members instead of a policy templated for the type seems
			// to be done to tame template bloat. Need to check if this is worth is.
			using base_type = typename std::remove_pointer< typename std::remove_reference< T >::type >::type;
			typedef out_value_converter<base_type, Policies> type;
		};
	};

	template<int Size, class Policies = no_policies>
	struct pure_out_value_converter
	{
		enum { consumed_args = 0 };

        template<class T>
		T& to_cpp(lua_State*, by_reference<T>, int)
		{
			storage_.construct<T>();
			return storage_.get<T>();
		}

		template<class T>
		static int match(lua_State*, by_reference<T>, int)
		{
			return 0;
		}

		template<class T>
		void converter_postcall(lua_State* L, by_reference<T>, int)
		{
			specialized_converter_policy_n<1, Policies, T, cpp_to_lua> converter;
			converter.to_lua(L, storage_.get<T>());
			storage_.destroy<T>();
		}

		template<class T>
		T* to_cpp(lua_State*, by_pointer<T>, int)
		{
			storage_.construct<T>();
			return &storage_.get<T>();
		}

		template<class T>
		static int match(lua_State*, by_pointer<T>, int)
		{
			return 0;
		}

		template<class T>
		void converter_postcall(lua_State* L, by_pointer<T>, int)
		{
			specialized_converter_policy_n<1, Policies, T, cpp_to_lua> converter;
			converter.to_lua(L, storage_.get<T>());
			storage_.destroy<T>();
		}

	private:
		out_value_detail::temporary_storage_size<Size> storage_;
	};

	template<class Policies = no_policies>
	struct pure_out_value_policy
	{
		struct only_accepts_nonconst_references_or_pointers {};
		struct can_only_convert_from_lua_to_cpp {};

		template<class T, class Direction>
		struct specialize
		{
			static_assert(std::is_same< Direction, lua_to_cpp >::value, "Pure out value policy can only convert from lua to cpp");
			static_assert(meta::or_< is_nonconst_reference<T>, is_nonconst_pointer<T> >::value, "Pure out value policy only accepts non const references or pointers");

			typedef pure_out_value_converter<indirect_sizeof<T>::value, Policies> type;
		};
	};

}}

namespace luabind
{
	template<unsigned int N, class Policies = no_policies >
	using out_value = meta::type_list<converter_policy_injector<N,detail::out_value_policy<Policies>>>;

	template<unsigned int N, class Policies = no_policies >
	using pure_out_value = meta::type_list<converter_policy_injector<N,detail::pure_out_value_policy<Policies>>>;
}

#endif // LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED

<commit_msg>Added missing 'template' keyword<commit_after>// Copyright (c) 2003 Daniel Wallin and Arvid Norberg

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
// OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED
#define LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED

#include <luabind/config.hpp>
#include <luabind/detail/policy.hpp>    // for find_conversion_policy, etc
#include <luabind/detail/decorate_type.hpp>  // for decorated_type
#include <luabind/detail/primitives.hpp>  // for by_pointer, by_reference, etc
#include <luabind/detail/typetraits.hpp>  // for is_nonconst_pointer, is_nonconst_reference, etc
#include <new>                          // for operator new

namespace luabind { namespace detail
{
	template<int N>
	struct char_array
	{
		char storage[N];
	};

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_reference<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_const_reference<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_pointer<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_const_pointer<U>);

	template<class U>
	char_array<sizeof(typename identity<U>::type)> indirect_sizeof_test(by_value<U>);

	template<class T>
	struct indirect_sizeof
	{
		static const int value = sizeof(indirect_sizeof_test(decorated_type<T>()));
	};

	namespace out_value_detail {

		template< int Size >
		struct temporary_storage_size {

			template< typename T, typename... Args >
			void construct(Args&&... args)
			{
				new (&m_storage) T(std::forward<Args>(args)...);
			}

			template<typename T>
			T& get() {
				return *reinterpret_cast<T*>(&m_storage);
			}

			template<typename T>
			const T& get() const {
				return *reinterpret_cast<T*>(&m_storage);
			}

			template<typename T>
			void destroy()
			{
				get<T>().~T();
			}

			typename std::aligned_storage<Size>::type m_storage;

		};

		template< typename T >
		struct temporary_storage_type {

			template< typename... Args >
			void construct(Args&&... args)
			{
				new (&m_storage) T(std::forward<Args>(args)...);
			}

			T& get() {
				return *reinterpret_cast<T*>(&m_storage);
			}

			const T& get() const {
				return *reinterpret_cast<T*>(&m_storage);
			}

			void destroy()
			{
				get().~T();
			}

			typename std::aligned_storage<sizeof(T),alignof(T)>::type m_storage;

		};

	}

	// See note in out_value_policy about why we're not templating
	// for the parameter type.
	template<typename T, class Policies = no_policies>
	struct out_value_converter
	{
		enum { consumed_args = 1 };

		T& to_cpp(lua_State* L, by_reference<T>, int index)
		{
			//specialized_converter_policy_n<1, Policies, T, lua_to_cpp> converter;
			storage_.construct(converter_.to_cpp(L, decorated_type<T>(), index));
			return storage_.get();
		}

		int match(lua_State* L, by_reference<T>, int index)
		{
			return converter_.match(L, decorated_type<T>(), index);
		}

		void converter_postcall(lua_State* L, by_reference<T>, int)
		{
			//specialized_converter_policy_n<2,Policies,T,cpp_to_lua> converter;
			converter_.to_lua(L, storage_.get());
			storage_.destroy();
		}

		T* to_cpp(lua_State* L, by_pointer<T>, int index)
		{
			storage_.construct(converter_.to_cpp(L, decorated_type<T>(), index));
			return &storage_.get();
		}

		int match(lua_State* L, by_pointer<T>, int index)
		{
			return converter_.match(L, decorated_type<T>(), index);
		}

		void converter_postcall(lua_State* L, by_pointer<T>, int)
		{
			//specialized_converter_policy_n<2, Policies, T, cpp_to_lua> converter;
			converter_.to_lua(L, storage_.get());
			storage_.destroy();
		}

	private:
		specialized_converter_policy_n<1, Policies, T, lua_to_cpp > converter_;
		out_value_detail::temporary_storage_type<T> storage_;
	};

	template<class Policies = no_policies>
	struct out_value_policy
	{
		struct only_accepts_nonconst_references_or_pointers {};
		struct can_only_convert_from_lua_to_cpp {};

		template<class T, class Direction>
		struct specialize
		{
			static_assert(std::is_same< Direction, lua_to_cpp >::value, "Out value policy can only convert from lua to cpp");
			static_assert(meta::or_< is_nonconst_reference<T>, is_nonconst_pointer<T> >::value, "Out value policy only accepts non const references or pointers");

			// Note to myself:
			// Using the size and template members instead of a policy templated for the type seems
			// to be done to tame template bloat. Need to check if this is worth is.
			using base_type = typename std::remove_pointer< typename std::remove_reference< T >::type >::type;
			typedef out_value_converter<base_type, Policies> type;
		};
	};

	template<int Size, class Policies = no_policies>
	struct pure_out_value_converter
	{
		enum { consumed_args = 0 };

        template<class T>
		T& to_cpp(lua_State*, by_reference<T>, int)
		{
           storage_.template construct<T>();
           return storage_.template get<T>();
		}

		template<class T>
		static int match(lua_State*, by_reference<T>, int)
		{
			return 0;
		}

		template<class T>
		void converter_postcall(lua_State* L, by_reference<T>, int)
		{
			specialized_converter_policy_n<1, Policies, T, cpp_to_lua> converter;
           converter.to_lua(L, storage_.template get<T>());
           storage_.template destroy<T>();
		}

		template<class T>
		T* to_cpp(lua_State*, by_pointer<T>, int)
		{
           storage_.template construct<T>();
           return &storage_.template get<T>();
		}

		template<class T>
		static int match(lua_State*, by_pointer<T>, int)
		{
			return 0;
		}

		template<class T>
		void converter_postcall(lua_State* L, by_pointer<T>, int)
		{
			specialized_converter_policy_n<1, Policies, T, cpp_to_lua> converter;
           converter.to_lua(L, storage_.template get<T>());
           storage_.template destroy<T>();
		}

	private:
		out_value_detail::temporary_storage_size<Size> storage_;
	};

	template<class Policies = no_policies>
	struct pure_out_value_policy
	{
		struct only_accepts_nonconst_references_or_pointers {};
		struct can_only_convert_from_lua_to_cpp {};

		template<class T, class Direction>
		struct specialize
		{
			static_assert(std::is_same< Direction, lua_to_cpp >::value, "Pure out value policy can only convert from lua to cpp");
			static_assert(meta::or_< is_nonconst_reference<T>, is_nonconst_pointer<T> >::value, "Pure out value policy only accepts non const references or pointers");

			typedef pure_out_value_converter<indirect_sizeof<T>::value, Policies> type;
		};
	};

}}

namespace luabind
{
	template<unsigned int N, class Policies = no_policies >
	using out_value = meta::type_list<converter_policy_injector<N,detail::out_value_policy<Policies>>>;

	template<unsigned int N, class Policies = no_policies >
	using pure_out_value = meta::type_list<converter_policy_injector<N,detail::pure_out_value_policy<Policies>>>;
}

#endif // LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */
#include "sgsql.h"

using namespace std;
using namespace hal;

SGSQL::SGSQL() : _sgBuilder(0), _sg(0)
{
}

SGSQL::~SGSQL()
{
}

void SGSQL::writeDb(const SGBuilder* sgBuilder, const string& sqlInsertPath,
                    const string& fastaPath)
{
  _sgBuilder = sgBuilder;
  _sg = _sgBuilder->getSideGraph();
  assert(_sg != NULL);
  _outPath = sqlInsertPath;
  _outStream.open(_outPath.c_str());
  assert(_outStream);
  _faPath = fastaPath;
  _faStream.open(_faPath.c_str());
  assert(_faStream);
  _checksumMap.clear();

  writeFasta();
  writeFastaInsert();
  writeSequenceInserts();
  writeReferenceInserts();
  writeJoinInserts();
  writePathInserts();

  _outStream.close();
  _faStream.close();
}

void SGSQL::writeFasta()
{
  string dnaBuffer;
  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    _sgBuilder->getSequenceString(seq, dnaBuffer);
    assert((sg_int_t)dnaBuffer.length() == seq->getLength());
    _faStream << ">"  << seq->getName() << "\n";
    size_t len;
    for (size_t pos = 0; pos < dnaBuffer.length(); pos += len)
    {
      len = min((size_t)80, dnaBuffer.length() - pos);
      _faStream << dnaBuffer.substr(pos, len) << "\n";
    }
    string checksum;
    getChecksum(dnaBuffer, checksum);
    _checksumMap.insert(pair<sg_seqid_t, string>(seq->getID(), checksum));
  }
}

/*
  CREATE TABLE FASTA (ID INTEGER PRIMARY KEY,
  fastaURI TEXT NOT NULL);
*/
void SGSQL::writeFastaInsert()
{
  _outStream << "INSERT INTO FASTA VALUES ("
             << 0 << ", "
             << "file://" << _faPath << ")\n";
  _outStream << endl;
}

/*
  CREATE TABLE Sequence (ID INTEGER PRIMARY KEY,
  -- FASTA file URI and record name within it containing sequence
  fastaID INTEGER, -- If null, query enclosing ReferenceSet's fastaID
  sequenceRecordName TEXT NOT NULL,
  md5checksum TEXT NOT NULL,
  length INTEGER NOT NULL,
  FOREIGN KEY(fastaID) REFERENCES FASTA(ID));
*/
void SGSQL::writeSequenceInserts()
{
  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    map<sg_seqid_t, string>::const_iterator j = _checksumMap.find(seq->getID());
    assert(j != _checksumMap.end());
    _outStream << "INSERT INTO Sequence VALUES ("
               << seq->getID() << ", "
               << 0 << ", "
               << "\'"<< seq->getName() << "\', "
               << "\'" << j->second  << "\', "
               << seq->getLength() << ");\n";
  }
  _outStream << endl;
}

/*
-- References
CREATE TABLE Reference (ID INTEGER PRIMARY KEY,
	name TEXT NOT NULL,
	updateTime DATE NOT NULL,
	sequenceID INTEGER NOT NULL,
	start INTEGER NOT NULL, -- default 0.
	length INTEGER, -- if null, assume sequence.lenght - start
	md5checksum TEXT, -- if null, assume sequence.md5checksum
	isDerived BOOLEAN NOT NULL,
	sourceDivergence REAL, -- may be null if isDerived is FALSE (not sure if it needs to be stored)?
	ncbiTaxonID INTEGER, -- ID from http://www.ncbi.nlm.nih.gov/taxonomy, may be null
	isPrimary BOOLEAN NOT NULL,
	FOREIGN KEY(sequenceID) REFERENCES Sequence(ID));
CREATE TABLE ReferenceAccession (ID INTEGER PRIMARY KEY,
	referenceID INTEGER NOT NULL,
	accessionID TEXT NOT NULL,
	FOREIGN KEY(referenceID) REFERENCES Reference(ID));

-- Reference sets
CREATE TABLE ReferenceSet (ID INTEGER PRIMARY KEY,
	ncbiTaxonID INT, -- may be null, may differ from ncbiTaxonID of contained Reference record
	description TEXT, -- may be null, but shouldn't be?
	fastaID INTEGER, -- may be null. TODO: What if both this and a member Reference's Sequence fastaID are null?
	assemblyID TEXT, -- may be null, but REALLY shouldn't be?
	isDerived BOOLEAN NOT NULL,
	FOREIGN KEY(fastaID) REFERENCES FASTA(ID));
CREATE TABLE ReferenceSetAccession (ID INTEGER PRIMARY KEY,
	referenceSetID INTEGER NOT NULL,
	accessionID TEXT NOT NULL,
	FOREIGN KEY(referenceSetID) REFERENCES ReferenceSet(ID));

CREATE TABLE Reference_ReferenceSet_Join (referenceID INTEGER NOT NULL,
	referenceSetID INTEGER NOT NULL,
	PRIMARY KEY(referenceID, referenceSetID),
	FOREIGN KEY(referenceID) REFERENCES Reference(ID),
	FOREIGN KEY(referenceSetID) REFERENCES ReferenceSet(ID));
*/
void SGSQL::writeReferenceInserts()
{
  // make a reference set for each input genome from the HAL
  map<string, size_t> refMap;
  refMap.insert(pair<string, size_t>(_sgBuilder->getPrimaryGenomeName(), 0));
  _outStream << "INSERT INTO ReferenceSet VALUES "
             << "(0, NULL, NULL, 0, NULL, \'FALSE\')\n";
  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    string halGenomeName = _sgBuilder->getHalGenomeName(seq);
    if (refMap.find(halGenomeName) == refMap.end())
    {
      sg_int_t id = refMap.size();
      refMap.insert(pair<string, size_t>(halGenomeName, id));
      // single reference set
      _outStream << "INSERT INTO ReferenceSet VALUES "
                 << "(" << id
                 << ", NULL, "
                 << "\'HAL Genome " + halGenomeName << "\'"
                 << ", 0, NULL, \'FALSE\')\n";
    }
  }

  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    string halGenomeName = _sgBuilder->getHalGenomeName(seq);
    bool primary = halGenomeName == _sgBuilder->getPrimaryGenomeName();
    _outStream << "INSERT INTO Reference VALUES ("
               << seq->getID() << ", "
               << "\'"<< seq->getName() << "\', "
               << "date(\'now\')" << ", "
               << seq->getID() << ", "
               << refMap.find(halGenomeName)->second << ", "
               << "NULL " << ", "
               << "NULL " << ", "
               << "\'FALSE\'" << ", "
               << "NULL " << ", "
               << "NULL " << ", "
               << (primary ? "\'TRUE\'" : "\'FALSE\'")
               << ");\n";
  }

  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    _outStream << "INSERT INTO Reference_ReferenceSet_Join VALUES ("
               << seq->getID() << ", 0);\n";
  }

  _outStream << endl;

}

/*
  CREATE TABLE GraphJoin (ID INTEGER PRIMARY KEY,
  -- startJoin defines parent sequence & position that 5' end attaches to.
  side1SequenceID INTEGER NOT NULL,
  side1Position INTEGER NOT NULL,
  side1StrandIsForward BOOLEAN NOT NULL,
  -- endJoin defines parent sequence & position that 3' end attaches to.
  side2SequenceID INTEGER NOT NULL,
  side2Position INTEGER NOT NULL,
  side2StrandIsForward BOOLEAN NOT NULL,
  FOREIGN KEY(side1SequenceID) REFERENCES Sequence(ID),
  FOREIGN KEY(side2SequenceID) REFERENCES Sequence(ID));
*/
void SGSQL::writeJoinInserts()
{
  const SideGraph::JoinSet* joinSet = _sg->getJoinSet();
  SideGraph::JoinSet::const_iterator i;
  size_t count = 0;
  for (i = joinSet->begin(); i != joinSet->end(); ++i)
  {
    const SGJoin* join = *i;
    const SGSide& side1 = join->getSide1();
    const SGSide& side2 = join->getSide2();
    _outStream << "INSERT INTO GraphJoin VALUES ("
               << count++ << ", "
               << side1.getBase().getSeqID() << ", "
               << side1.getBase().getPos() << ", "
               << (side1.getForward() ? "TRUE" : "FALSE") << ", "
               << side2.getBase().getSeqID() << ", "
               << side2.getBase().getPos() << ", "
               << (side2.getForward() ? "TRUE" : "FALSE") << ")\n";
  }
  _outStream << endl;
}

void SGSQL::writePathInserts()
{
  const vector<const Sequence*>& halSequences = _sgBuilder->getHalSequences();

  _outStream << "# Preliminary path data for each INPUT sequence (from "
             << "HAL file). \n#Still need to write in whatever official"
             << " path format is.  Tuples below are:\n"
             << "# (INPUT-SEQUENCE-NAME, PATH-STEP-#, SEGMENT) "
             << "where SEGMENT = (SEQUENCE-ID, POSITION, LENGTH, FORWARD)\n";

  for (size_t i = 0; i < halSequences.size(); ++i)
  {
    vector<SGSegment> path;
    _sgBuilder->getHalSequencePath(halSequences[i], path);
    for (size_t j = 0; j < path.size(); ++j)
    {
      _outStream << "INSERT INTO Path VALUES ("
                 << halSequences[i]->getFullName() << ", "
                 << j << ", "
                 << path[j].getSide().getBase().getSeqID() << ", "
                 << path[j].getSide().getBase().getPos() << ", "
                 << path[j].getLength() << ", "
                 << (path[j].getSide().getForward() ? "\'TRUE\'" : "\'FALSE\'")
                 << ")\n";

    }
  }
  _outStream <<endl;
}

void SGSQL::getChecksum(const string& inputString, string& outputString)
{
  outputString = "md5";
}
<commit_msg>clean path comment a bit<commit_after>/*
 * Copyright (C) 2015 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */
#include "sgsql.h"

using namespace std;
using namespace hal;

SGSQL::SGSQL() : _sgBuilder(0), _sg(0)
{
}

SGSQL::~SGSQL()
{
}

void SGSQL::writeDb(const SGBuilder* sgBuilder, const string& sqlInsertPath,
                    const string& fastaPath)
{
  _sgBuilder = sgBuilder;
  _sg = _sgBuilder->getSideGraph();
  assert(_sg != NULL);
  _outPath = sqlInsertPath;
  _outStream.open(_outPath.c_str());
  assert(_outStream);
  _faPath = fastaPath;
  _faStream.open(_faPath.c_str());
  assert(_faStream);
  _checksumMap.clear();

  writeFasta();
  writeFastaInsert();
  writeSequenceInserts();
  writeReferenceInserts();
  writeJoinInserts();
  writePathInserts();

  _outStream.close();
  _faStream.close();
}

void SGSQL::writeFasta()
{
  string dnaBuffer;
  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    _sgBuilder->getSequenceString(seq, dnaBuffer);
    assert((sg_int_t)dnaBuffer.length() == seq->getLength());
    _faStream << ">"  << seq->getName() << "\n";
    size_t len;
    for (size_t pos = 0; pos < dnaBuffer.length(); pos += len)
    {
      len = min((size_t)80, dnaBuffer.length() - pos);
      _faStream << dnaBuffer.substr(pos, len) << "\n";
    }
    string checksum;
    getChecksum(dnaBuffer, checksum);
    _checksumMap.insert(pair<sg_seqid_t, string>(seq->getID(), checksum));
  }
}

/*
  CREATE TABLE FASTA (ID INTEGER PRIMARY KEY,
  fastaURI TEXT NOT NULL);
*/
void SGSQL::writeFastaInsert()
{
  _outStream << "INSERT INTO FASTA VALUES ("
             << 0 << ", "
             << "file://" << _faPath << ")\n";
  _outStream << endl;
}

/*
  CREATE TABLE Sequence (ID INTEGER PRIMARY KEY,
  -- FASTA file URI and record name within it containing sequence
  fastaID INTEGER, -- If null, query enclosing ReferenceSet's fastaID
  sequenceRecordName TEXT NOT NULL,
  md5checksum TEXT NOT NULL,
  length INTEGER NOT NULL,
  FOREIGN KEY(fastaID) REFERENCES FASTA(ID));
*/
void SGSQL::writeSequenceInserts()
{
  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    map<sg_seqid_t, string>::const_iterator j = _checksumMap.find(seq->getID());
    assert(j != _checksumMap.end());
    _outStream << "INSERT INTO Sequence VALUES ("
               << seq->getID() << ", "
               << 0 << ", "
               << "\'"<< seq->getName() << "\', "
               << "\'" << j->second  << "\', "
               << seq->getLength() << ");\n";
  }
  _outStream << endl;
}

/*
-- References
CREATE TABLE Reference (ID INTEGER PRIMARY KEY,
	name TEXT NOT NULL,
	updateTime DATE NOT NULL,
	sequenceID INTEGER NOT NULL,
	start INTEGER NOT NULL, -- default 0.
	length INTEGER, -- if null, assume sequence.lenght - start
	md5checksum TEXT, -- if null, assume sequence.md5checksum
	isDerived BOOLEAN NOT NULL,
	sourceDivergence REAL, -- may be null if isDerived is FALSE (not sure if it needs to be stored)?
	ncbiTaxonID INTEGER, -- ID from http://www.ncbi.nlm.nih.gov/taxonomy, may be null
	isPrimary BOOLEAN NOT NULL,
	FOREIGN KEY(sequenceID) REFERENCES Sequence(ID));
CREATE TABLE ReferenceAccession (ID INTEGER PRIMARY KEY,
	referenceID INTEGER NOT NULL,
	accessionID TEXT NOT NULL,
	FOREIGN KEY(referenceID) REFERENCES Reference(ID));

-- Reference sets
CREATE TABLE ReferenceSet (ID INTEGER PRIMARY KEY,
	ncbiTaxonID INT, -- may be null, may differ from ncbiTaxonID of contained Reference record
	description TEXT, -- may be null, but shouldn't be?
	fastaID INTEGER, -- may be null. TODO: What if both this and a member Reference's Sequence fastaID are null?
	assemblyID TEXT, -- may be null, but REALLY shouldn't be?
	isDerived BOOLEAN NOT NULL,
	FOREIGN KEY(fastaID) REFERENCES FASTA(ID));
CREATE TABLE ReferenceSetAccession (ID INTEGER PRIMARY KEY,
	referenceSetID INTEGER NOT NULL,
	accessionID TEXT NOT NULL,
	FOREIGN KEY(referenceSetID) REFERENCES ReferenceSet(ID));

CREATE TABLE Reference_ReferenceSet_Join (referenceID INTEGER NOT NULL,
	referenceSetID INTEGER NOT NULL,
	PRIMARY KEY(referenceID, referenceSetID),
	FOREIGN KEY(referenceID) REFERENCES Reference(ID),
	FOREIGN KEY(referenceSetID) REFERENCES ReferenceSet(ID));
*/
void SGSQL::writeReferenceInserts()
{
  // make a reference set for each input genome from the HAL
  map<string, size_t> refMap;
  refMap.insert(pair<string, size_t>(_sgBuilder->getPrimaryGenomeName(), 0));
  _outStream << "INSERT INTO ReferenceSet VALUES "
             << "(0, NULL, NULL, 0, NULL, \'FALSE\')\n";
  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    string halGenomeName = _sgBuilder->getHalGenomeName(seq);
    if (refMap.find(halGenomeName) == refMap.end())
    {
      sg_int_t id = refMap.size();
      refMap.insert(pair<string, size_t>(halGenomeName, id));
      // single reference set
      _outStream << "INSERT INTO ReferenceSet VALUES "
                 << "(" << id
                 << ", NULL, "
                 << "\'HAL Genome " + halGenomeName << "\'"
                 << ", 0, NULL, \'FALSE\')\n";
    }
  }

  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    string halGenomeName = _sgBuilder->getHalGenomeName(seq);
    bool primary = halGenomeName == _sgBuilder->getPrimaryGenomeName();
    _outStream << "INSERT INTO Reference VALUES ("
               << seq->getID() << ", "
               << "\'"<< seq->getName() << "\', "
               << "date(\'now\')" << ", "
               << seq->getID() << ", "
               << refMap.find(halGenomeName)->second << ", "
               << "NULL " << ", "
               << "NULL " << ", "
               << "\'FALSE\'" << ", "
               << "NULL " << ", "
               << "NULL " << ", "
               << (primary ? "\'TRUE\'" : "\'FALSE\'")
               << ");\n";
  }

  for (sg_int_t i = 0; i < _sg->getNumSequences(); ++i)
  {
    const SGSequence* seq = _sg->getSequence(i);
    _outStream << "INSERT INTO Reference_ReferenceSet_Join VALUES ("
               << seq->getID() << ", 0);\n";
  }

  _outStream << endl;

}

/*
  CREATE TABLE GraphJoin (ID INTEGER PRIMARY KEY,
  -- startJoin defines parent sequence & position that 5' end attaches to.
  side1SequenceID INTEGER NOT NULL,
  side1Position INTEGER NOT NULL,
  side1StrandIsForward BOOLEAN NOT NULL,
  -- endJoin defines parent sequence & position that 3' end attaches to.
  side2SequenceID INTEGER NOT NULL,
  side2Position INTEGER NOT NULL,
  side2StrandIsForward BOOLEAN NOT NULL,
  FOREIGN KEY(side1SequenceID) REFERENCES Sequence(ID),
  FOREIGN KEY(side2SequenceID) REFERENCES Sequence(ID));
*/
void SGSQL::writeJoinInserts()
{
  const SideGraph::JoinSet* joinSet = _sg->getJoinSet();
  SideGraph::JoinSet::const_iterator i;
  size_t count = 0;
  for (i = joinSet->begin(); i != joinSet->end(); ++i)
  {
    const SGJoin* join = *i;
    const SGSide& side1 = join->getSide1();
    const SGSide& side2 = join->getSide2();
    _outStream << "INSERT INTO GraphJoin VALUES ("
               << count++ << ", "
               << side1.getBase().getSeqID() << ", "
               << side1.getBase().getPos() << ", "
               << (side1.getForward() ? "TRUE" : "FALSE") << ", "
               << side2.getBase().getSeqID() << ", "
               << side2.getBase().getPos() << ", "
               << (side2.getForward() ? "TRUE" : "FALSE") << ")\n";
  }
  _outStream << endl;
}

void SGSQL::writePathInserts()
{
  const vector<const Sequence*>& halSequences = _sgBuilder->getHalSequences();

  _outStream << "-- Preliminary path data for each INPUT sequence (from "
             << "HAL file). \n-- Still need to write in whatever official"
             << " path format is.  Tuples below are:\n"
             << "-- (INPUT-SEQUENCE-NAME, PATH-STEP-#, SEGMENT) "
             << "where SEGMENT = (SEQUENCE-ID, POSITION, LENGTH, FORWARD)\n";

  for (size_t i = 0; i < halSequences.size(); ++i)
  {
    vector<SGSegment> path;
    _sgBuilder->getHalSequencePath(halSequences[i], path);
    for (size_t j = 0; j < path.size(); ++j)
    {
      _outStream << "INSERT INTO Path VALUES ("
                 << halSequences[i]->getFullName() << ", "
                 << j << ", "
                 << path[j].getSide().getBase().getSeqID() << ", "
                 << path[j].getSide().getBase().getPos() << ", "
                 << path[j].getLength() << ", "
                 << (path[j].getSide().getForward() ? "\'TRUE\'" : "\'FALSE\'")
                 << ")\n";

    }
  }
  _outStream <<endl;
}

void SGSQL::getChecksum(const string& inputString, string& outputString)
{
  outputString = "md5";
}
<|endoftext|>


<commit_before>#ifndef MIDDLEWARE_PARSLEY_HPP
#define MIDDLEWARE_PARSLEY_HPP

#include "json.hpp"
#include "middleware.hpp"

/**
 * @brief A vegan way to parse JSON Content in a response
 * @details TBC..
 *
 */
class Parsley : public server::Middleware {

public:

  virtual void process(
    server::Request_ptr req,
    server::Response_ptr,
    server::Next next
    ) override
  {
    using namespace json;

    if(!has_json(req)) {
      printf("<Parsley> No JSON in header field.\n");
      (*next)();
      return;
    }
    printf("<Parsley> Found json header\n");

    // Request doesn't have JSON attribute
    if(!req->has_attribute<JsonDoc>()) {
      // create attribute
      auto json = std::make_shared<JsonDoc>();
      // access the document and parse the body
      json->doc().Parse(req->get_body().c_str());
      printf("<Parsley> Parsed JSON data.\n");
      // add the json to the request
      req->set_attribute(json);
    }

    (*next)();
  }

private:
  bool has_json(server::Request_ptr req) const {
    auto c_type = http::header_fields::Entity::Content_Type;
    if(!req->has_header(c_type))
      return false;
    return (req->header_value(c_type).find("application/json") != std::string::npos);
  }

};

#endif
<commit_msg>Middleware: Silenced some debug output<commit_after>#ifndef MIDDLEWARE_PARSLEY_HPP
#define MIDDLEWARE_PARSLEY_HPP

#include "json.hpp"
#include "middleware.hpp"

/**
 * @brief A vegan way to parse JSON Content in a response
 * @details TBC..
 *
 */
class Parsley : public server::Middleware {

public:

  virtual void process(
    server::Request_ptr req,
    server::Response_ptr,
    server::Next next
    ) override
  {
    using namespace json;

    if(!has_json(req)) {
      //printf("<Parsley> No JSON in header field.\n");
      (*next)();
      return;
    }
    //printf("<Parsley> Found json header\n");

    // Request doesn't have JSON attribute
    if(!req->has_attribute<JsonDoc>()) {
      // create attribute
      auto json = std::make_shared<JsonDoc>();
      // access the document and parse the body
      json->doc().Parse(req->get_body().c_str());
      printf("<Parsley> Parsed JSON data.\n");
      // add the json to the request
      req->set_attribute(json);
    }

    (*next)();
  }

private:
  bool has_json(server::Request_ptr req) const {
    auto c_type = http::header_fields::Entity::Content_Type;
    if(!req->has_header(c_type))
      return false;
    return (req->header_value(c_type).find("application/json") != std::string::npos);
  }

};

#endif
<|endoftext|>