<commit_before>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2009, 2010, 2012, 2013 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

// check ConstraintMatrix.distribute() for a petsc vector
//
// we do this by creating a vector where each processor has 100
// elements but no ghost elements. then we add constraints on each
// processor that constrain elements within each processor's local
// range to ones outside. these have to be added on all
// processors. then call distribute() and verify that the result is
// true.
//
// we use constraints of the form x_i = x_j with sequentially growing
// x_j's so that we can verify the correctness analytically
//
// compared to the _01 test, here the ConstraintMatrix object acts on an index
// set that only includes the locally owned vector elements, without any
// overlap. this verifies that we really only need to know about the *sources*
// of constraints locally, not the *targets*.

#include "../tests.h"
#include <deal.II/base/logstream.h>
#include <deal.II/lac/petsc_parallel_vector.h>
#include <deal.II/lac/constraint_matrix.h>

#include <fstream>
#include <sstream>

void test()
{
  const unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
  const unsigned int n_processes = Utilities::MPI::n_mpi_processes (MPI_COMM_WORLD);

  // create a vector that consists of elements indexed from 0 to n
  PETScWrappers::MPI::Vector vec (MPI_COMM_WORLD, 100 * n_processes, 100);
  Assert (vec.local_size() == 100, ExcInternalError());
  Assert (vec.local_range().first == 100*myid, ExcInternalError());
  Assert (vec.local_range().second == 100*myid+100, ExcInternalError());
  for (unsigned int i=vec.local_range().first; i<vec.local_range().second; ++i)
    vec(i) = i;
  vec.compress();

  // verify correctness so far
  {
    double exact_l1 = 0;
    for (unsigned int i=0; i<vec.size(); ++i)
      exact_l1 += i;
    Assert (vec.l1_norm() == exact_l1, ExcInternalError());
  }

  // create a ConstraintMatrix with a range that only includes locally active
  // DoFs
  IndexSet locally_relevant_range (vec.size());
  locally_relevant_range.add_range (100*myid,
				    100*myid+100);
  ConstraintMatrix cm (locally_relevant_range);

  // add constraints that constrain an element in the middle of the
  // local range of each processor against an element outside, both in
  // the ghost range before and after
  //
  // note that we tell each processor about all constraints, but most
  // of them will throw away this information since it is not for a
  // DoF inside the locally relevant range
  for (unsigned int p=0; p<n_processes; ++p)
    {
      if ((p != 0) && locally_relevant_range.is_element (p*100+10))
	{
	  cm.add_line (p*100+10);
	  cm.add_entry (p*100+10,
			p*100-25,
			1);
	}

      if ((p != n_processes-1) && locally_relevant_range.is_element (p*100+90))
	{
	  cm.add_line (p*100+90);
	  cm.add_entry (p*100+90,
			p*100+105,
			1);
	}
    }
  cm.close ();

  // now distribute these constraints
  cm.distribute (vec);

  // verify correctness
  vec.compress ();

  if (myid != 0)
    Assert (vec(vec.local_range().first+10) == vec.local_range().first-25,
	    ExcInternalError());

  if (myid != n_processes-1)
    Assert (vec(vec.local_range().first+90) == vec.local_range().first+105,
	    ExcInternalError());

  for (unsigned int i=vec.local_range().first; i<vec.local_range().second; ++i)
    {
      if ((i != vec.local_range().first+10)
	  &&
	  (i != vec.local_range().first+90))
	{
	  double val = vec(i);
	  Assert (std::fabs(val - i) <= 1e-6, ExcInternalError());
	}
    }

  {
    double exact_l1 = 0;

    // add up original values of vector entries
    for (unsigned int i=0; i<vec.size(); ++i)
      exact_l1 += i;

    // but then correct for the constrained values
    for (unsigned int p=0; p<n_processes; ++p)
      {
	if (p != 0)
	  exact_l1 = exact_l1 - (p*100+10) + (p*100-25);
	if (p != n_processes-1)
	  exact_l1 = exact_l1 - (p*100+90) + (p*100+105);
      }

    Assert (vec.l1_norm() == exact_l1, ExcInternalError());

    if (myid == 0)
      deallog << "Norm = " << vec.l1_norm() << std::endl;
  }
}

int main(int argc, char *argv[])
{
  Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);

  unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);

  deallog.push(Utilities::int_to_string(myid));

  if (myid == 0)
    {
      std::ofstream logfile(output_file_for_mpi("petsc_condense_02").c_str());
      deallog.attach(logfile);
      deallog.depth_console(0);
      deallog.threshold_double(1.e-10);

      test();
    }
  else
    test();

}
<commit_msg>Augment text.<commit_after>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2009, 2010, 2012, 2013 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

// check ConstraintMatrix.distribute() for a petsc vector
//
// we do this by creating a vector where each processor has 100
// elements but no ghost elements. then we add constraints on each
// processor that constrain elements within each processor's local
// range to ones outside. these have to be added on all
// processors. then call distribute() and verify that the result is
// true.
//
// we use constraints of the form x_i = x_j with sequentially growing
// x_j's so that we can verify the correctness analytically
//
// compared to the _01 test, here the ConstraintMatrix object acts on an index
// set that only includes the locally owned vector elements, without any
// overlap. this verifies that we really only need to know about the *targets*
// of constraints locally, not the *sources*. (at the time of writing this
// test, ConstraintMatrix::distribute for PETSc distributed vectors actively
// imported the source vector elements for those target elements we locally
// own.)

#include "../tests.h"
#include <deal.II/base/logstream.h>
#include <deal.II/lac/petsc_parallel_vector.h>
#include <deal.II/lac/constraint_matrix.h>

#include <fstream>
#include <sstream>

void test()
{
  const unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);
  const unsigned int n_processes = Utilities::MPI::n_mpi_processes (MPI_COMM_WORLD);

  // create a vector that consists of elements indexed from 0 to n
  PETScWrappers::MPI::Vector vec (MPI_COMM_WORLD, 100 * n_processes, 100);
  Assert (vec.local_size() == 100, ExcInternalError());
  Assert (vec.local_range().first == 100*myid, ExcInternalError());
  Assert (vec.local_range().second == 100*myid+100, ExcInternalError());
  for (unsigned int i=vec.local_range().first; i<vec.local_range().second; ++i)
    vec(i) = i;
  vec.compress();

  // verify correctness so far
  {
    double exact_l1 = 0;
    for (unsigned int i=0; i<vec.size(); ++i)
      exact_l1 += i;
    Assert (vec.l1_norm() == exact_l1, ExcInternalError());
  }

  // create a ConstraintMatrix with a range that only includes locally owned
  // DoFs
  IndexSet locally_owned_range (vec.size());
  locally_owned_range.add_range (100*myid,
				    100*myid+100);
  ConstraintMatrix cm (locally_owned_range);

  // add constraints that constrain an element in the middle of the
  // local range of each processor against an element outside, both in
  // the ghost range before and after
  //
  // note that we tell each processor about all constraints, but most
  // of them will throw away this information since it is not for a
  // DoF inside the locally relevant range
  for (unsigned int p=0; p<n_processes; ++p)
    {
      if ((p != 0) && locally_owned_range.is_element (p*100+10))
	{
	  cm.add_line (p*100+10);
	  cm.add_entry (p*100+10,
			p*100-25,
			1);
	}

      if ((p != n_processes-1) && locally_owned_range.is_element (p*100+90))
	{
	  cm.add_line (p*100+90);
	  cm.add_entry (p*100+90,
			p*100+105,
			1);
	}
    }
  cm.close ();

  // now distribute these constraints
  cm.distribute (vec);

  // verify correctness
  vec.compress ();

  if (myid != 0)
    Assert (vec(vec.local_range().first+10) == vec.local_range().first-25,
	    ExcInternalError());

  if (myid != n_processes-1)
    Assert (vec(vec.local_range().first+90) == vec.local_range().first+105,
	    ExcInternalError());

  for (unsigned int i=vec.local_range().first; i<vec.local_range().second; ++i)
    {
      if ((i != vec.local_range().first+10)
	  &&
	  (i != vec.local_range().first+90))
	{
	  double val = vec(i);
	  Assert (std::fabs(val - i) <= 1e-6, ExcInternalError());
	}
    }

  {
    double exact_l1 = 0;

    // add up original values of vector entries
    for (unsigned int i=0; i<vec.size(); ++i)
      exact_l1 += i;

    // but then correct for the constrained values
    for (unsigned int p=0; p<n_processes; ++p)
      {
	if (p != 0)
	  exact_l1 = exact_l1 - (p*100+10) + (p*100-25);
	if (p != n_processes-1)
	  exact_l1 = exact_l1 - (p*100+90) + (p*100+105);
      }

    Assert (vec.l1_norm() == exact_l1, ExcInternalError());

    if (myid == 0)
      deallog << "Norm = " << vec.l1_norm() << std::endl;
  }
}

int main(int argc, char *argv[])
{
  Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);

  unsigned int myid = Utilities::MPI::this_mpi_process (MPI_COMM_WORLD);

  deallog.push(Utilities::int_to_string(myid));

  if (myid == 0)
    {
      std::ofstream logfile(output_file_for_mpi("petsc_condense_02").c_str());
      deallog.attach(logfile);
      deallog.depth_console(0);
      deallog.threshold_double(1.e-10);

      test();
    }
  else
    test();

}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. 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 "build.h"

#include <stdio.h>
#include <sys/time.h>

#include "build_log.h"
#include "graph.h"
#include "ninja.h"
#include "subprocess.h"

struct BuildStatus {
  BuildStatus();
  void PlanHasTotalEdges(int total);
  void BuildEdgeStarted(Edge* edge);
  // Returns the time the edge took, in ms.
  int BuildEdgeFinished(Edge* edge);

  void PrintStatus(Edge* edge);

  time_t last_update_;
  int finished_edges_, total_edges_;

  typedef map<Edge*, timeval> RunningEdgeMap;
  RunningEdgeMap running_edges_;

  BuildConfig::Verbosity verbosity_;
  // Whether we can do fancy terminal control codes.
  bool smart_terminal_;
};

BuildStatus::BuildStatus()
    : last_update_(time(NULL)), finished_edges_(0), total_edges_(0),
      verbosity_(BuildConfig::NORMAL) {
  const char* term = getenv("TERM");
  smart_terminal_ = isatty(1) && term && string(term) != "dumb";
}

void BuildStatus::PlanHasTotalEdges(int total) {
  total_edges_ = total;
}

