text:
// Copyright (C) 2008-2018 Lorenzo Caminiti
// Distributed under the Boost Software License, Version 1.0 (see accompanying
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html

// Test overrides with mixed access level from (single) base.

#include "../detail/oteststream.hpp"
#include <boost/contract/public_function.hpp>
#include <boost/contract/function.hpp>
#include <boost/contract/base_types.hpp>
#include <boost/contract/override.hpp>
#include <boost/contract/check.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <sstream>

boost::contract::test::detail::oteststream out;

struct b { // Test all access levels (public, protected, and private).
    friend void call(b& me) { // Test polymorphic calls (object by &).
        me.f();
        me.g();
        me.h();
    }

    static void statci_inv() { out << "b::static_inv" << std::endl; }
    void invariant() const { out << "b::inv" << std::endl; }

    virtual void f(boost::contract::virtual_* v = 0) {
        boost::contract::check c = boost::contract::public_function(v, this)
            .precondition([] { out << "b::f::pre" << std::endl; })
            .old([] { out << "b::f::old" << std::endl; })
            .postcondition([] { out << "b::f::post" << std::endl; })
        ;
        out << "b::f::body" << std::endl;
    }

    // NOTE: Both protected and private virtual members must declare
    // extra `virtual_* = 0` parameter (otherwise they cannot be overridden in
    // derived classes with contracts because C++ uses also default parameters
    // to match signature of overriding functions).

protected:
    virtual void g(boost::contract::virtual_* /* v */= 0) {
        boost::contract::check c = boost::contract::function()
            .precondition([] { out << "b::g::pre" << std::endl; })
            .old([] { out << "b::g::old" << std::endl; })
            .postcondition([] { out << "b::g::post" << std::endl; })
        ;
        out << "b::g::body" << std::endl;
    }

private:
    virtual void h(boost::contract::virtual_* /* v */ = 0) {
        boost::contract::check c = boost::contract::function()
            .precondition([] { out << "b::h::pre" << std::endl; })
            .old([] { out << "b::h::old" << std::endl; })
            .postcondition([] { out << "b::h::post" << std::endl; })
        ;
        out << "b::h::body" << std::endl;
    }
};

struct a // Test overrides with mixed access levels from base.
    #define BASES public b
    : BASES
{
    typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
    #undef BASES

    static void statci_inv() { out << "a::static_inv" << std::endl; }
    void invariant() const { out << "a::inv" << std::endl; }

    virtual void f(boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::check c = boost::contract::public_function<override_f>(
                v, &a::f, this)
            .precondition([] { out << "a::f::pre" << std::endl; })
            .old([] { out << "a::f::old" << std::endl; })
            .postcondition([] { out << "a::f::post" << std::endl; })
        ;
        out << "a::f::body" << std::endl;
    }
    BOOST_CONTRACT_OVERRIDES(f)

    // Following do not override public members so no `override_...` param and
    // they do not actually subcontract.

    virtual void g(boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::check c = boost::contract::public_function(v, this)
            .precondition([] { out << "a::g::pre" << std::endl; })
            .old([] { out << "a::g::old" << std::endl; })
            .postcondition([] { out << "a::g::post" << std::endl; })
        ;
        out << "a::g::body" << std::endl;
    }

    virtual void h(boost::contract::virtual_* v = 0) /* override */ {
        boost::contract::check c = boost::contract::public_function(v, this)
            .precondition([] { out << "a::h::pre" << std::endl; })
            .old([] { out << "a::h::old" << std::endl; })
            .postcondition([] { out << "a::h::post" << std::endl; })
        ;
        out << "a::h::body" << std::endl;
    }
};

int main() {
    std::ostringstream ok;

    b bb;
    out.str("");
    call(bb);
    ok.str(""); ok
        #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
            << "b::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
            << "b::f::pre" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_OLDS
            << "b::f::old" << std::endl
        #endif
        << "b::f::body" << std::endl
        #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
            << "b::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
            << "b::f::post" << std::endl
        #endif

        #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
            << "b::g::pre" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_OLDS
            << "b::g::old" << std::endl
        #endif
        << "b::g::body" << std::endl
        #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
            << "b::g::post" << std::endl
        #endif

        #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
            << "b::h::pre" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_OLDS
            << "b::h::old" << std::endl
        #endif
        << "b::h::body" << std::endl
        #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
            << "b::h::post" << std::endl
        #endif
    ;
    BOOST_TEST(out.eq(ok.str()));

    a aa;
    out.str("");
    call(aa);
    ok.str(""); ok
        #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
            << "b::inv" << std::endl
            << "a::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
            << "b::f::pre" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_OLDS
            << "b::f::old" << std::endl
            << "a::f::old" << std::endl
        #endif
        << "a::f::body" << std::endl
        #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
            << "b::inv" << std::endl
            << "a::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
            << "b::f::old" << std::endl
            << "b::f::post" << std::endl
            << "a::f::post" << std::endl
        #endif

        #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
            << "a::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
            << "a::g::pre" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_OLDS
            << "a::g::old" << std::endl
        #endif
        << "a::g::body" << std::endl
        #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
            << "a::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
            << "a::g::post" << std::endl
        #endif

        #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
            << "a::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
            << "a::h::pre" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_OLDS
            << "a::h::old" << std::endl
        #endif
        << "a::h::body" << std::endl
        #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
            << "a::inv" << std::endl
        #endif
        #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
            << "a::h::post" << std::endl
        #endif
    ;
    BOOST_TEST(out.eq(ok.str()));

    return boost::report_errors();
}

max_issues_repo_name: qingkouwei/mediaones


text:
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2021 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Heiko Kernbach
/// @author Lars Maier
/// @author Markus Pfeiffer
////////////////////////////////////////////////////////////////////////////////

#include <boost/range/adaptor/transformed.hpp>

#include <Basics/VelocyPackHelper.h>
#include <velocypack/Collection.h>
#include <velocypack/Iterator.h>
#include <velocypack/Parser.h>
#include <velocypack/velocypack-aliases.h>

#include <iostream>
#include <list>

#include "Extractor.h"
#include "Interpreter.h"
#include "Primitives.h"

