blob: 9e23205f86f9427effb7b711fcf0cf5fcc86b3fb [file] [log] [blame]
// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import static com.android.tools.r8.utils.StringUtils.EMPTY_CHAR_ARRAY;
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.Set;
public class SymbolGenerationUtils {
public enum MixedCasing {
USE_MIXED_CASE,
DONT_USE_MIXED_CASE
}
public static Set<String> PRIMITIVE_TYPE_NAMES =
Sets.newHashSet("boolean", "byte", "char", "double", "float", "int", "long", "short", "void");
// These letters are used not creating fresh names to output and not for parsing dex/class files.
private static final char[] IDENTIFIER_CHARACTERS =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private static final int NUMBER_OF_CHARACTERS = IDENTIFIER_CHARACTERS.length;
private static final int NUMBER_OF_CHARACTERS_MINUS_CAPITAL_LETTERS = NUMBER_OF_CHARACTERS - 26;
private static final int NON_ALLOWED_FIRST_CHARACTERS = 10;
public static String numberToIdentifier(int nameCount, MixedCasing mixedCasing) {
return numberToIdentifier(nameCount, mixedCasing, EMPTY_CHAR_ARRAY, false);
}
public static String numberToIdentifier(int nameCount, MixedCasing mixedCasing, char[] prefix) {
return numberToIdentifier(nameCount, mixedCasing, prefix, false);
}
public static String numberToIdentifier(
int nameCount, MixedCasing mixedCasing, char[] prefix, boolean addSemicolon) {
int size = 1;
int number = nameCount;
int maximumNumberOfCharacters =
mixedCasing == MixedCasing.USE_MIXED_CASE
? NUMBER_OF_CHARACTERS
: NUMBER_OF_CHARACTERS_MINUS_CAPITAL_LETTERS;
int firstNumberOfCharacters = maximumNumberOfCharacters - NON_ALLOWED_FIRST_CHARACTERS;
int availableCharacters = firstNumberOfCharacters;
// We first do an initial computation to find the size of the resulting string to allocate an
// array that will fit in length.
while (number > availableCharacters) {
number = (number - 1) / availableCharacters;
availableCharacters = maximumNumberOfCharacters;
size++;
}
size += addSemicolon ? 1 : 0;
char characters[] = Arrays.copyOfRange(prefix, 0, prefix.length + size);
number = nameCount;
int i = prefix.length;
availableCharacters = firstNumberOfCharacters;
int firstLetterPadding = NON_ALLOWED_FIRST_CHARACTERS;
while (number > availableCharacters) {
characters[i++] =
IDENTIFIER_CHARACTERS[(number - 1) % availableCharacters + firstLetterPadding];
number = (number - 1) / availableCharacters;
availableCharacters = maximumNumberOfCharacters;
firstLetterPadding = 0;
}
characters[i++] = IDENTIFIER_CHARACTERS[number - 1 + firstLetterPadding];
if (addSemicolon) {
characters[i++] = ';';
}
assert i == characters.length;
assert !Character.isDigit(characters[prefix.length]);
return new String(characters);
}
}