<commit_before>/********** tell emacs we use -*- c++ -*- style comments *******************
 $Revision: 1.10 $  $Author: trey $  $Date: 2006-07-12 19:42:00 $

 @file    ConvexBounds.cc
 @brief   No brief

 Copyright (c) 2006, Trey Smith. All rights reserved.

 Licensed under the Apache License, Version 2.0 (the "License"); you may
 not use this file except in compliance with the License.  You may
 obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 implied.  See the License for the specific language governing
 permissions and limitations under the License.

 ***************************************************************************/

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

#include <iostream>
#include <fstream>
#include <queue>

#include "zmdpCommonDefs.h"
#include "zmdpCommonTime.h"
#include "MatrixUtils.h"
#include "Pomdp.h"
#include "AbstractBound.h"
#include "ConvexBounds.h"

using namespace std;
using namespace sla;
using namespace MatrixUtils;

#define CB_QVAL_UNDEFINED (-99e+20)
#define CB_INITIALIZATION_PRECISION_FACTOR (1e-2)

namespace zmdp {

ConvexBounds::ConvexBounds(bool _keepLowerBound,
			   bool _forceUpperBoundActionSelection) :
  lowerBound(NULL),
  upperBound(NULL),
  keepLowerBound(_keepLowerBound),
  forceUpperBoundActionSelection(_forceUpperBoundActionSelection)
{}

// lower bound on long-term reward for taking action a (alpha vector)
void ConvexBounds::getNewLBPlaneQ(LBPlane& result, const MDPNode& cn, int a)
{
  alpha_vector betaA(pomdp->getBeliefSize()), betaAO(pomdp->getBeliefSize());
  alpha_vector tmp, tmp2;
#if USE_MASKED_ALPHA
  alpha_vector tmp3;
#endif

  set_to_zero(betaA);

  bool defaultIsSet = false;
  alpha_vector defaultBetaAO;
  const MDPQEntry& Qa = cn.Q[a];
  FOR (o, Qa.getNumOutcomes()) {
    MDPEdge* e = Qa.outcomes[o];
    if (NULL != e) {
      betaAO = lowerBound->getBestLBPlane(e->nextState->s).alpha;
    } else {
      // impossible to see this observation, so it doesn't make sense to
      // pick the alpha that optimizes for the next belief.  plug in a
      // default alpha (arbitrarily chosen to optimize for cn.b).
      if (!defaultIsSet) {
	defaultBetaAO = lowerBound->getBestLBPlane(cn.s).alpha;
	defaultIsSet = true;
      }
      betaAO = defaultBetaAO;
    }

    emult_column( tmp, pomdp->O[a], o, betaAO );
#if USE_MASKED_ALPHA
    mult( tmp3, pomdp->T[a], tmp );
    mask_copy( tmp2, tmp3, cn.s );
#else
    mult( tmp2, tmp, pomdp->Ttr[a] );
#endif
    betaA += tmp2;
  }

  alpha_vector Rxa;
#if USE_MASKED_ALPHA
  copy_from_column( tmp, pomdp->R, a );
  mask_copy( Rxa, tmp, cn.s );
#else
  copy_from_column( Rxa, pomdp->R, a );
#endif
  betaA *= pomdp->getDiscount();
  betaA += Rxa;

  result.alpha = betaA;
  result.action = a;
#if USE_MASKED_ALPHA
  result.mask = cn.s;
#endif
}

void ConvexBounds::getNewLBPlane(LBPlane& result, MDPNode& cn)
{
#if USE_DEBUG_PRINT
  timeval startTime = getTime();
#endif

  double val, maxVal = -99e+20;
  LBPlane betaA;

  FOR (a, cn.getNumActions()) {
    getNewLBPlaneQ(betaA, cn, a);
    val = inner_prod(betaA.alpha, cn.s);
    cn.Q[a].lbVal = val;
    if (val > maxVal) {
      maxVal = val;
      result = betaA;
    }
  }
#if USE_DEBUG_PRINT
  cout << "** newLowerBound: elapsed time = "
       << timevalToSeconds(getTime() - startTime)
       << endl;
#endif
}

void ConvexBounds::updateLowerBound(MDPNode& cn)
{
  LBPlane newPlane;
  getNewLBPlane(newPlane, cn);
  lowerBound->addLBPlane(cn.s, newPlane);
  lowerBound->maybePrune();
  cn.lbVal = inner_prod(cn.s, newPlane.alpha);
}

// upper bound on long-term reward for taking action a
double ConvexBounds::getNewUBValueQ(MDPNode& cn, int a)
{
  double val = 0;

  MDPQEntry& Qa = cn.Q[a];
  FOR (o, Qa.getNumOutcomes()) {
    MDPEdge* e = Qa.outcomes[o];
    if (NULL != e) {
      val += e->obsProb * upperBound->getValue(e->nextState->s);
    }
  }
  val = Qa.immediateReward + pomdp->getDiscount() * val;
  Qa.ubVal = val;

  return val;
}

double ConvexBounds::getNewUBValueSimple(MDPNode& cn, int* maxUBActionP)
{
#if USE_DEBUG_PRINT
  timeval startTime = getTime();
#endif

  double val, maxVal = -99e+20;
  int maxUBAction = -1;
  FOR (a, pomdp->getNumActions()) {
    val = getNewUBValueQ(cn,a);
    if (val > maxVal) {
      maxVal = val;
      maxUBAction = a;
    }
  }

  if (NULL != maxUBActionP) *maxUBActionP = maxUBAction;

#if USE_DEBUG_PRINT
  cout << "** newUpperBound: elapsed time = "
       << timevalToSeconds(getTime() - startTime)
       << endl;
#endif

  return maxVal;
}

double ConvexBounds::getNewUBValueUseCache(MDPNode& cn, int* maxUBActionP)
{
#if USE_DEBUG_PRINT
  timeval startTime = getTime();
#endif

  // cache upper bound for each action
  dvector cachedUpperBound(pomdp->getNumActions());
  FOR (a, pomdp->numActions) {
    cachedUpperBound(a) = cn.Q[a].ubVal;
  }

  // remember which Q functions we have updated on this call
  std::vector<bool> updatedAction(pomdp->getNumActions());
  FOR (a, pomdp->getNumActions()) {
    updatedAction[a] = false;
  }

  double val;
  int maxUBAction = argmax_elt(cachedUpperBound);
  while (1) {
    // do the backup for the best Q
    val = getNewUBValueQ(cn,maxUBAction);
    cachedUpperBound(maxUBAction) = val;
    updatedAction[maxUBAction] = true;

    // the best action may have changed after updating Q
    maxUBAction = argmax_elt(cachedUpperBound);

    // if the best action after the update is one that we have already
    //    updated, we're done
    if (updatedAction[maxUBAction]) break;
  }

  double maxVal = cachedUpperBound(maxUBAction);

  if (NULL != maxUBActionP) *maxUBActionP = maxUBAction;

#if USE_DEBUG_PRINT
  cout << "** newUpperBound: elapsed time = "
       << timevalToSeconds(getTime() - startTime)
       << endl;
#endif

  return maxVal;
}

double ConvexBounds::getNewUBValue(MDPNode& cn, int* maxUBActionP)
{
  if (CB_QVAL_UNDEFINED == cn.Q[0].ubVal) {
    return getNewUBValueSimple(cn, maxUBActionP);
  } else {
    return getNewUBValueUseCache(cn, maxUBActionP);
  }
}

void ConvexBounds::updateUpperBound(MDPNode& cn, int* maxUBActionP)
{
  double newUBVal = getNewUBValue(cn, maxUBActionP);
  upperBound->addPoint(cn.s, newUBVal);
  upperBound->maybePrune();
  cn.ubVal = newUBVal;
}

void ConvexBounds::initialize(const MDP* _pomdp,
			      double _targetPrecision)
{
  pomdp = (const Pomdp*) _pomdp;
  targetPrecision = CB_INITIALIZATION_PRECISION_FACTOR * _targetPrecision;

  if (keepLowerBound) {
    lowerBound = new MaxPlanesLowerBound(pomdp);
    lowerBound->initialize(targetPrecision);
  }

  upperBound = new SawtoothUpperBound(pomdp);
  upperBound->initialize(targetPrecision);

  lookup = new MDPHash();
  root = NULL;

  numStatesTouched = 0;
  numStatesExpanded = 0;
  numBackups = 0;

  getNodeHandler = NULL;
  handlerData = NULL;
}

MDPNode* ConvexBounds::getRootNode(void)
{
  if (NULL == root) {
    root = getNode(pomdp->getInitialState());
  }
  return root;
}

MDPNode* ConvexBounds::getNode(const state_vector& s)
{
  string hs = hashable(s);
  MDPHash::iterator pr = lookup->find(hs);
  if (lookup->end() == pr) {
    // create a new fringe node
    MDPNode& cn = *(new MDPNode);
    cn.s = s;
    cn.isTerminal = pomdp->getIsTerminalState(s);
    if (cn.isTerminal) {
      cn.ubVal = 0;
    } else {
      cn.ubVal = upperBound->getValue(s);
    }
    if (keepLowerBound) {
      if (cn.isTerminal) {
	cn.lbVal = 0;
      } else {
	cn.lbVal = lowerBound->getValue(s);
      }
    } else {
      cn.lbVal = -1; // n/a
    }
    cn.searchData = NULL;
    cn.boundsData = NULL;
    (*lookup)[hs] = &cn;

    if (NULL != getNodeHandler) {
      (*getNodeHandler)(cn, handlerData);
    }

    numStatesTouched++;
    return &cn;
  } else {
    // return existing node
    return pr->second;
  }
}

void ConvexBounds::expand(MDPNode& cn)
{
  // set up successors for this fringe node (possibly creating new fringe nodes)
  outcome_prob_vector opv;
  state_vector sp;
  cn.Q.resize(pomdp->getNumActions());
  FOR (a, pomdp->getNumActions()) {
    MDPQEntry& Qa = cn.Q[a];
    Qa.immediateReward = pomdp->getReward(cn.s, a);
    pomdp->getOutcomeProbVector(opv, cn.s, a);
    Qa.outcomes.resize(opv.size());
    FOR (o, opv.size()) {
      double oprob = opv(o);
      if (oprob > OBS_IS_ZERO_EPS) {
	MDPEdge* e = new MDPEdge();
        Qa.outcomes[o] = e;
        e->obsProb = oprob;
        e->nextState = getNode(pomdp->getNextState(sp, cn.s, a, o));
      } else {
        Qa.outcomes[o] = NULL;
      }
    }
    Qa.ubVal = CB_QVAL_UNDEFINED;
  }
  numStatesExpanded++;
}

void ConvexBounds::update(MDPNode& cn, int* maxUBActionP)
{
  if (cn.isFringe()) {
    expand(cn);
  }
  if (keepLowerBound) {
    updateLowerBound(cn);
  }
  updateUpperBound(cn, maxUBActionP);

  numBackups++;
}

// this implementation is not very efficient, but it is guaranteed not
// to modify the algorithm state, so it can safely be used for
// simulation testing in the middle of a run.
int ConvexBounds::chooseAction(const state_vector& s) const
{
  if (!forceUpperBoundActionSelection && keepLowerBound) {
    // 'direct' policy as opposed to 'lookahead' policy
    return lowerBound->getBestLBPlane(s).action;
  }

  // if not maintaining LB, fall back to UB
  outcome_prob_vector opv;
  state_vector sp;
  int bestAction = -1;

  double ubVal, ubValO;
  double maxVal = -99e+20;
  FOR (a, pomdp->getNumActions()) {
    pomdp->getOutcomeProbVector(opv, s, a);
    ubVal = 0;
    FOR (o, opv.size()) {
      if (opv(o) > OBS_IS_ZERO_EPS) {
	ubValO = upperBound->getValue(pomdp->getNextState(sp, s, a, o));
	ubVal += opv(o) * ubValO;
      }
    }
    ubVal = pomdp->getReward(s,a) + pomdp->getDiscount() * ubVal;
    if (ubVal > maxVal) {
      maxVal = ubVal;
      bestAction = a;
    }
  }
  return bestAction;
}

ValueInterval ConvexBounds::getValueAt(const state_vector& s) const
{
  return ValueInterval(keepLowerBound ? lowerBound->getValue(s) : -1,
		       upperBound->getValue(s));
}

bool ConvexBounds::getSupportsPolicyOutput(void) const
{
  return keepLowerBound;
}

void ConvexBounds::writePolicy(const std::string& outFileName)
{
  assert(NULL != lowerBound);
  lowerBound->prunePlanes();
  lowerBound->writeToFile(outFileName);
}

}; // namespace zmdp

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.9  2006/07/04 23:21:03  trey
 * removed unused variable declaration
 *
 * Revision 1.8  2006/06/03 13:32:08  trey
 * added CB_INITIALIZATION_PRECISION_FACTOR -- initialization is now forced to converge more tightly than the overall desired precision
 *
 * Revision 1.7  2006/05/12 16:04:30  trey
 * fixed problem with uninitialized variable
 *
 * Revision 1.6  2006/04/28 17:57:41  trey
 * changed to use apache license
 *
 * Revision 1.5  2006/04/27 23:10:31  trey
 * added support for writing policies
 *
 * Revision 1.4  2006/04/10 20:26:38  trey
 * added forceUpperBoundActionSelection
 *
 * Revision 1.3  2006/04/08 22:21:25  trey
 * fixed some bugs and added getNewUBValueUseCache()
 *
 * Revision 1.2  2006/04/06 20:34:47  trey
 * filled out most of ConvexBounds implementation
 *
 * Revision 1.1  2006/04/05 21:43:20  trey
 * collected and renamed several classes into pomdpBounds
 *
 *
 ***************************************************************************/