namespace arangodb::greenspun {

EvalResult Prim_Min(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  bool set = false;
  auto tmp = double{0};
  for (auto p : VPackArrayIterator(params)) {
    if (p.isNumber<double>()) {
      if (!set) {
        tmp = p.getNumericValue<double>();
        set = true;
      } else {
        tmp = std::min(tmp, p.getNumericValue<double>());
      }
    } else {
      return EvalError("expected double, found: " + p.toJson());
    }
  }
  if (set) {
    result.add(VPackValue(tmp));
  } else {
    result.add(VPackSlice::nullSlice());
  }
  return {};
}

EvalResult Prim_Max(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  bool set = false;
  auto tmp = double{0};
  for (auto p : VPackArrayIterator(params)) {
    if (p.isNumber<double>()) {
      if (!set) {
        tmp = p.getNumericValue<double>();
        set = true;
      } else {
        tmp = std::max(tmp, p.getNumericValue<double>());
      }
    } else {
      return EvalError("expected double, found: " + p.toJson());
    }
  }
  if (set) {
    result.add(VPackValue(tmp));
  } else {
    result.add(VPackSlice::nullSlice());
  }
  return {};
}

EvalResult Prim_Avg(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  auto tmp = double{0};
  for (auto p : VPackArrayIterator(params)) {
    if (p.isNumber<double>()) {
      tmp += p.getNumericValue<double>();
    } else {
      return EvalError("expected double, found: " + p.toJson());
    }
  }
  auto length = params.length();
  result.add(VPackValue(length == 0 ? tmp : tmp / length));
  return {};
}

EvalResult Prim_Add(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  auto tmp = double{0};
  for (auto p : VPackArrayIterator(params)) {
    if (p.isNumber<double>()) {
      tmp += p.getNumericValue<double>();
    } else {
      return EvalError("expected double, found: " + p.toJson());
    }
  }
  result.add(VPackValue(tmp));
  return {};
}

EvalResult Prim_Sub(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  auto tmp = double{0};
  auto iter = VPackArrayIterator(params);
  if (iter.valid()) {
    if (!(*iter).isNumber<double>()) {
      return EvalError("expected double, found: " + (*iter).toJson());
    }
    tmp = (*iter).getNumericValue<double>();
    iter++;
    for (; iter.valid(); iter++) {
      if (!(*iter).isNumber<double>()) {
        return EvalError("expected double, found: " + (*iter).toJson());
      }
      tmp -= (*iter).getNumericValue<double>();
    }
  }
  result.add(VPackValue(tmp));
  return {};
}

EvalResult Prim_Mul(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  auto tmp = double{1};
  for (auto p : VPackArrayIterator(params)) {
    if (!p.isNumber<double>()) {
      return EvalError("expected double, found: " + p.toJson());
    }
    tmp *= p.getNumericValue<double>();
  }
  result.add(VPackValue(tmp));
  return {};
}

EvalResult Prim_Div(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  auto tmp = double{1};
  auto iter = VPackArrayIterator(params);
  if (iter.valid()) {
    if (!(*iter).isNumber<double>()) {
      return EvalError("expected double, found: " + (*iter).toJson());
    }
    tmp = (*iter).getNumericValue<double>();
    iter++;
    for (; iter.valid(); iter++) {
      if (!(*iter).isNumber<double>()) {
        return EvalError("expected double, found: " + (*iter).toJson());
      }
      auto v = (*iter).getNumericValue<double>();
      if (v == 0) {
        return EvalError("division by zero");
      }
      tmp /= v;
    }
  }
  result.add(VPackValue(tmp));
  return {};
}

template<typename T>
EvalResult Prim_CmpHuh(Machine& ctx, VPackSlice const params,
                       VPackBuilder& result) {
  auto iter = VPackArrayIterator(params);
  if (iter.valid()) {
    auto proto = *iter;
    iter++;
    if (proto.isNumber()) {
      auto value = proto.getNumber<double>();
      for (; iter.valid(); iter++) {
        auto other = *iter;
        if (!other.isNumber()) {
          return EvalError("Expected numerical value at parameter " +
                           std::to_string(iter.index()) +
                           ", found: " + other.toJson());
        }

        if (!T{}(value, other.getNumber<double>())) {
          result.add(VPackValue(false));
          return {};
        }
      }
    } else if (proto.isBool()) {
      if constexpr (!std::is_same_v<T, std::equal_to<>> &&
                    !std::is_same_v<T, std::not_equal_to<>>) {
        return EvalError("There is no order on booleans");
      }
      auto value = proto.getBool();
      for (; iter.valid(); iter++) {
        auto other = *iter;
        if (!T{}(value, ValueConsideredTrue(other))) {
          result.add(VPackValue(false));
          return {};
        }
      }
    } else if (proto.isString()) {
      if constexpr (!std::is_same_v<T, std::equal_to<>> &&
                    !std::is_same_v<T, std::not_equal_to<>>) {
        return EvalError("There is no order on strings implemented");
      }
      auto value = proto.stringView();
      for (; iter.valid(); iter++) {
        auto other = *iter;
        if (!other.isString()) {
          return EvalError("Expected string value at parameter " +
                           std::to_string(iter.index()) +
                           ", found: " + other.toJson());
        }
        if (!T{}(value, other.stringView())) {
          result.add(VPackValue(false));
          return {};
        }
      }
    } else {
      return EvalError("Cannot compare values of given type, found: " +
                       proto.toJson());
    }
  }
  result.add(VPackValue(true));
  return {};
}

EvalResult Prim_VarRef(Machine& ctx, VPackSlice const params,
                       VPackBuilder& result) {
  if (params.length() == 1) {
    auto nameSlice = params.at(0);
    if (nameSlice.isString()) {
      return ctx.getVariable(nameSlice.copyString(), result);
    }
  }
  return EvalError("expecting a single string parameter, found " +
                   params.toJson());
}

EvalResult Prim_VarSet(Machine& ctx, VPackSlice const params,
                       VPackBuilder& result) {
  if (!params.isArray() && params.length() != 2) {
    return EvalError("expected exactly two parameters");
  }

  auto&& [key, slice] =
      arangodb::basics::VelocyPackHelper::unpackTuple<VPackSlice, VPackSlice>(
          params);
  if (!slice.isObject()) {
    return EvalError("expect second parameter to be an object");
  }

  if (key.isString()) {
    return ctx.setVariable(key.copyString(), slice);
  } else {
    return EvalError("expect first parameter to be a string");
  }
  return {};
}

std::list<std::string> createObjectPaths(velocypack::Slice object,
                                         std::list<std::string> currentPath) {
  for (VPackObjectIterator iter(object); iter.valid(); iter++) {
    currentPath.emplace_back(iter.key().toString());
    if (iter.value().isObject()) {
      // recursive through all available keys
      return createObjectPaths(iter.value(), currentPath);
    }
  }
  return currentPath;
}

EvalResult Prim_IntToStr(Machine& ctx, VPackSlice const params,
                         VPackBuilder& result) {
  if (params.length() != 1) {
    return EvalError("expected a single argument");
  }
  auto value = params.at(0);
  if (!value.isNumber<int64_t>()) {
    return EvalError("expected int, found: " + value.toJson());
  }

  result.add(VPackValue(std::to_string(value.getNumericValue<int64_t>())));
  return {};
}

EvalResult Prim_ToJsonString(Machine& ctx, VPackSlice const params,
                             VPackBuilder& result) {
  if (params.length() != 1) {
    return EvalError("expected a single argument");
  }
  auto value = params.at(0);

  result.add(VPackValue(value.toJson()));

  return {};
}

EvalResult Prim_FalseHuh(Machine& ctx, VPackSlice const params,
                         VPackBuilder& result) {
  if (params.length() != 1) {
    return EvalError("expected a single argument");
  }
  result.add(VPackValue(ValueConsideredFalse(params.at(0))));
  return {};
}

EvalResult Prim_TrueHuh(Machine& ctx, VPackSlice const params,
                        VPackBuilder& result) {
  if (params.length() != 1) {
    return EvalError("expected a single argument");
  }
  result.add(VPackValue(ValueConsideredTrue(params.at(0))));
  return {};
}

EvalResult Prim_Not(Machine& ctx, VPackSlice const params,
                    VPackBuilder& result) {
  if (params.length() != 1) {
    return EvalError("expected a single argument");
  }
  result.add(VPackValue(ValueConsideredFalse(params.at(0))));
  return {};
}

EvalResult Prim_Report(Machine& ctx, VPackSlice const params,
                       VPackBuilder& result) {
  result.add(VPackSlice::nullSlice());
  return ctx.print(paramsToString(params));
}

EvalResult Machine::print(const std::string& msg) const {
  if (printCallback) {
    printCallback(msg);
    return {};
  } else {
    return EvalError("reporting not supported in this context (message was `" +
                     msg + "`)");
  }
}

EvalResult Prim_Error(Machine& ctx, VPackSlice const params,
                      VPackBuilder& result) {
  return EvalError(paramsToString(params));
}

EvalResult Prim_Lambda(Machine& ctx, VPackSlice const paramsList,
                       VPackBuilder& result) {
  VPackArrayIterator paramIterator(paramsList);
  if (!paramIterator.valid()) {
    return EvalError(
        "lambda requires two arguments: a list of argument names and a body");
  }

  auto captures = *paramIterator++;
  if (captures.isArray()) {
    for (auto&& name : VPackArrayIterator(captures)) {
      if (!name.isString()) {
        return EvalError("in capture list: expected name, found: " +
                         name.toJson());
      }
    }
  } else {
    return EvalError("capture list: expected array, found: " +
                     captures.toJson());
  }

  auto params = *paramIterator++;
  if (params.isArray()) {
    for (auto&& name : VPackArrayIterator(params)) {
      if (!name.isString()) {
        return EvalError("in parameter list: expected name, found: " +
                         name.toJson());
      }
    }
  } else {
    return EvalError("parameter list: expected array, found: " +
                     captures.toJson());
  }

  if (!paramIterator.valid()) {
    return EvalError("missing body");
  }

  auto body = *paramIterator++;
  if (paramIterator.valid()) {
    return EvalError("too many arguments to lambda constructor");
  }

  {
    VPackObjectBuilder ob(&result);
    result.add("_params", params);
    result.add("_call", body);
    {
      VPackObjectBuilder cob(&result, "_captures");
      for (auto&& name : VPackArrayIterator(captures)) {
        result.add(name);
        if (auto res = ctx.getVariable(name.copyString(), result); res.fail()) {
          return res;
        }
      }
    }
  }
  return {};
}

EvalResult Prim_Apply(Machine& ctx, VPackSlice const paramsList,
                      VPackBuilder& result) {
  if (!paramsList.isArray() || paramsList.length() != 2) {
    return EvalError(
        "expected one function argument on one list of parameters");
  }

  auto functionSlice = paramsList.at(0);
  auto parameters = paramsList.at(1);
  if (!parameters.isArray()) {
    return EvalError("expected list of parameters, found: " +
                     parameters.toJson());
  }

  return EvaluateApply(ctx, functionSlice, VPackArrayIterator(parameters),
                       result, false);
}

EvalResult Prim_Identity(Machine& ctx, VPackSlice const paramsList,
                         VPackBuilder& result) {
  if (!paramsList.isArray() || paramsList.length() != 1) {
    return EvalError("expecting a single argument");
  }

  result.add(paramsList.at(0));
  return {};
}

EvalResult Prim_Map(Machine& ctx, VPackSlice const paramsList,
                    VPackBuilder& result) {
  if (!paramsList.isArray() || paramsList.length() != 2) {
    return EvalError("expecting two arguments, a function and a list");
  }

  auto functionSlice = paramsList.at(0);
  auto list = paramsList.at(1);

  if (list.isArray()) {
    VPackArrayBuilder ab(&result);
    for (VPackArrayIterator iter(list); iter.valid(); ++iter) {
      VPackBuilder parameter;
      {
        VPackArrayBuilder pb(&parameter);
        parameter.add(VPackValue(iter.index()));
        parameter.add(*iter);
      }

      auto res =
          EvaluateApply(ctx, functionSlice,
                        VPackArrayIterator(parameter.slice()), result, false);
      if (res.fail()) {
        return res.error().wrapMessage("when mapping pair " +
                                       parameter.toJson());
      }
    }
  } else if (list.isObject()) {
    VPackObjectBuilder ob(&result);
    for (VPackObjectIterator iter(list); iter.valid(); ++iter) {
      VPackBuilder parameter;
      {
        VPackArrayBuilder pb(&parameter);
        parameter.add(iter.key());
        parameter.add(iter.value());
      }

      VPackBuilder tempBuffer;

      auto res = EvaluateApply(ctx, functionSlice,
                               VPackArrayIterator(parameter.slice()),
                               tempBuffer, false);
      if (res.fail()) {
        return res.error().wrapMessage("when mapping pair " +
                                       parameter.toJson());
      }

      result.add(iter.key());
      result.add(tempBuffer.slice());
    }
  } else {
    return EvalError("expected list or object, found: " + list.toJson());
  }

  return {};
}

EvalResult Prim_Reduce(Machine& ctx, VPackSlice const paramsList,
                       VPackBuilder& result) {
  if (!paramsList.isArray() || paramsList.length() < 2) {
    return EvalError(
        "expecting at least two arguments, a function and two dicts");
  }

  auto inputValue = paramsList.at(0);
  auto functionSlice = paramsList.at(1);
  auto inputAccumulator = paramsList.at(2);

  if (inputAccumulator.isNone()) {
    return EvalError("input accumulator is required but not set!");
  }

  // reduce(key, value, accumulator)
  // iter can be either VPackArrayIterator or VPackObjectIterator
  auto buildLambdaParameters = [&](VPackBuilder& parameter, auto& iter) {
    {
      VPackArrayBuilder pb(&parameter);
      if constexpr (std::is_same_v<VPackObjectIterator&, decltype(iter)>) {
        parameter.add(iter.key());  // object key
      } else {
        parameter.add(VPackValue(iter.index()));  // array index
      }

      if (iter.isFirst()) {
        parameter.add(iter.value());      // value
        parameter.add(inputAccumulator);  // accum
      } else {
        parameter.add(iter.value());    // value
        parameter.add(result.slice());  // accumulator / previous result
      }
    }
  };

  auto reduceArray = [&](auto& inputValue) -> EvalResult {
    for (VPackArrayIterator iter(inputValue); iter.valid(); ++iter) {
      VPackBuilder parameter;
      buildLambdaParameters(parameter, iter);

      result.clear();
      EvalResult res =
          EvaluateApply(ctx, functionSlice,
                        VPackArrayIterator(parameter.slice()), result, false);
      if (res.fail()) {
        return res.error().wrapMessage("when reducing array parameters " +
                                       parameter.toJson());
      }
    }
    // no error
    return {};
  };

  auto reduceObject = [&](auto& inputValue) -> EvalResult {
    for (VPackObjectIterator iter(inputValue); iter.valid(); iter++) {
      VPackBuilder parameter;
      buildLambdaParameters(parameter, iter);

      result.clear();
      auto res =
          EvaluateApply(ctx, functionSlice,
                        VPackArrayIterator(parameter.slice()), result, false);
      if (res.fail()) {
        return res.error().wrapMessage("when reducing object parameters " +
                                       parameter.toJson());
      }
    }
    // no error
    return {};
  };

  if (inputValue.isArray()) {
    auto res = reduceArray(inputValue);
    if (res.fail()) {
      return res;
    }
  } else if (inputValue.isObject()) {
    auto res = reduceObject(inputValue);
    if (res.fail()) {
      return res;
    }
  } else {
    return EvalError("expected either object or array as input value, found: " +
                     inputValue.toJson() + ". Accumulator can be any type: " +
                     inputAccumulator.toJson() +
                     " (depends on lambda definition");
  }

  return {};
}

EvalResult Prim_Filter(Machine& ctx, VPackSlice const paramsList,
                       VPackBuilder& result) {
  if (!paramsList.isArray() || paramsList.length() != 2) {
    return EvalError(
        "expecting two arguments, a function and a list or object");
  }

  auto functionSlice = paramsList.at(0);
  auto list = paramsList.at(1);

  if (list.isArray()) {
    VPackArrayBuilder ab(&result);
    for (VPackArrayIterator iter(list); iter.valid(); ++iter) {
      VPackBuilder parameter;
      {
        VPackArrayBuilder pb(&parameter);
        parameter.add(VPackValue(iter.index()));
        parameter.add(*iter);
      }

      VPackBuilder filterResult;
      auto res = EvaluateApply(ctx, functionSlice,
                               VPackArrayIterator(parameter.slice()),
                               filterResult, false);
      if (res.fail()) {
        return res.error().wrapMessage("when filtering pair " +
                                       parameter.toJson());
      }

      if (ValueConsideredTrue(filterResult.slice())) {
        result.add(*iter);
      }
    }
  } else if (list.isObject()) {
    VPackObjectBuilder ob(&result);
    for (VPackObjectIterator iter(list); iter.valid(); ++iter) {
      VPackBuilder parameter;
      {
        VPackArrayBuilder pb(&parameter);
        parameter.add(iter.key());
        parameter.add(iter.value());
      }

      VPackBuilder filterResult;
      auto res = EvaluateApply(ctx, functionSlice,
                               VPackArrayIterator(parameter.slice()),
                               filterResult, false);
      if (res.fail()) {
        return res.error().wrapMessage("when mapping pair " +
                                       parameter.toJson());
      }
      if (ValueConsideredTrue(filterResult.slice())) {
        result.add(iter.key());
        result.add(iter.value());
      }
    }
  } else {
    return EvalError("expected list or object, found: " + list.toJson());
  }

  return {};
}

EvalResult Prim_Foldl(Machine& ctx, VPackSlice const paramsList,
                      VPackBuilder& result) {
  return EvalError("Prim_Foldl not implemented");
}

EvalResult Prim_Foldl1(Machine& ctx, VPackSlice const paramsList,
                       VPackBuilder& result) {
  return EvalError("Prim_Foldl1 not implemented");
}

EvalResult Prim_NumberHuh(Machine& ctx, VPackSlice const paramsList,
                          VPackBuilder& result) {
  auto res = extract<VPackSlice>(paramsList);
  if (!res) {
    return std::move(res).asResult();
  }
  auto&& [testee] = res.value();

  result.add(VPackValue(testee.isNumber()));
  return {};
}

EvalResult Prim_NullHuh(Machine& ctx, VPackSlice const paramsList,
                        VPackBuilder& result) {
  auto res = extract<VPackSlice>(paramsList);
  if (!res) {
    return std::move(res).asResult();
  }
  auto&& [testee] = res.value();

  result.add(VPackValue(testee.isNull()));
  return {};
}

EvalResult Prim_BoolHuh(Machine& ctx, VPackSlice const paramsList,
                        VPackBuilder& result) {
  auto res = extract<VPackSlice>(paramsList);
  if (!res) {
    return std::move(res).asResult();
  }
  auto&& [testee] = res.value();

  result.add(VPackValue(testee.isBool()));
  return {};
}

EvalResult Prim_Assert(Machine& ctx, VPackSlice const paramsList,
                       VPackBuilder& result) {
  VPackArrayIterator iter(paramsList);
  if (!iter.valid()) {
    return EvalError("expected at least one argument");
  }

  VPackSlice value = *iter;
  if (ValueConsideredFalse(value)) {
    iter++;
    std::string errorMessage = "assertion failed";
    if (iter.valid()) {
      errorMessage = paramsToString(iter);
    }
    return EvalError(errorMessage);
  }

  result.add(VPackSlice::nullSlice());
  return {};
}

double rand_source_query() {
  return static_cast<double>(std::rand()) / RAND_MAX;
}

EvalResult Prim_Rand(Machine& ctx, VPackSlice const paramsList,
                     VPackBuilder& result) {
  result.add(VPackValue(rand_source_query()));
  return {};
}

EvalResult Prim_RandRange(Machine& ctx, VPackSlice const paramsList,
                          VPackBuilder& result) {
  auto res = extract<double, double>(paramsList);
  if (!res) {
    return res.error();
  }

  auto&& [min, max] = res.value();

  auto v = min + rand_source_query() * (max - min);
  result.add(VPackValue(v));
  return {};
}

EvalResult Prim_ToJson(Machine& ctx, VPackSlice const paramsList,
                       VPackBuilder& result) {
  auto res = extract<VPackSlice>(paramsList);
  if (res.fail()) {
    return res.error();
  }

  auto&& [slice] = res.value();
  result.add(VPackValue(slice.toJson()));
  return {};
}

EvalResult Prim_FromJson(Machine& ctx, VPackSlice const paramsList,
                         VPackBuilder& result) {
  auto res = extract<std::string>(paramsList);
  if (res.fail()) {
    return res.error();
  }

  auto&& [json] = res.value();
  try {
    VPackParser parser(result);
    parser.parse(json);
    return {};
  } catch (VPackException const& e) {
    return EvalError(std::string{"failed to parse json: "} + e.what());
  }
}

void RegisterFunction(Machine& ctx, std::string_view name,
                      Machine::function_type&& f) {
  ctx.setFunction(name, std::move(f));
}

void RegisterAllPrimitives(Machine& ctx) {
  // Calculation operators
  ctx.setFunction("banana", Prim_Add);
  ctx.setFunction("+", Prim_Add);
  ctx.setFunction("-", Prim_Sub);
  ctx.setFunction("*", Prim_Mul);
  ctx.setFunction("/", Prim_Div);

  // Logical operators
  ctx.setFunction("not", Prim_Not);  // unary
  ctx.setFunction("false?", Prim_FalseHuh);
  ctx.setFunction("true?", Prim_TrueHuh);

  // Comparison operators
  ctx.setFunction("eq?", Prim_CmpHuh<std::equal_to<>>);
  ctx.setFunction("gt?", Prim_CmpHuh<std::greater<>>);
  ctx.setFunction("ge?", Prim_CmpHuh<std::greater_equal<>>);
  ctx.setFunction("le?", Prim_CmpHuh<std::less_equal<>>);
  ctx.setFunction("lt?", Prim_CmpHuh<std::less<>>);
  ctx.setFunction("ne?", Prim_CmpHuh<std::not_equal_to<>>);

  // Misc
  ctx.setFunction("min", Prim_Min);
  ctx.setFunction("max", Prim_Max);
  ctx.setFunction("avg", Prim_Avg);

  // Debug operators
  ctx.setFunction("report", Prim_Report);
  ctx.setFunction("error", Prim_Error);
  ctx.setFunction("assert", Prim_Assert);

  // Lambdas
  ctx.setFunction("lambda", Prim_Lambda);

  // Utilities
  ctx.setFunction("int-to-str", Prim_IntToStr);
  ctx.setFunction("to-json-string", Prim_ToJsonString);

  // Functional stuff
  ctx.setFunction("id", Prim_Identity);
  ctx.setFunction("apply", Prim_Apply);
  ctx.setFunction("map",
                  Prim_Map);  // ["map", <func(index, value) -> value>, <list>]
                              // or ["map", <func(key, value) -> value>, <dict>]
  ctx.setFunction("reduce", Prim_Reduce);  // ["reduce", value, <func(index,
                                           // value, accumulator), accumulator]
  ctx.setFunction(
      "filter",
      Prim_Filter);  // ["filter", <func(index, value) -> bool>, <list>] or
                     // ["filter", <func(key, value) -> bool>, <dict>]
  ctx.setFunction("foldl", Prim_Foldl);
  ctx.setFunction("foldl1", Prim_Foldl1);

  // Type-related functions
  ctx.setFunction("number?", Prim_NumberHuh);
  ctx.setFunction("null?", Prim_NullHuh);
  ctx.setFunction("bool?", Prim_BoolHuh);

  ctx.setFunction("var-ref", Prim_VarRef);
  ctx.setFunction("bind-ref", Prim_VarRef);

  ctx.setFunction("rand", Prim_Rand);
  ctx.setFunction("rand-range", Prim_RandRange);

  ctx.setFunction("to-json", Prim_ToJson);
  ctx.setFunction("from-json", Prim_FromJson);
}

}  // namespace arangodb::greenspun

