KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > util > StringSwitcher


1 /*
2  * Copyright 2003 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.sf.cglib.util;
17
18 import java.util.*;
19 import net.sf.cglib.core.*;
20 import org.objectweb.asm.ClassVisitor;
21 import org.objectweb.asm.Label;
22 import org.objectweb.asm.Type;
23
24 /**
25  * This class implements a simple String->int mapping for a fixed set of keys.
26  */

27 abstract public class StringSwitcher {
28     private static final Type STRING_SWITCHER =
29       TypeUtils.parseType("net.sf.cglib.util.StringSwitcher");
30     private static final Signature INT_VALUE =
31       TypeUtils.parseSignature("int intValue(String)");
32     private static final StringSwitcherKey KEY_FACTORY =
33       (StringSwitcherKey)KeyFactory.create(StringSwitcherKey.class);
34
35     interface StringSwitcherKey {
36         public Object JavaDoc newInstance(String JavaDoc[] strings, int[] ints, boolean fixedInput);
37     }
38
39     /**
40      * Helper method to create a StringSwitcher.
41      * For finer control over the generated instance, use a new instance of StringSwitcher.Generator
42      * instead of this static method.
43      * @param strings the array of String keys; must be the same length as the value array
44      * @param ints the array of integer results; must be the same length as the key array
45      * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true,
46      * the result will be undefined, and the resulting code will be faster
47      */

48     public static StringSwitcher create(String JavaDoc[] strings, int[] ints, boolean fixedInput) {
49         Generator gen = new Generator();
50         gen.setStrings(strings);
51         gen.setInts(ints);
52         gen.setFixedInput(fixedInput);
53         return gen.create();
54     }
55
56     protected StringSwitcher() {
57     }
58
59     /**
60      * Return the integer associated with the given key.
61      * @param s the key
62      * @return the associated integer value, or <code>-1</code> if the key is unknown (unless
63      * <code>fixedInput</code> was specified when this <code>StringSwitcher</code> was created,
64      * in which case the return value for an unknown key is undefined)
65      */

66     abstract public int intValue(String JavaDoc s);
67
68     public static class Generator extends AbstractClassGenerator {
69         private static final Source SOURCE = new Source(StringSwitcher.class.getName());
70
71         private String JavaDoc[] strings;
72         private int[] ints;
73         private boolean fixedInput;
74         
75         public Generator() {
76             super(SOURCE);
77         }
78
79         /**
80          * Set the array of recognized Strings.
81          * @param strings the array of String keys; must be the same length as the value array
82          * @see #setInts
83          */

84         public void setStrings(String JavaDoc[] strings) {
85             this.strings = strings;
86         }
87
88         /**
89          * Set the array of integer results.
90          * @param ints the array of integer results; must be the same length as the key array
91          * @see #setStrings
92          */

93         public void setInts(int[] ints) {
94             this.ints = ints;
95         }
96
97         /**
98          * Configure how unknown String keys will be handled.
99          * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true,
100          * the result will be undefined, and the resulting code will be faster
101          */

102         public void setFixedInput(boolean fixedInput) {
103             this.fixedInput = fixedInput;
104         }
105
106         protected ClassLoader JavaDoc getDefaultClassLoader() {
107             return getClass().getClassLoader();
108         }
109
110         /**
111          * Generate the <code>StringSwitcher</code>.
112          */

113         public StringSwitcher create() {
114             setNamePrefix(StringSwitcher.class.getName());
115             Object JavaDoc key = KEY_FACTORY.newInstance(strings, ints, fixedInput);
116             return (StringSwitcher)super.create(key);
117         }
118
119         public void generateClass(ClassVisitor v) throws Exception JavaDoc {
120             ClassEmitter ce = new ClassEmitter(v);
121             ce.begin_class(Constants.V1_2,
122                            Constants.ACC_PUBLIC,
123                            getClassName(),
124                            STRING_SWITCHER,
125                            null,
126                            Constants.SOURCE_FILE);
127             EmitUtils.null_constructor(ce);
128             final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, INT_VALUE, null);
129             e.load_arg(0);
130             final List stringList = Arrays.asList(strings);
131             int style = fixedInput ? Constants.SWITCH_STYLE_HASHONLY : Constants.SWITCH_STYLE_HASH;
132             EmitUtils.string_switch(e, strings, style, new ObjectSwitchCallback() {
133                 public void processCase(Object JavaDoc key, Label end) {
134                     e.push(ints[stringList.indexOf(key)]);
135                     e.return_value();
136                 }
137                 public void processDefault() {
138                     e.push(-1);
139                     e.return_value();
140                 }
141             });
142             e.end_method();
143             ce.end_class();
144         }
145
146         protected Object JavaDoc firstInstance(Class JavaDoc type) {
147             return (StringSwitcher)ReflectUtils.newInstance(type);
148         }
149
150         protected Object JavaDoc nextInstance(Object JavaDoc instance) {
151             return instance;
152         }
153     }
154 }
155
Popular Tags