<commit_msg>removed belief argument fram addLBPlane()<commit_after>/********** tell emacs we use -*- c++ -*- style comments *******************
 $Revision: 1.11 $  $Author: trey $  $Date: 2006-07-14 15:10:08 $

 @file    ConvexBounds.cc
 @brief   No brief

 Copyright (c) 2006, Trey Smith. All rights reserved.

 Licensed under the Apache License, Version 2.0 (the "License"); you may
 not use this file except in compliance with the License.  You may
 obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 implied.  See the License for the specific language governing
 permissions and limitations under the License.

 ***************************************************************************/

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

#include <iostream>
#include <fstream>
#include <queue>

#include "zmdpCommonDefs.h"
#include "zmdpCommonTime.h"
#include "MatrixUtils.h"
#include "Pomdp.h"
#include "AbstractBound.h"
#include "ConvexBounds.h"

using namespace std;
using namespace sla;
using namespace MatrixUtils;

#define CB_QVAL_UNDEFINED (-99e+20)
#define CB_INITIALIZATION_PRECISION_FACTOR (1e-2)

namespace zmdp {

ConvexBounds::ConvexBounds(bool _keepLowerBound,
			   bool _forceUpperBoundActionSelection) :
  lowerBound(NULL),
  upperBound(NULL),
  keepLowerBound(_keepLowerBound),
  forceUpperBoundActionSelection(_forceUpperBoundActionSelection)
{}

// lower bound on long-term reward for taking action a (alpha vector)
void ConvexBounds::getNewLBPlaneQ(LBPlane& result, const MDPNode& cn, int a)
{
  alpha_vector betaA(pomdp->getBeliefSize()), betaAO(pomdp->getBeliefSize());
  alpha_vector tmp, tmp2;
#if USE_MASKED_ALPHA
  alpha_vector tmp3;
#endif

  set_to_zero(betaA);

  bool defaultIsSet = false;
  alpha_vector defaultBetaAO;
  const MDPQEntry& Qa = cn.Q[a];
  FOR (o, Qa.getNumOutcomes()) {
    MDPEdge* e = Qa.outcomes[o];
    if (NULL != e) {
      betaAO = lowerBound->getBestLBPlane(e->nextState->s).alpha;
    } else {
      // impossible to see this observation, so it doesn't make sense to
      // pick the alpha that optimizes for the next belief.  plug in a
      // default alpha (arbitrarily chosen to optimize for cn.b).
      if (!defaultIsSet) {
	defaultBetaAO = lowerBound->getBestLBPlane(cn.s).alpha;
	defaultIsSet = true;
      }
      betaAO = defaultBetaAO;
    }

    emult_column( tmp, pomdp->O[a], o, betaAO );
#if USE_MASKED_ALPHA
    mult( tmp3, pomdp->T[a], tmp );
    mask_copy( tmp2, tmp3, cn.s );
#else
    mult( tmp2, tmp, pomdp->Ttr[a] );
#endif
    betaA += tmp2;
  }

  alpha_vector Rxa;
#if USE_MASKED_ALPHA
  copy_from_column( tmp, pomdp->R, a );
  mask_copy( Rxa, tmp, cn.s );
#else
  copy_from_column( Rxa, pomdp->R, a );
#endif
  betaA *= pomdp->getDiscount();
  betaA += Rxa;

  result.alpha = betaA;
  result.action = a;
#if USE_MASKED_ALPHA
  result.mask = cn.s;
#endif
}

void ConvexBounds::getNewLBPlane(LBPlane& result, MDPNode& cn)
{
#if USE_DEBUG_PRINT
  timeval startTime = getTime();
#endif

  double val, maxVal = -99e+20;
  LBPlane betaA;

  FOR (a, cn.getNumActions()) {
    getNewLBPlaneQ(betaA, cn, a);
    val = inner_prod(betaA.alpha, cn.s);
    cn.Q[a].lbVal = val;
    if (val > maxVal) {
      maxVal = val;
      result = betaA;
    }
  }
#if USE_DEBUG_PRINT
  cout << "** newLowerBound: elapsed time = "
       << timevalToSeconds(getTime() - startTime)
       << endl;
#endif
}

void ConvexBounds::updateLowerBound(MDPNode& cn)
{
  LBPlane* newPlane = new LBPlane();
  getNewLBPlane(*newPlane, cn);
  cn.lbVal = inner_prod(cn.s, newPlane->alpha);

  lowerBound->addLBPlane(newPlane);
  lowerBound->maybePrune();
}

// upper bound on long-term reward for taking action a
double ConvexBounds::getNewUBValueQ(MDPNode& cn, int a)
{
  double val = 0;

  MDPQEntry& Qa = cn.Q[a];
  FOR (o, Qa.getNumOutcomes()) {
    MDPEdge* e = Qa.outcomes[o];
    if (NULL != e) {
      val += e->obsProb * upperBound->getValue(e->nextState->s);
    }
  }
  val = Qa.immediateReward + pomdp->getDiscount() * val;
  Qa.ubVal = val;

  return val;
}

double ConvexBounds::getNewUBValueSimple(MDPNode& cn, int* maxUBActionP)
{
#if USE_DEBUG_PRINT
  timeval startTime = getTime();
#endif

  double val, maxVal = -99e+20;
  int maxUBAction = -1;
  FOR (a, pomdp->getNumActions()) {
    val = getNewUBValueQ(cn,a);
    if (val > maxVal) {
      maxVal = val;
      maxUBAction = a;
    }
  }

  if (NULL != maxUBActionP) *maxUBActionP = maxUBAction;

#if USE_DEBUG_PRINT
  cout << "** newUpperBound: elapsed time = "
       << timevalToSeconds(getTime() - startTime)
       << endl;
#endif

  return maxVal;
}

double ConvexBounds::getNewUBValueUseCache(MDPNode& cn, int* maxUBActionP)
{
#if USE_DEBUG_PRINT
  timeval startTime = getTime();
#endif

  // cache upper bound for each action
  dvector cachedUpperBound(pomdp->getNumActions());
  FOR (a, pomdp->numActions) {
    cachedUpperBound(a) = cn.Q[a].ubVal;
  }

  // remember which Q functions we have updated on this call
  std::vector<bool> updatedAction(pomdp->getNumActions());
  FOR (a, pomdp->getNumActions()) {
    updatedAction[a] = false;
  }

  double val;
  int maxUBAction = argmax_elt(cachedUpperBound);
  while (1) {
    // do the backup for the best Q
    val = getNewUBValueQ(cn,maxUBAction);
    cachedUpperBound(maxUBAction) = val;
    updatedAction[maxUBAction] = true;

    // the best action may have changed after updating Q
    maxUBAction = argmax_elt(cachedUpperBound);

    // if the best action after the update is one that we have already
    //    updated, we're done
    if (updatedAction[maxUBAction]) break;
  }

  double maxVal = cachedUpperBound(maxUBAction);

  if (NULL != maxUBActionP) *maxUBActionP = maxUBAction;

#if USE_DEBUG_PRINT
  cout << "** newUpperBound: elapsed time = "
       << timevalToSeconds(getTime() - startTime)
       << endl;
#endif

  return maxVal;
}

double ConvexBounds::getNewUBValue(MDPNode& cn, int* maxUBActionP)
{
  if (CB_QVAL_UNDEFINED == cn.Q[0].ubVal) {
    return getNewUBValueSimple(cn, maxUBActionP);
  } else {
    return getNewUBValueUseCache(cn, maxUBActionP);
  }
}

void ConvexBounds::updateUpperBound(MDPNode& cn, int* maxUBActionP)
{
  double newUBVal = getNewUBValue(cn, maxUBActionP);
  upperBound->addPoint(cn.s, newUBVal);
  upperBound->maybePrune();
  cn.ubVal = newUBVal;
}

void ConvexBounds::initialize(const MDP* _pomdp,
			      double _targetPrecision)
{
  pomdp = (const Pomdp*) _pomdp;
  targetPrecision = CB_INITIALIZATION_PRECISION_FACTOR * _targetPrecision;

  if (keepLowerBound) {
    lowerBound = new MaxPlanesLowerBound(pomdp);
    lowerBound->initialize(targetPrecision);
  }

  upperBound = new SawtoothUpperBound(pomdp);
  upperBound->initialize(targetPrecision);

  lookup = new MDPHash();
  root = NULL;

  numStatesTouched = 0;
  numStatesExpanded = 0;
  numBackups = 0;

  getNodeHandler = NULL;
  handlerData = NULL;
}

MDPNode* ConvexBounds::getRootNode(void)
{
  if (NULL == root) {
    root = getNode(pomdp->getInitialState());
  }
  return root;
}

MDPNode* ConvexBounds::getNode(const state_vector& s)
{
  string hs = hashable(s);
  MDPHash::iterator pr = lookup->find(hs);
  if (lookup->end() == pr) {
    // create a new fringe node
    MDPNode& cn = *(new MDPNode);
    cn.s = s;
    cn.isTerminal = pomdp->getIsTerminalState(s);
    if (cn.isTerminal) {
      cn.ubVal = 0;
    } else {
      cn.ubVal = upperBound->getValue(s);
    }
    if (keepLowerBound) {
      if (cn.isTerminal) {
	cn.lbVal = 0;
      } else {
	cn.lbVal = lowerBound->getValue(s);
      }
    } else {
      cn.lbVal = -1; // n/a
    }
    cn.searchData = NULL;
    cn.boundsData = NULL;
    (*lookup)[hs] = &cn;

    if (NULL != getNodeHandler) {
      (*getNodeHandler)(cn, handlerData);
    }

    numStatesTouched++;
    return &cn;
  } else {
    // return existing node
    return pr->second;
  }
}

void ConvexBounds::expand(MDPNode& cn)
{
  // set up successors for this fringe node (possibly creating new fringe nodes)
  outcome_prob_vector opv;
  state_vector sp;
  cn.Q.resize(pomdp->getNumActions());
  FOR (a, pomdp->getNumActions()) {
    MDPQEntry& Qa = cn.Q[a];
    Qa.immediateReward = pomdp->getReward(cn.s, a);
    pomdp->getOutcomeProbVector(opv, cn.s, a);
    Qa.outcomes.resize(opv.size());
    FOR (o, opv.size()) {
      double oprob = opv(o);
      if (oprob > OBS_IS_ZERO_EPS) {
	MDPEdge* e = new MDPEdge();
        Qa.outcomes[o] = e;
        e->obsProb = oprob;
        e->nextState = getNode(pomdp->getNextState(sp, cn.s, a, o));
      } else {
        Qa.outcomes[o] = NULL;
      }
    }
    Qa.ubVal = CB_QVAL_UNDEFINED;
  }
  numStatesExpanded++;
}

void ConvexBounds::update(MDPNode& cn, int* maxUBActionP)
{
  if (cn.isFringe()) {
    expand(cn);
  }
  if (keepLowerBound) {
    updateLowerBound(cn);
  }
  updateUpperBound(cn, maxUBActionP);

  numBackups++;
}

// this implementation is not very efficient, but it is guaranteed not
// to modify the algorithm state, so it can safely be used for
// simulation testing in the middle of a run.
int ConvexBounds::chooseAction(const state_vector& s) const
{
  if (!forceUpperBoundActionSelection && keepLowerBound) {
    // 'direct' policy as opposed to 'lookahead' policy
    return lowerBound->getBestLBPlane(s).action;
  }

  // if not maintaining LB, fall back to UB
  outcome_prob_vector opv;
  state_vector sp;
  int bestAction = -1;

  double ubVal, ubValO;
  double maxVal = -99e+20;
  FOR (a, pomdp->getNumActions()) {
    pomdp->getOutcomeProbVector(opv, s, a);
    ubVal = 0;
    FOR (o, opv.size()) {
      if (opv(o) > OBS_IS_ZERO_EPS) {
	ubValO = upperBound->getValue(pomdp->getNextState(sp, s, a, o));
	ubVal += opv(o) * ubValO;
      }
    }
    ubVal = pomdp->getReward(s,a) + pomdp->getDiscount() * ubVal;
    if (ubVal > maxVal) {
      maxVal = ubVal;
      bestAction = a;
    }
  }
  return bestAction;
}

ValueInterval ConvexBounds::getValueAt(const state_vector& s) const
{
  return ValueInterval(keepLowerBound ? lowerBound->getValue(s) : -1,
		       upperBound->getValue(s));
}

bool ConvexBounds::getSupportsPolicyOutput(void) const
{
  return keepLowerBound;
}

void ConvexBounds::writePolicy(const std::string& outFileName)
{
  assert(NULL != lowerBound);
  lowerBound->prunePlanes();
  lowerBound->writeToFile(outFileName);
}

}; // namespace zmdp