ext: cpp

max_stars_repo_name: Mu-L/arangodb

max_issues_repo_name: Mu-L/arangodb

max_forks_repo_name: Mu-L/arangodb


text:
// BoostLogSampleFromSinks.cpp : This file contains the 'main' function. Program execution begins and ends there.
// TODO: Boost deps has not been included here.

#include "pch.h"
/**
 * A simple sample of Boost Log
 */
#include <windows.h>
#pragma warning(push)
//#pragma warning(disable:4819)

#include <boost/shared_ptr.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/attributes/named_scope.hpp>
#include <boost/current_function.hpp>
#include <boost/log/attributes/scoped_attribute.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>

#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/record_ordering.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/log/sinks.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <string>
//
#pragma warning(pop)
//#pragma warning(disable:4503)
namespace attrs = boost::log::attributes;
namespace logging = boost::log;
namespace sinks = boost::log::sinks;
namespace keywords = boost::log::keywords;
using namespace std;

//enum severity_level
//{
//	normal,
//	notification,
//	warning,
//	error,
//	critical
//};
boost::log::sources::severity_logger< boost::log::trivial::severity_level > lg;

// Convert file path to only the filename
std::string path_to_filename(std::string path) {
	return path.substr(path.find_last_of("/\\") + 1);
}

#define logInfo(message)                          \
  LOG_LOCATION;                                               \
  BOOST_LOG_SEV(lg, boost::log::trivial::severity_level::info) << message

#define LOG_LOCATION                            \
  boost::log::attribute_cast<boost::log::attributes::mutable_constant<int>>(boost::log::core::get()->get_global_attributes()["Line"]).set(__LINE__); \
  boost::log::attribute_cast<boost::log::attributes::mutable_constant<std::string>>(boost::log::core::get()->get_global_attributes()["File"]).set(path_to_filename(__FILE__));

// Logging macro that includes severity, filename, and line number.
// Copied and modified from
// https://stackoverflow.com/questions/24750218/boost-log-to-print-source-code-file-name-and-line-number
// Set attribute and return the new value
template <typename ValueType>
ValueType SetGetAttrib(const char* name, ValueType value) {
	auto attr = boost::log::attribute_cast<
		boost::log::attributes::mutable_constant<ValueType>>(
			boost::log::core::get()->get_global_attributes()[name]);
	attr.set(value);
	return attr.get();
}

static std::string PathToFilename(const std::string& path) {
	std::string sub_path = path.substr(path.find_last_of("/\\") + 1);
	return sub_path;
}

static std::wstring GetHxWinAgentLogsFolder()
{
	TCHAR tcRoot[MAX_PATH];
	GetWindowsDirectory(tcRoot, MAX_PATH);
	tcRoot[3] = 0;
	wstring OutputFolder = (wstring)tcRoot + L"Logs";
	if (CreateDirectory(OutputFolder.c_str(), NULL) ||
		ERROR_ALREADY_EXISTS == GetLastError())
	{
		return OutputFolder;
	}
	else
		return L"";
}

static void init_log(void)
{
	/* init boost log
	 * 1. Add common attributes
	 * 2. set log filter to trace
	 */
	boost::log::add_common_attributes();
	boost::log::core::get()->add_global_attribute("Scope",
		boost::log::attributes::named_scope());
	boost::log::core::get()->set_filter(
		boost::log::trivial::severity >= boost::log::trivial::info
	);

	boost::log::core::get()->add_global_attribute("Line", boost::log::attributes::mutable_constant<int>(5));
	boost::log::core::get()->add_global_attribute("File", boost::log::attributes::mutable_constant<std::string>(""));

	/* log formatter:
	 * [TimeStamp] |(ProcessID)-(ThreadId)|[Severity Level] [Scope] Log message
	 */
	auto fmtTimeStamp = boost::log::expressions::
		format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S");
	auto fmtTProcId = boost::log::expressions::
		attr<boost::log::attributes::current_process_id::value_type>("ProcessID");
	auto fmtThreadId = boost::log::expressions::
		attr<boost::log::attributes::current_thread_id::value_type>("ThreadID");
	auto fmtSeverity = boost::log::expressions::
		attr<boost::log::trivial::severity_level>("Severity");
	auto fmtScope = boost::log::expressions::format_named_scope("Scope",
		boost::log::keywords::format = "%n(%f:%l)",
		boost::log::keywords::iteration = boost::log::expressions::reverse,
		boost::log::keywords::depth = 2);
	boost::log::formatter logFmt =
		boost::log::expressions::format("[%1%]|(%2%)-(%3%)| (%4%) [%5%]: %6%")
		% fmtTimeStamp % fmtThreadId % fmtTProcId % fmtSeverity % fmtScope
		% boost::log::expressions::smessage;

	/* console sink */
	/*auto consoleSink = boost::log::add_console_log(std::clog);
	consoleSink->set_formatter(logFmt);*/

	std::wstring fileName = GetHxWinAgentLogsFolder() + L"/Provider_%Y-%m-%d_%2N.log";

	auto fsSink = boost::log::add_file_log(
		boost::log::keywords::file_name = fileName,
		boost::log::keywords::rotation_size = 10 * 1024 * 1024,
		boost::log::keywords::target = GetHxWinAgentLogsFolder(),
		boost::log::keywords::open_mode = std::ios_base::app);
	fsSink->set_formatter(logFmt);
	fsSink->locked_backend()->auto_flush(true);

}

