<commit_before>// source_file.C -- File source for gnuplot interface
//
// Copyright 2005 Per Abrahamsen and KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy 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 Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "source_file.h"
#include "lexer_data.h"
#include "submodeler.h"
#include "vcheck.h"
#include "mathlib.h"
#include "memutils.h"
#include <sstream>

static int
find_tag (const std::map<std::string,int>& tag_pos,
	  const std::string& tag1,
	  const std::string& tag2)
{
  int result = find_tag (tag_pos, tag1);
  return result < 0 ? find_tag (tag_pos, tag2) : result;
}

struct SourceFile::Filter
{
  const std::string tag;
  const std::vector<std::string> allowed;
  static void load_syntax (Syntax& syntax, AttributeList&);
  explicit Filter (Block&);
};

void
SourceFile::Filter::load_syntax (Syntax& syntax, AttributeList&)
{
  syntax.add ("tag", Syntax::String, Syntax::Const, "\
Name of column in Daisy log file to filter for.");
  syntax.add ("allowed", Syntax::String, Syntax::Const, Syntax::Sequence, "\
List of allowable values in filter.");
  syntax.add_check ("allowed", VCheck::min_size_1 ());
  syntax.order ("tag", "allowed");
}

SourceFile::Filter::Filter (Block& al)
  : tag (al.name ("tag")),
    allowed (al.name_sequence ("allowed"))
{ }

std::string
SourceFile::get_entry (LexerData& lex) const
{
  std::string tmp_term;  // Data storage.
  const char* field_term;

  switch (field_sep.size ())
    {
    case 0:
      // Whitespace
      field_term = " \t\n";
      break;
    case 1:
      // Single character field seperator.
      tmp_term = field_sep + "\n";
      field_term = tmp_term.c_str ();
      break;
    default:
      // Multi-character field seperator.
      daisy_assert (false);
    }

  // Find it.
  std::string entry = "";
  while (lex.good ())
    {
      int c = lex.peek ();
      if (strchr (field_term, c))
	break;
      entry += int2char (lex.get ());
    }
  return entry;
}

std::vector<std::string>
SourceFile::get_entries (LexerData& lex) const
{
  lex.skip ("\n");
  std::vector<std::string> entries;

  while (lex.good ())
    {
      entries.push_back (get_entry (lex));

      if (lex.peek () == '\n')
        break;

      if (field_sep == "")
	lex.skip_space ();
      else
	lex.skip(field_sep.c_str ());
    }
  return entries;
}

int
SourceFile::get_date_component (LexerData& lex,
				const std::vector<std::string>&
				/**/ entries,
				int column,
				int default_value)
{
  if (column < 0)
    return default_value;
  daisy_assert (column < entries.size ());
  const char *const str = entries[column].c_str ();
  const char* end_ptr = str;
  const long lval = strtol (str, const_cast<char**> (&end_ptr), 10);
  if (*end_ptr != '\0')
    lex.error (std::string ("Junk at end of number '") + end_ptr + "'");
  const int ival = lval;
  if (ival != lval)
    lex.error ("Number out of range");
  return ival;
}

Time
SourceFile::get_time (const std::string& entry)
{
  int year;
  int month;
  int mday;
  int hour = 8;
  char dummy;

  std::istringstream in (entry);

  in >> year >> dummy >> month >> dummy >> mday;
  if (in.good () && !in.eof ())
    in >> dummy >> hour;

  if (Time::valid (year, month, mday, hour))
    return Time (year, month, mday, hour);

  return Time (9999, 1, 1, 1);
}

double
SourceFile::convert_to_double (LexerData& lex,
			       const std::string& value)
{
  const char *const str = value.c_str ();
  const char* end_ptr = str;
  const double val = strtod (str, const_cast<char**> (&end_ptr));
  if (*end_ptr != '\0')
    lex.error (std::string ("Junk at end of number '") + end_ptr + "'");
  return val;
}

bool
SourceFile::read_header (LexerData& lex)
{
  // Open errors?
  if (!lex.good ())
    return false;

  // Read first line.
  const std::string type = lex.get_word ();
  if (type == "dwf-0.0")
    {
      field_sep = "";
      if (with_ == "")
	with_ = "lines";
    }
  else if (type == "dlf-0.0")
    {
      field_sep = "\t";
      if (with_ == "")
	with_ = "lines";
    }
  else if (type == "ddf-0.0")
    {
      field_sep = "\t";
      if (with_ == "")
	with_ = "points";
    }
  else
    lex.error ("Unknown file type '" + type + "'");
  lex.skip_line ();
  lex.next_line ();

  // Skip keywords.
  while (lex.good () && lex.peek () != '-')
    {
      lex.skip_line ();
      lex.next_line ();
    }

  // Skip hyphens.
  while (lex.good () && lex.peek () == '-')
    lex.get ();
  lex.skip_space ();

  // Read tags.
  tag_names = get_entries (lex);
  for (int count = 0; count < tag_names.size (); count++)
    {
      const std::string candidate = tag_names[count];
      if (tag_pos.find (candidate) == tag_pos.end ())
        tag_pos[candidate] = count;
      else
	lex.warning ("Duplicate tag: '" + candidate + "'");
    }

  // Time tags.
  year_c = find_tag (tag_pos, "year", "Year");
  month_c = find_tag (tag_pos, "month", "Month");
  mday_c = find_tag (tag_pos, "mday", "Day");
  hour_c = find_tag (tag_pos, "hour", "Hour");
  time_c = find_tag (tag_pos, "time", "Date");

  // Filter tags.
  for (size_t i = 0; i < filter.size (); i++)
    {
      int c = find_tag (tag_pos, filter[i]->tag);
      if (c < 0)
	{
	  lex.error ("Filter tag '" + filter[i]->tag + "' not found");
	  return false;
	}
      fil_col.push_back (c);
    }

  return lex.good ();
}

bool
SourceFile::read_entry (LexerData& lex,
                        std::vector<std::string>& entries,
                        Time& time) const
{
  // Read entries.
  entries = get_entries (lex);

  if (entries.size () != tag_names.size ())
    {
      if (entries.size () != 0 && lex.good ())
        {
          std::ostringstream tmp;
          tmp << "Got " << entries.size () << " entries, expected "
              << tag_names.size ();
          lex.warning (tmp.str ());
        }
      return false;
    }

  // Extract date.
  if (time_c < 0)
    {
      int year = get_date_component (lex, entries, year_c, 1000);
      int month = get_date_component (lex, entries, month_c, 1);
      int mday = get_date_component (lex, entries, mday_c, 1);
      int hour = get_date_component (lex, entries, hour_c, 0);

      if (!Time::valid (year, month, mday, hour))
        {
          std::ostringstream tmp;
          tmp << year << "-" << month << "-" << mday << "T" << hour
              << ": invalid date";
          lex.warning (tmp.str ());
          return false;
        }
      else
        time = Time (year, month, mday, hour);
    }
  else
    time = get_time (entries[time_c]);

  if (time.year () == 9999)
    {
      std::ostringstream tmp;
      tmp << time.year () << "-" << time.month () << "-" << time.mday ()
          << "T" << time.hour () << ": invalid date";
      lex.warning (tmp.str ());
      return false;
    }

  // Filter.
  for (size_t i = 0; i < filter.size (); i++)
    {
      const std::vector<std::string>& allowed = filter[i]->allowed;
      const std::string& v = entries[fil_col[i]];
      if (std::find (allowed.begin (), allowed.end (), v)
          == allowed.end ())
        return false;
    }

  // If we survived here, everything is fine.
  return true;
}

void
SourceFile::load_syntax (Syntax& syntax, AttributeList& alist)
{
  Source::load_syntax (syntax, alist);
  syntax.add ("file", Syntax::String, Syntax::Const, "\
Name of Daisy log file where data is found.");
  syntax.add ("missing", Syntax::String, Syntax::Const, Syntax::Sequence, "\
List of strings indicating missing values.");
  std::vector<symbol> misses;
  misses.push_back (symbol (""));
  misses.push_back (symbol ("00.00"));
  alist.add ("missing", misses);
  syntax.add_submodule_sequence ("filter", Syntax::Const, "\
Only include data from rows that passes all these filters.",
				 SourceFile::Filter::load_syntax);
  alist.add ("filter", std::vector<AttributeList*> ());
  syntax.add ("with", Syntax::String, Syntax::OptionalConst, "\
Specify 'points' to plot each point individually, or 'lines' to draw\n\
lines between them.  By default, data from dwf and dlf files will be\n\
drawn with lines, and data from ddf files will be drawn with points.");
  static VCheck::Enum with ("lines", "points");
  syntax.add_check ("with", with);
  syntax.add ("style", Syntax::Integer, Syntax::OptionalConst, "\
Style to use for this dataset.  By default, gnuplot will use style 1\n\
for the first source to plot with lines, style 2 for the second, and\n\
so forth until it runs out of styles and has to start over.  Points\n\
work similar, but with its own style counter.  For color plots, points\n\
and lines with the same style number also have the same color.");
}

SourceFile::SourceFile (Block& al)
  : Source (al),
    filename (al.name ("file")),
    with_ (al.name ("with", "")),
    style_ (al.integer ("style", -1)),
    missing (al.name_sequence ("missing")),
    filter (map_submodel_const<Filter> (al, "filter")),
    field_sep ("UNINITIALIZED"),
    year_c (-42),
    month_c (-42),
    mday_c (-42),
    hour_c (-42),
    time_c (-42)
{ }

SourceFile::~SourceFile ()
{ sequence_delete (filter.begin (), filter.end ()); }

// source_file.h ends here.
<commit_msg>kvl-t<commit_after>// source_file.C -- File source for gnuplot interface
//
// Copyright 2005 Per Abrahamsen and KVL.
//
// This file is part of Daisy.
//
// Daisy is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// Daisy 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 Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with Daisy; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "source_file.h"
#include "lexer_data.h"
#include "submodeler.h"
#include "vcheck.h"
#include "mathlib.h"
#include "memutils.h"
#include <sstream>

static int
find_tag (const std::map<std::string,int>& tag_pos,
	  const std::string& tag1,
	  const std::string& tag2)
{
  int result = find_tag (tag_pos, tag1);
  return result < 0 ? find_tag (tag_pos, tag2) : result;
}

struct SourceFile::Filter
{
  const std::string tag;
  const std::vector<std::string> allowed;
  static void load_syntax (Syntax& syntax, AttributeList&);
  explicit Filter (Block&);
};

void
SourceFile::Filter::load_syntax (Syntax& syntax, AttributeList&)
{
  syntax.add ("tag", Syntax::String, Syntax::Const, "\
Name of column in Daisy log file to filter for.");
  syntax.add ("allowed", Syntax::String, Syntax::Const, Syntax::Sequence, "\
List of allowable values in filter.");
  syntax.add_check ("allowed", VCheck::min_size_1 ());
  syntax.order ("tag", "allowed");
}