void BuildStatus::BuildEdgeStarted(Edge* edge) {
  timeval now;
  gettimeofday(&now, NULL);
  running_edges_.insert(make_pair(edge, now));

  PrintStatus(edge);
}

int BuildStatus::BuildEdgeFinished(Edge* edge) {
  timeval now;
  gettimeofday(&now, NULL);
  ++finished_edges_;

  if (verbosity_ != BuildConfig::QUIET) {
    if (smart_terminal_ && verbosity_ == BuildConfig::NORMAL) {
      PrintStatus(edge);
      if (finished_edges_ == total_edges_)
        printf("\n");
    } else {
      if (now.tv_sec - last_update_ > 5) {
        printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
               finished_edges_, total_edges_);
        last_update_ = now.tv_sec;
      }
    }
  }

  RunningEdgeMap::iterator i = running_edges_.find(edge);
  timeval delta;
  timersub(&now, &i->second, &delta);
  int ms = (delta.tv_sec * 1000) + (delta.tv_usec / 1000);
  running_edges_.erase(i);

  return ms;
}

void BuildStatus::PrintStatus(Edge* edge) {
  switch (verbosity_) {
  case BuildConfig::QUIET:
    return;

  case BuildConfig::VERBOSE:
    printf("%s\n", edge->EvaluateCommand().c_str());
    break;

  default: {
    string to_print = edge->GetDescription();
    if (to_print.empty() || verbosity_ == BuildConfig::VERBOSE)
      to_print = edge->EvaluateCommand();

    if (smart_terminal_) {
      printf("\r[%d/%d] %s\e[K", finished_edges_, total_edges_,
             to_print.c_str());
      fflush(stdout);
    } else {
      printf("%s\n", to_print.c_str());
    }
  }
  }
}

Plan::Plan() : command_edges_(0) {}

bool Plan::AddTarget(Node* node, string* err) {
  vector<Node*> stack;
  return AddSubTarget(node, &stack, err);
}

bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
  Edge* edge = node->in_edge_;
  if (!edge) {  // Leaf node.
    if (node->dirty_) {
      string referenced;
      if (!stack->empty())
        referenced = ", needed by '" + stack->back()->file_->path_ + "',";
      *err = "'" + node->file_->path_ + "'" + referenced + " missing "
             "and no known rule to make it";
    }
    return false;
  }
  assert(edge);

  if (CheckDependencyCycle(node, stack, err))
    return false;

  if (!node->dirty())
    return false;  // Don't need to do anything.
  if (want_.find(edge) != want_.end())
    return true;  // We've already enqueued it.
  want_.insert(edge);
  if (!edge->is_phony())
    ++command_edges_;

  stack->push_back(node);
  bool awaiting_inputs = false;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    if (!edge->is_implicit(i - edge->inputs_.begin()) &&
        AddSubTarget(*i, stack, err)) {
      awaiting_inputs = true;
    } else if (!err->empty()) {
      return false;
    }
  }
  assert(stack->back() == node);
  stack->pop_back();

  if (!awaiting_inputs)
    ready_.insert(edge);

  return true;
}

bool Plan::CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err) {
  vector<Node*>::reverse_iterator ri =
      find(stack->rbegin(), stack->rend(), node);
  if (ri == stack->rend())
    return false;

  // Add this node onto the stack to make it clearer where the loop
  // is.
  stack->push_back(node);

  vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
  *err = "dependency cycle: ";
  for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
    if (i != start)
      err->append(" -> ");
    err->append((*i)->file_->path_);
  }
  return true;
}

Edge* Plan::FindWork() {
  if (ready_.empty())
    return NULL;
  set<Edge*>::iterator i = ready_.begin();
  Edge* edge = *i;
  ready_.erase(i);
  return edge;
}

void Plan::EdgeFinished(Edge* edge) {
  want_.erase(edge);

  // Check off any nodes we were waiting for with this edge.
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    NodeFinished(*i);
  }
}

void Plan::NodeFinished(Node* node) {
  // See if we we want any edges from this node.
  for (vector<Edge*>::iterator i = node->out_edges_.begin();
       i != node->out_edges_.end(); ++i) {
    if (want_.find(*i) != want_.end()) {
      // See if the edge is now ready.
      bool ready = true;
      for (vector<Node*>::iterator j = (*i)->inputs_.begin();
           j != (*i)->inputs_.end(); ++j) {
        if ((*j)->dirty()) {
          ready = false;
          break;
        }
      }
      if (ready)
        ready_.insert(*i);
    }
  }
}

void Plan::Dump() {
  printf("pending: %d\n", (int)want_.size());
  for (set<Edge*>::iterator i = want_.begin(); i != want_.end(); ++i) {
    (*i)->Dump();
  }
  printf("ready: %d\n", (int)ready_.size());
}

struct RealCommandRunner : public CommandRunner {
  RealCommandRunner(const BuildConfig& config) : config_(config) {}
  virtual ~RealCommandRunner() {}
  virtual bool CanRunMore();
  virtual bool StartCommand(Edge* edge);
  virtual bool WaitForCommands();
  virtual Edge* NextFinishedCommand(bool* success);

  const BuildConfig& config_;
  SubprocessSet subprocs_;
  map<Subprocess*, Edge*> subproc_to_edge_;
};

bool RealCommandRunner::CanRunMore() {
  return ((int)subprocs_.running_.size()) < config_.parallelism;
}

bool RealCommandRunner::StartCommand(Edge* edge) {
  string command = edge->EvaluateCommand();
  Subprocess* subproc = new Subprocess;
  subproc_to_edge_.insert(make_pair(subproc, edge));
  if (!subproc->Start(command))
    return false;

  subprocs_.Add(subproc);
  return true;
}

bool RealCommandRunner::WaitForCommands() {
  if (subprocs_.running_.empty())
    return false;

  while (subprocs_.finished_.empty()) {
    subprocs_.DoWork();
  }
  return true;
}

Edge* RealCommandRunner::NextFinishedCommand(bool* success) {
  Subprocess* subproc = subprocs_.NextFinished();
  if (!subproc)
    return NULL;

  *success = subproc->Finish();

  map<Subprocess*, Edge*>::iterator i = subproc_to_edge_.find(subproc);
  Edge* edge = i->second;
  subproc_to_edge_.erase(i);

  if (!*success ||
      !subproc->stdout_.buf_.empty() ||
      !subproc->stderr_.buf_.empty()) {
    // Print the command that is spewing before printing its output.
    // Print the full command when it failed, otherwise the short name if
    // available.
    string to_print = edge->GetDescription();
    if (to_print.empty() ||
        config_.verbosity == BuildConfig::VERBOSE ||
        !*success) {
      to_print = edge->EvaluateCommand();
    }

    printf("\n%s%s\n", *success ? "" : "FAILED: ", to_print.c_str());
    if (!subproc->stdout_.buf_.empty())
      printf("%s\n", subproc->stdout_.buf_.c_str());
    if (!subproc->stderr_.buf_.empty())
      printf("%s\n", subproc->stderr_.buf_.c_str());
  }

  delete subproc;
  return edge;
}

struct DryRunCommandRunner : public CommandRunner {
  virtual ~DryRunCommandRunner() {}
  virtual bool CanRunMore() {
    return true;
  }
  virtual bool StartCommand(Edge* edge) {
    finished_.push(edge);
    return true;
  }
  virtual bool WaitForCommands() {
    return true;
  }
  virtual Edge* NextFinishedCommand(bool* success) {
    if (finished_.empty())
      return NULL;
    *success = true;
    Edge* edge = finished_.front();
    finished_.pop();
    return edge;
  }

  queue<Edge*> finished_;
};

Builder::Builder(State* state, const BuildConfig& config)
    : state_(state) {
  disk_interface_ = new RealDiskInterface;
  if (config.dry_run)
    command_runner_ = new DryRunCommandRunner;
  else
    command_runner_ = new RealCommandRunner(config);
  status_ = new BuildStatus;
  status_->verbosity_ = config.verbosity;
  log_ = state->build_log_;
}

Node* Builder::AddTarget(const string& name, string* err) {
  Node* node = state_->LookupNode(name);
  if (!node) {
    *err = "unknown target: '" + name + "'";
    return NULL;
  }
  node->file_->StatIfNecessary(disk_interface_);
  if (node->in_edge_) {
    if (!node->in_edge_->RecomputeDirty(state_, disk_interface_, err))
      return NULL;
  }
  if (!node->dirty_)
    return NULL;  // Intentionally no error.

  if (!plan_.AddTarget(node, err))
    return NULL;
  return node;
}

bool Builder::Build(string* err) {
  if (!plan_.more_to_do()) {
    *err = "no work to do";
    return true;
  }

  status_->PlanHasTotalEdges(plan_.command_edge_count());
  while (plan_.more_to_do()) {
    while (command_runner_->CanRunMore()) {
      Edge* edge = plan_.FindWork();
      if (!edge)
        break;

      if (!StartEdge(edge, err))
        return false;

      if (edge->is_phony())
        FinishEdge(edge);
    }

    if (!plan_.more_to_do())
      break;

    bool success;
    if (Edge* edge = command_runner_->NextFinishedCommand(&success)) {
      if (!success) {
        *err = "subcommand failed";
        return false;
      }
      FinishEdge(edge);
    } else {
      if (!command_runner_->WaitForCommands()) {
        *err = "stuck [this is a bug]";
        return false;
      }
    }
  }

  return true;
}

bool Builder::StartEdge(Edge* edge, string* err) {
  if (edge->is_phony())
    return true;

  status_->BuildEdgeStarted(edge);

  // Create directories necessary for outputs.
  // XXX: this will block; do we care?
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    if (!disk_interface_->MakeDirs((*i)->file_->path_))
      return false;
  }

  // Compute command and start it.
  string command = edge->EvaluateCommand();
  if (!command_runner_->StartCommand(edge)) {
    err->assign("command '" + command + "' failed.");
    return false;
  }

  return true;
}

void Builder::FinishEdge(Edge* edge) {
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    // XXX check that the output actually changed
    // XXX just notify node and have it propagate?
    (*i)->dirty_ = false;
  }
  plan_.EdgeFinished(edge);

  if (edge->is_phony())
    return;

  int ms = status_->BuildEdgeFinished(edge);
  if (log_)
    log_->RecordCommand(edge, ms);
}
<commit_msg>limit output width to prevent line-wrapping<commit_after>// Copyright 2011 Google Inc. 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 "build.h"

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/termios.h>

