bool Command::ParseTargetInfoAndSourceInfo(const std::vector<std::string>& tokens, const std::string& tgt_hash, TargetInfo* target, const std::string& src_hash, SourceInfo* source,
std::string* err) { // We expect the given args (in 'tokens' vector) in one of the following formats. // // <tgt_ranges> <src_block_count> - <[stash_id:location] ...> // (loads data from stashes only) // // <tgt_ranges> <src_block_count> <src_ranges> // (loads data from source image only) // // <tgt_ranges> <src_block_count> <src_ranges> <src_ranges_location> <[stash_id:location] ...> // (loads data from both of source image and stashes)
// At least it needs to provide three args: <tgt_ranges>, <src_block_count> and "-"/<src_ranges>. if (tokens.size() < 3) {
*err = "invalid number of args"; returnfalse;
}
// <[stash_id:stash_location]>
std::vector<StashInfo> stashes; while (pos < tokens.size()) { // Each word is a an index into the stash table, a colon, and then a RangeSet describing where // in the source block that stashed data should go.
std::vector<std::string> pairs = android::base::Split(tokens[pos++], ":"); if (pairs.size() != 2) {
*err = "invalid stash info"; returnfalse;
}
RangeSet stash_location = RangeSet::Parse(pairs[1]); if (!stash_location) {
*err = "invalid stash location"; returnfalse;
}
stashes.emplace_back(pairs[0], stash_location);
}
// Moves blocks in the 'source' vector to the specified locations (as in 'locs') in the 'dest' // vector. Note that source and dest may be the same buffer. staticvoid MoveRange(std::vector<uint8_t>* dest, const RangeSet& locs, const std::vector<uint8_t>& source, size_t block_size) { const uint8_t* from = source.data();
uint8_t* to = dest->data();
size_t start = locs.blocks(); // Must do the movement backward. for (auto it = locs.crbegin(); it != locs.crend(); it++) {
size_t blocks = it->second - it->first;
start -= blocks;
memmove(to + (it->first * block_size), from + (start * block_size), blocks * block_size);
}
}
std::vector<std::string> lines = android::base::Split(transfer_list_str, "\n"); if (lines.size() < kTransferListHeaderLines) {
*err = android::base::StringPrintf("too few lines in the transfer list [%zu]", lines.size()); return TransferList{};
}
// First line in transfer list is the version number. if (!android::base::ParseInt(lines[0], &result.version_, 3, 4)) {
*err = "unexpected transfer list version ["s + lines[0] + "]"; return TransferList{};
}
// Second line in transfer list is the total number of blocks we expect to write. if (!android::base::ParseUint(lines[1], &result.total_blocks_)) {
*err = "unexpected block count ["s + lines[1] + "]"; return TransferList{};
}
// Third line is how many stash entries are needed simultaneously. if (!android::base::ParseUint(lines[2], &result.stash_max_entries_)) { return TransferList{};
}
// Fourth line is the maximum number of blocks that will be stashed simultaneously. if (!android::base::ParseUint(lines[3], &result.stash_max_blocks_)) {
*err = "unexpected maximum stash blocks ["s + lines[3] + "]"; return TransferList{};
}
// Subsequent lines are all individual transfer commands. for (size_t i = kTransferListHeaderLines; i < lines.size(); i++) { const std::string& line = lines[i]; if (line.empty()) continue;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.