This is an automated email from the ASF dual-hosted git repository.

guangmingchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new 8d878143 Wrap absl::string_view as std::string to support protobuf 
v30+ (#3187)
8d878143 is described below

commit 8d87814330d9ebbfe5b95774fdb71056fcb3170c
Author: Xiaofeng Wang <[email protected]>
AuthorDate: Sun Jan 4 11:34:25 2026 +0800

    Wrap absl::string_view as std::string to support protobuf v30+ (#3187)
    
    * Wrap absl::string_view as std::string to support protobuf v30+
    
    Closes #3181
    
    * remove unnecessary specialization for abs:string_view
    
    * keep path for consistency
---
 src/brpc/amf.cpp                           |  2 +-
 src/brpc/builtin/protobufs_service.cpp     | 11 +++--
 src/brpc/channel.cpp                       | 10 ++---
 src/brpc/nshead_pb_service_adaptor.cpp     | 10 +++--
 src/brpc/policy/baidu_rpc_protocol.cpp     | 19 +++++----
 src/brpc/policy/http_rpc_protocol.cpp      | 47 ++++++++++++---------
 src/brpc/policy/hulu_pbrpc_protocol.cpp    | 10 +++--
 src/brpc/policy/mongo_protocol.cpp         |  7 +++-
 src/brpc/policy/nshead_mcpack_protocol.cpp | 13 +++---
 src/brpc/policy/sofa_pbrpc_protocol.cpp    |  7 +++-
 src/brpc/policy/ubrpc2pb_protocol.cpp      | 16 ++++----
 src/brpc/server.cpp                        | 17 ++++----
 src/brpc/server.h                          |  2 +-
 src/butil/strings/string_util.h            | 20 +++++++++
 src/json2pb/json_to_pb.cpp                 | 20 +++++----
 src/json2pb/pb_to_json.cpp                 | 16 ++++----
 src/json2pb/pb_to_json.h                   |  4 ++
 src/json2pb/protobuf_map.cpp               |  4 +-
 src/json2pb/protobuf_type_resolver.h       |  5 ++-
 src/mcpack2pb/generator.cpp                | 66 +++++++++++++++---------------
 20 files changed, 184 insertions(+), 122 deletions(-)

diff --git a/src/brpc/amf.cpp b/src/brpc/amf.cpp
index 023eaa9b..b251ccf2 100644
--- a/src/brpc/amf.cpp
+++ b/src/brpc/amf.cpp
@@ -1000,7 +1000,7 @@ void WriteAMFObject(const google::protobuf::Message& 
message,
                 continue;
             }
         }
-        const std::string& name = field->name();
+        const auto& name = field->name();
         if (name.size() >= 65536u) {
             LOG(ERROR) << "name is too long!";
             return stream->set_bad();
diff --git a/src/brpc/builtin/protobufs_service.cpp 
b/src/brpc/builtin/protobufs_service.cpp
index 2344e461..99a3fea3 100644
--- a/src/brpc/builtin/protobufs_service.cpp
+++ b/src/brpc/builtin/protobufs_service.cpp
@@ -17,13 +17,16 @@
 
 
 #include <google/protobuf/descriptor.h>     // ServiceDescriptor
+
+#include "brpc/builtin/protobufs_service.h"
+
 #include "brpc/controller.h"           // Controller
 #include "brpc/server.h"               // Server
 #include "brpc/closure_guard.h"        // ClosureGuard
 #include "brpc/details/method_status.h"// MethodStatus
-#include "brpc/builtin/protobufs_service.h"
 #include "brpc/builtin/common.h"
 
+#include "butil/strings/string_util.h"
 
 namespace brpc {
 
@@ -42,7 +45,7 @@ int ProtobufsService::Init() {
         }
         const google::protobuf::ServiceDescriptor* d =
             iter->second.service->GetDescriptor();
-        _map[d->full_name()] = d->DebugString();
+        _map[butil::EnsureString(d->full_name())] = d->DebugString();
         const int method_count = d->method_count();
         for (int j = 0; j < method_count; ++j) {
             const google::protobuf::MethodDescriptor* md = d->method(j);
@@ -53,13 +56,13 @@ int ProtobufsService::Init() {
     while (!stack.empty()) {
         const google::protobuf::Descriptor* d = stack.back();
         stack.pop_back();
-        _map[d->full_name()] = d->DebugString();
+        _map[butil::EnsureString(d->full_name())] = d->DebugString();
         for (int i = 0; i < d->field_count(); ++i) {
             const google::protobuf::FieldDescriptor* f = d->field(i);
             if (f->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE ||
                 f->type() == google::protobuf::FieldDescriptor::TYPE_GROUP) {
                 const google::protobuf::Descriptor* sub_d = f->message_type();
-                if (sub_d != d && _map.find(sub_d->full_name()) == _map.end()) 
{
+                if (sub_d != d && 
_map.find(butil::EnsureString(sub_d->full_name())) == _map.end()) {
                     stack.push_back(sub_d);
                 }
             }
diff --git a/src/brpc/channel.cpp b/src/brpc/channel.cpp
index 0252e97d..0fd43d7c 100644
--- a/src/brpc/channel.cpp
+++ b/src/brpc/channel.cpp
@@ -492,17 +492,17 @@ void Channel::CallMethod(const 
google::protobuf::MethodDescriptor* method,
 
     if (cntl->_sender == NULL && IsTraceable(Span::tls_parent())) {
         const int64_t start_send_us = butil::cpuwide_time_us();
-        const std::string* method_name = NULL;
+        std::string method_name;
         if (_get_method_name) {
-            method_name = &_get_method_name(method, cntl);
+            method_name = butil::EnsureString(_get_method_name(method, cntl));
         } else if (method) {
-            method_name = &method->full_name();
+            method_name = butil::EnsureString(method->full_name());
         } else {
             const static std::string NULL_METHOD_STR = "null-method";
-            method_name = &NULL_METHOD_STR;
+            method_name = NULL_METHOD_STR;
         }
         Span* span = Span::CreateClientSpan(
-            *method_name, start_send_real_us - start_send_us);
+            method_name, start_send_real_us - start_send_us);
         span->set_log_id(cntl->log_id());
         span->set_base_cid(correlation_id);
         span->set_protocol(_options.protocol);
diff --git a/src/brpc/nshead_pb_service_adaptor.cpp 
b/src/brpc/nshead_pb_service_adaptor.cpp
index ed3552f5..889f9575 100644
--- a/src/brpc/nshead_pb_service_adaptor.cpp
+++ b/src/brpc/nshead_pb_service_adaptor.cpp
@@ -19,8 +19,7 @@
 #include <google/protobuf/descriptor.h>         // MethodDescriptor
 #include <google/protobuf/message.h>            // Message
 
-#include "butil/time.h" 
-#include "butil/iobuf.h"                         // butil::IOBuf
+#include "brpc/nshead_pb_service_adaptor.h"
 
 #include "brpc/controller.h"               // Controller
 #include "brpc/socket.h"                   // Socket
@@ -28,9 +27,12 @@
 #include "brpc/span.h"
 #include "brpc/details/server_private_accessor.h"
 #include "brpc/details/controller_private_accessor.h"
-#include "brpc/nshead_pb_service_adaptor.h"
 #include "brpc/policy/most_common_message.h"
 
+#include "butil/iobuf.h"                         // butil::IOBuf
+#include "butil/strings/string_util.h"
+#include "butil/time.h"
+
 
 namespace brpc {
 
@@ -126,7 +128,7 @@ void NsheadPbServiceAdaptor::ProcessNsheadRequest(
         google::protobuf::Service* svc = sp->service;
         const google::protobuf::MethodDescriptor* method = sp->method;
         ControllerPrivateAccessor(controller).set_method(method);
-        done->SetMethodName(method->full_name());
+        done->SetMethodName(butil::EnsureString(method->full_name()));
         pbdone->pbreq.reset(svc->GetRequestPrototype(method).New());
         pbdone->pbres.reset(svc->GetResponsePrototype(method).New());
 
diff --git a/src/brpc/policy/baidu_rpc_protocol.cpp 
b/src/brpc/policy/baidu_rpc_protocol.cpp
index 5adf77b2..0dba0162 100644
--- a/src/brpc/policy/baidu_rpc_protocol.cpp
+++ b/src/brpc/policy/baidu_rpc_protocol.cpp
@@ -21,10 +21,13 @@
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/text_format.h>
-#include "butil/logging.h"                       // LOG()
+
 #include "butil/iobuf.h"                         // butil::IOBuf
-#include "butil/raw_pack.h"                      // RawPacker RawUnpacker
+#include "butil/logging.h"                       // LOG()
 #include "butil/memory/scope_guard.h"
+#include "butil/raw_pack.h"                      // RawPacker RawUnpacker
+#include "butil/strings/string_util.h"
+
 #include "json2pb/json_to_pb.h"
 #include "json2pb/pb_to_json.h"
 #include "brpc/controller.h"                    // Controller
@@ -233,7 +236,7 @@ static bool SerializeResponse(const 
google::protobuf::Message& res,
         cntl.SetFailed(ERESPONSE,
                        "Fail to serialize response=%s, "
                        "ContentType=%s, CompressType=%s, ChecksumType=%s",
-                       res.GetDescriptor()->full_name().c_str(),
+                       
butil::EnsureString(res.GetDescriptor()->full_name()).c_str(),
                        ContentTypeToCStr(content_type),
                        CompressTypeToCStr(compress_type),
                        ChecksumTypeToCStr(checksum_type));
@@ -775,7 +778,7 @@ void ProcessRpcRequest(InputMessageBase* msg_base) {
                     cntl->SetFailed(
                         ELIMIT,
                         "Rejected by %s's ConcurrencyLimiter, concurrency=%d",
-                        mp->method->full_name().c_str(), rejected_cc);
+                        butil::EnsureString(mp->method->full_name()).c_str(), 
rejected_cc);
                     break;
                 }
             }
@@ -784,7 +787,7 @@ void ProcessRpcRequest(InputMessageBase* msg_base) {
             accessor.set_method(method);
 
             if (span) {
-                span->ResetServerSpanName(method->full_name());
+                
span->ResetServerSpanName(butil::EnsureString(method->full_name()));
             }
 
             if (!server->AcceptRequest(cntl.get())) {
@@ -812,7 +815,7 @@ void ProcessRpcRequest(InputMessageBase* msg_base) {
                     EREQUEST,
                     "Fail to parse request=%s, ContentType=%s, "
                     "CompressType=%s, ChecksumType=%s, request_size=%d",
-                    messages->Request()->GetDescriptor()->full_name().c_str(),
+                    
butil::EnsureString(messages->Request()->GetDescriptor()->full_name()).c_str(),
                     ContentTypeToCStr(content_type),
                     CompressTypeToCStr(compress_type),
                     ChecksumTypeToCStr(checksum_type), req_size);
@@ -996,7 +999,7 @@ void ProcessRpcResponse(InputMessageBase* msg_base) {
                     EREQUEST,
                     "Fail to parse response=%s, ContentType=%s, "
                     "CompressType=%s, ChecksumType=%s, request_size=%d",
-                    cntl->response()->GetDescriptor()->full_name().c_str(),
+                    
butil::EnsureString(cntl->response()->GetDescriptor()->full_name()).c_str(),
                     ContentTypeToCStr(content_type),
                     CompressTypeToCStr(compress_type),
                     ChecksumTypeToCStr(checksum_type), res_size);
@@ -1033,7 +1036,7 @@ void SerializeRpcRequest(butil::IOBuf* request_buf, 
Controller* cntl,
             EREQUEST,
             "Fail to compress request=%s, "
             "ContentType=%s, CompressType=%s, ChecksumType=%s",
-            request->GetDescriptor()->full_name().c_str(),
+            butil::EnsureString(request->GetDescriptor()->full_name()).c_str(),
             ContentTypeToCStr(content_type), CompressTypeToCStr(compress_type),
             ChecksumTypeToCStr(checksum_type));
     }
diff --git a/src/brpc/policy/http_rpc_protocol.cpp 
b/src/brpc/policy/http_rpc_protocol.cpp
index 872c2897..d0150a63 100644
--- a/src/brpc/policy/http_rpc_protocol.cpp
+++ b/src/brpc/policy/http_rpc_protocol.cpp
@@ -20,12 +20,16 @@
 #include <google/protobuf/text_format.h>
 #include <gflags/gflags.h>
 #include <string>
+
 #include "brpc/policy/http_rpc_protocol.h"
-#include "butil/unique_ptr.h"                       // std::unique_ptr
-#include "butil/string_splitter.h"                  // StringMultiSplitter
+
 #include "butil/string_printf.h"
-#include "butil/time.h"
+#include "butil/string_splitter.h"                  // StringMultiSplitter
+#include "butil/strings/string_util.h"
 #include "butil/sys_byteorder.h"
+#include "butil/time.h"
+#include "butil/unique_ptr.h"                       // std::unique_ptr
+
 #include "json2pb/pb_to_json.h"                     // ProtoMessageToJson
 #include "json2pb/json_to_pb.h"                     // JsonToProtoMessage
 #include "brpc/compress.h"
@@ -284,7 +288,7 @@ static bool JsonToProtoMessage(const butil::IOBuf& body,
     bool ok = json2pb::JsonToProtoMessage(&wrapper, message, options, &error);
     if (!ok) {
         cntl->SetFailed(error_code, "Fail to parse http json body as %s: %s",
-                        message->GetDescriptor()->full_name().c_str(),
+                        
butil::EnsureString(message->GetDescriptor()->full_name()).c_str(),
                         error.c_str());
     }
     return ok;
@@ -305,7 +309,7 @@ static bool ProtoMessageToJson(const 
google::protobuf::Message& message,
     bool ok = json2pb::ProtoMessageToJson(message, wrapper, options, &error);
     if (!ok) {
         cntl->SetFailed(error_code, "Fail to convert %s to json: %s",
-                        message.GetDescriptor()->full_name().c_str(),
+                        
butil::EnsureString(message.GetDescriptor()->full_name()).c_str(),
                         error.c_str());
     }
     return ok;
@@ -321,7 +325,7 @@ static bool ProtoJsonToProtoMessage(const butil::IOBuf& 
body,
     bool ok = json2pb::ProtoJsonToProtoMessage(&wrapper, message, options, 
&error);
     if (!ok) {
         cntl->SetFailed(error_code, "Fail to parse http proto-json body as %s: 
%s",
-                        message->GetDescriptor()->full_name().c_str(),
+                        
butil::EnsureString(message->GetDescriptor()->full_name()).c_str(),
                         error.c_str());
     }
     return ok;
@@ -337,7 +341,7 @@ static bool ProtoMessageToProtoJson(const 
google::protobuf::Message& message,
     bool ok = json2pb::ProtoMessageToProtoJson(message, wrapper, options, 
&error);
     if (!ok) {
         cntl->SetFailed(error_code, "Fail to convert %s to proto-json: %s",
-                        message.GetDescriptor()->full_name().c_str(), 
error.c_str());
+                        
butil::EnsureString(message.GetDescriptor()->full_name()).c_str(), 
error.c_str());
     }
     return ok;
 }
@@ -527,13 +531,13 @@ void ProcessHttpResponse(InputMessageBase* msg) {
         if (content_type == HTTP_CONTENT_PROTO) {
             if (!ParsePbFromIOBuf(cntl->response(), res_body)) {
                 cntl->SetFailed(ERESPONSE, "Fail to parse content as %s",
-                                
cntl->response()->GetDescriptor()->full_name().c_str());
+                                
butil::EnsureString(cntl->response()->GetDescriptor()->full_name()).c_str());
                 break;
             }
         } else if (content_type == HTTP_CONTENT_PROTO_TEXT) {
             if (!ParsePbTextFromIOBuf(cntl->response(), res_body)) {
                 cntl->SetFailed(ERESPONSE, "Fail to parse proto-text content 
as %s",
-                                
cntl->response()->GetDescriptor()->full_name().c_str());
+                                
butil::EnsureString(cntl->response()->GetDescriptor()->full_name()).c_str());
                 break;
             }
         } else if (content_type == HTTP_CONTENT_JSON) {
@@ -612,13 +616,13 @@ void SerializeHttpRequest(butil::IOBuf* /*not used*/,
             if (!pbreq->SerializeToZeroCopyStream(&wrapper)) {
                 cntl->request_attachment().clear();
                 return cntl->SetFailed(EREQUEST, "Fail to serialize %s",
-                                       pbreq->GetTypeName().c_str());
+                                       
butil::EnsureString(pbreq->GetTypeName()).c_str());
             }
         } else if (content_type == HTTP_CONTENT_PROTO_TEXT) {
             if (!google::protobuf::TextFormat::Print(*pbreq, &wrapper)) {
                 cntl->request_attachment().clear();
                 return cntl->SetFailed(EREQUEST, "Fail to print %s as 
proto-text",
-                                       pbreq->GetTypeName().c_str());
+                                       
butil::EnsureString(pbreq->GetTypeName()).c_str());
             }
         } else if (content_type == HTTP_CONTENT_PROTO_JSON) {
             if (!ProtoMessageToProtoJson(*pbreq, &wrapper, cntl, EREQUEST)) {
@@ -880,11 +884,13 @@ HttpResponseSender::~HttpResponseSender() {
         butil::IOBufAsZeroCopyOutputStream 
wrapper(&cntl->response_attachment());
         if (content_type == HTTP_CONTENT_PROTO) {
             if (!res->SerializeToZeroCopyStream(&wrapper)) {
-                cntl->SetFailed(ERESPONSE, "Fail to serialize %s", 
res->GetTypeName().c_str());
+                cntl->SetFailed(ERESPONSE, "Fail to serialize %s",
+                                
butil::EnsureString(res->GetTypeName()).c_str());
             }
         } else if (content_type == HTTP_CONTENT_PROTO_TEXT) {
             if (!google::protobuf::TextFormat::Print(*res, &wrapper)) {
-                cntl->SetFailed(ERESPONSE, "Fail to print %s as proto-text", 
res->GetTypeName().c_str());
+                cntl->SetFailed(ERESPONSE, "Fail to print %s as proto-text",
+                                
butil::EnsureString(res->GetTypeName()).c_str());
             }
         } else if (content_type == HTTP_CONTENT_PROTO_JSON) {
             ProtoMessageToProtoJson(*res, &wrapper, cntl, ERESPONSE);
@@ -1535,7 +1541,7 @@ void ProcessHttpRequest(InputMessageBase *msg) {
         cntl->request_attachment().swap(req_body);
         google::protobuf::Closure* done = new 
HttpResponseSenderAsDone(&resp_sender);
         if (span) {
-            span->ResetServerSpanName(md->full_name());
+            span->ResetServerSpanName(butil::EnsureString(md->full_name()));
             span->set_start_callback_us(butil::cpuwide_time_us());
             span->AsParent();
         }
@@ -1565,18 +1571,19 @@ void ProcessHttpRequest(InputMessageBase *msg) {
     // Switch to service-specific error.
     non_service_error.release();
     MethodStatus* method_status = mp->status;
+    const std::string method_full_name = 
butil::EnsureString(mp->method->full_name());
     resp_sender.set_method_status(method_status);
     if (method_status) {
         int rejected_cc = 0;
         if (!method_status->OnRequested(&rejected_cc)) {
             cntl->SetFailed(ELIMIT, "Rejected by %s's ConcurrencyLimiter, 
concurrency=%d",
-                            mp->method->full_name().c_str(), rejected_cc);
+                            method_full_name.c_str(), rejected_cc);
             return;
         }
     }
     
     if (span) {
-        span->ResetServerSpanName(mp->method->full_name());
+        span->ResetServerSpanName(method_full_name);
     }
     // NOTE: accesses to builtin services are not counted as part of
     // concurrency, therefore are not limited by ServerOptions.max_concurrency.
@@ -1616,6 +1623,8 @@ void ProcessHttpRequest(InputMessageBase *msg) {
     google::protobuf::Message* req = messages->Request();
     google::protobuf::Message* res = messages->Response();
 
+    const std::string request_full_name = 
butil::EnsureString(req->GetDescriptor()->full_name());
+
     if (__builtin_expect(!req || !res, 0)) {
         PLOG(FATAL) << "Fail to new req or res";
         cntl->SetFailed("Fail to new req or res");
@@ -1632,7 +1641,7 @@ void ProcessHttpRequest(InputMessageBase *msg) {
             if (!req->IsInitialized()) {
                 cntl->SetFailed(EREQUEST, "%s needs to be created from a"
                                 " non-empty json, it has required fields.",
-                                req->GetDescriptor()->full_name().c_str());
+                                request_full_name.c_str());
                 return;
             } // else all fields of the request are optional.
         } else {
@@ -1677,13 +1686,13 @@ void ProcessHttpRequest(InputMessageBase *msg) {
             if (content_type == HTTP_CONTENT_PROTO) {
                 if (!ParsePbFromIOBuf(req, req_body)) {
                     cntl->SetFailed(EREQUEST, "Fail to parse http body as %s",
-                                    req->GetDescriptor()->full_name().c_str());
+                                    request_full_name.c_str());
                     return;
                 }
             } else if (content_type == HTTP_CONTENT_PROTO_TEXT) {
                 if (!ParsePbTextFromIOBuf(req, req_body)) {
                     cntl->SetFailed(EREQUEST, "Fail to parse http proto-text 
body as %s",
-                                    req->GetDescriptor()->full_name().c_str());
+                                    request_full_name.c_str());
                     return;
                 }
             } else if (content_type == HTTP_CONTENT_PROTO_JSON) {
diff --git a/src/brpc/policy/hulu_pbrpc_protocol.cpp 
b/src/brpc/policy/hulu_pbrpc_protocol.cpp
index 02ec8efc..bd0c4960 100644
--- a/src/brpc/policy/hulu_pbrpc_protocol.cpp
+++ b/src/brpc/policy/hulu_pbrpc_protocol.cpp
@@ -20,7 +20,10 @@
 #include <google/protobuf/message.h>             // Message
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/io/coded_stream.h>
+
+#include "butil/strings/string_util.h"
 #include "butil/time.h"
+
 #include "brpc/controller.h"                     // Controller
 #include "brpc/socket.h"                         // Socket
 #include "brpc/server.h"                         // Server
@@ -469,17 +472,18 @@ void ProcessHuluRequest(InputMessageBase* msg_base) {
         // Switch to service-specific error.
         non_service_error.release();
         method_status = sp->status;
+        const google::protobuf::MethodDescriptor* method = sp->method;
+        const std::string method_full_name = 
butil::EnsureString(method->full_name());
         if (method_status) {
             int rejected_cc = 0;
             if (!method_status->OnRequested(&rejected_cc)) {
                 cntl->SetFailed(ELIMIT, "Rejected by %s's ConcurrencyLimiter, 
concurrency=%d",
-                                sp->method->full_name().c_str(), rejected_cc);
+                                method_full_name.c_str(), rejected_cc);
                 break;
             }
         }
         
         google::protobuf::Service* svc = sp->service;
-        const google::protobuf::MethodDescriptor* method = sp->method;
         accessor.set_method(method);
 
         if (!server->AcceptRequest(cntl.get())) {
@@ -487,7 +491,7 @@ void ProcessHuluRequest(InputMessageBase* msg_base) {
         }
 
         if (span) {
-            span->ResetServerSpanName(method->full_name());
+            span->ResetServerSpanName(method_full_name);
         }
         const int reqsize = msg->payload.length();
         butil::IOBuf req_buf;
diff --git a/src/brpc/policy/mongo_protocol.cpp 
b/src/brpc/policy/mongo_protocol.cpp
index 82bb3e0b..5df304e1 100644
--- a/src/brpc/policy/mongo_protocol.cpp
+++ b/src/brpc/policy/mongo_protocol.cpp
@@ -18,8 +18,11 @@
 #include <google/protobuf/descriptor.h>         // MethodDescriptor
 #include <google/protobuf/message.h>            // Message
 #include <gflags/gflags.h>
-#include "butil/time.h" 
+
 #include "butil/iobuf.h"                         // butil::IOBuf
+#include "butil/strings/string_util.h"
+#include "butil/time.h"
+
 #include "brpc/controller.h"               // Controller
 #include "brpc/socket.h"                   // Socket
 #include "brpc/server.h"                   // Server
@@ -249,7 +252,7 @@ void ProcessMongoRequest(InputMessageBase* msg_base) {
             if (!method_status->OnRequested(&rejected_cc)) {
                 mongo_done->cntl.SetFailed(
                     ELIMIT, "Rejected by %s's ConcurrencyLimiter, 
concurrency=%d",
-                    mp->method->full_name().c_str(), rejected_cc);
+                    butil::EnsureString(mp->method->full_name()).c_str(), 
rejected_cc);
                 break;
             }
         }
diff --git a/src/brpc/policy/nshead_mcpack_protocol.cpp 
b/src/brpc/policy/nshead_mcpack_protocol.cpp
index 40d38836..052fd0f3 100644
--- a/src/brpc/policy/nshead_mcpack_protocol.cpp
+++ b/src/brpc/policy/nshead_mcpack_protocol.cpp
@@ -20,8 +20,9 @@
 #include <google/protobuf/message.h>            // Message
 #include <gflags/gflags.h>
 
-#include "butil/time.h"
 #include "butil/iobuf.h"                        // butil::IOBuf
+#include "butil/strings/string_util.h"
+#include "butil/time.h"
 
 #include "brpc/controller.h"               // Controller
 #include "brpc/socket.h"                   // Socket
@@ -49,7 +50,7 @@ void NsheadMcpackAdaptor::ParseNsheadMeta(
     const google::protobuf::ServiceDescriptor* sd = service->GetDescriptor();
     if (sd->method_count() == 0) {
         cntl->SetFailed(ENOMETHOD, "No method in service=%s",
-                        sd->full_name().c_str());
+                        butil::EnsureString(sd->full_name()).c_str());
         return;
     }
     const google::protobuf::MethodDescriptor* method = sd->method(0);
@@ -59,7 +60,7 @@ void NsheadMcpackAdaptor::ParseNsheadMeta(
 void NsheadMcpackAdaptor::ParseRequestFromIOBuf(
     const NsheadMeta&, const NsheadMessage& raw_req,
     Controller* cntl, google::protobuf::Message* pb_req) const {
-    const std::string& msg_name = pb_req->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(pb_req->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (!handler.parse_from_iobuf(pb_req, raw_req.body)) {
         cntl->SetFailed(EREQUEST, "Fail to parse request message, "
@@ -86,7 +87,7 @@ void NsheadMcpackAdaptor::SerializeResponseToIOBuf(
         return;
     }
 
-    const std::string& msg_name = pb_res->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(pb_res->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (!handler.serialize_to_iobuf(*pb_res, &raw_res->body,
                                    ::mcpack2pb::FORMAT_MCPACK_V2)) {
@@ -124,7 +125,7 @@ void ProcessNsheadMcpackResponse(InputMessageBase* 
msg_base) {
         // silently ignore response.
         return;
     }
-    const std::string& msg_name = res->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(res->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (!handler.parse_from_iobuf(res, msg->payload)) {
         return cntl->CloseConnection("Fail to parse response message");
@@ -143,7 +144,7 @@ void SerializeNsheadMcpackRequest(butil::IOBuf* buf, 
Controller* cntl,
                         "nshead_mcpack protocol doesn't support compression");
         return;
     }
-    const std::string& msg_name = pb_req->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(pb_req->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (!handler.serialize_to_iobuf(*pb_req, buf, 
::mcpack2pb::FORMAT_MCPACK_V2)) {
         cntl->SetFailed(EREQUEST, "Fail to serialize %s", msg_name.c_str());
diff --git a/src/brpc/policy/sofa_pbrpc_protocol.cpp 
b/src/brpc/policy/sofa_pbrpc_protocol.cpp
index 9ee772dc..2fb33ed5 100644
--- a/src/brpc/policy/sofa_pbrpc_protocol.cpp
+++ b/src/brpc/policy/sofa_pbrpc_protocol.cpp
@@ -20,7 +20,10 @@
 #include <google/protobuf/message.h>             // Message
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/io/coded_stream.h>
+
 #include "butil/time.h"
+#include "butil/strings/string_util.h"
+
 #include "brpc/controller.h"                // Controller
 #include "brpc/socket.h"                    // Socket
 #include "brpc/server.h"                    // Server
@@ -424,7 +427,7 @@ void ProcessSofaRequest(InputMessageBase* msg_base) {
             int rejected_cc = 0;
             if (!method_status->OnRequested(&rejected_cc)) {
                 cntl->SetFailed(ELIMIT, "Rejected by %s's ConcurrencyLimiter, 
concurrency=%d",
-                                sp->method->full_name().c_str(), rejected_cc);
+                                
butil::EnsureString(sp->method->full_name()).c_str(), rejected_cc);
                 break;
             }
         }
@@ -437,7 +440,7 @@ void ProcessSofaRequest(InputMessageBase* msg_base) {
         }
 
         if (span) {
-            span->ResetServerSpanName(method->full_name());
+            
span->ResetServerSpanName(butil::EnsureString(method->full_name()));
         }
         req.reset(svc->GetRequestPrototype(method).New());
         if (!ParseFromCompressedData(msg->payload, req.get(), req_cmp_type)) {
diff --git a/src/brpc/policy/ubrpc2pb_protocol.cpp 
b/src/brpc/policy/ubrpc2pb_protocol.cpp
index 312ec5d9..fe2c4619 100644
--- a/src/brpc/policy/ubrpc2pb_protocol.cpp
+++ b/src/brpc/policy/ubrpc2pb_protocol.cpp
@@ -20,8 +20,10 @@
 #include <google/protobuf/message.h>            // Message
 #include <gflags/gflags.h>
 
-#include "butil/time.h"
 #include "butil/iobuf.h"                         // butil::IOBuf
+#include "butil/strings/string_util.h"
+#include "butil/time.h"
+
 #include "brpc/controller.h"               // Controller
 #include "brpc/socket.h"                   // Socket
 #include "brpc/server.h"                   // Server
@@ -169,7 +171,7 @@ void UbrpcAdaptor::ParseNsheadMeta(
 void UbrpcAdaptor::ParseRequestFromIOBuf(
     const NsheadMeta&, const NsheadMessage& raw_req,
     Controller* cntl, google::protobuf::Message* pb_req) const {
-    const std::string& msg_name = pb_req->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(pb_req->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (handler.parse_body == NULL) {
         return cntl->SetFailed(EREQUEST, "Fail to find parser of %s",
@@ -227,7 +229,7 @@ void UbrpcAdaptor::SerializeResponseToIOBuf(
     //     return AppendError(meta, cntl, raw_res->body);
     // }
 
-    const std::string& msg_name = pb_res->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(pb_res->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (handler.serialize_body == NULL) {
         cntl->SetFailed(ERESPONSE, "Fail to find serializer of %s",
@@ -279,7 +281,7 @@ static void ParseResponse(Controller* cntl, butil::IOBuf& 
buf,
         // silently ignore response.
         return;
     }
-    const std::string& msg_name = res->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(res->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (handler.parse_body == NULL) {
         return cntl->SetFailed(ERESPONSE, "Fail to find parser of %s",
@@ -480,7 +482,7 @@ static void SerializeUbrpcRequest(butil::IOBuf* buf, 
Controller* cntl,
     if (cntl->method() == NULL) {
         return cntl->SetFailed(ENOMETHOD, "method is NULL");
     }
-    const std::string& msg_name = request->GetDescriptor()->full_name();
+    const std::string msg_name = 
butil::EnsureString(request->GetDescriptor()->full_name());
     mcpack2pb::MessageHandler handler = 
mcpack2pb::find_message_handler(msg_name);
     if (handler.serialize_body == NULL) {
         return cntl->SetFailed(EREQUEST, "Fail to find serializer of %s",
@@ -500,9 +502,9 @@ static void SerializeUbrpcRequest(butil::IOBuf* buf, 
Controller* cntl,
         sr.begin_mcpack_array("content", mcpack2pb::FIELD_OBJECT);
         sr.begin_object();
         {
-            sr.add_string("service_name", cntl->method()->service()->name());
+            sr.add_string("service_name", 
butil::EnsureString(cntl->method()->service()->name()));
             sr.add_int64("id", cntl->call_id().value);
-            sr.add_string("method", cntl->method()->name());
+            sr.add_string("method", 
butil::EnsureString(cntl->method()->name()));
             sr.begin_object("params");
             const char* const request_name = cntl->idl_names().request_name;
             if (request_name != NULL && *request_name) {
diff --git a/src/brpc/server.cpp b/src/brpc/server.cpp
index a82817be..8e2368bc 100644
--- a/src/brpc/server.cpp
+++ b/src/brpc/server.cpp
@@ -30,6 +30,7 @@
 #include "butil/time.h"
 #include "butil/class_name.h"
 #include "butil/string_printf.h"
+#include "butil/strings/string_util.h"
 #include "butil/debug/leak_annotations.h"
 #include "brpc/log.h"
 #include "brpc/compress.h"
@@ -411,9 +412,9 @@ void* Server::UpdateDerivedVars(void* arg) {
     }
 }
 
-const std::string& Server::ServiceProperty::service_name() const {
+const std::string Server::ServiceProperty::service_name() const {
     if (service) {
-        return service->GetDescriptor()->full_name();
+        return butil::EnsureString(service->GetDescriptor()->full_name());
     } else if (restful_map) {
         return restful_map->service_name();
     }
@@ -1439,7 +1440,7 @@ int Server::AddServiceInternal(google::protobuf::Service* 
service,
         mp.service = service;
         mp.method = md;
         mp.status = new MethodStatus;
-        _method_map[md->full_name()] = mp;
+        _method_map[butil::EnsureString(md->full_name())] = mp;
         if (is_idl_support && sd->name() != sd->full_name()/*has ns*/) {
             MethodProperty mp2 = mp;
             mp2.own_method_status = false;
@@ -1462,8 +1463,8 @@ int Server::AddServiceInternal(google::protobuf::Service* 
service,
 
     const ServiceProperty ss = {
         is_builtin_service, svc_opt.ownership, service, NULL };
-    _fullname_service_map[sd->full_name()] = ss;
-    _service_map[sd->name()] = ss;
+    _fullname_service_map[butil::EnsureString(sd->full_name())] = ss;
+    _service_map[butil::EnsureString(sd->name())] = ss;
     if (is_builtin_service) {
         ++_builtin_service_count;
     } else {
@@ -1505,7 +1506,7 @@ int Server::AddServiceInternal(google::protobuf::Service* 
service,
         // handling is not affected.
         for (size_t i = 0; i < mappings.size(); ++i) {
             const std::string full_method_name =
-                sd->full_name() + "." + mappings[i].method_name;
+                butil::EnsureString(sd->full_name()) + "." + 
mappings[i].method_name;
             MethodProperty* mp = _method_map.seek(full_method_name);
             if (mp == NULL) {
                 LOG(ERROR) << "Unknown method=`" << full_method_name << '\'';
@@ -1730,9 +1731,9 @@ int Server::RemoveService(google::protobuf::Service* 
service) {
     }
 
     const google::protobuf::ServiceDescriptor* sd = service->GetDescriptor();
-    ServiceProperty* ss = _fullname_service_map.seek(sd->full_name());
+    ServiceProperty* ss = 
_fullname_service_map.seek(butil::EnsureString(sd->full_name()));
     if (ss == NULL) {
-        RPC_VLOG << "Fail to find service=" << sd->full_name().c_str();
+        RPC_VLOG << "Fail to find service=" << sd->full_name();
         return -1;
     }
     RemoveMethodsOf(service);
diff --git a/src/brpc/server.h b/src/brpc/server.h
index f833325c..c262375c 100644
--- a/src/brpc/server.h
+++ b/src/brpc/server.h
@@ -391,7 +391,7 @@ public:
             return !is_builtin_service && !restful_map;
         }
 
-        const std::string& service_name() const;
+        const std::string service_name() const;
     };
     typedef butil::FlatMap<std::string, ServiceProperty> ServiceMap;
 
diff --git a/src/butil/strings/string_util.h b/src/butil/strings/string_util.h
index 4d78e20f..bd3328a7 100644
--- a/src/butil/strings/string_util.h
+++ b/src/butil/strings/string_util.h
@@ -11,6 +11,8 @@
 #include <stdarg.h>   // va_list
 
 #include <string>
+#include <type_traits>
+#include <utility>
 #include <vector>
 
 #include "butil/base_export.h"
@@ -258,6 +260,24 @@ BUTIL_EXPORT bool IsStringUTF8(const StringPiece& str);
 BUTIL_EXPORT bool IsStringASCII(const StringPiece& str);
 BUTIL_EXPORT bool IsStringASCII(const string16& str);
 
+inline std::string EnsureString(const std::string& s) {
+    return s;
+}
+
+inline std::string EnsureString(std::string&& s) {
+    return std::move(s);
+}
+
+inline std::string EnsureString(const char* s) {
+    return s ? std::string(s) : std::string();
+}
+
+// Enabled only when std::string is constructible from T.
+template <typename T, typename = typename 
std::enable_if<std::is_constructible<std::string, T>::value>::type>
+inline std::string EnsureString(T&& v) {
+    return std::string(std::forward<T>(v));
+}
+
 }  // namespace butil
 
 #if defined(OS_WIN)
diff --git a/src/json2pb/json_to_pb.cpp b/src/json2pb/json_to_pb.cpp
index e758bdb3..87fd080a 100644
--- a/src/json2pb/json_to_pb.cpp
+++ b/src/json2pb/json_to_pb.cpp
@@ -28,6 +28,7 @@
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <gflags/gflags.h>
 #include "butil/strings/string_number_conversions.h"
+#include "butil/strings/string_util.h"
 #include "butil/third_party/rapidjson/error/error.h"
 #include "butil/third_party/rapidjson/rapidjson.h"
 #include "json2pb/json_to_pb.h"
@@ -53,8 +54,9 @@
             perr->append(", ", 2);                                      \
         }                                                               \
         butil::string_appendf(perr, fmt, ##__VA_ARGS__);                \
-        if ((pb) != nullptr) {                                            \
-            butil::string_appendf(perr, " [%s]", 
(pb)->GetDescriptor()->name().c_str());  \
+        if ((pb) != nullptr) {                                          \
+            butil::string_appendf(perr, " [%s]",                        \
+                    
butil::EnsureString((pb)->GetDescriptor()->name()).c_str()); \
         }                                                               \
     } else { }
 
@@ -126,7 +128,7 @@ inline bool value_invalid(const 
google::protobuf::FieldDescriptor* field, const
         string_append_value(value, err);
         butil::string_appendf(err, "' for %sfield `%s' which SHOULD be %s",
                        optional ? "optional " : "",
-                       field->full_name().c_str(), type);
+                       butil::EnsureString(field->full_name()).c_str(), type);
     }
     if (!optional) {
         return false;                                           
@@ -324,7 +326,7 @@ static bool JsonValueToProtoField(const 
BUTIL_RAPIDJSON_NAMESPACE::Value& value,
                                   int depth) {
     if (value.IsNull()) {
         if (field->is_required()) {
-            J2PERROR(err, "Missing required field: %s", 
field->full_name().c_str());
+            J2PERROR(err, "Missing required field: %s", 
butil::EnsureString(field->full_name()).c_str());
             return false;
         }
         return true;
@@ -333,7 +335,7 @@ static bool JsonValueToProtoField(const 
BUTIL_RAPIDJSON_NAMESPACE::Value& value,
     if (field->is_repeated()) {
         if (!value.IsArray()) {
             J2PERROR(err, "Invalid value for repeated field: %s",
-                     field->full_name().c_str());
+                     butil::EnsureString(field->full_name()).c_str());
             return false;
         }
     } 
@@ -506,7 +508,7 @@ bool JsonMapToProtoMap(const 
BUTIL_RAPIDJSON_NAMESPACE::Value& value,
                        int depth) {
     if (!value.IsObject()) {
         J2PERROR(err, "Non-object value for map field: %s",
-                 map_desc->full_name().c_str());
+                 butil::EnsureString(map_desc->full_name()).c_str());
         return false;
     }
 
@@ -584,7 +586,7 @@ bool JsonValueToProtoMessage(const 
BUTIL_RAPIDJSON_NAMESPACE::Value& json_value,
     for (size_t i = 0; i < fields.size(); ++i) {
         const google::protobuf::FieldDescriptor* field = fields[i];
         
-        const std::string& orig_name = field->name();
+        const std::string orig_name = butil::EnsureString(field->name());
         bool res = decode_name(orig_name, field_name_str_temp); 
         const std::string& field_name_str = (res ? field_name_str_temp : 
orig_name);
 
@@ -593,7 +595,7 @@ bool JsonValueToProtoMessage(const 
BUTIL_RAPIDJSON_NAMESPACE::Value& json_value,
                 json_value.FindMember(field_name_str.data());
         if (member == json_value.MemberEnd()) {
             if (field->is_required()) {
-                J2PERROR(err, "Missing required field: %s", 
field->full_name().c_str());
+                J2PERROR(err, "Missing required field: %s", 
butil::EnsureString(field->full_name()).c_str());
                 return false;
             }
             continue; 
@@ -604,7 +606,7 @@ bool JsonValueToProtoMessage(const 
BUTIL_RAPIDJSON_NAMESPACE::Value& json_value,
                 json_value.FindMember(field_name_str.data());
         if (member == NULL) {
             if (field->is_required()) {
-                J2PERROR(err, "Missing required field: %s", 
field->full_name().c_str());
+                J2PERROR(err, "Missing required field: %s", 
butil::EnsureString(field->full_name()).c_str());
                 return false;
             }
             continue; 
diff --git a/src/json2pb/pb_to_json.cpp b/src/json2pb/pb_to_json.cpp
index f2322267..b9d01c2a 100644
--- a/src/json2pb/pb_to_json.cpp
+++ b/src/json2pb/pb_to_json.cpp
@@ -30,8 +30,10 @@
 #include "json2pb/rapidjson.h"
 #include "json2pb/pb_to_json.h"
 #include "json2pb/protobuf_type_resolver.h"
-#include "butil/iobuf.h"
+
 #include "butil/base64.h"
+#include "butil/iobuf.h"
+#include "butil/strings/string_util.h"
 
 namespace json2pb {
 
@@ -172,7 +174,7 @@ bool PbToJsonConverter::Convert(const 
google::protobuf::Message& message, Handle
         if (!field->is_repeated() && !reflection->HasField(message, field)) {
             // Field that has not been set
             if (field->is_required()) {
-                _error = "Missing required field: " + field->full_name();
+                _error = "Missing required field: " + 
butil::EnsureString(field->full_name());
                 return false;
             }
             // Whether dumps default fields
@@ -186,7 +188,7 @@ bool PbToJsonConverter::Convert(const 
google::protobuf::Message& message, Handle
             continue;
         }
 
-        const std::string& orig_name = field->name();
+        const std::string orig_name = butil::EnsureString(field->name());
         bool decoded = decode_name(orig_name, field_name_str); 
         const std::string& name = decoded ? field_name_str : orig_name;
         handler.Key(name.data(), name.size(), false);
@@ -205,7 +207,7 @@ bool PbToJsonConverter::Convert(const 
google::protobuf::Message& message, Handle
 
         // Write a json object corresponding to hold protobuf map
         // such as {"key": value, ...}
-        const std::string& orig_name = map_desc->name();
+        const std::string orig_name = butil::EnsureString(map_desc->name());
         bool decoded = decode_name(orig_name, field_name_str);
         const std::string& name = decoded ? field_name_str : orig_name;
         handler.Key(name.data(), name.size(), false);
@@ -306,8 +308,8 @@ bool PbToJsonConverter::_PbFieldToJson(
             handler.StartArray();
             if (_option.enum_option == OUTPUT_ENUM_BY_NAME) {
                 for (int index = 0; index < field_size; ++index) { 
-                    const std::string& enum_name = reflection->GetRepeatedEnum(
-                        message, field, index)->name();
+                    const std::string enum_name = 
butil::EnsureString(reflection->GetRepeatedEnum(
+                        message, field, index)->name());
                     handler.String(enum_name.data(), enum_name.size(), false);
                 }
             } else {
@@ -321,7 +323,7 @@ bool PbToJsonConverter::_PbFieldToJson(
         } else {
             if (_option.enum_option == OUTPUT_ENUM_BY_NAME) {
                 const std::string& enum_name =
-                        reflection->GetEnum(message, field)->name();
+                        butil::EnsureString(reflection->GetEnum(message, 
field)->name());
                 handler.String(enum_name.data(), enum_name.size(), false);
             } else {
                 handler.AddInt(reflection->GetEnum(message, field)->number());
diff --git a/src/json2pb/pb_to_json.h b/src/json2pb/pb_to_json.h
index 8de63517..4dda3a76 100644
--- a/src/json2pb/pb_to_json.h
+++ b/src/json2pb/pb_to_json.h
@@ -93,7 +93,11 @@ bool ProtoMessageToJson(const google::protobuf::Message& 
message,
                         std::string* error = NULL);
 
 // See <google/protobuf/util/json_util.h> for details.
+#if GOOGLE_PROTOBUF_VERSION >= 6030000
+using Pb2ProtoJsonOptions = google::protobuf::util::JsonPrintOptions;
+#else
 using Pb2ProtoJsonOptions = google::protobuf::util::JsonOptions;
+#endif
 
 #if GOOGLE_PROTOBUF_VERSION >= 5026002
 #define AlwaysPrintPrimitiveFields(options) 
options.always_print_fields_with_no_presence
diff --git a/src/json2pb/protobuf_map.cpp b/src/json2pb/protobuf_map.cpp
index f552bf62..75535234 100644
--- a/src/json2pb/protobuf_map.cpp
+++ b/src/json2pb/protobuf_map.cpp
@@ -38,12 +38,12 @@ bool IsProtobufMap(const FieldDescriptor* field) {
     if (NULL == key_desc
         || key_desc->is_repeated()
         || key_desc->cpp_type() != FieldDescriptor::CPPTYPE_STRING
-        || strcmp(KEY_NAME, key_desc->name().c_str()) != 0) {
+        || key_desc->name() != KEY_NAME) {
         return false;
     }
     const FieldDescriptor* value_desc = entry_desc->field(VALUE_INDEX);
     if (NULL == value_desc
-        || strcmp(VALUE_NAME, value_desc->name().c_str()) != 0) {
+        || value_desc->name() != VALUE_NAME) {
         return false;
     }
     return true;
diff --git a/src/json2pb/protobuf_type_resolver.h 
b/src/json2pb/protobuf_type_resolver.h
index a73a4231..7eff6c61 100644
--- a/src/json2pb/protobuf_type_resolver.h
+++ b/src/json2pb/protobuf_type_resolver.h
@@ -23,8 +23,9 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/util/type_resolver_util.h>
-#include "butil/string_printf.h"
 #include "butil/memory/singleton_on_pthread_once.h"
+#include "butil/string_printf.h"
+#include "butil/strings/string_util.h"
 
 namespace json2pb {
 
@@ -32,7 +33,7 @@ namespace json2pb {
 
 inline std::string GetTypeUrl(const google::protobuf::Message& message) {
     return butil::string_printf(PROTOBUF_TYPE_URL_PREFIX"/%s",
-                                message.GetDescriptor()->full_name().c_str());
+                                
butil::EnsureString(message.GetDescriptor()->full_name()).c_str());
 }
 
 // unique_ptr deleter for TypeResolver only deletes the object
diff --git a/src/mcpack2pb/generator.cpp b/src/mcpack2pb/generator.cpp
index 0fb78936..fe47fb33 100644
--- a/src/mcpack2pb/generator.cpp
+++ b/src/mcpack2pb/generator.cpp
@@ -24,16 +24,18 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/plugin.h>
-#include "butil/string_printf.h"
+
 #include "butil/file_util.h"
-#include "mcpack2pb/mcpack2pb.h"
+#include "butil/string_printf.h"
+#include "butil/strings/string_util.h"
 #include "idl_options.pb.h"
+#include "mcpack2pb/mcpack2pb.h"
 
 namespace mcpack2pb {
 
-const std::string& get_idl_name(const google::protobuf::FieldDescriptor* f) {
-    const std::string& real_name = f->options().GetExtension(idl_name);
-    return real_name.empty() ? f->name() : real_name;
+const std::string get_idl_name(const google::protobuf::FieldDescriptor* f) {
+    const std::string real_name = 
butil::EnsureString(f->options().GetExtension(idl_name));
+    return real_name.empty() ? butil::EnsureString(f->name()) : real_name;
 }
 
 bool is_integral_type(ConvertibleIdlType type) {
@@ -52,7 +54,7 @@ bool is_integral_type(ConvertibleIdlType type) {
     }
 }
 
-const char* field_to_string(const google::protobuf::FieldDescriptor* f) {
+const std::string field_to_string(const google::protobuf::FieldDescriptor* f) {
     switch (f->type()) {
     case google::protobuf::FieldDescriptor::TYPE_DOUBLE:   return "double";
     case google::protobuf::FieldDescriptor::TYPE_FLOAT:    return "float";
@@ -65,11 +67,11 @@ const char* field_to_string(const 
google::protobuf::FieldDescriptor* f) {
     case google::protobuf::FieldDescriptor::TYPE_STRING:   return "string";
     case google::protobuf::FieldDescriptor::TYPE_GROUP:
     case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
-        return f->message_type()->name().c_str();
+        return butil::EnsureString(f->message_type()->name());
     case google::protobuf::FieldDescriptor::TYPE_BYTES:    return "bytes";
     case google::protobuf::FieldDescriptor::TYPE_UINT32:   return "uint32";
     case google::protobuf::FieldDescriptor::TYPE_ENUM:
-        return f->enum_type()->name().c_str();
+        return butil::EnsureString(f->enum_type()->name());
     case google::protobuf::FieldDescriptor::TYPE_SFIXED32: return "sfixed32";
     case google::protobuf::FieldDescriptor::TYPE_SFIXED64: return "sfixed64";
     case google::protobuf::FieldDescriptor::TYPE_SINT32:   return "sint32";
@@ -269,8 +271,8 @@ static bool generate_parsing(const 
google::protobuf::Descriptor* d,
                              std::set<std::string> & ref_msgs,
                              std::set<std::string> & ref_maps,
                              google::protobuf::io::Printer& impl) {
-    std::string var_name = mcpack2pb::to_var_name(d->full_name());
-    std::string cpp_name = mcpack2pb::to_cpp_name(d->full_name());
+    std::string var_name = 
mcpack2pb::to_var_name(butil::EnsureString(d->full_name()));
+    std::string cpp_name = 
mcpack2pb::to_cpp_name(butil::EnsureString(d->full_name()));
     ref_msgs.insert(var_name);
 
     impl.Print("\n// $msg$ from mcpack\n", "msg", d->full_name());
@@ -338,7 +340,7 @@ static bool generate_parsing(const 
google::protobuf::Descriptor* d,
                     "  return false;\n"                                        
         
                     "}\n"
                     , "msg", cpp_name
-                    , "enum", to_cpp_name(f->enum_type()->full_name())
+                    , "enum", 
to_cpp_name(butil::EnsureString(f->enum_type()->full_name()))
                     , "lcfield", f->lowercase_name());
                 break;
             case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
@@ -380,8 +382,8 @@ static bool generate_parsing(const 
google::protobuf::Descriptor* d,
                     , "lcfield", f->lowercase_name());
                 break;
             case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
-                std::string var_name2 = 
mcpack2pb::to_var_name(f->message_type()->full_name());
-                std::string cpp_name2 = 
mcpack2pb::to_cpp_name(f->message_type()->full_name());
+                std::string var_name2 = 
mcpack2pb::to_var_name(butil::EnsureString(f->message_type()->full_name()));
+                std::string cpp_name2 = 
mcpack2pb::to_cpp_name(butil::EnsureString(f->message_type()->full_name()));
                 if (is_map_entry(f->message_type())) {
                     ref_maps.insert(var_name2);
                     impl.Print(
@@ -544,7 +546,7 @@ static bool generate_parsing(const 
google::protobuf::Descriptor* d,
                     "  return value.stream()->good();\n"
                     "}\n"
                     , "msg", cpp_name
-                    , "enum", to_cpp_name(f->enum_type()->full_name())
+                    , "enum", 
to_cpp_name(butil::EnsureString(f->enum_type()->full_name()))
                     , "lcfield", f->lowercase_name());
                 break;
             case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
@@ -566,7 +568,7 @@ static bool generate_parsing(const 
google::protobuf::Descriptor* d,
                     , "lcfield", f->lowercase_name());
                 break;
             case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
-                std::string var_name2 = 
mcpack2pb::to_var_name(f->message_type()->full_name());
+                std::string var_name2 = 
mcpack2pb::to_var_name(butil::EnsureString(f->message_type()->full_name()));
                 ref_msgs.insert(var_name2);
                 impl.Print(
                     "{\n"
@@ -858,8 +860,8 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                                  std::set<std::string> & ref_msgs,
                                  std::set<std::string> & ref_maps,
                                  google::protobuf::io::Printer & impl) {
-    std::string var_name = mcpack2pb::to_var_name(d->full_name());
-    std::string cpp_name = mcpack2pb::to_cpp_name(d->full_name());
+    std::string var_name = 
mcpack2pb::to_var_name(butil::EnsureString(d->full_name()));
+    std::string cpp_name = 
mcpack2pb::to_cpp_name(butil::EnsureString(d->full_name()));
     ref_msgs.insert(var_name);
     impl.Print(
         "void serialize_$vmsg$_body(\n"
@@ -946,8 +948,8 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                     return false;
                 }
                 const google::protobuf::Descriptor* msg2 = f->message_type();
-                std::string var_name2 = 
mcpack2pb::to_var_name(msg2->full_name());
-                std::string cpp_name2 = 
mcpack2pb::to_cpp_name(msg2->full_name());
+                std::string var_name2 = 
mcpack2pb::to_var_name(butil::EnsureString(msg2->full_name()));
+                std::string cpp_name2 = 
mcpack2pb::to_cpp_name(butil::EnsureString(msg2->full_name()));
                 if (is_map_entry(msg2)) {
                     ref_maps.insert(var_name2);
                     impl.Print(
@@ -988,7 +990,7 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                         break;
                     case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
                         std::string var_name3 = mcpack2pb::to_var_name(
-                            value_desc->message_type()->full_name());
+                            
butil::EnsureString(value_desc->message_type()->full_name()));
                         ref_msgs.insert(var_name3);
                         impl.Print(
                             "  serializer.begin_object(pair.key());\n"
@@ -1048,7 +1050,7 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                                        << to_mcpack_typestr(cit2, f2) << " 
(idl)";
                             return false;
                         }
-                        std::string var_name3 = 
mcpack2pb::to_var_name(f2->message_type()->full_name());
+                        std::string var_name3 = 
mcpack2pb::to_var_name(butil::EnsureString(f2->message_type()->full_name()));
                         ref_msgs.insert(var_name3);
                         if (f2->is_repeated()) {
                             impl.Print(
@@ -1091,7 +1093,7 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                         }
                     } else if (f2->is_repeated()) {
                         const std::string msgstr = butil::string_printf(
-                            "msg.%s(i)", f->lowercase_name().c_str());
+                            "msg.%s(i)", 
butil::EnsureString(f->lowercase_name()).c_str());
                         switch (f2->cpp_type()) {
                         case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
                         case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
@@ -1141,7 +1143,7 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                         }
                     } else {
                         const std::string msgstr = butil::string_printf(
-                            "msg.%s(i)", f->lowercase_name().c_str());
+                            "msg.%s(i)", 
butil::EnsureString(f->lowercase_name()).c_str());
                         switch (f2->cpp_type()) {
                         case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
                         case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
@@ -1239,7 +1241,7 @@ static bool generate_serializing(const 
google::protobuf::Descriptor* d,
                                << to_mcpack_typestr(cit, f) << " (idl)";
                     return false;
                 }
-                std::string var_name2 = 
mcpack2pb::to_var_name(f->message_type()->full_name());
+                std::string var_name2 = 
mcpack2pb::to_var_name(butil::EnsureString(f->message_type()->full_name()));
                 ref_msgs.insert(var_name2);
                 impl.Print("if (msg.has_$lcfield$()) {\n"
                            "  serializer.begin_object(\"$field$\");\n"
@@ -1298,8 +1300,8 @@ static std::string 
protobuf_style_normalize_filename(const std::string & fname)
 static bool generate_registration(
     const google::protobuf::FileDescriptor* file,
     google::protobuf::io::Printer & impl) {
-    const std::string cpp_ns = to_cpp_name(file->package());
-    std::string norm_fname = protobuf_style_normalize_filename(file->name());
+    const std::string cpp_ns = 
to_cpp_name(butil::EnsureString(file->package()));
+    std::string norm_fname = 
protobuf_style_normalize_filename(butil::EnsureString(file->name()));
     impl.Print(
         "\n// register all message handlers\n"
         "struct RegisterMcpackFunctions_$norm_fname$ {\n"
@@ -1309,7 +1311,7 @@ static bool generate_registration(
     impl.Indent();
     for (int i = 0; i < file->message_type_count(); ++i) {
         const google::protobuf::Descriptor* d = file->message_type(i);
-        std::string var_name = mcpack2pb::to_var_name(d->full_name());
+        std::string var_name = 
mcpack2pb::to_var_name(butil::EnsureString(d->full_name()));
 
         impl.Print(
             "\n"
@@ -1359,8 +1361,8 @@ bool McpackToProtobuf::Generate(const 
google::protobuf::FileDescriptor* file,
         // skip the file.
         return true;
     }
-    
-    std::string cpp_name = file->name();
+
+    std::string cpp_name = butil::EnsureString(file->name());
     const size_t pos = cpp_name.find_last_of('.');
     if (pos == std::string::npos) {
         ::butil::string_printf(error, "Bad filename=%s", cpp_name.c_str());
@@ -1391,16 +1393,16 @@ bool McpackToProtobuf::Generate(const 
google::protobuf::FileDescriptor* file,
         if (!generate_parsing(d, ref_msgs, ref_maps, gimpl_printer)) {
             ::butil::string_printf(
                 error, "Fail to generate parsing code for %s",
-                d->full_name().c_str());
+                butil::EnsureString(d->full_name()).c_str());
             return false;
         }
         if (!generate_serializing(d, ref_msgs, ref_maps, gimpl_printer)) {
             ::butil::string_printf(
                 error, "Fail to generate serializing code for %s",
-                d->full_name().c_str());
+                butil::EnsureString(d->full_name()).c_str());
             return false;
         }
-        std::string var_name = mcpack2pb::to_var_name(d->full_name());
+        std::string var_name = 
mcpack2pb::to_var_name(butil::EnsureString(d->full_name()));
         gdecl_printer.Print(
             "::mcpack2pb::FieldMap* g_$vmsg$_fields = NULL;\n"
             , "vmsg", var_name);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to