/***************************************************************************
 * REVISION HISTORY:
 * $Log: not supported by cvs2svn $
 * Revision 1.10  2006/07/12 19:42:00  trey
 * removed use of obsolete copyFrom() function
 *
 * Revision 1.9  2006/07/04 23:21:03  trey
 * removed unused variable declaration
 *
 * Revision 1.8  2006/06/03 13:32:08  trey
 * added CB_INITIALIZATION_PRECISION_FACTOR -- initialization is now forced to converge more tightly than the overall desired precision
 *
 * Revision 1.7  2006/05/12 16:04:30  trey
 * fixed problem with uninitialized variable
 *
 * Revision 1.6  2006/04/28 17:57:41  trey
 * changed to use apache license
 *
 * Revision 1.5  2006/04/27 23:10:31  trey
 * added support for writing policies
 *
 * Revision 1.4  2006/04/10 20:26:38  trey
 * added forceUpperBoundActionSelection
 *
 * Revision 1.3  2006/04/08 22:21:25  trey
 * fixed some bugs and added getNewUBValueUseCache()
 *
 * Revision 1.2  2006/04/06 20:34:47  trey
 * filled out most of ConvexBounds implementation
 *
 * Revision 1.1  2006/04/05 21:43:20  trey
 * collected and renamed several classes into pomdpBounds
 *
 *
 ***************************************************************************/
<|endoftext|>


<commit_before>/*

Copyright (c) 2008-2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/
#include "test.hpp"

EXPORT int run_http_suite(int proxy, char const* protocol, bool test_url_seed, bool chunked_encoding, bool test_ban);

<commit_msg>attempt to fix test link error on windows<commit_after>/*

Copyright (c) 2008-2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/
#include "test.hpp"

int EXPORT run_http_suite(int proxy, char const* protocol, bool test_url_seed, bool chunked_encoding, bool test_ban);

<|endoftext|>


<commit_before>/*
* Copyright (c) 2009 Kevin Wolf <kevin@tyndur.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITRTLSS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, RTLGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONRTLCTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "CdiNet.h"

#include <Log.h>
#include <machine/Network.h>
#include <network-stack/NetworkStack.h>

// Prototypes in the extern "C" block to ensure that they are not mangled
extern "C" {
    void cdi_cpp_net_register(void* void_pdev, struct cdi_net_device* device);
    void cdi_net_receive(struct cdi_net_device* device, void* buffer, size_t size);
    struct cdi_net_device* cdi_net_get_device(int num);
};

CdiNet::CdiNet(Network* pDev, struct cdi_net_device* device) :
    Device(pDev), Network(pDev), m_Device(device)
{
    setSpecificType(String("CDI NIC"));

    /// \todo Check endianness - *should* be fine, but we'll see...
    uint64_t mac = m_Device->mac;
    m_StationInfo.mac.setMac(reinterpret_cast<uint8_t*>(&mac), false);

    NetworkStack::instance().registerDevice(this);
}

CdiNet::~CdiNet()
{
}

bool CdiNet::send(size_t nBytes, uintptr_t buffer)
{
    struct cdi_net_driver *driver = reinterpret_cast<struct cdi_net_driver *>(m_Device->dev.driver);
    if(driver)
    {
        driver->send_packet(m_Device, reinterpret_cast<void*>(buffer), nBytes);
        return true;
    }
    return false;
}

StationInfo CdiNet::getStationInfo()
{
    return m_StationInfo;
}

bool CdiNet::setStationInfo(StationInfo info)
{
    // free the old DNS servers list, if there is one
    if (m_StationInfo.dnsServers)
        delete [] m_StationInfo.dnsServers;

    // MAC isn't changeable, so set it all manually
    m_StationInfo.ipv4 = info.ipv4;
    NOTICE("cdi-net: Setting ipv4, " << info.ipv4.toString() << ", " << m_StationInfo.ipv4.toString() << "...");
    m_StationInfo.ipv6 = info.ipv6;

    m_StationInfo.subnetMask = info.subnetMask;
    NOTICE("cdi-net: Setting subnet mask, " << info.subnetMask.toString() << ", " << m_StationInfo.subnetMask.toString() << "...");
    m_StationInfo.gateway = info.gateway;
    NOTICE("cdi-net: Setting gateway, " << info.gateway.toString() << ", " << m_StationInfo.gateway.toString() << "...");

    // Callers do not free their dnsServers memory
    m_StationInfo.dnsServers = info.dnsServers;
    m_StationInfo.nDnsServers = info.nDnsServers;
    NOTICE("cdi-net: Setting DNS servers [" << Dec << m_StationInfo.nDnsServers << Hex << " servers being set]...");

    return true;
}

void cdi_cpp_net_register(void* void_pdev, struct cdi_net_device* device)
{
    Network* pDev = reinterpret_cast<Network*>(void_pdev);

    // Create a new CdiNet node
    CdiNet *pCdiNet = new CdiNet(pDev, device);

    // Replace pDev with pCdiNet
    pCdiNet->setParent(pDev->getParent());
    pDev->getParent()->replaceChild(pDev, pCdiNet);
    device->dev.backdev = reinterpret_cast<void*>(pCdiNet);
}

/**
 * Wird von Netzwerktreibern aufgerufen, wenn ein Netzwerkpaket
 * empfangen wurde.
 */
void cdi_net_receive(struct cdi_net_device* device, void* buffer, size_t size)
{
    NetworkStack::instance().receive(size, reinterpret_cast<uintptr_t>(buffer), reinterpret_cast<Network*>(device->dev.backdev), 0);
}
<commit_msg>cdi-net: ensure nIpv6Addresses is set in StationInfo to avoid issues where it's undefined value is a large number.<commit_after>/*
* Copyright (c) 2009 Kevin Wolf <kevin@tyndur.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITRTLSS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, RTLGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONRTLCTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "CdiNet.h"

#include <Log.h>
#include <machine/Network.h>
#include <network-stack/NetworkStack.h>

// Prototypes in the extern "C" block to ensure that they are not mangled
extern "C" {
    void cdi_cpp_net_register(void* void_pdev, struct cdi_net_device* device);
    void cdi_net_receive(struct cdi_net_device* device, void* buffer, size_t size);
    struct cdi_net_device* cdi_net_get_device(int num);
};

CdiNet::CdiNet(Network* pDev, struct cdi_net_device* device) :
    Device(pDev), Network(pDev), m_Device(device)
{
    setSpecificType(String("CDI NIC"));

    /// \todo Check endianness - *should* be fine, but we'll see...
    uint64_t mac = m_Device->mac;
    m_StationInfo.mac.setMac(reinterpret_cast<uint8_t*>(&mac), false);

    NetworkStack::instance().registerDevice(this);
}

CdiNet::~CdiNet()
{
}

bool CdiNet::send(size_t nBytes, uintptr_t buffer)
{
    struct cdi_net_driver *driver = reinterpret_cast<struct cdi_net_driver *>(m_Device->dev.driver);
    if(driver)
    {
        driver->send_packet(m_Device, reinterpret_cast<void*>(buffer), nBytes);
        return true;
    }
    return false;
}

StationInfo CdiNet::getStationInfo()
{
    return m_StationInfo;
}

bool CdiNet::setStationInfo(StationInfo info)
{
    // free the old DNS servers list, if there is one
    if (m_StationInfo.dnsServers)
        delete [] m_StationInfo.dnsServers;

    // MAC isn't changeable, so set it all manually
    m_StationInfo.ipv4 = info.ipv4;
    NOTICE("cdi-net: Setting ipv4, " << info.ipv4.toString() << ", " << m_StationInfo.ipv4.toString() << "...");

    m_StationInfo.ipv6 = info.ipv6;
    m_StationInfo.nIpv6Addresses = info.nIpv6Addresses;
    NOTICE("cdi-net: Assigning " << Dec << info.nIpv6Addresses << Hex << " IPv6 addresses.");

    m_StationInfo.subnetMask = info.subnetMask;
    NOTICE("cdi-net: Setting subnet mask, " << info.subnetMask.toString() << ", " << m_StationInfo.subnetMask.toString() << "...");
    m_StationInfo.gateway = info.gateway;
    NOTICE("cdi-net: Setting gateway, " << info.gateway.toString() << ", " << m_StationInfo.gateway.toString() << "...");

    // Callers do not free their dnsServers memory
    m_StationInfo.dnsServers = info.dnsServers;
    m_StationInfo.nDnsServers = info.nDnsServers;
    NOTICE("cdi-net: Setting DNS servers [" << Dec << m_StationInfo.nDnsServers << Hex << " servers being set]...");

    return true;
}

void cdi_cpp_net_register(void* void_pdev, struct cdi_net_device* device)
{
    Network* pDev = reinterpret_cast<Network*>(void_pdev);

    // Create a new CdiNet node
    CdiNet *pCdiNet = new CdiNet(pDev, device);

    // Replace pDev with pCdiNet
    pCdiNet->setParent(pDev->getParent());
    pDev->getParent()->replaceChild(pDev, pCdiNet);
    device->dev.backdev = reinterpret_cast<void*>(pCdiNet);
}

/**
 * Wird von Netzwerktreibern aufgerufen, wenn ein Netzwerkpaket
 * empfangen wurde.
 */
void cdi_net_receive(struct cdi_net_device* device, void* buffer, size_t size)
{
    NetworkStack::instance().receive(size, reinterpret_cast<uintptr_t>(buffer), reinterpret_cast<Network*>(device->dev.backdev), 0);
}
<|endoftext|>


<commit_before>#include<stdio.h>
#include<stdlib.h>
#include<queue>
using namespace std;

#define SIZE 1000

int step[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};

typedef struct {
  int x;
  int y;
  int s;
} node;

