OSDN Git Service

new String8, String16 ctors to initialize empty static strings with static linkage
authorMathias Agopian <mathias@google.com>
Wed, 8 May 2013 23:04:13 +0000 (16:04 -0700)
committerMathias Agopian <mathias@google.com>
Thu, 9 May 2013 01:13:07 +0000 (18:13 -0700)
when libutils is statically linked, the ordering of the static
initializer is not guaranteed and therefore it's unsafe to use
empty static strings: e.g.:

static String8 sThisStaticStringIsNotSafe;

instead, this new constructor can be used:

static String8 sThisStaticStringIsSafe(kEmptyString);

Change-Id: Ia3daf1cab1c97d021c0ee9c2b394b5e27e8d6c0d

include/utils/String16.h
include/utils/String8.h
libs/utils/String16.cpp
libs/utils/String8.cpp

index 6d4253d..d131bfc 100644 (file)
@@ -41,7 +41,16 @@ class TextOutput;
 class String16
 {
 public:
+    /* use String16(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String16, e.g.:
+     *
+     *   static String16 sAStaticEmptyString(String16::kEmptyString);
+     *   static String16 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
                                 String16();
+    explicit                    String16(StaticLinkage);
                                 String16(const String16& o);
                                 String16(const String16& o,
                                          size_t len,
index 9426fcf..ef59470 100644 (file)
@@ -37,7 +37,16 @@ class TextOutput;
 class String8
 {
 public:
+    /* use String8(StaticLinkage) if you're statically linking against
+     * libutils and declaring an empty static String8, e.g.:
+     *
+     *   static String8 sAStaticEmptyString(String8::kEmptyString);
+     *   static String8 sAnotherStaticEmptyString(sAStaticEmptyString);
+     */
+    enum StaticLinkage { kEmptyString };
+
                                 String8();
+    explicit                    String8(StaticLinkage);
                                 String8(const String8& o);
     explicit                    String8(const char* o);
     explicit                    String8(const char* o, size_t numChars);
index c856ceb..b09b728 100644 (file)
@@ -93,6 +93,19 @@ String16::String16()
 {
 }
 
+String16::String16(StaticLinkage)
+    : mString(0)
+{
+    // this constructor is used when we can't rely on the static-initializers
+    // having run. In this case we always allocate an empty string. It's less
+    // efficient than using getEmptyString(), but we assume it's uncommon.
+
+    char16_t* data = static_cast<char16_t*>(
+            SharedBuffer::alloc(sizeof(char16_t))->data());
+    data[0] = 0;
+    mString = data;
+}
+
 String16::String16(const String16& o)
     : mString(o.mString)
 {
index 413928a..e852d77 100644 (file)
@@ -47,16 +47,12 @@ void initialize_string8();
 
 static inline char* getEmptyString()
 {
-    if (!gEmptyStringBuf) initialize_string8();
-
     gEmptyStringBuf->acquire();
     return gEmptyString;
 }
 
 void initialize_string8()
 {
-    if (gEmptyStringBuf) return;
-
     // HACK: This dummy dependency forces linking libutils Static.cpp,
     // which is needed to initialize String8/String16 classes.
     // These variables are named for Darwin, but are needed elsewhere too,
@@ -146,6 +142,19 @@ String8::String8()
 {
 }
 
+String8::String8(StaticLinkage)
+    : mString(0)
+{
+    // this constructor is used when we can't rely on the static-initializers
+    // having run. In this case we always allocate an empty string. It's less
+    // efficient than using getEmptyString(), but we assume it's uncommon.
+
+    char* data = static_cast<char*>(
+            SharedBuffer::alloc(sizeof(char))->data());
+    data[0] = 0;
+    mString = data;
+}
+
 String8::String8(const String8& o)
     : mString(o.mString)
 {