<commit_before>// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef PARALLEL_LOOP_HPP
#define PARALLEL_LOOP_HPP

#include "CompletionEvent.hpp"
#include "ConditionVariable.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Tasking.hpp"
#include "Addressing.hpp"
#include "Communicator.hpp"
#include "GlobalCompletionEvent.hpp"
#include "Barrier.hpp"
#include "Collective.hpp"

/// Flag: loop_threshold
///
/// Iterations of `forall` loops *may* be run in parallel. A complete loop is decomposed into
/// separate (parallel) tasks by recursively splitting the number of iterations in half. This
/// parameter specifies the threshold where the decomposition ends, and the remaining iterations
/// are run serially in a single task. This global threshold is used by all parallel loops by
/// default, unless overridden statically as the `Threshold` template parameter in any of the
/// parallel loop functions.
DECLARE_int64(loop_threshold);

namespace Grappa {

  namespace impl {
    /// Declares that the loop threshold should be determined by the `loop_threshold` command-line flag.
    /// (default for loop decompositions)
    const int64_t USE_LOOP_THRESHOLD_FLAG = 0;

    // TODO: figure out way to put these different kinds of loop_decomposition
    // Need to template on the now-templated task spawn function.

    /// Does recursive loop decomposition, subdividing iterations by 2 until reaching
    /// the threshold and serializing the remaining iterations at each leaf.
    /// Note: this is an internal primitive for spawning tasks and does not synchronize on spawned tasks.
    ///
    /// This version spawns *private* tasks all the way down.
    template<int64_t Threshold = USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
    void loop_decomposition_private(int64_t start, int64_t iterations, F loop_body) {
      DVLOG(4) << "< " << start << " : " << iterations << ">";
      DVLOG(4) << "sizeof(loop_body) = " << sizeof(loop_body);

      if (iterations == 0) {
        return;
      } else if ((Threshold == USE_LOOP_THRESHOLD_FLAG && iterations <= FLAGS_loop_threshold)
                 || iterations <= Threshold) {
        loop_body(start, iterations);
        return;
      } else {
        // spawn right half
        int64_t rstart = start+(iterations+1)/2, riters = iterations/2;

        auto t = [rstart, riters, loop_body] {
          loop_decomposition_private<Threshold,F>(rstart, riters, loop_body);
        };
        privateTask(t);

        // left side here
        loop_decomposition_private<Threshold,F>(start, (iterations+1)/2, loop_body);
      }
    }

    /// Does recursive loop decomposition, subdividing iterations by 2 until reaching
    /// the threshold and serializing the remaining iterations at each leaf.
    /// Note: this is an internal primitive for spawning tasks and does not synchronize on spawned tasks.
    ///
    /// This version spawns *public* tasks all the way down.
    template<int64_t Threshold = USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
    void loop_decomposition_public(int64_t start, int64_t iterations, F loop_body) {
      DVLOG(4) << "< " << start << " : " << iterations << ">";

      if (iterations == 0) {
        return;
      } else if ((Threshold == USE_LOOP_THRESHOLD_FLAG && iterations <= FLAGS_loop_threshold)
                 || iterations <= Threshold) {
        loop_body(start, iterations);
        return;
      } else {
        // spawn right half
        int64_t rstart = start+(iterations+1)/2, riters = iterations/2;

        publicTask([rstart, riters, loop_body] {
          loop_decomposition_public<Threshold,F>(rstart, riters, loop_body);
        });

        // left side here
        loop_decomposition_public<Threshold,F>(start, (iterations+1)/2, loop_body);
      }
    }

    extern CompletionEvent local_ce;
    extern GlobalCompletionEvent local_gce;
  }

  /// Blocking parallel for loop, spawns only private tasks. Synchronizes itself with
  /// either a given static CompletionEvent (template param) or the local builtin one.
  ///
  /// Intended to be used for a loop of local tasks, often used as a primitive (along
  /// with `on_all_cores`) in global loops.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  ///
  /// @warning { All calls to forall_here will share the same CompletionEvent by default,
  ///            so only one should be called at once per core. }
  ///
  /// Also note: a single copy of `loop_body` is passed by reference to all of the child
  /// tasks, so be sure not to modify anything in the functor
  /// (TODO: figure out how to enforce this for all kinds of functors)
  template<CompletionEvent * CE = &impl::local_ce, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
  void forall_here(int64_t start, int64_t iters, F loop_body) {
    CE->enroll(iters);
    impl::loop_decomposition_private<Threshold>(start, iters,
      // passing loop_body by ref to avoid copying potentially large functors many times in decomposition
      // also keeps task args < 24 bytes, preventing it from being needing to be heap-allocated
      [&loop_body](int64_t s, int64_t n) {
        loop_body(s, n);
        CE->complete(n);
      });
    CE->wait();
  }

  /// Non-blocking version of `forall_here`, does recursive decomposition of loop locally,
  /// but synchronization is up to you.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  ///
  /// Note: this also cannot guarantee that `loop_body` will be in scope, so it passes it
  /// by copy to spawned tasks.
  template<int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
  void forall_here_async_public(int64_t start, int64_t iters, F loop_body) {
    impl::loop_decomposition_public<Threshold>(start, iters,
      [loop_body](int64_t start, int64_t iters) {
        loop_body(start, iters);
      });
  }

  /// Spread iterations evenly (block-distributed) across all the cores, using recursive
  /// decomposition with private tasks (so will not be load-balanced). Blocks until all
  /// iterations on all cores complete.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  template<CompletionEvent * CE = &impl::local_ce, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr)>
  void forall_global_private(int64_t start, int64_t iters, F loop_body) {
    on_all_cores([start,iters,loop_body]{
      range_t r = blockDist(start, start+iters, mycore(), cores());
      forall_here<CE,Threshold>(r.start, r.end-r.start, loop_body);
    });
  }

  /// Spread iterations evenly (block-distributed) across all the cores, using recursive
  /// decomposition with public tasks (that may moved to a different core for load-balancing).
  /// Blocks until all iterations on all cores complete.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  template<GlobalCompletionEvent * GCE = &impl::local_gce, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr)>
  void forall_global_public(int64_t start, int64_t iters, F loop_body) {
    // note: loop_decomp uses 2*8-byte values to specify range. We additionally track originating
    // core. So to avoid exceeding 3*8-byte task size, we save the loop body once on each core
    // (on `on_all_cores` task's stack) and embed the pointer to it in GCE, so each public task
    // can look it up when run, wherever it is.

    on_all_cores([start,iters,loop_body]{
      GCE->reset();
      GCE->set_shared_ptr(&loop_body); // need to initialize this on all nodes before any tasks start

      // may as well do this before the barrier too, but it shouldn't matter
      range_t r = blockDist(start, start+iters, mycore(), cores());
      GCE->enroll(r.end-r.start);

      barrier();

      Core origin = mycore();

      impl::loop_decomposition_public<Threshold>(r.start, r.end-r.start,
        [origin](int64_t s, int64_t n) {
          auto& loop_body = *GCE->get_shared_ptr<F>();
          loop_body(s,n);
          complete(make_global(GCE,origin),n);
        }
      );

      GCE->wait(); // keeps captured `loop_body` around for child tasks from any core to use
      GCE->set_shared_ptr(nullptr);
    });
  }

  /// Parallel loop over a global array. Spawned from a single core, fans out and runs
  /// tasks on elements that are local to each core.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  ///
  /// Takes an optional pointer to a global static `CompletionEvent` as a template
  /// parameter to allow for programmer-specified task joining (to potentially allow
  /// more than one in flight simultaneously, though this call is itself blocking.
  ///
  /// TODO: asynchronous version that supports many outstanding calls to `forall_localized` (to be used in BFS)
  template< typename T,
            CompletionEvent * CE = &impl::local_ce,
            int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG,
            typename F = decltype(nullptr) >
  void forall_localized(GlobalAddress<T> base, int64_t nelems, F loop_body) {
    on_all_cores([base, nelems, loop_body]{
      T* local_base = base.localize();
      T* local_end = (base+nelems).localize();

      forall_here<CE,Threshold>(0, local_end-local_base,
        // note: this functor will be passed by ref in `forall_here` so should be okay if >24B
        [loop_body, local_base, base](int64_t start, int64_t iters) {
          auto laddr = make_linear(local_base+start);

          for (int64_t i=start; i<start+iters; i++) {
            // TODO: check if this is inlined and if this loop is unrollable
            loop_body(laddr-base, local_base[i]);
          }
        }
      );
    });
  }

} // namespace Grappa

#endif
<commit_msg>For public task loop decomposition, enroll where spawned.<commit_after>// Copyright 2010-2012 University of Washington. All Rights Reserved.
// LICENSE_PLACEHOLDER
// This software was created with Government support under DE
// AC05-76RL01830 awarded by the United States Department of
// Energy. The Government has certain rights in the software.

#ifndef PARALLEL_LOOP_HPP
#define PARALLEL_LOOP_HPP

#include "CompletionEvent.hpp"
#include "ConditionVariable.hpp"
#include "Message.hpp"
#include "MessagePool.hpp"
#include "Tasking.hpp"
#include "Addressing.hpp"
#include "Communicator.hpp"
#include "GlobalCompletionEvent.hpp"
#include "Barrier.hpp"
#include "Collective.hpp"

/// Flag: loop_threshold
///
/// Iterations of `forall` loops *may* be run in parallel. A complete loop is decomposed into
/// separate (parallel) tasks by recursively splitting the number of iterations in half. This
/// parameter specifies the threshold where the decomposition ends, and the remaining iterations
/// are run serially in a single task. This global threshold is used by all parallel loops by
/// default, unless overridden statically as the `Threshold` template parameter in any of the
/// parallel loop functions.
DECLARE_int64(loop_threshold);

namespace Grappa {

  namespace impl {
    /// Declares that the loop threshold should be determined by the `loop_threshold` command-line flag.
    /// (default for loop decompositions)
    const int64_t USE_LOOP_THRESHOLD_FLAG = 0;

    // TODO: figure out way to put these different kinds of loop_decomposition
    // Need to template on the now-templated task spawn function.

    /// Does recursive loop decomposition, subdividing iterations by 2 until reaching
    /// the threshold and serializing the remaining iterations at each leaf.
    /// Note: this is an internal primitive for spawning tasks and does not synchronize on spawned tasks.
    ///
    /// This version spawns *private* tasks all the way down.
    template<int64_t Threshold = USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
    void loop_decomposition_private(int64_t start, int64_t iterations, F loop_body) {
      DVLOG(4) << "< " << start << " : " << iterations << ">";
      DVLOG(4) << "sizeof(loop_body) = " << sizeof(loop_body);

      if (iterations == 0) {
        return;
      } else if ((Threshold == USE_LOOP_THRESHOLD_FLAG && iterations <= FLAGS_loop_threshold)
                 || iterations <= Threshold) {
        loop_body(start, iterations);
        return;
      } else {
        // spawn right half
        int64_t rstart = start+(iterations+1)/2, riters = iterations/2;

        auto t = [rstart, riters, loop_body] {
          loop_decomposition_private<Threshold,F>(rstart, riters, loop_body);
        };
        privateTask(t);

        // left side here
        loop_decomposition_private<Threshold,F>(start, (iterations+1)/2, loop_body);
      }
    }