int main(int argc,char** argv){
  int total;
  bool all_in_all[100];
  scanf("%d",&total);
  for(int counter = 0; counter < total; counter ++){
    all_in_all[counter] = false;
    int hx,lx,hy,ly,cnt;
    int head = 0,tail = 0;
    queue<node> q;
    char a[SIZE][SIZE];
    scanf("%d",&cnt);
    for(int i = 0; i < cnt; i++)
      scanf("%s",a[i]);
    //hx,hy是出发点，lx,ly是目标位置
    scanf("%d%d%d%d",&hx,&hy,&lx,&ly);
    while(!q.empty())q.pop();
    node now;
    now.x = hx;
    now.y = hy;
    now.s = 0;
    q.push(now);
    tail++;
    while(!q.empty()){
      now = q.front();
      q.pop();
      if(now.x == lx && now.y == ly){
	all_in_all[counter] = true;
        break;
      }
      a[now.x][now.y] = '#';
      for(int i=0;i<4;i++){
	int x=now.x+step[i][0];
	int y=now.y+step[i][1];
	if(x >= 0 && y >= 0 && x < cnt && y < cnt && a[x][y] == '.'){
	  a[x][y] = '#';
	  node next;
	  next.x = x;
	  next.y = y;
	  next.s = now.s + 1;
	  q.push(next);
	}
      }
    //↓while的终止大括号
    }
  }
  for(int counter = 0; counter < total; counter ++){
    if(all_in_all[counter]) printf("YES\n");
    else printf("NO\n");
  }
  // system("PAUSE");
  return 0;
}
<commit_msg>把宏改成常量<commit_after>#include<stdio.h>
#include<stdlib.h>
#include<queue>
using namespace std;

const int SIZE = 1000;

int step[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};

typedef struct {
  int x;
  int y;
  int s;
} node;

int main(int argc,char** argv){
  int total;
  bool all_in_all[100];
  scanf("%d",&total);
  for(int counter = 0; counter < total; counter ++){
    all_in_all[counter] = false;
    int hx,lx,hy,ly,cnt;
    int head = 0,tail = 0;
    queue<node> q;
    char a[SIZE][SIZE];
    scanf("%d",&cnt);
    for(int i = 0; i < cnt; i++)
      scanf("%s",a[i]);
    //hx,hy是出发点，lx,ly是目标位置
    scanf("%d%d%d%d",&hx,&hy,&lx,&ly);
    while(!q.empty())q.pop();
    node now;
    now.x = hx;
    now.y = hy;
    now.s = 0;
    q.push(now);
    tail++;
    while(!q.empty()){
      now = q.front();
      q.pop();
      if(now.x == lx && now.y == ly){
	all_in_all[counter] = true;
        break;
      }
      a[now.x][now.y] = '#';
      for(int i=0;i<4;i++){
	int x=now.x+step[i][0];
	int y=now.y+step[i][1];
	if(x >= 0 && y >= 0 && x < cnt && y < cnt && a[x][y] == '.'){
	  a[x][y] = '#';
	  node next;
	  next.x = x;
	  next.y = y;
	  next.s = now.s + 1;
	  q.push(next);
	}
      }
    //↓while的终止大括号
    }
  }
  for(int counter = 0; counter < total; counter ++){
    if(all_in_all[counter]) printf("YES\n");
    else printf("NO\n");
  }
  // system("PAUSE");
  return 0;
}
<|endoftext|>


<commit_before>/*
 *  This file is part of the beirdobot package
 *  Copyright (C) 2010 Gavin Hurlbut
 *
 *  beirdobot is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*HEADER---------------------------------------------------
* $Id$
*
* Copyright 2010 Gavin Hurlbut
* All rights reserved
*
*/

#include "environment.h"
#include "clucene.h"
#include <CLucene.h>
#include <CLucene/config/repl_tchar.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#ifndef WEBSERVICE
#include "protos.h"
#include "logging.h"
#include "queue.h"
#endif

using namespace std;
using namespace lucene::index;
using namespace lucene::analysis;
using namespace lucene::util;
using namespace lucene::store;
using namespace lucene::queryParser;
using namespace lucene::document;
using namespace lucene::search;

static char ident[] _UNUSED_=
    "$Id$";

#define MAX_STRING_LEN 1024

#ifndef WEBSERVICE
typedef struct {
    unsigned long   id;
    int             chanid;
    char           *nick;
    char           *text;
    unsigned long   timestamp;
} IndexItem_t;

pthread_t       cluceneThreadId;
pthread_t       kickerThreadId;
int             docmax = 0;

void addLogentry( Document *doc, unsigned long *tb, IndexItem_t *item );
int loadLogentry( Document *doc, unsigned long tb );
void *clucene_thread( void *arg );
void *kicker_thread( void *arg );
IndexWriter *getWriter( int clear );
void closeWriter( IndexWriter *writer );
#endif
char *clucene_escape( char *text );

/* The C interface portion */
extern "C" {
#ifndef WEBSERVICE
    QueueObject_t  *IndexQ;

    void clucene_init(int clear)
    {
        int        *clr;

        clr = (int *)malloc(sizeof(int));
        *clr = clear;

        IndexQ = QueueCreate( 1024 );

        versionAdd( (char *)"CLucene", (char *)_CL_VERSION );

        /* Start the threads */
        thread_create( &cluceneThreadId, clucene_thread, clr,
                       (char *)"thread_clucene", NULL );
        if( !clear ) {
            thread_create( &kickerThreadId, kicker_thread, NULL,
                           (char *)"thread_kicker", NULL );
        }
    }
#endif

    void clucene_shutdown(void)
    {
        _lucene_shutdown();
    }

#ifndef WEBSERVICE
    void clucene_add( int chanid, char *nick, char *text,
                      unsigned long timestamp )
    {
        IndexItem_t        *item;

        item = (IndexItem_t *)malloc(sizeof(IndexItem_t));
        memset( item, 0, sizeof(IndexItem_t) );

        item->chanid    = chanid;
        item->nick      = nick ? strdup(nick) : NULL;
        item->text      = text ? strdup(text) : NULL;
        item->timestamp = (timestamp / SEARCH_WINDOW);

        QueueEnqueueItem( IndexQ, item );
    }
#endif

    SearchResults_t *clucene_search( int chanid, char *text, int *count,
                                     int max )
    {
        IndexReader            *reader;
        WhitespaceAnalyzer      an;
        IndexSearcher          *s;
        Query                  *q;
        Hits                   *h;
        Document               *d;
        static TCHAR            query[MAX_STRING_LEN];
        char                   *esctext;
        SearchResults_t        *results;
        int                     i;
        char                   *ts;

        reader = IndexReader::open(CLUCENE_INDEX_DIR);
        s = _CLNEW IndexSearcher(reader);

        esctext = clucene_escape(text);
        _sntprintf( query, MAX_STRING_LEN,
                    _T("chanid:%ld AND (text:\"%s\" OR nick:\"%s\")"), chanid,
                    esctext, esctext );
#ifndef WEBSERVICE
        LogPrint(LOG_INFO, "Query: %ls", query);
#endif
        q = QueryParser::parse(query, _T("text"), &an);
        h = s->search(q);
        if( h->length() == 0 ) {
            *count = 0;
            reader->close();
            _CLDELETE(h);
            _CLDELETE(q);
            _CLDELETE(s);
            _CLDELETE(reader);
            return( NULL );
        }
        *count = (h->length() > max ? max : h->length());
        results = (SearchResults_t *)malloc(*count * sizeof(SearchResults_t));
        for( i = 0; i < *count; i++ ) {
            d = &h->doc(i);
            ts = STRDUP_TtoA(d->get(_T("timestamp")));
            results[i].timestamp = atoi(ts) * SEARCH_WINDOW;
            results[i].score = h->score(i);
            free( ts );
        }

        reader->close();
        _CLDELETE(h);
        _CLDELETE(q);
        _CLDELETE(s);
        _CLDELETE(reader);

        return( results );
    }
}

/* C++ internals */

char *clucene_escape( char *text )
{
    static char         buf[MAX_STRING_LEN];
    static const char   chars[] = "+-&|!(){}[]^\"~*?:\\";
    int                 len;
    int                 i;
    int                 j;

    len = strlen(text);
    for( i = 0, j = 0; i < len && j < MAX_STRING_LEN - 1; i++ ) {
        if( strchr( chars, (int)text[i] ) ) {
            buf[j++] = '\\';
        }
        buf[j++] = text[i];
    }
    buf[j] = '\0';
    return( buf );
}

#ifndef WEBSERVICE
void addLogentry( Document *doc, unsigned long *tb, IndexItem_t *item )
{
    static TCHAR            buf[MAX_STRING_LEN];
    IndexWriter            *writer;

    if( *tb != item->timestamp ) {
        if( *tb != 0 ) {
            writer = getWriter(false);
            writer->addDocument( doc );
            closeWriter( writer );
            doc->clear();
        }

        if( item->text == NULL ) {
            /* Keepalive */
            *tb = 0;
            return;
        }

        if( !loadLogentry( doc, item->timestamp ) ) {
            _sntprintf( buf, MAX_STRING_LEN, _T("%ld"), item->timestamp );
            doc->add( *_CLNEW Field( _T("timestamp"), buf,
                      Field::STORE_YES | Field::INDEX_TOKENIZED ) );

            _sntprintf( buf, MAX_STRING_LEN, _T("%ld"), item->chanid );
            doc->add( *_CLNEW Field( _T("chanid"), buf,
                    Field::STORE_YES | Field::INDEX_TOKENIZED ) );
        }
        *tb = item->timestamp;
    }

    STRCPY_AtoT(buf, item->nick, MAX_STRING_LEN);
    doc->add( *_CLNEW Field( _T("nick"), buf,
              Field::STORE_YES | Field::INDEX_TOKENIZED ) );

    STRCPY_AtoT(buf, item->text, MAX_STRING_LEN);
    doc->add( *_CLNEW Field( _T("text"), buf,
              Field::STORE_YES | Field::INDEX_TOKENIZED ) );
}

int loadLogentry( Document *doc, unsigned long tb )
{
    IndexReader                *reader;
    WhitespaceAnalyzer          an;
    IndexSearcher              *s;
    Query                      *q;
    Hits                       *h;
    Document                   *d;
    DocumentFieldEnumeration   *fields;
    Field                      *field;
    static TCHAR                query[80];
    int                         len;

    reader = IndexReader::open(CLUCENE_INDEX_DIR);
    s = _CLNEW IndexSearcher(reader);

    _sntprintf( query, 80, _T("%ld"), tb );
    q = QueryParser::parse(query, _T("timestamp"), &an);
    h = s->search(q);
    len = h->length();
#if 0
    LogPrint( LOG_INFO, "Q: %ls  len: %d", q->toString(), len );
#endif
    if( h->length() == 0 ) {
        reader->close();
        _CLDELETE(h);
        _CLDELETE(q);
        _CLDELETE(s);
        _CLDELETE(reader);
        return( 0 );
    }
    d = &h->doc(0);
    fields = d->fields();
    doc->clear();
    /* Recreate the current document */
    while( (field = fields->nextElement()) ) {
        doc->add( *_CLNEW Field( field->name(), field->stringValue(),
                                 Field::STORE_YES | Field::INDEX_TOKENIZED ) );
    }
    LogPrint( LOG_INFO, "Deleting document %lld", h->id(0) );
    reader->deleteDocument( h->id(0) );
    reader->close();

    _CLDELETE(h);
    _CLDELETE(q);
    _CLDELETE(s);
    _CLDELETE(reader);

    return( 1 );
}

IndexWriter *getWriter( int clear )
{
    WhitespaceAnalyzer *an;
    IndexWriter        *writer = NULL;

#if 0
    LogPrintNoArg(LOG_INFO, "Opening writer");
#endif
    an = _CLNEW WhitespaceAnalyzer;
    if ( !clear && IndexReader::indexExists(CLUCENE_INDEX_DIR) ){
        if ( IndexReader::isLocked(CLUCENE_INDEX_DIR) ){
            LogPrintNoArg( LOG_INFO, "Index was locked... unlocking it.");
            IndexReader::unlock(CLUCENE_INDEX_DIR);
        }

        writer = _CLNEW IndexWriter( CLUCENE_INDEX_DIR, an, false);
    } else {
        writer = _CLNEW IndexWriter( CLUCENE_INDEX_DIR, an, true);
    }

    writer->setMaxFieldLength(1000000);

    return( writer );
}

