<commit_before>/*
Copyright (c) 2014-15 Ableton AG, Berlin

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

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

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

#include "CssParser.hpp"

#include "Warnings.hpp"

SUPPRESS_WARNINGS
#include <boost/variant/get.hpp>
#include <boost/variant/variant.hpp>
#include <gtest/gtest.h>
RESTORE_WARNINGS

//========================================================================================

using namespace aqt::stylesheets;

namespace
{

std::string selectorNames(const StyleSheet& ss,
                          size_t propsetIndex,
                          size_t selNumber,
                          size_t selIndex0,
                          size_t selIndex1)
{
  return ss.propsets[propsetIndex].selectors[selNumber][selIndex0][selIndex1];
}

std::string selectorName(const StyleSheet& ss,
                         size_t propsetIndex,
                         size_t selIndex0,
                         size_t selIndex1)
{
  return ss.propsets[propsetIndex].selectors[0][selIndex0][selIndex1];
}

std::string getFirstValue(const PropertyValues& val, const std::string& def = "")
{
  if (!val.empty()) {
    if (const std::string* str = boost::get<std::string>(&val[0])) {
      return *str;
    }
  }

  return def;
}

Expression getExpr(const PropertyValues& val, size_t idx, const Expression& def = {})
{
  if (!val.empty()) {
    if (const Expression* expr = boost::get<Expression>(&val[idx])) {
      return *expr;
    }
  }

  return def;
}

size_t getNumberOfValues(const PropertyValues& val)
{
  return val.size();
}

} // anonymous namespace

TEST(CssParserTest, ParserFromString_basic)
{
  const std::string src =
    "A { \n"
    "  background: red;\n"
    "}\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);

  EXPECT_EQ(ss.propsets[0].properties.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties[0].name, "background");
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[0].values), std::string("red"));
}

TEST(CssParserTest, ParserFromString_selectors)
{
  const std::string src =
    "A.b { color: #123456; }\n"
    ".b { text: 'green'; }\n"
    "A B.b { background: yellow; }\n"
    "A B .b { foreground: black; }\n"
    "A .b .c { foreground: black; }\n"
    ".b.a { text: 'a and b'; }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 6);
  EXPECT_EQ(selectorName(ss, 0, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 0, 0, 1), ".b");

  EXPECT_EQ(selectorName(ss, 1, 0, 0), ".b");

  EXPECT_EQ(selectorName(ss, 2, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 2, 1, 0), "B");
  EXPECT_EQ(selectorName(ss, 2, 1, 1), ".b");

  EXPECT_EQ(selectorName(ss, 3, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 3, 1, 0), "B");
  EXPECT_EQ(selectorName(ss, 3, 2, 0), ".b");

  EXPECT_EQ(ss.propsets[3].properties.size(), 1);
  EXPECT_EQ(ss.propsets[3].properties[0].name, "foreground");
  EXPECT_EQ(getFirstValue(ss.propsets[3].properties[0].values), std::string("black"));

  EXPECT_EQ(selectorName(ss, 4, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 4, 1, 0), ".b");
  EXPECT_EQ(selectorName(ss, 4, 2, 0), ".c");

  EXPECT_EQ(selectorName(ss, 5, 0, 0), ".b");
  EXPECT_EQ(selectorName(ss, 5, 0, 1), ".a");
}

TEST(CssParserTest, ParserFromString_separatedSelectors)
{
  const std::string src =
    "A, B, C { foreground: black; }\n"
    "A.a B.b, A.a C.c { foreground: black; }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(selectorNames(ss, 0, 0, 0, 0), "A");
  EXPECT_EQ(selectorNames(ss, 0, 1, 0, 0), "B");
  EXPECT_EQ(selectorNames(ss, 0, 2, 0, 0), "C");

  EXPECT_EQ(selectorNames(ss, 1, 0, 0, 0), "A");
  EXPECT_EQ(selectorNames(ss, 1, 0, 0, 1), ".a");
  EXPECT_EQ(selectorNames(ss, 1, 0, 1, 0), "B");
  EXPECT_EQ(selectorNames(ss, 1, 0, 1, 1), ".b");
  EXPECT_EQ(selectorNames(ss, 1, 1, 0, 0), "A");
  EXPECT_EQ(selectorNames(ss, 1, 1, 0, 1), ".a");
  EXPECT_EQ(selectorNames(ss, 1, 1, 1, 0), "C");
  EXPECT_EQ(selectorNames(ss, 1, 1, 1, 1), ".c");
}

TEST(CssParserTest, ParserFromString_childrenSelectors)
{
  const std::string src = "A.b > B.c { color: #123456; }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(selectorName(ss, 0, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 0, 0, 1), ".b");
  EXPECT_EQ(selectorName(ss, 0, 1, 0), ">");
  EXPECT_EQ(selectorName(ss, 0, 2, 0), "B");
  EXPECT_EQ(selectorName(ss, 0, 2, 1), ".c");
}

TEST(CssParserTest, ParserFromString_properties)
{
  const std::string src =
    "X {\n"
    "  abc: #123456; \n"
    "  def: 'string'; \n"
    "  ghi: \"string\"; \n"
    "  jkl: 1234; \n"
    "  mno: 123.45; \n"
    "  pqr: symbol; \n"
    "}\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties.size(), 6);

  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[0].values), std::string("#123456"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[1].values), std::string("string"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[2].values), std::string("string"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[3].values), std::string("1234"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[4].values), std::string("123.45"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[5].values), std::string("symbol"));
}

TEST(CssParserTest, ParserFromString_stringProperties)
{
  const std::string src =
    "X {\n"
    "  def: 'str\"ing'; \n"
    "  ghi: \"str'ing\"; \n"
    "}\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);

  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[0].values), std::string("str\"ing"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[1].values), std::string("str'ing"));
}

TEST(CssParserTest, ParserFromString_emptyString)
{
  const std::string src = "";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_onlyWhitespace)
{
  const std::string src =
    "\n\n\n"
    "\t\t       \n\r"
    "\n";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_onlyCppComment)
{
  const std::string src = "// Copyright 2014 by Yoyodyne Inc.\n";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_onlyComment)
{
  const std::string src = "/* Copyright 2014 by Yoyodyne Inc. */\n";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_crlfNewlines)
{
  const std::string src =
    "X {\r\n"
    "abc: #123456; \r\n"
    "def: 'string'; \r\n"
    "}\r\n"
    "X .a {\r\n"
    "xyz: red;\r\n"
    "}\r\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_mixedNewlines)
{
  const std::string src =
    "X {\r\n"
    "abc: #123456; \n\r"
    "def: 'string'; \n"
    "}"
    "X .a {"
    "xyz: red;"
    "}\n\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_noNewlines)
{
  const std::string src =
    "X {"
    "abc: #123456;"
    "def: 'string';"
    "}"
    "X .a {"
    "xyz: red;"
    "}";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_noSemicolons)
{
  const std::string src =
    "X {"
    "  abc: #123456"
    "  def: 'string'"
    "}"
    "X .a {"
    "  xyz: red"
    "}";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_multipleValues)
{
  const std::string src =
    "X {"
    "  abc: a, b, c, d;\n"
    "}";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties.size(), 1);
  EXPECT_EQ(getNumberOfValues(ss.propsets[0].properties[0].values), 4);
}

TEST(CssParserTest, ParserFromString_fontFaceDeclarations)
{
  const std::string src =
    "// Copyright\n"
    "@font-face { src: url('../../Assets/times.ttf'); }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
  EXPECT_EQ(ss.fontfaces.size(), 1);

  EXPECT_EQ(ss.fontfaces[0].url, "../../Assets/times.ttf");
}

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

TEST(CssParserTest, ParserFromString_Expressions)
{
  const std::string src = "foo { bar: url('hello world'); }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(1, ss.propsets.size());
  EXPECT_EQ(1, ss.propsets[0].properties.size());
  EXPECT_EQ(1, getNumberOfValues(ss.propsets[0].properties[0].values));

  EXPECT_EQ(std::string("url"), getExpr(ss.propsets[0].properties[0].values, 0).name);
  EXPECT_EQ((std::vector<std::string>{"hello world"}),
            getExpr(ss.propsets[0].properties[0].values, 0).args);
}

TEST(CssParserTest, ParserFromString_ExpressionsInLists)
{
  const std::string src =
    "foo { bar: rgba(123, 45, 92, 0.1), "
    "           foo(), "
    "           hsla(320, 100%, 20%, 0.3); }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(1, ss.propsets.size());
  EXPECT_EQ(1, ss.propsets[0].properties.size());

  EXPECT_EQ(std::string("rgba"), getExpr(ss.propsets[0].properties[0].values, 0).name);
  EXPECT_EQ((std::vector<std::string>{"123", "45", "92", "0.1"}),
            getExpr(ss.propsets[0].properties[0].values, 0).args);
  EXPECT_EQ(std::string("foo"), getExpr(ss.propsets[0].properties[0].values, 1).name);
  EXPECT_TRUE(getExpr(ss.propsets[0].properties[0].values, 1).args.empty());

  EXPECT_EQ(std::string("hsla"), getExpr(ss.propsets[0].properties[0].values, 2).name);
  EXPECT_EQ((std::vector<std::string>{"320", "100%", "20%", "0.3"}),
            getExpr(ss.propsets[0].properties[0].values, 2).args);
}

/* Missing tests:

   pathological cases:
   - non closed }
   - non closed "
   - non closed '
   - ambiguous selectors
   - no selectors
   - invalid chars in selector
   - invalid chars in propertyname
 */
<commit_msg>Specify type for default value in method<commit_after>/*
Copyright (c) 2014-15 Ableton AG, Berlin

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

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

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

#include "CssParser.hpp"

#include "Warnings.hpp"

SUPPRESS_WARNINGS
#include <boost/variant/get.hpp>
#include <boost/variant/variant.hpp>
#include <gtest/gtest.h>
RESTORE_WARNINGS

//========================================================================================

using namespace aqt::stylesheets;

namespace
{

std::string selectorNames(const StyleSheet& ss,
                          size_t propsetIndex,
                          size_t selNumber,
                          size_t selIndex0,
                          size_t selIndex1)
{
  return ss.propsets[propsetIndex].selectors[selNumber][selIndex0][selIndex1];
}

std::string selectorName(const StyleSheet& ss,
                         size_t propsetIndex,
                         size_t selIndex0,
                         size_t selIndex1)
{
  return ss.propsets[propsetIndex].selectors[0][selIndex0][selIndex1];
}

std::string getFirstValue(const PropertyValues& val, const std::string& def = "")
{
  if (!val.empty()) {
    if (const std::string* str = boost::get<std::string>(&val[0])) {
      return *str;
    }
  }

  return def;
}

Expression getExpr(const PropertyValues& val, size_t idx, const Expression& def = Expression{})
{
  if (!val.empty()) {
    if (const Expression* expr = boost::get<Expression>(&val[idx])) {
      return *expr;
    }
  }

  return def;
}

size_t getNumberOfValues(const PropertyValues& val)
{
  return val.size();
}

} // anonymous namespace

TEST(CssParserTest, ParserFromString_basic)
{
  const std::string src =
    "A { \n"
    "  background: red;\n"
    "}\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);

  EXPECT_EQ(ss.propsets[0].properties.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties[0].name, "background");
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[0].values), std::string("red"));
}

TEST(CssParserTest, ParserFromString_selectors)
{
  const std::string src =
    "A.b { color: #123456; }\n"
    ".b { text: 'green'; }\n"
    "A B.b { background: yellow; }\n"
    "A B .b { foreground: black; }\n"
    "A .b .c { foreground: black; }\n"
    ".b.a { text: 'a and b'; }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 6);
  EXPECT_EQ(selectorName(ss, 0, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 0, 0, 1), ".b");

  EXPECT_EQ(selectorName(ss, 1, 0, 0), ".b");

  EXPECT_EQ(selectorName(ss, 2, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 2, 1, 0), "B");
  EXPECT_EQ(selectorName(ss, 2, 1, 1), ".b");

  EXPECT_EQ(selectorName(ss, 3, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 3, 1, 0), "B");
  EXPECT_EQ(selectorName(ss, 3, 2, 0), ".b");

  EXPECT_EQ(ss.propsets[3].properties.size(), 1);
  EXPECT_EQ(ss.propsets[3].properties[0].name, "foreground");
  EXPECT_EQ(getFirstValue(ss.propsets[3].properties[0].values), std::string("black"));

  EXPECT_EQ(selectorName(ss, 4, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 4, 1, 0), ".b");
  EXPECT_EQ(selectorName(ss, 4, 2, 0), ".c");

  EXPECT_EQ(selectorName(ss, 5, 0, 0), ".b");
  EXPECT_EQ(selectorName(ss, 5, 0, 1), ".a");
}

TEST(CssParserTest, ParserFromString_separatedSelectors)
{
  const std::string src =
    "A, B, C { foreground: black; }\n"
    "A.a B.b, A.a C.c { foreground: black; }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(selectorNames(ss, 0, 0, 0, 0), "A");
  EXPECT_EQ(selectorNames(ss, 0, 1, 0, 0), "B");
  EXPECT_EQ(selectorNames(ss, 0, 2, 0, 0), "C");

  EXPECT_EQ(selectorNames(ss, 1, 0, 0, 0), "A");
  EXPECT_EQ(selectorNames(ss, 1, 0, 0, 1), ".a");
  EXPECT_EQ(selectorNames(ss, 1, 0, 1, 0), "B");
  EXPECT_EQ(selectorNames(ss, 1, 0, 1, 1), ".b");
  EXPECT_EQ(selectorNames(ss, 1, 1, 0, 0), "A");
  EXPECT_EQ(selectorNames(ss, 1, 1, 0, 1), ".a");
  EXPECT_EQ(selectorNames(ss, 1, 1, 1, 0), "C");
  EXPECT_EQ(selectorNames(ss, 1, 1, 1, 1), ".c");
}

TEST(CssParserTest, ParserFromString_childrenSelectors)
{
  const std::string src = "A.b > B.c { color: #123456; }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(selectorName(ss, 0, 0, 0), "A");
  EXPECT_EQ(selectorName(ss, 0, 0, 1), ".b");
  EXPECT_EQ(selectorName(ss, 0, 1, 0), ">");
  EXPECT_EQ(selectorName(ss, 0, 2, 0), "B");
  EXPECT_EQ(selectorName(ss, 0, 2, 1), ".c");
}

TEST(CssParserTest, ParserFromString_properties)
{
  const std::string src =
    "X {\n"
    "  abc: #123456; \n"
    "  def: 'string'; \n"
    "  ghi: \"string\"; \n"
    "  jkl: 1234; \n"
    "  mno: 123.45; \n"
    "  pqr: symbol; \n"
    "}\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties.size(), 6);

  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[0].values), std::string("#123456"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[1].values), std::string("string"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[2].values), std::string("string"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[3].values), std::string("1234"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[4].values), std::string("123.45"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[5].values), std::string("symbol"));
}

TEST(CssParserTest, ParserFromString_stringProperties)
{
  const std::string src =
    "X {\n"
    "  def: 'str\"ing'; \n"
    "  ghi: \"str'ing\"; \n"
    "}\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);

  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[0].values), std::string("str\"ing"));
  EXPECT_EQ(getFirstValue(ss.propsets[0].properties[1].values), std::string("str'ing"));
}

TEST(CssParserTest, ParserFromString_emptyString)
{
  const std::string src = "";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_onlyWhitespace)
{
  const std::string src =
    "\n\n\n"
    "\t\t       \n\r"
    "\n";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_onlyCppComment)
{
  const std::string src = "// Copyright 2014 by Yoyodyne Inc.\n";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_onlyComment)
{
  const std::string src = "/* Copyright 2014 by Yoyodyne Inc. */\n";
  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
}

