Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ffe7986d authored by vichang's avatar vichang Committed by Gerrit Code Review
Browse files

Merge "Copy StringPool to framework"

parents 0a632252 246c8c13
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.util;

import libcore.internal.StringPool;
import com.android.internal.util.StringPool;

import java.io.Closeable;
import java.io.EOFException;
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.
 */

package com.android.internal.util;

/**
 * A pool of string instances. Unlike the {@link String#intern() VM's
 * interned strings}, this pool provides no guarantee of reference equality.
 * It is intended only to save allocations. This class is not thread safe.
 *
 * @hide
 */
public final class StringPool {

    private final String[] mPool = new String[512];

    /**
     * Constructs string pool.
     */
    public StringPool() {
    }

    private static boolean contentEquals(String s, char[] chars, int start, int length) {
        if (s.length() != length) {
            return false;
        }
        for (int i = 0; i < length; i++) {
            if (chars[start + i] != s.charAt(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns a string equal to {@code new String(array, start, length)}.
     *
     * @param array  buffer containing string chars
     * @param start  offset in {@code array} where string starts
     * @param length length of string
     * @return string equal to {@code new String(array, start, length)}
     */
    public String get(char[] array, int start, int length) {
        // Compute an arbitrary hash of the content
        int hashCode = 0;
        for (int i = start; i < start + length; i++) {
            hashCode = (hashCode * 31) + array[i];
        }

        // Pick a bucket using Doug Lea's supplemental secondaryHash function (from HashMap)
        hashCode ^= (hashCode >>> 20) ^ (hashCode >>> 12);
        hashCode ^= (hashCode >>> 7) ^ (hashCode >>> 4);
        int index = hashCode & (mPool.length - 1);

        String pooled = mPool[index];
        if (pooled != null && contentEquals(pooled, array, start, length)) {
            return pooled;
        }

        String result = new String(array, start, length);
        mPool[index] = result;
        return result;
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.
 */

package com.android.internal.util;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;

@SmallTest
public final class StringPoolTest extends AndroidTestCase {

    public void testStringPool() {
        StringPool stringPool = new StringPool();
        String bcd = stringPool.get(new char[] { 'a', 'b', 'c', 'd', 'e' }, 1, 3);
        assertEquals("bcd", bcd);
        assertSame(bcd, stringPool.get(new char[] { 'a', 'b', 'c', 'd', 'e' }, 1, 3));
    }

    public void testHashCollision() {
        StringPool stringPool = new StringPool();
        char[] a = { (char) 1, (char) 0 };
        char[] b = { (char) 0, (char) 31 };
        assertEquals(new String(a).hashCode(), new String(b).hashCode());

        String aString = stringPool.get(a, 0, 2);
        assertEquals(new String(a), aString);
        String bString = stringPool.get(b, 0, 2);
        assertEquals(new String(b), bString);
        assertSame(bString, stringPool.get(b, 0, 2));
        assertNotSame(aString, stringPool.get(a, 0, 2));
    }
}