    /// Does recursive loop decomposition, subdividing iterations by 2 until reaching
    /// the threshold and serializing the remaining iterations at each leaf.
    /// Note: this is an internal primitive for spawning tasks and does not synchronize on spawned tasks.
    ///
    /// Optionally enrolls/completes spawned tasks with a GlobalCompletionEvent if specified.
    ///
    /// This version spawns *public* tasks all the way down.
    template<GlobalCompletionEvent * GCE = nullptr, int64_t Threshold = USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
    void loop_decomposition_public(int64_t start, int64_t iterations, F loop_body) {
      DVLOG(4) << "< " << start << " : " << iterations << ">";

      if (iterations == 0) {
        return;
      } else if ((Threshold == USE_LOOP_THRESHOLD_FLAG && iterations <= FLAGS_loop_threshold)
                 || iterations <= Threshold) {
        loop_body(start, iterations);
        return;
      } else {
        // spawn right half
        int64_t rstart = start+(iterations+1)/2, riters = iterations/2;
        Core origin = mycore();

        // pack these 3 into 14 bytes so we still have room for a full 8-byte word from user
        // (also need to count 2 bytes from lambda overhead)
        struct { long rstart:48, riters:48, origin:16; } packed = { rstart, riters, origin };

        if (GCE) GCE->enroll();
        publicTask([packed, loop_body] {
          loop_decomposition_public<GCE,Threshold,F>(packed.rstart, packed.riters, loop_body);
          if (GCE) complete(make_global(GCE,packed.origin));
        });

        // left side here
        loop_decomposition_public<GCE,Threshold,F>(start, (iterations+1)/2, loop_body);
      }
    }

    extern CompletionEvent local_ce;
    extern GlobalCompletionEvent local_gce;
  }

  /// Blocking parallel for loop, spawns only private tasks. Synchronizes itself with
  /// either a given static CompletionEvent (template param) or the local builtin one.
  ///
  /// Intended to be used for a loop of local tasks, often used as a primitive (along
  /// with `on_all_cores`) in global loops.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  ///
  /// @warning { All calls to forall_here will share the same CompletionEvent by default,
  ///            so only one should be called at once per core. }
  ///
  /// Also note: a single copy of `loop_body` is passed by reference to all of the child
  /// tasks, so be sure not to modify anything in the functor
  /// (TODO: figure out how to enforce this for all kinds of functors)
  template<CompletionEvent * CE = &impl::local_ce, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
  void forall_here(int64_t start, int64_t iters, F loop_body) {
    CE->enroll(iters);
    impl::loop_decomposition_private<Threshold>(start, iters,
      // passing loop_body by ref to avoid copying potentially large functors many times in decomposition
      // also keeps task args < 24 bytes, preventing it from being needing to be heap-allocated
      [&loop_body](int64_t s, int64_t n) {
        loop_body(s, n);
        CE->complete(n);
      });
    CE->wait();
  }

  /// Non-blocking version of `forall_here`, does recursive decomposition of loop locally,
  /// but synchronization is up to you.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  ///
  /// Note: this also cannot guarantee that `loop_body` will be in scope, so it passes it
  /// by copy to spawned tasks.
  template< GlobalCompletionEvent * GCE = nullptr, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr) >
  void forall_here_async_public(int64_t start, int64_t iters, F loop_body) {
    if (GCE) GCE->enroll();
    impl::loop_decomposition_public<GCE,Threshold>(start, iters,
      [loop_body](int64_t start, int64_t iters) {
        loop_body(start, iters);
      });
    if (GCE) GCE->complete();
  }

  /// Spread iterations evenly (block-distributed) across all the cores, using recursive
  /// decomposition with private tasks (so will not be load-balanced). Blocks until all
  /// iterations on all cores complete.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  template<CompletionEvent * CE = &impl::local_ce, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr)>
  void forall_global_private(int64_t start, int64_t iters, F loop_body) {
    on_all_cores([start,iters,loop_body]{
      range_t r = blockDist(start, start+iters, mycore(), cores());
      forall_here<CE,Threshold>(r.start, r.end-r.start, loop_body);
    });
  }

  /// Spread iterations evenly (block-distributed) across all the cores, using recursive
  /// decomposition with public tasks (that may moved to a different core for load-balancing).
  /// Blocks until all iterations on all cores complete.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  template<GlobalCompletionEvent * GCE = &impl::local_gce, int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG, typename F = decltype(nullptr)>
  void forall_global_public(int64_t start, int64_t iters, F loop_body) {
    // note: loop_decomp uses 2*8-byte values to specify range. We additionally track originating
    // core. So to avoid exceeding 3*8-byte task size, we save the loop body once on each core
    // (on `on_all_cores` task's stack) and embed the pointer to it in GCE, so each public task
    // can look it up when run, wherever it is.

    on_all_cores([start,iters,loop_body]{
      GCE->reset();
      GCE->set_shared_ptr(&loop_body); // need to initialize this on all nodes before any tasks start

      // may as well do this before the barrier too, but it shouldn't matter
      range_t r = blockDist(start, start+iters, mycore(), cores());

      barrier();

      Core origin = mycore();

      forall_here_async_public<GCE,Threshold>(r.start, r.end-r.start,
        [](int64_t s, int64_t n) {
          auto& loop_body = *GCE->get_shared_ptr<F>();
          loop_body(s,n);
        }
      );

      GCE->wait(); // keeps captured `loop_body` around for child tasks from any core to use
      GCE->set_shared_ptr(nullptr);
    });
  }

  /// Parallel loop over a global array. Spawned from a single core, fans out and runs
  /// tasks on elements that are local to each core.
  ///
  /// Subject to "may-parallelism", @see `loop_threshold`.
  ///
  /// Takes an optional pointer to a global static `CompletionEvent` as a template
  /// parameter to allow for programmer-specified task joining (to potentially allow
  /// more than one in flight simultaneously, though this call is itself blocking.
  ///
  /// TODO: asynchronous version that supports many outstanding calls to `forall_localized` (to be used in BFS)
  template< typename T,
            CompletionEvent * CE = &impl::local_ce,
            int64_t Threshold = impl::USE_LOOP_THRESHOLD_FLAG,
            typename F = decltype(nullptr) >
  void forall_localized(GlobalAddress<T> base, int64_t nelems, F loop_body) {
    on_all_cores([base, nelems, loop_body]{
      T* local_base = base.localize();
      T* local_end = (base+nelems).localize();

      forall_here<CE,Threshold>(0, local_end-local_base,
        // note: this functor will be passed by ref in `forall_here` so should be okay if >24B
        [loop_body, local_base, base](int64_t start, int64_t iters) {
          auto laddr = make_linear(local_base+start);

          for (int64_t i=start; i<start+iters; i++) {
            // TODO: check if this is inlined and if this loop is unrollable
            loop_body(laddr-base, local_base[i]);
          }
        }
      );
    });
  }

} // namespace Grappa

#endif
<|endoftext|>


<commit_before>#include "Analyze.h"
#include <iostream>

using namespace std;

