1*ff7655f0SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ff7655f0SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ff7655f0SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ff7655f0SAndrew Rist  * distributed with this work for additional information
6*ff7655f0SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ff7655f0SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ff7655f0SAndrew Rist  * "License"); you may not use this file except in compliance
9*ff7655f0SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ff7655f0SAndrew Rist  *
11*ff7655f0SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ff7655f0SAndrew Rist  *
13*ff7655f0SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ff7655f0SAndrew Rist  * software distributed under the License is distributed on an
15*ff7655f0SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ff7655f0SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ff7655f0SAndrew Rist  * specific language governing permissions and limitations
18*ff7655f0SAndrew Rist  * under the License.
19*ff7655f0SAndrew Rist  *
20*ff7655f0SAndrew Rist  *************************************************************/
21*ff7655f0SAndrew Rist 
22*ff7655f0SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_codemaker.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "classfile.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include "codemaker/global.hxx"
30cdf0e10cSrcweir #include "codemaker/options.hxx"
31cdf0e10cSrcweir #include "codemaker/unotype.hxx"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include "boost/static_assert.hpp"
34cdf0e10cSrcweir #include "osl/diagnose.h"
35cdf0e10cSrcweir #include "rtl/string.h"
36cdf0e10cSrcweir #include "rtl/string.hxx"
37cdf0e10cSrcweir #include "sal/types.h"
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <map>
40cdf0e10cSrcweir #include <utility>
41cdf0e10cSrcweir #include <vector>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir using codemaker::javamaker::ClassFile;
44cdf0e10cSrcweir 
45cdf0e10cSrcweir namespace {
46cdf0e10cSrcweir 
47cdf0e10cSrcweir void appendU1(std::vector< unsigned char > & stream, sal_uInt8 data) {
48cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data));
49cdf0e10cSrcweir }
50cdf0e10cSrcweir 
51cdf0e10cSrcweir void appendU2(std::vector< unsigned char > & stream, sal_uInt16 data) {
52cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data >> 8));
53cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data & 0xFF));
54cdf0e10cSrcweir }
55cdf0e10cSrcweir 
56cdf0e10cSrcweir void appendU4(std::vector< unsigned char > & stream, sal_uInt32 data) {
57cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data >> 24));
58cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
59cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
60cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data & 0xFF));
61cdf0e10cSrcweir }
62cdf0e10cSrcweir 
63cdf0e10cSrcweir void appendU8(std::vector< unsigned char > & stream, sal_uInt64 data) {
64cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data >> 56));
65cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 48) & 0xFF));
66cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 40) & 0xFF));
67cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 32) & 0xFF));
68cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 24) & 0xFF));
69cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 16) & 0xFF));
70cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >((data >> 8) & 0xFF));
71cdf0e10cSrcweir     stream.push_back(static_cast< unsigned char >(data & 0xFF));
72cdf0e10cSrcweir }
73cdf0e10cSrcweir 
74cdf0e10cSrcweir void appendStream(
75cdf0e10cSrcweir     std::vector< unsigned char > & stream,
76cdf0e10cSrcweir     std::vector< unsigned char > const & data)
77cdf0e10cSrcweir {
78cdf0e10cSrcweir     stream.insert(stream.end(), data.begin(), data.end());
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir void write(FileStream & file, void const * buffer, sal_uInt64 size) {
82cdf0e10cSrcweir     if (!file.write(buffer, size)) {
83cdf0e10cSrcweir         throw CannotDumpException(
84cdf0e10cSrcweir             rtl::OString(RTL_CONSTASCII_STRINGPARAM("Error writing file")));
85cdf0e10cSrcweir     }
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir void writeU1(FileStream & file, sal_uInt8 data) {
89cdf0e10cSrcweir     unsigned char buf[] = { static_cast< unsigned char >(data) };
90cdf0e10cSrcweir     write(file, &buf, sizeof buf);
91cdf0e10cSrcweir }
92cdf0e10cSrcweir 
93cdf0e10cSrcweir void writeU2(FileStream & file, sal_uInt16 data) {
94cdf0e10cSrcweir     unsigned char buf[] = {
95cdf0e10cSrcweir         static_cast< unsigned char >(data >> 8),
96cdf0e10cSrcweir         static_cast< unsigned char >(data & 0xFF) };
97cdf0e10cSrcweir     write(file, buf, sizeof buf);
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
100cdf0e10cSrcweir void writeU4(FileStream & file, sal_uInt32 data) {
101cdf0e10cSrcweir     unsigned char buf[] = {
102cdf0e10cSrcweir         static_cast< unsigned char >(data >> 24),
103cdf0e10cSrcweir         static_cast< unsigned char >((data >> 16) & 0xFF),
104cdf0e10cSrcweir         static_cast< unsigned char >((data >> 8) & 0xFF),
105cdf0e10cSrcweir         static_cast< unsigned char >(data & 0xFF) };
106cdf0e10cSrcweir     write(file, buf, sizeof buf);
107cdf0e10cSrcweir }
108cdf0e10cSrcweir 
109cdf0e10cSrcweir void writeStream(FileStream & file, std::vector< unsigned char > const & stream)
110cdf0e10cSrcweir {
111cdf0e10cSrcweir     std::vector< unsigned char >::size_type n = stream.size();
112cdf0e10cSrcweir     BOOST_STATIC_ASSERT(
113cdf0e10cSrcweir         sizeof (std::vector< unsigned char >::size_type)
114cdf0e10cSrcweir         <= sizeof (sal_uInt64));
115cdf0e10cSrcweir         // both unsigned integral, so sizeof is a practically sufficient
116cdf0e10cSrcweir         // approximation of std::numeric_limits<T1>::max() <=
117cdf0e10cSrcweir         // std::numeric_limits<T2>::max()
118cdf0e10cSrcweir     if (n != 0) {
119cdf0e10cSrcweir         write(file, &stream[0], static_cast< sal_uInt64 >(n));
120cdf0e10cSrcweir     }
121cdf0e10cSrcweir }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir }
124cdf0e10cSrcweir 
125cdf0e10cSrcweir ClassFile::Code::~Code() {}
126cdf0e10cSrcweir 
127cdf0e10cSrcweir void ClassFile::Code::instrAastore() {
128cdf0e10cSrcweir     // aastore:
129cdf0e10cSrcweir     appendU1(m_code, 0x53);
130cdf0e10cSrcweir }
131cdf0e10cSrcweir 
132cdf0e10cSrcweir void ClassFile::Code::instrAconstNull() {
133cdf0e10cSrcweir     // aconst_null:
134cdf0e10cSrcweir     appendU1(m_code, 0x01);
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir void ClassFile::Code::instrAnewarray(rtl::OString const & type) {
138cdf0e10cSrcweir     // anewarray <indexbyte1> <indexbyte2>:
139cdf0e10cSrcweir     appendU1(m_code, 0xBD);
140cdf0e10cSrcweir     appendU2(m_code, m_classFile.addClassInfo(type));
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir void ClassFile::Code::instrAreturn() {
144cdf0e10cSrcweir     // areturn:
145cdf0e10cSrcweir     appendU1(m_code, 0xB0);
146cdf0e10cSrcweir }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir void ClassFile::Code::instrAthrow() {
149cdf0e10cSrcweir     // athrow:
150cdf0e10cSrcweir     appendU1(m_code, 0xBF);
151cdf0e10cSrcweir }
152cdf0e10cSrcweir 
153cdf0e10cSrcweir void ClassFile::Code::instrCheckcast(rtl::OString const & type) {
154cdf0e10cSrcweir     // checkcast <indexbyte1> <indexbyte2>:
155cdf0e10cSrcweir     appendU1(m_code, 0xC0);
156cdf0e10cSrcweir     appendU2(m_code, m_classFile.addClassInfo(type));
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
159cdf0e10cSrcweir void ClassFile::Code::instrDup() {
160cdf0e10cSrcweir     // dup:
161cdf0e10cSrcweir     appendU1(m_code, 0x59);
162cdf0e10cSrcweir }
163cdf0e10cSrcweir 
164cdf0e10cSrcweir void ClassFile::Code::instrGetstatic(
165cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
166cdf0e10cSrcweir     rtl::OString const & descriptor)
167cdf0e10cSrcweir {
168cdf0e10cSrcweir     // getstatic <indexbyte1> <indexbyte2>:
169cdf0e10cSrcweir     appendU1(m_code, 0xB2);
170cdf0e10cSrcweir     appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
171cdf0e10cSrcweir }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir ClassFile::Code::Branch ClassFile::Code::instrIfAcmpne() {
174cdf0e10cSrcweir     // if_acmpne <branchbyte1> <branchbyte2>:
175cdf0e10cSrcweir     Branch branch = m_code.size();
176cdf0e10cSrcweir     appendU1(m_code, 0xA6);
177cdf0e10cSrcweir     appendU2(m_code, 0);
178cdf0e10cSrcweir     return branch;
179cdf0e10cSrcweir }
180cdf0e10cSrcweir 
181cdf0e10cSrcweir ClassFile::Code::Branch ClassFile::Code::instrIfeq() {
182cdf0e10cSrcweir     // ifeq <branchbyte1> <branchbyte2>:
183cdf0e10cSrcweir     Branch branch = m_code.size();
184cdf0e10cSrcweir     appendU1(m_code, 0x99);
185cdf0e10cSrcweir     appendU2(m_code, 0);
186cdf0e10cSrcweir     return branch;
187cdf0e10cSrcweir }
188cdf0e10cSrcweir 
189cdf0e10cSrcweir ClassFile::Code::Branch ClassFile::Code::instrIfnull() {
190cdf0e10cSrcweir     // ifnull <branchbyte1> <branchbyte2>:
191cdf0e10cSrcweir     Branch branch = m_code.size();
192cdf0e10cSrcweir     appendU1(m_code, 0xC6);
193cdf0e10cSrcweir     appendU2(m_code, 0);
194cdf0e10cSrcweir     return branch;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir void ClassFile::Code::instrInstanceof(rtl::OString const & type) {
198cdf0e10cSrcweir     // instanceof <indexbyte1> <indexbyte2>:
199cdf0e10cSrcweir     appendU1(m_code, 0xC1);
200cdf0e10cSrcweir     appendU2(m_code, m_classFile.addClassInfo(type));
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir void ClassFile::Code::instrInvokeinterface(
204cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
205cdf0e10cSrcweir     rtl::OString const & descriptor, sal_uInt8 args)
206cdf0e10cSrcweir {
207cdf0e10cSrcweir     // invokeinterface <indexbyte1> <indexbyte2> <nargs> 0:
208cdf0e10cSrcweir     appendU1(m_code, 0xB9);
209cdf0e10cSrcweir     appendU2(
210cdf0e10cSrcweir         m_code, m_classFile.addInterfaceMethodrefInfo(type, name, descriptor));
211cdf0e10cSrcweir     appendU1(m_code, args);
212cdf0e10cSrcweir     appendU1(m_code, 0);
213cdf0e10cSrcweir }
214cdf0e10cSrcweir 
215cdf0e10cSrcweir void ClassFile::Code::instrInvokespecial(
216cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
217cdf0e10cSrcweir     rtl::OString const & descriptor)
218cdf0e10cSrcweir {
219cdf0e10cSrcweir     // invokespecial <indexbyte1> <indexbyte2>:
220cdf0e10cSrcweir     appendU1(m_code, 0xB7);
221cdf0e10cSrcweir     appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
224cdf0e10cSrcweir void ClassFile::Code::instrInvokestatic(
225cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
226cdf0e10cSrcweir     rtl::OString const & descriptor)
227cdf0e10cSrcweir {
228cdf0e10cSrcweir     // invokestatic <indexbyte1> <indexbyte2>:
229cdf0e10cSrcweir     appendU1(m_code, 0xB8);
230cdf0e10cSrcweir     appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
231cdf0e10cSrcweir }
232cdf0e10cSrcweir 
233cdf0e10cSrcweir void ClassFile::Code::instrInvokevirtual(
234cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
235cdf0e10cSrcweir     rtl::OString const & descriptor)
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     // invokevirtual <indexbyte1> <indexbyte2>:
238cdf0e10cSrcweir     appendU1(m_code, 0xB6);
239cdf0e10cSrcweir     appendU2(m_code, m_classFile.addMethodrefInfo(type, name, descriptor));
240cdf0e10cSrcweir }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir void ClassFile::Code::instrLookupswitch(
243cdf0e10cSrcweir     Code const * defaultBlock,
244cdf0e10cSrcweir     std::list< std::pair< sal_Int32, Code * > > const & blocks)
245cdf0e10cSrcweir {
246cdf0e10cSrcweir     // lookupswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
247cdf0e10cSrcweir     // <defaultbyte4> <npairs1> <npairs2> <npairs3> <npairs4>
248cdf0e10cSrcweir     // <match--offset pairs...>:
249cdf0e10cSrcweir     std::list< std::pair< sal_Int32, Code * > >::size_type size = blocks.size();
250cdf0e10cSrcweir     if (size > SAL_MAX_INT32) {
251cdf0e10cSrcweir         throw CannotDumpException(
252cdf0e10cSrcweir             rtl::OString(
253cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
254cdf0e10cSrcweir                     "Lookup-switch too large for Java class file format")));
255cdf0e10cSrcweir     }
256cdf0e10cSrcweir     Position pos1 = m_code.size();
257cdf0e10cSrcweir     appendU1(m_code, 0xAB);
258cdf0e10cSrcweir     int pad = (pos1 + 1) % 4;
259cdf0e10cSrcweir     {for (int i = 0; i < pad; ++i) {
260cdf0e10cSrcweir         appendU1(m_code, 0);
261cdf0e10cSrcweir     }}
262cdf0e10cSrcweir     Position pos2 = pos1 + 1 + pad + 8 + blocks.size() * 8; //FIXME: overflow
263cdf0e10cSrcweir     appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1)); //FIXME: overflow
264cdf0e10cSrcweir     pos2 += defaultBlock->m_code.size(); //FIXME: overflow
265cdf0e10cSrcweir     appendU4(m_code, static_cast< sal_uInt32 >(size));
266cdf0e10cSrcweir     {for (std::list< std::pair< sal_Int32, Code * > >::const_iterator i(
267cdf0e10cSrcweir               blocks.begin());
268cdf0e10cSrcweir           i != blocks.end(); ++i)
269cdf0e10cSrcweir     {
270cdf0e10cSrcweir         appendU4(m_code, static_cast< sal_uInt32 >(i->first));
271cdf0e10cSrcweir         appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
272cdf0e10cSrcweir             //FIXME: overflow
273cdf0e10cSrcweir         pos2 += i->second->m_code.size(); //FIXME: overflow
274cdf0e10cSrcweir     }}
275cdf0e10cSrcweir     appendStream(m_code, defaultBlock->m_code);
276cdf0e10cSrcweir     {for (std::list< std::pair< sal_Int32, Code * > >::const_iterator i(
277cdf0e10cSrcweir               blocks.begin());
278cdf0e10cSrcweir           i != blocks.end(); ++i)
279cdf0e10cSrcweir     {
280cdf0e10cSrcweir         appendStream(m_code, i->second->m_code);
281cdf0e10cSrcweir     }}
282cdf0e10cSrcweir }
283cdf0e10cSrcweir 
284cdf0e10cSrcweir void ClassFile::Code::instrNew(rtl::OString const & type) {
285cdf0e10cSrcweir     // new <indexbyte1> <indexbyte2>:
286cdf0e10cSrcweir     appendU1(m_code, 0xBB);
287cdf0e10cSrcweir     appendU2(m_code, m_classFile.addClassInfo(type));
288cdf0e10cSrcweir }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir void ClassFile::Code::instrNewarray(codemaker::UnoType::Sort sort) {
291cdf0e10cSrcweir     OSL_ASSERT(
292cdf0e10cSrcweir         sort >= codemaker::UnoType::SORT_BOOLEAN
293cdf0e10cSrcweir         && sort <= codemaker::UnoType::SORT_CHAR);
294cdf0e10cSrcweir     // newarray <atype>:
295cdf0e10cSrcweir     appendU1(m_code, 0xBC);
296cdf0e10cSrcweir     static sal_uInt8 const atypes[codemaker::UnoType::SORT_CHAR] = {
297cdf0e10cSrcweir         0x04, 0x08, 0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x06, 0x07, 0x05 };
298cdf0e10cSrcweir     appendU1(m_code, atypes[sort - 1]);
299cdf0e10cSrcweir }
300cdf0e10cSrcweir 
301cdf0e10cSrcweir void ClassFile::Code::instrPop() {
302cdf0e10cSrcweir     // pop:
303cdf0e10cSrcweir     appendU1(m_code, 0x57);
304cdf0e10cSrcweir }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir void ClassFile::Code::instrPutfield(
307cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
308cdf0e10cSrcweir     rtl::OString const & descriptor)
309cdf0e10cSrcweir {
310cdf0e10cSrcweir     // putfield <indexbyte1> <indexbyte2>:
311cdf0e10cSrcweir     appendU1(m_code, 0xB5);
312cdf0e10cSrcweir     appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
313cdf0e10cSrcweir }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir void ClassFile::Code::instrPutstatic(
316cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
317cdf0e10cSrcweir     rtl::OString const & descriptor)
318cdf0e10cSrcweir {
319cdf0e10cSrcweir     // putstatic <indexbyte1> <indexbyte2>:
320cdf0e10cSrcweir     appendU1(m_code, 0xB3);
321cdf0e10cSrcweir     appendU2(m_code, m_classFile.addFieldrefInfo(type, name, descriptor));
322cdf0e10cSrcweir }
323cdf0e10cSrcweir 
324cdf0e10cSrcweir void ClassFile::Code::instrReturn() {
325cdf0e10cSrcweir     // return:
326cdf0e10cSrcweir     appendU1(m_code, 0xB1);
327cdf0e10cSrcweir }
328cdf0e10cSrcweir 
329cdf0e10cSrcweir void ClassFile::Code::instrSwap() {
330cdf0e10cSrcweir     // swap:
331cdf0e10cSrcweir     appendU1(m_code, 0x5F);
332cdf0e10cSrcweir }
333cdf0e10cSrcweir 
334cdf0e10cSrcweir void ClassFile::Code::instrTableswitch(
335cdf0e10cSrcweir     Code const * defaultBlock, sal_Int32 low,
336cdf0e10cSrcweir     std::list< Code * > const & blocks)
337cdf0e10cSrcweir {
338cdf0e10cSrcweir     // tableswitch <0--3 byte pad> <defaultbyte1> <defaultbyte2> <defaultbyte3>
339cdf0e10cSrcweir     // <defaultbyte4> <lowbyte1> <lowbyte2> <lowbyte3> <lowbyte4> <highbyte1>
340cdf0e10cSrcweir     // <highbyte2> <highbyte3> <highbyte4> <jump offsets...>:
341cdf0e10cSrcweir     Position pos1 = m_code.size();
342cdf0e10cSrcweir     appendU1(m_code, 0xAA);
343cdf0e10cSrcweir     int pad = (pos1 + 1) % 4;
344cdf0e10cSrcweir     {for (int i = 0; i < pad; ++i) {
345cdf0e10cSrcweir         appendU1(m_code, 0);
346cdf0e10cSrcweir     }}
347cdf0e10cSrcweir     std::list< Code * >::size_type size = blocks.size();
348cdf0e10cSrcweir     Position pos2 = pos1 + 1 + pad + 12 + size * 4; //FIXME: overflow
349cdf0e10cSrcweir     sal_uInt32 defaultOffset = static_cast< sal_uInt32 >(pos2 - pos1);
350cdf0e10cSrcweir         //FIXME: overflow
351cdf0e10cSrcweir     appendU4(m_code, defaultOffset);
352cdf0e10cSrcweir     pos2 += defaultBlock->m_code.size(); //FIXME: overflow
353cdf0e10cSrcweir     appendU4(m_code, static_cast< sal_uInt32 >(low));
354cdf0e10cSrcweir     appendU4(m_code, static_cast< sal_uInt32 >(low + (size - 1)));
355cdf0e10cSrcweir     {for (std::list< Code * >::const_iterator i(blocks.begin());
356cdf0e10cSrcweir           i != blocks.end(); ++i)
357cdf0e10cSrcweir     {
358cdf0e10cSrcweir         if (*i == 0) {
359cdf0e10cSrcweir             appendU4(m_code, defaultOffset);
360cdf0e10cSrcweir         } else {
361cdf0e10cSrcweir             appendU4(m_code, static_cast< sal_uInt32 >(pos2 - pos1));
362cdf0e10cSrcweir                 //FIXME: overflow
363cdf0e10cSrcweir             pos2 += (*i)->m_code.size(); //FIXME: overflow
364cdf0e10cSrcweir         }
365cdf0e10cSrcweir     }}
366cdf0e10cSrcweir     appendStream(m_code, defaultBlock->m_code);
367cdf0e10cSrcweir     {for (std::list< Code * >::const_iterator i(blocks.begin());
368cdf0e10cSrcweir           i != blocks.end(); ++i)
369cdf0e10cSrcweir     {
370cdf0e10cSrcweir         if (*i != 0) {
371cdf0e10cSrcweir             appendStream(m_code, (*i)->m_code);
372cdf0e10cSrcweir         }
373cdf0e10cSrcweir     }}
374cdf0e10cSrcweir }
375cdf0e10cSrcweir 
376cdf0e10cSrcweir void ClassFile::Code::loadIntegerConstant(sal_Int32 value) {
377cdf0e10cSrcweir     if (value >= -1 && value <= 5) {
378cdf0e10cSrcweir         // iconst_<i>:
379cdf0e10cSrcweir         appendU1(m_code, static_cast< sal_uInt8 >(0x02 + value + 1));
380cdf0e10cSrcweir     } else if (value >= -128 && value <= 127) {
381cdf0e10cSrcweir         // bipush <byte>:
382cdf0e10cSrcweir         appendU1(m_code, 0x10);
383cdf0e10cSrcweir         appendU1(m_code, static_cast< sal_uInt8 >(value));
384cdf0e10cSrcweir     } else if (value >= -32768 && value <= 32767) {
385cdf0e10cSrcweir         // sipush <byte1> <byte2>:
386cdf0e10cSrcweir         appendU1(m_code, 0x11);
387cdf0e10cSrcweir         appendU2(m_code, static_cast< sal_uInt16 >(value));
388cdf0e10cSrcweir     } else {
389cdf0e10cSrcweir         ldc(m_classFile.addIntegerInfo(value));
390cdf0e10cSrcweir     }
391cdf0e10cSrcweir }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir void ClassFile::Code::loadStringConstant(rtl::OString const & value) {
394cdf0e10cSrcweir     ldc(m_classFile.addStringInfo(value));
395cdf0e10cSrcweir }
396cdf0e10cSrcweir 
397cdf0e10cSrcweir void ClassFile::Code::loadLocalInteger(sal_uInt16 index) {
398cdf0e10cSrcweir     accessLocal(index, 0x1A, 0x15); // iload_<n>, iload
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir void ClassFile::Code::loadLocalLong(sal_uInt16 index) {
402cdf0e10cSrcweir     accessLocal(index, 0x1E, 0x16); // load_<n>, load
403cdf0e10cSrcweir }
404cdf0e10cSrcweir 
405cdf0e10cSrcweir void ClassFile::Code::loadLocalFloat(sal_uInt16 index) {
406cdf0e10cSrcweir     accessLocal(index, 0x22, 0x17); // load_<n>, load
407cdf0e10cSrcweir }
408cdf0e10cSrcweir 
409cdf0e10cSrcweir void ClassFile::Code::loadLocalDouble(sal_uInt16 index) {
410cdf0e10cSrcweir     accessLocal(index, 0x26, 0x18); // load_<n>, load
411cdf0e10cSrcweir }
412cdf0e10cSrcweir 
413cdf0e10cSrcweir void ClassFile::Code::loadLocalReference(sal_uInt16 index) {
414cdf0e10cSrcweir     accessLocal(index, 0x2A, 0x19); // aload_<n>, aload
415cdf0e10cSrcweir }
416cdf0e10cSrcweir 
417cdf0e10cSrcweir void ClassFile::Code::storeLocalReference(sal_uInt16 index) {
418cdf0e10cSrcweir     accessLocal(index, 0x4B, 0x3A); // astore_<n>, astore
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir void ClassFile::Code::branchHere(Branch branch) {
422cdf0e10cSrcweir     std::vector< unsigned char >::size_type n = m_code.size();
423cdf0e10cSrcweir     OSL_ASSERT(n > branch && n - branch <= SAL_MAX_INT16);
424cdf0e10cSrcweir     n -= branch;
425cdf0e10cSrcweir     m_code[branch + 1] = static_cast< sal_uInt8 >(n >> 8);
426cdf0e10cSrcweir     m_code[branch + 2] = static_cast< sal_uInt8 >(n & 0xFF);
427cdf0e10cSrcweir }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir void ClassFile::Code::addException(
430cdf0e10cSrcweir     Position start, Position end, Position handler, rtl::OString const & type)
431cdf0e10cSrcweir {
432cdf0e10cSrcweir     OSL_ASSERT(start < end && end <= m_code.size() && handler <= m_code.size());
433cdf0e10cSrcweir     if (m_exceptionTableLength == SAL_MAX_UINT16) {
434cdf0e10cSrcweir         throw CannotDumpException(
435cdf0e10cSrcweir             rtl::OString(
436cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
437cdf0e10cSrcweir                     "Too many exception handlers for Java class file format")));
438cdf0e10cSrcweir     }
439cdf0e10cSrcweir     ++m_exceptionTableLength;
440cdf0e10cSrcweir     appendU2(m_exceptionTable, static_cast< sal_uInt16 >(start));
441cdf0e10cSrcweir         //FIXME: overflow
442cdf0e10cSrcweir     appendU2(m_exceptionTable, static_cast< sal_uInt16 >(end));
443cdf0e10cSrcweir         //FIXME: overflow
444cdf0e10cSrcweir     appendU2(m_exceptionTable, static_cast< sal_uInt16 >(handler));
445cdf0e10cSrcweir         //FIXME: overflow
446cdf0e10cSrcweir     appendU2(m_exceptionTable, m_classFile.addClassInfo(type));
447cdf0e10cSrcweir }
448cdf0e10cSrcweir 
449cdf0e10cSrcweir ClassFile::Code::Position ClassFile::Code::getPosition() const {
450cdf0e10cSrcweir     return m_code.size();
451cdf0e10cSrcweir }
452cdf0e10cSrcweir 
453cdf0e10cSrcweir ClassFile::Code::Code(ClassFile & classFile):
454cdf0e10cSrcweir     m_classFile(classFile), m_exceptionTableLength(0)
455cdf0e10cSrcweir {}
456cdf0e10cSrcweir 
457cdf0e10cSrcweir void ClassFile::Code::ldc(sal_uInt16 index) {
458cdf0e10cSrcweir     if (index <= 0xFF) {
459cdf0e10cSrcweir         // ldc <index>:
460cdf0e10cSrcweir         appendU1(m_code, 0x12);
461cdf0e10cSrcweir         appendU1(m_code, static_cast< sal_uInt8 >(index));
462cdf0e10cSrcweir     } else {
463cdf0e10cSrcweir         // ldc_w <indexbyte1> <indexbyte2>:
464cdf0e10cSrcweir         appendU1(m_code, 0x13);
465cdf0e10cSrcweir         appendU2(m_code, index);
466cdf0e10cSrcweir     }
467cdf0e10cSrcweir }
468cdf0e10cSrcweir 
469cdf0e10cSrcweir void ClassFile::Code::accessLocal(
470cdf0e10cSrcweir     sal_uInt16 index, sal_uInt8 fastOp, sal_uInt8 normalOp)
471cdf0e10cSrcweir {
472cdf0e10cSrcweir     if (index <= 3) {
473cdf0e10cSrcweir         // ...load/store_<n>:
474cdf0e10cSrcweir         appendU1(m_code, static_cast< sal_uInt8 >(fastOp + index));
475cdf0e10cSrcweir     } else if (index <= 0xFF) {
476cdf0e10cSrcweir         // ...load/store <index>:
477cdf0e10cSrcweir         appendU1(m_code, normalOp);
478cdf0e10cSrcweir         appendU1(m_code, static_cast< sal_uInt8 >(index));
479cdf0e10cSrcweir     } else {
480cdf0e10cSrcweir         // wide ...load/store <indexbyte1> <indexbyte2>:
481cdf0e10cSrcweir         appendU1(m_code, 0xC4);
482cdf0e10cSrcweir         appendU1(m_code, normalOp);
483cdf0e10cSrcweir         appendU2(m_code, index);
484cdf0e10cSrcweir     }
485cdf0e10cSrcweir }
486cdf0e10cSrcweir 
487cdf0e10cSrcweir ClassFile::ClassFile(
488cdf0e10cSrcweir     AccessFlags accessFlags, rtl::OString const & thisClass,
489cdf0e10cSrcweir     rtl::OString const & superClass, rtl::OString const & signature):
490cdf0e10cSrcweir     m_constantPoolCount(1), m_accessFlags(accessFlags), m_interfacesCount(0),
491cdf0e10cSrcweir     m_fieldsCount(0), m_methodsCount(0), m_attributesCount(0)
492cdf0e10cSrcweir {
493cdf0e10cSrcweir     m_thisClass = addClassInfo(thisClass);
494cdf0e10cSrcweir     m_superClass = addClassInfo(superClass);
495cdf0e10cSrcweir     if (signature.getLength() != 0) {
496cdf0e10cSrcweir         ++m_attributesCount;
497cdf0e10cSrcweir         appendU2(
498cdf0e10cSrcweir             m_attributes,
499cdf0e10cSrcweir             addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Signature"))));
500cdf0e10cSrcweir         appendU4(m_attributes, 2);
501cdf0e10cSrcweir         appendU2(m_attributes, addUtf8Info(signature));
502cdf0e10cSrcweir     }
503cdf0e10cSrcweir }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir ClassFile::~ClassFile() {}
506cdf0e10cSrcweir 
507cdf0e10cSrcweir ClassFile::Code * ClassFile::newCode() {
508cdf0e10cSrcweir     return new Code(*this);
509cdf0e10cSrcweir }
510cdf0e10cSrcweir 
511cdf0e10cSrcweir sal_uInt16 ClassFile::addIntegerInfo(sal_Int32 value) {
512cdf0e10cSrcweir     std::map< sal_Int32, sal_uInt16 >::iterator i(m_integerInfos.find(value));
513cdf0e10cSrcweir     if (i != m_integerInfos.end()) {
514cdf0e10cSrcweir         return i->second;
515cdf0e10cSrcweir     }
516cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
517cdf0e10cSrcweir     appendU1(m_constantPool, 3);
518cdf0e10cSrcweir     appendU4(m_constantPool, static_cast< sal_uInt32 >(value));
519cdf0e10cSrcweir     if (!m_integerInfos.insert(
520cdf0e10cSrcweir             std::map< sal_Int32, sal_uInt16 >::value_type(value, index)).second)
521cdf0e10cSrcweir     {
522cdf0e10cSrcweir         OSL_ASSERT(false);
523cdf0e10cSrcweir     }
524cdf0e10cSrcweir     return index;
525cdf0e10cSrcweir }
526cdf0e10cSrcweir 
527cdf0e10cSrcweir sal_uInt16 ClassFile::addFloatInfo(float value) {
528cdf0e10cSrcweir     std::map< float, sal_uInt16 >::iterator i(m_floatInfos.find(value));
529cdf0e10cSrcweir     if (i != m_floatInfos.end()) {
530cdf0e10cSrcweir         return i->second;
531cdf0e10cSrcweir     }
532cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
533cdf0e10cSrcweir     appendU1(m_constantPool, 4);
534cdf0e10cSrcweir     union { float floatBytes; sal_uInt32 uint32Bytes; } bytes;
535cdf0e10cSrcweir     bytes.floatBytes = value;
536cdf0e10cSrcweir     appendU4(m_constantPool, bytes.uint32Bytes);
537cdf0e10cSrcweir     if (!m_floatInfos.insert(
538cdf0e10cSrcweir             std::map< float, sal_uInt16 >::value_type(value, index)).second)
539cdf0e10cSrcweir     {
540cdf0e10cSrcweir         OSL_ASSERT(false);
541cdf0e10cSrcweir     }
542cdf0e10cSrcweir     return index;
543cdf0e10cSrcweir }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir sal_uInt16 ClassFile::addLongInfo(sal_Int64 value) {
546cdf0e10cSrcweir     std::map< sal_Int64, sal_uInt16 >::iterator i(m_longInfos.find(value));
547cdf0e10cSrcweir     if (i != m_longInfos.end()) {
548cdf0e10cSrcweir         return i->second;
549cdf0e10cSrcweir     }
550cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(2);
551cdf0e10cSrcweir     appendU1(m_constantPool, 5);
552cdf0e10cSrcweir     appendU8(m_constantPool, static_cast< sal_uInt64 >(value));
553cdf0e10cSrcweir     if (!m_longInfos.insert(
554cdf0e10cSrcweir             std::map< sal_Int64, sal_uInt16 >::value_type(value, index)).second)
555cdf0e10cSrcweir     {
556cdf0e10cSrcweir         OSL_ASSERT(false);
557cdf0e10cSrcweir     }
558cdf0e10cSrcweir     return index;
559cdf0e10cSrcweir }
560cdf0e10cSrcweir 
561cdf0e10cSrcweir sal_uInt16 ClassFile::addDoubleInfo(double value) {
562cdf0e10cSrcweir     std::map< double, sal_uInt16 >::iterator i(m_doubleInfos.find(value));
563cdf0e10cSrcweir     if (i != m_doubleInfos.end()) {
564cdf0e10cSrcweir         return i->second;
565cdf0e10cSrcweir     }
566cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(2);
567cdf0e10cSrcweir     appendU1(m_constantPool, 6);
568cdf0e10cSrcweir     union { double doubleBytes; sal_uInt64 uint64Bytes; } bytes;
569cdf0e10cSrcweir     bytes.doubleBytes = value;
570cdf0e10cSrcweir     appendU8(m_constantPool, bytes.uint64Bytes);
571cdf0e10cSrcweir     if (!m_doubleInfos.insert(
572cdf0e10cSrcweir             std::map< double, sal_uInt16 >::value_type(value, index)).second)
573cdf0e10cSrcweir     {
574cdf0e10cSrcweir         OSL_ASSERT(false);
575cdf0e10cSrcweir     }
576cdf0e10cSrcweir     return index;
577cdf0e10cSrcweir }
578cdf0e10cSrcweir 
579cdf0e10cSrcweir void ClassFile::addInterface(rtl::OString const & interface) {
580cdf0e10cSrcweir     if (m_interfacesCount == SAL_MAX_UINT16) {
581cdf0e10cSrcweir         throw CannotDumpException(
582cdf0e10cSrcweir             rtl::OString(
583cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
584cdf0e10cSrcweir                     "Too many interfaces for Java class file format")));
585cdf0e10cSrcweir     }
586cdf0e10cSrcweir     ++m_interfacesCount;
587cdf0e10cSrcweir     appendU2(m_interfaces, addClassInfo(interface));
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
590cdf0e10cSrcweir void ClassFile::addField(
591cdf0e10cSrcweir     AccessFlags accessFlags, rtl::OString const & name,
592cdf0e10cSrcweir     rtl::OString const & descriptor, sal_uInt16 constantValueIndex,
593cdf0e10cSrcweir     rtl::OString const & signature)
594cdf0e10cSrcweir {
595cdf0e10cSrcweir     if (m_fieldsCount == SAL_MAX_UINT16) {
596cdf0e10cSrcweir         throw CannotDumpException(
597cdf0e10cSrcweir             rtl::OString(
598cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
599cdf0e10cSrcweir                     "Too many fields for Java class file format")));
600cdf0e10cSrcweir     }
601cdf0e10cSrcweir     ++m_fieldsCount;
602cdf0e10cSrcweir     appendU2(m_fields, static_cast< sal_uInt16 >(accessFlags));
603cdf0e10cSrcweir     appendU2(m_fields, addUtf8Info(name));
604cdf0e10cSrcweir     appendU2(m_fields, addUtf8Info(descriptor));
605cdf0e10cSrcweir     appendU2(
606cdf0e10cSrcweir         m_fields,
607cdf0e10cSrcweir         ((constantValueIndex == 0 ? 0 : 1)
608cdf0e10cSrcweir          + (signature.getLength() == 0 ? 0 : 1)));
609cdf0e10cSrcweir     if (constantValueIndex != 0) {
610cdf0e10cSrcweir         appendU2(
611cdf0e10cSrcweir             m_fields,
612cdf0e10cSrcweir             addUtf8Info(
613cdf0e10cSrcweir                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("ConstantValue"))));
614cdf0e10cSrcweir         appendU4(m_fields, 2);
615cdf0e10cSrcweir         appendU2(m_fields, constantValueIndex);
616cdf0e10cSrcweir     }
617cdf0e10cSrcweir     appendSignatureAttribute(m_fields, signature);
618cdf0e10cSrcweir }
619cdf0e10cSrcweir 
620cdf0e10cSrcweir void ClassFile::addMethod(
621cdf0e10cSrcweir     AccessFlags accessFlags, rtl::OString const & name,
622cdf0e10cSrcweir     rtl::OString const & descriptor, Code const * code,
623cdf0e10cSrcweir     std::vector< rtl::OString > const & exceptions,
624cdf0e10cSrcweir     rtl::OString const & signature)
625cdf0e10cSrcweir {
626cdf0e10cSrcweir     if (m_methodsCount == SAL_MAX_UINT16) {
627cdf0e10cSrcweir         throw CannotDumpException(
628cdf0e10cSrcweir             rtl::OString(
629cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
630cdf0e10cSrcweir                     "Too many methods for Java class file format")));
631cdf0e10cSrcweir     }
632cdf0e10cSrcweir     ++m_methodsCount;
633cdf0e10cSrcweir     appendU2(m_methods, static_cast< sal_uInt16 >(accessFlags));
634cdf0e10cSrcweir     appendU2(m_methods, addUtf8Info(name));
635cdf0e10cSrcweir     appendU2(m_methods, addUtf8Info(descriptor));
636cdf0e10cSrcweir     std::vector< rtl::OString >::size_type excs = exceptions.size();
637cdf0e10cSrcweir     if (excs > SAL_MAX_UINT16) {
638cdf0e10cSrcweir         throw CannotDumpException(
639cdf0e10cSrcweir             rtl::OString(
640cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
641cdf0e10cSrcweir                     "Too many exception specifications for Java class file"
642cdf0e10cSrcweir                     " format")));
643cdf0e10cSrcweir     }
644cdf0e10cSrcweir     appendU2(
645cdf0e10cSrcweir         m_methods,
646cdf0e10cSrcweir         ((code == 0 ? 0 : 1) + (exceptions.empty() ? 0 : 1)
647cdf0e10cSrcweir          + (signature.getLength() == 0 ? 0 : 1)));
648cdf0e10cSrcweir     if (code != 0) {
649cdf0e10cSrcweir         std::vector< unsigned char >::size_type codeSize = code->m_code.size();
650cdf0e10cSrcweir         std::vector< unsigned char >::size_type exceptionTableSize
651cdf0e10cSrcweir             = code->m_exceptionTable.size();
652cdf0e10cSrcweir         if (codeSize > SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
653cdf0e10cSrcweir             || (exceptionTableSize
654cdf0e10cSrcweir                 > (SAL_MAX_UINT32 - (2 + 2 + 4 + 2 + 2)
655cdf0e10cSrcweir                    - static_cast< sal_uInt32 >(codeSize))))
656cdf0e10cSrcweir         {
657cdf0e10cSrcweir             throw CannotDumpException(
658cdf0e10cSrcweir                 rtl::OString(
659cdf0e10cSrcweir                     RTL_CONSTASCII_STRINGPARAM(
660cdf0e10cSrcweir                         "Code block is too big for Java class file format")));
661cdf0e10cSrcweir         }
662cdf0e10cSrcweir         appendU2(
663cdf0e10cSrcweir             m_methods,
664cdf0e10cSrcweir             addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Code"))));
665cdf0e10cSrcweir         appendU4(
666cdf0e10cSrcweir             m_methods,
667cdf0e10cSrcweir             (2 + 2 + 4 + static_cast< sal_uInt32 >(codeSize) + 2
668cdf0e10cSrcweir              + static_cast< sal_uInt32 >(exceptionTableSize) + 2));
669cdf0e10cSrcweir         appendU2(m_methods, code->m_maxStack);
670cdf0e10cSrcweir         appendU2(m_methods, code->m_maxLocals);
671cdf0e10cSrcweir         appendU4(m_methods, static_cast< sal_uInt32 >(codeSize));
672cdf0e10cSrcweir         appendStream(m_methods, code->m_code);
673cdf0e10cSrcweir         appendU2(m_methods, code->m_exceptionTableLength);
674cdf0e10cSrcweir         appendStream(m_methods, code->m_exceptionTable);
675cdf0e10cSrcweir         appendU2(m_methods, 0);
676cdf0e10cSrcweir     }
677cdf0e10cSrcweir     if (!exceptions.empty()) {
678cdf0e10cSrcweir         appendU2(
679cdf0e10cSrcweir             m_methods,
680cdf0e10cSrcweir             addUtf8Info(
681cdf0e10cSrcweir                 rtl::OString(RTL_CONSTASCII_STRINGPARAM("Exceptions"))));
682cdf0e10cSrcweir         appendU4(
683cdf0e10cSrcweir             m_methods,
684cdf0e10cSrcweir             static_cast< sal_uInt32 >(2 + 2 * static_cast< sal_uInt32 >(excs)));
685cdf0e10cSrcweir         appendU2(m_methods, static_cast< sal_uInt16 >(excs));
686cdf0e10cSrcweir         for (std::vector< rtl::OString >::const_iterator i(exceptions.begin());
687cdf0e10cSrcweir              i != exceptions.end(); ++i)
688cdf0e10cSrcweir         {
689cdf0e10cSrcweir             appendU2(m_methods, addClassInfo(*i));
690cdf0e10cSrcweir         }
691cdf0e10cSrcweir     }
692cdf0e10cSrcweir     appendSignatureAttribute(m_methods, signature);
693cdf0e10cSrcweir }
694cdf0e10cSrcweir 
695cdf0e10cSrcweir void ClassFile::write(FileStream & file) const {
696cdf0e10cSrcweir     writeU4(file, 0xCAFEBABE);
697cdf0e10cSrcweir     writeU2(file, 0);
698cdf0e10cSrcweir     writeU2(file, 46);
699cdf0e10cSrcweir     writeU2(file, m_constantPoolCount);
700cdf0e10cSrcweir     writeStream(file, m_constantPool);
701cdf0e10cSrcweir     writeU2(file, static_cast< sal_uInt16 >(m_accessFlags));
702cdf0e10cSrcweir     writeU2(file, m_thisClass);
703cdf0e10cSrcweir     writeU2(file, m_superClass);
704cdf0e10cSrcweir     writeU2(file, m_interfacesCount);
705cdf0e10cSrcweir     writeStream(file, m_interfaces);
706cdf0e10cSrcweir     writeU2(file, m_fieldsCount);
707cdf0e10cSrcweir     writeStream(file, m_fields);
708cdf0e10cSrcweir     writeU2(file, m_methodsCount);
709cdf0e10cSrcweir     writeStream(file, m_methods);
710cdf0e10cSrcweir     writeU2(file, m_attributesCount);
711cdf0e10cSrcweir     writeStream(file, m_attributes);
712cdf0e10cSrcweir }
713cdf0e10cSrcweir 
714cdf0e10cSrcweir sal_uInt16 ClassFile::nextConstantPoolIndex(sal_uInt16 width) {
715cdf0e10cSrcweir     OSL_ASSERT(width == 1 || width == 2);
716cdf0e10cSrcweir     if (m_constantPoolCount > SAL_MAX_UINT16 - width) {
717cdf0e10cSrcweir         throw CannotDumpException(
718cdf0e10cSrcweir             rtl::OString(
719cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
720cdf0e10cSrcweir                     "Too many constant pool items for Java class file"
721cdf0e10cSrcweir                     " format")));
722cdf0e10cSrcweir     }
723cdf0e10cSrcweir     sal_uInt16 index = m_constantPoolCount;
724cdf0e10cSrcweir     m_constantPoolCount = m_constantPoolCount + width;
725cdf0e10cSrcweir     return index;
726cdf0e10cSrcweir }
727cdf0e10cSrcweir 
728cdf0e10cSrcweir sal_uInt16 ClassFile::addUtf8Info(rtl::OString const & value) {
729cdf0e10cSrcweir     std::map< rtl::OString, sal_uInt16 >::iterator i(m_utf8Infos.find(value));
730cdf0e10cSrcweir     if (i != m_utf8Infos.end()) {
731cdf0e10cSrcweir         return i->second;
732cdf0e10cSrcweir     }
733cdf0e10cSrcweir     if (value.getLength() > SAL_MAX_UINT16) {
734cdf0e10cSrcweir         throw CannotDumpException(
735cdf0e10cSrcweir             rtl::OString(
736cdf0e10cSrcweir                 RTL_CONSTASCII_STRINGPARAM(
737cdf0e10cSrcweir                     "UTF-8 string too long for Java class file format")));
738cdf0e10cSrcweir     }
739cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
740cdf0e10cSrcweir     appendU1(m_constantPool, 1);
741cdf0e10cSrcweir     appendU2(m_constantPool, static_cast< sal_uInt16 >(value.getLength()));
742cdf0e10cSrcweir     for (sal_Int32 j = 0; j < value.getLength(); ++j) {
743cdf0e10cSrcweir         appendU1(m_constantPool, static_cast< sal_uInt8 >(value[j]));
744cdf0e10cSrcweir     }
745cdf0e10cSrcweir     if (!m_utf8Infos.insert(
746cdf0e10cSrcweir             std::map< rtl::OString, sal_uInt16 >::value_type(value, index)).
747cdf0e10cSrcweir         second)
748cdf0e10cSrcweir     {
749cdf0e10cSrcweir         OSL_ASSERT(false);
750cdf0e10cSrcweir     }
751cdf0e10cSrcweir     return index;
752cdf0e10cSrcweir }
753cdf0e10cSrcweir 
754cdf0e10cSrcweir sal_uInt16 ClassFile::addClassInfo(rtl::OString const & type) {
755cdf0e10cSrcweir     sal_uInt16 nameIndex = addUtf8Info(type);
756cdf0e10cSrcweir     std::map< sal_uInt16, sal_uInt16 >::iterator i(
757cdf0e10cSrcweir         m_classInfos.find(nameIndex));
758cdf0e10cSrcweir     if (i != m_classInfos.end()) {
759cdf0e10cSrcweir         return i->second;
760cdf0e10cSrcweir     }
761cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
762cdf0e10cSrcweir     appendU1(m_constantPool, 7);
763cdf0e10cSrcweir     appendU2(m_constantPool, nameIndex);
764cdf0e10cSrcweir     if (!m_classInfos.insert(
765cdf0e10cSrcweir             std::map< sal_uInt16, sal_uInt16 >::value_type(nameIndex, index)).
766cdf0e10cSrcweir         second)
767cdf0e10cSrcweir     {
768cdf0e10cSrcweir         OSL_ASSERT(false);
769cdf0e10cSrcweir     }
770cdf0e10cSrcweir     return index;
771cdf0e10cSrcweir }
772cdf0e10cSrcweir 
773cdf0e10cSrcweir sal_uInt16 ClassFile::addStringInfo(rtl::OString const & value) {
774cdf0e10cSrcweir     sal_uInt16 stringIndex = addUtf8Info(value);
775cdf0e10cSrcweir     std::map< sal_uInt16, sal_uInt16 >::iterator i(
776cdf0e10cSrcweir         m_stringInfos.find(stringIndex));
777cdf0e10cSrcweir     if (i != m_stringInfos.end()) {
778cdf0e10cSrcweir         return i->second;
779cdf0e10cSrcweir     }
780cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
781cdf0e10cSrcweir     appendU1(m_constantPool, 8);
782cdf0e10cSrcweir     appendU2(m_constantPool, stringIndex);
783cdf0e10cSrcweir     if (!m_stringInfos.insert(
784cdf0e10cSrcweir             std::map< sal_uInt16, sal_uInt16 >::value_type(stringIndex, index)).
785cdf0e10cSrcweir         second)
786cdf0e10cSrcweir     {
787cdf0e10cSrcweir         OSL_ASSERT(false);
788cdf0e10cSrcweir     }
789cdf0e10cSrcweir     return index;
790cdf0e10cSrcweir }
791cdf0e10cSrcweir 
792cdf0e10cSrcweir sal_uInt16 ClassFile::addFieldrefInfo(
793cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
794cdf0e10cSrcweir     rtl::OString const & descriptor)
795cdf0e10cSrcweir {
796cdf0e10cSrcweir     sal_uInt16 classIndex = addClassInfo(type);
797cdf0e10cSrcweir     sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
798cdf0e10cSrcweir     sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
799cdf0e10cSrcweir         | nameAndTypeIndex;
800cdf0e10cSrcweir     std::map< sal_uInt32, sal_uInt16 >::iterator i(m_fieldrefInfos.find(key));
801cdf0e10cSrcweir     if (i != m_fieldrefInfos.end()) {
802cdf0e10cSrcweir         return i->second;
803cdf0e10cSrcweir     }
804cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
805cdf0e10cSrcweir     appendU1(m_constantPool, 9);
806cdf0e10cSrcweir     appendU2(m_constantPool, classIndex);
807cdf0e10cSrcweir     appendU2(m_constantPool, nameAndTypeIndex);
808cdf0e10cSrcweir     if (!m_fieldrefInfos.insert(
809cdf0e10cSrcweir             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
810cdf0e10cSrcweir     {
811cdf0e10cSrcweir         OSL_ASSERT(false);
812cdf0e10cSrcweir     }
813cdf0e10cSrcweir     return index;
814cdf0e10cSrcweir }
815cdf0e10cSrcweir 
816cdf0e10cSrcweir sal_uInt16 ClassFile::addMethodrefInfo(
817cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
818cdf0e10cSrcweir     rtl::OString const & descriptor)
819cdf0e10cSrcweir {
820cdf0e10cSrcweir     sal_uInt16 classIndex = addClassInfo(type);
821cdf0e10cSrcweir     sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
822cdf0e10cSrcweir     sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
823cdf0e10cSrcweir         | nameAndTypeIndex;
824cdf0e10cSrcweir     std::map< sal_uInt32, sal_uInt16 >::iterator i(m_methodrefInfos.find(key));
825cdf0e10cSrcweir     if (i != m_methodrefInfos.end()) {
826cdf0e10cSrcweir         return i->second;
827cdf0e10cSrcweir     }
828cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
829cdf0e10cSrcweir     appendU1(m_constantPool, 10);
830cdf0e10cSrcweir     appendU2(m_constantPool, classIndex);
831cdf0e10cSrcweir     appendU2(m_constantPool, nameAndTypeIndex);
832cdf0e10cSrcweir     if (!m_methodrefInfos.insert(
833cdf0e10cSrcweir             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
834cdf0e10cSrcweir     {
835cdf0e10cSrcweir         OSL_ASSERT(false);
836cdf0e10cSrcweir     }
837cdf0e10cSrcweir     return index;
838cdf0e10cSrcweir }
839cdf0e10cSrcweir 
840cdf0e10cSrcweir sal_uInt16 ClassFile::addInterfaceMethodrefInfo(
841cdf0e10cSrcweir     rtl::OString const & type, rtl::OString const & name,
842cdf0e10cSrcweir     rtl::OString const & descriptor)
843cdf0e10cSrcweir {
844cdf0e10cSrcweir     sal_uInt16 classIndex = addClassInfo(type);
845cdf0e10cSrcweir     sal_uInt16 nameAndTypeIndex = addNameAndTypeInfo(name, descriptor);
846cdf0e10cSrcweir     sal_uInt32 key = (static_cast< sal_uInt32 >(classIndex) << 16)
847cdf0e10cSrcweir         | nameAndTypeIndex;
848cdf0e10cSrcweir     std::map< sal_uInt32, sal_uInt16 >::iterator i(
849cdf0e10cSrcweir         m_interfaceMethodrefInfos.find(key));
850cdf0e10cSrcweir     if (i != m_interfaceMethodrefInfos.end()) {
851cdf0e10cSrcweir         return i->second;
852cdf0e10cSrcweir     }
853cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
854cdf0e10cSrcweir     appendU1(m_constantPool, 11);
855cdf0e10cSrcweir     appendU2(m_constantPool, classIndex);
856cdf0e10cSrcweir     appendU2(m_constantPool, nameAndTypeIndex);
857cdf0e10cSrcweir     if (!m_interfaceMethodrefInfos.insert(
858cdf0e10cSrcweir             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
859cdf0e10cSrcweir     {
860cdf0e10cSrcweir         OSL_ASSERT(false);
861cdf0e10cSrcweir     }
862cdf0e10cSrcweir     return index;
863cdf0e10cSrcweir }
864cdf0e10cSrcweir 
865cdf0e10cSrcweir sal_uInt16 ClassFile::addNameAndTypeInfo(
866cdf0e10cSrcweir     rtl::OString const & name, rtl::OString const & descriptor)
867cdf0e10cSrcweir {
868cdf0e10cSrcweir     sal_uInt16 nameIndex = addUtf8Info(name);
869cdf0e10cSrcweir     sal_uInt16 descriptorIndex = addUtf8Info(descriptor);
870cdf0e10cSrcweir     sal_uInt32 key = (static_cast< sal_uInt32 >(nameIndex) << 16)
871cdf0e10cSrcweir         | descriptorIndex;
872cdf0e10cSrcweir     std::map< sal_uInt32, sal_uInt16 >::iterator i(
873cdf0e10cSrcweir         m_nameAndTypeInfos.find(key));
874cdf0e10cSrcweir     if (i != m_nameAndTypeInfos.end()) {
875cdf0e10cSrcweir         return i->second;
876cdf0e10cSrcweir     }
877cdf0e10cSrcweir     sal_uInt16 index = nextConstantPoolIndex(1);
878cdf0e10cSrcweir     appendU1(m_constantPool, 12);
879cdf0e10cSrcweir     appendU2(m_constantPool, nameIndex);
880cdf0e10cSrcweir     appendU2(m_constantPool, descriptorIndex);
881cdf0e10cSrcweir     if (!m_nameAndTypeInfos.insert(
882cdf0e10cSrcweir             std::map< sal_uInt32, sal_uInt16 >::value_type(key, index)).second)
883cdf0e10cSrcweir     {
884cdf0e10cSrcweir         OSL_ASSERT(false);
885cdf0e10cSrcweir     }
886cdf0e10cSrcweir     return index;
887cdf0e10cSrcweir }
888cdf0e10cSrcweir 
889cdf0e10cSrcweir void ClassFile::appendSignatureAttribute(
890cdf0e10cSrcweir     std::vector< unsigned char > & stream, rtl::OString const & signature)
891cdf0e10cSrcweir {
892cdf0e10cSrcweir     if (signature.getLength() != 0) {
893cdf0e10cSrcweir         appendU2(
894cdf0e10cSrcweir             stream,
895cdf0e10cSrcweir             addUtf8Info(rtl::OString(RTL_CONSTASCII_STRINGPARAM("Signature"))));
896cdf0e10cSrcweir         appendU4(stream, 2);
897cdf0e10cSrcweir         appendU2(stream, addUtf8Info(signature));
898cdf0e10cSrcweir     }
899cdf0e10cSrcweir }
900