1/*
2 * Copyright (C) 2008 The Android Open Source Project
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
17/*
18 * Functions for dealing with method prototypes
19 */
20
21#ifndef LIBDEX_DEXPROTO_H_
22#define LIBDEX_DEXPROTO_H_
23
24#include "DexFile.h"
25
26/*
27 * Single-thread single-string cache. This structure holds a pointer to
28 * a string which is semi-automatically manipulated by some of the
29 * method prototype functions. Functions which use in this struct
30 * generally return a string that is valid until the next
31 * time the same DexStringCache is used.
32 */
33struct DexStringCache {
34    char* value;          /* the latest value */
35    size_t allocatedSize; /* size of the allocated buffer, if allocated */
36    char buffer[120];     /* buffer used to hold small-enough results */
37};
38
39/*
40 * Make sure that the given cache can hold a string of the given length,
41 * including the final '\0' byte.
42 */
43void dexStringCacheAlloc(DexStringCache* pCache, size_t length);
44
45/*
46 * Initialize the given DexStringCache. Use this function before passing
47 * one into any other function.
48 */
49void dexStringCacheInit(DexStringCache* pCache);
50
51/*
52 * Release the allocated contents of the given DexStringCache, if any.
53 * Use this function after your last use of a DexStringCache.
54 */
55void dexStringCacheRelease(DexStringCache* pCache);
56
57/*
58 * If the given DexStringCache doesn't already point at the given value,
59 * make a copy of it into the cache. This always returns a writable
60 * pointer to the contents (whether or not a copy had to be made). This
61 * function is intended to be used after making a call that at least
62 * sometimes doesn't populate a DexStringCache.
63 */
64char* dexStringCacheEnsureCopy(DexStringCache* pCache, const char* value);
65
66/*
67 * Abandon the given DexStringCache, and return a writable copy of the
68 * given value (reusing the string cache's allocation if possible).
69 * The return value must be free()d by the caller. Use this instead of
70 * dexStringCacheRelease() if you want the buffer to survive past the
71 * scope of the DexStringCache.
72 */
73char* dexStringCacheAbandon(DexStringCache* pCache, const char* value);
74
75/*
76 * Method prototype structure, which refers to a protoIdx in a
77 * particular DexFile.
78 */
79struct DexProto {
80    const DexFile* dexFile;     /* file the idx refers to */
81    u4 protoIdx;                /* index into proto_ids table of dexFile */
82};
83
84/*
85 * Set the given DexProto to refer to the prototype of the given MethodId.
86 */
87DEX_INLINE void dexProtoSetFromMethodId(DexProto* pProto,
88    const DexFile* pDexFile, const DexMethodId* pMethodId)
89{
90    pProto->dexFile = pDexFile;
91    pProto->protoIdx = pMethodId->protoIdx;
92}
93
94/*
95 * Get the short-form method descriptor for the given prototype. The
96 * prototype must be protoIdx-based.
97 */
98const char* dexProtoGetShorty(const DexProto* pProto);
99
100/*
101 * Get the full method descriptor for the given prototype.
102 */
103const char* dexProtoGetMethodDescriptor(const DexProto* pProto,
104    DexStringCache* pCache);
105
106/*
107 * Get a copy of the descriptor string associated with the given prototype.
108 * The returned pointer must be free()ed by the caller.
109 */
110char* dexProtoCopyMethodDescriptor(const DexProto* pProto);
111
112/*
113 * Get the parameter descriptors for the given prototype. This is the
114 * concatenation of all the descriptors for all the parameters, in
115 * order, with no other adornment.
116 */
117const char* dexProtoGetParameterDescriptors(const DexProto* pProto,
118    DexStringCache* pCache);
119
120/*
121 * Return the utf-8 encoded descriptor string from the proto of a MethodId.
122 */
123DEX_INLINE const char* dexGetDescriptorFromMethodId(const DexFile* pDexFile,
124        const DexMethodId* pMethodId, DexStringCache* pCache)
125{
126    DexProto proto;
127
128    dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
129    return dexProtoGetMethodDescriptor(&proto, pCache);
130}
131
132/*
133 * Get a copy of the utf-8 encoded method descriptor string from the
134 * proto of a MethodId. The returned pointer must be free()ed by the
135 * caller.
136 */
137DEX_INLINE char* dexCopyDescriptorFromMethodId(const DexFile* pDexFile,
138    const DexMethodId* pMethodId)
139{
140    DexProto proto;
141
142    dexProtoSetFromMethodId(&proto, pDexFile, pMethodId);
143    return dexProtoCopyMethodDescriptor(&proto);
144}
145
146/*
147 * Get the type descriptor for the return type of the given prototype.
148 */
149const char* dexProtoGetReturnType(const DexProto* pProto);
150
151/*
152 * Get the parameter count of the given prototype.
153 */
154size_t dexProtoGetParameterCount(const DexProto* pProto);
155
156/*
157 * Compute the number of parameter words (u4 units) required by the
158 * given prototype. For example, if the method takes (int, long) and
159 * returns double, this would return 3 (one for the int, two for the
160 * long, and the return type isn't relevant).
161 */
162int dexProtoComputeArgsSize(const DexProto* pProto);
163
164/*
165 * Compare the two prototypes. The two prototypes are compared
166 * with the return type as the major order, then the first arguments,
167 * then second, etc. If two prototypes are identical except that one
168 * has extra arguments, then the shorter argument is considered the
169 * earlier one in sort order (similar to strcmp()).
170 */
171int dexProtoCompare(const DexProto* pProto1, const DexProto* pProto2);
172
173/*
174 * Compare the two prototypes, ignoring return type. The two
175 * prototypes are compared with the first argument as the major order,
176 * then second, etc. If two prototypes are identical except that one
177 * has extra arguments, then the shorter argument is considered the
178 * earlier one in sort order (similar to strcmp()).
179 */
180int dexProtoCompareParameters(const DexProto* pProto1,
181        const DexProto* pProto2);
182
183/*
184 * Compare a prototype and a string method descriptor. The comparison
185 * is done as if the descriptor were converted to a prototype and compared
186 * with dexProtoCompare().
187 */
188int dexProtoCompareToDescriptor(const DexProto* proto, const char* descriptor);
189
190/*
191 * Compare a prototype and a concatenation of type descriptors. The
192 * comparison is done as if the descriptors were converted to a
193 * prototype and compared with dexProtoCompareParameters().
194 */
195int dexProtoCompareToParameterDescriptors(const DexProto* proto,
196        const char* descriptors);
197
198/*
199 * Single-thread prototype parameter iterator. This structure holds a
200 * pointer to a prototype and its parts, along with a cursor.
201 */
202struct DexParameterIterator {
203    const DexProto* proto;
204    const DexTypeList* parameters;
205    int parameterCount;
206    int cursor;
207};
208
209/*
210 * Initialize the given DexParameterIterator to be at the start of the
211 * parameters of the given prototype.
212 */
213void dexParameterIteratorInit(DexParameterIterator* pIterator,
214        const DexProto* pProto);
215
216/*
217 * Get the type_id index for the next parameter, if any. This returns
218 * kDexNoIndex if the last parameter has already been consumed.
219 */
220u4 dexParameterIteratorNextIndex(DexParameterIterator* pIterator);
221
222/*
223 * Get the type descriptor for the next parameter, if any. This returns
224 * NULL if the last parameter has already been consumed.
225 */
226const char* dexParameterIteratorNextDescriptor(
227        DexParameterIterator* pIterator);
228
229#endif  // LIBDEX_DEXPROTO_H_
230