int Analyze::analyzeString(vector<string>* givenString, int* exitFlag){
  vector<string> commandVector;
  int result = 0;
  int finalResult = 0;
  int skipAndFlag = 0;
  int skipOrFlag = 0;
  unsigned int outer = 0;
  unsigned int paranthesesCount = 0;
  unsigned int insideQuotes = 0;
  unsigned int finishedParantheses = 0;

  for (unsigned int i = 0;i < givenString->size();i++){

    if(skipAndFlag){    //MODIFY THESE SKIP LOOPS SO THEY WILL SKIP OVER && OR || OR ; IF ITS IN ()
      skipAndFlag = 0;
      insideQuotes = 0;
      result = 1;
      while(((givenString->at(i)!="||"&&givenString->at(i)!=";")||insideQuotes)&& i < givenString->size()-1){
        if(givenString->at(i)=="("){
          insideQuotes = 1;
        }

        if(givenString->at(i)==")"){
          insideQuotes = 0;
        }
        i++;
      }

    }else if(skipOrFlag){
      skipOrFlag = 0;
      insideQuotes = 0;
      result = 0;
      while(((givenString->at(i)!="&&"&&givenString->at(i)!=";")||insideQuotes)&&i < givenString->size()-1){
        if(givenString->at(i)=="("){
          insideQuotes = 1;
        }

        if(givenString->at(i)==")"){
          insideQuotes = 0;
        }
        i++;
      }

    }else if ( (givenString->at(i)!="&&")&&(givenString->at(i)!="||")&&(givenString->at(i)!=";") ) {
      outer = i;
      if(givenString->at(i) == "("){
        if(commandVector.size()!= 0){
          cout << "Error: Unexpected token ";
          for (unsigned int unexp = 0; unexp < commandVector.size(); unexp++){
            cout << commandVector[unexp] << " ";
          }
          cout << endl;

          return 4;
        }
        paranthesesCount = 0;
        for (unsigned int k=i+1; k < givenString->size(); k++){
          if( givenString->at(k)== ")" ){
            if(paranthesesCount == 0){
              outer = k;
              k = givenString->size();
            }else{
              paranthesesCount--;
            }
          }else if( givenString->at(k) == "("){
            paranthesesCount++;
          }
        }

        if (outer != i){
          //create and call subvector then return its result.
          for(unsigned int outcnt = i+1; outcnt < outer; outcnt++){  //for everything between i and outer.
            commandVector.push_back(givenString->at(outcnt));
          }
          //Output sub vector.
          /*cout << "Created SubVector: ";
          for (unsigned int tempcnt = 0; tempcnt < commandVector.size(); tempcnt++){
            cout << commandVector[tempcnt] << " ";
          }
          cout << endl;*/

          finishedParantheses = 1;
          i = outer;
          result = analyzeString(&commandVector, exitFlag);

          commandVector.clear();

          if (result == 2||result == 4){
            return result;
          }

        }

      }else{
        if(finishedParantheses){
          cout << "Error: Unexpected token ";
          while((givenString->at(i)!="&&")&&(givenString->at(i)!="||")&&(givenString->at(i)!=";")&&(i < givenString->size() - 1)){
            commandVector.push_back(givenString->at(i));
            i++;
          }
          if((givenString->at(i) != "&&")&&(givenString->at(i) != "||")&&(givenString->at(i)!=";")&&(i < givenString->size())){
            commandVector.push_back(givenString->at(i));
          }
          for (unsigned int unexp = 0; unexp < commandVector.size(); unexp++){
            cout << commandVector[unexp] << " ";
          }
          cout << endl;

          return 4;

        }else{
          commandVector.push_back(givenString->at(i));
        }
      }

    } else {
	  //execute the command and reset the commandVector, take the value from and decide what to do next based
	  //on the connector

      if (commandVector[0] == "exit"){
        *exitFlag = 1;
        break;
      }
      if(commandVector.size() != 0){
        //cout << "executed command: " << commandVector[0] << endl;
        result = commander.callCommand(commandVector);}

      if(result == 2){
        cout << "Error: Invalid Call to Command " << commandVector[0] << "." << endl;
        return result;
      }

      //cout << "result flag before && and || check: " << result << "." << endl;

      if (givenString->at(i)=="&&"){
        finishedParantheses = 0;
        if (result!=0){
          skipAndFlag = 1;
          finalResult = 1;
        }else{
          finalResult = 0;
        }
      }

      if (givenString->at(i)=="||"){
        finishedParantheses = 0;
        if (result==0){
          skipOrFlag = 1;
          finalResult = 0;
        }else{
          finalResult = 1;
        }
      }

        commandVector.clear();
   }

  }

  if(commandVector.size()>0){
    if (commandVector[0] == "exit"){
        *exitFlag = 1;
    }

    //if (commandVector[0] == "test"){}

    if(commandVector[0] != "exit"){
      result = commander.callCommand(commandVector);
    }

    if(result == 2){
      cout << "Error: Invalid Call to Command " << commandVector[0] << "." << endl;
      return result;
    }
  }
  //cout << "Final Result: " << finalResult << "." << endl;
  return finalResult;

}
<commit_msg>Added test command to program<commit_after>#include "Analyze.h"
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int Analyze::analyzeString(vector<string>* givenString, int* exitFlag){
  vector<string> commandVector;
  int result = 0;
  int finalResult = 0;
  int skipAndFlag = 0;
  int skipOrFlag = 0;
  unsigned int outer = 0;
  unsigned int paranthesesCount = 0;
  unsigned int insideQuotes = 0;
  unsigned int finishedParantheses = 0;

  for (unsigned int i = 0;i < givenString->size();i++){

    if(skipAndFlag){    //MODIFY THESE SKIP LOOPS SO THEY WILL SKIP OVER && OR || OR ; IF ITS IN ()
      skipAndFlag = 0;
      insideQuotes = 0;
      result = 1;
      while(((givenString->at(i)!="||"&&givenString->at(i)!=";")||insideQuotes)&& i < givenString->size()-1){
        if(givenString->at(i)=="("){
          insideQuotes = 1;
        }

        if(givenString->at(i)==")"){
          insideQuotes = 0;
        }
        i++;
      }

    }else if(skipOrFlag){
      skipOrFlag = 0;
      insideQuotes = 0;
      result = 0;
      while(((givenString->at(i)!="&&"&&givenString->at(i)!=";")||insideQuotes)&&i < givenString->size()-1){
        if(givenString->at(i)=="("){
          insideQuotes = 1;
        }

        if(givenString->at(i)==")"){
          insideQuotes = 0;
        }
        i++;
      }

    }else if ( (givenString->at(i)!="&&")&&(givenString->at(i)!="||")&&(givenString->at(i)!=";") ) {
      outer = i;
      if(givenString->at(i) == "("){
        if(commandVector.size()!= 0){
          cout << "Error: Unexpected token ";
          for (unsigned int unexp = 0; unexp < commandVector.size(); unexp++){
            cout << commandVector[unexp] << " ";
          }
          cout << endl;

          return 4;
        }
        paranthesesCount = 0;
        for (unsigned int k=i+1; k < givenString->size(); k++){
          if( givenString->at(k)== ")" ){
            if(paranthesesCount == 0){
              outer = k;
              k = givenString->size();
            }else{
              paranthesesCount--;
            }
          }else if( givenString->at(k) == "("){
            paranthesesCount++;
          }
        }

        if (outer != i){
          //create and call subvector then return its result.
          for(unsigned int outcnt = i+1; outcnt < outer; outcnt++){  //for everything between i and outer.
            commandVector.push_back(givenString->at(outcnt));
          }
          //Output sub vector.
          /*cout << "Created SubVector: ";
          for (unsigned int tempcnt = 0; tempcnt < commandVector.size(); tempcnt++){
            cout << commandVector[tempcnt] << " ";
          }
          cout << endl;*/

          finishedParantheses = 1;
          i = outer;
          result = analyzeString(&commandVector, exitFlag);

          commandVector.clear();

          if (result == 2||result == 4){
            return result;
          }

        }

      }else{
        if(finishedParantheses){
          cout << "Error: Unexpected token ";
          while((givenString->at(i)!="&&")&&(givenString->at(i)!="||")&&(givenString->at(i)!=";")&&(i < givenString->size() - 1)){
            commandVector.push_back(givenString->at(i));
            i++;
          }
          if((givenString->at(i) != "&&")&&(givenString->at(i) != "||")&&(givenString->at(i)!=";")&&(i < givenString->size())){
            commandVector.push_back(givenString->at(i));
          }
          for (unsigned int unexp = 0; unexp < commandVector.size(); unexp++){
            cout << commandVector[unexp] << " ";
          }
          cout << endl;

          return 4;

        }else{
          commandVector.push_back(givenString->at(i));
        }
      }

    } else {
	  //execute the command and reset the commandVector, take the value from and decide what to do next based
	  //on the connector

      if ( commandVector[0] == "exit" ) {
        *exitFlag = 1;
        break;
      }

      if ( commandVector[0] == "test" ) {
        if ( commandVector.size() != 3 ) {
          cout << "Error: Incorrect number of arguments for test command." << endl;
          break;
        }else{
          struct stat statObj;
          int statResult = stat(commandVector[2].c_str(), &statObj);
          if ( commandVector[1] == "-e" ) {
            if(statResult){
              cout << "(False)" << endl;
              result = 1;
            }else if(statResult == -1){
              perror("stat error with -e flag.");
              exit(EXIT_FAILURE);
            }else{
              cout << "(True)" << endl;
              result = 0;
            }
          } else if ( commandVector[1] == "-f" ) {
            if(statResult){
              cout << "(False)" << endl;
              result = 1;
            }else if(statResult == -1){
              perror("stat error with -f flag.");
              exit(EXIT_FAILURE);
            }else{
              if(S_ISREG(statObj.st_mode)){
                cout << "(True)" << endl;
                result = 0;
              }else{
                cout << "(False)" << endl;
                result = 1;
              }
            }
          } else if ( commandVector[1] == "-d" ) {
            if(statResult){
              cout << "(False)" << endl;
              result = 1;
            }else if(statResult == -1){
              perror("stat error with -d flag.");
              exit(EXIT_FAILURE);
            }else{
              if(S_ISDIR(statObj.st_mode)){
                cout << "(True)" << endl;
                result = 0;
              }else{
                cout << "(False)" << endl;
                result = 1;
              }
            }
          } else {
            cout << "Error: unreadable flags for test command." << endl;
            break;
          }
        }
        commandVector.clear();
      }

      if(commandVector.size() != 0){
        //cout << "executed command: " << commandVector[0] << endl;
        result = commander.callCommand(commandVector);}

      if(result == 2){
        cout << "Error: Invalid Call to Command " << commandVector[0] << "." << endl;
        return result;
      }

      //cout << "result flag before && and || check: " << result << "." << endl;

      if (givenString->at(i)=="&&"){
        finishedParantheses = 0;
        if (result!=0){
          skipAndFlag = 1;
          finalResult = 1;
        }else{
          finalResult = 0;
        }
      }

      if (givenString->at(i)=="||"){
        finishedParantheses = 0;
        if (result==0){
          skipOrFlag = 1;
          finalResult = 0;
        }else{
          finalResult = 1;
        }
      }

        commandVector.clear();
   }

  }

  if(commandVector.size()>0){
    if (commandVector[0] == "exit"){
        *exitFlag = 1;
    }

    if (commandVector[0] == "test"){
       if ( commandVector.size() != 3 ) {
          cout << "Error: Incorrect number of arguments for test command." << endl;
        }else{
          struct stat statObj;
          int statResult = stat(commandVector[2].c_str(), &statObj);
          if ( commandVector[1] == "-e" ) {
            if(statResult){
              cout << "(False)" << endl;
              result = 1;
            }else if(statResult == -1){
              perror("stat error with -e flag.");
              exit(EXIT_FAILURE);
            }else{
              cout << "(True)" << endl;
              result = 0;
            }
          } else if ( commandVector[1] == "-f" ) {
            if(statResult){
              cout << "(False)" << endl;
              result = 1;
            }else if(statResult == -1){
              perror("stat error with -f flag.");
              exit(EXIT_FAILURE);
            }else{
              if(S_ISREG(statObj.st_mode)){
                cout << "(True)" << endl;
                result = 0;
              }else{
                cout << "(False)" << endl;
                result = 1;
              }
            }
          } else if ( commandVector[1] == "-d" ) {
            if(statResult){
              cout << "(False)" << endl;
              result = 1;
            }else if(statResult == -1){
              perror("stat error with -d flag.");
              exit(EXIT_FAILURE);
            }else{
              if(S_ISDIR(statObj.st_mode)){
                cout << "(True)" << endl;
                result = 0;
              }else{
                cout << "(False)" << endl;
                result = 1;
              }
            }
          } else {
            cout << "Error: unreadable flags for test command." << endl;
          }
        }

    }

    if(commandVector[0] != "exit"&&commandVector[0] != "test"){
      result = commander.callCommand(commandVector);
    }

    if(result == 2){
      cout << "Error: Invalid Call to Command " << commandVector[0] << "." << endl;
      return result;
    }
  }
  //cout << "Final Result: " << finalResult << "." << endl;
  return finalResult;

}
<|endoftext|>


<commit_before>#include "arbiter.h"

#include <iostream>

void say_hi() {
  std::cout << "Hello world" << std::endl;
}
<commit_msg>Fix header include<commit_after>#include "Arbiter.h"

#include <iostream>

void say_hi() {
  std::cout << "Hello world" << std::endl;
}
<|endoftext|>


<commit_before>#include "ble.h"

//BLE::BLE(Stream *sp) : BC127(sp)
//{
//
//}

int BLE::begin(void)
{
	//force into command mode (not needed if already in command mode...but historical Tympan units were preloaded to Data mode instead)
	//myTympan.forceBTtoDataMode(false);
	_serialPort->print("$");  delay(400);	_serialPort->print("$$$");

	//now do the usual setup stuff
	int ret_val;
	ret_val = restore();
	if (ret_val != BC127::SUCCESS) {
		Serial.print(F("BLE: begin: restore() returned error "));
		Serial.println(ret_val);
		//return ret_val;
	}
    ret_val = writeConfig();
	if (ret_val != BC127::SUCCESS) {
		Serial.print(F("BLE: begin: writeConfig() returned error "));
		Serial.println(ret_val);
		//return ret_val;
	}
    ret_val = reset();
	if (ret_val != BC127::SUCCESS) {
		Serial.print(F("BLE: begin: reset() returned error "));
		Serial.println(ret_val);
		//return ret_val;
	}

	return ret_val;
}

