1
2
3
4
5
6
7
8
9
10
11 package com.legstar.coxb.convert.simple;
12
13 import com.legstar.coxb.CobolContext;
14 import com.legstar.coxb.ICobolArrayFloatBinding;
15 import com.legstar.coxb.ICobolFloatBinding;
16 import com.legstar.coxb.convert.ICobolFloatConverter;
17 import com.legstar.coxb.convert.CobolConversionException;
18 import com.legstar.coxb.host.HostData;
19 import com.legstar.coxb.host.HostException;
20 import com.legstar.coxb.host.HostFloat;
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25
26
27
28
29
30
31
32 public class CobolFloatSimpleConverter extends CobolSimpleConverter
33 implements ICobolFloatConverter {
34
35
36
37
38 public CobolFloatSimpleConverter(final CobolContext cobolContext) {
39 super(cobolContext);
40 }
41
42
43 public int toHost(
44 final ICobolFloatBinding ce,
45 final byte[] hostTarget,
46 final int offset)
47 throws HostException {
48 int newOffset = 0;
49 try {
50 newOffset = toHostSingle(ce.getFloatValue(),
51 hostTarget,
52 offset);
53 } catch (CobolConversionException e) {
54 throwHostException(ce, e);
55 }
56 return newOffset;
57 }
58
59
60 public int toHost(
61 final ICobolArrayFloatBinding ce,
62 final byte[] hostTarget,
63 final int offset,
64 final int currentOccurs)
65 throws HostException {
66 int newOffset = offset;
67 try {
68 for (Float javaSource : ce.getFloatList()) {
69 newOffset = toHostSingle(javaSource,
70 hostTarget,
71 newOffset);
72 }
73
74 for (int i = ce.getFloatList().size(); i < currentOccurs; i++) {
75 newOffset = toHostSingle(Float.valueOf(0),
76 hostTarget,
77 newOffset);
78 }
79 } catch (CobolConversionException e) {
80 throwHostException(ce, e);
81 }
82 return newOffset;
83 }
84
85
86 public int fromHost(
87 final ICobolFloatBinding ce,
88 final byte[] hostSource,
89 final int offset)
90 throws HostException {
91 int newOffset = offset;
92 try {
93 Float javaFloat = fromHostSingle(ce.getByteLength(),
94 hostSource,
95 newOffset);
96 ce.setFloatValue(javaFloat);
97 newOffset += ce.getByteLength();
98 } catch (CobolConversionException e) {
99 throwHostException(ce, e);
100 }
101 return newOffset;
102 }
103
104
105 public int fromHost(
106 final ICobolArrayFloatBinding ce,
107 final byte[] hostSource,
108 final int offset,
109 final int currentOccurs)
110 throws HostException {
111 List < Float > lArray = new ArrayList < Float >();
112 int newOffset = offset;
113 try {
114 for (int i = 0; i < currentOccurs; i++) {
115 Float javaFloat = fromHostSingle(ce.getItemByteLength(),
116 hostSource,
117 newOffset);
118 lArray.add(javaFloat);
119 newOffset += ce.getItemByteLength();
120 }
121 ce.setFloatList(lArray);
122 } catch (CobolConversionException e) {
123 throwHostException(ce, e);
124 }
125 return newOffset;
126 }
127
128
129
130
131
132
133
134
135
136
137 public static final int toHostSingle(
138 final Float javaFloat,
139 final byte[] hostTarget,
140 final int offset)
141 throws CobolConversionException {
142
143
144 int cobolByteLength = 4;
145
146
147 int lastOffset = offset + cobolByteLength;
148 if (lastOffset > hostTarget.length) {
149 throw (new CobolConversionException(
150 "Attempt to write past end of host source buffer",
151 new HostData(hostTarget), offset));
152 }
153
154
155 Float localFloat = javaFloat;
156 if (localFloat == null) {
157 localFloat = 0f;
158 }
159
160
161 if (localFloat.isInfinite()) {
162 throw (new CobolConversionException(
163 "Infinite floats are not supported",
164 new HostData(hostTarget), offset));
165 }
166 if (localFloat.isNaN()) {
167 throw (new CobolConversionException(
168 "NaN floats are not supported",
169 new HostData(hostTarget), offset));
170 }
171
172
173
174
175
176 if ((localFloat.floatValue() == 0.0f)
177 ||
178 (localFloat.floatValue() == -0.0f)) {
179 for (int i = 0; i < 4; i++) {
180 hostTarget[offset + i] = 0;
181 }
182 return offset + cobolByteLength;
183 }
184
185
186 HostFloat jF = parseJavaFloat(localFloat);
187
188
189 HostFloat hF = new HostFloat();
190 hF.setSign(jF.getSign());
191
192
193
194
195
196
197
198 int r = jF.getExponent() % 4;
199 int mantissaShift = 0;
200 if (r <= 0) {
201 mantissaShift = -1 * r;
202 } else {
203 mantissaShift = 4 - r;
204 }
205
206 hF.setExponent((jF.getExponent() + mantissaShift) / 4);
207 hF.setMantissa(jF.getMantissa() >> mantissaShift);
208
209
210 int hostIntBits = createHostFloat(hF);
211
212
213 for (int i = 0; i < 4; i++) {
214 hostTarget[offset + i] = (byte) ((hostIntBits >>> (24 - i * 8)) & 0xff);
215 }
216
217 return offset + cobolByteLength;
218 }
219
220
221
222
223
224
225
226
227
228
229 public static final Float fromHostSingle(
230 final int cobolByteLength,
231 final byte[] hostSource,
232 final int offset)
233 throws CobolConversionException {
234
235 int lastOffset = offset + cobolByteLength;
236
237
238
239
240
241
242 if (lastOffset > hostSource.length) {
243 return Float.valueOf(0f);
244 }
245
246
247 int hostIntBits = 0;
248 for (int i = 0; i < 4; i++) {
249 hostIntBits = hostIntBits
250 | ((hostSource[offset + (3 - i)] & 0xff) << (i * 8));
251 }
252 HostFloat hF = parseHostFloat(hostIntBits);
253
254
255 HostFloat jF = new HostFloat();
256 jF.setSign(hF.getSign());
257
258
259
260
261
262
263 if (hF.getMantissa() != 0) {
264 jF.setExponent((4 * hF.getExponent()) - 1);
265 }
266
267
268 jF.setMantissa(hF.getMantissa());
269
270
271 while ((jF.getMantissa() > 0) && (jF.getMantissa() & 0x00800000) == 0) {
272 jF.setMantissa(jF.getMantissa() << 1);
273 jF.setExponent(jF.getExponent() - 1);
274 }
275
276 return createJavaFloat(jF);
277 }
278
279
280
281
282
283
284
285 public static final HostFloat parseJavaFloat(final float f) {
286 HostFloat jF = new HostFloat();
287
288 if (f == 0.0f) {
289 return jF;
290 }
291
292 int javaIntBits = Float.floatToIntBits(f);
293
294
295 jF.setSign((javaIntBits & 0x80000000) >>> 31);
296
297
298
299
300
301
302
303
304
305 int excess = (javaIntBits & 0x7f800000) >>> 23;
306 jF.setExponent(excess - 127 + 1);
307
308
309
310
311
312
313
314 int orMask = 1 << 23;
315 jF.setMantissa(javaIntBits & 0x007fffff | orMask);
316
317 return jF;
318 }
319
320
321
322
323
324
325
326
327 public static final float createJavaFloat(final HostFloat jF) {
328
329 if (jF.getExponent() == 0 && jF.getMantissa() == 0) {
330 return 0f;
331 }
332
333
334 int javaIntBits = jF.getMantissa() & 0x007fffff;
335 javaIntBits = javaIntBits | ((jF.getExponent() + 127) << 23);
336 javaIntBits = javaIntBits | (jF.getSign() << 31);
337 return Float.intBitsToFloat(javaIntBits);
338 }
339
340
341
342
343
344
345
346 public static final HostFloat parseHostFloat(final int hostIntBits) {
347
348 HostFloat hF = new HostFloat();
349
350
351 hF.setSign((hostIntBits & 0x80000000) >>> 31);
352
353
354
355
356
357
358 int excess = (hostIntBits & 0x7f000000) >>> 24;
359 if (excess != 0) {
360 hF.setExponent((excess - 64));
361 }
362
363
364 hF.setMantissa(hostIntBits & 0x00ffffff);
365
366 return hF;
367 }
368
369
370
371
372
373
374
375
376 public static final int createHostFloat(final HostFloat hF) {
377
378
379 if (hF.getExponent() == 0 && hF.getMantissa() == 0) {
380 return 0;
381 }
382
383 int hostIntBits = hF.getMantissa();
384 hostIntBits = hostIntBits | ((hF.getExponent() + 64) << 24);
385 hostIntBits = hostIntBits | (hF.getSign() << 31);
386 return hostIntBits;
387 }
388 }