#include "build_log.h"
#include "graph.h"
#include "ninja.h"
#include "subprocess.h"

struct BuildStatus {
  BuildStatus();
  void PlanHasTotalEdges(int total);
  void BuildEdgeStarted(Edge* edge);
  // Returns the time the edge took, in ms.
  int BuildEdgeFinished(Edge* edge);

  void PrintStatus(Edge* edge);

  time_t last_update_;
  int finished_edges_, total_edges_;

  typedef map<Edge*, timeval> RunningEdgeMap;
  RunningEdgeMap running_edges_;

  BuildConfig::Verbosity verbosity_;
  // Whether we can do fancy terminal control codes.
  bool smart_terminal_;
};

BuildStatus::BuildStatus()
    : last_update_(time(NULL)), finished_edges_(0), total_edges_(0),
      verbosity_(BuildConfig::NORMAL) {
  const char* term = getenv("TERM");
  smart_terminal_ = isatty(1) && term && string(term) != "dumb";
}

void BuildStatus::PlanHasTotalEdges(int total) {
  total_edges_ = total;
}

void BuildStatus::BuildEdgeStarted(Edge* edge) {
  timeval now;
  gettimeofday(&now, NULL);
  running_edges_.insert(make_pair(edge, now));

  PrintStatus(edge);
}

int BuildStatus::BuildEdgeFinished(Edge* edge) {
  timeval now;
  gettimeofday(&now, NULL);
  ++finished_edges_;

  if (verbosity_ != BuildConfig::QUIET) {
    if (smart_terminal_ && verbosity_ == BuildConfig::NORMAL) {
      PrintStatus(edge);
      if (finished_edges_ == total_edges_)
        printf("\n");
    } else {
      if (now.tv_sec - last_update_ > 5) {
        printf("%.1f%% %d/%d\n", finished_edges_ * 100 / (float)total_edges_,
               finished_edges_, total_edges_);
        last_update_ = now.tv_sec;
      }
    }
  }

  RunningEdgeMap::iterator i = running_edges_.find(edge);
  timeval delta;
  timersub(&now, &i->second, &delta);
  int ms = (delta.tv_sec * 1000) + (delta.tv_usec / 1000);
  running_edges_.erase(i);

  return ms;
}

void BuildStatus::PrintStatus(Edge* edge) {
  switch (verbosity_) {
  case BuildConfig::QUIET:
    return;

  case BuildConfig::VERBOSE:
    printf("%s\n", edge->EvaluateCommand().c_str());
    break;

  default: {
    string to_print = edge->GetDescription();
    if (to_print.empty() || verbosity_ == BuildConfig::VERBOSE)
      to_print = edge->EvaluateCommand();

    if (smart_terminal_) {
      // Limit output to width of the terminal so we don't cause line-wrapping.
      winsize size;
      if (ioctl(0, TIOCGWINSZ, &size) == 0) {
        const int kMargin = 15;  // Space for [xxx/yyy] and "...".
        if (to_print.size() + kMargin > size.ws_col) {
          int substr = to_print.size() + kMargin - size.ws_col;
          to_print = "..." + to_print.substr(substr);
        }
      }

      printf("\r[%d/%d] %s\e[K", finished_edges_, total_edges_,
             to_print.c_str());
      fflush(stdout);
    } else {
      printf("%s\n", to_print.c_str());
    }
  }
  }
}

Plan::Plan() : command_edges_(0) {}

bool Plan::AddTarget(Node* node, string* err) {
  vector<Node*> stack;
  return AddSubTarget(node, &stack, err);
}

bool Plan::AddSubTarget(Node* node, vector<Node*>* stack, string* err) {
  Edge* edge = node->in_edge_;
  if (!edge) {  // Leaf node.
    if (node->dirty_) {
      string referenced;
      if (!stack->empty())
        referenced = ", needed by '" + stack->back()->file_->path_ + "',";
      *err = "'" + node->file_->path_ + "'" + referenced + " missing "
             "and no known rule to make it";
    }
    return false;
  }
  assert(edge);

  if (CheckDependencyCycle(node, stack, err))
    return false;

  if (!node->dirty())
    return false;  // Don't need to do anything.
  if (want_.find(edge) != want_.end())
    return true;  // We've already enqueued it.
  want_.insert(edge);
  if (!edge->is_phony())
    ++command_edges_;

  stack->push_back(node);
  bool awaiting_inputs = false;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    if (!edge->is_implicit(i - edge->inputs_.begin()) &&
        AddSubTarget(*i, stack, err)) {
      awaiting_inputs = true;
    } else if (!err->empty()) {
      return false;
    }
  }
  assert(stack->back() == node);
  stack->pop_back();

  if (!awaiting_inputs)
    ready_.insert(edge);

  return true;
}

bool Plan::CheckDependencyCycle(Node* node, vector<Node*>* stack, string* err) {
  vector<Node*>::reverse_iterator ri =
      find(stack->rbegin(), stack->rend(), node);
  if (ri == stack->rend())
    return false;

  // Add this node onto the stack to make it clearer where the loop
  // is.
  stack->push_back(node);

  vector<Node*>::iterator start = find(stack->begin(), stack->end(), node);
  *err = "dependency cycle: ";
  for (vector<Node*>::iterator i = start; i != stack->end(); ++i) {
    if (i != start)
      err->append(" -> ");
    err->append((*i)->file_->path_);
  }
  return true;
}

Edge* Plan::FindWork() {
  if (ready_.empty())
    return NULL;
  set<Edge*>::iterator i = ready_.begin();
  Edge* edge = *i;
  ready_.erase(i);
  return edge;
}

void Plan::EdgeFinished(Edge* edge) {
  want_.erase(edge);

  // Check off any nodes we were waiting for with this edge.
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    NodeFinished(*i);
  }
}

void Plan::NodeFinished(Node* node) {
  // See if we we want any edges from this node.
  for (vector<Edge*>::iterator i = node->out_edges_.begin();
       i != node->out_edges_.end(); ++i) {
    if (want_.find(*i) != want_.end()) {
      // See if the edge is now ready.
      bool ready = true;
      for (vector<Node*>::iterator j = (*i)->inputs_.begin();
           j != (*i)->inputs_.end(); ++j) {
        if ((*j)->dirty()) {
          ready = false;
          break;
        }
      }
      if (ready)
        ready_.insert(*i);
    }
  }
}

void Plan::Dump() {
  printf("pending: %d\n", (int)want_.size());
  for (set<Edge*>::iterator i = want_.begin(); i != want_.end(); ++i) {
    (*i)->Dump();
  }
  printf("ready: %d\n", (int)ready_.size());
}

struct RealCommandRunner : public CommandRunner {
  RealCommandRunner(const BuildConfig& config) : config_(config) {}
  virtual ~RealCommandRunner() {}
  virtual bool CanRunMore();
  virtual bool StartCommand(Edge* edge);
  virtual bool WaitForCommands();
  virtual Edge* NextFinishedCommand(bool* success);

  const BuildConfig& config_;
  SubprocessSet subprocs_;
  map<Subprocess*, Edge*> subproc_to_edge_;
};

bool RealCommandRunner::CanRunMore() {
  return ((int)subprocs_.running_.size()) < config_.parallelism;
}

bool RealCommandRunner::StartCommand(Edge* edge) {
  string command = edge->EvaluateCommand();
  Subprocess* subproc = new Subprocess;
  subproc_to_edge_.insert(make_pair(subproc, edge));
  if (!subproc->Start(command))
    return false;

  subprocs_.Add(subproc);
  return true;
}

bool RealCommandRunner::WaitForCommands() {
  if (subprocs_.running_.empty())
    return false;

  while (subprocs_.finished_.empty()) {
    subprocs_.DoWork();
  }
  return true;
}

Edge* RealCommandRunner::NextFinishedCommand(bool* success) {
  Subprocess* subproc = subprocs_.NextFinished();
  if (!subproc)
    return NULL;

  *success = subproc->Finish();

  map<Subprocess*, Edge*>::iterator i = subproc_to_edge_.find(subproc);
  Edge* edge = i->second;
  subproc_to_edge_.erase(i);

  if (!*success ||
      !subproc->stdout_.buf_.empty() ||
      !subproc->stderr_.buf_.empty()) {
    // Print the command that is spewing before printing its output.
    // Print the full command when it failed, otherwise the short name if
    // available.
    string to_print = edge->GetDescription();
    if (to_print.empty() ||
        config_.verbosity == BuildConfig::VERBOSE ||
        !*success) {
      to_print = edge->EvaluateCommand();
    }

    printf("\n%s%s\n", *success ? "" : "FAILED: ", to_print.c_str());
    if (!subproc->stdout_.buf_.empty())
      printf("%s\n", subproc->stdout_.buf_.c_str());
    if (!subproc->stderr_.buf_.empty())
      printf("%s\n", subproc->stderr_.buf_.c_str());
  }

  delete subproc;
  return edge;
}

struct DryRunCommandRunner : public CommandRunner {
  virtual ~DryRunCommandRunner() {}
  virtual bool CanRunMore() {
    return true;
  }
  virtual bool StartCommand(Edge* edge) {
    finished_.push(edge);
    return true;
  }
  virtual bool WaitForCommands() {
    return true;
  }
  virtual Edge* NextFinishedCommand(bool* success) {
    if (finished_.empty())
      return NULL;
    *success = true;
    Edge* edge = finished_.front();
    finished_.pop();
    return edge;
  }

  queue<Edge*> finished_;
};

Builder::Builder(State* state, const BuildConfig& config)
    : state_(state) {
  disk_interface_ = new RealDiskInterface;
  if (config.dry_run)
    command_runner_ = new DryRunCommandRunner;
  else
    command_runner_ = new RealCommandRunner(config);
  status_ = new BuildStatus;
  status_->verbosity_ = config.verbosity;
  log_ = state->build_log_;
}

Node* Builder::AddTarget(const string& name, string* err) {
  Node* node = state_->LookupNode(name);
  if (!node) {
    *err = "unknown target: '" + name + "'";
    return NULL;
  }
  node->file_->StatIfNecessary(disk_interface_);
  if (node->in_edge_) {
    if (!node->in_edge_->RecomputeDirty(state_, disk_interface_, err))
      return NULL;
  }
  if (!node->dirty_)
    return NULL;  // Intentionally no error.

  if (!plan_.AddTarget(node, err))
    return NULL;
  return node;
}