size_t BLE::sendByte(char c)
{
	//Serial.print("BLE: sendBytle: "); Serial.println(c);

    String s = String("").concat(c);
    if (send(s))
        return 1;

    return 0;
}

size_t BLE::sendString(const String &s)
{
	//Serial.print("BLE: sendString: "); Serial.println(s);

    if (send(s))
        return s.length();

    return 0;
}

size_t BLE::sendMessage(const String &s)
{
	const size_t len = s.length();
	const int payloadLen = 19;
	size_t sentBytes = 0;

    String header;
    header = "\xab\xad\xc0\xde"; // ABADCODE, message preamble
    header.concat('\xff');       // message type

    // message length
    if (len >= 0x4000) {
        Serial.println("BLE: Message is too long!!! Aborting.");
        return 0;
    }
    int lenBytes = (len<<1) | 0x8001; //the 0x8001 is avoid the first message having the 2nd-to-last byte being NULL
    header.concat((char)highByte(lenBytes));
    header.concat((char )lowByte(lenBytes));

	//check to ensure that there isn't a NULL or a CR in this header
	bool sendExtraByte = false;
	if ((header[6] == '\r') || (header[6] == '\0')) {
		sendExtraByte = true;
		lenBytes = ( (len+1) << 1) | 0x8001;
		header[5] = (char)highByte(lenBytes);
		header[6] = (char)lowByte(lenBytes);
	}

    //Serial.println("BLE: sendMessage: Header (" + String(header.length()) + " bytes): '" + header + "'");
    //Serial.println("BLE: Message: '" + s + "'");

	//send the packet with the header information
    char buf[16];
    sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X", header.charAt(0), header.charAt(1), header.charAt(2), header.charAt(3), header.charAt(4), header.charAt(5), header.charAt(6));
    //Serial.println(buf);
    int a = sendString(header);
    if (a != 7) Serial.println("BLE: sendMessage: Error in sending header... Sent: '" + String(a) + "'");

    //int numPackets = ceil(s.length() / (float)payloadLen);
    int numPackets = ceil(len / (float)payloadLen);

/* 	int ind_start = 0, ind_end=0, ind_out;
	char bu[1+payloadLen+1];  //temporary buffer
	int packet_counter = 0;

	String foo_s;
	while (ind_end < len) {
		//compute indices into our source string
		ind_start = ind_end;
		ind_end = ind_start + payloadLen;
		ind_end = min(ind_end,len);

		//construct this payload
		ind_out = 0;
		bu[ind_out++] = (char)(0xF0 | lowByte(packet_counter++));  //first byte
		while (ind_start < ind_end) {
			bu[ind_out++]=c_str[ind_start++];  //payload
		}
		bu[ind_out] = '\0';  //trailing byte...null terminated c-style string

		//send the payload
		//sentBytes += (sendString(String(bu))-1);
		foo_s = String(bu);
		size_t foo = sendString(foo_s);
		if (foo > 0) sentBytes += (foo-1);
		//Serial.println("BLE: sendMessage: packet " + String(packet_counter) + ", " + String(ind_start) + ", " + String(ind_end) + ", sentBytes = " + String(foo) + ", " + foo_s);
		//delay(10);
		delay(5); //20 characters characcters at 9600 baud is about 2.1 msec...make at least 10% longer (if not 2x longer)
	} */

	for (int i = 0; i < numPackets; i++)
    {
        String bu = (char)(0xF0 | lowByte(i));
        bu.concat(s.substring(i * payloadLen, (i * payloadLen) + payloadLen));
        sentBytes += (sendString(bu)-1);
        delay(4); //20 characters characcters at 9600 baud is about 2.1 msec...make at least 10% longer (if not 2x longer)
    }

	if (sendExtraByte) sendString(String(" "));

	//Serial.print("BLE: sendMessage: sentBytes = "); Serial.println((unsigned int)sentBytes);
    if (len == sentBytes) return sentBytes;

    return 0;
}

size_t BLE::recvMessage(String *s)
{
    int msgSize = 0;
    int bytesRecvd = 0;

    while (1)
    {
        if (available() > 0)
        {
            if (recvBLE(s) > 0)
            {
                if (s->startsWith("\xab\xad\xc0\xde\xff"))
                {
                    msgSize = word(s->charAt(5), s->charAt(6));
                    Serial.println("BLE: recvMessage: Length of message: '" + String(msgSize) + "'");

                    char buf[16];

                    sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X", s->charAt(0), s->charAt(1), s->charAt(2), s->charAt(3), s->charAt(4), s->charAt(5), s->charAt(6));

                    Serial.println(buf);

                    int numPackets = ceil(msgSize / 20.0);

                    for (int i = 0; i < numPackets; i++)
                    {
                        bytesRecvd += recvBLE(s);
                    }

                    if (bytesRecvd == msgSize)
                    {
                        return bytesRecvd;
                    }
                }
                continue;
            }

            break;
        }
    }

    return 0;
}

/* size_t BLE::maintainBLE(void) {
	if isConnected() {
		//do nothing
	} else {
		//check to see if advertising

		//
	}
} */

size_t BLE::recvBLE(String *s)
{
    String tmp = String("");

    // get our start time
    unsigned long startTime = millis();

    // as long as we have time
    while ((startTime + _timeout) > millis())
    {
        if (recv(&tmp) > 0)
        {
            if (tmp.startsWith("RECV BLE "))
            {
                s->concat(tmp.substring(9).trim());
                return tmp.substring(9).length();
            }

            tmp = "";
        }
    }

    return 0;
}

bool BLE::isConnected(bool printResponse)
{
    if (status() > 0)
    {
		String s = getCmdResponse();
		if (printResponse) {
			Serial.println("BLE: isConnected() response: ");
			Serial.print(s);
		}
        //return s.startsWith("STATE CONNECTED"); //original
		if (s.indexOf("CONNECTED") == -1) { //if it finds -1, then it wasn't found
			return false;
		} else {
			return true;
		}
    }

    return false;
}

bool BLE::waitConnect(int time)
{
    // some output has multiple lines
    String line = String("");

    // decide how long we're willing to wait
    int timeout = time > 0 ? time : _timeout;

    // get our start time
    unsigned long startTime = millis();

    // as long as we have time
    while ((startTime + timeout) > millis())
    {
        if (_serialPort->available() > 0)
        {
            line.concat((char)_serialPort->read());
        }

        if (line.endsWith(EOL))
        {
            if (line.startsWith("OPEN_OK BLE"))
            {
                return true;
            }

            // move on to next line
            line = "";
        }
    }

    return false;
}<commit_msg>BLE: adding a warning message when padding to avoid the length problem<commit_after>#include "ble.h"

//BLE::BLE(Stream *sp) : BC127(sp)
//{
//
//}

int BLE::begin(void)
{
	//force into command mode (not needed if already in command mode...but historical Tympan units were preloaded to Data mode instead)
	//myTympan.forceBTtoDataMode(false);
	_serialPort->print("$");  delay(400);	_serialPort->print("$$$");

	//now do the usual setup stuff
	int ret_val;
	ret_val = restore();
	if (ret_val != BC127::SUCCESS) {
		Serial.print(F("BLE: begin: restore() returned error "));
		Serial.println(ret_val);
		//return ret_val;
	}
    ret_val = writeConfig();
	if (ret_val != BC127::SUCCESS) {
		Serial.print(F("BLE: begin: writeConfig() returned error "));
		Serial.println(ret_val);
		//return ret_val;
	}
    ret_val = reset();
	if (ret_val != BC127::SUCCESS) {
		Serial.print(F("BLE: begin: reset() returned error "));
		Serial.println(ret_val);
		//return ret_val;
	}

	return ret_val;
}

size_t BLE::sendByte(char c)
{
	//Serial.print("BLE: sendBytle: "); Serial.println(c);

    String s = String("").concat(c);
    if (send(s))
        return 1;

    return 0;
}

size_t BLE::sendString(const String &s)
{
	//Serial.print("BLE: sendString: "); Serial.println(s);

    if (send(s))
        return s.length();

    return 0;
}

size_t BLE::sendMessage(const String &s)
{
	const size_t len = s.length();
	const int payloadLen = 19;
	size_t sentBytes = 0;

    String header;
    header = "\xab\xad\xc0\xde"; // ABADCODE, message preamble
    header.concat('\xff');       // message type

    // message length
    if (len >= 0x4000) {
        Serial.println("BLE: Message is too long!!! Aborting.");
        return 0;
    }
    int lenBytes = (len<<1) | 0x8001; //the 0x8001 is avoid the first message having the 2nd-to-last byte being NULL
    header.concat((char)highByte(lenBytes));
    header.concat((char )lowByte(lenBytes));

	//check to ensure that there isn't a NULL or a CR in this header
	bool sendExtraByte = false;
	if ((header[6] == '\r') || (header[6] == '\0')) {
		Serial.println("BLE: sendMessage: ***WARNING*** message is being padded with a space to avoid its length being an unallowed value.");
		sendExtraByte = true;
		lenBytes = ( (len+1) << 1) | 0x8001;
		header[5] = (char)highByte(lenBytes);
		header[6] = (char)lowByte(lenBytes);
	}

    //Serial.println("BLE: sendMessage: Header (" + String(header.length()) + " bytes): '" + header + "'");
    //Serial.println("BLE: Message: '" + s + "'");

	//send the packet with the header information
    char buf[16];
    sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X", header.charAt(0), header.charAt(1), header.charAt(2), header.charAt(3), header.charAt(4), header.charAt(5), header.charAt(6));
    //Serial.println(buf);
    int a = sendString(header);
    if (a != 7) Serial.println("BLE: sendMessage: Error in sending header... Sent: '" + String(a) + "'");

    //int numPackets = ceil(s.length() / (float)payloadLen);
    int numPackets = ceil(len / (float)payloadLen);

/* 	int ind_start = 0, ind_end=0, ind_out;
	char bu[1+payloadLen+1];  //temporary buffer
	int packet_counter = 0;

	String foo_s;
	while (ind_end < len) {
		//compute indices into our source string
		ind_start = ind_end;
		ind_end = ind_start + payloadLen;
		ind_end = min(ind_end,len);

		//construct this payload
		ind_out = 0;
		bu[ind_out++] = (char)(0xF0 | lowByte(packet_counter++));  //first byte
		while (ind_start < ind_end) {
			bu[ind_out++]=c_str[ind_start++];  //payload
		}
		bu[ind_out] = '\0';  //trailing byte...null terminated c-style string

		//send the payload
		//sentBytes += (sendString(String(bu))-1);
		foo_s = String(bu);
		size_t foo = sendString(foo_s);
		if (foo > 0) sentBytes += (foo-1);
		//Serial.println("BLE: sendMessage: packet " + String(packet_counter) + ", " + String(ind_start) + ", " + String(ind_end) + ", sentBytes = " + String(foo) + ", " + foo_s);
		//delay(10);
		delay(5); //20 characters characcters at 9600 baud is about 2.1 msec...make at least 10% longer (if not 2x longer)
	} */

	for (int i = 0; i < numPackets; i++)
    {
        String bu = (char)(0xF0 | lowByte(i));
        bu.concat(s.substring(i * payloadLen, (i * payloadLen) + payloadLen));
        sentBytes += (sendString(bu)-1);
        delay(4); //20 characters characcters at 9600 baud is about 2.1 msec...make at least 10% longer (if not 2x longer)
    }

	if (sendExtraByte) sendString(String(" "));

	//Serial.print("BLE: sendMessage: sentBytes = "); Serial.println((unsigned int)sentBytes);
    if (len == sentBytes) return sentBytes;

    return 0;
}