static void Test(void)
{
	BOOST_LOG_FUNCTION();
	BOOST_LOG_TRIVIAL(info) << "Info Log in Test()";
}

int main(int argc, char **argv)
{

	BOOST_LOG_FUNCTION();
	init_log();
	logInfo("Hello"); //Macro based wrapping for regular logging with line/file . Does not require BOOST_LOG_FUNCTION

	int i = 10;
	while (i < 100)
	{
		Sleep(500);
		BOOST_LOG_TRIVIAL(info) << "Info Log";
		Test();
		BOOST_LOG_TRIVIAL(info) << "app exiting";
	}
	return 0;
}

max_stars_repo_name: manojmanpal/cppLibSamples

max_issues_repo_name: manojmanpal/cppLibSamples

max_forks_repo_name: manojmanpal/cppLibSamples


text:
/* (c) 2016, 2021 FFF Services. For details refers to LICENSE.txt */
/*
 * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
 *
 * The MIT License
 *
 * 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.
 */
#pragma once
#include <graphene/chain/protocol/operations.hpp>
#include <graphene/db/generic_index.hpp>
#include <boost/multi_index/composite_key.hpp>

namespace graphene { namespace chain {

   /**
    * @class account_statistics_object
    * @ingroup object
    * @ingroup implementation
    *
    * This object contains regularly updated statistical data about an account. It is provided for the purpose of
    * separating the account data that changes frequently from the account data that is mostly static, which will
    * minimize the amount of data that must be backed up as part of the undo history everytime a transfer is made.
    */
   class account_statistics_object : public graphene::db::abstract_object<implementation_ids, impl_account_statistics_object_type, account_statistics_object>
   {
      public:
         account_id_type owner;

         /**
          * The most recent calculated voting stake.
          */
         uint64_t voting_stake = 0;

         /**
          * The most recent votes cast.
          */
         boost::container::flat_set<vote_id_type> votes;

         /**
          * Keep the most recent operation as a root pointer to a linked list of the transaction history.
          */
         account_transaction_history_id_type most_recent_op;
         uint32_t                            total_ops = 0;

         /**
          * When calculating votes it is necessary to know how much is stored in orders (and thus unavailable for
          * transfers). Rather than maintaining an index of [asset,owner,order_id] we will simply maintain the running
          * total here and update it every time an order is created or modified.
          */
         share_type total_core_in_orders;

         /**
          * Tracks the fees paid by this account which have not been disseminated to the various parties that receive
          * them yet (registrar, referrer, lifetime referrer, network, etc). This is used as an optimization to avoid
          * doing massive amounts of uint128 arithmetic on each and every operation.
          *
          * These fees will be paid out as vesting cash-back, and this counter will reset during the maintenance
          * interval.
          */
         share_type pending_fees;
         /**
          * Same as @ref pending_fees, except these fees will be paid out as pre-vested cash-back (immediately
          * available for withdrawal) rather than requiring the normal vesting period.
          */
         share_type pending_vested_fees;
   };

   /**
    * @brief Tracks the balance of a single account/asset pair
    * @ingroup object
    *
    * This object is indexed on owner and asset_type so that black swan
    * events in asset_type can be processed quickly.
    */
   class account_balance_object : public graphene::db::abstract_object<implementation_ids, impl_account_balance_object_type, account_balance_object>
   {
      public:
         account_id_type   owner;
         asset_id_type     asset_type;
         share_type        balance;

         asset get_balance()const { return asset(balance, asset_type); }
         void  adjust_balance(const asset& delta);
   };

   /**
    * @brief This class represents an account on the object graph
    * @ingroup object
    * @ingroup protocol
    *
    * Accounts are the primary unit of authority on the graphene system. Users must have an account in order to use
    * assets, trade in the markets, vote for committee_members, etc.
    */
   class account_object : public graphene::db::abstract_object<protocol_ids, account_object_type, account_object>
   {
      public:
         ///The account that paid the fee to register this account. Receives a percentage of referral rewards.
         account_id_type registrar;

         /// The account's name. This name must be unique among all account names on the graph. May not be empty.
         std::string name;

         /**
          * The owner authority represents absolute control over the account. Usually the keys in this authority will
          * be kept in cold storage, as they should not be needed very often and compromise of these keys constitutes
          * complete and irrevocable loss of the account. Generally the only time the owner authority is required is to
          * update the active authority.
          */
         authority owner;
         /// The owner authority contains the hot keys of the account. This authority has control over nearly all
         /// operations the account may perform.
         authority active;

         account_options options;
         publishing_rights rights_to_publish;

         /// The reference implementation records the account's statistics in a separate object. This field contains the
         /// ID of that object.
         account_statistics_id_type statistics;

         /**
          * This flag is set when the top_n logic sets both authorities,
          * and gets reset when authority is set.
          */
         uint8_t top_n_control_flags = 0;
         static const uint8_t top_n_control_owner  = 1;
         static const uint8_t top_n_control_active = 2;

         bool is_publishing_manager() const { return rights_to_publish.is_publishing_manager; }
   };

   /**
    *  @brief This secondary index will allow a reverse lookup of all accounts that a particular key or account
    *  is an potential signing authority.
    */
   class account_member_index : public graphene::db::secondary_index
   {
      public:
         virtual void object_inserted( const graphene::db::object& obj ) override;
         virtual void object_removed( const graphene::db::object& obj ) override;
         virtual void about_to_modify( const graphene::db::object& before ) override;
         virtual void object_modified( const graphene::db::object& after  ) override;

         /** given an account or key, map it to the set of accounts that reference it in an active or owner authority */
         std::map<account_id_type, std::set<account_id_type>> account_to_account_memberships;
         std::map<public_key_type, std::set<account_id_type>> account_to_key_memberships;
         /** some accounts use address authorities in the genesis block */

      protected:
         std::set<account_id_type>  get_account_members( const account_object& a )const;
         std::set<public_key_type>  get_key_members( const account_object& a )const;

         std::set<account_id_type>  before_account_members;
         std::set<public_key_type>  before_key_members;
   };

   struct by_account_asset;
   struct by_asset_balance;
   /**
    * @ingroup object_index
    */
   typedef boost::multi_index_container<
      account_balance_object,
      db::mi::indexed_by<
         db::object_id_index,
         db::mi::ordered_unique<db::mi::tag<by_account_asset>,
            db::mi::composite_key<
               account_balance_object,
               db::mi::member<account_balance_object, account_id_type, &account_balance_object::owner>,
               db::mi::member<account_balance_object, asset_id_type, &account_balance_object::asset_type>
            >
         >,
         db::mi::ordered_unique<db::mi::tag<by_asset_balance>,
            db::mi::composite_key<
               account_balance_object,
               db::mi::member<account_balance_object, asset_id_type, &account_balance_object::asset_type>,
               db::mi::member<account_balance_object, share_type, &account_balance_object::balance>,
               db::mi::member<account_balance_object, account_id_type, &account_balance_object::owner>
            >,
            db::mi::composite_key_compare<
               std::less<asset_id_type>,
               std::greater<share_type>,
               std::less<account_id_type>
            >
         >
      >
   > account_balance_object_multi_index_type;

   /**
    * @ingroup object_index
    */
   typedef graphene::db::generic_index<account_balance_object, account_balance_object_multi_index_type> account_balance_index;

   struct by_name;
   struct by_publishing_manager_and_name;

   template <typename TAG, typename _t_object>
   struct key_extractor;

   template <>
   struct key_extractor<graphene::db::by_id, account_object>
   {
      static graphene::db::object_id_type get(account_object const& ob)
      {
         return ob.id;
      }
   };

   template <>
   struct key_extractor<by_name, account_object>
   {
      static std::string get(account_object const& ob)
      {
         return ob.name;
      }
   };

   /**
    * @ingroup object_index
    */
   typedef boost::multi_index_container<
      account_object,
      db::mi::indexed_by<
         db::object_id_index,
         db::mi::ordered_unique<db::mi::tag<by_name>,
            db::mi::member<account_object, std::string, &account_object::name>
         >,
         db::mi::ordered_unique<db::mi::tag<by_publishing_manager_and_name>,
            db::mi::composite_key<account_object,
               db::mi::const_mem_fun<account_object, bool, &account_object::is_publishing_manager>,
               db::mi::member<account_object, std::string, &account_object::name>
            >
         >
      >
   > account_multi_index_type;

   /**
    * @ingroup object_index
    */
   typedef graphene::db::generic_index<account_object, account_multi_index_type> account_index;

}}

FC_REFLECT_DERIVED( graphene::chain::account_object,
                    (graphene::db::object),
                    (registrar)
                    (name)(owner)(active)(options)(rights_to_publish)(statistics)
                    (top_n_control_flags)
                    )

FC_REFLECT_DERIVED( graphene::chain::account_balance_object,
                    (graphene::db::object),
                    (owner)(asset_type)(balance) )

FC_REFLECT_DERIVED( graphene::chain::account_statistics_object,
                    (graphene::db::object),
                    (owner)
                    (voting_stake)
                    (votes)
                    (most_recent_op)
                    (total_ops)
                    (total_core_in_orders)
                    (pending_fees)
                    (pending_vested_fees)
                  )

ext: hpp


text:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "IRAssembler.h"

#include <boost/functional/hash.hpp>
#include <boost/optional/optional.hpp>
#include <sstream>
#include <string>
#include <unordered_map>

using namespace sparta;