TEST(CssParserTest, ParserFromString_crlfNewlines)
{
  const std::string src =
    "X {\r\n"
    "abc: #123456; \r\n"
    "def: 'string'; \r\n"
    "}\r\n"
    "X .a {\r\n"
    "xyz: red;\r\n"
    "}\r\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_mixedNewlines)
{
  const std::string src =
    "X {\r\n"
    "abc: #123456; \n\r"
    "def: 'string'; \n"
    "}"
    "X .a {"
    "xyz: red;"
    "}\n\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_noNewlines)
{
  const std::string src =
    "X {"
    "abc: #123456;"
    "def: 'string';"
    "}"
    "X .a {"
    "xyz: red;"
    "}";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_noSemicolons)
{
  const std::string src =
    "X {"
    "  abc: #123456"
    "  def: 'string'"
    "}"
    "X .a {"
    "  xyz: red"
    "}";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 2);
  EXPECT_EQ(ss.propsets[0].properties.size(), 2);
  EXPECT_EQ(ss.propsets[1].properties.size(), 1);
}

TEST(CssParserTest, ParserFromString_multipleValues)
{
  const std::string src =
    "X {"
    "  abc: a, b, c, d;\n"
    "}";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 1);
  EXPECT_EQ(ss.propsets[0].properties.size(), 1);
  EXPECT_EQ(getNumberOfValues(ss.propsets[0].properties[0].values), 4);
}

TEST(CssParserTest, ParserFromString_fontFaceDeclarations)
{
  const std::string src =
    "// Copyright\n"
    "@font-face { src: url('../../Assets/times.ttf'); }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(ss.propsets.size(), 0);
  EXPECT_EQ(ss.fontfaces.size(), 1);

  EXPECT_EQ(ss.fontfaces[0].url, "../../Assets/times.ttf");
}

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

TEST(CssParserTest, ParserFromString_Expressions)
{
  const std::string src = "foo { bar: url('hello world'); }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(1, ss.propsets.size());
  EXPECT_EQ(1, ss.propsets[0].properties.size());
  EXPECT_EQ(1, getNumberOfValues(ss.propsets[0].properties[0].values));

  EXPECT_EQ(std::string("url"), getExpr(ss.propsets[0].properties[0].values, 0).name);
  EXPECT_EQ((std::vector<std::string>{"hello world"}),
            getExpr(ss.propsets[0].properties[0].values, 0).args);
}