bool Builder::Build(string* err) {
  if (!plan_.more_to_do()) {
    *err = "no work to do";
    return true;
  }

  status_->PlanHasTotalEdges(plan_.command_edge_count());
  while (plan_.more_to_do()) {
    while (command_runner_->CanRunMore()) {
      Edge* edge = plan_.FindWork();
      if (!edge)
        break;

      if (!StartEdge(edge, err))
        return false;

      if (edge->is_phony())
        FinishEdge(edge);
    }

    if (!plan_.more_to_do())
      break;

    bool success;
    if (Edge* edge = command_runner_->NextFinishedCommand(&success)) {
      if (!success) {
        *err = "subcommand failed";
        return false;
      }
      FinishEdge(edge);
    } else {
      if (!command_runner_->WaitForCommands()) {
        *err = "stuck [this is a bug]";
        return false;
      }
    }
  }

  return true;
}

bool Builder::StartEdge(Edge* edge, string* err) {
  if (edge->is_phony())
    return true;

  status_->BuildEdgeStarted(edge);

  // Create directories necessary for outputs.
  // XXX: this will block; do we care?
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    if (!disk_interface_->MakeDirs((*i)->file_->path_))
      return false;
  }

  // Compute command and start it.
  string command = edge->EvaluateCommand();
  if (!command_runner_->StartCommand(edge)) {
    err->assign("command '" + command + "' failed.");
    return false;
  }

  return true;
}

void Builder::FinishEdge(Edge* edge) {
  for (vector<Node*>::iterator i = edge->outputs_.begin();
       i != edge->outputs_.end(); ++i) {
    // XXX check that the output actually changed
    // XXX just notify node and have it propagate?
    (*i)->dirty_ = false;
  }
  plan_.EdgeFinished(edge);

  if (edge->is_phony())
    return;

  int ms = status_->BuildEdgeFinished(edge);
  if (log_)
    log_->RecordCommand(edge, ms);
}
<|endoftext|>