namespace {

#define OP(OP, KIND, STR) {OPCODE_##OP, STR},
std::unordered_map<IROpcode, std::string, boost::hash<IROpcode>>
    opcode_to_string_table = {
        OPS
        {IOPCODE_LOAD_PARAM, "load-param"},
        {IOPCODE_LOAD_PARAM_OBJECT, "load-param-object"},
        {IOPCODE_LOAD_PARAM_WIDE, "load-param-wide"},
        {IOPCODE_MOVE_RESULT_PSEUDO, "move-result-pseudo"},
        {IOPCODE_MOVE_RESULT_PSEUDO_OBJECT, "move-result-pseudo-object"},
        {IOPCODE_MOVE_RESULT_PSEUDO_WIDE, "move-result-pseudo-wide"},
};
#undef OP

#define OP(OP, KIND, STR) {STR, OPCODE_##OP},
std::unordered_map<std::string, IROpcode> string_to_opcode_table = {
    OPS
    {"load-param", IOPCODE_LOAD_PARAM},
    {"load-param-object", IOPCODE_LOAD_PARAM_OBJECT},
    {"load-param-wide", IOPCODE_LOAD_PARAM_WIDE},
    {"move-result-pseudo", IOPCODE_MOVE_RESULT_PSEUDO},
    {"move-result-pseudo-object", IOPCODE_MOVE_RESULT_PSEUDO_OBJECT},
    {"move-result-pseudo-wide", IOPCODE_MOVE_RESULT_PSEUDO_WIDE},
};
#undef OP

using LabelDefs = std::unordered_map<std::string, MethodItemEntry*>;
using LabelRefs =
    std::unordered_map<const IRInstruction*, std::vector<std::string>>;

uint16_t reg_from_str(const std::string& reg_str) {
  always_assert(reg_str.at(0) == 'v');
  uint16_t reg;
  sscanf(&reg_str.c_str()[1], "%hu", &reg);
  return reg;
}

std::string reg_to_str(uint16_t reg) { return "v" + std::to_string(reg); }

s_expr to_s_expr(const IRInstruction* insn, const LabelRefs& label_refs) {
  auto op = insn->opcode();
  auto opcode_str = opcode_to_string_table.at(op);
  std::vector<s_expr> s_exprs{s_expr(opcode_str)};
  if (insn->dests_size()) {
    s_exprs.emplace_back(reg_to_str(insn->dest()));
  }
  if (opcode::has_variable_srcs_size(op)) {
    std::vector<s_expr> src_s_exprs;
    for (size_t i = 0; i < insn->srcs_size(); ++i) {
      src_s_exprs.emplace_back(reg_to_str(insn->src(i)));
    }
    s_exprs.emplace_back(src_s_exprs);
  } else {
    for (size_t i = 0; i < insn->srcs_size(); ++i) {
      s_exprs.emplace_back(reg_to_str(insn->src(i)));
    }
  }
  switch (opcode::ref(op)) {
  case opcode::Ref::None:
    break;
  case opcode::Ref::Data:
    always_assert_log(false, "Not yet supported");
    break;
  case opcode::Ref::Field:
    s_exprs.emplace_back(show(insn->get_field()));
    break;
  case opcode::Ref::Method:
    s_exprs.emplace_back(show(insn->get_method()));
    break;
  case opcode::Ref::String:
    s_exprs.emplace_back(insn->get_string()->str());
    break;
  case opcode::Ref::Literal:
    s_exprs.emplace_back(std::to_string(insn->get_literal()));
    break;
  case opcode::Ref::Type:
    s_exprs.emplace_back(insn->get_type()->get_name()->str());
    break;
  }

  if (is_branch(op)) {
    const auto& label_strs = label_refs.at(insn);
    if (is_switch(op)) {
      // (switch v0 (:a :b :c))
      std::vector<s_expr> label_exprs;
      for (const auto& label_str : label_strs) {
        label_exprs.emplace_back(label_str);
      }
      s_exprs.emplace_back(label_exprs);
    } else {
      // (if-eqz v0 :a)
      always_assert(label_strs.size() == 1);
      s_exprs.emplace_back(label_strs[0]);
    }
  }
  return s_expr(s_exprs);
}

namespace {

std::string get_dbg_label(uint32_t i) { return ("dbg_" + std::to_string(i)); }

s_expr _to_s_expr(const DexPosition* pos, uint32_t idx, uint32_t parent_idx) {
  auto idx_str = get_dbg_label(idx);
  auto parent_idx_str = get_dbg_label(parent_idx);
  return s_expr({
      s_expr(".pos:" + idx_str),
      s_expr(show(pos->method)),
      s_expr(pos->file->c_str()),
      s_expr(std::to_string(pos->line)),
      s_expr(parent_idx_str),
  });
}
}

std::vector<s_expr> to_s_exprs(
    const DexPosition* pos,
    std::vector<const DexPosition*>* positions_emitted) {
  if (pos->parent) {
    // Get it? snay is redex's dad
    auto snay = pos->parent;
    for (size_t i = 0; i < positions_emitted->size(); i++) {
      auto pos_emitted = positions_emitted->at(i);
      if (*pos_emitted == *snay) {
        // Shane thought he could hide from us... hah! a quick linear search
        // got him
        positions_emitted->push_back(pos);
        return {_to_s_expr(pos, positions_emitted->size() - 1, i)};
      }
    }
    auto result = to_s_exprs(snay, positions_emitted);
    always_assert(positions_emitted->size() > 0);
    auto parent_idx = positions_emitted->size() - 1;
    positions_emitted->push_back(pos);
    auto pos_idx = positions_emitted->size() - 1;
    result.push_back(_to_s_expr(pos, pos_idx, parent_idx));
    return result;
  } else {
    positions_emitted->push_back(pos);
    auto idx_str = get_dbg_label(positions_emitted->size() - 1);
    return {s_expr({
        s_expr(".pos:" + idx_str),
        s_expr(show(pos->method)),
        s_expr(pos->file->c_str()),
        s_expr(std::to_string(pos->line)),
    })};
  }
}

std::unique_ptr<IRInstruction> instruction_from_s_expr(
    const std::string& opcode_str, const s_expr& e, LabelRefs* label_refs) {
  auto op_it = string_to_opcode_table.find(opcode_str);
  always_assert_log(op_it != string_to_opcode_table.end(),
                    "'%s' is not a valid opcode",
                    opcode_str.c_str());
  auto op = op_it->second;
  auto insn = std::make_unique<IRInstruction>(op);
  std::string reg_str;
  s_expr tail = e;
  if (insn->dests_size()) {
    s_patn({s_patn(&reg_str)}, tail)
        .must_match(tail, "Expected dest reg for " + opcode_str);
    insn->set_dest(reg_from_str(reg_str));
  }
  if (opcode::has_variable_srcs_size(op)) {
    auto srcs = tail[0];
    tail = tail.tail(1);
    insn->set_arg_word_count(srcs.size());
    for (size_t i = 0; i < insn->srcs_size(); ++i) {
      insn->set_src(i, reg_from_str(srcs[i].get_string()));
    }
  } else {
    for (size_t i = 0; i < insn->srcs_size(); ++i) {
      s_patn({s_patn(&reg_str)}, tail)
          .must_match(tail, "Expected src reg for" + opcode_str);
      insn->set_src(i, reg_from_str(reg_str));
    }
  }
  switch (opcode::ref(op)) {
  case opcode::Ref::None:
    break;
  case opcode::Ref::Data:
    always_assert_log(false, "Not yet supported");
    break;
  case opcode::Ref::Field: {
    std::string str;
    s_patn({s_patn(&str)}, tail)
        .must_match(tail, "Expecting string literal for " + opcode_str);
    auto* dex_field = DexField::make_field(str);
    insn->set_field(dex_field);
    break;
  }
  case opcode::Ref::Method: {
    std::string str;
    s_patn({s_patn(&str)}, tail)
        .must_match(tail, "Expecting string literal for " + opcode_str);
    auto* dex_method = DexMethod::make_method(str);
    insn->set_method(dex_method);
    break;
  }
  case opcode::Ref::String: {
    std::string str;
    s_patn({s_patn(&str)}, tail)
        .must_match(tail, "Expecting string literal for " + opcode_str);
    auto* dex_str = DexString::make_string(str);
    insn->set_string(dex_str);
    break;
  }
  case opcode::Ref::Literal: {
    std::string num_str;
    s_patn({s_patn(&num_str)}, tail)
        .must_match(tail, "Expecting numeric literal for " + opcode_str);
    int64_t num;
    std::istringstream in(num_str);
    in >> num;
    insn->set_literal(num);
    break;
  }
  case opcode::Ref::Type: {
    std::string type_str;
    s_patn({s_patn(&type_str)}, tail)
        .must_match(tail, "Expecting type specifier for " + opcode_str);
    DexType* ty = DexType::make_type(type_str.c_str());
    insn->set_type(ty);
    break;
  }
  }

  if (is_branch(op)) {
    std::string label_str;
    if (is_switch(op)) {
      s_expr list;
      s_patn({s_patn(list)}, tail)
          .must_match(tail, "Expecting list of labels for " + opcode_str);
      while (s_patn({s_patn(&label_str)}, list).match_with(list)) {
        (*label_refs)[insn.get()].push_back(label_str);
      }
    } else {
      s_patn({s_patn(&label_str)}, tail)
          .must_match(tail, "Expecting label for " + opcode_str);
      (*label_refs)[insn.get()].push_back(label_str);
    }
  }

  always_assert_log(tail.is_nil(),
                    "Found unexpected trailing items when parsing %s: %s",
                    opcode_str.c_str(),
                    tail.str().c_str());
  return insn;
}

std::unique_ptr<DexPosition> position_from_s_expr(
    const s_expr& e,
    const std::unordered_map<std::string, DexPosition*>& positions) {
  std::string method_str;
  std::string file_str;
  std::string line_str;
  s_expr parent_expr;
  s_patn({
      s_patn(&method_str),
      s_patn(&file_str),
      s_patn(&line_str),
  }, parent_expr).must_match(e, "Expected 3 or 4 args for position directive");
  auto* dex_method =
      static_cast<DexMethod*>(DexMethod::make_method(method_str));
  // We should ideally allow DexPosition to take non-concrete methods too...
  always_assert(dex_method->is_concrete());
  auto* file = DexString::make_string(file_str);
  uint32_t line;
  std::istringstream in(line_str);
  in >> line;
  auto pos = std::make_unique<DexPosition>(line);
  pos->bind(dex_method, file);
  if (!parent_expr.is_nil()) {
    std::string parent_str;
    s_patn({
               s_patn(&parent_str),
           })
        .must_match(parent_expr,
                    "Expected 4th arg of pos directive to be a string");

    // Try and find parent matching parent_str at end of expr
    auto iter = positions.find(parent_str);
    if (iter != positions.end()) {
      pos->parent = iter->second;
    } else {
      pos->parent = nullptr;
      fprintf(stderr,
              "Failed to find parent position with label %s\n",
              parent_str.c_str());
    }
  } else {
    pos->parent = nullptr;
  }
  return pos;
}

/*
 * Connect label defs to label refs via creation of MFLOW_TARGET instances
 */
void handle_labels(IRCode* code,
                   const LabelDefs& label_defs,
                   const LabelRefs label_refs) {
  for (auto& mie : InstructionIterable(code)) {
    auto* insn = mie.insn;
    if (label_refs.count(insn)) {
      for (const std::string& label : label_refs.at(insn)) {
        auto target_mie = label_defs.at(label);
        // Since one label can be the target of multiple branches, but one
        // MFLOW_TARGET can only point to one branching opcode, we may need to
        // create additional MFLOW_TARGET items here.
        always_assert(target_mie->type == MFLOW_TARGET);
        BranchTarget* target = target_mie->target;
        if (target->src == nullptr) {
          target->src = &mie;
        } else {
          // First target already filled. Create another
          BranchTarget* new_target =
              (target->type == BRANCH_SIMPLE)
                  ? new BranchTarget(&mie)
                  : new BranchTarget(&mie, target->case_key);
          auto new_target_mie = new MethodItemEntry(new_target);
          code->insert_before(code->iterator_to(*target_mie), *new_target_mie);
        }
      }
    }
  }

  // Clean up any unreferenced labels
  for (auto& mie : *code) {
    if (mie.type == MFLOW_TARGET && mie.target->src == nullptr) {
      delete mie.target;
      mie.type = MFLOW_FALLTHROUGH;
    }
  }
}

std::unordered_map<std::string, MethodItemEntry*> get_catch_name_map(
    const s_expr& insns) {
  std::unordered_map<std::string, MethodItemEntry*> result;
  for (size_t i = 0; i < insns.size(); ++i) {
    std::string keyword;
    s_expr tail;
    if (s_patn({s_patn(&keyword)}, tail).match_with(insns[i])) {
      if (keyword == ".catch") {
        // Catch markers look like this:
        // (.catch (this next) "LCatchType;")
        // where next and "LCatchType;" are optional
        std::string this_catch;
        s_expr maybe_next, type_expr;
        s_patn({s_patn({s_patn(&this_catch)}, maybe_next)}, type_expr)
            .must_match(tail, "catch marker missing a name list");
        // FIXME?
        result.emplace(
            this_catch,
            new MethodItemEntry(static_cast<DexType*>(nullptr)));
      }
    }
  }
  return result;
}

// Can we merge this target into the same label as the previous target?
bool can_merge(IRList::const_iterator prev, IRList::const_iterator it) {
  always_assert(it->type == MFLOW_TARGET);
  return prev->type == MFLOW_TARGET &&
         // can't merge if/goto targets with switch targets
         it->target->type == prev->target->type &&
         // if/goto targets only need to be adjacent in the instruction stream
         // to be merged into a single label
         (it->target->type == BRANCH_SIMPLE ||
          // switch targets also need matching case keys
          it->target->case_key == prev->target->case_key);
}

s_expr create_try_expr(TryEntryType type, const std::string& catch_name) {
  // (.try_start name) and (.try_end name)
  const std::string& type_str = type == TRY_START ? ".try_start" : ".try_end";
  return s_expr({s_expr(type_str), s_expr(catch_name)});
}

s_expr create_catch_expr(const MethodItemEntry* mie,
                         const std::unordered_map<const MethodItemEntry*,
                                                  std::string>& catch_names) {
  // (.catch (this_name next_name) "LCatchType;")
  // where next_name and the "LCatchType;" are optional
  std::vector<s_expr> catch_name_exprs;
  catch_name_exprs.emplace_back(catch_names.at(mie));
  if (mie->centry->next != nullptr) {
    catch_name_exprs.emplace_back(catch_names.at(mie->centry->next));
  }
  std::vector<s_expr> result;
  result.emplace_back(".catch");
  result.emplace_back(catch_name_exprs);
  if (mie->centry->catch_type != nullptr) {
    result.emplace_back(mie->centry->catch_type->get_name()->str());
  }
  return s_expr(result);
}

} // namespace