TEST(CssParserTest, ParserFromString_ExpressionsInLists)
{
  const std::string src =
    "foo { bar: rgba(123, 45, 92, 0.1), "
    "           foo(), "
    "           hsla(320, 100%, 20%, 0.3); }\n";

  StyleSheet ss = parseStdString(src);
  EXPECT_EQ(1, ss.propsets.size());
  EXPECT_EQ(1, ss.propsets[0].properties.size());

  EXPECT_EQ(std::string("rgba"), getExpr(ss.propsets[0].properties[0].values, 0).name);
  EXPECT_EQ((std::vector<std::string>{"123", "45", "92", "0.1"}),
            getExpr(ss.propsets[0].properties[0].values, 0).args);
  EXPECT_EQ(std::string("foo"), getExpr(ss.propsets[0].properties[0].values, 1).name);
  EXPECT_TRUE(getExpr(ss.propsets[0].properties[0].values, 1).args.empty());

  EXPECT_EQ(std::string("hsla"), getExpr(ss.propsets[0].properties[0].values, 2).name);
  EXPECT_EQ((std::vector<std::string>{"320", "100%", "20%", "0.3"}),
            getExpr(ss.propsets[0].properties[0].values, 2).args);
}

/* Missing tests:

   pathological cases:
   - non closed }
   - non closed "
   - non closed '
   - ambiguous selectors
   - no selectors
   - invalid chars in selector
   - invalid chars in propertyname
 */
<|endoftext|>


<commit_before>#include "Mocks.hpp"

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

namespace asio = boost::asio;

namespace blackhole {

namespace sink {

class boost_asio_backend_t {
    const std::string host;
    const std::uint16_t port;

    asio::io_service io_service;
    asio::ip::udp::endpoint endpoint;
    std::unique_ptr<asio::ip::udp::socket> socket;

public:
    boost_asio_backend_t(const std::string& host, std::uint16_t port) :
        host(host),
        port(port)
    {
        asio::ip::udp::resolver resolver(io_service);
        asio::ip::udp::resolver::query query(host, boost::lexical_cast<std::string>(port));
        asio::ip::udp::resolver::iterator it = resolver.resolve(query); //!@todo: May throw! Whatever.
        std::vector<asio::ip::udp::endpoint> endpoints(it, asio::ip::udp::resolver::iterator());

        for (auto it = endpoints.begin(); it != endpoints.end(); ++it) {
            try {
                socket = std::make_unique<asio::ip::udp::socket>(io_service);
                socket->open(it->protocol());
                endpoint = *it;
                break;
            } catch (const boost::system::system_error& err) {
                std::cout << err.what() << std::endl;
                continue;
            }
        }

        if (!socket) {
            throw error_t("couldn't open UDP socket at %s:%d", host, port);
        }
    }

    ssize_t write(const std::string& message) {
        return socket->send_to(boost::asio::buffer(message.data(), message.size()), endpoint);
    }
};

template<typename Backend = boost_asio_backend_t>
class socket_t {
    Backend m_backend;

public:
    socket_t(const std::string& host, std::uint16_t port) :
        m_backend(host, port)
    {
    }

    void consume(const std::string& message) {
        m_backend.write(message);
    }

    Backend& backend() {
        return m_backend;
    }
};

class tcp_socket_t {
    const std::string host;
    const std::uint16_t port;

    asio::io_service io_service;
    std::unique_ptr<asio::ip::tcp::socket> socket;

public:
    tcp_socket_t(const std::string& host, std::uint16_t port) :
        host(host),
        port(port),
        socket(initialize(io_service, host, port))
    {
    }

    void consume(const std::string& message) {
        if (!socket) {
            socket = initialize(io_service, host, port);
        }

        try {
            socket->write_some(boost::asio::buffer(message.data(), message.size()));
        } catch (const boost::system::system_error& err) {
            socket.release();
            std::rethrow_exception(std::current_exception());
        }
    }

private:
    static inline
    std::unique_ptr<asio::ip::tcp::socket>
    initialize(asio::io_service& io_service, const std::string& host, std::uint16_t port) {
        auto socket = std::make_unique<asio::ip::tcp::socket>(io_service);
        connect(io_service, *socket, host, port);
        return socket;
    }

    static inline
    void
    connect(asio::io_service& io_service, asio::ip::tcp::socket& socket, const std::string& host, std::uint16_t port) {
        try {
            asio::ip::tcp::resolver resolver(io_service);
            asio::ip::tcp::resolver::query query(host, boost::lexical_cast<std::string>(port));
            asio::ip::tcp::resolver::iterator it = resolver.resolve(query);

            try {
                asio::connect(socket, it);
            } catch (const boost::system::system_error& err) {
                throw error_t("couldn't connect to the %s:%d - %s", host, port, err.what());
            }
        } catch (const boost::system::system_error& err) {
            throw error_t("couldn't resolve %s:%d - %s", host, port, err.what());
        }
    }
};

} // namespace sink

} // namespace blackhole

TEST(socket_t, Class) {
    sink::socket_t<> sink("localhost", 50030);
    UNUSED(sink);
}

TEST(socket_t, TestCanSendMessages) {
    sink::socket_t<NiceMock<mock::socket::backend_t>> sink("localhost", 50030);
    EXPECT_CALL(sink.backend(), write(std::string("formatted message"))).
            Times(1);
    sink.consume("formatted message");
}

TEST(socket_t, ThrowsExceptionOnAnyWriteErrorOccurred) {
    // This behaviour is normal for blocking udp/tcp socket sink.
    // When some network error occurs, message is on the half way to be dropped.
    // In case of UDP socket, handler will try to reopen socket immediately and rewrite again here
    // and every next message.
    // In case of TCP socket, handler will try to reconnect on every next message before sending.
    sink::socket_t<NiceMock<mock::socket::backend_t>> sink("localhost", 50030);
    EXPECT_CALL(sink.backend(), write(_))
            .Times(1)
            .WillOnce(Throw(std::exception()));
    EXPECT_THROW(sink.consume("message"), std::exception);
}

TEST(socket_t, ThrowsExceptionWhenCannotAcquireResource) {
    // This is initialization behaviour and cannot be caught by any log backend. If handler cannot
    // acquire resource needed, it can't continue its work, so it's neccessary to notify upper level
    // code about it.
    EXPECT_THROW(sink::socket_t<NiceMock<mock::socket::failing_backend_t>>("localhost", 50030), std::exception); //!@todo: Maybe some kind of typecheck here?
}

TEST(socket_t, Manual) {
    sink::tcp_socket_t sink("localhost", 50030);
    int i = 0;
    while (true) {
        try {
            sink.consume(utils::format("{\"@message\": \"value = %d\"}\n", i));
        } catch (std::exception& e) {
            std::cout << utils::format("I've fucked up: %s", e.what()) << std::endl;
        }

        i++;
        usleep(1000000);
    }
}
<commit_msg>Explicit is better than implicit.<commit_after>#include "Mocks.hpp"

#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

namespace asio = boost::asio;

namespace blackhole {

namespace sink {

class boost_asio_backend_t {
    const std::string host;
    const std::uint16_t port;

    asio::io_service io_service;
    asio::ip::udp::endpoint endpoint;
    std::unique_ptr<asio::ip::udp::socket> socket;

public:
    boost_asio_backend_t(const std::string& host, std::uint16_t port) :
        host(host),
        port(port)
    {
        asio::ip::udp::resolver resolver(io_service);
        asio::ip::udp::resolver::query query(host, boost::lexical_cast<std::string>(port));
        asio::ip::udp::resolver::iterator it = resolver.resolve(query); //!@todo: May throw! Whatever.
        std::vector<asio::ip::udp::endpoint> endpoints(it, asio::ip::udp::resolver::iterator());

        for (auto it = endpoints.begin(); it != endpoints.end(); ++it) {
            try {
                socket = std::make_unique<asio::ip::udp::socket>(io_service);
                socket->open(it->protocol());
                endpoint = *it;
                break;
            } catch (const boost::system::system_error& err) {
                std::cout << err.what() << std::endl;
                continue;
            }
        }

        if (!socket) {
            throw error_t("couldn't open UDP socket at %s:%d", host, port);
        }
    }

    ssize_t write(const std::string& message) {
        return socket->send_to(boost::asio::buffer(message.data(), message.size()), endpoint);
    }
};

template<typename Backend = boost_asio_backend_t>
class socket_t {
    Backend m_backend;

public:
    socket_t(const std::string& host, std::uint16_t port) :
        m_backend(host, port)
    {
    }

    void consume(const std::string& message) {
        m_backend.write(message);
    }

    Backend& backend() {
        return m_backend;
    }
};

class tcp_socket_t {
    const std::string host;
    const std::uint16_t port;

    asio::io_service io_service;
    std::unique_ptr<asio::ip::tcp::socket> socket;

public:
    tcp_socket_t(const std::string& host, std::uint16_t port) :
        host(host),
        port(port),
        socket(initialize(io_service, host, port))
    {
    }

    void consume(const std::string& message) {
        if (!socket) {
            socket = initialize(io_service, host, port);
        }

        try {
            socket->write_some(boost::asio::buffer(message.data(), message.size()));
        } catch (const boost::system::system_error& err) {
            socket.release();
            std::rethrow_exception(std::current_exception());
        }
    }

private:
    static inline
    std::unique_ptr<asio::ip::tcp::socket>
    initialize(asio::io_service& io_service, const std::string& host, std::uint16_t port) {
        std::unique_ptr<asio::ip::tcp::socket> socket = std::make_unique<asio::ip::tcp::socket>(io_service);
        connect(io_service, *socket, host, port);
        return socket;
    }