size_t BLE::recvMessage(String *s)
{
    int msgSize = 0;
    int bytesRecvd = 0;

    while (1)
    {
        if (available() > 0)
        {
            if (recvBLE(s) > 0)
            {
                if (s->startsWith("\xab\xad\xc0\xde\xff"))
                {
                    msgSize = word(s->charAt(5), s->charAt(6));
                    Serial.println("BLE: recvMessage: Length of message: '" + String(msgSize) + "'");

                    char buf[16];

                    sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X", s->charAt(0), s->charAt(1), s->charAt(2), s->charAt(3), s->charAt(4), s->charAt(5), s->charAt(6));

                    Serial.println(buf);

                    int numPackets = ceil(msgSize / 20.0);

                    for (int i = 0; i < numPackets; i++)
                    {
                        bytesRecvd += recvBLE(s);
                    }

                    if (bytesRecvd == msgSize)
                    {
                        return bytesRecvd;
                    }
                }
                continue;
            }

            break;
        }
    }

    return 0;
}

/* size_t BLE::maintainBLE(void) {
	if isConnected() {
		//do nothing
	} else {
		//check to see if advertising

		//
	}
} */

size_t BLE::recvBLE(String *s)
{
    String tmp = String("");

    // get our start time
    unsigned long startTime = millis();

    // as long as we have time
    while ((startTime + _timeout) > millis())
    {
        if (recv(&tmp) > 0)
        {
            if (tmp.startsWith("RECV BLE "))
            {
                s->concat(tmp.substring(9).trim());
                return tmp.substring(9).length();
            }

            tmp = "";
        }
    }

    return 0;
}

bool BLE::isConnected(bool printResponse)
{
    if (status() > 0)
    {
		String s = getCmdResponse();
		if (printResponse) {
			Serial.println("BLE: isConnected() response: ");
			Serial.print(s);
		}
        //return s.startsWith("STATE CONNECTED"); //original
		if (s.indexOf("CONNECTED") == -1) { //if it finds -1, then it wasn't found
			return false;
		} else {
			return true;
		}
    }

    return false;
}

bool BLE::waitConnect(int time)
{
    // some output has multiple lines
    String line = String("");

    // decide how long we're willing to wait
    int timeout = time > 0 ? time : _timeout;

    // get our start time
    unsigned long startTime = millis();

    // as long as we have time
    while ((startTime + timeout) > millis())
    {
        if (_serialPort->available() > 0)
        {
            line.concat((char)_serialPort->read());
        }

        if (line.endsWith(EOL))
        {
            if (line.startsWith("OPEN_OK BLE"))
            {
                return true;
            }

            // move on to next line
            line = "";
        }
    }

    return false;
}<|endoftext|>


<commit_before>#include <map>

#include "normalise.hh"
#include "references.hh"
#include "db.hh"
#include "exec.hh"
#include "globals.hh"

void registerSuccessor(const FSId & id1, const FSId & id2)
{
    setDB(nixDB, dbSuccessors, id1, id2);
}

static FSId storeSuccessor(const FSId & id1, ATerm sc)
{
    FSId id2 = writeTerm(sc, "-s-" + (string) id1);
    registerSuccessor(id1, id2);
    return id2;
}

typedef set<FSId> FSIdSet;

Slice normaliseFState(FSId id, FSIdSet pending)
{
    Nest nest(lvlTalkative, format("normalising fstate %1%") % (string) id);

    /* Try to substitute $id$ by any known successors in order to
       speed up the rewrite process. */
    string idSucc;
    while (queryDB(nixDB, dbSuccessors, id, idSucc)) {
        debug(format("successor %1% -> %2%") % (string) id % idSucc);
        id = parseHash(idSucc);
    }

    /* Get the fstate expression. */
    FState fs = parseFState(termFromId(id));

    /* It this is a normal form (i.e., a slice) we are done. */
    if (fs.type == FState::fsSlice) return fs.slice;

    /* Otherwise, it's a derivation. */

    /* Right platform? */
    if (fs.derive.platform != thisSystem)
        throw Error(format("a `%1%' is required, but I am a `%2%'")
            % fs.derive.platform % thisSystem);

    /* Realise inputs (and remember all input paths). */
    typedef map<string, SliceElem> ElemMap;

    ElemMap inMap;

    for (FSIds::iterator i = fs.derive.inputs.begin();
         i != fs.derive.inputs.end(); i++) {
        Slice slice = normaliseFState(*i, pending);
        realiseSlice(slice, pending);

        for (SliceElems::iterator j = slice.elems.begin();
             j != slice.elems.end(); j++)
            inMap[j->path] = *j;
    }

    Strings inPaths;
    for (ElemMap::iterator i = inMap.begin(); i != inMap.end(); i++)
        inPaths.push_back(i->second.path);

    /* Build the environment. */
    Environment env;
    for (StringPairs::iterator i = fs.derive.env.begin();
         i != fs.derive.env.end(); i++)
        env[i->first] = i->second;

    /* Parse the outputs. */
    typedef map<string, FSId> OutPaths;
    OutPaths outPaths;
    for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
         i != fs.derive.outputs.end(); i++)
    {
        debug(format("building %1% in `%2%'") % (string) i->second % i->first);
        outPaths[i->first] = i->second;
        inPaths.push_back(i->first);
    }

    /* We can skip running the builder if we can expand all output
       paths from their ids. */
    bool fastBuild = true;
    for (OutPaths::iterator i = outPaths.begin();
         i != outPaths.end(); i++)
    {
        try {
            expandId(i->second, i->first, "/", pending);
        } catch (Error & e) {
            debug(format("fast build failed for %1%") % e.what());
            fastBuild = false;
            break;
        }
    }

    if (!fastBuild) {

        /* Check that none of the outputs exist. */
        for (OutPaths::iterator i = outPaths.begin();
             i != outPaths.end(); i++)
            if (pathExists(i->first))
                throw Error(format("path `%1%' exists") % i->first);

        /* Run the builder. */
        msg(lvlChatty, format("building..."));
        runProgram(fs.derive.builder, env);
        msg(lvlChatty, format("build completed"));

    } else
        msg(lvlChatty, format("fast build succesful"));

    /* Check whether the output paths were created, and register each
       one. */
    FSIdSet used;
    for (OutPaths::iterator i = outPaths.begin();
         i != outPaths.end(); i++)
    {
        string path = i->first;
        if (!pathExists(path))
            throw Error(format("path `%1%' does not exist") % path);
        registerPath(path, i->second);
        fs.slice.roots.push_back(i->second);

        Strings refs = filterReferences(path, inPaths);

        SliceElem elem;
        elem.path = path;
        elem.id = i->second;

        for (Strings::iterator j = refs.begin(); j != refs.end(); j++) {
            ElemMap::iterator k;
            OutPaths::iterator l;
            if ((k = inMap.find(*j)) != inMap.end()) {
                elem.refs.push_back(k->second.id);
                used.insert(k->second.id);
                for (FSIds::iterator m = k->second.refs.begin();
                     m != k->second.refs.end(); m++)
                    used.insert(*m);
            } else if ((l = outPaths.find(*j)) != outPaths.end()) {
                elem.refs.push_back(l->second);
                used.insert(l->second);
            } else
                throw Error(format("unknown referenced path `%1%'") % *j);
        }

        fs.slice.elems.push_back(elem);
    }

    for (ElemMap::iterator i = inMap.begin();
         i != inMap.end(); i++)
    {
        FSIdSet::iterator j = used.find(i->second.id);
        if (j == used.end())
            debug(format("NOT referenced: `%1%'") % i->second.path);
        else {
            debug(format("referenced: `%1%'") % i->second.path);
            fs.slice.elems.push_back(i->second);
        }
    }

    fs.type = FState::fsSlice;
    ATerm nf = unparseFState(fs);
    msg(lvlVomit, format("normal form: %1%") % printTerm(nf));
    storeSuccessor(id, nf);

    return fs.slice;
}

void realiseSlice(const Slice & slice, FSIdSet pending)
{
    Nest nest(lvlDebug, format("realising slice"));

    /* Perhaps all paths already contain the right id? */

    bool missing = false;
    for (SliceElems::const_iterator i = slice.elems.begin();
         i != slice.elems.end(); i++)
    {
        SliceElem elem = *i;
        string id;
        if (!queryDB(nixDB, dbPath2Id, elem.path, id)) {
            if (pathExists(elem.path))
                throw Error(format("path `%1%' obstructed") % elem.path);
            missing = true;
            break;
        }
        if (parseHash(id) != elem.id)
            throw Error(format("path `%1%' obstructed") % elem.path);
    }

    if (!missing) {
        debug(format("already installed"));
        return;
    }

    /* For each element, expand its id at its path. */
    for (SliceElems::const_iterator i = slice.elems.begin();
         i != slice.elems.end(); i++)
    {
        SliceElem elem = *i;
        debug(format("expanding %1% in `%2%'") % (string) elem.id % elem.path);
        expandId(elem.id, elem.path, "/", pending);
    }
}

Strings fstatePaths(const FSId & id, bool normalise)
{
    Strings paths;

    FState fs;

    if (normalise) {
        fs.slice = normaliseFState(id);
        fs.type = FState::fsSlice;
    } else
        fs = parseFState(termFromId(id));

    if (fs.type == FState::fsSlice) {
        /* !!! fix complexity */
        for (FSIds::const_iterator i = fs.slice.roots.begin();
             i != fs.slice.roots.end(); i++)
            for (SliceElems::const_iterator j = fs.slice.elems.begin();
                 j != fs.slice.elems.end(); j++)
                if (*i == j->id) paths.push_back(j->path);
    }

    else if (fs.type == FState::fsDerive) {
        for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
             i != fs.derive.outputs.end(); i++)
            paths.push_back(i->first);
    }

    else abort();

    return paths;
}

Strings fstateRefs(const FSId & id)
{
    Strings paths;
    Slice slice = normaliseFState(id);
    for (SliceElems::const_iterator i = slice.elems.begin();
         i != slice.elems.end(); i++)
        paths.push_back(i->path);
    return paths;
}

