summaryrefslogtreecommitdiffstats
path: root/libutils
diff options
context:
space:
mode:
Diffstat (limited to 'libutils')
-rw-r--r--libutils/Android.mk1
-rw-r--r--libutils/BlobCache.cpp9
-rw-r--r--libutils/NativeHandle.cpp38
-rw-r--r--libutils/String8.cpp24
-rw-r--r--libutils/Unicode.cpp3
-rw-r--r--libutils/tests/BitSet_test.cpp191
6 files changed, 260 insertions, 6 deletions
diff --git a/libutils/Android.mk b/libutils/Android.mk
index 0c8625c..856a86c 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -26,6 +26,7 @@ commonSources:= \
LinearAllocator.cpp \
LinearTransform.cpp \
Log.cpp \
+ NativeHandle.cpp \
Printer.cpp \
ProcessCallStack.cpp \
PropertyMap.cpp \
diff --git a/libutils/BlobCache.cpp b/libutils/BlobCache.cpp
index f00bf14..8edb401 100644
--- a/libutils/BlobCache.cpp
+++ b/libutils/BlobCache.cpp
@@ -213,7 +213,14 @@ status_t BlobCache::flatten(void* buffer, size_t size) const {
memcpy(eheader->mData, keyBlob->getData(), keySize);
memcpy(eheader->mData + keySize, valueBlob->getData(), valueSize);
- byteOffset += align4(entrySize);
+ size_t totalSize = align4(entrySize);
+ if (totalSize > entrySize) {
+ // We have padding bytes. Those will get written to storage, and contribute to the CRC,
+ // so make sure we zero-them to have reproducible results.
+ memset(eheader->mData + keySize + valueSize, 0, totalSize - entrySize);
+ }
+
+ byteOffset += totalSize;
}
return OK;
diff --git a/libutils/NativeHandle.cpp b/libutils/NativeHandle.cpp
new file mode 100644
index 0000000..e4daca7
--- /dev/null
+++ b/libutils/NativeHandle.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * 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 <utils/NativeHandle.h>
+#include <cutils/native_handle.h>
+
+namespace android {
+
+sp<NativeHandle> NativeHandle::create(
+ native_handle_t* handle, bool ownsHandle) {
+ return handle ? new NativeHandle(handle, ownsHandle) : NULL;
+}
+
+NativeHandle::NativeHandle(native_handle_t* handle, bool ownsHandle)
+: mHandle(handle), mOwnsHandle(ownsHandle)
+{}
+
+NativeHandle::~NativeHandle() {
+ if (mOwnsHandle) {
+ native_handle_close(mHandle);
+ native_handle_delete(mHandle);
+ }
+}
+
+} // namespace android
diff --git a/libutils/String8.cpp b/libutils/String8.cpp
index 49340bb..9092cbc 100644
--- a/libutils/String8.cpp
+++ b/libutils/String8.cpp
@@ -408,6 +408,30 @@ ssize_t String8::find(const char* other, size_t start) const
return p ? p-mString : -1;
}
+bool String8::removeAll(const char* other) {
+ ssize_t index = find(other);
+ if (index < 0) return false;
+
+ char* buf = lockBuffer(size());
+ if (!buf) return false; // out of memory
+
+ size_t skip = strlen(other);
+ size_t len = size();
+ size_t tail = index;
+ while (size_t(index) < len) {
+ ssize_t next = find(other, index + skip);
+ if (next < 0) {
+ next = len;
+ }
+
+ memcpy(buf + tail, buf + index + skip, next - index - skip);
+ tail += next - index - skip;
+ index = next;
+ }
+ unlockBuffer(tail);
+ return true;
+}
+
void String8::toLower()
{
toLower(0, size());
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index fe8887d..378d2a7 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -342,7 +342,8 @@ void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst)
while (cur_utf16 < end_utf16) {
char32_t utf32;
// surrogate pairs
- if ((*cur_utf16 & 0xFC00) == 0xD800) {
+ if((*cur_utf16 & 0xFC00) == 0xD800 && (cur_utf16 + 1) < end_utf16
+ && (*(cur_utf16 + 1) & 0xFC00) == 0xDC00) {
utf32 = (*cur_utf16++ - 0xD800) << 10;
utf32 |= *cur_utf16++ - 0xDC00;
utf32 += 0x10000;
diff --git a/libutils/tests/BitSet_test.cpp b/libutils/tests/BitSet_test.cpp
index 752e56d..38b668a 100644
--- a/libutils/tests/BitSet_test.cpp
+++ b/libutils/tests/BitSet_test.cpp
@@ -23,7 +23,7 @@
namespace android {
-class BitSetTest : public testing::Test {
+class BitSet32Test : public testing::Test {
protected:
BitSet32 b1;
BitSet32 b2;
@@ -34,7 +34,7 @@ protected:
};
-TEST_F(BitSetTest, BitWiseOr) {
+TEST_F(BitSet32Test, BitWiseOr) {
b1.markBit(2);
b2.markBit(4);
@@ -49,7 +49,7 @@ TEST_F(BitSetTest, BitWiseOr) {
EXPECT_TRUE(b1.hasBit(2) && b1.hasBit(4));
EXPECT_TRUE(b2.hasBit(4) && b2.count() == 1u);
}
-TEST_F(BitSetTest, BitWiseAnd_Disjoint) {
+TEST_F(BitSet32Test, BitWiseAnd_Disjoint) {
b1.markBit(2);
b1.markBit(4);
b1.markBit(6);
@@ -65,7 +65,7 @@ TEST_F(BitSetTest, BitWiseAnd_Disjoint) {
EXPECT_TRUE(b1.hasBit(2) && b1.hasBit(4) && b1.hasBit(6));
}
-TEST_F(BitSetTest, BitWiseAnd_NonDisjoint) {
+TEST_F(BitSet32Test, BitWiseAnd_NonDisjoint) {
b1.markBit(2);
b1.markBit(4);
b1.markBit(6);
@@ -84,4 +84,187 @@ TEST_F(BitSetTest, BitWiseAnd_NonDisjoint) {
EXPECT_EQ(b2.count(), 3u);
EXPECT_TRUE(b2.hasBit(3) && b2.hasBit(6) && b2.hasBit(9));
}
+
+TEST_F(BitSet32Test, MarkFirstUnmarkedBit) {
+ b1.markBit(1);
+
+ b1.markFirstUnmarkedBit();
+ EXPECT_EQ(b1.count(), 2u);
+ EXPECT_TRUE(b1.hasBit(0) && b1.hasBit(1));
+
+ b1.markFirstUnmarkedBit();
+ EXPECT_EQ(b1.count(), 3u);
+ EXPECT_TRUE(b1.hasBit(0) && b1.hasBit(1) && b1.hasBit(2));
+}
+
+TEST_F(BitSet32Test, ClearFirstMarkedBit) {
+ b1.markBit(0);
+ b1.markBit(10);
+
+ b1.clearFirstMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(10));
+
+ b1.markBit(30);
+ b1.clearFirstMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(30));
+}
+
+TEST_F(BitSet32Test, ClearLastMarkedBit) {
+ b1.markBit(10);
+ b1.markBit(31);
+
+ b1.clearLastMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(10));
+
+ b1.markBit(5);
+ b1.clearLastMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(5));
+}
+
+TEST_F(BitSet32Test, FillAndClear) {
+ EXPECT_TRUE(b1.isEmpty());
+ for (size_t i = 0; i < 32; i++) {
+ b1.markFirstUnmarkedBit();
+ }
+ EXPECT_TRUE(b1.isFull());
+ b1.clear();
+ EXPECT_TRUE(b1.isEmpty());
+}
+
+TEST_F(BitSet32Test, GetIndexOfBit) {
+ b1.markBit(1);
+ b1.markBit(4);
+ EXPECT_EQ(b1.getIndexOfBit(1), 0);
+ EXPECT_EQ(b1.getIndexOfBit(4), 1);
+ b1.markFirstUnmarkedBit();
+ EXPECT_EQ(b1.getIndexOfBit(1), 1);
+ EXPECT_EQ(b1.getIndexOfBit(4), 2);
+}
+
+class BitSet64Test : public testing::Test {
+protected:
+ BitSet64 b1;
+ BitSet64 b2;
+ virtual void TearDown() {
+ b1.clear();
+ b2.clear();
+ }
+};
+
+
+TEST_F(BitSet64Test, BitWiseOr) {
+ b1.markBit(20);
+ b2.markBit(40);
+
+ BitSet64 tmp = b1 | b2;
+ EXPECT_EQ(tmp.count(), 2u);
+ EXPECT_TRUE(tmp.hasBit(20) && tmp.hasBit(40));
+ // Check that the operator is symmetric
+ EXPECT_TRUE((b2 | b1) == (b1 | b2));
+
+ b1 |= b2;
+ EXPECT_EQ(b1.count(), 2u);
+ EXPECT_TRUE(b1.hasBit(20) && b1.hasBit(40));
+ EXPECT_TRUE(b2.hasBit(40) && b2.count() == 1u);
+}
+TEST_F(BitSet64Test, BitWiseAnd_Disjoint) {
+ b1.markBit(20);
+ b1.markBit(40);
+ b1.markBit(60);
+
+ BitSet64 tmp = b1 & b2;
+ EXPECT_TRUE(tmp.isEmpty());
+ // Check that the operator is symmetric
+ EXPECT_TRUE((b2 & b1) == (b1 & b2));
+
+ b2 &= b1;
+ EXPECT_TRUE(b2.isEmpty());
+ EXPECT_EQ(b1.count(), 3u);
+ EXPECT_TRUE(b1.hasBit(20) && b1.hasBit(40) && b1.hasBit(60));
+}
+
+TEST_F(BitSet64Test, BitWiseAnd_NonDisjoint) {
+ b1.markBit(20);
+ b1.markBit(40);
+ b1.markBit(60);
+ b2.markBit(30);
+ b2.markBit(60);
+ b2.markBit(63);
+
+ BitSet64 tmp = b1 & b2;
+ EXPECT_EQ(tmp.count(), 1u);
+ EXPECT_TRUE(tmp.hasBit(60));
+ // Check that the operator is symmetric
+ EXPECT_TRUE((b2 & b1) == (b1 & b2));
+
+ b1 &= b2;
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_EQ(b2.count(), 3u);
+ EXPECT_TRUE(b2.hasBit(30) && b2.hasBit(60) && b2.hasBit(63));
+}
+
+TEST_F(BitSet64Test, MarkFirstUnmarkedBit) {
+ b1.markBit(1);
+
+ b1.markFirstUnmarkedBit();
+ EXPECT_EQ(b1.count(), 2u);
+ EXPECT_TRUE(b1.hasBit(0) && b1.hasBit(1));
+
+ b1.markFirstUnmarkedBit();
+ EXPECT_EQ(b1.count(), 3u);
+ EXPECT_TRUE(b1.hasBit(0) && b1.hasBit(1) && b1.hasBit(2));
+}
+
+TEST_F(BitSet64Test, ClearFirstMarkedBit) {
+ b1.markBit(0);
+ b1.markBit(10);
+
+ b1.clearFirstMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(10));
+
+ b1.markBit(50);
+ b1.clearFirstMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(50));
+}
+
+TEST_F(BitSet64Test, ClearLastMarkedBit) {
+ b1.markBit(10);
+ b1.markBit(63);
+
+ b1.clearLastMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(10));
+
+ b1.markBit(5);
+ b1.clearLastMarkedBit();
+ EXPECT_EQ(b1.count(), 1u);
+ EXPECT_TRUE(b1.hasBit(5));
+}
+
+TEST_F(BitSet64Test, FillAndClear) {
+ EXPECT_TRUE(b1.isEmpty());
+ for (size_t i = 0; i < 64; i++) {
+ b1.markFirstUnmarkedBit();
+ }
+ EXPECT_TRUE(b1.isFull());
+ b1.clear();
+ EXPECT_TRUE(b1.isEmpty());
+}
+
+TEST_F(BitSet64Test, GetIndexOfBit) {
+ b1.markBit(10);
+ b1.markBit(40);
+ EXPECT_EQ(b1.getIndexOfBit(10), 0);
+ EXPECT_EQ(b1.getIndexOfBit(40), 1);
+ b1.markFirstUnmarkedBit();
+ EXPECT_EQ(b1.getIndexOfBit(10), 1);
+ EXPECT_EQ(b1.getIndexOfBit(40), 2);
+}
+
} // namespace android