SimpleNameFactory.java revision 8a6199f0c36a778f22394364347a301b0b28e94b
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.obfuscate;
22
23import java.util.*;
24
25
26/**
27 * This <code>NameFactory</code> generates unique short names, using mixed-case
28 * characters or lower-case characters only.
29 *
30 * @author Eric Lafortune
31 */
32public class SimpleNameFactory implements NameFactory
33{
34    private static final int CHARACTER_COUNT = 26;
35
36    private static final List cachedMixedCaseNames = new ArrayList();
37    private static final List cachedLowerCaseNames = new ArrayList();
38
39    private final boolean generateMixedCaseNames;
40    private int     index = 0;
41
42
43    /**
44     * Creates a new <code>SimpleNameFactory</code> that generates mixed-case names.
45     */
46    public SimpleNameFactory()
47    {
48        this(true);
49    }
50
51
52    /**
53     * Creates a new <code>SimpleNameFactory</code>.
54     * @param generateMixedCaseNames a flag to indicate whether the generated
55     *                               names will be mixed-case, or lower-case only.
56     */
57    public SimpleNameFactory(boolean generateMixedCaseNames)
58    {
59        this.generateMixedCaseNames = generateMixedCaseNames;
60    }
61
62
63    // Implementations for NameFactory.
64
65    public void reset()
66    {
67        index = 0;
68    }
69
70
71    public String nextName()
72    {
73        return name(index++);
74    }
75
76
77    /**
78     * Returns the name at the given index.
79     */
80    private String name(int index)
81    {
82        // Which cache do we need?
83        List cachedNames = generateMixedCaseNames ?
84            cachedMixedCaseNames :
85            cachedLowerCaseNames;
86
87        // Do we have the name in the cache?
88        if (index < cachedNames.size())
89        {
90            return (String)cachedNames.get(index);
91        }
92
93        // Create a new name and cache it.
94        String name = newName(index);
95        cachedNames.add(index, name);
96
97        return name;
98    }
99
100
101    /**
102     * Creates and returns the name at the given index.
103     */
104    private String newName(int index)
105    {
106        // If we're allowed to generate mixed-case names, we can use twice as
107        // many characters.
108        int totalCharacterCount = generateMixedCaseNames ?
109            2 * CHARACTER_COUNT :
110            CHARACTER_COUNT;
111
112        int baseIndex = index / totalCharacterCount;
113        int offset    = index % totalCharacterCount;
114
115        char newChar = charAt(offset);
116
117        String newName = baseIndex == 0 ?
118            new String(new char[] { newChar }) :
119            (name(baseIndex-1) + newChar);
120
121        return newName;
122    }
123
124
125    /**
126     * Returns the character with the given index, between 0 and the number of
127     * acceptable characters.
128     */
129    private char charAt(int index)
130    {
131        return (char)((index < CHARACTER_COUNT ? 'a' - 0               :
132                                                 'A' - CHARACTER_COUNT) + index);
133    }
134
135
136    public static void main(String[] args)
137    {
138        System.out.println("Some mixed-case names:");
139        printNameSamples(new SimpleNameFactory(true), 60);
140        System.out.println("Some lower-case names:");
141        printNameSamples(new SimpleNameFactory(false), 60);
142        System.out.println("Some more mixed-case names:");
143        printNameSamples(new SimpleNameFactory(true), 80);
144        System.out.println("Some more lower-case names:");
145        printNameSamples(new SimpleNameFactory(false), 80);
146    }
147
148
149    private static void printNameSamples(SimpleNameFactory factory, int count)
150    {
151        for (int counter = 0; counter < count; counter++)
152        {
153            System.out.println("  ["+factory.nextName()+"]");
154        }
155    }
156}
157