FSIds findGenerators(const FSIds & _ids)
{
    FSIdSet ids(_ids.begin(), _ids.end());
    FSIds generators;

    /* !!! hack; for performance, we just look at the rhs of successor
       mappings, since we know that those are Nix expressions. */

    Strings sucs;
    enumDB(nixDB, dbSuccessors, sucs);

    for (Strings::iterator i = sucs.begin();
         i != sucs.end(); i++)
    {
        string s;
        if (!queryDB(nixDB, dbSuccessors, *i, s)) continue;
        FSId id = parseHash(s);

        FState fs;
        try {
            /* !!! should substitutes be used? */
            fs = parseFState(termFromId(id));
        } catch (...) { /* !!! only catch parse errors */
            continue;
        }

        if (fs.type != FState::fsSlice) continue;

        bool okay = true;
        for (SliceElems::const_iterator i = fs.slice.elems.begin();
             i != fs.slice.elems.end(); i++)
            if (ids.find(i->id) == ids.end()) {
                okay = false;
                break;
            }

        if (!okay) continue;

        generators.push_back(id);
    }

    return generators;
}
<commit_msg>* Fix message.<commit_after>#include <map>

#include "normalise.hh"
#include "references.hh"
#include "db.hh"
#include "exec.hh"
#include "globals.hh"

void registerSuccessor(const FSId & id1, const FSId & id2)
{
    setDB(nixDB, dbSuccessors, id1, id2);
}

static FSId storeSuccessor(const FSId & id1, ATerm sc)
{
    FSId id2 = writeTerm(sc, "-s-" + (string) id1);
    registerSuccessor(id1, id2);
    return id2;
}

typedef set<FSId> FSIdSet;

Slice normaliseFState(FSId id, FSIdSet pending)
{
    Nest nest(lvlTalkative, format("normalising fstate %1%") % (string) id);

    /* Try to substitute $id$ by any known successors in order to
       speed up the rewrite process. */
    string idSucc;
    while (queryDB(nixDB, dbSuccessors, id, idSucc)) {
        debug(format("successor %1% -> %2%") % (string) id % idSucc);
        id = parseHash(idSucc);
    }

    /* Get the fstate expression. */
    FState fs = parseFState(termFromId(id));

    /* It this is a normal form (i.e., a slice) we are done. */
    if (fs.type == FState::fsSlice) return fs.slice;

    /* Otherwise, it's a derivation. */

    /* Right platform? */
    if (fs.derive.platform != thisSystem)
        throw Error(format("a `%1%' is required, but I am a `%2%'")
            % fs.derive.platform % thisSystem);

    /* Realise inputs (and remember all input paths). */
    typedef map<string, SliceElem> ElemMap;

    ElemMap inMap;

    for (FSIds::iterator i = fs.derive.inputs.begin();
         i != fs.derive.inputs.end(); i++) {
        Slice slice = normaliseFState(*i, pending);
        realiseSlice(slice, pending);

        for (SliceElems::iterator j = slice.elems.begin();
             j != slice.elems.end(); j++)
            inMap[j->path] = *j;
    }

    Strings inPaths;
    for (ElemMap::iterator i = inMap.begin(); i != inMap.end(); i++)
        inPaths.push_back(i->second.path);

    /* Build the environment. */
    Environment env;
    for (StringPairs::iterator i = fs.derive.env.begin();
         i != fs.derive.env.end(); i++)
        env[i->first] = i->second;

    /* Parse the outputs. */
    typedef map<string, FSId> OutPaths;
    OutPaths outPaths;
    for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
         i != fs.derive.outputs.end(); i++)
    {
        debug(format("building %1% in `%2%'") % (string) i->second % i->first);
        outPaths[i->first] = i->second;
        inPaths.push_back(i->first);
    }

    /* We can skip running the builder if we can expand all output
       paths from their ids. */
    bool fastBuild = true;
    for (OutPaths::iterator i = outPaths.begin();
         i != outPaths.end(); i++)
    {
        try {
            expandId(i->second, i->first, "/", pending);
        } catch (Error & e) {
            debug(format("fast build failed for `%1%': %2%")
		  % i->first % e.what());
            fastBuild = false;
            break;
        }
    }

    if (!fastBuild) {

        /* Check that none of the outputs exist. */
        for (OutPaths::iterator i = outPaths.begin();
             i != outPaths.end(); i++)
            if (pathExists(i->first))
                throw Error(format("path `%1%' exists") % i->first);

        /* Run the builder. */
        msg(lvlChatty, format("building..."));
        runProgram(fs.derive.builder, env);
        msg(lvlChatty, format("build completed"));

    } else
        msg(lvlChatty, format("fast build succesful"));

    /* Check whether the output paths were created, and register each
       one. */
    FSIdSet used;
    for (OutPaths::iterator i = outPaths.begin();
         i != outPaths.end(); i++)
    {
        string path = i->first;
        if (!pathExists(path))
            throw Error(format("path `%1%' does not exist") % path);
        registerPath(path, i->second);
        fs.slice.roots.push_back(i->second);

        Strings refs = filterReferences(path, inPaths);

        SliceElem elem;
        elem.path = path;
        elem.id = i->second;

        for (Strings::iterator j = refs.begin(); j != refs.end(); j++) {
            ElemMap::iterator k;
            OutPaths::iterator l;
            if ((k = inMap.find(*j)) != inMap.end()) {
                elem.refs.push_back(k->second.id);
                used.insert(k->second.id);
                for (FSIds::iterator m = k->second.refs.begin();
                     m != k->second.refs.end(); m++)
                    used.insert(*m);
            } else if ((l = outPaths.find(*j)) != outPaths.end()) {
                elem.refs.push_back(l->second);
                used.insert(l->second);
            } else
                throw Error(format("unknown referenced path `%1%'") % *j);
        }

        fs.slice.elems.push_back(elem);
    }

    for (ElemMap::iterator i = inMap.begin();
         i != inMap.end(); i++)
    {
        FSIdSet::iterator j = used.find(i->second.id);
        if (j == used.end())
            debug(format("NOT referenced: `%1%'") % i->second.path);
        else {
            debug(format("referenced: `%1%'") % i->second.path);
            fs.slice.elems.push_back(i->second);
        }
    }

    fs.type = FState::fsSlice;
    ATerm nf = unparseFState(fs);
    msg(lvlVomit, format("normal form: %1%") % printTerm(nf));
    storeSuccessor(id, nf);

    return fs.slice;
}

void realiseSlice(const Slice & slice, FSIdSet pending)
{
    Nest nest(lvlDebug, format("realising slice"));

    /* Perhaps all paths already contain the right id? */

    bool missing = false;
    for (SliceElems::const_iterator i = slice.elems.begin();
         i != slice.elems.end(); i++)
    {
        SliceElem elem = *i;
        string id;
        if (!queryDB(nixDB, dbPath2Id, elem.path, id)) {
            if (pathExists(elem.path))
                throw Error(format("path `%1%' obstructed") % elem.path);
            missing = true;
            break;
        }
        if (parseHash(id) != elem.id)
            throw Error(format("path `%1%' obstructed") % elem.path);
    }

    if (!missing) {
        debug(format("already installed"));
        return;
    }

    /* For each element, expand its id at its path. */
    for (SliceElems::const_iterator i = slice.elems.begin();
         i != slice.elems.end(); i++)
    {
        SliceElem elem = *i;
        debug(format("expanding %1% in `%2%'") % (string) elem.id % elem.path);
        expandId(elem.id, elem.path, "/", pending);
    }
}

Strings fstatePaths(const FSId & id, bool normalise)
{
    Strings paths;

    FState fs;

    if (normalise) {
        fs.slice = normaliseFState(id);
        fs.type = FState::fsSlice;
    } else
        fs = parseFState(termFromId(id));

    if (fs.type == FState::fsSlice) {
        /* !!! fix complexity */
        for (FSIds::const_iterator i = fs.slice.roots.begin();
             i != fs.slice.roots.end(); i++)
            for (SliceElems::const_iterator j = fs.slice.elems.begin();
                 j != fs.slice.elems.end(); j++)
                if (*i == j->id) paths.push_back(j->path);
    }

    else if (fs.type == FState::fsDerive) {
        for (DeriveOutputs::iterator i = fs.derive.outputs.begin();
             i != fs.derive.outputs.end(); i++)
            paths.push_back(i->first);
    }

    else abort();

    return paths;
}

Strings fstateRefs(const FSId & id)
{
    Strings paths;
    Slice slice = normaliseFState(id);
    for (SliceElems::const_iterator i = slice.elems.begin();
         i != slice.elems.end(); i++)
        paths.push_back(i->path);
    return paths;
}

FSIds findGenerators(const FSIds & _ids)
{
    FSIdSet ids(_ids.begin(), _ids.end());
    FSIds generators;

    /* !!! hack; for performance, we just look at the rhs of successor
       mappings, since we know that those are Nix expressions. */

    Strings sucs;
    enumDB(nixDB, dbSuccessors, sucs);

    for (Strings::iterator i = sucs.begin();
         i != sucs.end(); i++)
    {
        string s;
        if (!queryDB(nixDB, dbSuccessors, *i, s)) continue;
        FSId id = parseHash(s);

        FState fs;
        try {
            /* !!! should substitutes be used? */
            fs = parseFState(termFromId(id));
        } catch (...) { /* !!! only catch parse errors */
            continue;
        }

        if (fs.type != FState::fsSlice) continue;

        bool okay = true;
        for (SliceElems::const_iterator i = fs.slice.elems.begin();
             i != fs.slice.elems.end(); i++)
            if (ids.find(i->id) == ids.end()) {
                okay = false;
                break;
            }

        if (!okay) continue;

        generators.push_back(id);
    }

    return generators;
}
<|endoftext|>


<commit_before>
#include <DuiLocale>
#include <QTimer>
#include <QHash>
#include <QObject>
#include <QDebug>
#include <QDBusInterface>
#include <QAbstractEventDispatcher>
#include <DuiInfoBanner>

#include "notifier.h"
#include "sysuid.h"
#include "notifierdbusadaptor.h"

NotifTimer::NotifTimer(int expireTimeout, QObject *receiver, const char *member, unsigned int notifId) :
    QObject(QAbstractEventDispatcher::instance()),
    notifId(notifId),
    notification(NULL)
{
    connect(this, SIGNAL(timeout(unsigned int)), receiver, member);
    timerId = startTimer(expireTimeout);
}

NotifTimer::NotifTimer(int expireTimeout, QObject *receiver, const char *member, DuiInfoBanner* notification) :
    QObject(QAbstractEventDispatcher::instance()),
    notifId(-1),
    notification(notification)
{
    connect(this, SIGNAL(timeout(DuiInfoBanner*)), receiver, member);
    timerId = startTimer(expireTimeout);
}

NotifTimer::~NotifTimer()
{
    if (timerId > 0)
        killTimer(timerId);
}