SourceFile::Filter::Filter (Block& al)
  : tag (al.name ("tag")),
    allowed (al.name_sequence ("allowed"))
{ }

std::string
SourceFile::get_entry (LexerData& lex) const
{
  std::string tmp_term;  // Data storage.
  const char* field_term;

  switch (field_sep.size ())
    {
    case 0:
      // Whitespace
      field_term = " \t\n";
      break;
    case 1:
      // Single character field seperator.
      tmp_term = field_sep + "\n";
      field_term = tmp_term.c_str ();
      break;
    default:
      // Multi-character field seperator.
      daisy_assert (false);
    }

  // Find it.
  std::string entry = "";
  while (lex.good ())
    {
      int c = lex.peek ();
      if (strchr (field_term, c))
	break;
      entry += int2char (lex.get ());
    }
  return entry;
}

std::vector<std::string>
SourceFile::get_entries (LexerData& lex) const
{
  lex.skip ("\n");
  std::vector<std::string> entries;

  while (lex.good ())
    {
      entries.push_back (get_entry (lex));

      if (lex.peek () == '\n')
        break;

      if (field_sep == "")
	lex.skip_space ();
      else
	lex.skip(field_sep.c_str ());
    }
  return entries;
}

int
SourceFile::get_date_component (LexerData& lex,
				const std::vector<std::string>&
				/**/ entries,
				int column,
				int default_value)
{
  if (column < 0)
    return default_value;
  daisy_assert (column < entries.size ());
  const char *const str = entries[column].c_str ();
  const char* end_ptr = str;
  const long lval = strtol (str, const_cast<char**> (&end_ptr), 10);
  if (*end_ptr != '\0')
    lex.error (std::string ("Junk at end of number '") + end_ptr + "'");
  const int ival = lval;
  if (ival != lval)
    lex.error ("Number out of range");
  return ival;
}

Time
SourceFile::get_time (const std::string& entry)
{
  int year;
  int month;
  int mday;
  int hour = 8;
  char dummy;

  std::istringstream in (entry);

  in >> year >> dummy >> month >> dummy >> mday;
  if (in.good () && !in.eof ())
    in >> dummy >> hour;

  if (Time::valid (year, month, mday, hour))
    return Time (year, month, mday, hour);

  return Time (9999, 1, 1, 1);
}

double
SourceFile::convert_to_double (LexerData& lex,
			       const std::string& value)
{
  const char *const str = value.c_str ();
  const char* end_ptr = str;
  const double val = strtod (str, const_cast<char**> (&end_ptr));
  if (*end_ptr != '\0')
    lex.error (std::string ("Junk at end of number '") + end_ptr + "'");
  return val;
}

bool
SourceFile::read_header (LexerData& lex)
{
  // Open errors?
  if (!lex.good ())
    return false;

  // Read first line.
  const std::string type = lex.get_word ();
  if (type == "dwf-0.0")
    {
      field_sep = "";
      if (with_ == "")
	with_ = "lines";
    }
  else if (type == "dlf-0.0")
    {
      field_sep = "\t";
      if (with_ == "")
	with_ = "lines";
    }
  else if (type == "ddf-0.0")
    {
      field_sep = "\t";
      if (with_ == "")
	with_ = "points";
    }
  else
    lex.error ("Unknown file type '" + type + "'");
  lex.skip_line ();
  lex.next_line ();

  // Skip keywords.
  while (lex.good () && lex.peek () != '-')
    {
      lex.skip_line ();
      lex.next_line ();
    }

  // Skip hyphens.
  while (lex.good () && lex.peek () == '-')
    lex.get ();
  lex.skip_space ();

  // Read tags.
  tag_names = get_entries (lex);
  for (int count = 0; count < tag_names.size (); count++)
    {
      const std::string candidate = tag_names[count];
      if (tag_pos.find (candidate) == tag_pos.end ())
        tag_pos[candidate] = count;
      else
	lex.warning ("Duplicate tag: '" + candidate + "'");
    }

  // Time tags.
  year_c = find_tag (tag_pos, "year", "Year");
  month_c = find_tag (tag_pos, "month", "Month");
  mday_c = find_tag (tag_pos, "mday", "Day");
  hour_c = find_tag (tag_pos, "hour", "Hour");
  time_c = find_tag (tag_pos, "time", "Date");

  // Filter tags.
  for (size_t i = 0; i < filter.size (); i++)
    {
      int c = find_tag (tag_pos, filter[i]->tag);
      if (c < 0)
	{
	  lex.error ("Filter tag '" + filter[i]->tag + "' not found");
	  return false;
	}
      fil_col.push_back (c);
    }

  return lex.good ();
}

bool
SourceFile::read_entry (LexerData& lex,
                        std::vector<std::string>& entries,
                        Time& time) const
{
  // Read entries.
  entries = get_entries (lex);

  if (entries.size () != tag_names.size ())
    {
      if (entries.size () != 0 && lex.good ())
        {
          std::ostringstream tmp;
          tmp << "Got " << entries.size () << " entries, expected "
              << tag_names.size ();
          lex.warning (tmp.str ());
          while (entries.size () < tag_names.size ())
            entries.push_back ("");
        }
      else
        return false;
    }

  // Extract date.
  if (time_c < 0)
    {
      int year = get_date_component (lex, entries, year_c, 1000);
      int month = get_date_component (lex, entries, month_c, 1);
      int mday = get_date_component (lex, entries, mday_c, 1);
      int hour = get_date_component (lex, entries, hour_c, 0);

      if (!Time::valid (year, month, mday, hour))
        {
          std::ostringstream tmp;
          tmp << year << "-" << month << "-" << mday << "T" << hour
              << ": invalid date";
          lex.warning (tmp.str ());
          return false;
        }
      else
        time = Time (year, month, mday, hour);
    }
  else
    time = get_time (entries[time_c]);

  if (time.year () == 9999)
    {
      std::ostringstream tmp;
      tmp << time.year () << "-" << time.month () << "-" << time.mday ()
          << "T" << time.hour () << ": invalid date";
      lex.warning (tmp.str ());
      return false;
    }

  // Filter.
  for (size_t i = 0; i < filter.size (); i++)
    {
      const std::vector<std::string>& allowed = filter[i]->allowed;
      const std::string& v = entries[fil_col[i]];
      if (std::find (allowed.begin (), allowed.end (), v)
          == allowed.end ())
        return false;
    }

  // If we survived here, everything is fine.
  return true;
}

void
SourceFile::load_syntax (Syntax& syntax, AttributeList& alist)
{
  Source::load_syntax (syntax, alist);
  syntax.add ("file", Syntax::String, Syntax::Const, "\
Name of Daisy log file where data is found.");
  syntax.add ("missing", Syntax::String, Syntax::Const, Syntax::Sequence, "\
List of strings indicating missing values.");
  std::vector<symbol> misses;
  misses.push_back (symbol (""));
  misses.push_back (symbol ("00.00"));
  alist.add ("missing", misses);
  syntax.add_submodule_sequence ("filter", Syntax::Const, "\
Only include data from rows that passes all these filters.",
				 SourceFile::Filter::load_syntax);
  alist.add ("filter", std::vector<AttributeList*> ());
  syntax.add ("with", Syntax::String, Syntax::OptionalConst, "\
Specify 'points' to plot each point individually, or 'lines' to draw\n\
lines between them.  By default, data from dwf and dlf files will be\n\
drawn with lines, and data from ddf files will be drawn with points.");
  static VCheck::Enum with ("lines", "points");
  syntax.add_check ("with", with);
  syntax.add ("style", Syntax::Integer, Syntax::OptionalConst, "\
Style to use for this dataset.  By default, gnuplot will use style 1\n\
for the first source to plot with lines, style 2 for the second, and\n\
so forth until it runs out of styles and has to start over.  Points\n\
work similar, but with its own style counter.  For color plots, points\n\
and lines with the same style number also have the same color.");
}

SourceFile::SourceFile (Block& al)
  : Source (al),
    filename (al.name ("file")),
    with_ (al.name ("with", "")),
    style_ (al.integer ("style", -1)),
    missing (al.name_sequence ("missing")),
    filter (map_submodel_const<Filter> (al, "filter")),
    field_sep ("UNINITIALIZED"),
    year_c (-42),
    month_c (-42),
    mday_c (-42),
    hour_c (-42),
    time_c (-42)
{ }

SourceFile::~SourceFile ()
{ sequence_delete (filter.begin (), filter.end ()); }

// source_file.h ends here.
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "base/misc.hh"
#include "dev/pktfifo.hh"

using namespace std;

void
PacketFifo::serialize(const string &base, ostream &os)
{
    paramOut(os, base + ".size", _size);
    paramOut(os, base + ".maxsize", _maxsize);
    paramOut(os, base + ".reserved", _reserved);
    paramOut(os, base + ".packets", fifo.size());

    int i = 0;
    std::list<PacketPtr>::iterator p = fifo.begin();
    std::list<PacketPtr>::iterator end = fifo.end();
    while (p != end) {
        (*p)->serialize(csprintf("%s.packet%d", base, i), os);
        ++p;
        ++i;
    }
}