void closeWriter( IndexWriter *writer )
{
    WhitespaceAnalyzer *an;

#if 0
    LogPrintNoArg( LOG_INFO, "Closing Writer" );
#endif
    an = (WhitespaceAnalyzer *)writer->getAnalyzer();
    writer->close();
    _CLDELETE(an);
    _CLDELETE(writer);
}

void *kicker_thread( void *arg )
{
    struct timeval  tv;
    unsigned long   now;
    unsigned long   target;
    int             i;

    LogPrintNoArg( LOG_INFO, "Starting CLucene Kicker thread" );
    while( !GlobalAbort ) {
        gettimeofday( &tv, NULL );
        now = tv.tv_sec;
        target = ((now / SEARCH_WINDOW) + 1) * SEARCH_WINDOW;
        sleep( target - now );

        LogPrint( LOG_INFO, "Kicking %d channel indexes", docmax );
        for( i = 0; i < docmax; i++ ) {
            clucene_add( i + 1, NULL, NULL, target / SEARCH_WINDOW );
        }
    }
    LogPrintNoArg( LOG_INFO, "Ending CLucene Kicker thread" );

    return( NULL );
}

void *clucene_thread( void *arg )
{
    IndexItem_t        *item;
    IndexWriter        *writer = NULL;
    Document          **doc = NULL;
    unsigned long      *lasttb = NULL;
    int                 i;
    int                 clear;

    clear = *(int *)arg;
    LogPrint(LOG_INFO, "Clear: %d", clear );

    LogPrintNoArg( LOG_NOTICE, "Starting CLucene thread" );
    LogPrint( LOG_INFO, "Using CLucene v%s index in %s", _CL_VERSION,
              CLUCENE_INDEX_DIR );

    writer = getWriter(clear);
    LogPrint( LOG_INFO, "%lld documents indexed", writer->docCount() );
    LogPrintNoArg( LOG_INFO, "Optimizing index" );
    writer->optimize();
    LogPrintNoArg( LOG_INFO, "Finished optimizing index" );
    closeWriter( writer );

    while( !GlobalAbort ) {
        item = (IndexItem_t *)QueueDequeueItem( IndexQ, 1000 );
        if( !item ) {
            continue;
        }

        if( item->chanid > docmax ) {
            doc = (Document **)realloc(doc, item->chanid * sizeof(Document *));
            lasttb = (unsigned long *)realloc(lasttb,
                                        item->chanid * sizeof(unsigned long ));
            for( i = docmax; i < item->chanid; i++ ) {
                doc[i] = new Document;
                doc[i]->clear();
                lasttb[i] = 0;
            }
            docmax = item->chanid;
        }

        addLogentry( doc[item->chanid - 1], &lasttb[item->chanid - 1], item );

        if( item->nick ) {
            free( item->nick );
        }

        if( item->text ) {
            free( item->text );
        }
        free( item );
    }

    LogPrintNoArg( LOG_NOTICE, "Ending CLucene thread" );

    writer = getWriter(0);
    for( i = 0; i < docmax; i++ ) {
        if( lasttb[i] != 0 ) {
            writer->addDocument( doc[i] );
            _CLDELETE( doc[i] );
        }
    }
    closeWriter( writer );

    free( lasttb );
    free( doc );

    return(NULL);
}
#endif

/*
 * vim:ts=4:sw=4:ai:et:si:sts=4
 */
<commit_msg>Fix a 32bit counter print on clucene startup<commit_after>/*
 *  This file is part of the beirdobot package
 *  Copyright (C) 2010 Gavin Hurlbut
 *
 *  beirdobot is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*HEADER---------------------------------------------------
* $Id$
*
* Copyright 2010 Gavin Hurlbut
* All rights reserved
*
*/

#include "environment.h"
#include "clucene.h"
#include <CLucene.h>
#include <CLucene/config/repl_tchar.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#ifndef WEBSERVICE
#include "protos.h"
#include "logging.h"
#include "queue.h"
#endif

using namespace std;
using namespace lucene::index;
using namespace lucene::analysis;
using namespace lucene::util;
using namespace lucene::store;
using namespace lucene::queryParser;
using namespace lucene::document;
using namespace lucene::search;

static char ident[] _UNUSED_=
    "$Id$";

#define MAX_STRING_LEN 1024

#ifndef WEBSERVICE
typedef struct {
    unsigned long   id;
    int             chanid;
    char           *nick;
    char           *text;
    unsigned long   timestamp;
} IndexItem_t;

pthread_t       cluceneThreadId;
pthread_t       kickerThreadId;
int             docmax = 0;

void addLogentry( Document *doc, unsigned long *tb, IndexItem_t *item );
int loadLogentry( Document *doc, unsigned long tb );
void *clucene_thread( void *arg );
void *kicker_thread( void *arg );
IndexWriter *getWriter( int clear );
void closeWriter( IndexWriter *writer );
#endif
char *clucene_escape( char *text );

/* The C interface portion */
extern "C" {
#ifndef WEBSERVICE
    QueueObject_t  *IndexQ;

    void clucene_init(int clear)
    {
        int        *clr;

        clr = (int *)malloc(sizeof(int));
        *clr = clear;

        IndexQ = QueueCreate( 1024 );

        versionAdd( (char *)"CLucene", (char *)_CL_VERSION );

        /* Start the threads */
        thread_create( &cluceneThreadId, clucene_thread, clr,
                       (char *)"thread_clucene", NULL );
        if( !clear ) {
            thread_create( &kickerThreadId, kicker_thread, NULL,
                           (char *)"thread_kicker", NULL );
        }
    }
#endif

    void clucene_shutdown(void)
    {
        _lucene_shutdown();
    }

#ifndef WEBSERVICE
    void clucene_add( int chanid, char *nick, char *text,
                      unsigned long timestamp )
    {
        IndexItem_t        *item;

        item = (IndexItem_t *)malloc(sizeof(IndexItem_t));
        memset( item, 0, sizeof(IndexItem_t) );

        item->chanid    = chanid;
        item->nick      = nick ? strdup(nick) : NULL;
        item->text      = text ? strdup(text) : NULL;
        item->timestamp = (timestamp / SEARCH_WINDOW);

        QueueEnqueueItem( IndexQ, item );
    }
#endif

    SearchResults_t *clucene_search( int chanid, char *text, int *count,
                                     int max )
    {
        IndexReader            *reader;
        WhitespaceAnalyzer      an;
        IndexSearcher          *s;
        Query                  *q;
        Hits                   *h;
        Document               *d;
        static TCHAR            query[MAX_STRING_LEN];
        char                   *esctext;
        SearchResults_t        *results;
        int                     i;
        char                   *ts;

        reader = IndexReader::open(CLUCENE_INDEX_DIR);
        s = _CLNEW IndexSearcher(reader);

        esctext = clucene_escape(text);
        _sntprintf( query, MAX_STRING_LEN,
                    _T("chanid:%ld AND (text:\"%s\" OR nick:\"%s\")"), chanid,
                    esctext, esctext );
#ifndef WEBSERVICE
        LogPrint(LOG_INFO, "Query: %ls", query);
#endif
        q = QueryParser::parse(query, _T("text"), &an);
        h = s->search(q);
        if( h->length() == 0 ) {
            *count = 0;
            reader->close();
            _CLDELETE(h);
            _CLDELETE(q);
            _CLDELETE(s);
            _CLDELETE(reader);
            return( NULL );
        }
        *count = (h->length() > max ? max : h->length());
        results = (SearchResults_t *)malloc(*count * sizeof(SearchResults_t));
        for( i = 0; i < *count; i++ ) {
            d = &h->doc(i);
            ts = STRDUP_TtoA(d->get(_T("timestamp")));
            results[i].timestamp = atoi(ts) * SEARCH_WINDOW;
            results[i].score = h->score(i);
            free( ts );
        }

        reader->close();
        _CLDELETE(h);
        _CLDELETE(q);
        _CLDELETE(s);
        _CLDELETE(reader);

        return( results );
    }
}

/* C++ internals */

char *clucene_escape( char *text )
{
    static char         buf[MAX_STRING_LEN];
    static const char   chars[] = "+-&|!(){}[]^\"~*?:\\";
    int                 len;
    int                 i;
    int                 j;

    len = strlen(text);
    for( i = 0, j = 0; i < len && j < MAX_STRING_LEN - 1; i++ ) {
        if( strchr( chars, (int)text[i] ) ) {
            buf[j++] = '\\';
        }
        buf[j++] = text[i];
    }
    buf[j] = '\0';
    return( buf );
}

#ifndef WEBSERVICE
void addLogentry( Document *doc, unsigned long *tb, IndexItem_t *item )
{
    static TCHAR            buf[MAX_STRING_LEN];
    IndexWriter            *writer;

    if( *tb != item->timestamp ) {
        if( *tb != 0 ) {
            writer = getWriter(false);
            writer->addDocument( doc );
            closeWriter( writer );
            doc->clear();
        }

        if( item->text == NULL ) {
            /* Keepalive */
            *tb = 0;
            return;
        }

        if( !loadLogentry( doc, item->timestamp ) ) {
            _sntprintf( buf, MAX_STRING_LEN, _T("%ld"), item->timestamp );
            doc->add( *_CLNEW Field( _T("timestamp"), buf,
                      Field::STORE_YES | Field::INDEX_TOKENIZED ) );

            _sntprintf( buf, MAX_STRING_LEN, _T("%ld"), item->chanid );
            doc->add( *_CLNEW Field( _T("chanid"), buf,
                    Field::STORE_YES | Field::INDEX_TOKENIZED ) );
        }
        *tb = item->timestamp;
    }

    STRCPY_AtoT(buf, item->nick, MAX_STRING_LEN);
    doc->add( *_CLNEW Field( _T("nick"), buf,
              Field::STORE_YES | Field::INDEX_TOKENIZED ) );

    STRCPY_AtoT(buf, item->text, MAX_STRING_LEN);
    doc->add( *_CLNEW Field( _T("text"), buf,
              Field::STORE_YES | Field::INDEX_TOKENIZED ) );
}

int loadLogentry( Document *doc, unsigned long tb )
{
    IndexReader                *reader;
    WhitespaceAnalyzer          an;
    IndexSearcher              *s;
    Query                      *q;
    Hits                       *h;
    Document                   *d;
    DocumentFieldEnumeration   *fields;
    Field                      *field;
    static TCHAR                query[80];
    int                         len;

    reader = IndexReader::open(CLUCENE_INDEX_DIR);
    s = _CLNEW IndexSearcher(reader);

    _sntprintf( query, 80, _T("%ld"), tb );
    q = QueryParser::parse(query, _T("timestamp"), &an);
    h = s->search(q);
    len = h->length();
#if 0
    LogPrint( LOG_INFO, "Q: %ls  len: %d", q->toString(), len );
#endif
    if( h->length() == 0 ) {
        reader->close();
        _CLDELETE(h);
        _CLDELETE(q);
        _CLDELETE(s);
        _CLDELETE(reader);
        return( 0 );
    }
    d = &h->doc(0);
    fields = d->fields();
    doc->clear();
    /* Recreate the current document */
    while( (field = fields->nextElement()) ) {
        doc->add( *_CLNEW Field( field->name(), field->stringValue(),
                                 Field::STORE_YES | Field::INDEX_TOKENIZED ) );
    }
    LogPrint( LOG_INFO, "Deleting document %lld", h->id(0) );
    reader->deleteDocument( h->id(0) );
    reader->close();

    _CLDELETE(h);
    _CLDELETE(q);
    _CLDELETE(s);
    _CLDELETE(reader);

    return( 1 );
}

IndexWriter *getWriter( int clear )
{
    WhitespaceAnalyzer *an;
    IndexWriter        *writer = NULL;

#if 0
    LogPrintNoArg(LOG_INFO, "Opening writer");
#endif
    an = _CLNEW WhitespaceAnalyzer;
    if ( !clear && IndexReader::indexExists(CLUCENE_INDEX_DIR) ){
        if ( IndexReader::isLocked(CLUCENE_INDEX_DIR) ){
            LogPrintNoArg( LOG_INFO, "Index was locked... unlocking it.");
            IndexReader::unlock(CLUCENE_INDEX_DIR);
        }

        writer = _CLNEW IndexWriter( CLUCENE_INDEX_DIR, an, false);
    } else {
        writer = _CLNEW IndexWriter( CLUCENE_INDEX_DIR, an, true);
    }

    writer->setMaxFieldLength(1000000);

    return( writer );
}