<commit_before>//
// Screen_HX8353E.cpp
// Library C++ code
// ----------------------------------
// Developed with embedXcode
// http://embedXcode.weebly.com
//
// Project new_screen_HX8353
//
// Created by Rei VILO, mars 07, 2013 09:21
// embedXcode.weebly.com
//
// Apr 25, 2014
// Support for new LaunchPads with
// . MSP430F5529
// . LM4F120H5QR TM4C123GH6PM
// . TM4C1294NCPDT TM4C1294XNCZAD
//
//
// Copyright © Rei VILO, 2013-2014
// License CC = BY NC SA
//
// See Screen_HX8353E.h and ReadMe.txt for references
//
// Library header
#include "Screen_HX8353E.h"
///
#define HX8353E_WIDTH  128
#define HX8353E_HEIGHT 128
#define HX8353E_MADCTL_MY  0x80
#define HX8353E_MADCTL_MX  0x40
#define HX8353E_MADCTL_MV  0x20
#define HX8353E_MADCTL_ML  0x10
#define HX8353E_MADCTL_RGB 0x08
#define HX8353E_MADCTL_MH  0x04
#define HX8353E_NOP     0x00
#define HX8353E_SWRESET 0x01
#define HX8353E_RDDID   0x04
#define HX8353E_RDDST   0x09
#define HX8353E_SLPIN   0x10
#define HX8353E_SLPOUT  0x11
#define HX8353E_PTLON   0x12
#define HX8353E_NORON   0x13
#define HX8353E_INVOFF  0x20
#define HX8353E_INVON   0x21
#define HX8353E_GAMSET  0x26
#define HX8353E_DISPOFF 0x28
#define HX8353E_DISPON  0x29
#define HX8353E_CASET   0x2A
#define HX8353E_RASET   0x2B
#define HX8353E_RAMWR   0x2C
#define HX8353E_RGBSET  0x2d
#define HX8353E_RAMRD   0x2E
#define HX8353E_PTLAR   0x30
#define HX8353E_MADCTL  0x36
#define HX8353E_COLMOD  0x3A
#define HX8353E_SETPWCTR 0xB1
#define HX8353E_SETDISPL 0xB2
#define HX8353E_FRMCTR3  0xB3
#define HX8353E_SETCYC   0xB4
#define HX8353E_SETBGP   0xb5
#define HX8353E_SETVCOM  0xB6
#define HX8353E_SETSTBA  0xC0
#define HX8353E_SETID    0xC3
#define HX8353E_GETHID   0xd0
#define HX8353E_SETGAMMA 0xE0
Screen_HX8353E::Screen_HX8353E() {
#if defined(__LM4F120H5QR__) || defined(__MSP430F5529__) || defined(__TM4C123GH6PM__) || defined(__TM4C1294NCPDT__) || defined(__TM4C1294XNCZAD__)
    _pinReset          = 17;
    _pinDataCommand    = 31;
    _pinChipSelect     = 13;
    _pinBacklight      = NULL;
#else
#error Platform not supported
#endif
}
Screen_HX8353E::Screen_HX8353E(uint8_t resetPin, uint8_t dataCommandPin, uint8_t chipSelectPin, uint8_t backlightPin)
{
    _pinReset = resetPin;
    _pinDataCommand = dataCommandPin;
    _pinChipSelect = chipSelectPin;
    _pinBacklight = backlightPin;
};
void Screen_HX8353E::begin()
{
#if defined(__LM4F120H5QR__)
    SPI.setModule(2);
#endif
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV2);
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
    if (_pinReset!=NULL) pinMode(_pinReset, OUTPUT);
    if (_pinBacklight!=NULL) pinMode(_pinBacklight, OUTPUT);
    pinMode(_pinDataCommand, OUTPUT);
    pinMode(_pinChipSelect, OUTPUT);
    if (_pinBacklight!=NULL) digitalWrite(_pinBacklight, HIGH);
    if (_pinReset!=NULL) digitalWrite(_pinReset, 1);
    delay(100);
    if (_pinReset!=NULL) digitalWrite(_pinReset, 0);
    delay(50);
    if (_pinReset!=NULL) digitalWrite(_pinReset, 1);
    delay(120);
    _writeCommand(HX8353E_SWRESET);
    delay(150);
    _writeCommand(HX8353E_SLPOUT);
    delay(200);
    _writeRegister(HX8353E_GAMSET, 0x04);
    _writeCommand(HX8353E_SETPWCTR);
    _writeData88(0x0A, 0x14);
    _writeCommand(HX8353E_SETSTBA);
    _writeData88(0x0A, 0x00);
    _writeRegister(HX8353E_COLMOD, 0x05);
    delay(10);
    _writeRegister(HX8353E_MADCTL, HX8353E_MADCTL_RGB);
    _writeCommand(HX8353E_CASET);
    _writeData8888(0x00, 0x00, 0x00, 0x79);
    _writeCommand(HX8353E_RASET);
    _writeData8888(0x00, 0x00, 0x00, 0x79);
    _writeCommand(HX8353E_NORON);
    delay(10);
    _writeCommand(HX8353E_DISPON);
    delay(120);
    _writeCommand(HX8353E_RAMWR);
    setBacklight(true);
    setOrientation(0);
    _screenWidth  = HX8353E_WIDTH;
    _screenHeigth = HX8353E_HEIGHT;
    _penSolid  = false;
    _fontSolid = true;
    _flagRead  = false;
    _touchTrim = 0;
    clear();
}
String Screen_HX8353E::WhoAmI()
{
    return "LCD MKII BoosterPack";
}
void Screen_HX8353E::invert(boolean flag)
{
    _writeCommand(flag ? HX8353E_INVON : HX8353E_INVOFF);
}
void Screen_HX8353E::setBacklight(boolean flag)
{
    if (_pinBacklight!=NULL) digitalWrite(_pinBacklight, flag);
}
void Screen_HX8353E::setDisplay(boolean flag)
{
    if (_pinBacklight!=NULL) setBacklight(flag);
}
void Screen_HX8353E::setOrientation(uint8_t orientation)
{
    _orientation = orientation % 4;
    _writeCommand(HX8353E_MADCTL);
    switch (_orientation) {
        case 0:
            _writeData(HX8353E_MADCTL_MX | HX8353E_MADCTL_MY | HX8353E_MADCTL_RGB);
            break;
        case 1:
            _writeData(HX8353E_MADCTL_MY | HX8353E_MADCTL_MV | HX8353E_MADCTL_RGB);
            break;
        case 2:
            _writeData(HX8353E_MADCTL_RGB);
            break;
        case 3:
            _writeData(HX8353E_MADCTL_MX | HX8353E_MADCTL_MV | HX8353E_MADCTL_RGB);
            break;
    }
}
void Screen_HX8353E::_fastFill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t colour)
{
    if (x1 > x2) _swap(x1, x2);
    if (y1 > y2) _swap(y1, y2);
    _setWindow(x1, y1, x2, y2);
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    uint8_t hi = highByte(colour);
    uint8_t lo = lowByte(colour);
    for (uint32_t t=(uint32_t)(y2-y1+1)*(x2-x1+1); t>0; t--) {
        SPI.transfer(hi);
        SPI.transfer(lo);
    }
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_setPoint(uint16_t x1, uint16_t y1, uint16_t colour)
{
    if( (x1 < 0) || (x1 >= screenSizeX()) || (y1 < 0) || (y1 >= screenSizeY()) ) return;
    _setWindow(x1, y1, x1+1, y1+1);
    _writeData16(colour);
}
void Screen_HX8353E::_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
    switch (_orientation) {
        case 0:
            x0 += 2;
            y0 += 3;
            x1 += 2;
            y1 += 3;
            break;
        case 1:
            x0 += 3;
            y0 += 2;
            x1 += 3;
            y1 += 2;
            break;
        case 2:
            x0 += 2;
            y0 += 1;
            x1 += 2;
            y1 += 1;
            break;
        case 3:
            x0 += 1;
            y0 += 2;
            x1 += 1;
            y1 += 2;
            break;
        default:
            break;
    }
    _writeCommand(HX8353E_CASET);
    _writeData16(x0);
    _writeData16(x1);
    _writeCommand(HX8353E_RASET);
    _writeData16(y0);
    _writeData16(y1);
    _writeCommand(HX8353E_RAMWR);
}
void Screen_HX8353E::_writeRegister(uint8_t command8, uint8_t data8)
{
    _writeCommand(command8);
    _writeData(data8);
}
void Screen_HX8353E::_writeCommand(uint8_t command8)
{
    digitalWrite(_pinDataCommand, LOW);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(command8);
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData(uint8_t data8)
{
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(data8);
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData16(uint16_t data16)
{
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(highByte(data16));
    SPI.transfer(lowByte(data16));
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData88(uint8_t dataHigh8, uint8_t dataLow8)
{
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(dataHigh8);
    SPI.transfer(dataLow8);
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData8888(uint8_t dataHigh8, uint8_t dataLow8, uint8_t data8_3, uint8_t data8_4)
{
    _writeData(dataHigh8);
    _writeData(dataLow8);
    _writeData(data8_3);
    _writeData(data8_4);
}
void Screen_HX8353E::_getRawTouch(uint16_t &x0, uint16_t &y0, uint16_t &z0)
{
    x0 = 0;
    y0 = 0;
    z0 = 0;
}
<commit_msg>Fix compilation errors for EduBPMKII_Screen<commit_after>//
// Screen_HX8353E.cpp
// Library C++ code
// ----------------------------------
// Developed with embedXcode
// http://embedXcode.weebly.com
//
// Project new_screen_HX8353
//
// Created by Rei VILO, mars 07, 2013 09:21
// embedXcode.weebly.com
//
// Apr 25, 2014
// Support for new LaunchPads with
// . MSP430F5529
// . LM4F120H5QR TM4C123GH6PM
// . TM4C1294NCPDT TM4C1294XNCZAD
//
//
// Copyright © Rei VILO, 2013-2014
// License CC = BY NC SA
//
// See Screen_HX8353E.h and ReadMe.txt for references
//
// Library header
#include "Screen_HX8353E.h"
///
#define HX8353E_WIDTH  128
#define HX8353E_HEIGHT 128
#define HX8353E_MADCTL_MY  0x80
#define HX8353E_MADCTL_MX  0x40
#define HX8353E_MADCTL_MV  0x20
#define HX8353E_MADCTL_ML  0x10
#define HX8353E_MADCTL_RGB 0x08
#define HX8353E_MADCTL_MH  0x04
#define HX8353E_NOP     0x00
#define HX8353E_SWRESET 0x01
#define HX8353E_RDDID   0x04
#define HX8353E_RDDST   0x09
#define HX8353E_SLPIN   0x10
#define HX8353E_SLPOUT  0x11
#define HX8353E_PTLON   0x12
#define HX8353E_NORON   0x13
#define HX8353E_INVOFF  0x20
#define HX8353E_INVON   0x21
#define HX8353E_GAMSET  0x26
#define HX8353E_DISPOFF 0x28
#define HX8353E_DISPON  0x29
#define HX8353E_CASET   0x2A
#define HX8353E_RASET   0x2B
#define HX8353E_RAMWR   0x2C
#define HX8353E_RGBSET  0x2d
#define HX8353E_RAMRD   0x2E
#define HX8353E_PTLAR   0x30
#define HX8353E_MADCTL  0x36
#define HX8353E_COLMOD  0x3A
#define HX8353E_SETPWCTR 0xB1
#define HX8353E_SETDISPL 0xB2
#define HX8353E_FRMCTR3  0xB3
#define HX8353E_SETCYC   0xB4
#define HX8353E_SETBGP   0xb5
#define HX8353E_SETVCOM  0xB6
#define HX8353E_SETSTBA  0xC0
#define HX8353E_SETID    0xC3
#define HX8353E_GETHID   0xd0
#define HX8353E_SETGAMMA 0xE0
Screen_HX8353E::Screen_HX8353E() {
#if defined(__MSP432P401R__) || defined(__LM4F120H5QR__) || defined(__MSP430F5529__) || defined(__TM4C123GH6PM__) || defined(__TM4C1294NCPDT__) || defined(__TM4C1294XNCZAD__)
    _pinReset          = 17;
    _pinDataCommand    = 31;
    _pinChipSelect     = 13;
    _pinBacklight      = 0;
#else
#error Platform not supported
#endif
}
Screen_HX8353E::Screen_HX8353E(uint8_t resetPin, uint8_t dataCommandPin, uint8_t chipSelectPin, uint8_t backlightPin)
{
    _pinReset = resetPin;
    _pinDataCommand = dataCommandPin;
    _pinChipSelect = chipSelectPin;
    _pinBacklight = backlightPin;
};
void Screen_HX8353E::begin()
{
#if defined(__LM4F120H5QR__)
    SPI.setModule(2);
#endif
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV2);
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
    if (_pinReset!=0) pinMode(_pinReset, OUTPUT);
    if (_pinBacklight!=0) pinMode(_pinBacklight, OUTPUT);
    pinMode(_pinDataCommand, OUTPUT);
    pinMode(_pinChipSelect, OUTPUT);
    if (_pinBacklight!=0) digitalWrite(_pinBacklight, HIGH);
    if (_pinReset!=0) digitalWrite(_pinReset, 1);
    delay(100);
    if (_pinReset!=0) digitalWrite(_pinReset, 0);
    delay(50);
    if (_pinReset!=0) digitalWrite(_pinReset, 1);
    delay(120);
    _writeCommand(HX8353E_SWRESET);
    delay(150);
    _writeCommand(HX8353E_SLPOUT);
    delay(200);
    _writeRegister(HX8353E_GAMSET, 0x04);
    _writeCommand(HX8353E_SETPWCTR);
    _writeData88(0x0A, 0x14);
    _writeCommand(HX8353E_SETSTBA);
    _writeData88(0x0A, 0x00);
    _writeRegister(HX8353E_COLMOD, 0x05);
    delay(10);
    _writeRegister(HX8353E_MADCTL, HX8353E_MADCTL_RGB);
    _writeCommand(HX8353E_CASET);
    _writeData8888(0x00, 0x00, 0x00, 0x79);
    _writeCommand(HX8353E_RASET);
    _writeData8888(0x00, 0x00, 0x00, 0x79);
    _writeCommand(HX8353E_NORON);
    delay(10);
    _writeCommand(HX8353E_DISPON);
    delay(120);
    _writeCommand(HX8353E_RAMWR);
    setBacklight(true);
    setOrientation(0);
    _screenWidth  = HX8353E_WIDTH;
    _screenHeigth = HX8353E_HEIGHT;
    _penSolid  = false;
    _fontSolid = true;
    _flagRead  = false;
    _touchTrim = 0;
    clear();
}
String Screen_HX8353E::WhoAmI()
{
    return "LCD MKII BoosterPack";
}
void Screen_HX8353E::invert(boolean flag)
{
    _writeCommand(flag ? HX8353E_INVON : HX8353E_INVOFF);
}
void Screen_HX8353E::setBacklight(boolean flag)
{
    if (_pinBacklight!=0) digitalWrite(_pinBacklight, flag);
}
void Screen_HX8353E::setDisplay(boolean flag)
{
    if (_pinBacklight!=0) setBacklight(flag);
}
void Screen_HX8353E::setOrientation(uint8_t orientation)
{
    _orientation = orientation % 4;
    _writeCommand(HX8353E_MADCTL);
    switch (_orientation) {
        case 0:
            _writeData(HX8353E_MADCTL_MX | HX8353E_MADCTL_MY | HX8353E_MADCTL_RGB);
            break;
        case 1:
            _writeData(HX8353E_MADCTL_MY | HX8353E_MADCTL_MV | HX8353E_MADCTL_RGB);
            break;
        case 2:
            _writeData(HX8353E_MADCTL_RGB);
            break;
        case 3:
            _writeData(HX8353E_MADCTL_MX | HX8353E_MADCTL_MV | HX8353E_MADCTL_RGB);
            break;
    }
}
void Screen_HX8353E::_fastFill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t colour)
{
    if (x1 > x2) _swap(x1, x2);
    if (y1 > y2) _swap(y1, y2);
    _setWindow(x1, y1, x2, y2);
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    uint8_t hi = highByte(colour);
    uint8_t lo = lowByte(colour);
    for (uint32_t t=(uint32_t)(y2-y1+1)*(x2-x1+1); t>0; t--) {
        SPI.transfer(hi);
        SPI.transfer(lo);
    }
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_setPoint(uint16_t x1, uint16_t y1, uint16_t colour)
{
    if( (x1 < 0) || (x1 >= screenSizeX()) || (y1 < 0) || (y1 >= screenSizeY()) ) return;
    _setWindow(x1, y1, x1+1, y1+1);
    _writeData16(colour);
}
void Screen_HX8353E::_setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
{
    switch (_orientation) {
        case 0:
            x0 += 2;
            y0 += 3;
            x1 += 2;
            y1 += 3;
            break;
        case 1:
            x0 += 3;
            y0 += 2;
            x1 += 3;
            y1 += 2;
            break;
        case 2:
            x0 += 2;
            y0 += 1;
            x1 += 2;
            y1 += 1;
            break;
        case 3:
            x0 += 1;
            y0 += 2;
            x1 += 1;
            y1 += 2;
            break;
        default:
            break;
    }
    _writeCommand(HX8353E_CASET);
    _writeData16(x0);
    _writeData16(x1);
    _writeCommand(HX8353E_RASET);
    _writeData16(y0);
    _writeData16(y1);
    _writeCommand(HX8353E_RAMWR);
}
void Screen_HX8353E::_writeRegister(uint8_t command8, uint8_t data8)
{
    _writeCommand(command8);
    _writeData(data8);
}
void Screen_HX8353E::_writeCommand(uint8_t command8)
{
    digitalWrite(_pinDataCommand, LOW);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(command8);
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData(uint8_t data8)
{
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(data8);
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData16(uint16_t data16)
{
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(highByte(data16));
    SPI.transfer(lowByte(data16));
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData88(uint8_t dataHigh8, uint8_t dataLow8)
{
    digitalWrite(_pinDataCommand, HIGH);
    digitalWrite(_pinChipSelect, LOW);
    SPI.transfer(dataHigh8);
    SPI.transfer(dataLow8);
    digitalWrite(_pinChipSelect, HIGH);
}
void Screen_HX8353E::_writeData8888(uint8_t dataHigh8, uint8_t dataLow8, uint8_t data8_3, uint8_t data8_4)
{
    _writeData(dataHigh8);
    _writeData(dataLow8);
    _writeData(data8_3);
    _writeData(data8_4);
}
void Screen_HX8353E::_getRawTouch(uint16_t &x0, uint16_t &y0, uint16_t &z0)
{
    x0 = 0;
    y0 = 0;
    z0 = 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: indexentrysupplier_ja_phonetic.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $Date$
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#define INDEXENTRYSUPPLIER_ja_phonetic
#include <indexentrysupplier_asian.hxx>
#include <data/indexdata_ja_phonetic.h>
#include <string.h>

namespace com { namespace sun { namespace star { namespace i18n {

rtl::OUString SAL_CALL IndexEntrySupplier_ja_phonetic::getIndexCharacter( const rtl::OUString& rIndexEntry,
    const lang::Locale& rLocale, const rtl::OUString& rSortAlgorithm )
    throw (com::sun::star::uno::RuntimeException)
{
    return IndexEntrySupplier_CJK::getIndexString(rIndexEntry.toChar(), idx,
            strstr(implementationName, "syllable") ? syllable : consonant);
}

rtl::OUString SAL_CALL IndexEntrySupplier_ja_phonetic::getIndexKey( const rtl::OUString& IndexEntry,
    const rtl::OUString& PhoneticEntry, const lang::Locale& rLocale )
    throw (com::sun::star::uno::RuntimeException)
{
    return IndexEntrySupplier_CJK::getIndexString(
        PhoneticEntry.getLength() > 0 ? PhoneticEntry.toChar() : IndexEntry.toChar(), idx,
            strstr(implementationName, "syllable") ? syllable : consonant);
}

sal_Int16 SAL_CALL IndexEntrySupplier_ja_phonetic::compareIndexEntry(
    const rtl::OUString& IndexEntry1, const rtl::OUString& PhoneticEntry1, const lang::Locale& rLocale1,
    const rtl::OUString& IndexEntry2, const rtl::OUString& PhoneticEntry2, const lang::Locale& rLocale2 )
    throw (com::sun::star::uno::RuntimeException)
{
    sal_Int16 result =  collator->compareString(
        IndexEntrySupplier_ja_phonetic::getIndexKey(IndexEntry1, PhoneticEntry1, rLocale1),
        IndexEntrySupplier_ja_phonetic::getIndexKey(IndexEntry2, PhoneticEntry2, rLocale2));

    if (result == 0)
        return IndexEntrySupplier_Common::compareIndexEntry(
                    IndexEntry1, PhoneticEntry1, rLocale1,
                    IndexEntry2, PhoneticEntry2, rLocale2);
    return result;
}

static sal_Char first[] = "ja_phonetic (alphanumeric first)";
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_first_by_syllable::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(first), rLocale, collatorOptions) == 0;
}
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_first_by_consonant::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(first), rLocale, collatorOptions) == 0;
}

static sal_Char last[] = "ja_phonetic (alphanumeric last)";
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_last_by_syllable::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(last), rLocale, collatorOptions) == 0;
}
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_last_by_consonant::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(last), rLocale, collatorOptions) == 0;
}

} } } }
<commit_msg>INTEGRATION: CWS ooo19126 (1.7.66); FILE MERGED 2005/09/05 17:47:38 rt 1.7.66.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: indexentrysupplier_ja_phonetic.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 17:10:14 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#define INDEXENTRYSUPPLIER_ja_phonetic
#include <indexentrysupplier_asian.hxx>
#include <data/indexdata_ja_phonetic.h>
#include <string.h>

