1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // MemoryImageReader, class for reading a memory image. 18 19 #ifndef LIBTEXTCLASSIFIER_COMMON_MEMORY_IMAGE_MEMORY_IMAGE_READER_H_ 20 #define LIBTEXTCLASSIFIER_COMMON_MEMORY_IMAGE_MEMORY_IMAGE_READER_H_ 21 22 #include <string> 23 #include <vector> 24 25 #include "common/memory_image/memory-image-common.h" 26 #include "common/memory_image/memory-image.pb.h" 27 #include "util/base/integral_types.h" 28 #include "util/base/logging.h" 29 #include "util/base/macros.h" 30 31 namespace libtextclassifier { 32 namespace nlp_core { 33 34 // General, non-templatized class, to reduce code duplication. 35 // 36 // Given a memory area (pointer to start + size in bytes) parses a memory image 37 // from there into (1) MemoryImageHeader proto (it includes the serialized form 38 // of the trimmed down original proto) and (2) a list of void* pointers to the 39 // beginning of all data blobs. 40 // 41 // In case of parsing errors, we prefer to log the error and set the 42 // success_status() to false, instead of CHECK-failing . This way, the client 43 // has the option of performing error recovery or crashing. Some mobile apps 44 // don't like crashing (a restart is very slow) so, if possible, we try to avoid 45 // that. 46 class GeneralMemoryImageReader { 47 public: 48 // Constructs this object. See class-level comments. Note: the memory area 49 // pointed to by start should not be deallocated while this object is used: 50 // this object does not copy it; instead, it keeps pointers inside that memory 51 // area. GeneralMemoryImageReader(const void * start,uint64 num_bytes)52 GeneralMemoryImageReader(const void *start, uint64 num_bytes) 53 : start_(start), num_bytes_(num_bytes) { 54 success_ = ReadMemoryImage(); 55 } 56 ~GeneralMemoryImageReader()57 virtual ~GeneralMemoryImageReader() {} 58 59 // Returns true if reading the memory image has been successful. If this 60 // returns false, then none of the other accessors should be used. success_status()61 bool success_status() const { return success_; } 62 63 // Returns number of data blobs from the memory image. num_data_blobs()64 int num_data_blobs() const { 65 return data_blob_views_.size(); 66 } 67 68 // Returns pointer to the beginning of the data blob #i. data_blob_view(int i)69 DataBlobView data_blob_view(int i) const { 70 if ((i < 0) || (i >= num_data_blobs())) { 71 TC_LOG(ERROR) << "Blob index " << i << " outside range [0, " 72 << num_data_blobs() << "); will return empty data chunk"; 73 return DataBlobView(); 74 } 75 return data_blob_views_[i]; 76 } 77 78 // Returns std::string with binary serialization of the original proto, but 79 // trimmed of the large fields (those were placed in the data blobs). trimmed_proto_str()80 std::string trimmed_proto_str() const { 81 return trimmed_proto_serialization_.ToString(); 82 } 83 header()84 const MemoryImageHeader &header() { return header_; } 85 86 protected: set_as_failed()87 void set_as_failed() { 88 success_ = false; 89 } 90 91 private: 92 bool ReadMemoryImage(); 93 94 // Pointer to beginning of memory image. Not owned. 95 const void *const start_; 96 97 // Number of bytes in the memory image. This class will not read more bytes. 98 const uint64 num_bytes_; 99 100 // MemoryImageHeader parsed from the memory image. 101 MemoryImageHeader header_; 102 103 // Binary serialization of the trimmed version of the original proto. 104 // Represented as a DataBlobView backed up by the underlying memory image 105 // bytes. 106 DataBlobView trimmed_proto_serialization_; 107 108 // List of DataBlobView objects for all data blobs from the memory image (in 109 // order). 110 std::vector<DataBlobView> data_blob_views_; 111 112 // Memory reading success status. 113 bool success_; 114 115 TC_DISALLOW_COPY_AND_ASSIGN(GeneralMemoryImageReader); 116 }; 117 118 // Like GeneralMemoryImageReader, but has knowledge about the type of the 119 // original proto. As such, it can parse it (well, the trimmed version) and 120 // offer access to it. 121 // 122 // Template parameter T should be the type of the original proto. 123 template<class T> 124 class MemoryImageReader : public GeneralMemoryImageReader { 125 public: MemoryImageReader(const void * start,uint64 num_bytes)126 MemoryImageReader(const void *start, uint64 num_bytes) 127 : GeneralMemoryImageReader(start, num_bytes) { 128 if (!trimmed_proto_.ParseFromString(trimmed_proto_str())) { 129 TC_LOG(INFO) << "Unable to parse the trimmed proto"; 130 set_as_failed(); 131 } 132 } 133 134 // Returns const reference to the trimmed version of the original proto. 135 // Useful for retrieving the many small fields that are not converted into 136 // data blobs. trimmed_proto()137 const T &trimmed_proto() const { return trimmed_proto_; } 138 139 private: 140 T trimmed_proto_; 141 142 TC_DISALLOW_COPY_AND_ASSIGN(MemoryImageReader); 143 }; 144 145 } // namespace nlp_core 146 } // namespace libtextclassifier 147 148 #endif // LIBTEXTCLASSIFIER_COMMON_MEMORY_IMAGE_MEMORY_IMAGE_READER_H_ 149