void closeWriter( IndexWriter *writer )
{
    WhitespaceAnalyzer *an;

#if 0
    LogPrintNoArg( LOG_INFO, "Closing Writer" );
#endif
    an = (WhitespaceAnalyzer *)writer->getAnalyzer();
    writer->close();
    _CLDELETE(an);
    _CLDELETE(writer);
}

void *kicker_thread( void *arg )
{
    struct timeval  tv;
    unsigned long   now;
    unsigned long   target;
    int             i;

    LogPrintNoArg( LOG_INFO, "Starting CLucene Kicker thread" );
    while( !GlobalAbort ) {
        gettimeofday( &tv, NULL );
        now = tv.tv_sec;
        target = ((now / SEARCH_WINDOW) + 1) * SEARCH_WINDOW;
        sleep( target - now );

        LogPrint( LOG_INFO, "Kicking %d channel indexes", docmax );
        for( i = 0; i < docmax; i++ ) {
            clucene_add( i + 1, NULL, NULL, target / SEARCH_WINDOW );
        }
    }
    LogPrintNoArg( LOG_INFO, "Ending CLucene Kicker thread" );

    return( NULL );
}

void *clucene_thread( void *arg )
{
    IndexItem_t        *item;
    IndexWriter        *writer = NULL;
    Document          **doc = NULL;
    unsigned long      *lasttb = NULL;
    int                 i;
    int                 clear;

    clear = *(int *)arg;
    LogPrint(LOG_INFO, "Clear: %d", clear );

    LogPrintNoArg( LOG_NOTICE, "Starting CLucene thread" );
    LogPrint( LOG_INFO, "Using CLucene v%s index in %s", _CL_VERSION,
              CLUCENE_INDEX_DIR );

    writer = getWriter(clear);
    LogPrint( LOG_INFO, "%ld documents indexed", (long int)writer->docCount() );
    LogPrintNoArg( LOG_INFO, "Optimizing index" );
    writer->optimize();
    LogPrintNoArg( LOG_INFO, "Finished optimizing index" );
    closeWriter( writer );

    while( !GlobalAbort ) {
        item = (IndexItem_t *)QueueDequeueItem( IndexQ, 1000 );
        if( !item ) {
            continue;
        }

        if( item->chanid > docmax ) {
            doc = (Document **)realloc(doc, item->chanid * sizeof(Document *));
            lasttb = (unsigned long *)realloc(lasttb,
                                        item->chanid * sizeof(unsigned long ));
            for( i = docmax; i < item->chanid; i++ ) {
                doc[i] = new Document;
                doc[i]->clear();
                lasttb[i] = 0;
            }
            docmax = item->chanid;
        }

        addLogentry( doc[item->chanid - 1], &lasttb[item->chanid - 1], item );

        if( item->nick ) {
            free( item->nick );
        }

        if( item->text ) {
            free( item->text );
        }
        free( item );
    }

    LogPrintNoArg( LOG_NOTICE, "Ending CLucene thread" );

    writer = getWriter(0);
    for( i = 0; i < docmax; i++ ) {
        if( lasttb[i] != 0 ) {
            writer->addDocument( doc[i] );
            _CLDELETE( doc[i] );
        }
    }
    closeWriter( writer );

    free( lasttb );
    free( doc );

    return(NULL);
}
#endif

/*
 * vim:ts=4:sw=4:ai:et:si:sts=4
 */
<|endoftext|>


<commit_before><commit_msg>Add experimental windows support<commit_after>#ifndef FREUD_WINDOWS_MEMORY_CONTEXT
#define FREUD_WINDOWS_MEMORY_CONTEXT

#include "freud/MemoryContext.hpp"
#include <windows.h>

namespace freud {

class WindowsMemoryContext : public BaseMemoryContext<WindowsMemoryContext> {
public:
    WindowsMemoryContext(unsigned long pid) : BaseMemoryContext(), m_pid(pid) {
        update_regions();
    }

    ~WindowsMemoryContext() {}

    bool read(address_t address, std::vector<char>& buffer) {
        return read(address, buffer, region_containing(address));
    }

    bool
    read(address_t address, std::vector<char>& buffer,
         std::vector<BaseMemoryContext::MemoryRegion>::const_iterator iter) {
        SIZE_T bytes_read;
        bool res =
            ReadProcessMemory(m_proc_handle, (LPCVOID)address, &*buffer.begin(),
                              buffer.size(), &bytes_read);
        return res;
    }

    void update_regions() {
        m_regions.clear();
        MEMORY_BASIC_INFORMATION mem_info;
        SYSTEM_INFO system_info;
        m_proc_handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, m_pid);

        GetSystemInfo(&system_info);

        for (LPVOID address = system_info.lpMinimumApplicationAddress;
             address < system_info.lpMaximumApplicationAddress;
             address = (LPVOID)((DWORD)mem_info.BaseAddress +
                                (DWORD)mem_info.RegionSize)) {

            VirtualQueryEx(m_proc_handle, address, &mem_info, sizeof(mem_info));

            if (mem_info.State & MEM_FREE || mem_info.State & MEM_RESERVE) {
                continue;
            }

            MemoryRegion region = {"", (address_t)mem_info.BaseAddress,
                                   (address_t)mem_info.BaseAddress +
                                       mem_info.RegionSize};
            m_regions.push_back(region);
        }
    }

private:
    unsigned long m_pid;
    HANDLE m_proc_handle;
};

typedef WindowsMemoryContext MemoryContext;
}

#endif
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthPass : public ScriptPass
{
	SynthPass() : ScriptPass("synth", "generic synthesis script") { }

	virtual void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth [options]\n");
		log("\n");
		log("This command runs the default synthesis script. This command does not operate\n");
		log("on partly selected designs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module (default='top')\n");
		log("\n");
		log("    -auto-top\n");
		log("        automatically determine the top of the design hierarchy\n");
		log("\n");
		log("    -flatten\n");
		log("        flatten the design before synthesis. this will pass '-auto-top' to\n");
		log("        'hierarchy' if no top module is specified.\n");
		log("\n");
		log("    -encfile <file>\n");
		log("        passed to 'fsm_recode' via 'fsm'\n");
		log("\n");
		log("    -nofsm\n");
		log("        do not run FSM optimization\n");
		log("\n");
		log("    -noabc\n");
		log("        do not run abc (as if yosys was compiled without ABC support)\n");
		log("\n");
		log("    -noalumacc\n");
		log("        do not run 'alumacc' pass. i.e. keep arithmetic operators in\n");
		log("        their direct form ($add, $sub, etc.).\n");
		log("\n");
		log("    -nordff\n");
		log("        passed to 'memory'. prohibits merging of FFs into memory read ports\n");
		log("\n");
		log("    -run <from_label>[:<to_label>]\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_module, fsm_opts, memory_opts;
	bool autotop, flatten, noalumacc, nofsm, noabc;

	virtual void clear_flags() YS_OVERRIDE
	{
		top_module.clear();
		fsm_opts.clear();
		memory_opts.clear();

		autotop = false;
		flatten = false;
		noalumacc = false;
		nofsm = false;
		noabc = false;
	}

	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_module = args[++argidx];
				continue;
			}
			if (args[argidx] == "-encfile" && argidx+1 < args.size()) {
				fsm_opts = " -encfile " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos) {
					run_from = args[++argidx];
					run_to = args[argidx];
				} else {
					run_from = args[++argidx].substr(0, pos);
					run_to = args[argidx].substr(pos+1);
				}
				continue;
			}
			if (args[argidx] == "-auto-top") {
				autotop = true;
				continue;
			}
			if (args[argidx] == "-flatten") {
				flatten = true;
				continue;
			}
			if (args[argidx] == "-nofsm") {
				nofsm = true;
				continue;
			}
			if (args[argidx] == "-noabc") {
				noabc = true;
				continue;
			}
			if (args[argidx] == "-noalumacc") {
				noalumacc = true;
				continue;
			}
			if (args[argidx] == "-nordff") {
				memory_opts += " -nordff";
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This comannd only operates on fully selected designs!\n");

		log_header(design, "Executing SYNTH pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	virtual void script() YS_OVERRIDE
	{
		if (check_label("begin"))
		{
			if (help_mode) {
				run("hierarchy -check [-top <top> | -auto-top]");
			} else {
				if (top_module.empty()) {
					if (flatten || autotop)
						run("hierarchy -check -auto-top");
					else
						run("hierarchy -check");
				} else
					run(stringf("hierarchy -check -top %s", top_module.c_str()));
			}
		}

		if (check_label("coarse"))
		{
			run("proc");
			if (help_mode || flatten)
				run("flatten", "(if -flatten)");
			run("opt_expr");
			run("opt_clean");
			run("check");
			run("opt");
			run("wreduce");
			if (!noalumacc)
				run("alumacc");
			run("share");
			run("opt");
			if (!nofsm)
				run("fsm" + fsm_opts);
			run("opt -fast");
			run("memory -nomap" + memory_opts);
			run("opt_clean");
		}

		if (check_label("fine"))
		{
			run("opt -fast -full");
			run("memory_map");
			run("opt -full");
			run("techmap");
			run("opt -fast");

			if (!noabc) {
		#ifdef YOSYS_ENABLE_ABC
				run("abc -fast");
				run("opt -fast");
		#endif
			}
		}

		if (check_label("check"))
		{
			run("hierarchy -check");
			run("stat");
			run("check");
		}
	}
} SynthPass;

PRIVATE_NAMESPACE_END
<commit_msg>Add "synth -noshare"<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct SynthPass : public ScriptPass
{
	SynthPass() : ScriptPass("synth", "generic synthesis script") { }

	virtual void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    synth [options]\n");
		log("\n");
		log("This command runs the default synthesis script. This command does not operate\n");
		log("on partly selected designs.\n");
		log("\n");
		log("    -top <module>\n");
		log("        use the specified module as top module (default='top')\n");
		log("\n");
		log("    -auto-top\n");
		log("        automatically determine the top of the design hierarchy\n");
		log("\n");
		log("    -flatten\n");
		log("        flatten the design before synthesis. this will pass '-auto-top' to\n");
		log("        'hierarchy' if no top module is specified.\n");
		log("\n");
		log("    -encfile <file>\n");
		log("        passed to 'fsm_recode' via 'fsm'\n");
		log("\n");
		log("    -nofsm\n");
		log("        do not run FSM optimization\n");
		log("\n");
		log("    -noabc\n");
		log("        do not run abc (as if yosys was compiled without ABC support)\n");
		log("\n");
		log("    -noalumacc\n");
		log("        do not run 'alumacc' pass. i.e. keep arithmetic operators in\n");
		log("        their direct form ($add, $sub, etc.).\n");
		log("\n");
		log("    -nordff\n");
		log("        passed to 'memory'. prohibits merging of FFs into memory read ports\n");
		log("\n");
		log("    -noshare\n");
		log("        do not run SAT-based resource sharing\n");
		log("\n");
		log("    -run <from_label>[:<to_label>]\n");
		log("        only run the commands between the labels (see below). an empty\n");
		log("        from label is synonymous to 'begin', and empty to label is\n");
		log("        synonymous to the end of the command list.\n");
		log("\n");
		log("\n");
		log("The following commands are executed by this synthesis command:\n");
		help_script();
		log("\n");
	}

	string top_module, fsm_opts, memory_opts;
	bool autotop, flatten, noalumacc, nofsm, noabc, noshare;

	virtual void clear_flags() YS_OVERRIDE
	{
		top_module.clear();
		fsm_opts.clear();
		memory_opts.clear();

		autotop = false;
		flatten = false;
		noalumacc = false;
		nofsm = false;
		noabc = false;
		noshare = false;
	}

	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		string run_from, run_to;
		clear_flags();

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-top" && argidx+1 < args.size()) {
				top_module = args[++argidx];
				continue;
			}
			if (args[argidx] == "-encfile" && argidx+1 < args.size()) {
				fsm_opts = " -encfile " + args[++argidx];
				continue;
			}
			if (args[argidx] == "-run" && argidx+1 < args.size()) {
				size_t pos = args[argidx+1].find(':');
				if (pos == std::string::npos) {
					run_from = args[++argidx];
					run_to = args[argidx];
				} else {
					run_from = args[++argidx].substr(0, pos);
					run_to = args[argidx].substr(pos+1);
				}
				continue;
			}
			if (args[argidx] == "-auto-top") {
				autotop = true;
				continue;
			}
			if (args[argidx] == "-flatten") {
				flatten = true;
				continue;
			}
			if (args[argidx] == "-nofsm") {
				nofsm = true;
				continue;
			}
			if (args[argidx] == "-noabc") {
				noabc = true;
				continue;
			}
			if (args[argidx] == "-noalumacc") {
				noalumacc = true;
				continue;
			}
			if (args[argidx] == "-nordff") {
				memory_opts += " -nordff";
				continue;
			}
			if (args[argidx] == "-noshare") {
				noshare = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		if (!design->full_selection())
			log_cmd_error("This comannd only operates on fully selected designs!\n");

		log_header(design, "Executing SYNTH pass.\n");
		log_push();

		run_script(design, run_from, run_to);

		log_pop();
	}

	virtual void script() YS_OVERRIDE
	{
		if (check_label("begin"))
		{
			if (help_mode) {
				run("hierarchy -check [-top <top> | -auto-top]");
			} else {
				if (top_module.empty()) {
					if (flatten || autotop)
						run("hierarchy -check -auto-top");
					else
						run("hierarchy -check");
				} else
					run(stringf("hierarchy -check -top %s", top_module.c_str()));
			}
		}

		if (check_label("coarse"))
		{
			run("proc");
			if (help_mode || flatten)
				run("flatten", "(if -flatten)");
			run("opt_expr");
			run("opt_clean");
			run("check");
			run("opt");
			run("wreduce");
			if (!noalumacc)
				run("alumacc");
			if (!noshare)
				run("share");
			run("opt");
			if (!nofsm)
				run("fsm" + fsm_opts);
			run("opt -fast");
			run("memory -nomap" + memory_opts);
			run("opt_clean");
		}

		if (check_label("fine"))
		{
			run("opt -fast -full");
			run("memory_map");
			run("opt -full");
			run("techmap");
			run("opt -fast");

			if (!noabc) {
		#ifdef YOSYS_ENABLE_ABC
				run("abc -fast");
				run("opt -fast");
		#endif
			}
		}

		if (check_label("check"))
		{
			run("hierarchy -check");
			run("stat");
			run("check");
		}
	}
} SynthPass;