void
PacketFifo::unserialize(const string &base, Checkpoint *cp,
                        const string &section)
{
    paramIn(cp, section, base + ".size", _size);
    paramIn(cp, section, base + ".maxsize", _maxsize);
    paramIn(cp, section, base + ".reserved", _reserved);
    int fifosize;
    paramIn(cp, section, base + ".packets", fifosize);

    fifo.clear();
    fifo.resize(fifosize);

    for (int i = 0; i < fifosize; ++i) {
        PacketPtr p = new PacketData(16384);
        p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
        fifo.push_back(p);
    }
}
<commit_msg>fix unserialization of PacketFifo<commit_after>/*
 * Copyright (c) 2002-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "base/misc.hh"
#include "dev/pktfifo.hh"

using namespace std;

void
PacketFifo::serialize(const string &base, ostream &os)
{
    paramOut(os, base + ".size", _size);
    paramOut(os, base + ".maxsize", _maxsize);
    paramOut(os, base + ".reserved", _reserved);
    paramOut(os, base + ".packets", fifo.size());

    int i = 0;
    std::list<PacketPtr>::iterator p = fifo.begin();
    std::list<PacketPtr>::iterator end = fifo.end();
    while (p != end) {
        (*p)->serialize(csprintf("%s.packet%d", base, i), os);
        ++p;
        ++i;
    }
}

void
PacketFifo::unserialize(const string &base, Checkpoint *cp,
                        const string &section)
{
    paramIn(cp, section, base + ".size", _size);
    paramIn(cp, section, base + ".maxsize", _maxsize);
    paramIn(cp, section, base + ".reserved", _reserved);
    int fifosize;
    paramIn(cp, section, base + ".packets", fifosize);

    fifo.clear();

    for (int i = 0; i < fifosize; ++i) {
        PacketPtr p = new PacketData(16384);
        p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
        fifo.push_back(p);
    }
}
<|endoftext|>


<commit_before>// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
#include <string>
#include <sstream>

// Patch for std::to_string() issue
// See here: http://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-so-g
namespace patch
{
    template < typename T > std::string to_string( const T& n )
    {
        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;
    }
}

#include<iostream>

using namespace Rcpp;
using namespace arma;

//' @export
// [[Rcpp::export]]
Rcpp::List returnLD(arma::uvec cIndex, arma::mat gen, arma::vec bpVec) {

	int nCausal = cIndex.n_elem;

	// Create a list for the output to be stored in.
	// We need a list because each of the elements is a different
	// length.

	// Not sure if the list type is the problem. It might be.
	Rcpp::List output;

	for(uword i = 0; i < nCausal; i++){

		// Give position of first element.
		// Remember that indexing starts at 0, not 1.
		uword index = cIndex(i);

		// Return the column of base pair positions and the basepair position
		// at causal SNP i index.
		//
		// This is still a test because I dont think that the logical
		// selection was working perfectly

		arma::uvec ldIndex = arma::find((bpVec > bpVec(index)-500000) && (bpVec < bpVec(index) + 500000));

		// This gives us the indices of which SNPs are within 500kb of
		// the causal SNP.
		// So now we have to subset the matrix to just include these,
		// as including anything else would be useless calculation

		mat subset = gen.rows(ldIndex);

		// Now that we have the collection of useful entries, we must
		// transform them into the R format
		//
		// 1. Cut off first 5 rows (but will need to save the indexes to recover
		//    these later)

		// 2. Transpose (will have to do it at some point)

		arma::mat genT = subset.t();

		// 3. Cooerce
		//
		// New output will have 1 for every three rows (with rows being the
		// old columns. It will have the same number of columns, as we aren't
		// changing the SNPs at all.

		arma::mat other((genT.n_rows / 3), genT.n_cols, fill::zeros);

		for(uword j = 0; j < genT.n_rows; j+=3){

			// The new row j / 3 (0, 1, 2, etc.) will be 0* none, 1 * 1,
			// and 2 x the double minor allele.
			other.row(j/3) = (0 * genT.row(j)) + (1 * genT.row(j+1)) + (2 * genT.row(j+2));
		}

		// Now that this preprocessing is accomplished, we can bring in
		// the cor_gen.cpp function.
		//
		// Note that we won't directly import it, merely use the code,
		// because I don't actually know how to do that.
		//
		// Ideally I would do all this preprocessing at the same time as
		// above but I can't figure out how to do it right now.

		// We create a new vector with as many entries as there are SNPs.
		// arma::vec out(other.n_cols);

		// Now create the "real" vector
		// Using the same process as above
		arma::rowvec causal_raw_row = gen.row(index);

		arma::colvec causal_raw = causal_raw_row.t();

		arma::vec causal(causal_raw.n_elem/3);

		for(uword j = 0; j < causal_raw.n_elem; j+=3){
			causal(j/3) = 0*causal_raw(j) + 1*causal_raw(j+1) + 2*causal_raw(j+2);
		}

		// Now we have causal and other
		//
		// vec causal = Vector of dosage for the causal SNP that we
		//              have been looking for.
		// mat other = All the other SNP data. Note that causal IS
		// 		included in this. I will have to figure out
		// 		how to deal with this soon.
		//
		// Now move on to actually calculating the correlation.

		// For each column in the all matrix
		//
		// 1. Create a new vector out of the column
		// 2. Calculate correlation between causal and that column
		// 3. Put that into out

		arma::vec out(other.n_cols);

		for(uword j = 0; j < other.n_cols; j++){

			arma::vec otherVec = other.col(j); // 1

			arma::mat temp = arma::cor(causal, otherVec); // 2

			out(j) = pow(temp(0,0),2); // 3

		}

		//cout << out << "\n";

		arma::mat outMat(ldIndex.n_elem, 2);

		outMat.col(0) = arma::conv_to<vec>::from(ldIndex)+ 1;
		outMat.col(1) = out;

		std::string name = std::to_string(i);

		output[name] = outMat;

	}

	return output ;
}
<commit_msg>export to_string from patch<commit_after>// [[Rcpp::depends(RcppArmadillo)]]

#include <RcppArmadillo.h>
#include <string>
#include <sstream>

// Patch for std::to_string() issue
// See here: http://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-so-g
namespace patch
{
    template < typename T > std::string to_string( const T& n )
    {
        std::ostringstream stm ;
        stm << n ;
        return stm.str() ;
    }
}

#include<iostream>

using namespace Rcpp;
using namespace arma;

//' @export
// [[Rcpp::export]]
Rcpp::List returnLD(arma::uvec cIndex, arma::mat gen, arma::vec bpVec) {

	int nCausal = cIndex.n_elem;

	// Create a list for the output to be stored in.
	// We need a list because each of the elements is a different
	// length.

	// Not sure if the list type is the problem. It might be.
	Rcpp::List output;

	for(uword i = 0; i < nCausal; i++){

		// Give position of first element.
		// Remember that indexing starts at 0, not 1.
		uword index = cIndex(i);

		// Return the column of base pair positions and the basepair position
		// at causal SNP i index.
		//
		// This is still a test because I dont think that the logical
		// selection was working perfectly

		arma::uvec ldIndex = arma::find((bpVec > bpVec(index)-500000) && (bpVec < bpVec(index) + 500000));

		// This gives us the indices of which SNPs are within 500kb of
		// the causal SNP.
		// So now we have to subset the matrix to just include these,
		// as including anything else would be useless calculation

		mat subset = gen.rows(ldIndex);

		// Now that we have the collection of useful entries, we must
		// transform them into the R format
		//
		// 1. Cut off first 5 rows (but will need to save the indexes to recover
		//    these later)

		// 2. Transpose (will have to do it at some point)

		arma::mat genT = subset.t();

		// 3. Cooerce
		//
		// New output will have 1 for every three rows (with rows being the
		// old columns. It will have the same number of columns, as we aren't
		// changing the SNPs at all.

		arma::mat other((genT.n_rows / 3), genT.n_cols, fill::zeros);

		for(uword j = 0; j < genT.n_rows; j+=3){

			// The new row j / 3 (0, 1, 2, etc.) will be 0* none, 1 * 1,
			// and 2 x the double minor allele.
			other.row(j/3) = (0 * genT.row(j)) + (1 * genT.row(j+1)) + (2 * genT.row(j+2));
		}

		// Now that this preprocessing is accomplished, we can bring in
		// the cor_gen.cpp function.
		//
		// Note that we won't directly import it, merely use the code,
		// because I don't actually know how to do that.
		//
		// Ideally I would do all this preprocessing at the same time as
		// above but I can't figure out how to do it right now.

		// We create a new vector with as many entries as there are SNPs.
		// arma::vec out(other.n_cols);

		// Now create the "real" vector
		// Using the same process as above
		arma::rowvec causal_raw_row = gen.row(index);

		arma::colvec causal_raw = causal_raw_row.t();

		arma::vec causal(causal_raw.n_elem/3);

		for(uword j = 0; j < causal_raw.n_elem; j+=3){
			causal(j/3) = 0*causal_raw(j) + 1*causal_raw(j+1) + 2*causal_raw(j+2);
		}

		// Now we have causal and other
		//
		// vec causal = Vector of dosage for the causal SNP that we
		//              have been looking for.
		// mat other = All the other SNP data. Note that causal IS
		// 		included in this. I will have to figure out
		// 		how to deal with this soon.
		//
		// Now move on to actually calculating the correlation.

		// For each column in the all matrix
		//
		// 1. Create a new vector out of the column
		// 2. Calculate correlation between causal and that column
		// 3. Put that into out

		arma::vec out(other.n_cols);

		for(uword j = 0; j < other.n_cols; j++){

			arma::vec otherVec = other.col(j); // 1

			arma::mat temp = arma::cor(causal, otherVec); // 2

			out(j) = pow(temp(0,0),2); // 3

		}

		//cout << out << "\n";

		arma::mat outMat(ldIndex.n_elem, 2);

		outMat.col(0) = arma::conv_to<vec>::from(ldIndex)+ 1;
		outMat.col(1) = out;

		std::string name = patch::to_string(i);

		output[name] = outMat;

	}

	return output ;
}
<|endoftext|>


<commit_before>/*
   This file is part of the clazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

  Copyright (C) 2015-2016 Sergio Martins <smartins@kde.org>

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

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

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "Utils.h"
#include "StringUtils.h"
#include "clazy_stl.h"
#include "checkbase.h"
#include "checkmanager.h"
#include "AccessSpecifierManager.h"

#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/AST/ParentMap.h"
#include <llvm/Config/llvm-config.h>

#include <stdio.h>
#include <sstream>
#include <iostream>

using namespace clang;
using namespace std;

namespace {

class MyFixItOptions : public FixItOptions
{
public:
    MyFixItOptions(const MyFixItOptions &other) = delete;
    MyFixItOptions(bool inplace)
    {
        InPlace = inplace;
        FixWhatYouCan = true;
        FixOnlyWarnings = true;
        Silent = false;
    }

    std::string RewriteFilename(const std::string &filename, int &fd) override
    {
        fd = -1;
        return InPlace ? filename : filename + "_fixed.cpp";
    }

#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 6
    // Clang >= 3.7 already has this member.
    // We define it for clang <= 3.6 so it builds.
    bool InPlace;
#endif
};

static void manuallyPopulateParentMap(ParentMap *map, Stmt *s)
{
    if (!s)
        return;

    for (Stmt *child : s->children()) {
        llvm::errs() << "Patching " << child->getStmtClassName() << "\n";
        map->setParent(child, s);
        manuallyPopulateParentMap(map, child);
    }
}

class LazyASTConsumer : public ASTConsumer, public RecursiveASTVisitor<LazyASTConsumer>
{
    LazyASTConsumer(const LazyASTConsumer &) = delete;
public:
    LazyASTConsumer(CompilerInstance &ci, CheckManager *checkManager,
                    const RegisteredCheck::List &requestedChecks, bool inplaceFixits)
        : m_ci(ci)
        , m_rewriter(nullptr)
        , m_parentMap(nullptr)
        , m_checkManager(checkManager)
    {
        m_createdChecks = checkManager->createChecks(requestedChecks, ci);
        if (checkManager->fixitsEnabled())
            m_rewriter = new FixItRewriter(ci.getDiagnostics(), m_ci.getSourceManager(), m_ci.getLangOpts(), new MyFixItOptions(inplaceFixits));
    }

    ~LazyASTConsumer()
    {
        if (m_rewriter) {
            m_rewriter->WriteFixedFiles();
            delete m_rewriter;
        }

        delete m_parentMap;
    }

    void setParentMap(ParentMap *map)
    {
        assert(map && !m_parentMap);
        m_parentMap = map;
        for (auto &check : m_createdChecks)
            check->setParentMap(map);
    }

    bool VisitDecl(Decl *decl)
    {
#if !defined(IS_OLD_CLANG)
        if (AccessSpecifierManager *a = m_checkManager->accessSpecifierManager())
            a->VisitDeclaration(decl);
#endif
        for (const auto &check : m_createdChecks)
            check->VisitDeclaration(decl);

        return true;
    }

    bool VisitStmt(Stmt *stm)
    {
        if (!m_parentMap) {
            if (m_ci.getDiagnostics().hasUnrecoverableErrorOccurred())
                return false; // ParentMap sometimes crashes when there were errors. Doesn't like a botched AST.

            setParentMap(new ParentMap(stm));
        }

        // Workaround llvm bug: Crashes creating a parent map when encountering Catch Statements.
        if (lastStm && isa<CXXCatchStmt>(lastStm) && !m_parentMap->hasParent(stm)) {
            m_parentMap->setParent(stm, lastStm);
            manuallyPopulateParentMap(m_parentMap, stm);
        }

        lastStm = stm;

        // clang::ParentMap takes a root statement, but there's no root statement in the AST, the root is a declaration
        // So add to parent map each time we go into a different hierarchy
        if (!m_parentMap->hasParent(stm))
            m_parentMap->addStmt(stm);

        for (const auto &check : m_createdChecks) {
            check->VisitStatement(stm);
        }

        return true;
    }

    void HandleTranslationUnit(ASTContext &ctx) override
    {
        TraverseDecl(ctx.getTranslationUnitDecl());
    }

    Stmt *lastStm = nullptr;
    CompilerInstance &m_ci;
    FixItRewriter *m_rewriter;
    ParentMap *m_parentMap;
    CheckBase::List m_createdChecks;
    CheckManager *const m_checkManager;
};

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

static bool parseArgument(const string &arg, vector<string> &args)
{
    auto it = clazy_std::find(args, arg);
    if (it != args.end()) {
        args.erase(it, it + 1);
        return true;
    }

    return false;
}

static CheckLevel parseLevel(vector<std::string> &args)
{
    static const vector<string> levels = { "level0", "level1", "level2", "level3", "level4" };
    const int numLevels = levels.size();
    for (int i = 0; i < numLevels; ++i) {
        if (parseArgument(levels.at(i), args)) {
            return static_cast<CheckLevel>(i);
        }
    }

    return CheckLevelUndefined;
}

static bool checkLessThan(const RegisteredCheck &c1, const RegisteredCheck &c2)
{
    return c1.name < c2.name;
}

static bool checkLessThanByLevel(const RegisteredCheck &c1, const RegisteredCheck &c2)
{
    if (c1.level == c2.level)
        return checkLessThan(c1, c2);

    return c1.level < c2.level;
}

class LazyASTAction : public PluginASTAction
{
public:
    LazyASTAction()
        : PluginASTAction()
        , m_checkManager(CheckManager::instance())
    {
    }

protected:
    std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(CompilerInstance &ci, llvm::StringRef) override
    {
        return llvm::make_unique<LazyASTConsumer>(ci, m_checkManager, m_checks, m_inplaceFixits);
    }

    bool ParseArgs(const CompilerInstance &ci, const std::vector<std::string> &args_) override
    {
        std::vector<std::string> args = args_;

        if (parseArgument("help", args)) {
            PrintHelp(llvm::errs());
            return true;
        }

        if (parseArgument("no-inplace-fixits", args)) {
            // Unit-tests don't use inplace fixits
            m_inplaceFixits = false;
        }

        // This argument is for debugging purposes
        const bool printRequestedChecks = parseArgument("print-requested-checks", args);

        const CheckLevel requestedLevel = parseLevel(/*by-ref*/args);
        if (requestedLevel != CheckLevelUndefined) {
            m_checkManager->setRequestedLevel(requestedLevel);
        }

        if (parseArgument("enable-all-fixits", args)) {
            // This is useful for unit-tests, where we also want to run fixits. Don't use it otherwise.
            m_checkManager->enableAllFixIts();
        }

        if (args.size() > 1) {
            // Too many arguments.
            llvm::errs() << "Too many arguments: ";
            for (const std::string &a : args)
                llvm::errs() << a << ' ';
            llvm::errs() << "\n";

            PrintHelp(llvm::errs());
            return false;
        } else if (args.size() == 1) {
            vector<string> userDisabledChecks;
            m_checks = m_checkManager->checksForCommaSeparatedString(args[0], /*by-ref=*/userDisabledChecks);
            if (m_checks.empty()) {
                llvm::errs() << "Could not find checks in comma separated string " + args[0] + "\n";
                PrintHelp(llvm::errs());
                return false;
            }
        }

        vector<string> userDisabledChecks;
        // Append checks specified from env variable
        RegisteredCheck::List checksFromEnv = m_checkManager->requestedChecksThroughEnv(/*by-ref*/userDisabledChecks);
        copy(checksFromEnv.cbegin(), checksFromEnv.cend(), back_inserter(m_checks));

        if (m_checks.empty() && requestedLevel == CheckLevelUndefined) {
            // No check or level specified, lets use the default level
            m_checkManager->setRequestedLevel(DefaultCheckLevel);
        }

        // Add checks from requested level
        auto checksFromRequestedLevel = m_checkManager->checksFromRequestedLevel();
        clazy_std::append(checksFromRequestedLevel, m_checks);
        clazy_std::sort_and_remove_dups(m_checks, checkLessThan);
        CheckManager::removeChecksFromList(m_checks, userDisabledChecks);

        if (printRequestedChecks) {
            llvm::errs() << "Requested checks: ";
            const unsigned int numChecks = m_checks.size();
            for (unsigned int i = 0; i < numChecks; ++i) {
                llvm::errs() << m_checks.at(i).name;
                const bool isLast = i == numChecks - 1;
                if (!isLast) {
                    llvm::errs() << ", ";
                }
            }

            llvm::errs() << "\n";
        }

        return true;
    }

    void PrintHelp(llvm::raw_ostream &ros)
    {
        RegisteredCheck::List checks = m_checkManager->availableChecks(MaxCheckLevel);
        clazy_std::sort(checks, checkLessThanByLevel);

        ros << "Available checks and FixIts:\n\n";

        int lastPrintedLevel = -1;
        const auto numChecks = checks.size();
        for (unsigned int i = 0; i < numChecks; ++i) {
            const RegisteredCheck &check = checks[i];
            if (lastPrintedLevel < check.level) {
                lastPrintedLevel = check.level;

                if (check.level > 0)
                    ros << "\n";

                ros << "- Checks from level" << to_string(check.level) << ":\n";
            }

            auto padded = check.name;
            padded.insert(padded.end(), 39 - padded.size(), ' ');
            ros << "    - " << check.name;
            auto fixits = m_checkManager->availableFixIts(check.name);
            if (!fixits.empty()) {
                ros << "    (";
                bool isFirst = true;
                for (const auto& fixit : fixits) {
                    if (isFirst) {
                        isFirst = false;
                    } else {
                        ros << ',';
                    }

                    ros << fixit.name;
                }
                ros << ')';
            }
            ros << "\n";
        }
        ros << "\nIf nothing is specified, all checks from level0 and level1 will be run.\n\n";
        ros << "To specify which checks to enable set the CLAZY_CHECKS env variable, for example:\n";
        ros << "    export CLAZY_CHECKS=\"level0\"\n";
        ros << "    export CLAZY_CHECKS=\"level0,reserve-candidates,qstring-allocations\"\n";
        ros << "    export CLAZY_CHECKS=\"reserve-candidates\"\n\n";
        ros << "or pass as compiler arguments, for example:\n";
        ros << "    -Xclang -plugin-arg-clang-lazy -Xclang reserve-candidates,qstring-allocations\n";
        ros << "\n";
        ros << "To enable FixIts for a check, also set the env variable CLAZY_FIXIT, for example:\n";
        ros << "    export CLAZY_FIXIT=\"fix-qlatin1string-allocations\"\n\n";
        ros << "FixIts are experimental and rewrite your code therefore only one FixIt is allowed per build.\nSpecifying a list of different FixIts is not supported.\nBackup your code before running them.\n";
    }

