CPP: Support ICU versions built without support for std::string.
authorphilip.liard@gmail.com <philip.liard@gmail.com@ee073f10-1060-11df-b6a4-87a95322a99c>
Thu, 10 May 2012 15:59:25 +0000 (15:59 +0000)
committerphilip.liard@gmail.com <philip.liard@gmail.com@ee073f10-1060-11df-b6a4-87a95322a99c>
Thu, 10 May 2012 15:59:25 +0000 (15:59 +0000)
This is the case on Android.

git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@452 ee073f10-1060-11df-b6a4-87a95322a99c

cpp/CMakeLists.txt
cpp/src/phonenumbers/regexp_adapter_icu.cc
cpp/src/phonenumbers/string_byte_sink.cc [new file with mode: 0644]
cpp/src/phonenumbers/string_byte_sink.h [new file with mode: 0644]

index 79ff593..5d0a442 100644 (file)
@@ -166,6 +166,7 @@ set (
   "src/phonenumbers/phonenumber.pb.cc"   # Generated by Protocol Buffers.
   "src/phonenumbers/phonenumberutil.cc"
   "src/phonenumbers/regexp_cache.cc"
+  "src/phonenumbers/string_byte_sink.cc"
   "src/phonenumbers/stringutil.cc"
   "src/phonenumbers/unicodestring.cc"
   "src/phonenumbers/utf/rune.c"
index bd2c98b..8ad361a 100644 (file)
 // Author: George Yakovlev
 //         Philippe Liard
 
+// Note that we don't use features of ICU that depend on std::string (e.g.
+// UnicodeString::toUTF8String()) to support clients that build ICU without
+// -DU_HAVE_STD_STRING.
+
 #include "phonenumbers/regexp_adapter_icu.h"
 
 #include <stddef.h>
 #include <string>
 
 #include <unicode/regex.h>
+#include <unicode/stringpiece.h>
 #include <unicode/unistr.h>
 
 #include "base/basictypes.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "phonenumbers/default_logger.h"
+#include "phonenumbers/string_byte_sink.h"
 
 namespace i18n {
 namespace phonenumbers {
@@ -40,10 +46,18 @@ namespace {
 // Converts UnicodeString 'source' to a UTF8-formatted std::string.
 string UnicodeStringToUtf8String(const UnicodeString& source) {
   string data;
-  source.toUTF8String<string>(data);
+  StringByteSink sink(&data);
+  source.toUTF8(sink);
   return data;
 }
 
+// Converts UTF8-formatted std::string 'source' to a UnicodeString.
+UnicodeString Utf8StringToUnicodeString(const string& source) {
+  // Note that we don't use icu::StringPiece(const string&).
+  return UnicodeString::fromUTF8(
+      icu::StringPiece(source.c_str(), source.size()));
+}
+
 }  // namespace
 
 // Implementation of the abstract classes RegExpInput and RegExp using ICU
@@ -53,7 +67,7 @@ string UnicodeStringToUtf8String(const UnicodeString& source) {
 class IcuRegExpInput : public RegExpInput {
  public:
   explicit IcuRegExpInput(const string& utf8_input)
-      : utf8_input_(UnicodeString::fromUTF8(utf8_input)),
+      : utf8_input_(Utf8StringToUnicodeString(utf8_input)),
         position_(0) {}
 
   virtual ~IcuRegExpInput() {}
@@ -92,7 +106,7 @@ class IcuRegExp : public RegExp {
     UParseError parse_error;
     UErrorCode status = U_ZERO_ERROR;
     utf8_regexp_.reset(RegexPattern::compile(
-        UnicodeString::fromUTF8(utf8_regexp), 0, parse_error, status));
+        Utf8StringToUnicodeString(utf8_regexp), 0, parse_error, status));
     if (U_FAILURE(status)) {
       // The provided regular expressions should compile correctly.
       LOG(ERROR) << "Error compiling regular expression: " << utf8_regexp;
@@ -178,9 +192,9 @@ class IcuRegExp : public RegExp {
     }
     UnicodeString result = global
         ? matcher->replaceAll(
-            UnicodeString::fromUTF8(replacement_string), status)
+            Utf8StringToUnicodeString(replacement_string), status)
         : matcher->replaceFirst(
-            UnicodeString::fromUTF8(replacement_string), status);
+            Utf8StringToUnicodeString(replacement_string), status);
     if (U_FAILURE(status)) {
       return false;
     }
diff --git a/cpp/src/phonenumbers/string_byte_sink.cc b/cpp/src/phonenumbers/string_byte_sink.cc
new file mode 100644 (file)
index 0000000..9c7ab41
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2012 The Libphonenumber Authors
+//
+// 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.
+
+#include "phonenumbers/string_byte_sink.h"
+
+#include <string>
+
+using std::string;
+
+namespace i18n {
+namespace phonenumbers {
+
+StringByteSink::StringByteSink(string* dest) : dest_(dest) {}
+
+StringByteSink::~StringByteSink() {}
+
+void StringByteSink::Append(const char* data, int32_t n) {
+  dest_->append(data, n);
+}
+
+}  // namespace phonenumbers
+}  // namespace i18n
diff --git a/cpp/src/phonenumbers/string_byte_sink.h b/cpp/src/phonenumbers/string_byte_sink.h
new file mode 100644 (file)
index 0000000..305be18
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2012 The Libphonenumber Authors
+//
+// 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.
+
+// We need this because when ICU is built without std::string support,
+// UnicodeString::toUTF8String() is not available. The alternative,
+// UnicodeString::toUTF8(), requires an implementation of a string byte sink.
+// See unicode/unistr.h and unicode/bytestream.h in ICU for more details.
+
+#include <string>
+
+#include <unicode/unistr.h>
+
+namespace i18n {
+namespace phonenumbers {
+
+class StringByteSink : public icu::ByteSink {
+ public:
+  // Constructs a ByteSink that will append bytes to the dest string.
+  explicit StringByteSink(std::string* dest);
+  virtual ~StringByteSink();
+
+  virtual void Append(const char* data, int32_t n);
+
+ private:
+  std::string* const dest_;
+};
+
+}  // namespace phonenumbers
+}  // namespace i18n