    static inline
    void
    connect(asio::io_service& io_service, asio::ip::tcp::socket& socket, const std::string& host, std::uint16_t port) {
        try {
            asio::ip::tcp::resolver resolver(io_service);
            asio::ip::tcp::resolver::query query(host, boost::lexical_cast<std::string>(port));
            asio::ip::tcp::resolver::iterator it = resolver.resolve(query);

            try {
                asio::connect(socket, it);
            } catch (const boost::system::system_error& err) {
                throw error_t("couldn't connect to the %s:%d - %s", host, port, err.what());
            }
        } catch (const boost::system::system_error& err) {
            throw error_t("couldn't resolve %s:%d - %s", host, port, err.what());
        }
    }
};

} // namespace sink

} // namespace blackhole

TEST(socket_t, Class) {
    sink::socket_t<> sink("localhost", 50030);
    UNUSED(sink);
}

TEST(socket_t, TestCanSendMessages) {
    sink::socket_t<NiceMock<mock::socket::backend_t>> sink("localhost", 50030);
    EXPECT_CALL(sink.backend(), write(std::string("formatted message"))).
            Times(1);
    sink.consume("formatted message");
}

TEST(socket_t, ThrowsExceptionOnAnyWriteErrorOccurred) {
    // This behaviour is normal for blocking udp/tcp socket sink.
    // When some network error occurs, message is on the half way to be dropped.
    // In case of UDP socket, handler will try to reopen socket immediately and rewrite again here
    // and every next message.
    // In case of TCP socket, handler will try to reconnect on every next message before sending.
    sink::socket_t<NiceMock<mock::socket::backend_t>> sink("localhost", 50030);
    EXPECT_CALL(sink.backend(), write(_))
            .Times(1)
            .WillOnce(Throw(std::exception()));
    EXPECT_THROW(sink.consume("message"), std::exception);
}

TEST(socket_t, ThrowsExceptionWhenCannotAcquireResource) {
    // This is initialization behaviour and cannot be caught by any log backend. If handler cannot
    // acquire resource needed, it can't continue its work, so it's neccessary to notify upper level
    // code about it.
    EXPECT_THROW(sink::socket_t<NiceMock<mock::socket::failing_backend_t>>("localhost", 50030), std::exception); //!@todo: Maybe some kind of typecheck here?
}

TEST(socket_t, Manual) {
    sink::tcp_socket_t sink("localhost", 50030);
    int i = 0;
    while (true) {
        try {
            sink.consume(utils::format("{\"@message\": \"value = %d\"}\n", i));
        } catch (std::exception& e) {
            std::cout << utils::format("I've fucked up: %s", e.what()) << std::endl;
        }

        i++;
        usleep(1000000);
    }
}
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s

struct A {
  int x;
  A(int a) { x = a; }
  int getx() const { return x; }
};

void f1() {
  A x(3);
  if (x.getx() == 3) {
    int *p = 0;
    *p = 3;  // expected-warning{{Dereference of null pointer}}
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}

void f2() {
  const A &x = A(3);
  if (x.getx() == 3) {
    int *p = 0;
    *p = 3;  // expected-warning{{Dereference of null pointer}}
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}

<commit_msg>[analyzer] Disable a test until inlining CXXConstructExprs is fully investigated.<commit_after>// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s
// XFAIL: *

struct A {
  int x;
  A(int a) { x = a; }
  int getx() const { return x; }
};

void f1() {
  A x(3);
  if (x.getx() == 3) {
    int *p = 0;
    *p = 3;  // expected-warning{{Dereference of null pointer}}
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}

void f2() {
  const A &x = A(3);
  if (x.getx() == 3) {
    int *p = 0;
    *p = 3;  // expected-warning{{Dereference of null pointer}}
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}

void f3() {
  const A &x = (A)3;
  if (x.getx() == 3) {
    int *p = 0;
    *p = 3;  // expected-warning{{Dereference of null pointer}}
  } else {
    int *p = 0;
    *p = 3;  // no-warning
  }
}
<|endoftext|>


<commit_before>#include "find_hub.hpp"

void GraphProcessor::find_hub()
{
    struct Result res = {};

    complete_graph      g(cities_cnt);
    multi_array<int, 2> weights(extents[cities_cnt][cities_cnt]);
    Vertex              roots[cities_cnt];
    vector<Edge>        branching;

    int n = {0};
    std::generate(roots, roots + cities_cnt, [&n] { return n++; } );

    int *end = weights.origin() + cities_cnt * cities_cnt;
    for (int *it = weights.origin(); it != end; ++it)
        *it = INT_MAX;

    for (auto it = lines.begin(); it != lines.end(); ++it) {
        weights[it->from][it->to] = it->price;
    }

    unsigned long min_cost = ULONG_MAX;
    unsigned int best_depot = INT_MAX;
    vector<Edge> best_branching;

    for (int r = 0; r < cities_cnt; r++) {
        branching.clear();

        edmonds_optimum_branching<false, true, true>
            (g, identity_property_map(), weights.origin(),
             roots + r, roots + r + 1, back_inserter(branching));

        unsigned long total_cost = 0;
        for (auto& e : branching)
             total_cost += weights[source(e, g)][target(e, g)];

        #ifdef DEBUG
            std::cout << "root: " << r << std::endl;
            BOOST_FOREACH (Edge e, branching)
                 std::cout << source(e, g) << " -> " << target(e, g) << " : " << weights[source(e, g)][target(e, g)] << std::endl;
            std::cout << total_cost << std::endl;
        #endif

        if (total_cost < min_cost) {
            min_cost = total_cost;
            best_depot = r;
            best_branching = branching;
        }
    }

    res.feasibility = best_branching.empty() ? false : true;
    res.total_cost = min_cost;
    res.depot_id = best_depot;

    BOOST_FOREACH (Edge e, best_branching)
        res.rec_offers.push_back(Line(source(e, g), target(e, g), weights[source(e, g)][target(e, g)]));

    last_res = res;
}

bool GraphProcessor::load_input()
{
    if (!(std::cin >> cities_cnt))
        return false;

    unsigned int from, to, price;

    while (cin >> from >> to >> price)
        lines.push_back(Line(from, to, price));

    return true;
}

void GraphProcessor::send_result()
{
    std::cout << last_res.feasibility << " " << last_res.total_cost << " " << last_res.depot_id << std::endl;

    for (auto it = last_res.rec_offers.begin(); it != last_res.rec_offers.end(); ++it) {
        std::cout << it->from << " " << it->to << " " << it->price << std::endl;
    }
}

int main(int argc, char *argv[])
{
    GraphProcessor gp;

    if (!gp.load_input())
        return 1;
    gp.find_hub();
    gp.send_result();

    return 0;
}
<commit_msg>find_hub: extend possible weight to ULONG_MAX<commit_after>#include "find_hub.hpp"

void GraphProcessor::find_hub()
{
    struct Result res = {};

    complete_graph      g(cities_cnt);
    multi_array<unsigned long, 2> weights(extents[cities_cnt][cities_cnt]);
    Vertex              roots[cities_cnt];
    vector<Edge>        branching;

    int n = {0};
    std::generate(roots, roots + cities_cnt, [&n] { return n++; } );

    unsigned long *end = weights.origin() + cities_cnt * cities_cnt;
    for (unsigned long *it = weights.origin(); it != end; ++it)
        *it = ULONG_MAX;

    for (auto it = lines.begin(); it != lines.end(); ++it) {
        weights[it->from][it->to] = it->price;
    }

    unsigned long min_cost = ULONG_MAX;
    unsigned int best_depot = INT_MAX;
    vector<Edge> best_branching;

    for (int r = 0; r < cities_cnt; r++) {
        branching.clear();

        edmonds_optimum_branching<false, true, true>
            (g, identity_property_map(), weights.origin(),
             roots + r, roots + r + 1, back_inserter(branching));

        unsigned long total_cost = 0;
        for (auto& e : branching)
             total_cost += weights[source(e, g)][target(e, g)];

        #ifdef DEBUG
            std::cout << "root: " << r << std::endl;
            BOOST_FOREACH (Edge e, branching)
                 std::cout << source(e, g) << " -> " << target(e, g) << " : " << weights[source(e, g)][target(e, g)] << std::endl;
            std::cout << total_cost << std::endl;
        #endif

        if (total_cost < min_cost) {
            min_cost = total_cost;
            best_depot = r;
            best_branching = branching;
        }
    }

    res.feasibility = best_branching.empty() ? false : true;
    res.total_cost = min_cost;
    res.depot_id = best_depot;

    BOOST_FOREACH (Edge e, best_branching)
        res.rec_offers.push_back(Line(source(e, g), target(e, g), weights[source(e, g)][target(e, g)]));

    last_res = res;
}

bool GraphProcessor::load_input()
{
    if (!(std::cin >> cities_cnt))
        return false;

    unsigned int from, to, price;

    while (cin >> from >> to >> price)
        lines.push_back(Line(from, to, price));

    return true;
}

void GraphProcessor::send_result()
{
    std::cout << last_res.feasibility << " " << last_res.total_cost << " " << last_res.depot_id << std::endl;

    for (auto it = last_res.rec_offers.begin(); it != last_res.rec_offers.end(); ++it) {
        std::cout << it->from << " " << it->to << " " << it->price << std::endl;
    }
}

int main(int argc, char *argv[])
{
    GraphProcessor gp;

    if (!gp.load_input())
        return 1;
    gp.find_hub();
    gp.send_result();

    return 0;
}
<|endoftext|>


<commit_before>#include <tightdb/exceptions.hpp>
#include <tightdb/version.hpp>

using namespace tightdb;

const char* ExceptionWithVersionInWhat::message() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    static const char ver[] = TIGHTDB_VER_CHUNK;
    return what() + sizeof(ver);
}

const char* Exception::version() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_STRING;
}

RuntimeError::RuntimeError(const std::string& message):
    std::runtime_error(std::string(TIGHTDB_VER_CHUNK) + " " + message)
{
}

RuntimeError::RuntimeError(const RuntimeError& other):
    std::runtime_error(other)
{
}

const char* RuntimeError::message() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    static const char ver[] = TIGHTDB_VER_CHUNK;
    return what() + sizeof(ver);
}

const char* RuntimeError::version() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_STRING;
}