namespace com { namespace sun { namespace star { namespace i18n {

rtl::OUString SAL_CALL IndexEntrySupplier_ja_phonetic::getIndexCharacter( const rtl::OUString& rIndexEntry,
    const lang::Locale& rLocale, const rtl::OUString& rSortAlgorithm )
    throw (com::sun::star::uno::RuntimeException)
{
    return IndexEntrySupplier_CJK::getIndexString(rIndexEntry.toChar(), idx,
            strstr(implementationName, "syllable") ? syllable : consonant);
}

rtl::OUString SAL_CALL IndexEntrySupplier_ja_phonetic::getIndexKey( const rtl::OUString& IndexEntry,
    const rtl::OUString& PhoneticEntry, const lang::Locale& rLocale )
    throw (com::sun::star::uno::RuntimeException)
{
    return IndexEntrySupplier_CJK::getIndexString(
        PhoneticEntry.getLength() > 0 ? PhoneticEntry.toChar() : IndexEntry.toChar(), idx,
            strstr(implementationName, "syllable") ? syllable : consonant);
}

sal_Int16 SAL_CALL IndexEntrySupplier_ja_phonetic::compareIndexEntry(
    const rtl::OUString& IndexEntry1, const rtl::OUString& PhoneticEntry1, const lang::Locale& rLocale1,
    const rtl::OUString& IndexEntry2, const rtl::OUString& PhoneticEntry2, const lang::Locale& rLocale2 )
    throw (com::sun::star::uno::RuntimeException)
{
    sal_Int16 result =  collator->compareString(
        IndexEntrySupplier_ja_phonetic::getIndexKey(IndexEntry1, PhoneticEntry1, rLocale1),
        IndexEntrySupplier_ja_phonetic::getIndexKey(IndexEntry2, PhoneticEntry2, rLocale2));

    if (result == 0)
        return IndexEntrySupplier_Common::compareIndexEntry(
                    IndexEntry1, PhoneticEntry1, rLocale1,
                    IndexEntry2, PhoneticEntry2, rLocale2);
    return result;
}

static sal_Char first[] = "ja_phonetic (alphanumeric first)";
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_first_by_syllable::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(first), rLocale, collatorOptions) == 0;
}
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_first_by_consonant::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(first), rLocale, collatorOptions) == 0;
}

static sal_Char last[] = "ja_phonetic (alphanumeric last)";
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_last_by_syllable::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(last), rLocale, collatorOptions) == 0;
}
sal_Bool SAL_CALL IndexEntrySupplier_ja_phonetic_alphanumeric_last_by_consonant::loadAlgorithm(
    const com::sun::star::lang::Locale& rLocale, const rtl::OUString& SortAlgorithm,
    sal_Int32 collatorOptions ) throw (com::sun::star::uno::RuntimeException)
{
    aLocale = rLocale;
    return collator->loadCollatorAlgorithm(rtl::OUString::createFromAscii(last), rLocale, collatorOptions) == 0;
}

} } } }
<|endoftext|>


<commit_before>#include <stdio.h>

#include <spikehw.h>

SpikeHw *spikeHw;

int main(int argc, const char **argv)
{
    spikeHw = new SpikeHw();
    // not needed yet
    //spikeHw->setupDma(memfd);

    // query mmcm and interrupt status
    spikeHw->status();

    // read boot rom
    uint32_t firstword;
    spikeHw->read(0x000000 + 0x000, (uint8_t *)&firstword);
    fprintf(stderr, "First word of boot ROM %08x (expected %08x)\n", firstword, 0x00001137);

    // read ethernet identification register
    uint32_t id;
    spikeHw->read(0x180000 + 0x4f8, (uint8_t *)&id);
    fprintf(stderr, "AXI Ethernet Identification %08x (expected %08x)\n", id, 0x09000000);

    // put flash in query mode
    spikeHw->setFlashParameters(50); // divides clock by 50
    uint32_t values[4] = { 0x98 };
    spikeHw->writeFlash(0x00aa, (uint8_t *)&values[0]);
    spikeHw->readFlash(0x0040, (uint8_t *)&values[1]);
    spikeHw->readFlash(0x0042, (uint8_t *)&values[2]);
    spikeHw->readFlash(0x0044, (uint8_t *)&values[3]);
    fprintf(stderr, "Query flash %02x.%02x.%02x %c%c%c (expected QRY)\n", values[1], values[2], values[3], values[1], values[2], values[3]);

    return 0;
}
<commit_msg>use the by-16 rather than by-32 CFI addresses<commit_after>#include <stdio.h>

#include <spikehw.h>

SpikeHw *spikeHw;

