diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 95110bbe8..87a36f621 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -73,8 +73,8 @@ find_required_library (PROTOBUF google/protobuf/message_lite.h protobuf "Google Protocol Buffers") check_library_version (PC_PROTOBUF protobuf 2.4) -find_required_library (ICU unicode/unistr.h icui18n "ICU") -check_library_version (PC_ICU icui18n 4.4) +find_required_library (ICU unicode/uchar.h icuuc "ICU") +check_library_version (PC_ICU icuuc 4.4) find_required_program (PROTOC protoc "Google Protocol Buffers compiler (protoc)") @@ -82,6 +82,25 @@ find_required_program (PROTOC protoc find_required_program (JAVA java "Java Runtime Environment") +if (APPLE) + FIND_LIBRARY (COREFOUNDATION_LIB CoreFoundation) + FIND_LIBRARY (FOUNDATION_LIB Foundation) +endif () + +INCLUDE (CheckIncludeFileCXX) +CHECK_INCLUDE_FILE_CXX ("tr1/unordered_map" HAVE_CXX_TR1_UNORDERED_MAP) + +if (HAVE_CXX_TR1_UNORDERED_MAP) + add_definitions ("-DUSE_TR1_UNORDERED_MAP") +else () + CHECK_INCLUDE_FILE_CXX (hash_map HAVE_CXX_HASH_MAP) + if (HAVE_CXX_HASH_MAP) + add_definitions ("-DUSE_HASH_MAP") + else () + print_error ("C++ map class" "tr1/unordered_map or hash_map") + endif () +endif () + # Add protoc (Protocol Buffers compiler) target. set (RESOURCES_DIR "${CMAKE_SOURCE_DIR}/../resources") @@ -189,9 +208,16 @@ if (UNIX) # The next flags are needed by base/ source files to compile low level code # needed by Singleton. - add_definitions ("-DCOMPILER_GCC -DOS_POSIX -DOS_LINUX") + add_definitions ("-DCOMPILER_GCC -DOS_POSIX") - if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86.*") + if (APPLE) + add_definitions ("-DOS_MACOSX") + else () + add_definitions ("-DOS_LINUX") + endif () + + if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86.*" OR + ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i386") add_definitions ("-DARCH_CPU_X86_FAMILY") # Add GCC specific sources. list (APPEND SOURCES "src/base/atomicops_internals_x86_gcc.cc") @@ -208,6 +234,13 @@ if (UNIX) "src/base/threading/platform_thread_posix.cc" "src/base/threading/thread_local_posix.cc" ) + + if (APPLE) + list ( + APPEND SOURCES + "src/base/threading/platform_thread_mac.mm" + ) + endif () else (WIN32) # TODO: add Windows support (define COMPILER_MSVC, OS_WIN). list ( @@ -227,6 +260,10 @@ add_dependencies (phonenumber generate-sources) target_link_libraries (phonenumber ${RE2_LIB} ${PROTOBUF_LIB} ${ICU_LIB}) +if (APPLE) + target_link_libraries (phonenumber ${COREFOUNDATION_LIB} ${FOUNDATION_LIB}) +endif () + # Tests. set (TEST_SOURCES "src/phonenumberutil_test.cc" diff --git a/cpp/src/base/atomicops.h b/cpp/src/base/atomicops.h index 445696bec..4fc3e1bde 100644 --- a/cpp/src/base/atomicops.h +++ b/cpp/src/base/atomicops.h @@ -135,7 +135,7 @@ Atomic64 Release_Load(volatile const Atomic64* ptr); // Include our platform specific implementation. #if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) #include "base/atomicops_internals_x86_msvc.h" -#elif defined(OS_MACOSX) && defined(ARCH_CPU_X86_FAMILY) +#elif defined(OS_MACOSX) #include "base/atomicops_internals_x86_macosx.h" #elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY) #include "base/atomicops_internals_x86_gcc.h" diff --git a/cpp/src/base/basictypes.h b/cpp/src/base/basictypes.h index 74c046075..f743146be 100644 --- a/cpp/src/base/basictypes.h +++ b/cpp/src/base/basictypes.h @@ -17,7 +17,34 @@ #include // For intptr_t. #endif -typedef signed char schar; +#ifdef INT64_MAX + +// INT64_MAX is defined if C99 stdint.h is included; use the +// native types if available. +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; + +const uint8 kuint8max = UINT8_MAX; +const uint16 kuint16max = UINT16_MAX; +const uint32 kuint32max = UINT32_MAX; +const uint64 kuint64max = UINT64_MAX; +const int8 kint8min = INT8_MIN; +const int8 kint8max = INT8_MAX; +const int16 kint16min = INT16_MIN; +const int16 kint16max = INT16_MAX; +const int32 kint32min = INT32_MIN; +const int32 kint32max = INT32_MAX; +const int64 kint64min = INT64_MIN; +const int64 kint64max = INT64_MAX; + +#else // !INT64_MAX + typedef signed char int8; typedef short int16; // TODO: Remove these type guards. These are to avoid conflicts with @@ -57,12 +84,6 @@ typedef unsigned long uint64; typedef unsigned long long uint64; #endif -// A type to represent a Unicode code-point value. As of Unicode 4.0, -// such values require up to 21 bits. -// (For type-checking on pointers, make this explicitly signed, -// and it should always be the signed version of whatever int32 is.) -typedef signed int char32; - const uint8 kuint8max = (( uint8) 0xFF); const uint16 kuint16max = ((uint16) 0xFFFF); const uint32 kuint32max = ((uint32) 0xFFFFFFFF); @@ -76,6 +97,16 @@ const int32 kint32max = (( int32) 0x7FFFFFFF); const int64 kint64min = (( int64) GG_LONGLONG(0x8000000000000000)); const int64 kint64max = (( int64) GG_LONGLONG(0x7FFFFFFFFFFFFFFF)); +#endif // !INT64_MAX + +typedef signed char schar; + +// A type to represent a Unicode code-point value. As of Unicode 4.0, +// such values require up to 21 bits. +// (For type-checking on pointers, make this explicitly signed, +// and it should always be the signed version of whatever int32 is.) +typedef signed int char32; + // A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ diff --git a/cpp/src/base/threading/platform_thread_mac.mm b/cpp/src/base/threading/platform_thread_mac.mm new file mode 100644 index 000000000..d77307c56 --- /dev/null +++ b/cpp/src/base/threading/platform_thread_mac.mm @@ -0,0 +1,54 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/threading/platform_thread.h" + +#import +#include + +#include "base/logging.h" + +namespace base { + +// If Cocoa is to be used on more than one thread, it must know that the +// application is multithreaded. Since it's possible to enter Cocoa code +// from threads created by pthread_thread_create, Cocoa won't necessarily +// be aware that the application is multithreaded. Spawning an NSThread is +// enough to get Cocoa to set up for multithreaded operation, so this is done +// if necessary before pthread_thread_create spawns any threads. +// +// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html +void InitThreading() { + static BOOL multithreaded = [NSThread isMultiThreaded]; + if (!multithreaded) { + // +[NSObject class] is idempotent. + [NSThread detachNewThreadSelector:@selector(class) + toTarget:[NSObject class] + withObject:nil]; + multithreaded = YES; + + DCHECK([NSThread isMultiThreaded]); + } +} + +// static +void PlatformThread::SetName(const char* name) { + // pthread_setname_np is only available in 10.6 or later, so test + // for it at runtime. + int (*dynamic_pthread_setname_np)(const char*); + *reinterpret_cast(&dynamic_pthread_setname_np) = + dlsym(RTLD_DEFAULT, "pthread_setname_np"); + if (!dynamic_pthread_setname_np) + return; + + // Mac OS X does not expose the length limit of the name, so + // hardcode it. + const int kMaxNameLength = 63; + std::string shortened_name = std::string(name).substr(0, kMaxNameLength); + // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does. + // See http://crbug.com/47058 + dynamic_pthread_setname_np(shortened_name.c_str()); +} + +} // namespace base diff --git a/cpp/src/build/build_config.h b/cpp/src/build/build_config.h index b7db7b65f..429f4b93c 100644 --- a/cpp/src/build/build_config.h +++ b/cpp/src/build/build_config.h @@ -8,4 +8,38 @@ # endif +#ifdef __APPLE__ + +# ifdef __GNUC__ +# ifndef COMPILER_GCC +# define COMPILER_GCC +# endif +# endif + +# if defined(__i386__) || defined(__x86_64__) +# ifndef ARCH_CPU_X86_FAMILY +# define ARCH_CPU_X86_FAMILY +# endif +# endif + +# ifdef __arm__ +# ifndef ARCH_CPU_ARM_FAMILY +# define ARCH_CPU_ARM_FAMILY +# endif +# endif + +# ifndef OS_MACOSX +# define OS_MACOSX +# endif + +# ifndef OS_POSIX +# define OS_POSIX +# endif + +# ifndef USE_TR1_UNORDERED_MAP +# define USE_TR1_UNORDERED_MAP +# endif + +#endif + #endif diff --git a/cpp/src/phonenumberutil.cc b/cpp/src/phonenumberutil.cc index f57ee0c60..d28db812e 100644 --- a/cpp/src/phonenumberutil.cc +++ b/cpp/src/phonenumberutil.cc @@ -27,8 +27,8 @@ #include #include #include -#include -#include +#include +#include #include "base/logging.h" #include "base/singleton.h" @@ -349,9 +349,9 @@ void FormatAccordingToFormats( bool IsNationalNumberSuffixOfTheOther(const PhoneNumber& first_number, const PhoneNumber& second_number) { const string& first_number_national_number = - SimpleItoa(first_number.national_number()); + SimpleItoa(static_cast(first_number.national_number())); const string& second_number_national_number = - SimpleItoa(second_number.national_number()); + SimpleItoa(static_cast(second_number.national_number())); // Note that HasSuffixString returns true if the numbers are equal. return HasSuffixString(first_number_national_number, second_number_national_number) || @@ -1738,35 +1738,24 @@ void PhoneNumberUtil::NormalizeDigitsOnly(string* number) { static const StringPiece empty; RE2::GlobalReplace(number, invalid_digits_pattern, empty); // Normalize all decimal digits to ASCII digits. - UParseError error; - icu::ErrorCode status; - - scoped_ptr transliterator( - icu::Transliterator::createFromRules( - "NormalizeDecimalDigits", - "[[:nv=0:]-[0]-[:^nt=de:]]>0;" - "[[:nv=1:]-[1]-[:^nt=de:]]>1;" - "[[:nv=2:]-[2]-[:^nt=de:]]>2;" - "[[:nv=3:]-[3]-[:^nt=de:]]>3;" - "[[:nv=4:]-[4]-[:^nt=de:]]>4;" - "[[:nv=5:]-[5]-[:^nt=de:]]>5;" - "[[:nv=6:]-[6]-[:^nt=de:]]>6;" - "[[:nv=7:]-[7]-[:^nt=de:]]>7;" - "[[:nv=8:]-[8]-[:^nt=de:]]>8;" - "[[:nv=9:]-[9]-[:^nt=de:]]>9;", - UTRANS_FORWARD, - error, - status - ) - ); - if (!status.isSuccess()) { - logger->Error("Error creating ICU Transliterator"); - return; + string normalized; + UnicodeText number_as_unicode; + number_as_unicode.PointToUTF8(number->data(), number->size()); + for (UnicodeText::const_iterator it = number_as_unicode.begin(); + it != number_as_unicode.end(); + ++it) { + int32_t digitValue = u_charDigitValue(*it); + if (digitValue == -1) { + // Not a decimal digit. + char utf8[4]; + int len = it.get_utf8(utf8); + normalized.append(utf8, len); + } else { + normalized.push_back('0' + digitValue); + } } - icu::UnicodeString utf16(icu::UnicodeString::fromUTF8(number->c_str())); - transliterator->transliterate(utf16); - number->clear(); - utf16.toUTF8String(*number); + + *number = normalized; } bool PhoneNumberUtil::IsAlphaNumber(const string& number) const { diff --git a/cpp/src/re2_cache.cc b/cpp/src/re2_cache.cc index 1abf95e49..c6c0a5b2b 100644 --- a/cpp/src/re2_cache.cc +++ b/cpp/src/re2_cache.cc @@ -27,6 +27,8 @@ using std::string; +#ifdef USE_HASH_MAP + // A basic text book string hash function implementation, this one taken from // The Practice of Programming (Kernighan and Pike 1999). It could be a good // idea in the future to evaluate how well it actually performs and possibly @@ -45,6 +47,8 @@ template<> struct hash { }; } // namespace __gnu_cxx +#endif + namespace i18n { namespace phonenumbers { diff --git a/cpp/src/re2_cache.h b/cpp/src/re2_cache.h index ab2e9bbf1..fb32f1c98 100644 --- a/cpp/src/re2_cache.h +++ b/cpp/src/re2_cache.h @@ -14,7 +14,7 @@ // Author: Fredrik Roubert -// RE2Cache is a simple wrapper around hash_map<> to store RE2 objects. +// RE2Cache is a simple wrapper around an STL map to store RE2 objects. // // To get a cached RE2 object for a regexp pattern string, create a ScopedAccess // object with a pointer to the cache object and the pattern string itself as @@ -30,17 +30,23 @@ #ifndef I18N_PHONENUMBERS_RE2_CACHE_H_ #define I18N_PHONENUMBERS_RE2_CACHE_H_ -#ifdef __DEPRECATED -#undef __DEPRECATED // Don't warn for using . -#endif - #include -#include #include #include "base/scoped_ptr.h" #include "base/synchronization/lock.h" +#ifdef USE_TR1_UNORDERED_MAP +# include +#elif defined(USE_HASH_MAP) +# ifndef __DEPRECATED +# define __DEPRECATED +# endif +# include +#else +# error STL map type unsupported on this platform! +#endif + namespace re2 { class RE2; } // namespace re2 @@ -50,11 +56,14 @@ namespace phonenumbers { using re2::RE2; using std::string; -using __gnu_cxx::hash_map; class RE2Cache { private: - typedef hash_map CacheImpl; +#ifdef USE_TR1_UNORDERED_MAP + typedef std::tr1::unordered_map CacheImpl; +#elif defined(USE_HASH_MAP) + typedef std::hash_map CacheImpl; +#endif public: explicit RE2Cache(size_t min_items); diff --git a/cpp/src/utf/unicodetext.cc b/cpp/src/utf/unicodetext.cc index 1039f1f60..f01f76849 100644 --- a/cpp/src/utf/unicodetext.cc +++ b/cpp/src/utf/unicodetext.cc @@ -470,7 +470,7 @@ UnicodeText::const_iterator& UnicodeText::const_iterator::operator++() { } UnicodeText::const_iterator& UnicodeText::const_iterator::operator--() { - while (UniLib::IsTrailByte(*--it_)); + while (UniLib::IsTrailByte(*--it_)) { } return *this; }