const char* LogicError::get_message_for_error(LogicError::error_kind kind) TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    switch (kind) {
        case LogicError::string_too_big:
            return TIGHTDB_VER_CHUNK " String too big";
        case LogicError::binary_too_big:
            return TIGHTDB_VER_CHUNK " Binary too big";
        case LogicError::table_name_too_long:
            return TIGHTDB_VER_CHUNK " Table name too long";
        case LogicError::column_name_too_long:
            return TIGHTDB_VER_CHUNK " Column name too long";
        case LogicError::table_index_out_of_range:
            return TIGHTDB_VER_CHUNK " Table index out of range";
        case LogicError::row_index_out_of_range:
            return TIGHTDB_VER_CHUNK " Row index out of range";
        case LogicError::column_index_out_of_range:
            return TIGHTDB_VER_CHUNK " Column index out of range";
        case LogicError::illegal_combination:
            return TIGHTDB_VER_CHUNK " Illegal combination";
        case LogicError::type_mismatch:
            return TIGHTDB_VER_CHUNK " Type mismatch";
        case LogicError::wrong_kind_of_table:
            return TIGHTDB_VER_CHUNK " Wrong kind of table";
        case LogicError::detached_accessor:
            return TIGHTDB_VER_CHUNK " Detached accessor";
        case LogicError::no_search_index:
            return TIGHTDB_VER_CHUNK " Column has no search index";
        case LogicError::no_primary_key:
            return TIGHTDB_VER_CHUNK " Table has no primary key";
        case LogicError::has_primary_key:
            return TIGHTDB_VER_CHUNK " Primary key already added";
        case LogicError::unique_constraint_violation:
            return TIGHTDB_VER_CHUNK " Unique constraint violation";
    }
    return TIGHTDB_VER_CHUNK " Unknown error";
}

const char* NoSuchTable::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " No such table exists";
}

const char* TableNameInUse::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " The specified table name is already in use";
}

const char* CrossTableLinkTarget::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " Table is target of cross-table link columns";
}

const char* DescriptorMismatch::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " Table descriptor mismatch";
}
<commit_msg>Guard against segfaults in RuntimeError::message() and Exception::message().<commit_after>#include <tightdb/exceptions.hpp>
#include <tightdb/version.hpp>

using namespace tightdb;

const char* ExceptionWithVersionInWhat::message() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    const char* msg = what();
    size_t len = strlen(msg);
    static const char ver[] = TIGHTDB_VER_CHUNK;
    if (len > sizeof(ver)) {
        // Assume that what() actually included the version string.
        return msg + sizeof(ver);
    }
    return msg;
}

const char* Exception::version() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_STRING;
}

RuntimeError::RuntimeError(const std::string& message):
    std::runtime_error(std::string(TIGHTDB_VER_CHUNK) + " " + message)
{
}

RuntimeError::RuntimeError(const RuntimeError& other):
    std::runtime_error(other)
{
}

const char* RuntimeError::message() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    const char* msg = what();
    size_t len = strlen(msg);
    static const char ver[] = TIGHTDB_VER_CHUNK;
    if (len > sizeof(ver)) {
        // Assume that what() actually included the version string.
        return msg + sizeof(ver);
    }
    return msg;
}

const char* RuntimeError::version() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_STRING;
}

const char* LogicError::get_message_for_error(LogicError::error_kind kind) TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    switch (kind) {
        case LogicError::string_too_big:
            return TIGHTDB_VER_CHUNK " String too big";
        case LogicError::binary_too_big:
            return TIGHTDB_VER_CHUNK " Binary too big";
        case LogicError::table_name_too_long:
            return TIGHTDB_VER_CHUNK " Table name too long";
        case LogicError::column_name_too_long:
            return TIGHTDB_VER_CHUNK " Column name too long";
        case LogicError::table_index_out_of_range:
            return TIGHTDB_VER_CHUNK " Table index out of range";
        case LogicError::row_index_out_of_range:
            return TIGHTDB_VER_CHUNK " Row index out of range";
        case LogicError::column_index_out_of_range:
            return TIGHTDB_VER_CHUNK " Column index out of range";
        case LogicError::illegal_combination:
            return TIGHTDB_VER_CHUNK " Illegal combination";
        case LogicError::type_mismatch:
            return TIGHTDB_VER_CHUNK " Type mismatch";
        case LogicError::wrong_kind_of_table:
            return TIGHTDB_VER_CHUNK " Wrong kind of table";
        case LogicError::detached_accessor:
            return TIGHTDB_VER_CHUNK " Detached accessor";
        case LogicError::no_search_index:
            return TIGHTDB_VER_CHUNK " Column has no search index";
        case LogicError::no_primary_key:
            return TIGHTDB_VER_CHUNK " Table has no primary key";
        case LogicError::has_primary_key:
            return TIGHTDB_VER_CHUNK " Primary key already added";
        case LogicError::unique_constraint_violation:
            return TIGHTDB_VER_CHUNK " Unique constraint violation";
    }
    return TIGHTDB_VER_CHUNK " Unknown error";
}

const char* NoSuchTable::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " No such table exists";
}

const char* TableNameInUse::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " The specified table name is already in use";
}

const char* CrossTableLinkTarget::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " Table is target of cross-table link columns";
}

const char* DescriptorMismatch::what() const TIGHTDB_NOEXCEPT_OR_NOTHROW
{
    return TIGHTDB_VER_CHUNK " Table descriptor mismatch";
}
<|endoftext|>


<commit_before>#ifndef ALEPH_MATH_STEP_FUNCTION_HH__
#define ALEPH_MATH_STEP_FUNCTION_HH__

#include <algorithm>
#include <iterator>
#include <ostream>
#include <set>

namespace aleph
{

namespace math
{

template <class T> class StepFunction
{
public:

  /**
    Auxiliary class for representing a point 'on' the step function;
    this assumes that the function consists of its non-zero points.
  */

  class Point
  {
  public:
    Point( T x, T y )
      : _x( x )
      , _y( y )
    {
    }

    T x() const noexcept { return _x; }
    T y() const noexcept { return _y; }

    bool operator<( const Point& other ) const
    {
      // Only compare by x coordinate; there must not be two or more
      // points with the same coordinate.
      return this->x() < other.x();
    }

  private:
    T _x = T();
    T _y = T();
  };

  /** Adds a new point to the step function */
  void add( T x, T y ) noexcept
  {
    _points.insert( Point(x,y) );
  }

  /** Returns the domain of the function */
  template <class OutputIterator> void domain( OutputIterator result )
  {
    for( auto&& p : _points )
      *result++ = p.x();
  }

  /** Returns the image of the function */
  template <class OutputIterator> void image( OutputIterator result )
  {
    for( auto&& p : _points )
      *result++ = p.y();
  }

  /** Returns the function value at a certain position */
  T operator()( T x ) const noexcept
  {
    // Find the point that is nearest to the query point and use its value as
    // the result. I don't want to do any interpolation here.
    auto it = std::lower_bound( _points.begin(), _points.end(),
                                Point( x, T() ) );

    if( it != _points.end() )
      return it->y();
    else
      return T();
  }

  /** Calculates the sum of this step function with another step function */
  StepFunction operator+( const StepFunction& other ) const noexcept
  {
    auto&& f = *this;
    auto&& g = other;

    std::set<T> domain;

    f.domain( std::inserter( domain, domain.begin() ) );
    g.domain( std::inserter( domain, domain.begin() ) );

    StepFunction<T> h;

    for( auto&& x : domain )
    {
      auto y1 = f(x);
      auto y2 = g(x);

      h.add( x, y1+y2 );
    }

    return h;
  }

  /** Calculates the integral over the domain of the step function */
  T integral() const noexcept
  {
    if( _points.empty() )
      return T();

    auto cur = _points.begin();
    auto pre = _points.begin();

    std::advance( cur, 1 );

    T value = T();

    for( ; cur != _points.end(); )
    {
      auto c  = this->operator()( pre->x() );
      auto t  = cur->x() - pre->x();
      value  += c*t;

      pre = cur++;
    }

    return value;
  }

  template <class U> friend std::ostream& operator<<( std::ostream&, const StepFunction<U>& f );

private:

  /** All non-zero points of the step function */
  std::set<Point> _points;
};

// TODO: This does not need to be a friend function; it suffices to be
// implemented using the public interface of the class.
template <class T> std::ostream& operator<<( std::ostream& o, const StepFunction<T>& f )
{
  for( auto&& p : f._points )
    o << p.x() << "\t" << p.y() << "\n";

  return o;
}

} // namespace math

} // namespace aleph

