blob: c5954fd9d739ba65d64b6f1bc2d4d16e4094d502 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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.
*/
// MemoryImageReader, class for reading a memory image.
#ifndef LIBTEXTCLASSIFIER_COMMON_MEMORY_IMAGE_MEMORY_IMAGE_READER_H_
#define LIBTEXTCLASSIFIER_COMMON_MEMORY_IMAGE_MEMORY_IMAGE_READER_H_
#include <string>
#include <vector>
#include "common/memory_image/memory-image.pb.h"
#include "util/base/integral_types.h"
#include "util/base/logging.h"
#include "util/base/macros.h"
#include "util/strings/stringpiece.h"
namespace libtextclassifier {
namespace nlp_core {
// General, non-templatized class, to reduce code duplication.
//
// Given a memory area (pointer to start + size in bytes) parses a memory image
// from there into (1) MemoryImageHeader proto (it includes the serialized form
// of the trimmed down original proto) and (2) a list of void* pointers to the
// beginning of all data blobs.
//
// In case of parsing errors, we prefer to log the error and set the
// success_status() to false, instead of CHECK-failing . This way, the client
// has the option of performing error recovery or crashing. Some mobile apps
// don't like crashing (a restart is very slow) so, if possible, we try to avoid
// that.
class GeneralMemoryImageReader {
public:
// Constructs this object. See class-level comments. Note: the memory area
// pointed to by start should not be deallocated while this object is used:
// this object does not copy it; instead, it keeps pointers inside that memory
// area.
GeneralMemoryImageReader(const void *start, uint64 num_bytes)
: start_(start), num_bytes_(num_bytes) {
success_ = ReadMemoryImage();
}
virtual ~GeneralMemoryImageReader() {}
// Returns true if reading the memory image has been successful. If this
// returns false, then none of the other accessors should be used.
bool success_status() const { return success_; }
// Returns number of data blobs from the memory image.
int num_data_blobs() const {
return data_blob_views_.size();
}
// Returns pointer to the beginning of the data blob #i.
StringPiece data_blob_view(int i) const {
if ((i < 0) || (i >= num_data_blobs())) {
TC_LOG(ERROR) << "Blob index " << i << " outside range [0, "
<< num_data_blobs() << "); will return empty data chunk";
return StringPiece();
}
return data_blob_views_[i];
}
// Returns std::string with binary serialization of the original proto, but
// trimmed of the large fields (those were placed in the data blobs).
std::string trimmed_proto_str() const {
return trimmed_proto_serialization_.ToString();
}
// Same as above but returns the trimmed proto as a string piece pointing to
// the image.
StringPiece trimmed_proto_view() const {
return trimmed_proto_serialization_;
}
const MemoryImageHeader &header() { return header_; }
protected:
void set_as_failed() {
success_ = false;
}
private:
bool ReadMemoryImage();
// Pointer to beginning of memory image. Not owned.
const void *const start_;
// Number of bytes in the memory image. This class will not read more bytes.
const uint64 num_bytes_;
// MemoryImageHeader parsed from the memory image.
MemoryImageHeader header_;
// Binary serialization of the trimmed version of the original proto.
// Represented as a StringPiece backed up by the underlying memory image
// bytes.
StringPiece trimmed_proto_serialization_;
// List of StringPiece objects for all data blobs from the memory image (in
// order).
std::vector<StringPiece> data_blob_views_;
// Memory reading success status.
bool success_;
TC_DISALLOW_COPY_AND_ASSIGN(GeneralMemoryImageReader);
};
// Like GeneralMemoryImageReader, but has knowledge about the type of the
// original proto. As such, it can parse it (well, the trimmed version) and
// offer access to it.
//
// Template parameter T should be the type of the original proto.
template<class T>
class MemoryImageReader : public GeneralMemoryImageReader {
public:
MemoryImageReader(const void *start, uint64 num_bytes)
: GeneralMemoryImageReader(start, num_bytes) {
if (!trimmed_proto_.ParseFromString(trimmed_proto_str())) {
TC_LOG(INFO) << "Unable to parse the trimmed proto";
set_as_failed();
}
}
// Returns const reference to the trimmed version of the original proto.
// Useful for retrieving the many small fields that are not converted into
// data blobs.
const T &trimmed_proto() const { return trimmed_proto_; }
private:
T trimmed_proto_;
TC_DISALLOW_COPY_AND_ASSIGN(MemoryImageReader);
};
} // namespace nlp_core
} // namespace libtextclassifier
#endif // LIBTEXTCLASSIFIER_COMMON_MEMORY_IMAGE_MEMORY_IMAGE_READER_H_