void NotifTimer::timerEvent(QTimerEvent *)
{
    // need to kill the timer _before_ we emit timeout() in case the
    // slot connected to timeout calls processEvents()
    if (timerId > 0)
        killTimer(timerId);
    timerId = -1;
    emit timeout(notification);
    emit timeout(notifId);
    delete this;
}

// TODO.: Use the logical names when available

// In the future the notifier connects to Notification Framework API and uses that to create notifications
// See messge formats from af/duihome:home/notifications/notificationmanager.xml;
// example message to test notificationManager:
//  dbus-send --print-reply --dest=org.maemo.dui.NotificationManager / org.maemo.dui.NotificationManager.addNotification uint32:0 string:'new-message' string:'Message received' string:'Hello DUI' string:'link' string:'Icon-close'
Notifier::Notifier(QObject* parent) :
        QObject(parent)
{
    dbus = new NotifierDBusAdaptor();
    managerIf = new QDBusInterface ( "org.maemo.dui.NotificationManager", "/", "org.maemo.dui.NotificationManager");
}

Notifier::~Notifier()
{
    if(NULL != dbus)
        delete dbus;

    dbus = NULL;
    delete managerIf;
    managerIf = NULL;
}

QObject* Notifier::responseObject()
{
    return (QObject*)dbus;
}

void Notifier::showNotification(const QString &notifText, NotificationType::Type type)
{
    switch (type)
    {
        case NotificationType::error:
            showDBusNotification(notifText, QString("error"));
            break;
        case NotificationType::warning:
            showDBusNotification(notifText, QString("warning"));
            break;
        case NotificationType::info:
            showDBusNotification(notifText, QString("info"));
            break;
    }
}

void Notifier::showConfirmation(const QString &notifText, const QString &buttonText)
{
/*
	// from DuiRemoteAction:

	QStringList l = string.split(' ');
    if (l.count() > 3) {
        d->serviceName = l.at(0);
        d->objectPath = l.at(1);
        d->interface = l.at(2);
        d->methodName = l.at(3);
    }
*/
    QString action(Sysuid::dbusService() + " " + Sysuid::dbusPath() + " " + NotifierDBusAdaptor::dbusInterfaceName() + " ");

    if (trid("qtn_cell_continue", "Continue") == buttonText)
        action += "pinQueryCancel";
    else if (trid("qtn_cell_try_again", "Try again") == buttonText)
        action += "simLockRetry";

    qDebug() << Q_FUNC_INFO << "action:" << action;
    showDBusNotification(notifText, QString("confirmation"), QString(""), 0, action, buttonText);
}

void Notifier::notificationTimeout(unsigned int notifId)
{
    if(0 < notifId) {
        removeNotification(notifId);
    }
}

void Notifier::notificationTimeout(DuiInfoBanner* notif)
{
    qDebug() << Q_FUNC_INFO << "notif:" << (QObject*)notif;
    if (notif != NULL) {
        notif->disappear();
    }
}

void Notifier::removeNotification(unsigned int id)
{
    QDBusMessage reply = managerIf->call(
        QString("removeNotification"),
        QVariant((unsigned int)id));

    // practically just debugging...
    if(reply.type() == QDBusMessage::ErrorMessage) {
        qDebug() << Q_FUNC_INFO << "(" << id << ") error reply:" << reply.errorName();
    }
    else if(reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() > 0) {
        qDebug() << Q_FUNC_INFO << "(" << id << ") result:" << reply.arguments()[0].toUInt();
    }
    else {
        qDebug() << Q_FUNC_INFO << "(" << id << ") reply type:" << reply.type();
    }

}

void Notifier::showDBusNotification(QString notifText, QString evetType, QString summary, int expireTimeout, QString action, QString buttonText)
{
    QDBusMessage reply = managerIf->call(
               QString("addNotification"),
               QVariant((unsigned int)0),
               QVariant(evetType), // temporary; correct types not specified yet; always shows envelope in info banner.
               QVariant(summary),
               QVariant(notifText),
               QVariant(action),
               QVariant(QString("Icon-close")));

    if(reply.type() == QDBusMessage::ErrorMessage) {
        qDebug() << Q_FUNC_INFO << " error reply:" << reply.errorName();
        // because of bootup order, connection can't be done in constructor.
        bool res = connect(
                dbus, SIGNAL(showNotification(QString, NotificationType)),
                this, SLOT(showNotification(QString, NotificationType)));
        if(!res){
            showLocalNotification(expireTimeout, notifText, buttonText);
        }
    }
    else if(reply.type() == QDBusMessage::ReplyMessage)
    {
        unsigned int notifId(0);
        QList<QVariant> args = reply.arguments();
        if(args.count() >= 1)
        {
            notifId = args[0].toUInt();
            qDebug() << Q_FUNC_INFO << ": notifId:" << notifId << "msg:" << notifText;
        }
        notifTimer(expireTimeout, notifId);
    }
    else {
        qDebug() << Q_FUNC_INFO << "reply type:" << reply.type();
    }
}

void Notifier::notifTimer(int expireTimeout, unsigned int notifId)
{
    if(0 < expireTimeout)
        (void) new NotifTimer(expireTimeout, this, SLOT(notificationTimeout(unsigned int)), notifId);
}

void Notifier::notifTimer(int expireTimeout, DuiInfoBanner* notif)
{
    qDebug() << Q_FUNC_INFO << "expireTimeout:" << expireTimeout;
    if(0 < expireTimeout)
        (void) new NotifTimer(expireTimeout, this, SLOT(notificationTimeout(DuiInfoBanner*)), notif);
    else if(0 >= notif->buttonText().length())
        notif->disappear();
}

void Notifier::showLocalNotification(int expireTimeout, QString notifText, QString buttonText)
{
    qDebug() << Q_FUNC_INFO << notifText;
    // DuiInfoBanner(BannerType type, const QString& image, const QString& body, const QString& iconId);
    DuiInfoBanner* n = new DuiInfoBanner(DuiInfoBanner::Information,
                                             "Icon-close",
                                             QString(notifText),
                                             "Icon-close");
/*    DuiInfoBanner* n = new DuiInfoBanner(DuiInfoBanner::Information,
                                             "Icon-close",
                                             QString( "" + notifText + ""),
                                             "Icon-close");
*/
    if (trid("qtn_cell_continue", "Continue") == buttonText){
        expireTimeout = 0;
        n->setButtonText(buttonText);
        connect(n, SIGNAL(buttonClicked()), this, SLOT(localNotificationPinQueryCancel()));
        connect(n, SIGNAL(clicked()), this, SLOT(localNotificationPinQueryCancel()));
    }
    else if (trid("qtn_cell_try_again", "Try again") == buttonText){
        expireTimeout = 0;
        n->setButtonText(buttonText);
        connect(n, SIGNAL(buttonClicked()), this, SLOT(localNotificationSimLockRetry()));
        connect(n, SIGNAL(clicked()), this, SLOT(localNotificationSimLockRetry()));
    } else {
        connect(n, SIGNAL(clicked()), this, SLOT(localNotificationClose()));
    }
    n->appear(DuiSceneWindow::DestroyWhenDone);
    notifTimer(expireTimeout, n);
}

void Notifier::localNotificationClose()
{
    DuiInfoBanner *ib = qobject_cast<DuiInfoBanner *>(sender());
    qDebug() << Q_FUNC_INFO << (QObject*) ib;
    if (ib != NULL) {
        ib->disappear();
    }
}
void Notifier::localNotificationPinQueryCancel()
{
    localNotificationClose();
    dbus->pinQueryCancel();
}

void Notifier::localNotificationSimLockRetry()
{
    localNotificationClose();
    dbus->simLockRetry();
}

<commit_msg>Null check added.<commit_after>
#include <DuiLocale>
#include <QTimer>
#include <QHash>
#include <QObject>
#include <QDebug>
#include <QDBusInterface>
#include <QAbstractEventDispatcher>
#include <DuiInfoBanner>

#include "notifier.h"
#include "sysuid.h"
#include "notifierdbusadaptor.h"

NotifTimer::NotifTimer(int expireTimeout, QObject *receiver, const char *member, unsigned int notifId) :
    QObject(QAbstractEventDispatcher::instance()),
    notifId(notifId),
    notification(NULL)
{
    connect(this, SIGNAL(timeout(unsigned int)), receiver, member);
    timerId = startTimer(expireTimeout);
}

NotifTimer::NotifTimer(int expireTimeout, QObject *receiver, const char *member, DuiInfoBanner* notification) :
    QObject(QAbstractEventDispatcher::instance()),
    notifId(-1),
    notification(notification)
{
    connect(this, SIGNAL(timeout(DuiInfoBanner*)), receiver, member);
    timerId = startTimer(expireTimeout);
}

NotifTimer::~NotifTimer()
{
    if (timerId > 0)
        killTimer(timerId);
}

void NotifTimer::timerEvent(QTimerEvent *)
{
    // need to kill the timer _before_ we emit timeout() in case the
    // slot connected to timeout calls processEvents()
    if (timerId > 0)
        killTimer(timerId);
    timerId = -1;
    emit timeout(notification);
    emit timeout(notifId);
    delete this;
}

// TODO.: Use the logical names when available

// In the future the notifier connects to Notification Framework API and uses that to create notifications
// See messge formats from af/duihome:home/notifications/notificationmanager.xml;
// example message to test notificationManager:
//  dbus-send --print-reply --dest=org.maemo.dui.NotificationManager / org.maemo.dui.NotificationManager.addNotification uint32:0 string:'new-message' string:'Message received' string:'Hello DUI' string:'link' string:'Icon-close'
Notifier::Notifier(QObject* parent) :
        QObject(parent)
{
    dbus = new NotifierDBusAdaptor();
    managerIf = new QDBusInterface ( "org.maemo.dui.NotificationManager", "/", "org.maemo.dui.NotificationManager");
}

Notifier::~Notifier()
{
    if(NULL != dbus)
        delete dbus;

    dbus = NULL;
    delete managerIf;
    managerIf = NULL;
}

QObject* Notifier::responseObject()
{
    return (QObject*)dbus;
}

void Notifier::showNotification(const QString &notifText, NotificationType::Type type)
{
    switch (type)
    {
        case NotificationType::error:
            showDBusNotification(notifText, QString("error"));
            break;
        case NotificationType::warning:
            showDBusNotification(notifText, QString("warning"));
            break;
        case NotificationType::info:
            showDBusNotification(notifText, QString("info"));
            break;
    }
}

void Notifier::showConfirmation(const QString &notifText, const QString &buttonText)
{
/*
	// from DuiRemoteAction:

	QStringList l = string.split(' ');
    if (l.count() > 3) {
        d->serviceName = l.at(0);
        d->objectPath = l.at(1);
        d->interface = l.at(2);
        d->methodName = l.at(3);
    }
*/
    QString action(Sysuid::dbusService() + " " + Sysuid::dbusPath() + " " + NotifierDBusAdaptor::dbusInterfaceName() + " ");

    if (trid("qtn_cell_continue", "Continue") == buttonText)
        action += "pinQueryCancel";
    else if (trid("qtn_cell_try_again", "Try again") == buttonText)
        action += "simLockRetry";

    qDebug() << Q_FUNC_INFO << "action:" << action;
    showDBusNotification(notifText, QString("confirmation"), QString(""), 0, action, buttonText);
}