#endif
<commit_msg>Scalar multiplication and division for step functions<commit_after>#ifndef ALEPH_MATH_STEP_FUNCTION_HH__
#define ALEPH_MATH_STEP_FUNCTION_HH__

#include <algorithm>
#include <iterator>
#include <ostream>
#include <set>

namespace aleph
{

namespace math
{

template <class T> class StepFunction
{
public:

  /**
    Auxiliary class for representing a point 'on' the step function;
    this assumes that the function consists of its non-zero points.
  */

  class Point
  {
  public:
    Point( T x, T y )
      : _x( x )
      , _y( y )
    {
    }

          T& x()       noexcept { return _x; }
    const T& x() const noexcept { return _x; }

          T& y()       noexcept { return _y; }
    const T& y() const noexcept { return _y; }

    bool operator<( const Point& other ) const
    {
      // Only compare by x coordinate; there must not be two or more
      // points with the same coordinate.
      return this->x() < other.x();
    }

  private:
    T _x = T();
    T _y = T();
  };

  /** Adds a new point to the step function */
  void add( T x, T y ) noexcept
  {
    _points.insert( Point(x,y) );
  }

  /** Returns the domain of the function */
  template <class OutputIterator> void domain( OutputIterator result )
  {
    for( auto&& p : _points )
      *result++ = p.x();
  }

  /** Returns the image of the function */
  template <class OutputIterator> void image( OutputIterator result )
  {
    for( auto&& p : _points )
      *result++ = p.y();
  }

  /** Returns the function value at a certain position */
  T operator()( T x ) const noexcept
  {
    // Find the point that is nearest to the query point and use its value as
    // the result. I don't want to do any interpolation here.
    auto it = std::lower_bound( _points.begin(), _points.end(),
                                Point( x, T() ) );

    if( it != _points.end() )
      return it->y();
    else
      return T();
  }

  /** Calculates the sum of this step function with another step function */
  StepFunction operator+( const StepFunction& other ) const noexcept
  {
    auto&& f = *this;
    auto&& g = other;

    std::set<T> domain;

    f.domain( std::inserter( domain, domain.begin() ) );
    g.domain( std::inserter( domain, domain.begin() ) );

    StepFunction<T> h;

    for( auto&& x : domain )
    {
      auto y1 = f(x);
      auto y2 = g(x);

      h.add( x, y1+y2 );
    }

    return h;
  }

  /** Multiplies the given step function with a scalar value */
  StepFunction operator*( T lambda ) const noexcept
  {
    StepFunction<T> f = *this;

    for( auto&& p : f._points )
      p.y() = p.y() * lambda;
  }

  /** Divides the given step function by a scalar value */
  StepFunction operator/( T lambda ) const
  {
    // TODO: What about division by zero?
    return this->operator*( 1/lambda );
  }

  /** Calculates the integral over the domain of the step function */
  T integral() const noexcept
  {
    if( _points.empty() )
      return T();

    auto cur = _points.begin();
    auto pre = _points.begin();

    std::advance( cur, 1 );

    T value = T();

    for( ; cur != _points.end(); )
    {
      auto c  = this->operator()( pre->x() );
      auto t  = cur->x() - pre->x();
      value  += c*t;

      pre = cur++;
    }

    return value;
  }

  template <class U> friend std::ostream& operator<<( std::ostream&, const StepFunction<U>& f );

private:

  /** All non-zero points of the step function */
  std::set<Point> _points;
};

// TODO: This does not need to be a friend function; it suffices to be
// implemented using the public interface of the class.
template <class T> std::ostream& operator<<( std::ostream& o, const StepFunction<T>& f )
{
  for( auto&& p : f._points )
    o << p.x() << "\t" << p.y() << "\n";

  return o;
}

} // namespace math

} // namespace aleph

#endif
<|endoftext|>


<commit_before>/*
 * redsea - RDS decoder
 * Copyright (c) Oona Räisänen OH2EIQ (windyoona@gmail.com)
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */
#include <getopt.h>
#include <iostream>

#include "config.h"
#include "src/channel.h"
#include "src/common.h"
#include "src/block_sync.h"
#include "src/groups.h"
#include "src/options.h"
#include "src/subcarrier.h"

namespace redsea {

void PrintUsage() {
  std::cout <<
    "radio_command | redsea [OPTIONS]\n"
    "\n"
    "By default, a 171 kHz single-channel 16-bit MPX signal is expected via\n"
    "stdin.\n"
    "\n"
    "-b, --input-bits       Input is an unsynchronized ASCII bit stream\n"
    "                       (011010110...). All characters but '0' and '1'\n"
    "                       are ignored.\n"
    "\n"
    "-c, --channels CHANS   Number of channels in the raw input signal. Each\n"
    "                       channel is demodulated independently.\n"
    "\n"
    "-e, --feed-through     Echo the input signal to stdout and print\n"
    "                       decoded groups to stderr.\n"
    "\n"
    "-E, --bler             Display the average block error rate, or the\n"
    "                       percentage of blocks that had errors before\n"
    "                       error correction. Averaged over the last 12\n"
    "                       groups. For hex input, this is the percentage\n"
    "                       of missing blocks.\n"
    "\n"
    "-f, --file FILENAME    Use an audio file as MPX input. All formats\n"
    "                       readable by libsndfile should work.\n"
    "\n"
    "-h, --input-hex        The input is in the RDS Spy hex format.\n"
    "\n"
    "-l, --loctable DIR     Load TMC location table from a directory in TMC\n"
    "                       Exchange format.\n"
    "\n"
    "-p, --show-partial     Under noisy conditions, redsea may not be able to\n"
    "                       fully receive all information. Multi-group data\n"
    "                       such as PS names, RadioText, and alternative\n"
    "                       frequencies are especially vulnerable. This option\n"
    "                       makes it display them even if not fully received,\n"
    "                       as partial_{ps,radiotext,alt_kilohertz}.\n"
    "\n"
    "-r, --samplerate RATE  Set stdin sample frequency in Hz. Will resample\n"
    "                       (slow) if this differs from 171000 Hz.\n"
    "\n"
    "-t, --timestamp FORMAT Add time of decoding to JSON groups; see\n"
    "                       man strftime for formatting options (or\n"
    "                       try \"%c\").\n"
    "\n"
    "-u, --rbds             RBDS mode; use North American program type names\n"
    "                       and \"back-calculate\" the station's call sign from\n"
    "                       its PI code. Note that this calculation gives an\n"
    "                       incorrect call sign for most stations that transmit\n"
    "                       TMC.\n"
    "\n"
    "-v, --version          Print version string and exit.\n"
    "\n"
    "-x, --output-hex       Output hex groups in the RDS Spy format,\n"
    "                       suppressing JSON output.\n";
}

void PrintVersion() {
#ifdef DEBUG
  std::cout << PACKAGE_STRING << "-debug by OH2EIQ" << '\n';
#else
  std::cout << PACKAGE_STRING << " by OH2EIQ" << '\n';
#endif
}

}  // namespace redsea

