Patch internal change 111557819.
Defer calls to mutable_unknown_fields() until it is actually required to save memory for C++ lite runtime. Change-Id: Ica9c1fd276cdb164942d1e7b6e098c83ee3ffdc5
This commit is contained in:
parent
363316a8d7
commit
76195058e2
@ -1772,6 +1772,17 @@ GenerateShutdownCode(io::Printer* printer) {
|
|||||||
|
|
||||||
void MessageGenerator::
|
void MessageGenerator::
|
||||||
GenerateClassMethods(io::Printer* printer) {
|
GenerateClassMethods(io::Printer* printer) {
|
||||||
|
// mutable_unknown_fields wrapper function for LazyStringOutputStream
|
||||||
|
// callback.
|
||||||
|
if (!UseUnknownFieldSet(descriptor_->file())) {
|
||||||
|
printer->Print(
|
||||||
|
"static ::std::string* MutableUnknownFieldsFor$classname$(\n"
|
||||||
|
" $classname$* ptr) {\n"
|
||||||
|
" return ptr->mutable_unknown_fields();\n"
|
||||||
|
"}\n"
|
||||||
|
"\n",
|
||||||
|
"classname", classname_);
|
||||||
|
}
|
||||||
if (IsAnyMessage(descriptor_)) {
|
if (IsAnyMessage(descriptor_)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
|
"void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
|
||||||
@ -2814,7 +2825,9 @@ GenerateMergeFrom(io::Printer* printer) {
|
|||||||
"}\n");
|
"}\n");
|
||||||
} else {
|
} else {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"mutable_unknown_fields()->append(from.unknown_fields());\n");
|
"if (!from.unknown_fields().empty()) {\n"
|
||||||
|
" mutable_unknown_fields()->append(from.unknown_fields());\n"
|
||||||
|
"}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2889,11 +2902,16 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
|||||||
"classname", classname_);
|
"classname", classname_);
|
||||||
|
|
||||||
if (!UseUnknownFieldSet(descriptor_->file())) {
|
if (!UseUnknownFieldSet(descriptor_->file())) {
|
||||||
|
// Use LazyStringOutputString to avoid initializing unknown fields string
|
||||||
|
// unless it is actually needed. For the same reason, disable eager refresh
|
||||||
|
// on the CodedOutputStream.
|
||||||
printer->Print(
|
printer->Print(
|
||||||
" ::google::protobuf::io::StringOutputStream unknown_fields_string(\n"
|
" ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n"
|
||||||
" mutable_unknown_fields());\n"
|
" ::google::protobuf::internal::NewPermanentCallback(\n"
|
||||||
|
" &MutableUnknownFieldsFor$classname$, this));\n"
|
||||||
" ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
|
" ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n"
|
||||||
" &unknown_fields_string);\n");
|
" &unknown_fields_string, false);\n",
|
||||||
|
"classname", classname_);
|
||||||
}
|
}
|
||||||
|
|
||||||
printer->Print(
|
printer->Print(
|
||||||
|
@ -629,6 +629,24 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
|
|||||||
had_error_ = false;
|
had_error_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output,
|
||||||
|
bool do_eager_refresh)
|
||||||
|
: output_(output),
|
||||||
|
buffer_(NULL),
|
||||||
|
buffer_size_(0),
|
||||||
|
total_bytes_(0),
|
||||||
|
had_error_(false),
|
||||||
|
aliasing_enabled_(false) {
|
||||||
|
if (do_eager_refresh) {
|
||||||
|
// Eagerly Refresh() so buffer space is immediately available.
|
||||||
|
Refresh();
|
||||||
|
// The Refresh() may have failed. If the client doesn't write any data,
|
||||||
|
// though, don't consider this an error. If the client does write data, then
|
||||||
|
// another Refresh() will be attempted and it will set the error once again.
|
||||||
|
had_error_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CodedOutputStream::~CodedOutputStream() {
|
CodedOutputStream::~CodedOutputStream() {
|
||||||
Trim();
|
Trim();
|
||||||
}
|
}
|
||||||
|
@ -666,6 +666,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
|
|||||||
public:
|
public:
|
||||||
// Create an CodedOutputStream that writes to the given ZeroCopyOutputStream.
|
// Create an CodedOutputStream that writes to the given ZeroCopyOutputStream.
|
||||||
explicit CodedOutputStream(ZeroCopyOutputStream* output);
|
explicit CodedOutputStream(ZeroCopyOutputStream* output);
|
||||||
|
CodedOutputStream(ZeroCopyOutputStream* output, bool do_eager_refresh);
|
||||||
|
|
||||||
// Destroy the CodedOutputStream and position the underlying
|
// Destroy the CodedOutputStream and position the underlying
|
||||||
// ZeroCopyOutputStream immediately after the last byte written.
|
// ZeroCopyOutputStream immediately after the last byte written.
|
||||||
|
@ -157,6 +157,7 @@ StringOutputStream::~StringOutputStream() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool StringOutputStream::Next(void** data, int* size) {
|
bool StringOutputStream::Next(void** data, int* size) {
|
||||||
|
GOOGLE_CHECK_NE(NULL, target_);
|
||||||
int old_size = target_->size();
|
int old_size = target_->size();
|
||||||
|
|
||||||
// Grow the string.
|
// Grow the string.
|
||||||
@ -188,14 +189,44 @@ bool StringOutputStream::Next(void** data, int* size) {
|
|||||||
|
|
||||||
void StringOutputStream::BackUp(int count) {
|
void StringOutputStream::BackUp(int count) {
|
||||||
GOOGLE_CHECK_GE(count, 0);
|
GOOGLE_CHECK_GE(count, 0);
|
||||||
|
GOOGLE_CHECK_NE(NULL, target_);
|
||||||
GOOGLE_CHECK_LE(count, target_->size());
|
GOOGLE_CHECK_LE(count, target_->size());
|
||||||
target_->resize(target_->size() - count);
|
target_->resize(target_->size() - count);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 StringOutputStream::ByteCount() const {
|
int64 StringOutputStream::ByteCount() const {
|
||||||
|
GOOGLE_CHECK_NE(NULL, target_);
|
||||||
return target_->size();
|
return target_->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StringOutputStream::SetString(string* target) {
|
||||||
|
target_ = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
LazyStringOutputStream::LazyStringOutputStream(
|
||||||
|
ResultCallback<string*>* callback)
|
||||||
|
: StringOutputStream(NULL),
|
||||||
|
callback_(GOOGLE_CHECK_NOTNULL(callback)),
|
||||||
|
string_is_set_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyStringOutputStream::~LazyStringOutputStream() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LazyStringOutputStream::Next(void** data, int* size) {
|
||||||
|
if (!string_is_set_) {
|
||||||
|
SetString(callback_->Run());
|
||||||
|
string_is_set_ = true;
|
||||||
|
}
|
||||||
|
return StringOutputStream::Next(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 LazyStringOutputStream::ByteCount() const {
|
||||||
|
return string_is_set_ ? StringOutputStream::ByteCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
CopyingInputStream::~CopyingInputStream() {}
|
CopyingInputStream::~CopyingInputStream() {}
|
||||||
|
@ -148,6 +148,9 @@ class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
|||||||
void BackUp(int count);
|
void BackUp(int count);
|
||||||
int64 ByteCount() const;
|
int64 ByteCount() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetString(string* target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int kMinimumSize = 16;
|
static const int kMinimumSize = 16;
|
||||||
|
|
||||||
@ -156,6 +159,27 @@ class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream {
|
|||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// LazyStringOutputStream is a StringOutputStream with lazy acquisition of
|
||||||
|
// the output string from a callback. The string is owned externally, and not
|
||||||
|
// deleted in the stream destructor.
|
||||||
|
class LIBPROTOBUF_EXPORT LazyStringOutputStream : public StringOutputStream {
|
||||||
|
public:
|
||||||
|
// Callback should be permanent (non-self-deleting). Ownership is transferred
|
||||||
|
// to the LazyStringOutputStream.
|
||||||
|
explicit LazyStringOutputStream(ResultCallback<string*>* callback);
|
||||||
|
~LazyStringOutputStream();
|
||||||
|
|
||||||
|
// implements ZeroCopyOutputStream, overriding StringOutputStream -----------
|
||||||
|
bool Next(void** data, int* size);
|
||||||
|
int64 ByteCount() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const scoped_ptr<ResultCallback<string*> > callback_;
|
||||||
|
bool string_is_set_;
|
||||||
|
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyStringOutputStream);
|
||||||
|
};
|
||||||
|
|
||||||
// Note: There is no StringInputStream. Instead, just create an
|
// Note: There is no StringInputStream. Instead, just create an
|
||||||
// ArrayInputStream as follows:
|
// ArrayInputStream as follows:
|
||||||
// ArrayInputStream input(str.data(), str.size());
|
// ArrayInputStream input(str.data(), str.size());
|
||||||
|
@ -78,6 +78,18 @@ class LIBPROTOBUF_EXPORT Closure {
|
|||||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
class LIBPROTOBUF_EXPORT ResultCallback {
|
||||||
|
public:
|
||||||
|
ResultCallback() {}
|
||||||
|
virtual ~ResultCallback() {}
|
||||||
|
|
||||||
|
virtual R Run() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename R, typename A1>
|
template<typename R, typename A1>
|
||||||
class LIBPROTOBUF_EXPORT ResultCallback1 {
|
class LIBPROTOBUF_EXPORT ResultCallback1 {
|
||||||
public:
|
public:
|
||||||
@ -240,6 +252,50 @@ class MethodClosure2 : public Closure {
|
|||||||
Arg2 arg2_;
|
Arg2 arg2_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
class FunctionResultCallback_0_0 : public ResultCallback<R> {
|
||||||
|
public:
|
||||||
|
typedef R (*FunctionType)();
|
||||||
|
|
||||||
|
FunctionResultCallback_0_0(FunctionType function, bool self_deleting)
|
||||||
|
: function_(function), self_deleting_(self_deleting) {}
|
||||||
|
~FunctionResultCallback_0_0() {}
|
||||||
|
|
||||||
|
R Run() {
|
||||||
|
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||||
|
R result = function_();
|
||||||
|
if (needs_delete) delete this;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionType function_;
|
||||||
|
bool self_deleting_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename R, typename P1>
|
||||||
|
class FunctionResultCallback_1_0 : public ResultCallback<R> {
|
||||||
|
public:
|
||||||
|
typedef R (*FunctionType)(P1);
|
||||||
|
|
||||||
|
FunctionResultCallback_1_0(FunctionType function, bool self_deleting,
|
||||||
|
P1 p1)
|
||||||
|
: function_(function), self_deleting_(self_deleting), p1_(p1) {}
|
||||||
|
~FunctionResultCallback_1_0() {}
|
||||||
|
|
||||||
|
R Run() {
|
||||||
|
bool needs_delete = self_deleting_; // read in case callback deletes
|
||||||
|
R result = function_(p1_);
|
||||||
|
if (needs_delete) delete this;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionType function_;
|
||||||
|
bool self_deleting_;
|
||||||
|
P1 p1_;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename R, typename Arg1>
|
template<typename R, typename Arg1>
|
||||||
class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
|
class FunctionResultCallback_0_1 : public ResultCallback1<R, Arg1> {
|
||||||
public:
|
public:
|
||||||
@ -408,6 +464,33 @@ inline Closure* NewPermanentCallback(
|
|||||||
object, method, false, arg1, arg2);
|
object, method, false, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See ResultCallback
|
||||||
|
template<typename R>
|
||||||
|
inline ResultCallback<R>* NewCallback(R (*function)()) {
|
||||||
|
return new internal::FunctionResultCallback_0_0<R>(function, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See ResultCallback
|
||||||
|
template<typename R>
|
||||||
|
inline ResultCallback<R>* NewPermanentCallback(R (*function)()) {
|
||||||
|
return new internal::FunctionResultCallback_0_0<R>(function, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See ResultCallback
|
||||||
|
template<typename R, typename P1>
|
||||||
|
inline ResultCallback<R>* NewCallback(R (*function)(P1), P1 p1) {
|
||||||
|
return new internal::FunctionResultCallback_1_0<R, P1>(
|
||||||
|
function, true, p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See ResultCallback
|
||||||
|
template<typename R, typename P1>
|
||||||
|
inline ResultCallback<R>* NewPermanentCallback(
|
||||||
|
R (*function)(P1), P1 p1) {
|
||||||
|
return new internal::FunctionResultCallback_1_0<R, P1>(
|
||||||
|
function, false, p1);
|
||||||
|
}
|
||||||
|
|
||||||
// See ResultCallback1
|
// See ResultCallback1
|
||||||
template<typename R, typename A1>
|
template<typename R, typename A1>
|
||||||
inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
|
inline ResultCallback1<R, A1>* NewCallback(R (*function)(A1)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user