Exemple #1
0
// The previous version of the lookupLedger command would accept the
// "ledger_index" argument as a string and silently treat it as a request to
// return the current ledger which, while not strictly wrong, could cause a lot
// of confusion.
//
// The code now robustly validates the input and ensures that the only possible
// values for the "ledger_index" parameter are the index of a ledger passed as
// an integer or one of the strings "current", "closed" or "validated".
// Additionally, the code ensures that the value passed in "ledger_hash" is a
// string and a valid hash. Invalid values will return an appropriate error
// code.
//
// In the absence of the "ledger_hash" or "ledger_index" parameters, the code
// assumes that "ledger_index" has the value "current".
//
// Returns a Json::objectValue.  If there was an error, it will be in that
// return value.  Otherwise, the object contains the field "validated" and
// optionally the fields "ledger_hash", "ledger_index" and
// "ledger_current_index", if they are defined.
Status lookupLedger (
    Json::Value const& params,
    Ledger::pointer& ledger,
    NetworkOPs& netOps,
    Json::Value& jsonResult)
{
    if (auto status = ledgerFromRequest (params, ledger, netOps))
        return status;

    if (ledger->isClosed ())
    {
        jsonResult[jss::ledger_hash] = to_string (ledger->getHash());
        jsonResult[jss::ledger_index] = ledger->getLedgerSeq();
    }
    else
    {
        jsonResult[jss::ledger_current_index] = ledger->getLedgerSeq();
    }
    jsonResult[jss::validated] = isValidated (*ledger);
    return Status::OK;
}
// The previous version of the lookupLedger command would accept the
// "ledger_index" argument as a string and silently treat it as a request to
// return the current ledger which, while not strictly wrong, could cause a lot
// of confusion.
//
// The code now robustly validates the input and ensures that the only possible
// values for the "ledger_index" parameter are the index of a ledger passed as
// an integer or one of the strings "current", "closed" or "validated".
// Additionally, the code ensures that the value passed in "ledger_hash" is a
// string and a valid hash. Invalid values will return an appropriate error
// code.
//
// In the absence of the "ledger_hash" or "ledger_index" parameters, the code
// assumes that "ledger_index" has the value "current".
//
// Returns a Json::objectValue.  If there was an error, it will be in that
// return value.  Otherwise, the object contains the field "validated" and
// optionally the fields "ledger_hash", "ledger_index" and
// "ledger_current_index", if they are defined.
Status lookupLedger (
    std::shared_ptr<ReadView const>& ledger, Context& context,
    Json::Value& result)
{
    if (auto status = ledgerFromRequest (ledger, context))
        return status;

    auto& info = ledger->info();

    if (!info.open)
    {
        result[jss::ledger_hash] = to_string (info.hash);
        result[jss::ledger_index] = info.seq;
    }
    else
    {
        result[jss::ledger_current_index] = info.seq;
    }

    result[jss::validated] = isValidated (context.ledgerMaster, *ledger, context.app);
    return Status::OK;
}
Exemple #3
0
        // init capture is C++14 feature
        // move capture in C++14, which doesn't contain in C++11
        void testInitCapture()
        {
            auto upw = std::make_unique<Widget>();
            auto func = [&] {return upw->isValidated(); };
            func();

            // using init capture makes it possible to specify:
            // 1. the name of a data member in the closure class generated from the lambda
            // 2. an expression to initialize that data member
            // To the left of the "=" is the name of the data member in the closure class we're specifying
            // To the right of the "=" is the initializing expression.
            // The scope on the left of the "=" is different from the scope on the right

            // The scope on the left is that of the closure class.
            // The scope on the right is the same as where the lambda is being defined.
            auto func1 = [upw = std::move(upw)]
            {
                return upw->isValidated();
            };

            // in c++11, it's not possible to capture the result of an expression.
            // another name for init capture is generalized lambda capture.
            auto func2 = [upw = std::make_unique<Widget>()]
            {
                upw->isValidated();
            };

            // this is the same with func2.
            // std::bind produces function objects like lambda expression.
            //    let's call that function object to be bind objects
            // the first argument to std::bind is a callable object,
            //        Subsequent arguments represent values to be passed to that object
            // A bind object contains copies of all the arguments passed to std::bind
            // For each lvalue argument, the corresponding object in the bind object is copy constructed
            // for each rvalue, it's move constructed.
            // In this example, the second argument is an rvalue.
            // so std::make_unique<Widget> is move constructed into the bind object.
            // This move construction is the crux of move capture emulation.
            // when a bind object is called, the arguments it stores are passed to the callable object originally passed to std::bind.
            // In this example, that means when func3 is called, the move-constructed copy of std::make_unique<Widget>() is passed
            //        as an argument to the lambda that was passed to std::bind.
            // This parameter in the lambda is a lvaue reference to the copy in the bind object.
            //    (It's not a rvalue reference, because although the expression used to initialize the copy in the bind object is a rvalue,
            //        the copy in the bind object itself is a lvalue)
            // Use of unique_ptr inside the lambda will thus operate on the move-constructed copy of the unique_ptr inside the bind object.
            auto func3 = std::bind(
                [](const std::unique_ptr<Widget>& p)
                    {return p->isValidated(); },
                std::make_unique<Widget>());
            func3();

            // by default, the operator() member function inside the closure class generated from a lambda is const
            // That has the effect of rendering all data members in the closure const within the body of the lambda.
            // the move-constructed copy of unique_ptr inside the bind object is not const. 
            // So to prevent that copy of unique_ptr from being modified inside the lambda, the lambda's parameter is declared reference-to-const
            // If the lambda were declared mutalbe, operator() in its closure class would not be declared const.
            // And it would be appropriate to omit const in the lambda's parameter declaration:
            auto func4 = std::bind(
                [](std::unique_ptr<Widget>& p) mutable
                    {return p->isValidated(); },
                std::make_unique<Widget>());
            func4();
        }