PRIVATE_NAMESPACE_END
<|endoftext|>


<commit_before>#include "ros/ros.h"
#include <tf/tf.h>
#include <tf/transform_listener.h>
#include "sensor_msgs/PointCloud2.h"
#include "geometry_msgs/Vector3.h"
#include "geometry_msgs/Twist.h"

ros::Publisher move_pub;

void goToCentroid(const geometry_msgs::Vector3::ConstPtr&);

int main(int argc, char** argv)
{
    // /cmd_vel_mux/input/teleop
    ros::init(argc, argv, "move_to_cap_node");

    ros::NodeHandle nh;

    ros::Subscriber centroid_sub = nh.subscribe("detect_cap/centroid", 100, goToCentroid);
    move_pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 100);

    ros::Rate rate(10.0);
    while (nh.ok()){
	ros::spinOnce();
	rate.sleep();
   }
}

void goToCentroid(const geometry_msgs::Vector3::ConstPtr& centroid) {
    //Try to obtain
    tf::TransformListener listener;
    tf::StampedTransform transform;
    try{
	listener.lookupTransform("/base_link", "/camera_depth_optical_frame", ros::Time(0), transform);
    }
    catch (tf::TransformException ex){
	ROS_ERROR("%s",ex.what());
	ros::Duration(1.0).sleep();
	return;
    }

    tf::Vector3 centroid_vec(centroid->x, centroid->y, centroid->z);
    tf::Vector3 centroid_transformed = transform(centroid_vec);

    ROS_INFO("ORIGINAL CENTROID:    (%.5f, %.5f, %.5f)", centroid->x, centroid->y, centroid->z
    ROS_INFO("TRANSFORMED CENTROID: (%.5f, %.5f, %.5f)", centroid_transformed.getX(), centroid_transformed.getY(), centroid_transformed.getZ());
}
<commit_msg>WOw. WOW YOU REALLY DID THAT<commit_after>#include "ros/ros.h"
#include <tf/tf.h>
#include <tf/transform_listener.h>
#include "sensor_msgs/PointCloud2.h"
#include "geometry_msgs/Vector3.h"
#include "geometry_msgs/Twist.h"

ros::Publisher move_pub;

void goToCentroid(const geometry_msgs::Vector3::ConstPtr&);

int main(int argc, char** argv)
{
    // /cmd_vel_mux/input/teleop
    ros::init(argc, argv, "move_to_cap_node");

    ros::NodeHandle nh;

    ros::Subscriber centroid_sub = nh.subscribe("detect_cap/centroid", 100, goToCentroid);
    move_pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 100);

    ros::Rate rate(10.0);
    while (nh.ok()){
	ros::spinOnce();
	rate.sleep();
   }
}

void goToCentroid(const geometry_msgs::Vector3::ConstPtr& centroid) {
    //Try to obtain
    tf::TransformListener listener;
    tf::StampedTransform transform;
    try{
	listener.lookupTransform("/base_link", "/camera_depth_optical_frame", ros::Time(0), transform);
    }
    catch (tf::TransformException ex){
	ROS_ERROR("%s",ex.what());
	ros::Duration(1.0).sleep();
	return;
    }

    tf::Vector3 centroid_vec(centroid->x, centroid->y, centroid->z);
    tf::Vector3 centroid_transformed = transform(centroid_vec);

    ROS_INFO("ORIGINAL CENTROID:    (%.5f, %.5f, %.5f)", centroid->x, centroid->y, centroid->z);
    ROS_INFO("TRANSFORMED CENTROID: (%.5f, %.5f, %.5f)", centroid_transformed.getX(), centroid_transformed.getY(), centroid_transformed.getZ());
}
<|endoftext|>