private:
    RegisteredCheck::List m_checks;
    bool m_inplaceFixits = true;
    CheckManager *const m_checkManager;
};

}

static FrontendPluginRegistry::Add<LazyASTAction>
X("clang-lazy", "clang lazy plugin");
<commit_msg>Rename LazyASTAction to ClazyASTAction<commit_after>/*
   This file is part of the clazy static checker.

  Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
  Author: Sérgio Martins <sergio.martins@kdab.com>

  Copyright (C) 2015-2016 Sergio Martins <smartins@kde.org>

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

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

  You should have received a copy of the GNU Library General Public License
  along with this library; see the file COPYING.LIB.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "Utils.h"
#include "StringUtils.h"
#include "clazy_stl.h"
#include "checkbase.h"
#include "checkmanager.h"
#include "AccessSpecifierManager.h"

#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Rewrite/Frontend/FixItRewriter.h"
#include "clang/AST/ParentMap.h"
#include <llvm/Config/llvm-config.h>

#include <stdio.h>
#include <sstream>
#include <iostream>

using namespace clang;
using namespace std;

namespace {

class MyFixItOptions : public FixItOptions
{
public:
    MyFixItOptions(const MyFixItOptions &other) = delete;
    MyFixItOptions(bool inplace)
    {
        InPlace = inplace;
        FixWhatYouCan = true;
        FixOnlyWarnings = true;
        Silent = false;
    }

    std::string RewriteFilename(const std::string &filename, int &fd) override
    {
        fd = -1;
        return InPlace ? filename : filename + "_fixed.cpp";
    }

#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 6
    // Clang >= 3.7 already has this member.
    // We define it for clang <= 3.6 so it builds.
    bool InPlace;
#endif
};

static void manuallyPopulateParentMap(ParentMap *map, Stmt *s)
{
    if (!s)
        return;

    for (Stmt *child : s->children()) {
        llvm::errs() << "Patching " << child->getStmtClassName() << "\n";
        map->setParent(child, s);
        manuallyPopulateParentMap(map, child);
    }
}

class LazyASTConsumer : public ASTConsumer, public RecursiveASTVisitor<LazyASTConsumer>
{
    LazyASTConsumer(const LazyASTConsumer &) = delete;
public:
    LazyASTConsumer(CompilerInstance &ci, CheckManager *checkManager,
                    const RegisteredCheck::List &requestedChecks, bool inplaceFixits)
        : m_ci(ci)
        , m_rewriter(nullptr)
        , m_parentMap(nullptr)
        , m_checkManager(checkManager)
    {
        m_createdChecks = checkManager->createChecks(requestedChecks, ci);
        if (checkManager->fixitsEnabled())
            m_rewriter = new FixItRewriter(ci.getDiagnostics(), m_ci.getSourceManager(), m_ci.getLangOpts(), new MyFixItOptions(inplaceFixits));
    }

    ~LazyASTConsumer()
    {
        if (m_rewriter) {
            m_rewriter->WriteFixedFiles();
            delete m_rewriter;
        }

        delete m_parentMap;
    }

    void setParentMap(ParentMap *map)
    {
        assert(map && !m_parentMap);
        m_parentMap = map;
        for (auto &check : m_createdChecks)
            check->setParentMap(map);
    }

    bool VisitDecl(Decl *decl)
    {
#if !defined(IS_OLD_CLANG)
        if (AccessSpecifierManager *a = m_checkManager->accessSpecifierManager())
            a->VisitDeclaration(decl);
#endif
        for (const auto &check : m_createdChecks)
            check->VisitDeclaration(decl);

        return true;
    }

    bool VisitStmt(Stmt *stm)
    {
        if (!m_parentMap) {
            if (m_ci.getDiagnostics().hasUnrecoverableErrorOccurred())
                return false; // ParentMap sometimes crashes when there were errors. Doesn't like a botched AST.

            setParentMap(new ParentMap(stm));
        }

        // Workaround llvm bug: Crashes creating a parent map when encountering Catch Statements.
        if (lastStm && isa<CXXCatchStmt>(lastStm) && !m_parentMap->hasParent(stm)) {
            m_parentMap->setParent(stm, lastStm);
            manuallyPopulateParentMap(m_parentMap, stm);
        }

        lastStm = stm;

        // clang::ParentMap takes a root statement, but there's no root statement in the AST, the root is a declaration
        // So add to parent map each time we go into a different hierarchy
        if (!m_parentMap->hasParent(stm))
            m_parentMap->addStmt(stm);

        for (const auto &check : m_createdChecks) {
            check->VisitStatement(stm);
        }

        return true;
    }

    void HandleTranslationUnit(ASTContext &ctx) override
    {
        TraverseDecl(ctx.getTranslationUnitDecl());
    }

    Stmt *lastStm = nullptr;
    CompilerInstance &m_ci;
    FixItRewriter *m_rewriter;
    ParentMap *m_parentMap;
    CheckBase::List m_createdChecks;
    CheckManager *const m_checkManager;
};

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

static bool parseArgument(const string &arg, vector<string> &args)
{
    auto it = clazy_std::find(args, arg);
    if (it != args.end()) {
        args.erase(it, it + 1);
        return true;
    }

    return false;
}

static CheckLevel parseLevel(vector<std::string> &args)
{
    static const vector<string> levels = { "level0", "level1", "level2", "level3", "level4" };
    const int numLevels = levels.size();
    for (int i = 0; i < numLevels; ++i) {
        if (parseArgument(levels.at(i), args)) {
            return static_cast<CheckLevel>(i);
        }
    }

    return CheckLevelUndefined;
}

static bool checkLessThan(const RegisteredCheck &c1, const RegisteredCheck &c2)
{
    return c1.name < c2.name;
}

static bool checkLessThanByLevel(const RegisteredCheck &c1, const RegisteredCheck &c2)
{
    if (c1.level == c2.level)
        return checkLessThan(c1, c2);

    return c1.level < c2.level;
}

class ClazyASTAction : public PluginASTAction
{
public:
    ClazyASTAction()
        : PluginASTAction()
        , m_checkManager(CheckManager::instance())
    {
    }

protected:
    std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(CompilerInstance &ci, llvm::StringRef) override
    {
        return llvm::make_unique<LazyASTConsumer>(ci, m_checkManager, m_checks, m_inplaceFixits);
    }

    bool ParseArgs(const CompilerInstance &ci, const std::vector<std::string> &args_) override
    {
        std::vector<std::string> args = args_;

        if (parseArgument("help", args)) {
            PrintHelp(llvm::errs());
            return true;
        }

        if (parseArgument("no-inplace-fixits", args)) {
            // Unit-tests don't use inplace fixits
            m_inplaceFixits = false;
        }

        // This argument is for debugging purposes
        const bool printRequestedChecks = parseArgument("print-requested-checks", args);

        const CheckLevel requestedLevel = parseLevel(/*by-ref*/args);
        if (requestedLevel != CheckLevelUndefined) {
            m_checkManager->setRequestedLevel(requestedLevel);
        }

        if (parseArgument("enable-all-fixits", args)) {
            // This is useful for unit-tests, where we also want to run fixits. Don't use it otherwise.
            m_checkManager->enableAllFixIts();
        }

        if (args.size() > 1) {
            // Too many arguments.
            llvm::errs() << "Too many arguments: ";
            for (const std::string &a : args)
                llvm::errs() << a << ' ';
            llvm::errs() << "\n";

            PrintHelp(llvm::errs());
            return false;
        } else if (args.size() == 1) {
            vector<string> userDisabledChecks;
            m_checks = m_checkManager->checksForCommaSeparatedString(args[0], /*by-ref=*/userDisabledChecks);
            if (m_checks.empty()) {
                llvm::errs() << "Could not find checks in comma separated string " + args[0] + "\n";
                PrintHelp(llvm::errs());
                return false;
            }
        }

        vector<string> userDisabledChecks;
        // Append checks specified from env variable
        RegisteredCheck::List checksFromEnv = m_checkManager->requestedChecksThroughEnv(/*by-ref*/userDisabledChecks);
        copy(checksFromEnv.cbegin(), checksFromEnv.cend(), back_inserter(m_checks));

        if (m_checks.empty() && requestedLevel == CheckLevelUndefined) {
            // No check or level specified, lets use the default level
            m_checkManager->setRequestedLevel(DefaultCheckLevel);
        }

        // Add checks from requested level
        auto checksFromRequestedLevel = m_checkManager->checksFromRequestedLevel();
        clazy_std::append(checksFromRequestedLevel, m_checks);
        clazy_std::sort_and_remove_dups(m_checks, checkLessThan);
        CheckManager::removeChecksFromList(m_checks, userDisabledChecks);

        if (printRequestedChecks) {
            llvm::errs() << "Requested checks: ";
            const unsigned int numChecks = m_checks.size();
            for (unsigned int i = 0; i < numChecks; ++i) {
                llvm::errs() << m_checks.at(i).name;
                const bool isLast = i == numChecks - 1;
                if (!isLast) {
                    llvm::errs() << ", ";
                }
            }

            llvm::errs() << "\n";
        }

        return true;
    }

    void PrintHelp(llvm::raw_ostream &ros)
    {
        RegisteredCheck::List checks = m_checkManager->availableChecks(MaxCheckLevel);
        clazy_std::sort(checks, checkLessThanByLevel);

        ros << "Available checks and FixIts:\n\n";

        int lastPrintedLevel = -1;
        const auto numChecks = checks.size();
        for (unsigned int i = 0; i < numChecks; ++i) {
            const RegisteredCheck &check = checks[i];
            if (lastPrintedLevel < check.level) {
                lastPrintedLevel = check.level;

                if (check.level > 0)
                    ros << "\n";

                ros << "- Checks from level" << to_string(check.level) << ":\n";
            }

            auto padded = check.name;
            padded.insert(padded.end(), 39 - padded.size(), ' ');
            ros << "    - " << check.name;
            auto fixits = m_checkManager->availableFixIts(check.name);
            if (!fixits.empty()) {
                ros << "    (";
                bool isFirst = true;
                for (const auto& fixit : fixits) {
                    if (isFirst) {
                        isFirst = false;
                    } else {
                        ros << ',';
                    }

                    ros << fixit.name;
                }
                ros << ')';
            }
            ros << "\n";
        }
        ros << "\nIf nothing is specified, all checks from level0 and level1 will be run.\n\n";
        ros << "To specify which checks to enable set the CLAZY_CHECKS env variable, for example:\n";
        ros << "    export CLAZY_CHECKS=\"level0\"\n";
        ros << "    export CLAZY_CHECKS=\"level0,reserve-candidates,qstring-allocations\"\n";
        ros << "    export CLAZY_CHECKS=\"reserve-candidates\"\n\n";
        ros << "or pass as compiler arguments, for example:\n";
        ros << "    -Xclang -plugin-arg-clang-lazy -Xclang reserve-candidates,qstring-allocations\n";
        ros << "\n";
        ros << "To enable FixIts for a check, also set the env variable CLAZY_FIXIT, for example:\n";
        ros << "    export CLAZY_FIXIT=\"fix-qlatin1string-allocations\"\n\n";
        ros << "FixIts are experimental and rewrite your code therefore only one FixIt is allowed per build.\nSpecifying a list of different FixIts is not supported.\nBackup your code before running them.\n";
    }