namespace assembler {

s_expr to_s_expr(const IRCode* code) {
  std::vector<s_expr> exprs;
  LabelRefs label_refs;
  std::unordered_map<const MethodItemEntry*, std::string> catch_names;

  size_t label_ctr{0};
  auto generate_label_name = [&]() {
    return ":L" + std::to_string(label_ctr++);
  };

  size_t catch_ctr{0};
  auto generate_catch_name = [&]() {
    return "c" + std::to_string(catch_ctr++);
  };

  // Gather jump targets and give them string names
  for (auto it = code->cbegin(); it != code->cend(); ++it) {
    switch (it->type) {
      case MFLOW_TARGET: {
        auto bt = it->target;
        always_assert_log(bt->src != nullptr, "%s", SHOW(code));

        // Don't generate redundant labels. If we would duplicate the previous
        // label, steal its name instead of generating another
        if (it != code->begin()) {
          auto prev = std::prev(it);
          if (can_merge(prev, it)) {
            auto& label_strs = label_refs.at(prev->target->src->insn);
            if (label_strs.size() > 0) {
              const auto& label_name = label_strs.back();
              label_refs[bt->src->insn].push_back(label_name);
              break;
            }
          }
        }
        label_refs[bt->src->insn].push_back(generate_label_name());
        break;
      }
      case MFLOW_CATCH:
        catch_names.emplace(&*it, generate_catch_name());
        break;
      default:
        break;
    }
  }

  // Now emit the exprs
  std::unordered_map<IRInstruction*, size_t> unused_label_index;
  std::vector<const DexPosition*> positions_emitted;
  for (auto it = code->begin(); it != code->end(); ++it) {
    switch (it->type) {
      case MFLOW_OPCODE:
        exprs.emplace_back(::to_s_expr(it->insn, label_refs));
        break;
      case MFLOW_TRY:
        exprs.emplace_back(create_try_expr(
            it->tentry->type, catch_names.at(it->tentry->catch_start)));
        break;
      case MFLOW_CATCH:
        exprs.emplace_back(create_catch_expr(&*it, catch_names));
        break;
      case MFLOW_DEBUG:
        always_assert_log(false, "Not yet implemented");
      case MFLOW_POSITION:
        for (const auto& e : ::to_s_exprs(it->pos.get(), &positions_emitted)) {
          exprs.push_back(e);
        }
        break;
      case MFLOW_TARGET: {
        auto branch_target = it->target;
        auto insn = branch_target->src->insn;
        const auto& label_strs = label_refs.at(insn);

        if (branch_target->type == BRANCH_MULTI) {
          // Claim one of the labels.
          // Doesn't matter which one as long as no other s_expr re-uses it.
          auto& index = unused_label_index[insn];
          auto label_str = label_strs[index];
          ++index;

          const s_expr& label =
              s_expr({s_expr(label_str),
                      s_expr(std::to_string(branch_target->case_key))});

          // Don't duplicate labels even if some crazy person has two switches
          // that share targets :O
          if (exprs.empty() || exprs.back() != label) {
            exprs.emplace_back(label);
          }
        } else {
          always_assert(branch_target->type == BRANCH_SIMPLE);
          always_assert_log(
              label_strs.size() == 1,
              "Expecting 1 label string, actually have %d. code:\n%s",
              label_strs.size(),
              SHOW(code));
          const s_expr& label = s_expr({s_expr(label_strs[0])});

          // Two gotos to the same destination will produce two MFLOW_TARGETs
          // but we only need one label in the s expression syntax.
          if (exprs.empty() || exprs.back() != label) {
            exprs.push_back(label);
          }
        }
        break;
      }
      case MFLOW_FALLTHROUGH:
        break;
      case MFLOW_DEX_OPCODE:
        not_reached();
    }
  }

  return s_expr(exprs);
}

static boost::optional<uint16_t> largest_reg_operand(const IRInstruction* insn) {
  boost::optional<uint16_t> max_reg;
  if (insn->dests_size()) {
    max_reg = insn->dest();
  }
  for (size_t i = 0; i < insn->srcs_size(); ++i) {
    // boost::none is the smallest element of the ordering.
    // It's smaller than any uint16_t.
    max_reg = std::max(max_reg, boost::optional<uint16_t>(insn->src(i)));
  }
  return max_reg;
}

std::unique_ptr<IRCode> ircode_from_s_expr(const s_expr& e) {
  s_expr insns_expr;
  auto code = std::make_unique<IRCode>();
  always_assert(s_patn({}, insns_expr).match_with(e));
  always_assert_log(insns_expr.size() > 0, "Empty instruction list?! %s");
  LabelDefs label_defs;
  LabelRefs label_refs;
  boost::optional<uint16_t> max_reg;
  std::unordered_map<std::string, DexPosition*> positions;

  // map from catch name to catch marker pointer
  const auto& catches = get_catch_name_map(insns_expr);

  for (size_t i = 0; i < insns_expr.size(); ++i) {
    std::string keyword;
    s_expr tail;
    if (s_patn({s_patn(&keyword)}, tail).match_with(insns_expr[i])) {
      // check if keyword starts with ".pos"
      if (strncmp(keyword.c_str(), ".pos", 4) == 0) {
        auto pos = position_from_s_expr(tail, positions);
        // check if keyword also has dbg label
        if (keyword != ".pos") {
          // get dbg label found after colon in keyword string
          auto key = keyword.substr(keyword.find(":") + 1);
          // insert pos into positions map using dbg label as key
          positions[key] = pos.get();
        }
        code->push_back(std::move(pos));
      } else if (keyword.substr(0, 4) == ".try") {
        // Try markers look like this:
        // (.try_start catch_name)
        // (.try_end catch_name)
        const auto& rest = keyword.substr(4, std::string::npos);
        bool is_start = rest == "_start";
        always_assert_log(is_start ^ (rest == "_end"),
                          "try must be .try_start or .try_end");
        std::string catch_name;
        s_patn({s_patn(&catch_name)})
            .must_match(tail, "try marker is missing a name");
        always_assert(catch_name != "");
        auto try_marker = new MethodItemEntry(is_start ? TRY_START : TRY_END,
                                              catches.at(catch_name));
        code->push_back(*try_marker);

      } else if (keyword == ".catch") {
        // Catch markers look like this:
        // (.catch (this next) "LCatchType;")
        // where next and "LCatchType;" are optional
        std::string this_catch;
        std::string next_catch;
        s_expr type_expr;
        // Check for having both this and next
        if (!s_patn({s_patn({s_patn(&this_catch), s_patn(&next_catch)})},
                    type_expr)
                 .match_with(tail)) {
          // There is no next catch. Match a single name, for example: (this)
          next_catch = "";
          s_patn({s_patn({s_patn(&this_catch)})}, type_expr)
              .must_match(tail, "catch marker is missing a name");
        }
        // Get the type name, for example: "LCatchType;"
        always_assert_log(this_catch != "", "catch marker is missing a name");
        std::string type_name;
        // nullptr is a valid catch type. It means catch all exceptions.
        DexType* catch_type = nullptr;
        if (s_patn({s_patn(&type_name)}).match_with(type_expr)) {
          catch_type = DexType::make_type(DexString::make_string(type_name));
        }
        MethodItemEntry* catch_marker = catches.at(this_catch);
        catch_marker->centry->catch_type = catch_type;
        if (next_catch != "") {
          catch_marker->centry->next = catches.at(next_catch);
        }
        code->push_back(*catch_marker);

      } else if (keyword[0] == ':') {
        const auto& label = keyword;
        always_assert_log(
            label_defs.count(label) == 0, "Duplicate label %s", label.c_str());

        // We insert a MFLOW_TARGET with an empty source mie that may be filled
        // in later if something points to it
        std::string case_key_str;
        BranchTarget* bt = nullptr;
        if (s_patn({s_patn(&case_key_str)}).match_with(tail)) {
          // A switch target like (:label 0)
          bt = new BranchTarget(nullptr, std::stoi(case_key_str));
        } else {
          // An if target like (:label)
          bt = new BranchTarget(nullptr);
        }
        auto maybe_target = new MethodItemEntry(bt);
        label_defs.emplace(label, maybe_target);
        code->push_back(*maybe_target);

      } else {
        auto insn = instruction_from_s_expr(keyword, tail, &label_refs);
        always_assert(insn != nullptr);
        max_reg = std::max(max_reg, largest_reg_operand(insn.get()));
        code->push_back(insn.release());
      }
    }
  }
  handle_labels(code.get(), label_defs, label_refs);

  // FIXME: I don't think this handles wides correctly
  code->set_registers_size(max_reg ? *max_reg + 1 : 0);

  return code;
}

std::unique_ptr<IRCode> ircode_from_string(const std::string& s) {
  std::istringstream input(s);
  s_expr_istream s_expr_input(input);
  s_expr expr;
  while (s_expr_input.good()) {
    s_expr_input >> expr;
    if (s_expr_input.eoi()) {
      break;
    }
    always_assert_log(
        !s_expr_input.fail(), "%s\n", s_expr_input.what().c_str());
  }
  return ircode_from_s_expr(expr);
}

#define AF(uc, lc, val) {ACC_##uc, #lc},
std::unordered_map<DexAccessFlags, std::string, boost::hash<DexAccessFlags>>
    access_to_string_table = {ACCESSFLAGS};
#undef AF

#define AF(uc, lc, val) {#lc, ACC_##uc},
std::unordered_map<std::string, DexAccessFlags> string_to_access_table = {
    ACCESSFLAGS};
#undef AF

DexMethod* method_from_s_expr(const s_expr& e) {
  s_expr tail;
  s_patn({s_patn("method")}, tail)
      .must_match(e, "method definitions must start with 'method'");

  s_expr access_tokens;
  std::string method_name;
  s_patn({s_patn(access_tokens), s_patn(&method_name)}, tail)
      .must_match(tail, "Expecting access list and method name");

  auto method = static_cast<DexMethod*>(DexMethod::make_method(method_name));
  DexAccessFlags access_flags = static_cast<DexAccessFlags>(0);
  for (size_t i = 0; i < access_tokens.size(); ++i) {
    access_flags |= string_to_access_table.at(access_tokens[i].str());
  }

  s_expr code_expr;
  s_patn({s_patn(code_expr)}, tail).match_with(tail);
  always_assert_log(code_expr.is_list(), "Expecting code listing");
  bool is_virtual = !is_static(access_flags) && !is_private(access_flags);
  method->make_concrete(
      access_flags, ircode_from_s_expr(code_expr), is_virtual);

  return method;
}

DexMethod* method_from_string(const std::string& s) {
  std::istringstream input(s);
  s_expr_istream s_expr_input(input);
  s_expr expr;
  while (s_expr_input.good()) {
    s_expr_input >> expr;
    if (s_expr_input.eoi()) {
      break;
    }
    always_assert_log(
        !s_expr_input.fail(), "%s\n", s_expr_input.what().c_str());
  }
  return method_from_s_expr(expr);
}

} // namespace assembler