int main(int argc, const char **argv)
{
    spikeHw = new SpikeHw();
    // not needed yet
    //spikeHw->setupDma(memfd);

    // query mmcm and interrupt status
    spikeHw->status();

    // read boot rom
    uint32_t firstword;
    spikeHw->read(0x000000 + 0x000, (uint8_t *)&firstword);
    fprintf(stderr, "First word of boot ROM %08x (expected %08x)\n", firstword, 0x00001137);

    // read ethernet identification register
    uint32_t id;
    spikeHw->read(0x180000 + 0x4f8, (uint8_t *)&id);
    fprintf(stderr, "AXI Ethernet Identification %08x (expected %08x)\n", id, 0x09000000);

    // put flash in query mode
    spikeHw->setFlashParameters(50); // divides clock by 50
    uint32_t values[4] = { 0x98 };
    spikeHw->writeFlash(0x00aa, (uint8_t *)&values[0]);
    spikeHw->readFlash(0x0020, (uint8_t *)&values[1]);
    spikeHw->readFlash(0x0022, (uint8_t *)&values[2]);
    spikeHw->readFlash(0x0024, (uint8_t *)&values[3]);
    fprintf(stderr, "Query flash %02x.%02x.%02x %c%c%c (expected QRY)\n", values[1], values[2], values[3], values[1], values[2], values[3]);

    return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include "acmacs-base/string.hh"
#include "acmacs-base/fmt.hh"
#include "acmacs-base/to-string.hh"
#include "acmacs-base/float.hh"
#include "acmacs-base/range.hh"

// Simplified version of https://github.com/joboccara/NamedType
// Also see https://github.com/Enhex/phantom_type

// ----------------------------------------------------------------------

namespace acmacs
{
    template <typename T, typename Tag> class named_t
    {
      public:
        using value_type = T;

        explicit constexpr named_t() = default;
        template <typename T2> explicit constexpr named_t(T2&& value) : value_(std::forward<T2>(value)) {}

        // template <typename T2, typename = std::enable_if_t<std::is_same_v<T, size_t>>>
        //     explicit constexpr named_t(T2 value) : value_(static_cast<T>(value)) {}

        // template <typename TT> using is_not_reference_t = typename std::enable_if<!std::is_reference<TT>::value, void>::type;
        // explicit constexpr named_t(const T& value) : value_(value) {}
        // explicit constexpr named_t(T&& value) : value_(std::move(value)) {}
        // template <typename T2 = T, typename = is_not_reference_t<T2>> explicit constexpr named_t(T2&& value) : value_(std::move(value)) {}

        constexpr T& get() noexcept { return value_; }
        constexpr const T& get() const noexcept { return value_; }
        constexpr T& operator*() noexcept { return value_; }
        constexpr const T& operator*() const noexcept { return value_; }
        constexpr const T* operator->() const noexcept { return &value_; }
        explicit constexpr operator T&() noexcept { return value_; }
        explicit constexpr operator const T&() const noexcept { return value_; }

      private:
        T value_;
    };

    template <typename T, typename Tag> constexpr bool operator==(const named_t<T, Tag>& lhs, const named_t<T, Tag>& rhs) noexcept { return lhs.get() == rhs.get(); }
    template <typename T, typename Tag> constexpr bool operator!=(const named_t<T, Tag>& lhs, const named_t<T, Tag>& rhs) noexcept { return !operator==(lhs, rhs); }

    template <typename T, typename Tag> inline std::string to_string(const named_t<T, Tag>& nt) { return acmacs::to_string(nt.get()); }

    // ----------------------------------------------------------------------

    template <typename T, typename Tag> class named_number_t : public named_t<T, Tag>
    {
      public:
        template <typename TT> explicit constexpr named_number_t(TT&& value) : named_t<T, Tag>(static_cast<T>(std::forward<TT>(value))) {}

        constexpr auto& operator++()
        {
            ++this->get();
            return *this;
        }
        constexpr auto& operator--()
        {
            --this->get();
            return *this;
        }
    };

    template <typename T, typename Tag> constexpr bool operator<(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return lhs.get() < rhs.get(); }
    template <typename T, typename Tag> constexpr bool operator<=(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return lhs.get() <= rhs.get(); }
    template <typename T, typename Tag> constexpr bool operator>(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return lhs.get() > rhs.get(); }
    template <typename T, typename Tag> constexpr bool operator>=(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return lhs.get() >= rhs.get(); }

    template <typename T, typename Tag> constexpr named_number_t<T, Tag> operator+(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return named_number_t<T, Tag>{lhs.get() + rhs.get()}; }
    template <typename T, typename Tag> constexpr named_number_t<T, Tag> operator-(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return named_number_t<T, Tag>{lhs.get() - rhs.get()}; }
    template <typename T, typename Tag> constexpr named_number_t<T, Tag> operator*(const named_number_t<T, Tag>& lhs, const named_number_t<T, Tag>& rhs) noexcept { return named_number_t<T, Tag>{lhs.get() * rhs.get()}; }
    // no operator/

    // ----------------------------------------------------------------------

    template <typename Tag> class named_size_t : public named_number_t<size_t, Tag>
    {
      public:
        using named_number_t<size_t, Tag>::named_number_t;
    };

    template <typename Tag> constexpr bool operator==(const named_size_t<Tag>& lhs, const named_size_t<Tag>& rhs) noexcept { return lhs.get() == rhs.get(); }
    template <typename Tag> constexpr bool operator!=(const named_size_t<Tag>& lhs, const named_size_t<Tag>& rhs) noexcept { return !operator==(lhs, rhs); }

    template <typename Tag> range(int, named_size_t<Tag>)->range<named_size_t<Tag>>;
    template <typename Tag> range(size_t, named_size_t<Tag>)->range<named_size_t<Tag>>;
    template <typename Tag> range(named_size_t<Tag>)->range<named_size_t<Tag>>;
    template <typename Tag> range(named_size_t<Tag>, named_size_t<Tag>)->range<named_size_t<Tag>>;

    // ----------------------------------------------------------------------

    template <typename Tag> class named_double_t : public named_number_t<double, Tag>
    {
      public:
        using named_number_t<double, Tag>::named_number_t;
    };

    template <typename Tag> constexpr bool operator==(const named_double_t<Tag>& lhs, const named_double_t<Tag>& rhs) noexcept { return float_equal(lhs.get(), rhs.get()); }
    template <typename Tag> constexpr bool operator!=(const named_double_t<Tag>& lhs, const named_double_t<Tag>& rhs) noexcept { return !operator==(lhs, rhs); }

    // ----------------------------------------------------------------------

    template <typename Tag> class named_string_t : public named_t<std::string, Tag>
    {
      public:
        using named_t<std::string, Tag>::named_t;

        bool empty() const noexcept { return this->get().empty(); }
        size_t size() const noexcept { return this->get().size(); }
        char operator[](size_t pos) const { return this->get()[pos]; }
        size_t find(const char* s, size_t pos = 0) const noexcept { return this->get().find(s, pos); }
        size_t find(char ch, size_t pos = 0) const noexcept { return this->get().find(ch, pos); }
        constexpr operator std::string_view() const noexcept { return this->get(); }
        int compare(const named_string_t<Tag>& rhs) const { return ::string::compare(this->get(), rhs.get()); }
        void assign(std::string_view source) { this->get().assign(source); }
    };

    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, const named_string_t<T>& rhs) noexcept { return lhs.get() == rhs.get(); }
    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, const std::string& rhs) noexcept { return lhs.get() == rhs; }
    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, const char* rhs) noexcept { return lhs.get() == rhs; }
    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, std::string_view rhs) noexcept { return lhs.get() == rhs; }
    template <typename T, typename R> constexpr bool operator!=(const named_string_t<T>& lhs, R&& rhs) noexcept { return !operator==(lhs, std::forward<R>(rhs)); }
    template <typename T> constexpr bool operator<(const named_string_t<T>& lhs, const named_string_t<T>& rhs) noexcept { return lhs.get() < rhs.get(); }

    // ----------------------------------------------------------------------

    template <typename T, typename Tag> class named_vector_t : public named_t<std::vector<T>, Tag>
    {
      public:
        using value_type = T;
        using named_t<std::vector<T>, Tag>::named_t;

        constexpr auto begin() const { return this->get().begin(); }
        constexpr auto end() const { return this->get().end(); }
        constexpr auto begin() { return this->get().begin(); }
        constexpr auto end() { return this->get().end(); }
        constexpr auto rbegin() { return this->get().rbegin(); }
        constexpr auto rend() { return this->get().rend(); }
        constexpr auto empty() const { return this->get().empty(); }
        constexpr auto size() const { return this->get().size(); }
        constexpr auto operator[](size_t index) const { return this->get()[index]; }
        constexpr auto& operator[](size_t index) { return this->get()[index]; }

        // for std::back_inserter
        constexpr void push_back(const T& val) { this->get().push_back(val); }
        constexpr void push_back(T&& val) { this->get().push_back(std::forward<T>(val)); }

        void remove(const T& val)
        {
            if (const auto found = std::find(begin(), end(), val); found != end())
                this->get().erase(found);
        }

        // set like
        bool exists(const T& val) const { return std::find(begin(), end(), val) != end(); }
        void insert_if_not_present(const T& val)
        {
            if (!exists(val))
                push_back(val);
        }
        void insert_if_not_present(T&& val)
        {
            if (!exist(val))
                push_back(std::forward<T>(val));
        }
        void merge_in(const named_vector_t<T, Tag>& another)
        {
            for (const auto& val : another)
                insert_if_not_present(val);
        }
    };

    template <typename Tag> constexpr bool operator<(const named_vector_t<std::string, Tag>& lhs, const named_vector_t<std::string, Tag>& rhs) noexcept
    {
        const auto sz = std::min(lhs.size(), rhs.size());
        for (size_t i = 0; i < sz; ++i) {
            if (!(lhs[i] == rhs[i]))
                return lhs[i] < rhs[i];
        }
        if (lhs.size() < rhs.size())
            return true;
        return false;
    }

} // namespace acmacs

// ----------------------------------------------------------------------

// template <typename T, typename Tag> struct fmt::formatter<acmacs::named_t<T, Tag>> : fmt::formatter<T> {
//     template <typename FormatCtx> auto format(const acmacs::named_t<T, Tag>& nt, FormatCtx& ctx) { return fmt::formatter<T>::format(nt.get(), ctx); }
// };

template <typename Tag> struct fmt::formatter<acmacs::named_size_t<Tag>> : fmt::formatter<size_t> {
    template <typename FormatCtx> auto format(const acmacs::named_size_t<Tag>& nt, FormatCtx& ctx) { return fmt::formatter<size_t>::format(nt.get(), ctx); }
};

template <typename Tag> struct fmt::formatter<acmacs::named_double_t<Tag>> : fmt::formatter<double> {
    template <typename FormatCtx> auto format(const acmacs::named_double_t<Tag>& nt, FormatCtx& ctx) { return fmt::formatter<double>::format(nt.get(), ctx); }
};

template <typename Tag> struct fmt::formatter<acmacs::named_string_t<Tag>> : fmt::formatter<std::string> {
    template <typename FormatCtx> auto format(const acmacs::named_string_t<Tag>& nt, FormatCtx& ctx) { return fmt::formatter<std::string>::format(nt.get(), ctx); }
};