private:
    RegisteredCheck::List m_checks;
    bool m_inplaceFixits = true;
    CheckManager *const m_checkManager;
};

}

static FrontendPluginRegistry::Add<ClazyASTAction>
X("clang-lazy", "clang lazy plugin");
<|endoftext|>


<commit_before>/**
 *
 * HX711 library for Arduino
 * https://github.com/bogde/HX711
 *
 * MIT License
 * (c) 2018 Bogdan Necula
 *
**/
#include <Arduino.h>
#include "HX711.h"

// TEENSYDUINO has a port of Dean Camera's ATOMIC_BLOCK macros for AVR to ARM Cortex M3.
#define HAS_ATOMIC_BLOCK (defined(ARDUINO_ARCH_AVR) || defined(TEENSYDUINO))

// Whether we are running on either the ESP8266 or the ESP32.
#define ARCH_ESPRESSIF (defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32))

// Whether we are actually running on FreeRTOS.
#define IS_FREE_RTOS defined(ARDUINO_ARCH_ESP32)

// Define macro designating whether we're running on a reasonable
// fast CPU and so should slow down sampling from GPIO.
#define FAST_CPU \
    ( \
    ARCH_ESPRESSIF || \
    defined(ARDUINO_ARCH_SAM)     || defined(ARDUINO_ARCH_SAMD) || \
    defined(ARDUINO_ARCH_STM32)   || defined(TEENSYDUINO) \
    )