max_stars_repo_name: UiNiNex/redex

max_issues_repo_name: UiNiNex/redex

max_forks_repo_name: UiNiNex/redex


text:
#pragma once
#include <boost/iostreams/concepts.hpp>  // sink
#include <boost/iostreams/stream_buffer.hpp>
#include "buffer.hpp"

namespace lugce{
	class buffer_sink : public boost::iostreams::sink
	{
	public:
		buffer_sink( lugce::buffer& buf ) : _buf(buf){}
		std::streamsize write(const char* s, std::streamsize n)
		{
			_buf.append( s, (size_t)n );
			return n;
		}
	private:
		lugce::buffer &_buf;
	};
};

max_stars_repo_name: jadedrip/lugce

max_issues_repo_name: jadedrip/lugce

max_forks_repo_name: jadedrip/lugce


text:
//"Copyright [year] <Copyright Owner>"
//
// Created by mrbgn on 5/5/21.
//

#include <rocksdb/db.h>
#include <rocksdb/options.h>
#include <rocksdb/slice.h>

#include <boost/log/common.hpp>
#include <boost/log/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/keyword.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sources/logger.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <ctime>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

#include "PicoSHA.hpp"
#include "ThreadPool.hpp"

#ifndef INCLUDE_DBCS_HPP_
#define INCLUDE_DBCS_HPP_

/**
 * @brief Struct to forward key-value pairs to consumer
 * @param key Key from key-value pair
 * @param value value from key-value pair
 */

struct CycledList {
  uint32_t length;
  uint32_t position;
  explicit CycledList(uint32_t len) : length(len) { position = 0; }
  uint32_t NextIndex() {
    position = (position + 1) % length;
    return position;
  }
};

/**
 * @brief Class to operate with existed ( created by time ) rocksdb DataBase
 * @class Dbcs
 *
 * @param log_level Log level to Boost_log; if log_level is unexpected it's set
 * to fatal
 * @param thread_count Quantity of threads to operate with db that is equal to
 * quantity of families in output db
 * @param output Link to output db
 * @param input Link to input db
 *
 */
class Dbcs {
 public:
  Dbcs(std::string &log_level, uint32_t &thread_count, std::string &output,
       std::string &input);

  /**
   * @brief void to read all families
   */
  void ReadDatabaseFamilies();
  /**
   * @brief void to read from exact family
   * @param iterator to First pair in exact family
   */
  void ReadFromFamily(rocksdb::Iterator *iterator);
  /**
   * @brief void to create new db with thread_count quanity of families
   */
  void CreateOutputDb();
  /**
   * @brief main void to read all data from input db
   */
  void ReadData();
  /**
   * @brief void to hash pairs and add it to output db
   * @param key key string
   * @param value value string
   * @param handle_number number of family to put pair in
   */
  void HashPair(std::string key, std::string value, uint32_t handle_number);
  /**
   * @brief void to enable logging via Bosst::Log
   */
  void EnableLogging();
  /**
   * @brief void to log messages
   * @param message string to log via Boost::Log
   */
  void Log(std::string message);

 private:
  std::string _logLevel;
  uint32_t _threadWriteCount;
  std::string _inputPath;
  std::string _outputPath;
  ThreadPool _poolWrite;
  std::vector<std::string> _families;
};

#endif  // INCLUDE_DBCS_HPP_


text:
#include <gtest/gtest.h>
#include "../include/model.h"
#include "../include/KalmanFilter.h"
#include "../include/filterModel.h"
#include "../include/mathWrapper/double.h"
#include "../include/mathWrapper/eigen.h"
#include "../include/mathWrapper/boost.h"
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <math.h>
#include "../include/Eigen.h"
#include <iostream>