int main(int argc, char** argv) {
  redsea::Options options = redsea::GetOptions(argc, argv);

  if (options.print_usage)
    redsea::PrintUsage();

  if (options.print_version)
    redsea::PrintVersion();

  if (options.exit_failure)
    return EXIT_FAILURE;

  if (options.exit_success)
    return EXIT_SUCCESS;

#ifndef HAVE_LIQUID
  if (options.input_type == redsea::InputType::MPX_stdin ||
      options.input_type == redsea::InputType::MPX_sndfile) {
    std::cerr << "error: redsea was compiled without liquid-dsp"
              << '\n';
    return EXIT_FAILURE;
  }
#endif

  redsea::MPXReader mpx(options);
  options.samplerate = mpx.samplerate();
  options.num_channels = mpx.num_channels();

  if (mpx.error())
    return EXIT_FAILURE;

  /* When we don't have MPX input, there are no channels. But we want at least
   * 1 Channel anyway. Also, we need a sample rate for the Subcarrier
   * constructor.
   */
  if (options.input_type != redsea::InputType::MPX_sndfile &&
      options.input_type != redsea::InputType::MPX_stdin) {
    options.num_channels = 1;
    options.samplerate = redsea::kTargetSampleRate_Hz;
  }

  std::vector<redsea::Channel> channels;
  for (int n_channel = 0; n_channel < options.num_channels; n_channel++)
    channels.emplace_back(redsea::Channel(options, n_channel));

  redsea::AsciiBitReader ascii_reader(options);

  while (true) {
    bool eof = false;
    if (options.input_type == redsea::InputType::MPX_stdin ||
        options.input_type == redsea::InputType::MPX_sndfile) {
      eof = mpx.eof();
    } else if (options.input_type == redsea::InputType::ASCIIbits) {
      eof = ascii_reader.eof();
    } else if (options.input_type == redsea::InputType::Hex) {
      eof = std::cin.eof();
    }

    if (eof)
      break;

    if (options.input_type == redsea::InputType::MPX_stdin ||
        options.input_type == redsea::InputType::MPX_sndfile)
      mpx.FillBuffer();

    for (int n_channel = 0; n_channel < options.num_channels; n_channel++) {
      switch (options.input_type) {
        case redsea::InputType::MPX_stdin:
        case redsea::InputType::MPX_sndfile:
          channels[n_channel].ProcessChunk(mpx.ReadChunk(n_channel));
          break;

        case redsea::InputType::ASCIIbits:
          channels[n_channel].ProcessBit(ascii_reader.ReadNextBit());
          break;

        case redsea::InputType::Hex:
          channels[n_channel].ProcessGroup(redsea::ReadNextHexGroup(options));
          break;
      }
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>tidier flow in main()<commit_after>/*
 * redsea - RDS decoder
 * Copyright (c) Oona Räisänen OH2EIQ (windyoona@gmail.com)
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */
#include <iostream>

#include "config.h"
#include "src/channel.h"
#include "src/common.h"
#include "src/groups.h"
#include "src/options.h"
#include "src/subcarrier.h"

namespace redsea {

void PrintUsage() {
  std::cout <<
    "radio_command | redsea [OPTIONS]\n"
    "\n"
    "By default, a 171 kHz single-channel 16-bit MPX signal is expected via\n"
    "stdin.\n"
    "\n"
    "-b, --input-bits       Input is an unsynchronized ASCII bit stream\n"
    "                       (011010110...). All characters but '0' and '1'\n"
    "                       are ignored.\n"
    "\n"
    "-c, --channels CHANS   Number of channels in the raw input signal. Each\n"
    "                       channel is demodulated independently.\n"
    "\n"
    "-e, --feed-through     Echo the input signal to stdout and print\n"
    "                       decoded groups to stderr.\n"
    "\n"
    "-E, --bler             Display the average block error rate, or the\n"
    "                       percentage of blocks that had errors before\n"
    "                       error correction. Averaged over the last 12\n"
    "                       groups. For hex input, this is the percentage\n"
    "                       of missing blocks.\n"
    "\n"
    "-f, --file FILENAME    Use an audio file as MPX input. All formats\n"
    "                       readable by libsndfile should work.\n"
    "\n"
    "-h, --input-hex        The input is in the RDS Spy hex format.\n"
    "\n"
    "-l, --loctable DIR     Load TMC location table from a directory in TMC\n"
    "                       Exchange format.\n"
    "\n"
    "-p, --show-partial     Under noisy conditions, redsea may not be able to\n"
    "                       fully receive all information. Multi-group data\n"
    "                       such as PS names, RadioText, and alternative\n"
    "                       frequencies are especially vulnerable. This option\n"
    "                       makes it display them even if not fully received,\n"
    "                       as partial_{ps,radiotext,alt_kilohertz}.\n"
    "\n"
    "-r, --samplerate RATE  Set stdin sample frequency in Hz. Will resample\n"
    "                       (slow) if this differs from 171000 Hz.\n"
    "\n"
    "-t, --timestamp FORMAT Add time of decoding to JSON groups; see\n"
    "                       man strftime for formatting options (or\n"
    "                       try \"%c\").\n"
    "\n"
    "-u, --rbds             RBDS mode; use North American program type names\n"
    "                       and \"back-calculate\" the station's call sign from\n"
    "                       its PI code. Note that this calculation gives an\n"
    "                       incorrect call sign for most stations that transmit\n"
    "                       TMC.\n"
    "\n"
    "-v, --version          Print version string and exit.\n"
    "\n"
    "-x, --output-hex       Output hex groups in the RDS Spy format,\n"
    "                       suppressing JSON output.\n";
}

void PrintVersion() {
#ifdef DEBUG
  std::cout << PACKAGE_STRING << "-debug by OH2EIQ" << '\n';
#else
  std::cout << PACKAGE_STRING << " by OH2EIQ" << '\n';
#endif
}

int ProcessMPXInput(Options options) {

#ifndef HAVE_LIQUID
  std::cerr << "error: redsea was compiled without liquid-dsp"
            << '\n';
  return EXIT_FAILURE;
#endif

  MPXReader mpx(options);
  options.samplerate = mpx.samplerate();
  options.num_channels = mpx.num_channels();

  if (mpx.error())
    return EXIT_FAILURE;

  std::vector<Channel> channels;
  for (int i = 0; i < options.num_channels; i++) {
    channels.emplace_back(options, i);
  }

  while (!mpx.eof()) {
    mpx.FillBuffer();
    for (int i = 0; i < options.num_channels; i++) {
      channels[i].ProcessChunk(mpx.ReadChunk(i));
    }
  }

  return EXIT_SUCCESS;
}

int ProcessASCIIBitsInput(Options options) {
  Channel channel(options, 0);
  AsciiBitReader ascii_reader(options);

  while (!ascii_reader.eof()) {
    channel.ProcessBit(ascii_reader.ReadBit());
  }

  return EXIT_SUCCESS;
}

int ProcessHexInput(Options options) {
  Channel channel(options, 0);

  while (!std::cin.eof()) {
    channel.ProcessGroup(ReadHexGroup(options));
  }

  return EXIT_SUCCESS;
}

}  // namespace redsea

int main(int argc, char** argv) {
  redsea::Options options = redsea::GetOptions(argc, argv);

  if (options.print_usage)
    redsea::PrintUsage();

  if (options.print_version)
    redsea::PrintVersion();

  if (options.exit_failure)
    return EXIT_FAILURE;

  if (options.exit_success)
    return EXIT_SUCCESS;

  switch (options.input_type) {
    case redsea::InputType::MPX_stdin:
    case redsea::InputType::MPX_sndfile:
      return ProcessMPXInput(options);
      break;

    case redsea::InputType::ASCIIbits:
      return ProcessASCIIBitsInput(options);
      break;

    case redsea::InputType::Hex:
      return ProcessHexInput(options);
      break;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkNullCanvas.h"

#include "SkCanvas.h"
#include "SKNWayCanvas.h"

SkCanvas* SkCreateNullCanvas() {
    // An N-Way canvas forwards calls to N canvas's. When N == 0 it's
    // effectively a null canvas.
    return SkNEW(SkNWayCanvas);
}
<commit_msg>Fix SkNWayCanvas cons call when creating null canvas.<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkNullCanvas.h"

#include "SkCanvas.h"
#include "SKNWayCanvas.h"

SkCanvas* SkCreateNullCanvas() {
    // An N-Way canvas forwards calls to N canvas's. When N == 0 it's
    // effectively a null canvas.
    return SkNEW(SkNWayCanvas(0,0));
}
<|endoftext|>


<commit_before>#pragma once
#ifndef DELEGATE_HPP
# define DELEGATE_HPP

#include <cassert>

#include <bitset>

#include <memory>

#include <new>

#include <type_traits>

#include <utility>

#include "lightptr.hpp"

namespace
{
  template <typename T>
  struct static_store
  {
    static constexpr ::std::size_t const max_instances = 64;

    static ::std::bitset<max_instances> memory_map_;
    static typename ::std::aligned_storage<sizeof(T), alignof(T)>::type
      store_[max_instances];
  };

  template <typename T>
  ::std::bitset<static_store<T>::max_instances>
    static_store<T>::memory_map_{(unsigned long long)(-1)};

  template <typename T>
  typename ::std::aligned_storage<sizeof(T), alignof(T)>::type
    static_store<T>::store_[static_store<T>::max_instances];

  template <typename T, typename ...A>
  inline T* static_new(A&& ...args)
  {
    using static_store = static_store<T>;

    auto const i(__builtin_ffsll(static_store::memory_map_.to_ullong()));
    //assert(static_store::max_instances != i);

    auto p(new (&static_store::store_[i]) T(::std::forward<A>(args)...));

    static_store::memory_map_[i] = false;

    return p;
  }

  template <typename T>
  inline void static_delete(T const* const p)
  {
    using static_store = static_store<T>;

    auto const i(p - static_cast<T const*>(static_cast<void const*>(
      static_store::store_)));
    //assert(!as_const(static_store::memory_map_)[i]);

    static_store::memory_map_[i] = true;

    static_cast<T const*>(static_cast<void const*>(
      &static_store::store_[i]))->~T();
  }
}

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  using stub_ptr_type = R (*)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  delegate(::std::nullptr_t const) noexcept : delegate() { }

  template <class C>
  explicit delegate(C const* const o) noexcept
    : object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C>
  explicit delegate(C const& o) noexcept
    : object_ptr_(const_cast<C*>(&o))
  {
  }

  delegate(R (* const function_ptr)(A...))
  {
    *this = from(function_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate(T&& f)
  {
    *this = ::std::forward<T>(f);
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  delegate& operator=(R (* const rhs)(A...))
  {
    return *this = from(rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate& operator=(T&& f)
  {
    using functor_type = typename ::std::decay<T>::type;

    store_.reset(static_new<functor_type>(::std::forward<T>(f)),
      functor_deleter<functor_type>);

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* const object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* const object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return ::std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return [function_ptr](A&&... args) {
      return (*function_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(::std::forward<A>(args)...); };
  }

  void reset() { stub_ptr_ = nullptr; store_.reset(); }

  void reset_stub() noexcept { stub_ptr_ = nullptr; }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) ||
      ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !stub_ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return stub_ptr_;
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  light_ptr<void> store_;

  template <class T>
  static void functor_deleter(void* const p)
  {
    static_cast<T const*>(p)->~T();

    static_delete(static_cast<T const*>(p));
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <typename T>
  static R functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_));

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_) +
        0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // DELEGATE_HPP
<commit_msg>some fixes<commit_after>#pragma once
#ifndef DELEGATE_HPP
# define DELEGATE_HPP

#include <cassert>

#include <bitset>

#include <memory>

#include <new>

#include <type_traits>

#include <utility>

#include "lightptr.hpp"

namespace
{
  template <typename T>
  struct static_store
  {
    static constexpr ::std::size_t const max_instances = 64;

    static ::std::bitset<max_instances> memory_map_;
    static typename ::std::aligned_storage<sizeof(T),
      alignof(T)>::type* store_;
  };

  template <typename T>
  ::std::bitset<static_store<T>::max_instances>
    static_store<T>::memory_map_{(unsigned long long)(-1)};

  template <typename T>
  typename ::std::aligned_storage<sizeof(T), alignof(T)>::type*
    static_store<T>::store_{new typename
      ::std::aligned_storage<sizeof(T), alignof(T)>::type[
        static_store<T>::max_instances]};

  template <typename T, typename ...A>
  inline T* static_new(A&& ...args)
  {
    using static_store = static_store<T>;

    auto const i(__builtin_ffsll(static_store::memory_map_.to_ullong()));
    //assert(static_store::max_instances != i);

    auto p(new (&static_store::store_[i]) T(::std::forward<A>(args)...));

    static_store::memory_map_[i] = false;

    return p;
  }

  template <typename T>
  inline void static_delete(T const* const p)
  {
    using static_store = static_store<T>;

    auto const i(p - static_cast<T const*>(static_cast<void const*>(
      static_store::store_)));
    //assert(!as_const(static_store::memory_map_)[i]);

    static_store::memory_map_[i] = true;

    static_cast<T const*>(static_cast<void const*>(
      &static_store::store_[i]))->~T();
  }
}

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  using stub_ptr_type = R (*)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  delegate(::std::nullptr_t const) noexcept : delegate() { }

  template <class C>
  explicit delegate(C const* const o) noexcept
    : object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C>
  explicit delegate(C const& o) noexcept
    : object_ptr_(const_cast<C*>(&o))
  {
  }

  delegate(R (* const function_ptr)(A...))
  {
    *this = from(function_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate(T&& f)
  {
    *this = ::std::forward<T>(f);
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  delegate& operator=(R (* const rhs)(A...))
  {
    return *this = from(rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate& operator=(T&& f)
  {
    using functor_type = typename ::std::decay<T>::type;

    store_.reset(static_new<functor_type>(::std::forward<T>(f)),
      functor_deleter<functor_type>);

    object_ptr_ = store_.get();

    stub_ptr_ = functor_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* const object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* const object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return ::std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return [function_ptr](A&&... args) {
      return (*function_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(::std::forward<A>(args)...); };
  }

  void reset() { stub_ptr_ = nullptr; store_.reset(); }

  void reset_stub() noexcept { stub_ptr_ = nullptr; }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) ||
      ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !stub_ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return stub_ptr_;
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  light_ptr<void> store_;

  template <class T>
  static void functor_deleter(void* const p)
  {
    static_cast<T const*>(p)->~T();

    static_delete(static_cast<T const*>(p));
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <typename T>
  static R functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_));

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_) +
        0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // DELEGATE_HPP
<|endoftext|>


<commit_before>#pragma once
#ifndef DELEGATE_HPP
# define DELEGATE_HPP

#include <cassert>

#include <memory>

#include <new>

#include <type_traits>

#include <utility>

template <typename T> class delegate;

template<class R, class ...A>
class delegate<R (A...)>
{
  using stub_ptr_type = R (*)(void*, A&&...);

  delegate(void* const o, stub_ptr_type const m) noexcept
    : object_ptr_(o),
      stub_ptr_(m)
  {
  }

public:
  static constexpr auto const max_stores = 200;

  delegate() = default;

  delegate(delegate const&) = default;

  delegate(delegate&&) = default;

  delegate(::std::nullptr_t const) noexcept : delegate() { }

  template <class C>
  explicit delegate(C const* const o) noexcept
    : object_ptr_(const_cast<C*>(o))
  {
  }

  template <class C>
  explicit delegate(C const& o) noexcept
    : object_ptr_(const_cast<C*>(&o))
  {
  }

  delegate(R (* const function_ptr)(A...))
  {
    *this = from(function_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object_ptr, method_ptr);
  }

  template <class C>
  delegate(C& object, R (C::* const method_ptr)(A...))
  {
    *this = from(object, method_ptr);
  }

  template <class C>
  delegate(C const& object, R (C::* const method_ptr)(A...) const)
  {
    *this = from(object, method_ptr);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate(T&& f)
  {
    using functor_type = typename ::std::decay<T>::type;

    alignas(functor_type) static char store_[max_stores][sizeof(T)];
    static ::std::size_t store_index;

    assert(store_index != max_stores);
    new (store_[store_index++]) functor_type(::std::forward<T>(f));

    object_ptr_ = store_;

    stub_ptr_ = functor_stub<functor_type>;

    deleter_ = deleter_stub<functor_type>;
  }

  delegate& operator=(delegate const&) = default;

  delegate& operator=(delegate&& rhs) = default;

  delegate& operator=(R (* const rhs)(A...))
  {
    return *this = from(rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...))
  {
    return *this = from(static_cast<C*>(object_ptr_), rhs);
  }

  template <class C>
  delegate& operator=(R (C::* const rhs)(A...) const)
  {
    return *this = from(static_cast<C const*>(object_ptr_), rhs);
  }

  template <
    typename T,
    typename = typename ::std::enable_if<
      !::std::is_same<delegate, typename ::std::decay<T>::type>{}
    >::type
  >
  delegate& operator=(T&& f)
  {
    using functor_type = typename ::std::decay<T>::type;

    alignas(functor_type) static char store_[max_stores][sizeof(T)];
    static ::std::size_t store_index;

    deleter_(store_);

    assert(store_index != max_stores);
    new (store_[store_index++]) functor_type(::std::forward<T>(f));

    object_ptr_ = store_;

    stub_ptr_ = functor_stub<functor_type>;

    deleter_ = deleter_stub<functor_type>;

    return *this;
  }

  template <R (* const function_ptr)(A...)>
  static delegate from() noexcept
  {
    return { nullptr, function_stub<function_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C* const object_ptr) noexcept
  {
    return { object_ptr, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const* const object_ptr) noexcept
  {
    return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...)>
  static delegate from(C& object) noexcept
  {
    return { &object, method_stub<C, method_ptr> };
  }

  template <class C, R (C::* const method_ptr)(A...) const>
  static delegate from(C const& object) noexcept
  {
    return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
  }

  template <typename T>
  static delegate from(T&& f)
  {
    return ::std::forward<T>(f);
  }

  static delegate from(R (* const function_ptr)(A...))
  {
    return [function_ptr](A&&... args) {
      return (*function_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C* const object_ptr,
    R (C::* const method_ptr)(A...))
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const* const object_ptr,
    R (C::* const method_ptr)(A...) const)
  {
    return [object_ptr, method_ptr](A&&... args) {
      return (object_ptr->*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C& object, R (C::* const method_ptr)(A...))
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(::std::forward<A>(args)...); };
  }

  template <class C>
  static delegate from(C const& object,
    R (C::* const method_ptr)(A...) const)
  {
    return [&object, method_ptr](A&&... args) {
      return (object.*method_ptr)(::std::forward<A>(args)...); };
  }

  void reset() { stub_ptr_ = nullptr; }

  void reset_stub() noexcept { stub_ptr_ = nullptr; }

  void swap(delegate& other) noexcept { ::std::swap(*this, other); }

  bool operator==(delegate const& rhs) const noexcept
  {
    return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
  }

  bool operator!=(delegate const& rhs) const noexcept
  {
    return !operator==(rhs);
  }

  bool operator<(delegate const& rhs) const noexcept
  {
    return (object_ptr_ < rhs.object_ptr_) ||
      ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
  }

  bool operator==(::std::nullptr_t const) const noexcept
  {
    return !stub_ptr_;
  }

  bool operator!=(::std::nullptr_t const) const noexcept
  {
    return stub_ptr_;
  }

  explicit operator bool() const noexcept { return stub_ptr_; }

  R operator()(A... args) const
  {
//  assert(stub_ptr);
    return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
  }

private:
  friend class ::std::hash<delegate>;

  using deleter_type = void (*)(void const*);

  void* object_ptr_;
  stub_ptr_type stub_ptr_{};

  deleter_type deleter_{default_deleter_stub};

  static void default_deleter_stub(void const* const) { }

  template <class T>
  static void deleter_stub(void const* const p)
  {
    static_cast<T const*>(p)->~T();
  }

  template <R (*function_ptr)(A...)>
  static R function_stub(void* const, A&&... args)
  {
    return function_ptr(::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...)>
  static R method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <class C, R (C::*method_ptr)(A...) const>
  static R const_method_stub(void* const object_ptr, A&&... args)
  {
    return (static_cast<C const*>(object_ptr)->*method_ptr)(
      ::std::forward<A>(args)...);
  }

  template <typename T>
  static R functor_stub(void* const object_ptr, A&&... args)
  {
    return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
  }
};

namespace std
{
  template <typename R, typename ...A>
  struct hash<delegate<R (A...)> >
  {
    size_t operator()(delegate<R (A...)> const& d) const noexcept
    {
      auto const seed(hash<void*>()(d.object_ptr_));

      return hash<typename delegate<R (A...)>::stub_ptr_type>()(d.stub_ptr_) +
        0x9e3779b9 + (seed << 6) + (seed >> 2);
    }
  };
}

#endif // DELEGATE_HPP
<commit_msg>strips2<commit_after><|endoftext|>