void Notifier::notificationTimeout(unsigned int notifId)
{
    if(0 < notifId) {
        removeNotification(notifId);
    }
}

void Notifier::notificationTimeout(DuiInfoBanner* notif)
{
    qDebug() << Q_FUNC_INFO << "notif:" << (QObject*)notif;
    if (notif != NULL) {
        notif->disappear();
    }
}

void Notifier::removeNotification(unsigned int id)
{
    QDBusMessage reply = managerIf->call(
        QString("removeNotification"),
        QVariant((unsigned int)id));

    // practically just debugging...
    if(reply.type() == QDBusMessage::ErrorMessage) {
        qDebug() << Q_FUNC_INFO << "(" << id << ") error reply:" << reply.errorName();
    }
    else if(reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() > 0) {
        qDebug() << Q_FUNC_INFO << "(" << id << ") result:" << reply.arguments()[0].toUInt();
    }
    else {
        qDebug() << Q_FUNC_INFO << "(" << id << ") reply type:" << reply.type();
    }

}

void Notifier::showDBusNotification(QString notifText, QString evetType, QString summary, int expireTimeout, QString action, QString buttonText)
{
    QDBusMessage reply = managerIf->call(
               QString("addNotification"),
               QVariant((unsigned int)0),
               QVariant(evetType), // temporary; correct types not specified yet; always shows envelope in info banner.
               QVariant(summary),
               QVariant(notifText),
               QVariant(action),
               QVariant(QString("Icon-close")));

    if(reply.type() == QDBusMessage::ErrorMessage) {
        qDebug() << Q_FUNC_INFO << " error reply:" << reply.errorName();
        // because of bootup order, connection can't be done in constructor.
        bool res = connect(
                dbus, SIGNAL(showNotification(QString, NotificationType)),
                this, SLOT(showNotification(QString, NotificationType)));
        if(!res){
            showLocalNotification(expireTimeout, notifText, buttonText);
        }
    }
    else if(reply.type() == QDBusMessage::ReplyMessage)
    {
        unsigned int notifId(0);
        QList<QVariant> args = reply.arguments();
        if(args.count() >= 1)
        {
            notifId = args[0].toUInt();
            qDebug() << Q_FUNC_INFO << ": notifId:" << notifId << "msg:" << notifText;
        }
        notifTimer(expireTimeout, notifId);
    }
    else {
        qDebug() << Q_FUNC_INFO << "reply type:" << reply.type();
    }
}

void Notifier::notifTimer(int expireTimeout, unsigned int notifId)
{
    if(0 < expireTimeout)
        (void) new NotifTimer(expireTimeout, this, SLOT(notificationTimeout(unsigned int)), notifId);
}

void Notifier::notifTimer(int expireTimeout, DuiInfoBanner* notif)
{
    qDebug() << Q_FUNC_INFO << "expireTimeout:" << expireTimeout;
    if(!notif){
        return;
    }

    if(0 < expireTimeout)
        (void) new NotifTimer(expireTimeout, this, SLOT(notificationTimeout(DuiInfoBanner*)), notif);
    else if(0 >= notif->buttonText().length())
        notif->disappear();
}

void Notifier::showLocalNotification(int expireTimeout, QString notifText, QString buttonText)
{
    qDebug() << Q_FUNC_INFO << notifText;
    // DuiInfoBanner(BannerType type, const QString& image, const QString& body, const QString& iconId);
    DuiInfoBanner* n = new DuiInfoBanner(DuiInfoBanner::Information,
                                             "Icon-close",
                                             QString(notifText),
                                             "Icon-close");
/*    DuiInfoBanner* n = new DuiInfoBanner(DuiInfoBanner::Information,
                                             "Icon-close",
                                             QString( "" + notifText + ""),
                                             "Icon-close");
*/
    if (trid("qtn_cell_continue", "Continue") == buttonText){
        expireTimeout = 0;
        n->setButtonText(buttonText);
        connect(n, SIGNAL(buttonClicked()), this, SLOT(localNotificationPinQueryCancel()));
        connect(n, SIGNAL(clicked()), this, SLOT(localNotificationPinQueryCancel()));
    }
    else if (trid("qtn_cell_try_again", "Try again") == buttonText){
        expireTimeout = 0;
        n->setButtonText(buttonText);
        connect(n, SIGNAL(buttonClicked()), this, SLOT(localNotificationSimLockRetry()));
        connect(n, SIGNAL(clicked()), this, SLOT(localNotificationSimLockRetry()));
    } else {
        connect(n, SIGNAL(clicked()), this, SLOT(localNotificationClose()));
    }
    n->appear(DuiSceneWindow::DestroyWhenDone);
    notifTimer(expireTimeout, n);
}

void Notifier::localNotificationClose()
{
    DuiInfoBanner *ib = qobject_cast<DuiInfoBanner *>(sender());
    qDebug() << Q_FUNC_INFO << (QObject*) ib;
    if (ib != NULL) {
        ib->disappear();
    }
}
void Notifier::localNotificationPinQueryCancel()
{
    localNotificationClose();
    dbus->pinQueryCancel();
}

void Notifier::localNotificationSimLockRetry()
{
    localNotificationClose();
    dbus->simLockRetry();
}

<|endoftext|>


<commit_before>#include <core/stdafx.h>
#include <core/smartview/NickNameCache.h>

namespace smartview
{
	SRowStruct::SRowStruct(const std::shared_ptr<binaryParser>& parser)
	{
		cValues = blockT<DWORD>::parse(parser);

		if (*cValues)
		{
			if (*cValues < _MaxEntriesSmall)
			{
				lpProps.EnableNickNameParsing();
				lpProps.SetMaxEntries(*cValues);
				lpProps.smartViewParser::parse(parser, false);
			}
		}
	} // namespace smartview

	void NickNameCache::parse()
	{
		m_Metadata1 = blockBytes::parse(m_Parser, 4);
		m_ulMajorVersion = blockT<DWORD>::parse(m_Parser);
		m_ulMinorVersion = blockT<DWORD>::parse(m_Parser);
		m_cRowCount = blockT<DWORD>::parse(m_Parser);

		if (*m_cRowCount)
		{
			if (*m_cRowCount < _MaxEntriesEnormous)
			{
				m_lpRows.reserve(*m_cRowCount);
				for (DWORD i = 0; i < *m_cRowCount; i++)
				{
					m_lpRows.emplace_back(std::make_shared<SRowStruct>(m_Parser));
				}
			}
		}

		m_cbEI = blockT<DWORD>::parse(m_Parser);
		m_lpbEI = blockBytes::parse(m_Parser, *m_cbEI, _MaxBytes);
		m_Metadata2 = blockBytes::parse(m_Parser, 8);
	}

	void NickNameCache::parseBlocks()
	{
		setRoot(L"Nickname Cache\r\n");
		addLabledChild(L"Metadata1 = ", m_Metadata1);

		addChild(m_ulMajorVersion, L"Major Version = %1!d!\r\n", m_ulMajorVersion->getData());
		addChild(m_ulMinorVersion, L"Minor Version = %1!d!\r\n", m_ulMinorVersion->getData());
		addChild(m_cRowCount, L"Row Count = %1!d!", m_cRowCount->getData());

		if (!m_lpRows.empty())
		{
			auto i = DWORD{};
			for (const auto& row : m_lpRows)
			{
				terminateBlock();
				if (i > 0) addBlankLine();
				addHeader(L"Row %1!d!\r\n", i);
				addChild(row->cValues, L"cValues = 0x%1!08X! = %1!d!\r\n", row->cValues->getData());

				addChild(row->lpProps.getBlock());

				i++;
			}
		}

		terminateBlock();
		addBlankLine();

		addLabledChild(L"Extra Info = ", m_lpbEI);

		addLabledChild(L"Metadata 2 = ", m_Metadata2);
	}
} // namespace smartview<commit_msg>make rows collapsable<commit_after>#include <core/stdafx.h>
#include <core/smartview/NickNameCache.h>

namespace smartview
{
	SRowStruct::SRowStruct(const std::shared_ptr<binaryParser>& parser)
	{
		cValues = blockT<DWORD>::parse(parser);

		if (*cValues)
		{
			if (*cValues < _MaxEntriesSmall)
			{
				lpProps.EnableNickNameParsing();
				lpProps.SetMaxEntries(*cValues);
				lpProps.smartViewParser::parse(parser, false);
			}
		}
	} // namespace smartview

	void NickNameCache::parse()
	{
		m_Metadata1 = blockBytes::parse(m_Parser, 4);
		m_ulMajorVersion = blockT<DWORD>::parse(m_Parser);
		m_ulMinorVersion = blockT<DWORD>::parse(m_Parser);
		m_cRowCount = blockT<DWORD>::parse(m_Parser);

		if (*m_cRowCount)
		{
			if (*m_cRowCount < _MaxEntriesEnormous)
			{
				m_lpRows.reserve(*m_cRowCount);
				for (DWORD i = 0; i < *m_cRowCount; i++)
				{
					m_lpRows.emplace_back(std::make_shared<SRowStruct>(m_Parser));
				}
			}
		}

		m_cbEI = blockT<DWORD>::parse(m_Parser);
		m_lpbEI = blockBytes::parse(m_Parser, *m_cbEI, _MaxBytes);
		m_Metadata2 = blockBytes::parse(m_Parser, 8);
	}

	void NickNameCache::parseBlocks()
	{
		setRoot(L"Nickname Cache\r\n");
		addLabledChild(L"Metadata1 = ", m_Metadata1);

		addChild(m_ulMajorVersion, L"Major Version = %1!d!\r\n", m_ulMajorVersion->getData());
		addChild(m_ulMinorVersion, L"Minor Version = %1!d!\r\n", m_ulMinorVersion->getData());
		addChild(m_cRowCount, L"Row Count = %1!d!", m_cRowCount->getData());

		if (!m_lpRows.empty())
		{
			auto i = DWORD{};
			for (const auto& row : m_lpRows)
			{
				terminateBlock();
				if (i > 0) addBlankLine();
				auto rowBlock = std::make_shared<block>(strings::formatmessage(L"Row %1!d!\r\n", i));
				addChild(rowBlock);
				rowBlock->addChild(row->cValues, L"cValues = 0x%1!08X! = %1!d!\r\n", row->cValues->getData());
				rowBlock->addChild(row->lpProps.getBlock());

				i++;
			}
		}

		terminateBlock();
		addBlankLine();

		addLabledChild(L"Extra Info = ", m_lpbEI);

		addLabledChild(L"Metadata 2 = ", m_Metadata2);
	}
} // namespace smartview<|endoftext|>