TEST(discreteDiscreteKalmanFilter, test){

	int stateCount = 1;
	int sensorCount = 1;
	int initialTime = 0;
	vectorDouble initialEstimate(1);
	matrixDouble initialCovariance(1);

	Eigen::VectorXd x(1);x<<1;
	vectorEigen initialEstimateEigen(x);
	Eigen::MatrixXd y(1,1);y<<1;
	matrixEigen initialCovarianceEigen(y);

	boost::numeric::ublas::matrix<double> initialCovarianceBoost(1,1);
	initialCovarianceBoost(0,0)=1;
	boost::numeric::ublas::vector<double> initialEstimateBoost(1);
	initialEstimateBoost(0) = 1;

	Eigen::VectorXd initialEstimateEigenSimple(1);initialEstimateEigenSimple<<1;
	Eigen::MatrixXd initialCovarianceEigenSimple(1,1);initialCovarianceEigenSimple<<1;

	class stateModel: public discreteModel<vectorDouble>{
		public:
			vectorDouble function(const vectorDouble & val, const int time) const override{
				vectorDouble result(val.getSystemValue() + 0.1);
				return result;
			}
	};
	class stateModelEigen: public discreteModel<vectorEigen>{
		Eigen::VectorXd velocity;
		public:
			stateModelEigen(){
				Eigen::VectorXd vel(1);vel<<0.1;
				velocity = vel;
			}
			vectorEigen function(const vectorEigen & val, const int time) const override{
				vectorEigen result(val.getSystemValue() + velocity);
				return result;
			}
	};
	class stateModelBoost: public discreteModel<vectorBoost>{
		boost::numeric::ublas::vector<double> velocity;
		public:
			stateModelBoost(){
				boost::numeric::ublas::vector<double> vel(1);vel(0) = 0.1;
				velocity = vel;
			}
			vectorBoost function(const vectorBoost & val, const int time) const override{
				vectorBoost result(val.getSystemValue() + velocity);
				return result;
			}
	};
	class stateModelEigenSimple: public discreteModel<Eigen::VectorXd>{
		Eigen::VectorXd velocity;
		public:
			stateModelEigenSimple(){
				Eigen::VectorXd vel(1);vel<< 0.1;
				velocity = vel;
			}
			Eigen::VectorXd function(const Eigen::VectorXd & val, const int time) const override{
				return val + velocity;
			}
	};

	class measurementModel: public discreteModel<vectorDouble>{
		public:
			vectorDouble function(const vectorDouble & val, const int time) const override{
				vectorDouble result(val.getSystemValue());
				return result;
			}
	};
	class measurementModelEigen: public discreteModel<vectorEigen>{
		public:
			vectorEigen function(const vectorEigen & val, const int time) const override{
				vectorEigen result(val.getSystemValue());
				return result;
			}
	};
	class measurementModelBoost: public discreteModel<vectorBoost>{
		public:
			vectorBoost function(const vectorBoost & val, const int time) const override{
				vectorBoost result(val.getSystemValue());
				return result;
			}
	};
	class measurementModelEigenSimple: public discreteModel<Eigen::VectorXd>{
		public:
			Eigen::VectorXd function(const Eigen::VectorXd & val, const int time) const override{
				return val;
			}
	};

	class transitionJac: public jacobianDiscrete<vectorDouble,matrixDouble>{
		public:
			matrixDouble function(const vectorDouble & val, int t){
				return matrixDouble(1);
			}
	};
	class measurementJac: public jacobianDiscrete<vectorDouble,matrixDouble>{
		public:
			matrixDouble function(const vectorDouble & val, int t){
				return matrixDouble(1);
			}
	};
	class transitionJacEigen: public jacobianDiscrete<vectorEigen,matrixEigen>{
		Eigen::MatrixXd v;
		public:
			transitionJacEigen(){
				Eigen::MatrixXd tmp(1,1);tmp<<1;
				v = tmp;
			}

			matrixEigen function(const vectorEigen & val, int t){
				return matrixEigen(v);
			}
	};
	class measurementJacEigen: public jacobianDiscrete<vectorEigen,matrixEigen>{
		Eigen::MatrixXd v;
		public:
			measurementJacEigen(){
				Eigen::MatrixXd tmp(1,1);tmp<<1;
				v = tmp;
			}

			matrixEigen function(const vectorEigen & val, int t){
				return matrixEigen(v);
			}
	};
	class transitionJacBoost: public jacobianDiscrete<vectorBoost,matrixBoost>{
		boost::numeric::ublas::matrix<double> v;
		public:
			transitionJacBoost(){
				boost::numeric::ublas::matrix<double> tmp(1,1);tmp(0,0) = 1;
				v = tmp;

			}

			matrixBoost function(const vectorBoost & val, int t){
				return matrixBoost(v);
			}
	};
	class measurementJacBoost: public jacobianDiscrete<vectorBoost,matrixBoost>{
		boost::numeric::ublas::matrix<double> v;
		public:
			measurementJacBoost(){
				boost::numeric::ublas::matrix<double> tmp(1,1);tmp(0,0) = 1;
				v = tmp;
			}

			matrixBoost function(const vectorBoost & val, int t){
				return matrixBoost(v);
			}
	};
	class transitionJacEigenSimple: public jacobianDiscrete<Eigen::VectorXd,Eigen::MatrixXd>{
		Eigen::MatrixXd v;
		public:
			transitionJacEigenSimple(){
				Eigen::MatrixXd tmp(1,1);tmp << 1;
				v = tmp;

			}

			Eigen::MatrixXd function(const Eigen::VectorXd & val, int t){
				return v;
			}
	};
	class measurementJacEigenSimple: public jacobianDiscrete<Eigen::VectorXd,Eigen::MatrixXd>{
		Eigen::MatrixXd v;
		public:
			measurementJacEigenSimple(){
				Eigen::MatrixXd tmp(1,1);tmp<< 1;
				v = tmp;
			}

			Eigen::MatrixXd function(const Eigen::VectorXd & val, int t){
				return v;
			}
	};

	class processNoise: public discreteNoiseCovariance<vectorDouble,matrixDouble>{
		matrixDouble function(const vectorDouble &est,int t) override{
			return matrixDouble(0.01);
		}
		matrixDouble sqrt(const vectorDouble &est, int t) override{
			return matrixDouble(0.1);
		}
	};
	class sensorNoise: public discreteNoiseCovariance<vectorDouble,matrixDouble>{
		matrixDouble function(const vectorDouble &est,int t) override{
			return matrixDouble(0.01);
		}
		matrixDouble sqrt(const vectorDouble &est, int t) override{
			return matrixDouble(0.1);
		}
	};
	class processNoiseEigen: public discreteNoiseCovariance<vectorEigen,matrixEigen>{
		Eigen::MatrixXd v;
		Eigen::MatrixXd v2;
		public:
		processNoiseEigen(){
			Eigen::MatrixXd tmp(1,1);tmp<<0.01;
			Eigen::MatrixXd tmp2(1,1);tmp2<<0.1;
			v = tmp;
			v2 = tmp2;
		}
		matrixEigen function(const vectorEigen &est,int t) override{
			return matrixEigen(v);
		}
		matrixEigen sqrt(const vectorEigen &est, int t) override{
			return matrixEigen(v2);
		}
	};
	class sensorNoiseEigen: public discreteNoiseCovariance<vectorEigen,matrixEigen>{
		Eigen::MatrixXd v;
		Eigen::MatrixXd v2;
		public:
		sensorNoiseEigen(){
			Eigen::MatrixXd tmp(1,1);tmp<<0.01;
			Eigen::MatrixXd tmp2(1,1);tmp2<<0.1;
			v = tmp;
			v2 = tmp2;
		}
		matrixEigen function(const vectorEigen &est, int t) override{
			return matrixEigen(v);
		}
		matrixEigen sqrt(const vectorEigen &est, int t) override{
			return matrixEigen(v2);
		}
	};
	class processNoiseBoost: public discreteNoiseCovariance<vectorBoost,matrixBoost>{
		boost::numeric::ublas::matrix<double> v;
		boost::numeric::ublas::matrix<double> v2;
		public:
		processNoiseBoost(){
			boost::numeric::ublas::matrix<double> tmp(1,1);tmp(0,0) = 0.01;
			boost::numeric::ublas::matrix<double> tmp2(1,1);tmp2(0,0) = 0.01;
			v = tmp;
			v2 = tmp2;
		}
		matrixBoost function(const vectorBoost &est,int t) override{
			return matrixBoost(v);
		}
		matrixBoost sqrt(const vectorBoost &est, int t) override{
			return matrixBoost(v2);
		}
	};
	class sensorNoiseBoost: public discreteNoiseCovariance<vectorBoost,matrixBoost>{
		boost::numeric::ublas::matrix<double> v;
		boost::numeric::ublas::matrix<double> v2;
		public:
		sensorNoiseBoost(){
			boost::numeric::ublas::matrix<double> tmp(1,1);tmp(0,0) = 0.01;
			boost::numeric::ublas::matrix<double> tmp2(1,1);tmp2(0,0) = 0.01;
			v = tmp;
			v2 = tmp2;
		}
		matrixBoost function(const vectorBoost &est,int t) override{
			return matrixBoost(v);
		}
		matrixBoost sqrt(const vectorBoost &est, int t) override{
			return matrixBoost(v2);
		}
	};
	class processNoiseEigenSimple: public discreteNoiseCovariance<Eigen::VectorXd,Eigen::MatrixXd>{
		Eigen::MatrixXd v;
		Eigen::MatrixXd v2;
		public:
		processNoiseEigenSimple(){
			Eigen::MatrixXd tmp(1,1);tmp<< 0.01;
			Eigen::MatrixXd tmp2(1,1);tmp2<<0.1;
			v = tmp;
			v2 = tmp2;
		}
		Eigen::MatrixXd function(const Eigen::VectorXd &est,int t) override{
			return v;
		}
		Eigen::MatrixXd sqrt(const Eigen::VectorXd &est, int t) override{
			return v2;
		}
	};
	class sensorNoiseEigenSimple: public discreteNoiseCovariance<Eigen::VectorXd,Eigen::MatrixXd>{
		Eigen::MatrixXd v;
		Eigen::MatrixXd v2;
		public:
		sensorNoiseEigenSimple(){
			Eigen::MatrixXd tmp(1,1);tmp<< 0.01;
			Eigen::MatrixXd tmp2(1,1);tmp2<<0.1;
			v = tmp;
			v2 = tmp2;
		}
		Eigen::MatrixXd function(const Eigen::VectorXd &est,int t) override{
			return v;
		}
		Eigen::MatrixXd sqrt(const Eigen::VectorXd &est, int t) override{
			return v2;
		}
	};

	stateModel tm;
	measurementModel mm;
	processNoise pn;
	sensorNoise sn;
	transitionJac tj;
	measurementJac mj;
	discreteDiscreteFilterModel<vectorDouble,matrixDouble> ddfm(&tm,&mm,&pn,&sn,&tj,&mj,stateCount,sensorCount);

	stateModelEigen tmEigen;
	measurementModelEigen mmEigen;
	processNoiseEigen pnEigen;
	sensorNoiseEigen snEigen;
	transitionJacEigen tjEigen;
	measurementJacEigen mjEigen;
	discreteDiscreteFilterModel<vectorEigen,matrixEigen> ddfmEigen(&tmEigen,&mmEigen,&pnEigen,&snEigen,&tjEigen,&mjEigen,
		stateCount,sensorCount);

	stateModelBoost tmBoost;
	measurementModelBoost mmBoost;
	processNoiseBoost pnBoost;
	sensorNoiseBoost snBoost;
	transitionJacBoost tjBoost;
	measurementJacBoost mjBoost;
	discreteDiscreteFilterModel<vectorBoost,matrixBoost> ddfmBoost(&tmBoost,&mmBoost,&pnBoost,&snBoost,&tjBoost,&mjBoost,
		stateCount,sensorCount);

	stateModelEigenSimple tmEigenSimple;
	measurementModelEigenSimple mmEigenSimple;
	processNoiseEigenSimple pnEigenSimple;
	sensorNoiseEigenSimple snEigenSimple;
	transitionJacEigenSimple tjEigenSimple;
	measurementJacEigenSimple mjEigenSimple;
	discreteDiscreteFilterModel<Eigen::VectorXd,Eigen::MatrixXd> ddfmEigenSimple(&tmEigenSimple,&mmEigenSimple,
		&pnEigenSimple,&snEigenSimple,&tjEigenSimple,&mjEigenSimple,stateCount,sensorCount);

	discreteDiscreteKalmanFilter<vectorDouble,matrixDouble>
		filter(initialTime, initialEstimate, initialCovariance, &ddfm);

	discreteDiscreteKalmanFilter<vectorEigen,matrixEigen>
		filterEigen(initialTime, initialEstimateEigen, initialCovarianceEigen, &ddfmEigen);

	discreteDiscreteKalmanFilter<vectorBoost,matrixBoost>
		filterBoost(initialTime, initialEstimateBoost, initialCovarianceBoost, &ddfmBoost);

	discreteDiscreteKalmanFilter<Eigen::VectorXd,Eigen::MatrixXd>
		filterEigenSimple( initialTime, initialEstimateEigenSimple, initialCovarianceEigenSimple,
			&ddfmEigenSimple);

	for(int i = 0; i < 10; i++){
		ASSERT_NEAR(filter.getCurrentEstimate().getSystemValue(),filterEigen.getCurrentEstimate().getSystemValue()[0],1e-9);
		ASSERT_NEAR(filter.getCurrentCovariance().getSystemValue(),
			filterEigen.getCurrentCovariance().getSystemValue().coeff(0,0),1e-9);
		ASSERT_NEAR(filter.getCurrentTime(),filterEigen.getCurrentTime(),1e-9);

		ASSERT_NEAR(filter.getCurrentEstimate().getSystemValue(),filterBoost.getCurrentEstimate().getSystemValue()[0],1e-9);
		boost::numeric::ublas::matrix<double> tmp = filterBoost.getCurrentCovariance().getSystemValue();
		ASSERT_NEAR(filter.getCurrentCovariance().getSystemValue(),tmp(0,0),1e-9);
		ASSERT_NEAR(filter.getCurrentTime(),filterBoost.getCurrentTime(),1e-9);

		filter.predict(1);
		filterEigen.predict(1);
		filterBoost.predict(1);
		filterEigenSimple.predict(1);
	}

	for(int i = 0; i < 10; i++){
		vectorDouble measurement(i);
		Eigen::VectorXd tmp(1);tmp<<i;
		vectorEigen tmp2(tmp);
		boost::numeric::ublas::vector<double> tmpBoost(1);tmpBoost(0)=i;
		vectorBoost tmp2Boost(tmpBoost);

		double sk = 1*filter.getCurrentCovariance().getSystemValue()*1 + 0.01;
		double kk = filter.getCurrentCovariance().getSystemValue()*(1.0/sk);
		double curEst = filter.getCurrentEstimate().getSystemValue();

		filter.update(measurement);
		filterEigen.update(tmp2);
		filterBoost.update(tmp2Boost);
		filterEigenSimple.update(tmp);

		ASSERT_NEAR(filter.getCurrentEstimate().getSystemValue(),filterEigen.getCurrentEstimate().getSystemValue()[0],1e-9);
		ASSERT_NEAR(filter.getCurrentEstimate().getSystemValue(),filterEigenSimple.getCurrentEstimate().coeff(0,0),1e-9);
		ASSERT_NEAR(filter.getCurrentCovariance().getSystemValue(),
			filterEigen.getCurrentCovariance().getSystemValue().coeff(0,0),1e-9);
		boost::numeric::ublas::matrix<double> t = filterBoost.getCurrentCovariance().getSystemValue();
		ASSERT_NEAR(filter.getCurrentCovariance().getSystemValue(),t(0,0),1e-9);
		ASSERT_NEAR(filter.getCurrentEstimate().getSystemValue(),filterBoost.getCurrentEstimate().getSystemValue()[0],1e-9);
	}
}

int main(int argc, char **argv){
	testing::InitGoogleTest(&argc, argv);
	return RUN_ALL_TESTS();
}

max_stars_repo_name: mannyray/KalmanFilter

max_issues_repo_name: mannyray/KalmanFilter

max_forks_repo_name: mannyray/KalmanFilter


text:
#ifndef TSA_VU8_CONTEXT_HPP
#define TSA_VU8_CONTEXT_HPP

#include <vu8/config.hpp>
#include <vu8/Module.hpp>

#include <v8.h>

#include <string>

#include <boost/unordered_map.hpp>
#include <boost/tuple/tuple.hpp>

namespace vu8 {

v8::Handle<v8::Value> LoadModule(const v8::Arguments& args);

struct ContextScope;

struct Context {
    friend struct ContextScope;

    typedef v8::Handle<v8::Value> (*ModuleLoadCallback)();

    bool IsEmpty() const { return context_.IsEmpty(); }

    // Returns false on failure, use v8::TryCatch around it to find out why.
    bool RunFile(char const *filename);

    // Same as RunFile but for use inside a pre-existing handle scope.
    bool RunFileInScope(char const *filename);

    void Set(char const *name, Module& module) {
        context_->Global()->Set(v8::String::New(name), module.NewInstance());
    }

    v8::Handle<v8::Value> operator[](char const *key) {
        return context_->Global()->Get(v8::String::New(key));
    }

    void Init();

    // Release all tracked data without freeing it, use if running dlclose on
    // library that contains v8 object to avoid core dump.
    void Release();

  private:
    typedef boost::unordered_map<
        std::string,
        boost::tuple<void *, v8::Persistent<v8::Value> > > modules_t;

    v8::Persistent<v8::Context>    context_;

    modules_t    modules_;
    std::string  libPath_;

    friend v8::Handle<v8::Value> LoadModule(const v8::Arguments& args);

  public:
    Context(std::string const& libPath = VU8_PLUGIN_LIB_PATH);
    ~Context();
};

struct ContextScope {
    ContextScope(Context& context) : context_(context) {
        context_.context_->Enter();
    }
    ~ContextScope() { context_.context_->Exit(); }
  private:
    Context& context_;
};

struct ContextScopeThreadLock : v8::Locker, ContextScope {
    ContextScopeThreadLock(Context& context) : ContextScope(context) {}
  private:
    v8::HandleScope scope;
};

}
#endif