#if HAS_ATOMIC_BLOCK
// Acquire AVR-specific ATOMIC_BLOCK(ATOMIC_RESTORESTATE) macro.
#include <util/atomic.h>
#endif

#if FAST_CPU
// Make shiftIn() be aware of clockspeed for
// faster CPUs like ESP32, Teensy 3.x and friends.
// See also:
// - https://github.com/bogde/HX711/issues/75
// - https://github.com/arduino/Arduino/issues/6561
// - https://community.hiveeyes.org/t/using-bogdans-canonical-hx711-library-on-the-esp32/539
uint8_t shiftInSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;

    for(i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(1);
        if(bitOrder == LSBFIRST)
            value |= digitalRead(dataPin) << i;
        else
            value |= digitalRead(dataPin) << (7 - i);
        digitalWrite(clockPin, LOW);
        delayMicroseconds(1);
    }
    return value;
}
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftInSlow(data,clock,order)
#else
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftIn(data,clock,order)
#endif

HX711::HX711() {
}

HX711::~HX711() {
}

void HX711::begin(byte dout, byte pd_sck, byte gain) {
	PD_SCK = pd_sck;
	DOUT = dout;

	pinMode(PD_SCK, OUTPUT);
	pinMode(DOUT, INPUT_PULLUP);

	set_gain(gain);
}

bool HX711::is_ready() {
	return digitalRead(DOUT) == LOW;
}

void HX711::set_gain(byte gain) {
	switch (gain) {
		case 128:		// channel A, gain factor 128
			GAIN = 1;
			break;
		case 64:		// channel A, gain factor 64
			GAIN = 3;
			break;
		case 32:		// channel B, gain factor 32
			GAIN = 2;
			break;
	}

}

long HX711::read() {

	// Wait for the chip to become ready.
	wait_ready();

	// Define structures for reading data into.
	unsigned long value = 0;
	uint8_t data[3] = { 0 };
	uint8_t filler = 0x00;

	// Protect the read sequence from system interrupts.  If an interrupt occurs during
	// the time the PD_SCK signal is high it will stretch the length of the clock pulse.
	// If the total pulse time exceeds 60 uSec this will cause the HX711 to enter
	// power down mode during the middle of the read sequence.  While the device will
	// wake up when PD_SCK goes low again, the reset starts a new conversion cycle which
	// forces DOUT high until that cycle is completed.
	//
	// The result is that all subsequent bits read by shiftIn() will read back as 1,
	// corrupting the value returned by read().  The ATOMIC_BLOCK macro disables
	// interrupts during the sequence and then restores the interrupt mask to its previous
	// state after the sequence completes, insuring that the entire read-and-gain-set
	// sequence is not interrupted.  The macro has a few minor advantages over bracketing
	// the sequence between `noInterrupts()` and `interrupts()` calls.
	#if HAS_ATOMIC_BLOCK
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {

	#elif IS_FREE_RTOS
	// Begin of critical section.
	// Critical sections are used as a valid protection method
	// against simultaneous access in vanilla FreeRTOS.
	// Disable the scheduler and call portDISABLE_INTERRUPTS. This prevents
	// context switches and servicing of ISRs during a critical section.
	portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
	portENTER_CRITICAL(&mux);

	#else
	// Disable interrupts.
	noInterrupts();
	#endif

	// Pulse the clock pin 24 times to read the data.
	data[2] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[1] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[0] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);

	// Set the channel and the gain factor for the next reading using the clock pin.
	for (unsigned int i = 0; i < GAIN; i++) {
		digitalWrite(PD_SCK, HIGH);
		#if ARCH_ESPRESSIF
		delayMicroseconds(1);
		#endif
		digitalWrite(PD_SCK, LOW);
		#if ARCH_ESPRESSIF
		delayMicroseconds(1);
		#endif
	}

	#if IS_FREE_RTOS
	// End of critical section.
	portEXIT_CRITICAL(&mux);

	#elif HAS_ATOMIC_BLOCK
	}

	#else
	// Enable interrupts again.
	interrupts();
	#endif

	// Replicate the most significant bit to pad out a 32-bit signed integer
	if (data[2] & 0x80) {
		filler = 0xFF;
	} else {
		filler = 0x00;
	}

	// Construct a 32-bit signed integer
	value = ( static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(data[2]) << 16
			| static_cast<unsigned long>(data[1]) << 8
			| static_cast<unsigned long>(data[0]) );

	return static_cast<long>(value);
}

void HX711::wait_ready(unsigned long delay_ms) {
	// Wait for the chip to become ready.
	// This is a blocking implementation and will
	// halt the sketch until a load cell is connected.
	while (!is_ready()) {
		// Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP.
		// https://github.com/bogde/HX711/issues/73
		delay(delay_ms);
	}
}

bool HX711::wait_ready_retry(int retries, unsigned long delay_ms) {
	// Wait for the chip to become ready by
	// retrying for a specified amount of attempts.
	// https://github.com/bogde/HX711/issues/76
	int count = 0;
	while (count < retries) {
		if (is_ready()) {
			return true;
		}
		delay(delay_ms);
		count++;
	}
	return false;
}

bool HX711::wait_ready_timeout(unsigned long timeout, unsigned long delay_ms) {
	// Wait for the chip to become ready until timeout.
	// https://github.com/bogde/HX711/pull/96
	unsigned long millisStarted = millis();
	while (millis() - millisStarted < timeout) {
		if (is_ready()) {
			return true;
		}
		delay(delay_ms);
	}
	return false;
}

long HX711::read_average(byte times) {
	long sum = 0;
	for (byte i = 0; i < times; i++) {
		sum += read();
		// Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP.
		// https://github.com/bogde/HX711/issues/73
		delay(0);
	}
	return sum / times;
}

double HX711::get_value(byte times) {
	return read_average(times) - OFFSET;
}

float HX711::get_units(byte times) {
	return get_value(times) / SCALE;
}

void HX711::tare(byte times) {
	double sum = read_average(times);
	set_offset(sum);
}

void HX711::set_scale(float scale) {
	SCALE = scale;
}

float HX711::get_scale() {
	return SCALE;
}

void HX711::set_offset(long offset) {
	OFFSET = offset;
}

long HX711::get_offset() {
	return OFFSET;
}

void HX711::power_down() {
	digitalWrite(PD_SCK, LOW);
	digitalWrite(PD_SCK, HIGH);
}

void HX711::power_up() {
	digitalWrite(PD_SCK, LOW);
}
<commit_msg>Unpull DOUT pin<commit_after>/**
 *
 * HX711 library for Arduino
 * https://github.com/bogde/HX711
 *
 * MIT License
 * (c) 2018 Bogdan Necula
 *
**/
#include <Arduino.h>
#include "HX711.h"

// TEENSYDUINO has a port of Dean Camera's ATOMIC_BLOCK macros for AVR to ARM Cortex M3.
#define HAS_ATOMIC_BLOCK (defined(ARDUINO_ARCH_AVR) || defined(TEENSYDUINO))

// Whether we are running on either the ESP8266 or the ESP32.
#define ARCH_ESPRESSIF (defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32))

// Whether we are actually running on FreeRTOS.
#define IS_FREE_RTOS defined(ARDUINO_ARCH_ESP32)

// Define macro designating whether we're running on a reasonable
// fast CPU and so should slow down sampling from GPIO.
#define FAST_CPU \
    ( \
    ARCH_ESPRESSIF || \
    defined(ARDUINO_ARCH_SAM)     || defined(ARDUINO_ARCH_SAMD) || \
    defined(ARDUINO_ARCH_STM32)   || defined(TEENSYDUINO) \
    )

#if HAS_ATOMIC_BLOCK
// Acquire AVR-specific ATOMIC_BLOCK(ATOMIC_RESTORESTATE) macro.
#include <util/atomic.h>
#endif

#if FAST_CPU
// Make shiftIn() be aware of clockspeed for
// faster CPUs like ESP32, Teensy 3.x and friends.
// See also:
// - https://github.com/bogde/HX711/issues/75
// - https://github.com/arduino/Arduino/issues/6561
// - https://community.hiveeyes.org/t/using-bogdans-canonical-hx711-library-on-the-esp32/539
uint8_t shiftInSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;

    for(i = 0; i < 8; ++i) {
        digitalWrite(clockPin, HIGH);
        delayMicroseconds(1);
        if(bitOrder == LSBFIRST)
            value |= digitalRead(dataPin) << i;
        else
            value |= digitalRead(dataPin) << (7 - i);
        digitalWrite(clockPin, LOW);
        delayMicroseconds(1);
    }
    return value;
}
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftInSlow(data,clock,order)
#else
#define SHIFTIN_WITH_SPEED_SUPPORT(data,clock,order) shiftIn(data,clock,order)
#endif

HX711::HX711() {
}

HX711::~HX711() {
}

void HX711::begin(byte dout, byte pd_sck, byte gain) {
	PD_SCK = pd_sck;
	DOUT = dout;

	pinMode(PD_SCK, OUTPUT);
	pinMode(DOUT, INPUT);

	set_gain(gain);
}

bool HX711::is_ready() {
	return digitalRead(DOUT) == LOW;
}

void HX711::set_gain(byte gain) {
	switch (gain) {
		case 128:		// channel A, gain factor 128
			GAIN = 1;
			break;
		case 64:		// channel A, gain factor 64
			GAIN = 3;
			break;
		case 32:		// channel B, gain factor 32
			GAIN = 2;
			break;
	}

}

