// 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; }
// 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(); }