1 /* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.apple.internal.jobjc.generator.model; 26 27 import java.util.Arrays; 28 29 import org.w3c.dom.Node; 30 31 import com.apple.internal.jobjc.generator.model.types.Type; 32 import com.apple.internal.jobjc.generator.model.types.JType.JPrimitive; 33 import com.apple.internal.jobjc.generator.model.types.NType.NPrimitive; 34 import com.apple.internal.jobjc.generator.utils.Fp; 35 import com.apple.jobjc.JObjCRuntime; 36 37 public class NativeEnum extends ElementWType<Framework> { 38 public final String value, value64, le_value, be_value; 39 public boolean ignore; 40 public String suggestion; 41 public NativeEnum(final Node node, final Framework parent) { 42 super(node, typeForEnum(getAttr(node, "name"), 43 getAttr(node, "value"), getAttr(node, "value64"), 44 getAttr(node, "le_value"), getAttr(node, "be_value"), 45 getAttr(node, "ignore")), parent); 46 this.value = getAttr(node, "value"); 47 this.value64 = getAttr(node, "value64"); 48 this.le_value = getAttr(node, "le_value"); 49 this.be_value = getAttr(node, "be_value"); 50 String ignoreS = getAttr(node, "ignore"); 51 this.ignore = ignoreS == null ? false : Boolean.parseBoolean(ignoreS); 52 this.suggestion = getAttr(node, "suggestion"); 53 assert valueToString() != null; 54 } 55 56 private static Type typeForEnum(String name, String value32, String value64, String le_value, String be_value, String ignore){ 57 if("true".equals(ignore)) return Type.getType(null, NPrimitive.inst('i'), null); 58 59 NumTest[] tests = new NumTest[]{new IntTest(), new LongTest(), new FloatTest(), new DoubleTest()}; 60 for(NumTest t : tests) 61 if(t.confirm(value32, value64, le_value, be_value)) 62 return t.getType(); 63 64 throw new NumberFormatException(String.format("Failed to parse type for enum: %1$s = 32: %2$s / 64: %3$s / le: %4$s / be: %5$s\n", 65 name, value32, value64, le_value, be_value)); 66 } 67 68 public String valueToString(){ 69 if(ignore == true) return "0"; 70 JPrimitive jprim = (JPrimitive) type.getJType(); 71 if(le_value == null && be_value == null){ 72 if(value == null && value64 != null) 73 return value64 + jprim.getLiteralSuffix(); 74 else if(value != null && value64 == null) 75 return value + jprim.getLiteralSuffix(); 76 else 77 return String.format("(%1$s.IS64 ? %2$s%4$s : %3$s%4$s)", JObjCRuntime.class.getName(), 78 value64, value, jprim.getLiteralSuffix()); 79 } 80 else if(value == null && value64 == null){ 81 return String.format("(%1$s.IS_BIG_ENDIAN ? %2$s%4$s : %3$s%4$s)", 82 JObjCRuntime.class.getName(), be_value, le_value, jprim.getLiteralSuffix()); 83 } 84 85 throw new RuntimeException("Unable to produce a value for enum " + name); 86 } 87 88 // Used to find the best type to use for the enum. 89 90 static abstract class NumTest{ 91 public boolean confirm(String... values){ 92 return Fp.all(new Fp.Map1<String,Boolean>(){ 93 public Boolean apply(String a) { 94 try{ return a == null || confirm(a); } 95 catch(Exception x){ return false; } 96 }}, 97 Arrays.asList(values)); 98 } 99 100 public abstract boolean confirm(String v); 101 public abstract Type getType(); 102 } 103 104 static class IntTest extends NumTest{ 105 @Override public boolean confirm(String v) { 106 Integer.parseInt(v); 107 return true; 108 } 109 110 @Override public Type getType() { return Type.getType(null, NPrimitive.inst('i'), null); } 111 } 112 113 static class LongTest extends NumTest{ 114 @Override public boolean confirm(String v) { 115 Long.parseLong(v); 116 return true; 117 } 118 119 @Override public Type getType() { return Type.getType(null, NPrimitive.inst('l'), null); } 120 } 121 122 static class FloatTest extends NumTest{ 123 @Override public boolean confirm(String v) { 124 return Float.parseFloat(v) == Double.parseDouble(v); 125 } 126 127 @Override public Type getType() { return Type.getType(null, NPrimitive.inst('f'), null); } 128 } 129 130 static class DoubleTest extends NumTest{ 131 @Override public boolean confirm(String v) { 132 double d = Double.parseDouble(v); 133 return !Double.isInfinite(d) && !Double.isNaN(d); 134 } 135 136 @Override public Type getType() { return Type.getType(null, NPrimitive.inst('d'), null); } 137 } 138 }