<commit_before>/*
 * This file is part of ofono-qt
 *
 * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: Alexander Kanavin <alexander.kanavin@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <QtTest/QtTest>
#include <QtCore/QObject>
#include <QDBusObjectPath>

#include <ofonomessagemanager.h>
#include <ofonomessage.h>

#include <QtDebug>

class TestOfonoMessageManager : public QObject
{
    Q_OBJECT

private slots:

    void initTestCase()
    {
	m = new OfonoMessageManager(OfonoModem::ManualSelect, "/phonesim", this);
	QCOMPARE(m->modem()->isValid(), true);

	if (!m->modem()->powered()) {
  	    m->modem()->setPowered(true);
            QTest::qWait(5000);
        }
        if (!m->modem()->online()) {
  	    m->modem()->setOnline(true);
            QTest::qWait(5000);
        }
	QCOMPARE(m->isValid(), true);
    }

    void testOfonoMessageManager()
    {
        QSignalSpy sendMessage(m, SIGNAL(sendMessageComplete(bool, QDBusObjectPath)));
        QSignalSpy messageAdded(m, SIGNAL(messageAdded(QString)));
        QSignalSpy messageRemoved(m, SIGNAL(messageRemoved(QString)));
        QSignalSpy immediateMessage(m, SIGNAL(immediateMessage(QString, QVariantMap)));
        QSignalSpy incomingMessage(m, SIGNAL(incomingMessage(QString, QVariantMap)));

        QStringList messages = m->getMessages();
        QVERIFY(messages.count() == 0);

        m->sendMessage("99999", "success");

        QTest::qWait(1000);

        QCOMPARE(sendMessage.count(), 1);
        QVariantList params = sendMessage.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QDBusObjectPath objectPath = params.at(1).value<QDBusObjectPath>();
        QVERIFY(objectPath.path().length() > 0);
        qDebug() << objectPath.path();

        QCOMPARE(messageAdded.count(), 1);
        QCOMPARE(messageRemoved.count(), 1);

        QString messageId = messageAdded.takeFirst().at(0).toString();
        OfonoMessage* message = new OfonoMessage(messageId);
        QSignalSpy state(message, SIGNAL(stateChanged(const QString)));
        qDebug() << message->state();

        m->sendMessage("abc", "fail");

        QTest::qWait(1000);

        QCOMPARE(sendMessage.count(), 1);
        params = sendMessage.takeFirst();
        QCOMPARE(params.at(0).toBool(), false);
        objectPath = params.at(1).value<QDBusObjectPath>();
        QVERIFY(objectPath.path().length() == 0);
    }

    void testOfonoMessageManagerSca()
    {
        QSignalSpy scaComplete(m, SIGNAL(serviceCenterAddressComplete(bool, QString)));
        m->requestServiceCenterAddress();
        for (int i=0; i<30; i++) {
            if (scaComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(scaComplete.count(), 1);
	QVariantList params = scaComplete.takeFirst();
	QCOMPARE(params.at(0).toBool(), true);
	QString sca = params.at(1).toString();
        QVERIFY(sca.length() > 0);
        qDebug() << sca;

        QSignalSpy setScaFailed(m, SIGNAL(setServiceCenterAddressFailed()));
        QSignalSpy scaChanged(m, SIGNAL(serviceCenterAddressChanged(QString)));

        m->setServiceCenterAddress("+12345678");
        for (int i=0; i<30; i++) {
            if (setScaFailed.count() > 0 || scaChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(setScaFailed.count(), 0);
	QCOMPARE(scaChanged.count(), 1);
	QCOMPARE(scaChanged.takeFirst().at(0).toString(), QString("+12345678"));

        m->setServiceCenterAddress("");
        for (int i=0; i<30; i++) {
            if (setScaFailed.count() > 0 || scaChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(setScaFailed.count(), 1);
	setScaFailed.takeFirst();
	QCOMPARE(scaChanged.count(), 0);
	QCOMPARE(m->errorName(), QString("org.ofono.Error.InvalidFormat"));
	QCOMPARE(m->errorMessage(), QString("Argument format is not recognized"));

	m->setServiceCenterAddress(sca);
        for (int i=0; i<30; i++) {
            if (setScaFailed.count() > 0 || scaChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(setScaFailed.count(), 0);
	QCOMPARE(scaChanged.count(), 1);
	QCOMPARE(scaChanged.takeFirst().at(0).toString(), sca);
    }

    void testOfonoMessageManagerUseDeliveryReports()
    {
        QSignalSpy useDeliveryReportsComplete(m, SIGNAL(useDeliveryReportsComplete(bool, bool)));
        QSignalSpy setUseDeliveryReportsFailed(m, SIGNAL(setUseDeliveryReportsFailed()));
        QSignalSpy useDeliveryReportsChanged(m, SIGNAL(useDeliveryReportsChanged(bool)));

        m->requestUseDeliveryReports();
        for (int i=0; i<30; i++) {
            if (useDeliveryReportsComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }
        QCOMPARE(useDeliveryReportsComplete.count(), 1);
        QVariantList params = useDeliveryReportsComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QCOMPARE(params.at(1).toBool(), false);

        m->setUseDeliveryReports(true);
        for (int i=0; i<30; i++) {
            if (setUseDeliveryReportsFailed.count() > 0 || useDeliveryReportsChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
        QCOMPARE(setUseDeliveryReportsFailed.count(), 0);
        QCOMPARE(useDeliveryReportsChanged.count(), 1);
        QCOMPARE(useDeliveryReportsChanged.takeFirst().at(0).toBool(), true);

         m->setUseDeliveryReports(false);
         for (int i=0; i<30; i++) {
             if (setUseDeliveryReportsFailed.count() > 0 || useDeliveryReportsChanged.count() > 0)
                 break;
             QTest::qWait(1000);
         }
         QCOMPARE(setUseDeliveryReportsFailed.count(), 0);
         QCOMPARE(useDeliveryReportsChanged.count(), 1);
         QCOMPARE(useDeliveryReportsChanged.takeFirst().at(0).toBool(), false);
    }

    void testOfonoMessageManagerAlphabet()
    {
        QSignalSpy alphabetComplete(m, SIGNAL(alphabetComplete(bool, QString)));
        QSignalSpy setAlphabetFailed(m, SIGNAL(setAlphabetFailed()));
        QSignalSpy alphabetChanged(m, SIGNAL(alphabetChanged(QString)));

        m->requestAlphabet();
        for (int i=0; i<30; i++) {
            if (alphabetComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(alphabetComplete.count(), 1);
        QVariantList params = alphabetComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QString alphabet = params.at(1).toString();
        QVERIFY(alphabet.length() > 0);
        QCOMPARE(alphabet, QString("default"));
        qDebug() << alphabet;

        m->setAlphabet("spanish");
        for (int i=0; i<30; i++) {
            if (setAlphabetFailed.count() > 0 || alphabetChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setAlphabetFailed.count(), 0);
        QCOMPARE(alphabetChanged.count(), 1);
        QCOMPARE(alphabetChanged.takeFirst().at(0).toString(), QString("spanish"));

        m->setAlphabet(alphabet);
        for (int i=0; i<30; i++) {
            if (setAlphabetFailed.count() > 0 || alphabetChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setAlphabetFailed.count(), 0);
        QCOMPARE(alphabetChanged.count(), 1);
        QCOMPARE(alphabetChanged.takeFirst().at(0).toString(), alphabet);
    }

    void testOfonoMessageManagerBearer()
    {
        QSignalSpy bearerComplete(m, SIGNAL(bearerComplete(bool, QString)));
        QSignalSpy setBearerFailed(m, SIGNAL(setBearerFailed()));
        QSignalSpy bearerChanged(m, SIGNAL(bearerChanged(QString)));

        m->requestBearer();
        for (int i=0; i<30; i++) {
            if (bearerComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(bearerComplete.count(), 1);
        QVariantList params = bearerComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QString bearer = params.at(1).toString();
        QVERIFY(bearer.length() > 0);
        qDebug() << bearer;

        m->setBearer("ps-preferred");
        for (int i=0; i<30; i++) {
            if (setBearerFailed.count() > 0 || bearerChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        m->requestBearer();
        for (int i=0; i<30; i++) {
            if (bearerComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(bearerComplete.count(), 1);
        params = bearerComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        bearer = params.at(1).toString();
        QVERIFY(bearer.length() > 0);
        QCOMPARE(bearer, QString("ps-preferred"));

        m->setBearer("cs-preferred"); // change value
        for (int i=0; i<30; i++) {
            if (setBearerFailed.count() > 0 || bearerChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setBearerFailed.count(), 0);
        QCOMPARE(bearerChanged.count(), 1);
    }

    void cleanupTestCase()
    {

    }

private:
    OfonoMessageManager *m;
};

QTEST_MAIN(TestOfonoMessageManager)
#include "test_ofonomessagemanager.moc"
<commit_msg>Fix up the sms bearer testcase<commit_after>/*
 * This file is part of ofono-qt
 *
 * Copyright (C) 2010-2011 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: Alexander Kanavin <alexander.kanavin@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <QtTest/QtTest>
#include <QtCore/QObject>
#include <QDBusObjectPath>

#include <ofonomessagemanager.h>
#include <ofonomessage.h>

#include <QtDebug>

class TestOfonoMessageManager : public QObject
{
    Q_OBJECT

private slots:

    void initTestCase()
    {
	m = new OfonoMessageManager(OfonoModem::ManualSelect, "/phonesim", this);
	QCOMPARE(m->modem()->isValid(), true);

	if (!m->modem()->powered()) {
  	    m->modem()->setPowered(true);
            QTest::qWait(5000);
        }
        if (!m->modem()->online()) {
  	    m->modem()->setOnline(true);
            QTest::qWait(5000);
        }
	QCOMPARE(m->isValid(), true);
    }

    void testOfonoMessageManager()
    {
        QSignalSpy sendMessage(m, SIGNAL(sendMessageComplete(bool, QDBusObjectPath)));
        QSignalSpy messageAdded(m, SIGNAL(messageAdded(QString)));
        QSignalSpy messageRemoved(m, SIGNAL(messageRemoved(QString)));
        QSignalSpy immediateMessage(m, SIGNAL(immediateMessage(QString, QVariantMap)));
        QSignalSpy incomingMessage(m, SIGNAL(incomingMessage(QString, QVariantMap)));

        QStringList messages = m->getMessages();
        QVERIFY(messages.count() == 0);

        m->sendMessage("99999", "success");

        QTest::qWait(1000);

        QCOMPARE(sendMessage.count(), 1);
        QVariantList params = sendMessage.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QDBusObjectPath objectPath = params.at(1).value<QDBusObjectPath>();
        QVERIFY(objectPath.path().length() > 0);
        qDebug() << objectPath.path();

        QCOMPARE(messageAdded.count(), 1);
        QCOMPARE(messageRemoved.count(), 1);

        QString messageId = messageAdded.takeFirst().at(0).toString();
        OfonoMessage* message = new OfonoMessage(messageId);
        QSignalSpy state(message, SIGNAL(stateChanged(const QString)));
        qDebug() << message->state();

        m->sendMessage("abc", "fail");

        QTest::qWait(1000);

        QCOMPARE(sendMessage.count(), 1);
        params = sendMessage.takeFirst();
        QCOMPARE(params.at(0).toBool(), false);
        objectPath = params.at(1).value<QDBusObjectPath>();
        QVERIFY(objectPath.path().length() == 0);
    }

    void testOfonoMessageManagerSca()
    {
        QSignalSpy scaComplete(m, SIGNAL(serviceCenterAddressComplete(bool, QString)));
        m->requestServiceCenterAddress();
        for (int i=0; i<30; i++) {
            if (scaComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(scaComplete.count(), 1);
	QVariantList params = scaComplete.takeFirst();
	QCOMPARE(params.at(0).toBool(), true);
	QString sca = params.at(1).toString();
        QVERIFY(sca.length() > 0);
        qDebug() << sca;

        QSignalSpy setScaFailed(m, SIGNAL(setServiceCenterAddressFailed()));
        QSignalSpy scaChanged(m, SIGNAL(serviceCenterAddressChanged(QString)));

        m->setServiceCenterAddress("+12345678");
        for (int i=0; i<30; i++) {
            if (setScaFailed.count() > 0 || scaChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(setScaFailed.count(), 0);
	QCOMPARE(scaChanged.count(), 1);
	QCOMPARE(scaChanged.takeFirst().at(0).toString(), QString("+12345678"));

        m->setServiceCenterAddress("");
        for (int i=0; i<30; i++) {
            if (setScaFailed.count() > 0 || scaChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(setScaFailed.count(), 1);
	setScaFailed.takeFirst();
	QCOMPARE(scaChanged.count(), 0);
	QCOMPARE(m->errorName(), QString("org.ofono.Error.InvalidFormat"));
	QCOMPARE(m->errorMessage(), QString("Argument format is not recognized"));

	m->setServiceCenterAddress(sca);
        for (int i=0; i<30; i++) {
            if (setScaFailed.count() > 0 || scaChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
	QCOMPARE(setScaFailed.count(), 0);
	QCOMPARE(scaChanged.count(), 1);
	QCOMPARE(scaChanged.takeFirst().at(0).toString(), sca);
    }

    void testOfonoMessageManagerUseDeliveryReports()
    {
        QSignalSpy useDeliveryReportsComplete(m, SIGNAL(useDeliveryReportsComplete(bool, bool)));
        QSignalSpy setUseDeliveryReportsFailed(m, SIGNAL(setUseDeliveryReportsFailed()));
        QSignalSpy useDeliveryReportsChanged(m, SIGNAL(useDeliveryReportsChanged(bool)));

        m->requestUseDeliveryReports();
        for (int i=0; i<30; i++) {
            if (useDeliveryReportsComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }
        QCOMPARE(useDeliveryReportsComplete.count(), 1);
        QVariantList params = useDeliveryReportsComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QCOMPARE(params.at(1).toBool(), false);

        m->setUseDeliveryReports(true);
        for (int i=0; i<30; i++) {
            if (setUseDeliveryReportsFailed.count() > 0 || useDeliveryReportsChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }
        QCOMPARE(setUseDeliveryReportsFailed.count(), 0);
        QCOMPARE(useDeliveryReportsChanged.count(), 1);
        QCOMPARE(useDeliveryReportsChanged.takeFirst().at(0).toBool(), true);

         m->setUseDeliveryReports(false);
         for (int i=0; i<30; i++) {
             if (setUseDeliveryReportsFailed.count() > 0 || useDeliveryReportsChanged.count() > 0)
                 break;
             QTest::qWait(1000);
         }
         QCOMPARE(setUseDeliveryReportsFailed.count(), 0);
         QCOMPARE(useDeliveryReportsChanged.count(), 1);
         QCOMPARE(useDeliveryReportsChanged.takeFirst().at(0).toBool(), false);
    }

    void testOfonoMessageManagerAlphabet()
    {
        QSignalSpy alphabetComplete(m, SIGNAL(alphabetComplete(bool, QString)));
        QSignalSpy setAlphabetFailed(m, SIGNAL(setAlphabetFailed()));
        QSignalSpy alphabetChanged(m, SIGNAL(alphabetChanged(QString)));

        m->requestAlphabet();
        for (int i=0; i<30; i++) {
            if (alphabetComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(alphabetComplete.count(), 1);
        QVariantList params = alphabetComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QString alphabet = params.at(1).toString();
        QVERIFY(alphabet.length() > 0);
        QCOMPARE(alphabet, QString("default"));
        qDebug() << alphabet;

        m->setAlphabet("spanish");
        for (int i=0; i<30; i++) {
            if (setAlphabetFailed.count() > 0 || alphabetChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setAlphabetFailed.count(), 0);
        QCOMPARE(alphabetChanged.count(), 1);
        QCOMPARE(alphabetChanged.takeFirst().at(0).toString(), QString("spanish"));

        m->setAlphabet(alphabet);
        for (int i=0; i<30; i++) {
            if (setAlphabetFailed.count() > 0 || alphabetChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setAlphabetFailed.count(), 0);
        QCOMPARE(alphabetChanged.count(), 1);
        QCOMPARE(alphabetChanged.takeFirst().at(0).toString(), alphabet);
    }

    void testOfonoMessageManagerBearer()
    {
        QSignalSpy bearerComplete(m, SIGNAL(bearerComplete(bool, QString)));
        QSignalSpy setBearerFailed(m, SIGNAL(setBearerFailed()));
        QSignalSpy bearerChanged(m, SIGNAL(bearerChanged(QString)));

        m->requestBearer();
        for (int i=0; i<30; i++) {
            if (bearerComplete.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(bearerComplete.count(), 1);
        QVariantList params = bearerComplete.takeFirst();
        QCOMPARE(params.at(0).toBool(), true);
        QString bearer = params.at(1).toString();
        QVERIFY(bearer.length() > 0);
        QCOMPARE(bearer, QString("cs-preferred"));
        qDebug() << bearer;

        m->setBearer("ps-preferred");
        for (int i=0; i<30; i++) {
            if (setBearerFailed.count() > 0 || bearerChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setBearerFailed.count(), 0);
        QCOMPARE(bearerChanged.count(), 1);
        QCOMPARE(bearerChanged.takeFirst().at(0).toString(), QString("ps-preferred"));

        m->setBearer(bearer); // change value
        for (int i=0; i<30; i++) {
            if (setBearerFailed.count() > 0 || bearerChanged.count() > 0)
                break;
            QTest::qWait(1000);
        }

        QCOMPARE(setBearerFailed.count(), 0);
        QCOMPARE(bearerChanged.count(), 1);
        QCOMPARE(bearerChanged.takeFirst().at(0).toString(), bearer);
    }

    void cleanupTestCase()
    {

    }

private:
    OfonoMessageManager *m;
};

QTEST_MAIN(TestOfonoMessageManager)
#include "test_ofonomessagemanager.moc"
<|endoftext|>