long HX711::read() {

	// Wait for the chip to become ready.
	wait_ready();

	// Define structures for reading data into.
	unsigned long value = 0;
	uint8_t data[3] = { 0 };
	uint8_t filler = 0x00;

	// Protect the read sequence from system interrupts.  If an interrupt occurs during
	// the time the PD_SCK signal is high it will stretch the length of the clock pulse.
	// If the total pulse time exceeds 60 uSec this will cause the HX711 to enter
	// power down mode during the middle of the read sequence.  While the device will
	// wake up when PD_SCK goes low again, the reset starts a new conversion cycle which
	// forces DOUT high until that cycle is completed.
	//
	// The result is that all subsequent bits read by shiftIn() will read back as 1,
	// corrupting the value returned by read().  The ATOMIC_BLOCK macro disables
	// interrupts during the sequence and then restores the interrupt mask to its previous
	// state after the sequence completes, insuring that the entire read-and-gain-set
	// sequence is not interrupted.  The macro has a few minor advantages over bracketing
	// the sequence between `noInterrupts()` and `interrupts()` calls.
	#if HAS_ATOMIC_BLOCK
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {

	#elif IS_FREE_RTOS
	// Begin of critical section.
	// Critical sections are used as a valid protection method
	// against simultaneous access in vanilla FreeRTOS.
	// Disable the scheduler and call portDISABLE_INTERRUPTS. This prevents
	// context switches and servicing of ISRs during a critical section.
	portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
	portENTER_CRITICAL(&mux);

	#else
	// Disable interrupts.
	noInterrupts();
	#endif

	// Pulse the clock pin 24 times to read the data.
	data[2] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[1] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);
	data[0] = SHIFTIN_WITH_SPEED_SUPPORT(DOUT, PD_SCK, MSBFIRST);

	// Set the channel and the gain factor for the next reading using the clock pin.
	for (unsigned int i = 0; i < GAIN; i++) {
		digitalWrite(PD_SCK, HIGH);
		#if ARCH_ESPRESSIF
		delayMicroseconds(1);
		#endif
		digitalWrite(PD_SCK, LOW);
		#if ARCH_ESPRESSIF
		delayMicroseconds(1);
		#endif
	}

	#if IS_FREE_RTOS
	// End of critical section.
	portEXIT_CRITICAL(&mux);

	#elif HAS_ATOMIC_BLOCK
	}

	#else
	// Enable interrupts again.
	interrupts();
	#endif

	// Replicate the most significant bit to pad out a 32-bit signed integer
	if (data[2] & 0x80) {
		filler = 0xFF;
	} else {
		filler = 0x00;
	}

	// Construct a 32-bit signed integer
	value = ( static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(data[2]) << 16
			| static_cast<unsigned long>(data[1]) << 8
			| static_cast<unsigned long>(data[0]) );

	return static_cast<long>(value);
}

void HX711::wait_ready(unsigned long delay_ms) {
	// Wait for the chip to become ready.
	// This is a blocking implementation and will
	// halt the sketch until a load cell is connected.
	while (!is_ready()) {
		// Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP.
		// https://github.com/bogde/HX711/issues/73
		delay(delay_ms);
	}
}

bool HX711::wait_ready_retry(int retries, unsigned long delay_ms) {
	// Wait for the chip to become ready by
	// retrying for a specified amount of attempts.
	// https://github.com/bogde/HX711/issues/76
	int count = 0;
	while (count < retries) {
		if (is_ready()) {
			return true;
		}
		delay(delay_ms);
		count++;
	}
	return false;
}

bool HX711::wait_ready_timeout(unsigned long timeout, unsigned long delay_ms) {
	// Wait for the chip to become ready until timeout.
	// https://github.com/bogde/HX711/pull/96
	unsigned long millisStarted = millis();
	while (millis() - millisStarted < timeout) {
		if (is_ready()) {
			return true;
		}
		delay(delay_ms);
	}
	return false;
}

long HX711::read_average(byte times) {
	long sum = 0;
	for (byte i = 0; i < times; i++) {
		sum += read();
		// Probably will do no harm on AVR but will feed the Watchdog Timer (WDT) on ESP.
		// https://github.com/bogde/HX711/issues/73
		delay(0);
	}
	return sum / times;
}

double HX711::get_value(byte times) {
	return read_average(times) - OFFSET;
}

float HX711::get_units(byte times) {
	return get_value(times) / SCALE;
}

void HX711::tare(byte times) {
	double sum = read_average(times);
	set_offset(sum);
}

void HX711::set_scale(float scale) {
	SCALE = scale;
}

float HX711::get_scale() {
	return SCALE;
}

void HX711::set_offset(long offset) {
	OFFSET = offset;
}

long HX711::get_offset() {
	return OFFSET;
}

void HX711::power_down() {
	digitalWrite(PD_SCK, LOW);
	digitalWrite(PD_SCK, HIGH);
}

void HX711::power_up() {
	digitalWrite(PD_SCK, LOW);
}
<|endoftext|>


<commit_before>#include "Image.h"

#include <cassert>
#include <iostream>

#include "rg_etc1.h"
#include "dxt.h"

using namespace std;
using namespace canvas;

bool Image::etc1_initialized = false;

std::shared_ptr<Image>
Image::convert(const ImageFormat & target_format) const {
  assert(format.getBytesPerPixel() == 4);
  assert(!format.getCompression());

  if (target_format.getCompression() == ImageFormat::DXT1 || target_format.getCompression() == ImageFormat::ETC1) {
    rg_etc1::etc1_pack_params params;
    params.m_quality = rg_etc1::cMediumQuality;
    if (target_format.getCompression() == ImageFormat::ETC1 && !etc1_initialized) {
      cerr << "initializing etc1" << endl;
      etc1_initialized = true;
      rg_etc1::pack_etc1_block_init();
    }
    assert((width & 3) == 0);
    assert((height & 3) == 0);
    unsigned int target_width = width, target_height = height;
    unsigned int target_size = calculateSize(target_width, target_height, levels, target_format);
    unsigned char * output_data = new unsigned char[target_size];
    unsigned char input_block[4*4*4];
    unsigned int target_offset = 0;
    for (unsigned int level = 0; level < levels; level++) {
      unsigned int rows = (target_height + 3) / 4, cols = (target_width + 3) / 4;
      int base_source_offset = calculateOffset(level);
      // cerr << "compressing DXT, level " << level << ", rows = " << rows << ", cols = " << cols << "\n";
      for (unsigned int row = 0; row < rows; row++) {
	for (unsigned int col = 0; col < cols; col++) {
	  for (unsigned int y = 0; y < 4; y++) {
	    for (unsigned int x = 0; x < 4; x++) {
	      int source_offset = base_source_offset + ((row * 4 + y) * target_width + col * 4 + x) * 4;
	      int offset = (y * 4 + x) * 4;
	      input_block[offset++] = data[source_offset + 2];
	      input_block[offset++] = data[source_offset + 1];
	      input_block[offset++] = data[source_offset + 0];
	      input_block[offset++] = 255; // data[source_offset++];
	    }
	  }
	  if (target_format.getCompression() == ImageFormat::ETC1) {
	    rg_etc1::pack_etc1_block(output_data + target_offset, (const unsigned int *)&(input_block[0]), params);
	  } else {
	    stb_compress_dxt_block(output_data + target_offset, &(input_block[0]), false, 0);
	  }
	  target_offset += 8;
	}
      }
      target_width = (target_width + 1) / 2;
      target_height = (target_height + 1) / 2;
    }
    auto r = std::shared_ptr<Image>(new Image(output_data, target_format, width, height, levels));
    delete[] output_data;
    return r;
  } else {
    assert(levels == 1);
    assert(target_format.getBytesPerPixel() == 2);

    unsigned int n = width * height;
    unsigned char * tmp = new unsigned char[target_format.getBytesPerPixel() * n];
    unsigned short * output_data = (unsigned short *)tmp;
    const unsigned int * input_data = (const unsigned int *)data;

    if (target_format.getNumChannels() == 2) {
      for (unsigned int i = 0; i < n; i++) {
	int v = input_data[i];
	int red = RGBA_TO_RED(v);
	int green = RGBA_TO_GREEN(v);
	int blue = RGBA_TO_BLUE(v);
	int alpha = RGBA_TO_ALPHA(v);
	int lum = (red + green + blue) / 3;
	if (lum >= 255) lum = 255;
	*output_data++ = (alpha << 8) | lum;
      }
    } else {
      for (unsigned int i = 0; i < n; i++) {
	int v = input_data[i];
	int red = RGBA_TO_RED(v) >> 3;
	int green = RGBA_TO_GREEN(v) >> 2;
	int blue = RGBA_TO_BLUE(v) >> 3;

#ifdef __APPLE__
	*output_data++ = PACK_RGB565(blue, green, red);
#else
	*output_data++ = PACK_RGB565(red, green, blue);
#endif
      }
    }

    auto r = std::shared_ptr<Image>(new Image(tmp, target_format, getWidth(), getHeight()));
    delete[] tmp;
    return r;
  }
}

std::shared_ptr<Image>
Image::scale(unsigned int target_base_width, unsigned int target_base_height, unsigned int target_levels) const {
  assert(format.getBytesPerPixel() == 4);
  assert(!format.getCompression());
  size_t target_size = calculateOffset(target_base_width, target_base_height, target_levels, format);
  cerr << "scaling to " << target_base_width << " " << target_base_height << " " << target_levels << " => " << target_size << " bytes\n";
  unsigned char * output_data = new unsigned char[target_size];
  unsigned int target_offset = 0, target_width = target_base_width, target_height = target_base_height;
  for (int y = 0; y < int(target_height); y++) {
    for (int x = 0; x < int(target_width); x++) {
      int red = 0, green = 0, blue = 0, alpha = 0, n = 0;
      int y0 = y * getHeight() / target_height;
      int y1 = (y + 1) * getHeight() / target_height;
      int x0 = x * getWidth() / target_width;
      int x1 = (x + 1) * getWidth() / target_width;
      if (y0 == y1) y1++;
      if (x0 == x1) x1++;
      for (int j = y0; j < y1; j++) {
	for (int k = x0; k < x1; k++) {
	  int offset = (j * getHeight() + k) * 4;
	  red += data[offset++];
	  green += data[offset++];
	  blue += data[offset++];
	  alpha += data[offset++];
	  n++;
	}
      }
      output_data[target_offset++] = (unsigned char)(red / n);
      output_data[target_offset++] = (unsigned char)(green / n);
      output_data[target_offset++] = (unsigned char)(blue / n);
      output_data[target_offset++] = (unsigned char)(alpha / n);
    }
  }

  if (target_levels > 1) {
    unsigned int source_width = target_width, source_height = target_height;
    target_width /= 2;
    target_height /= 2;

    for (unsigned int level = 1; level < target_levels; level++) {
      unsigned char * source_data = output_data + calculateOffset(target_base_width, target_base_height, level - 1, format);
      unsigned char * target_data = output_data + calculateOffset(target_base_width, target_base_height, level, format);
      for (int y = 0; y < target_height; y++) {
	for (int x = 0; x < target_width; x++) {
	  unsigned int source_offset = (2 * y * source_width + 2 * x) * 4;
	  unsigned int target_offset = (y * target_width + x) * 4;
	  for (unsigned int c = 0; c < 4; c++) {
	    target_data[target_offset] = ((int)source_data[source_offset]  +
					  (int)source_data[source_offset + 4]  +
					  (int)source_data[source_offset + 4 + 4 * source_width] +
					  (int)source_data[source_offset + 4 * source_width]) / 4;
	    source_offset++;
	    target_offset++;
	  }
	}
      }
      source_width = target_width;
      source_height = target_height;
      target_width /= 2;
      target_height /= 2;
    }
  }
  std::shared_ptr<Image> image2(new Image(output_data, format, target_base_width, target_base_height, target_levels));
  delete[] output_data;
  return image2;
}

