change impl to explicitly store length as u32, rather than size_t, so we keep a packed struct on 64bit machines

BUG=

Review URL: https://codereview.chromium.org/16356006

git-svn-id: http://skia.googlecode.com/svn/trunk@9436 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp
index a069a7e..3fae07e 100644
--- a/src/core/SkString.cpp
+++ b/src/core/SkString.cpp
@@ -189,15 +189,36 @@
 
 #define SizeOfRec()     (gEmptyRec.data() - (const char*)&gEmptyRec)
 
+static uint32_t trim_size_t_to_u32(size_t value) {
+    if (sizeof(size_t) > sizeof(uint32_t)) {
+        if (value > SK_MaxU32) {
+            value = SK_MaxU32;
+        }
+    }
+    return (uint32_t)value;
+}
+
+static size_t check_add32(size_t base, size_t extra) {
+    SkASSERT(base <= SK_MaxU32);
+    if (sizeof(size_t) > sizeof(uint32_t)) {
+        if (base + extra > SK_MaxU32) {
+            extra = SK_MaxU32 - base;
+        }
+    }
+    return extra;
+}
+
 SkString::Rec* SkString::AllocRec(const char text[], size_t len) {
     Rec* rec;
 
     if (0 == len) {
         rec = const_cast<Rec*>(&gEmptyRec);
     } else {
+        len = trim_size_t_to_u32(len);
+
         // add 1 for terminating 0, then align4 so we can have some slop when growing the string
         rec = (Rec*)sk_malloc_throw(SizeOfRec() + SkAlign4(len + 1));
-        rec->fLength = len;
+        rec->fLength = SkToU32(len);
         rec->fRefCnt = 1;
         if (text) {
             memcpy(rec->data(), text, len);
@@ -356,6 +377,8 @@
 }
 
 void SkString::set(const char text[], size_t len) {
+    len = trim_size_t_to_u32(len);
+
     if (0 == len) {
         this->reset();
     } else if (1 == fRec->fRefCnt && len <= fRec->fLength) {
@@ -366,7 +389,7 @@
             memcpy(p, text, len);
         }
         p[len] = 0;
-        fRec->fLength = len;
+        fRec->fLength = SkToU32(len);
     } else if (1 == fRec->fRefCnt && (fRec->fLength >> 2) == (len >> 2)) {
         // we have spare room in the current allocation, so don't alloc a larger one
         char* p = this->writable_str();
@@ -374,7 +397,7 @@
             memcpy(p, text, len);
         }
         p[len] = 0;
-        fRec->fLength = len;
+        fRec->fLength = SkToU32(len);
     } else {
         SkString tmp(text, len);
         this->swap(tmp);
@@ -387,10 +410,12 @@
     while (src[count]) {
         count += 1;
     }
-    setUTF16(src, count);
+    this->setUTF16(src, count);
 }
 
 void SkString::setUTF16(const uint16_t src[], size_t count) {
+    count = trim_size_t_to_u32(count);
+
     if (0 == count) {
         this->reset();
     } else if (count <= fRec->fLength) {
@@ -424,6 +449,12 @@
         if (offset > length) {
             offset = length;
         }
+        
+        // Check if length + len exceeds 32bits, we trim len
+        len = check_add32(length, len);
+        if (0 == len) {
+            return;
+        }
 
         /*  If we're the only owner, and we have room in our allocation for the insert,
             do it in place, rather than allocating a new buffer.
@@ -444,7 +475,7 @@
             memcpy(dst + offset, text, len);
 
             dst[length + len] = 0;
-            fRec->fLength = length + len;
+            fRec->fLength = SkToU32(length + len);
         } else {
             /*  Seems we should use realloc here, since that is safe if it fails
                 (we have the original data), and might be faster than alloc/copy/free.