template <typename T, typename Tag> struct fmt::formatter<acmacs::named_vector_t<T, Tag>> : fmt::formatter<std::vector<T>> {
    template <typename FormatCtx> auto format(const acmacs::named_vector_t<T, Tag>& vec, FormatCtx& ctx) { return fmt::formatter<std::vector<T>>::format(vec.get(), ctx); }
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>named_number_from_string_t<commit_after>#pragma once

#include <variant>

#include "acmacs-base/string.hh"
#include "acmacs-base/fmt.hh"
#include "acmacs-base/to-string.hh"
#include "acmacs-base/float.hh"
#include "acmacs-base/range.hh"

// Simplified version of https://github.com/joboccara/NamedType
// Also see https://github.com/Enhex/phantom_type

// ----------------------------------------------------------------------

namespace acmacs
{
    template <typename T, typename Tag> class named_t
    {
      public:
        using value_type = T;

        explicit constexpr named_t() = default;
        template <typename T2> explicit constexpr named_t(T2&& value) : value_(std::forward<T2>(value)) {}

        // template <typename T2, typename = std::enable_if_t<std::is_same_v<T, size_t>>>
        //     explicit constexpr named_t(T2 value) : value_(static_cast<T>(value)) {}

        // template <typename TT> using is_not_reference_t = typename std::enable_if<!std::is_reference<TT>::value, void>::type;
        // explicit constexpr named_t(const T& value) : value_(value) {}
        // explicit constexpr named_t(T&& value) : value_(std::move(value)) {}
        // template <typename T2 = T, typename = is_not_reference_t<T2>> explicit constexpr named_t(T2&& value) : value_(std::move(value)) {}

        constexpr T& get() noexcept { return value_; }
        constexpr const T& get() const noexcept { return value_; }
        constexpr T& operator*() noexcept { return value_; }
        constexpr const T& operator*() const noexcept { return value_; }
        constexpr const T* operator->() const noexcept { return &value_; }
        explicit constexpr operator T&() noexcept { return value_; }
        explicit constexpr operator const T&() const noexcept { return value_; }

      private:
        T value_;
    };

    template <typename T, typename Tag> constexpr bool operator==(const named_t<T, Tag>& lhs, const named_t<T, Tag>& rhs) noexcept { return lhs.get() == rhs.get(); }
    template <typename T, typename Tag> constexpr bool operator!=(const named_t<T, Tag>& lhs, const named_t<T, Tag>& rhs) noexcept { return !operator==(lhs, rhs); }

    template <typename T, typename Tag> inline std::string to_string(const named_t<T, Tag>& nt) { return acmacs::to_string(nt.get()); }

    // ----------------------------------------------------------------------

    template <typename Number, typename Tag> class named_number_t : public named_t<Number, Tag>
    {
      public:
        template <typename TT> explicit constexpr named_number_t(TT&& value) : named_t<Number, Tag>(static_cast<Number>(std::forward<TT>(value))) {}

        constexpr auto& operator++()
        {
            ++this->get();
            return *this;
        }
        constexpr auto& operator--()
        {
            --this->get();
            return *this;
        }
    };

    template <typename Number, typename Tag> constexpr bool operator<(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return lhs.get() < rhs.get(); }
    template <typename Number, typename Tag> constexpr bool operator<=(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return lhs.get() <= rhs.get(); }
    template <typename Number, typename Tag> constexpr bool operator>(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return lhs.get() > rhs.get(); }
    template <typename Number, typename Tag> constexpr bool operator>=(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return lhs.get() >= rhs.get(); }

    template <typename Number, typename Tag> constexpr named_number_t<Number, Tag> operator+(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return named_number_t<Number, Tag>{lhs.get() + rhs.get()}; }
    template <typename Number, typename Tag> constexpr named_number_t<Number, Tag> operator-(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return named_number_t<Number, Tag>{lhs.get() - rhs.get()}; }
    template <typename Number, typename Tag> constexpr named_number_t<Number, Tag> operator*(const named_number_t<Number, Tag>& lhs, const named_number_t<Number, Tag>& rhs) noexcept { return named_number_t<Number, Tag>{lhs.get() * rhs.get()}; }
    // no operator/

    // ----------------------------------------------------------------------

    template <typename Tag> class named_size_t : public named_number_t<size_t, Tag>
    {
      public:
        using named_number_t<size_t, Tag>::named_number_t;
    };

    template <typename Tag> constexpr bool operator==(const named_size_t<Tag>& lhs, const named_size_t<Tag>& rhs) noexcept { return lhs.get() == rhs.get(); }
    template <typename Tag> constexpr bool operator!=(const named_size_t<Tag>& lhs, const named_size_t<Tag>& rhs) noexcept { return !operator==(lhs, rhs); }

    template <typename Tag> range(int, named_size_t<Tag>)->range<named_size_t<Tag>>;
    template <typename Tag> range(size_t, named_size_t<Tag>)->range<named_size_t<Tag>>;
    template <typename Tag> range(named_size_t<Tag>)->range<named_size_t<Tag>>;
    template <typename Tag> range(named_size_t<Tag>, named_size_t<Tag>)->range<named_size_t<Tag>>;

    // ----------------------------------------------------------------------

    template <typename Tag> class named_double_t : public named_number_t<double, Tag>
    {
      public:
        using named_number_t<double, Tag>::named_number_t;
    };

    template <typename Tag> constexpr bool operator==(const named_double_t<Tag>& lhs, const named_double_t<Tag>& rhs) noexcept { return float_equal(lhs.get(), rhs.get()); }
    template <typename Tag> constexpr bool operator!=(const named_double_t<Tag>& lhs, const named_double_t<Tag>& rhs) noexcept { return !operator==(lhs, rhs); }

    // ----------------------------------------------------------------------

    template <typename Number, typename Tag> class named_number_from_string_t : public named_t<std::variant<Number, std::string_view>, Tag>
    {
      public:
        using base_t = named_t<std::variant<Number, std::string_view>, Tag>;

        template <typename TT> explicit constexpr named_number_from_string_t(TT&& value) : base_t(std::forward<TT>(value)) {}

        Number as_number() const
        {
            return std::visit(
                []<typename Repr>(Repr content) -> Number {
                    if constexpr (std::is_same_v<Repr, Number>)
                        return content;
                    else
                        return string::from_chars<Number>(content);
                },
                base_t::get());
        }

        std::string as_string() const
        {
            return std::visit(
                []<typename Repr>(Repr content) -> std::string {
                    if constexpr (std::is_same_v<Repr, Number>)
                        return acmacs::to_string(content);
                    else
                        return std::string{content};
                },
                base_t::get());
        }
    };

    template <typename Tag> class named_size_t_from_string_t : public named_number_from_string_t<size_t, Tag>
    {
      public:
        using named_number_from_string_t<size_t, Tag>::named_number_from_string_t;
    };

    template <typename Tag> class named_double_from_string_t : public named_number_from_string_t<double, Tag>
    {
      public:
        using named_number_from_string_t<double, Tag>::named_number_from_string_t;
    };

    // ----------------------------------------------------------------------

    template <typename Tag> class named_string_t : public named_t<std::string, Tag>
    {
      public:
        using named_t<std::string, Tag>::named_t;

        bool empty() const noexcept { return this->get().empty(); }
        size_t size() const noexcept { return this->get().size(); }
        char operator[](size_t pos) const { return this->get()[pos]; }
        size_t find(const char* s, size_t pos = 0) const noexcept { return this->get().find(s, pos); }
        size_t find(char ch, size_t pos = 0) const noexcept { return this->get().find(ch, pos); }
        constexpr operator std::string_view() const noexcept { return this->get(); }
        int compare(const named_string_t<Tag>& rhs) const { return ::string::compare(this->get(), rhs.get()); }
        void assign(std::string_view source) { this->get().assign(source); }
    };

    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, const named_string_t<T>& rhs) noexcept { return lhs.get() == rhs.get(); }
    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, const std::string& rhs) noexcept { return lhs.get() == rhs; }
    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, const char* rhs) noexcept { return lhs.get() == rhs; }
    template <typename T> constexpr bool operator==(const named_string_t<T>& lhs, std::string_view rhs) noexcept { return lhs.get() == rhs; }
    template <typename T, typename R> constexpr bool operator!=(const named_string_t<T>& lhs, R&& rhs) noexcept { return !operator==(lhs, std::forward<R>(rhs)); }
    template <typename T> constexpr bool operator<(const named_string_t<T>& lhs, const named_string_t<T>& rhs) noexcept { return lhs.get() < rhs.get(); }

    // ----------------------------------------------------------------------

    template <typename T, typename Tag> class named_vector_t : public named_t<std::vector<T>, Tag>
    {
      public:
        using value_type = T;
        using named_t<std::vector<T>, Tag>::named_t;

        constexpr auto begin() const { return this->get().begin(); }
        constexpr auto end() const { return this->get().end(); }
        constexpr auto begin() { return this->get().begin(); }
        constexpr auto end() { return this->get().end(); }
        constexpr auto rbegin() { return this->get().rbegin(); }
        constexpr auto rend() { return this->get().rend(); }
        constexpr auto empty() const { return this->get().empty(); }
        constexpr auto size() const { return this->get().size(); }
        constexpr auto operator[](size_t index) const { return this->get()[index]; }
        constexpr auto& operator[](size_t index) { return this->get()[index]; }

        // for std::back_inserter
        constexpr void push_back(const T& val) { this->get().push_back(val); }
        constexpr void push_back(T&& val) { this->get().push_back(std::forward<T>(val)); }

        void remove(const T& val)
        {
            if (const auto found = std::find(begin(), end(), val); found != end())
                this->get().erase(found);
        }

        // set like
        bool exists(const T& val) const { return std::find(begin(), end(), val) != end(); }
        void insert_if_not_present(const T& val)
        {
            if (!exists(val))
                push_back(val);
        }
        void insert_if_not_present(T&& val)
        {
            if (!exist(val))
                push_back(std::forward<T>(val));
        }
        void merge_in(const named_vector_t<T, Tag>& another)
        {
            for (const auto& val : another)
                insert_if_not_present(val);
        }
    };

    template <typename Tag> constexpr bool operator<(const named_vector_t<std::string, Tag>& lhs, const named_vector_t<std::string, Tag>& rhs) noexcept
    {
        const auto sz = std::min(lhs.size(), rhs.size());
        for (size_t i = 0; i < sz; ++i) {
            if (!(lhs[i] == rhs[i]))
                return lhs[i] < rhs[i];
        }
        if (lhs.size() < rhs.size())
            return true;
        return false;
    }

} // namespace acmacs

// ----------------------------------------------------------------------

// template <typename T, typename Tag> struct fmt::formatter<acmacs::named_t<T, Tag>> : fmt::formatter<T> {
//     template <typename FormatCtx> auto format(const acmacs::named_t<T, Tag>& nt, FormatCtx& ctx) { return fmt::formatter<T>::format(nt.get(), ctx); }
// };

template <typename Tag> struct fmt::formatter<acmacs::named_size_t<Tag>> : fmt::formatter<size_t> {
    template <typename FormatCtx> auto format(const acmacs::named_size_t<Tag>& nt, FormatCtx& ctx) { return fmt::formatter<size_t>::format(nt.get(), ctx); }
};

template <typename Tag> struct fmt::formatter<acmacs::named_double_t<Tag>> : fmt::formatter<double> {
    template <typename FormatCtx> auto format(const acmacs::named_double_t<Tag>& nt, FormatCtx& ctx) { return fmt::formatter<double>::format(nt.get(), ctx); }
};

template <typename Tag> struct fmt::formatter<acmacs::named_string_t<Tag>> : fmt::formatter<std::string> {
    template <typename FormatCtx> auto format(const acmacs::named_string_t<Tag>& nt, FormatCtx& ctx) { return fmt::formatter<std::string>::format(nt.get(), ctx); }
};

template <typename T, typename Tag> struct fmt::formatter<acmacs::named_vector_t<T, Tag>> : fmt::formatter<std::vector<T>> {
    template <typename FormatCtx> auto format(const acmacs::named_vector_t<T, Tag>& vec, FormatCtx& ctx) { return fmt::formatter<std::vector<T>>::format(vec.get(), ctx); }
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>