std::shared_ptr<Image>
Image::createMipmaps(unsigned int target_levels) const {
  assert(format.getBytesPerPixel() == 4);
  assert(!format.getCompression());
  assert(levels == 1);
  size_t target_size = calculateOffset(target_levels);
  unsigned char * output_data = new unsigned char[target_size];
  memcpy(output_data, data, calculateOffset(1));
  unsigned int source_width = width, source_height = height;
  unsigned int target_width = width / 2, target_height = height / 2;
  for (unsigned int level = 1; level < target_levels; level++) {
    unsigned char * source_data = output_data + calculateOffset(level - 1);
    unsigned char * target_data = output_data + calculateOffset(level);
    for (int y = 0; y < target_height; y++) {
      for (int x = 0; x < target_width; x++) {
	unsigned int source_offset = (2 * y * source_width + 2 * x) * 4;
	unsigned int target_offset = (y * target_width + x) * 4;
	for (unsigned int c = 0; c < 4; c++) {
	  target_data[target_offset] = ((int)source_data[source_offset]  +
					(int)source_data[source_offset + 4]  +
					(int)source_data[source_offset + 4 + 4 * source_width] +
					(int)source_data[source_offset + 4 * source_width]) / 4;
	  source_offset++;
	  target_offset++;
	}
      }
    }
    source_width = target_width;
    source_height = target_height;
    target_width /= 2;
    target_height /= 2;
  }
  std::shared_ptr<Image> image2(new Image(output_data, format, width, height, target_levels));
  delete[] output_data;
  return image2;
}
<commit_msg>switch byte order and decrease quality for ETC1<commit_after>#include "Image.h"

#include <cassert>
#include <iostream>

#include "rg_etc1.h"
#include "dxt.h"

using namespace std;
using namespace canvas;

bool Image::etc1_initialized = false;

std::shared_ptr<Image>
Image::convert(const ImageFormat & target_format) const {
  assert(format.getBytesPerPixel() == 4);
  assert(!format.getCompression());

  if (target_format.getCompression() == ImageFormat::DXT1 || target_format.getCompression() == ImageFormat::ETC1) {
    rg_etc1::etc1_pack_params params;
    params.m_quality = rg_etc1::cLowQuality;
    if (target_format.getCompression() == ImageFormat::ETC1 && !etc1_initialized) {
      cerr << "initializing etc1" << endl;
      etc1_initialized = true;
      rg_etc1::pack_etc1_block_init();
    }
    assert((width & 3) == 0);
    assert((height & 3) == 0);
    unsigned int target_width = width, target_height = height;
    unsigned int target_size = calculateSize(target_width, target_height, levels, target_format);
    unsigned char * output_data = new unsigned char[target_size];
    unsigned char input_block[4*4*4];
    unsigned int target_offset = 0;
    for (unsigned int level = 0; level < levels; level++) {
      unsigned int rows = (target_height + 3) / 4, cols = (target_width + 3) / 4;
      int base_source_offset = calculateOffset(level);
      cerr << "compressing texture, level " << level << ", rows = " << rows << ", cols = " << cols << "\n";
      for (unsigned int row = 0; row < rows; row++) {
	for (unsigned int col = 0; col < cols; col++) {
	  for (unsigned int y = 0; y < 4; y++) {
	    for (unsigned int x = 0; x < 4; x++) {
	      int source_offset = base_source_offset + ((row * 4 + y) * target_width + col * 4 + x) * 4;
	      int offset = (y * 4 + x) * 4;
	      if (target_format.getCompression() == ImageFormat::ETC1) {
		input_block[offset++] = data[source_offset++];
		input_block[offset++] = data[source_offset++];
		input_block[offset++] = data[source_offset++];
	      } else {
		input_block[offset++] = data[source_offset + 2];
		input_block[offset++] = data[source_offset + 1];
		input_block[offset++] = data[source_offset + 0];
	      }
	      input_block[offset++] = 255; // data[source_offset++];
	    }
	  }
	  if (target_format.getCompression() == ImageFormat::ETC1) {
	    rg_etc1::pack_etc1_block(output_data + target_offset, (const unsigned int *)&(input_block[0]), params);
	  } else {
	    stb_compress_dxt_block(output_data + target_offset, &(input_block[0]), false, 0);
	  }
	  target_offset += 8;
	}
      }
      target_width = (target_width + 1) / 2;
      target_height = (target_height + 1) / 2;
    }
    auto r = std::shared_ptr<Image>(new Image(output_data, target_format, width, height, levels));
    delete[] output_data;
    return r;
  } else {
    assert(levels == 1);
    assert(target_format.getBytesPerPixel() == 2);

    unsigned int n = width * height;
    unsigned char * tmp = new unsigned char[target_format.getBytesPerPixel() * n];
    unsigned short * output_data = (unsigned short *)tmp;
    const unsigned int * input_data = (const unsigned int *)data;

    if (target_format.getNumChannels() == 2) {
      for (unsigned int i = 0; i < n; i++) {
	int v = input_data[i];
	int red = RGBA_TO_RED(v);
	int green = RGBA_TO_GREEN(v);
	int blue = RGBA_TO_BLUE(v);
	int alpha = RGBA_TO_ALPHA(v);
	int lum = (red + green + blue) / 3;
	if (lum >= 255) lum = 255;
	*output_data++ = (alpha << 8) | lum;
      }
    } else {
      for (unsigned int i = 0; i < n; i++) {
	int v = input_data[i];
	int red = RGBA_TO_RED(v) >> 3;
	int green = RGBA_TO_GREEN(v) >> 2;
	int blue = RGBA_TO_BLUE(v) >> 3;

#ifdef __APPLE__
	*output_data++ = PACK_RGB565(blue, green, red);
#else
	*output_data++ = PACK_RGB565(red, green, blue);
#endif
      }
    }

    auto r = std::shared_ptr<Image>(new Image(tmp, target_format, getWidth(), getHeight()));
    delete[] tmp;
    return r;
  }
}

std::shared_ptr<Image>
Image::scale(unsigned int target_base_width, unsigned int target_base_height, unsigned int target_levels) const {
  assert(format.getBytesPerPixel() == 4);
  assert(!format.getCompression());
  size_t input_size = calculateSize();
  size_t target_size = calculateOffset(target_base_width, target_base_height, target_levels, format);
  cerr << "scaling to " << target_base_width << " " << target_base_height << " " << target_levels << " => " << target_size << " bytes\n";
  unsigned char * output_data = new unsigned char[target_size];
  unsigned int target_offset = 0, target_width = target_base_width, target_height = target_base_height;
  for (int y = 0; y < int(target_height); y++) {
    for (int x = 0; x < int(target_width); x++) {
      int red = 0, green = 0, blue = 0, alpha = 0, n = 0;
      int y0 = y * getHeight() / target_height;
      int y1 = (y + 1) * getHeight() / target_height;
      int x0 = x * getWidth() / target_width;
      int x1 = (x + 1) * getWidth() / target_width;
      if (y0 == y1 && y1 < height) y1++;
      if (x0 == x1 && x1 < width) x1++;
      for (int j = y0; j < y1; j++) {
	for (int k = x0; k < x1; k++) {
          int offset = (j * getWidth() + k) * 4;
          assert(offset + 4 <= input_size);
          red += data[offset++];
	  green += data[offset++];
	  blue += data[offset++];
	  alpha += data[offset++];
	  n++;
	}
      }
      output_data[target_offset++] = (unsigned char)(red / n);
      output_data[target_offset++] = (unsigned char)(green / n);
      output_data[target_offset++] = (unsigned char)(blue / n);
      output_data[target_offset++] = (unsigned char)(alpha / n);
    }
  }

  if (target_levels > 1) {
    unsigned int source_width = target_width, source_height = target_height;
    target_width /= 2;
    target_height /= 2;

    for (unsigned int level = 1; level < target_levels; level++) {
      unsigned char * source_data = output_data + calculateOffset(target_base_width, target_base_height, level - 1, format);
      unsigned char * target_data = output_data + calculateOffset(target_base_width, target_base_height, level, format);
      for (int y = 0; y < target_height; y++) {
	for (int x = 0; x < target_width; x++) {
	  unsigned int source_offset = (2 * y * source_width + 2 * x) * 4;
	  unsigned int target_offset = (y * target_width + x) * 4;
	  for (unsigned int c = 0; c < 4; c++) {
	    target_data[target_offset] = ((int)source_data[source_offset]  +
					  (int)source_data[source_offset + 4]  +
					  (int)source_data[source_offset + 4 + 4 * source_width] +
					  (int)source_data[source_offset + 4 * source_width]) / 4;
	    source_offset++;
	    target_offset++;
	  }
	}
      }
      source_width = target_width;
      source_height = target_height;
      target_width /= 2;
      target_height /= 2;
    }
  }
  std::shared_ptr<Image> image2(new Image(output_data, format, target_base_width, target_base_height, target_levels));
  delete[] output_data;
  return image2;
}

std::shared_ptr<Image>
Image::createMipmaps(unsigned int target_levels) const {
  assert(format.getBytesPerPixel() == 4);
  assert(!format.getCompression());
  assert(levels == 1);
  size_t target_size = calculateOffset(target_levels);
  unsigned char * output_data = new unsigned char[target_size];
  memcpy(output_data, data, calculateOffset(1));
  unsigned int source_width = width, source_height = height;
  unsigned int target_width = width / 2, target_height = height / 2;
  for (unsigned int level = 1; level < target_levels; level++) {
    unsigned char * source_data = output_data + calculateOffset(level - 1);
    unsigned char * target_data = output_data + calculateOffset(level);
    for (int y = 0; y < target_height; y++) {
      for (int x = 0; x < target_width; x++) {
	unsigned int source_offset = (2 * y * source_width + 2 * x) * 4;
	unsigned int target_offset = (y * target_width + x) * 4;
	for (unsigned int c = 0; c < 4; c++) {
	  target_data[target_offset] = ((int)source_data[source_offset]  +
					(int)source_data[source_offset + 4]  +
					(int)source_data[source_offset + 4 + 4 * source_width] +
					(int)source_data[source_offset + 4 * source_width]) / 4;
	  source_offset++;
	  target_offset++;
	}
      }
    }
    source_width = target_width;
    source_height = target_height;
    target_width /= 2;
    target_height /= 2;
  }
  std::shared_ptr<Image> image2(new Image(output_data, format, width, height, target_levels));
  delete[] output_data;
  return image2;
}
<|endoftext|>


<commit_before>#include "Lidar.hpp"

Lidar::Lidar(I2C::Port port, uint8_t address) : comm()
{

}
<commit_msg>finished lidar constructor<commit_after>#include "Lidar.hpp"

Lidar::Lidar(I2C::Port port, uint8_t address) : comm(port, address)
{

}
<|endoftext|>