GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
ConstantDefinition.java
Go to the documentation of this file.
1/**
2 * Copyright 2015 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.gluegen;
29
30import java.math.BigInteger;
31import java.util.Map;
32import java.util.regex.Matcher;
33import java.util.regex.Pattern;
34
35import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
36import com.jogamp.gluegen.cgram.types.AliasedSymbol.AliasedSymbolImpl;
37import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
38import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
39
40/**
41 * Represents a [native] constant expression,
42 * comprises the [native] expression, see {@link #getNativeExpr()}
43 * and the optional {@link CNumber} representation, see {@link #getNumber()}.
44 * <p>
45 * The representation of the equivalent java expression including
46 * the result type is covered by {@link JavaExpr},
47 * which can be computed via {@link #computeJavaExpr(Map)}.
48 * </p>
49 * <p>
50 * This class and its sub-classes define and convert all native expressions
51 * to Java space.
52 * </p>
53 */
55 public static final long UNSIGNED_INT_MAX_VALUE = 0xffffffffL;
56 public static final BigInteger UNSIGNED_LONG_MAX_VALUE = new BigInteger("ffffffffffffffff", 16);
57
58 /**
59 * A Number, either integer, optionally [long, unsigned],
60 * or floating point, optionally [double].
61 */
62 public static class CNumber {
63 /**
64 * {@code true} if number is integer and value stored in {@link #i},
65 * otherwise {@code false} for floating point and value stored in {@link #f}.
66 */
67 public final boolean isInteger;
68 /** {@code true} if number is a {@code long} {@link #isInteger}. */
69 public final boolean isLong;
70 /** {@code true} if number is an {@code unsigned} {@link #isInteger}. */
71 public final boolean isUnsigned;
72 /** The value if {@link #isInteger} */
73 public final long i;
74
75 /** {@code true} if number is a {@code double precision} {@code floating point}, i.e. !{@link #isInteger}. */
76 public final boolean isDouble;
77 /** The value if !{@link #isInteger} */
78 public final double f;
79
80 /** ctor for integer number */
81 public CNumber(final boolean isLong, final boolean isUnsigned, final long value) {
82 this.isInteger = true;
83 this.isLong = isLong;
84 this.isUnsigned = isUnsigned;
85 this.i = value;
86 this.isDouble = false;
87 this.f = 0.0;
88 }
89 /** ctor for floating point number */
90 public CNumber(final boolean isDouble, final double value) {
91 this.isInteger = false;
92 this.isLong = false;
93 this.isUnsigned = false;
94 this.i = 0;
95 this.isDouble = isDouble;
96 this.f = value;
97 }
98 @Override
99 public int hashCode() {
100 return isInteger ? Long.valueOf(i).hashCode() : Double.valueOf(f).hashCode();
101 }
102 @Override
103 public boolean equals(final Object arg) {
104 if (arg == this) {
105 return true;
106 } else if ( !(arg instanceof CNumber) ) {
107 return false;
108 }
109 final CNumber t = (CNumber) arg;
110 return isInteger == t.isInteger &&
111 ( isInteger ? i == t.i : f == t.f );
112 }
113 public final String toJavaString() {
114 if( isInteger ) {
115 if( i >= 0 || isUnsigned ) {
116 if( isLong ) {
117 return "0x"+Long.toHexString(i)+"L";
118 } else {
119 return "0x"+Integer.toHexString((int)i);
120 }
121 } else {
122 if( isLong ) {
123 return String.valueOf(i)+"L";
124 } else {
125 return String.valueOf((int)i);
126 }
127 }
128 } else {
129 return String.valueOf(f) + ( !isDouble ? "f" : "");
130 }
131 }
132 @Override
133 public final String toString() {
134 final StringBuilder sb = new StringBuilder();
135 sb.append("[");
136 if( isInteger ) {
137 if( isUnsigned ) {
138 sb.append("unsigned ");
139 }
140 if( isLong) {
141 sb.append("long: ");
142 } else {
143 sb.append("int: ");
144 }
145 sb.append(i);
146 } else {
147 if( isDouble ) {
148 sb.append("double: ");
149 } else {
150 sb.append("float: ");
151 }
152 sb.append(f);
153 }
154 sb.append("]");
155 return sb.toString();
156 }
157 }
158
159 /**
160 * A valid java expression, including its result type,
161 * usually generated from a native [C] expression,
162 * see {@link JavaExpr#create(ConstantDefinition)}.
163 */
164 public static class JavaExpr {
165 public final String javaExpression;
166 public final CNumber resultType;
167 public final Number resultJavaType;
168 public final String resultJavaTypeName;
169 public JavaExpr(final String javaExpression, final CNumber resultType) {
170 this.javaExpression = javaExpression;
171 this.resultType = resultType;
172 if( resultType.isDouble ) {
173 resultJavaTypeName = "double";
174 resultJavaType = Double.valueOf(resultType.f);
175 } else if( !resultType.isInteger ) {
176 resultJavaTypeName = "float";
177 resultJavaType = Double.valueOf(resultType.f).floatValue();
178 } else if( resultType.isLong ) {
179 resultJavaTypeName = "long";
180 resultJavaType = Long.valueOf(resultType.i);
181 } else /* if( resultType.isInteger ) */ {
182 resultJavaTypeName = "int";
183 resultJavaType = Long.valueOf(resultType.i).intValue();
184 }
185 }
186 /**
187 * Computes a valid {@link JavaExpr java expression} based on the given {@link ConstantDefinition},
188 * which may either be a single {@link CNumber}, see {@link ConstantDefinition#getNumber()},
189 * or represents a native expression, see {@link ConstantDefinition#getExpr()}.
190 */
191 public static JavaExpr compute(final ConstantDefinition constDef,
192 final Map<String, ConstantDefinition.JavaExpr> constMap) {
193 final boolean debug = GlueGen.debug();
194 if( debug ) {
195 System.err.println("ConstJavaExpr.create: "+constDef);
196 }
197 if( constDef.hasNumber() ) {
198 // Already parsed as CNumber completely!
199 if( debug ) {
200 System.err.printf("V %s (isCNumber)%n", constDef);
201 }
202 return new JavaExpr(constDef.getNumber().toJavaString(), constDef.getNumber());
203 }
204 final StringBuilder javaExpr = new StringBuilder();
205 final String nativeExpr = constDef.getNativeExpr();
206
207 // "calculates" the result type of a simple expression
208 // example: (2+3)-(2.0f-3.0) -> Double
209 // example: (1 << 2) -> Integer
210 CNumber resultType = null;
211 final Matcher matcher = patternCPPOperand.matcher(nativeExpr);
212 int preStartIdx = 0;
213 int opEndIdx = 0;
214 while ( matcher.find() ) {
215 final int opStartIdx = matcher.start();
216 if( opStartIdx > preStartIdx ) {
217 final String sValue = nativeExpr.substring(preStartIdx, opStartIdx).trim();
218 if( sValue.length() > 0 ) {
219 if( debug ) {
220 System.err.printf("V %03d-%03d: %s%n", preStartIdx, opStartIdx, sValue);
221 }
222 resultType = processValue(constDef, sValue, constMap, resultType, javaExpr);
223 javaExpr.append(" ");
224 }
225 }
226 opEndIdx = matcher.end();
227 final String op = nativeExpr.substring(opStartIdx, opEndIdx);
228 if( debug ) {
229 System.err.printf("O %03d-%03d: %s%n", opStartIdx, opEndIdx, op);
230 }
231 javaExpr.append(op).append(" ");
232 preStartIdx = opEndIdx;
233 }
234 if( opEndIdx < nativeExpr.length() ) {
235 // tail ..
236 final String sValue = nativeExpr.substring(opEndIdx).trim();
237 if( sValue.length() > 0 ) {
238 if( debug ) {
239 System.err.printf("V %03d %03d-%03d: %s (tail)%n", preStartIdx, opEndIdx, nativeExpr.length(), sValue);
240 }
241 resultType = processValue(constDef, sValue, constMap, resultType, javaExpr);
242 }
243 }
244 final String javaExprS = javaExpr.toString().trim();
245 if( null == resultType ) {
246 throw new GlueGenException("Cannot emit const \""+constDef.getName()+"\": value \""+nativeExpr+
247 "\", parsed \""+javaExprS+"\" does not contain a constant number", constDef.getASTLocusTag());
248 }
249 return new JavaExpr(javaExprS, resultType);
250 }
251 private static CNumber processValue(final ConstantDefinition constDef,
252 final String sValue,
253 final Map<String, ConstantDefinition.JavaExpr> constMap,
255 final StringBuilder javaExpr) {
256 final CNumber nValue = getANumber(constDef, sValue);
257 if( null != nValue ) {
258 resultType = evalType(resultType , nValue);
259 javaExpr.append(nValue.toJavaString());
260 } else {
261 // Lookup CNumber type in const-map, to evaluate this result type
262 final JavaExpr cje = constMap.get(sValue);
263 if( null != cje ) {
264 resultType = evalType(resultType , cje.resultType);
265 }
266 javaExpr.append(sValue);
267 }
268 return resultType;
269 }
270 private static CNumber getANumber(final ConstantDefinition constDef, final String value) {
271 try {
272 final CNumber number = decodeANumber(value);
273 if( null != number ) {
274 return number;
275 }
276 } catch( final Throwable _t ) {
277 final String msg = "Cannot emit const \""+constDef.getName()+"\": value \""+value+
278 "\" cannot be assigned to a int, long, float, or double";
279 throw new GlueGenException(msg, constDef.getASTLocusTag(), _t);
280 }
281 return null;
282 }
283 private static CNumber evalType(final CNumber resultType, final CNumber type) {
284 //fast path
285 if( type.isDouble ) {
286 return type;
287 }
288 if( null != resultType ) {
289 if( resultType.isInteger ) {
290 if( resultType.isLong ) {
291 /* resultType is Long */
292 if( !type.isInteger ) {
293 /* resultType: Long -> [ Float || Double ] */
294 return type;
295 }
296 } else if( type.isLong || !type.isInteger ) {
297 /* resultType: Integer -> [ Long || Float || Double ] */
298 return type;
299 }
300 } else if( !resultType.isInteger && !resultType.isDouble ) {
301 if( type.isDouble ) {
302 /* resultType: Float -> Double */
303 return type;
304 }
305 }
306 } else {
307 return type;
308 }
309 return resultType;
310 }
311 }
312
313 private final boolean relaxedEqSem;
314 private final String nativeExpr;
315 private final CNumber number;
316 private final boolean isEnum;
317 private final String enumName;
318 private final ASTLocusTag astLocus;
319
320 /**
321 * Constructor for plain const-values, non-enumerates.
322 * @param name unique name of this constant expression
323 * @param nativeExpr original [native] expression
324 * @param number optional {@link CNumber} representing this constant.
325 * If {@code null}, implementation attempts to derive a {@link CNumber}
326 * of the given {@code nativeExpr}.
327 * @param astLocus AST location of the represented constant.
328 */
329 public ConstantDefinition(final String name,
330 final String nativeExpr,
331 final CNumber number,
332 final ASTLocusTag astLocus) {
333 this(name, nativeExpr, number, false, null, astLocus);
334 }
335 /**
336 * Constructor for enumerates
337 * @param name unique name of this constant expression
338 * @param nativeExpr original [native] expression
339 * @param number optional {@link CNumber} representing this constant.
340 * If {@code null}, implementation attempts to derive a {@link CNumber}
341 * of the given {@code nativeExpr}.
342 * @param enumName optional name of the represented enumeration
343 * @param astLocus AST location of the represented constant.
344 */
345 public ConstantDefinition(final String name,
346 final String nativeExpr,
347 final CNumber number,
348 final String enumName, final ASTLocusTag astLocus) {
349 this(name, nativeExpr, number, true, enumName, astLocus);
350 }
351 /**
352 * @param name unique name of this constant expression
353 * @param nativeExpr original [native] expression
354 * @param number optional {@link CNumber} representing this constant.
355 * If {@code null}, implementation attempts to derive a {@link CNumber}
356 * of the given {@code nativeExpr}.
357 * @param isEnum {@code true} if this constant is an enumerate, otherwise {@code false}.
358 * @param enumName optional name of the represented enumeration
359 * @param astLocus AST location of the represented constant.
360 */
361 private ConstantDefinition(final String name,
362 final String nativeExpr,
363 final CNumber number,
364 final boolean isEnum, final String enumName, final ASTLocusTag astLocus) {
365 super(name);
366 this.nativeExpr = nativeExpr;
367 this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
368 if( null != number ) {
369 this.number = number;
370 } else {
371 // Attempt to parse define string as number
372 final CNumber iNum = decodeIntegerNumber(nativeExpr);
373 if( null != iNum ) {
374 this.number = iNum;
375 } else {
376 final CNumber fNum = decodeDecimalNumber(nativeExpr);
377 if( null != fNum ) {
378 this.number = fNum;
379 } else {
380 this.number = null;
381 }
382 }
383 }
384 this.isEnum = isEnum;
385 this.enumName = enumName;
386 this.astLocus = astLocus;
387 }
388
389 @Override
390 public ASTLocusTag getASTLocusTag() { return astLocus; }
391
392 /**
393 * Hash by its given {@link #getName() name}.
394 */
395 @Override
396 public final int hashCode() {
397 return getName().hashCode();
398 }
399
400 /**
401 * Equality test by its given {@link #getName() name}.
402 */
403 @Override
404 public final boolean equals(final Object arg) {
405 if (arg == this) {
406 return true;
407 } else if ( !(arg instanceof ConstantDefinition) ) {
408 return false;
409 } else {
411 return equals(getName(), t.getName());
412 }
413 }
414
415 @Override
416 public final int hashCodeSemantics() {
417 // 31 * x == (x << 5) - x
418 int hash = 31 + ( null != getName() ? getName().hashCode() : 0 );
419 hash = ((hash << 5) - hash) + ( isEnum ? 1 : 0 );
420 hash = ((hash << 5) - hash) + ( null != enumName ? enumName.hashCode() : 0 );
421 hash = ((hash << 5) - hash) + ( null != number ? number.hashCode() : 0 );
422 return ((hash << 5) - hash) + ( !relaxedEqSem && null != nativeExpr ? nativeExpr.hashCode() : 0 );
423 }
424
425 @Override
426 public final boolean equalSemantics(final SemanticEqualityOp arg) {
427 if (arg == this) {
428 return true;
429 } else if ( !(arg instanceof ConstantDefinition) ) {
430 return false;
431 } else {
433 if( !equals(getName(), t.getName()) ||
434 isEnum != t.isEnum ||
435 !equals(enumName, t.enumName) ) {
436 return false;
437 }
438 if( null != number ) {
439 if( number.isInteger ) {
440 return number.i == t.number.i;
441 } else {
442 return number.f == t.number.f;
443 }
444 } else {
445 // define's string value may be semantical equal .. but formatted differently!
446 return relaxedEqSem || equals(nativeExpr, t.nativeExpr);
447 }
448 }
449 }
450
451 /** Returns the original [native] expression. */
452 public String getNativeExpr() { return nativeExpr; }
453 /**
454 * Returns the parsed {@link CNumber} of the {@link #getNativeExpr() native expression},
455 * or {@code null} if the latter does not comprise a single number,
456 * i.e. is a complex expression.
457 */
458 public CNumber getNumber() { return number; }
459 /**
460 * Returns {@code true} if this instance represents has a {@link #getNumber() number},
461 * otherwise {@code false}.
462 */
463 public boolean hasNumber() { return null != number; }
464
465 /** Returns {@code null} if this definition was not part of an
466 enumeration, or if the enumeration is anonymous. */
467 public String getEnumName() { return enumName; }
468
469 public boolean isEnum() { return isEnum; }
470
471 @Override
472 public String toString() {
473 return "ConstantDefinition [name \"" + getName()
474 + "\", expression \"" + nativeExpr
475 + "\", number "+number
476 + "], enum[is " + isEnum + ", name \"" + enumName + "\"]]";
477 }
478
479 private static boolean equals(final String s1, final String s2) {
480 if (s1 == null || s2 == null) {
481 if (s1 == null && s2 == null) {
482 return true;
483 }
484 return false;
485 }
486
487 return s1.equals(s2);
488 }
489
490 /**
491 * Computes the {@link JavaExpr java expression} based on this instance,
492 * see {@link JavaExpr#create(ConstantDefinition)}.
493 */
494 public final JavaExpr computeJavaExpr(final Map<String, ConstantDefinition.JavaExpr> constMap) {
495 return JavaExpr.compute(this, constMap);
496 }
497
498 //
499 // Static utility functions for type detection
500 //
501
502 public static boolean isConstantExpression(final String value) {
503 if( null != value && value.length() > 0 ) {
504 // Single numeric value
505 if ( isNumber(value) ) {
506 return true;
507 }
508 // Find constant expressions like (1 << 3)
509 // if found just pass them through, they will most likely work in java too
510 // expressions containing identifiers are currently ignored (casts too).
511 // The pattern includes 'patternCPPOperand', i.e. all supported operands used for constant-expression of define macros
512 final String[] values = value.split("[\\s\\+\\-\\*\\/\\|\\&\\(\\)]|(\\<\\<)|(\\>\\>)|(\\~)"); // [ whitespace '(' ')' ]
513 int numberCount = 0;
514 for (final String s : values) {
515 if( s.length() > 0 ) {
516 if( isCPPOperand(s) ) {
517 // OK
518 } else if ( isNumber(s) ) {
519 // OK
520 numberCount++;
521 } else {
522 return false;
523 }
524 }
525 }
526 final boolean res = numberCount > 0;
527 return res;
528 }
529 return false;
530 }
531
532 public static boolean isIdentifier(final String value) {
533 boolean identifier = false;
534
535 final char[] chars = value.toCharArray();
536
537 for (int i = 0; i < chars.length; i++) {
538 final char c = chars[i];
539 if (i == 0) {
540 if (Character.isJavaIdentifierStart(c)) {
541 identifier = true;
542 }
543 } else {
544 if (!Character.isJavaIdentifierPart(c)) {
545 identifier = false;
546 break;
547 }
548 }
549 }
550 return identifier;
551 }
552
553 /**
554 * Returns either {@link #decodeIntegerNumber(String)},
555 * {@link #decodeDecimalNumber(String)} or {@code null}.
556 * @param v
557 */
558 public static CNumber decodeANumber(final String v) {
560 if( null != iNumber ) {
561 return iNumber;
562 }
564 }
565
566 /**
567 * If the given string {@link #isIntegerNumber(String)},
568 * return the decoded integer value, represented as a {@code ANumber},
569 * otherwise returns {@code null}.
570 * <p>
571 * Method strips off sign prefix {@code +}
572 * and integer modifier suffixes {@code [uUlL]}
573 * before utilizing {@link Long#decode(String)}.
574 * </p>
575 * @param v
576 */
577 public static CNumber decodeIntegerNumber(final String v) {
578 if( null == v || !isIntegerNumber(v) ) {
579 return null;
580 }
581 String s0 = v.trim();
582 if( 0 == s0.length() ) {
583 return null;
584 }
585 if (s0.startsWith("+")) {
586 s0 = s0.substring(1, s0.length()).trim();
587 if( 0 == s0.length() ) {
588 return null;
589 }
590 }
591 final boolean neg;
592 if (s0.startsWith("-")) {
593 s0 = s0.substring(1, s0.length()).trim();
594 if( 0 == s0.length() ) {
595 return null;
596 }
597 neg = true;
598 } else {
599 neg = false;
600 }
601
602 // Test last two chars for [lL] and [uU] modifiers!
603 boolean isUnsigned = false;
604 boolean isLong = false;
605 final int j = s0.length() - 2;
606 for(int i = s0.length() - 1; i >= 0 && i >= j; i--) {
607 final char lastChar = s0.charAt(s0.length()-1);
608 if( lastChar == 'u' || lastChar == 'U' ) {
609 s0 = s0.substring(0, s0.length()-1);
610 isUnsigned = true;
611 } else if( lastChar == 'l' || lastChar == 'L' ) {
612 s0 = s0.substring(0, s0.length()-1);
613 isLong = true;
614 } else {
615 // early out, no modifier match!
616 break;
617 }
618 }
619 if( 0 == s0.length() ) {
620 return null;
621 }
622 final long res;
623 if( isLong && isUnsigned ) {
624 res = decodeULong(s0, neg);
625 } else {
626 if( neg ) {
627 s0 = "-" + s0;
628 }
629 res = Long.decode(s0).longValue();
630 }
631 final boolean isLong2 = isLong ||
632 ( !isUnsigned && ( Integer.MIN_VALUE > res || res > Integer.MAX_VALUE ) ) ||
633 ( isUnsigned && res > UNSIGNED_INT_MAX_VALUE );
634 return new CNumber(isLong2, isUnsigned, res);
635 }
636 private static long decodeULong(final String v, final boolean neg) throws NumberFormatException {
637 final int radix;
638 final int idx;
639 if (v.startsWith("0x") || v.startsWith("0X")) {
640 idx = 2;
641 radix = 16;
642 } else if (v.startsWith("#")) {
643 idx = 1;
644 radix = 16;
645 } else if (v.startsWith("0") && v.length() > 1) {
646 idx = 1;
647 radix = 8;
648 } else {
649 idx = 0;
650 radix = 10;
651 }
652 final String s0 = ( neg ? "-" : "" ) + v.substring(idx);
653 final BigInteger res = new BigInteger(s0, radix);
654 if( res.compareTo(UNSIGNED_LONG_MAX_VALUE) > 0 ) {
655 throw new NumberFormatException("Value \""+v+"\" is > UNSIGNED_LONG_MAX");
656 }
657 return res.longValue();
658 }
659
660 /**
661 * If the given string {@link #isDecimalNumber(String)},
662 * return the decoded floating-point value, represented as a {@code ANumber} object,
663 * otherwise returns {@code null}.
664 * <p>
665 * Method utilizes {@link Double#valueOf(String)}.
666 * </p>
667 * @param v
668 * @param isDouble return value for {@code double} flag
669 */
670 public static CNumber decodeDecimalNumber(final String v) {
671 if( null == v || !isDecimalNumber(v) ) {
672 return null;
673 }
674 final String s0 = v.trim();
675 if( 0 == s0.length() ) {
676 return null;
677 }
678 boolean _isDouble = false;
679 final char lastChar = s0.charAt(s0.length()-1);
680 if( lastChar == 'd' || lastChar == 'D' ) {
681 _isDouble = true;
682 }
683 final double res = Double.valueOf(s0).doubleValue();
684 final double ares = Math.abs(res);
685 return new CNumber(_isDouble || Float.MIN_VALUE > ares || ares > Float.MAX_VALUE, res);
686 }
687
688 /**
689 * Matches {@link #isHexNumber(String)} or {@link #isDecimalOrIntNumber(String)}.
690 */
691 public static boolean isNumber(final String s) {
692 if( isHexNumber(s) ) {
693 return true;
694 } else {
695 return isDecimalOrIntNumber(s);
696 }
697 }
698
699 /**
700 * Matches {@link #isHexNumber(String)} or {@link #patternIntegerNumber}.
701 */
702 public static boolean isIntegerNumber(final String s) {
703 if( isHexNumber(s) ) {
704 return true;
705 } else {
706 return patternIntegerNumber.matcher(s).matches();
707 }
708 }
709
710 /**
711 * Matches {@link #patternHexNumber}.
712 */
713 public static boolean isHexNumber(final String s) {
714 return patternHexNumber.matcher(s).matches();
715 }
716
717 /**
718 * Matches pattern for <code>floating point</code> number,
719 * compatible and described in {@link Double#valueOf(String)}.
720 */
721 public static boolean isDecimalNumber(final String s) {
722 return patternDecimalNumber.matcher(s).matches();
723 }
724
725 /**
726 * Complete pattern for <code>floating point</code> <i>and</i> <code>integer</code> number,
727 * covering {@link #patternDecimalNumber} <i>and</i> {@link #patternIntegerNumber}.
728 */
729 public static boolean isDecimalOrIntNumber(final String s) {
730 return patternDecimalOrIntNumber.matcher(s).matches();
731 }
732
733 /**
734 * Matches pattern for valid CPP operands, see {@link #patternCPPOperand}.
735 */
736 public static boolean isCPPOperand(final String s) {
737 return patternCPPOperand.matcher(s).matches();
738 }
739
740 /**
741 * Complete pattern for <code>hexadecimal</code> number,
742 * including an optional sign {@code [+-]} and optional suffixes {@code [uUlL]}.
743 */
744 public static Pattern patternHexNumber;
745
746 /**
747 * Complete pattern for <code>floating point</code> number,
748 * compatible and described in {@link Double#valueOf(String)}.
749 */
750 public final static Pattern patternDecimalNumber;
751
752 /**
753 * Complete pattern for <code>floating point</code> <i>and</i> <code>integer</code> number,
754 * covering {@link #patternDecimalNumber} <i>and</i> {@link #patternIntegerNumber}.
755 */
756 public final static Pattern patternDecimalOrIntNumber;
757
758 /**
759 * Complete pattern for <code>integer</code> number,
760 * including an optional sign {@code [+-]} and optional suffixes {@code [uUlL]}.
761 */
762 public final static Pattern patternIntegerNumber;
763
764 /**
765 * One of: {@code +} {@code -} {@code *} {@code /} {@code |} {@code &} {@code (} {@code )} {@code <<} {@code >>} {@code ~}
766 * <p>
767 * Expression excludes {@link #patternDecimalOrIntNumber}.
768 * </p>
769 */
770 public static Pattern patternCPPOperand;
771
772 static {
773 final String WhiteSpace = "[\\x00-\\x20]*";
774 final String Digits = "(\\p{Digit}+)";
775 final String HexDigits = "(\\p{XDigit}+)";
776 final String IntTypeSuffix =
777 "(" +
778 "[uU]|" +
779 "([uU][lL])|" +
780 "[lL]|" +
781 "([lL][uU])" +
782 ")";
783
784 final String hexRegex =
785 WhiteSpace + // Optional leading "whitespace"
786 "[+-]?" + // Optional sign character
787 // HexDigits IntTypeSuffix_opt
788 "0[xX]" + HexDigits + IntTypeSuffix + "?" +
789 WhiteSpace // Optional trailing "whitespace"
790 ;
791 patternHexNumber = Pattern.compile(hexRegex);
792
793 final String intRegex =
794 WhiteSpace + // Optional leading "whitespace"
795 "[+-]?" + // Optional sign character
796 // Digits IntTypeSuffix_opt
797 Digits + IntTypeSuffix + "?" +
798 WhiteSpace // Optional trailing "whitespace"
799 ;
800 patternIntegerNumber = Pattern.compile(intRegex);
801
802 // an exponent is 'e' or 'E' followed by an optionally
803 // signed decimal integer.
804 final String Exp = "[eE][+-]?"+Digits;
805 final String fpRegex =
806 WhiteSpace + // Optional leading "whitespace"
807 "[+-]?" + // Optional sign character
808 "("+
809 "NaN|" + // "NaN" string
810 "Infinity|" + // "Infinity" string
811
812 // A decimal floating-point string representing a finite positive
813 // number without a leading sign has at most five basic pieces:
814 // Digits . Digits ExponentPart FloatTypeSuffix
815 //
816 // Since this method allows integer-only strings as input
817 // in addition to strings of floating-point literals, the
818 // two sub-patterns below are simplifications of the grammar
819 // productions from the Java Language Specification, 2nd
820 // edition, section 3.10.2.
821
822 "("+
823 "("+
824 // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
825 "("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
826
827 // . Digits ExponentPart_opt FloatTypeSuffix_opt
828 "(\\.("+Digits+")("+Exp+")?)|"+
829
830 // Hexadecimal w/ binary exponent
831 "(" +
832 "(" +
833 // Hexadecimal strings
834 // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
835 "(0[xX]" + HexDigits + "(\\.)?)|" +
836
837 // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
838 "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
839 ")" +
840
841 // binary exponent
842 "[pP][+-]?" + Digits +
843 ")" +
844 ")" +
845 "[fFdD]?"+
846 ")"+
847 ")" +
848 WhiteSpace // Optional trailing "whitespace"
849 ;
850 patternDecimalNumber = Pattern.compile(fpRegex);
851
852 final String fpOrIntRegex =
853 WhiteSpace + // Optional leading "whitespace"
854 "[+-]?" + // Optional sign character
855 "("+
856 "NaN|" + // "NaN" string
857 "Infinity|" + // "Infinity" string
858
859 // Matching integers w/ IntTypeSuffix,
860 // which are otherwise not matched by the below floating point matcher!
861 // Digits IntTypeSuffix
862 "(" + Digits + IntTypeSuffix +")|" +
863
864 // A decimal floating-point string representing a finite positive
865 // number without a leading sign has at most five basic pieces:
866 // Digits . Digits ExponentPart FloatTypeSuffix
867 //
868 // Since this method allows integer-only strings as input
869 // in addition to strings of floating-point literals, the
870 // two sub-patterns below are simplifications of the grammar
871 // productions from the Java Language Specification, 2nd
872 // edition, section 3.10.2.
873
874 "("+
875 "("+
876 // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
877 "(" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|" +
878
879 // . Digits ExponentPart_opt FloatTypeSuffix_opt
880 "(\\.(" + Digits + ")(" + Exp + ")?)|" +
881
882 // Hexadecimal w/ binary exponent
883 "(" +
884 "(" +
885 // Hexadecimal strings
886 // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
887 "(0[xX]" + HexDigits + "(\\.)?)|" +
888
889 // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
890 "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
891 ")" +
892
893 // binary exponent
894 "[pP][+-]?" + Digits +
895 ")" +
896 ")" +
897 "[fFdD]?"+
898 ")"+
899 ")" +
900 WhiteSpace // Optional trailing "whitespace"
901 ;
902 patternDecimalOrIntNumber = Pattern.compile(fpOrIntRegex);
903
904 final String fpOrIntRegex2 =
905 WhiteSpace + // Optional leading "whitespace"
906 // "[+-]?" + // Optional sign character
907 "("+
908 "NaN|" + // "NaN" string
909 "Infinity|" + // "Infinity" string
910
911 // Matching integers w/ IntTypeSuffix,
912 // which are otherwise not matched by the below floating point matcher!
913 // Digits IntTypeSuffix
914 "(" + Digits + IntTypeSuffix +")|" +
915
916 // A decimal floating-point string representing a finite positive
917 // number without a leading sign has at most five basic pieces:
918 // Digits . Digits ExponentPart FloatTypeSuffix
919 //
920 // Since this method allows integer-only strings as input
921 // in addition to strings of floating-point literals, the
922 // two sub-patterns below are simplifications of the grammar
923 // productions from the Java Language Specification, 2nd
924 // edition, section 3.10.2.
925
926 "("+
927 "("+
928 // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
929 "(" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|" +
930
931 // . Digits ExponentPart_opt FloatTypeSuffix_opt
932 "(\\.(" + Digits + ")(" + Exp + ")?)|" +
933
934 // Hexadecimal w/ binary exponent
935 "(" +
936 "(" +
937 // Hexadecimal strings
938 // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
939 "(0[xX]" + HexDigits + "(\\.)?)|" +
940
941 // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
942 "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
943 ")" +
944
945 // binary exponent
946 "[pP][+-]?" + Digits +
947 ")" +
948 ")" +
949 "[fFdD]?"+
950 ")"+
951 ")" +
952 WhiteSpace // Optional trailing "whitespace"
953 ;
954 patternCPPOperand = Pattern.compile("(?!"+fpOrIntRegex2+")[\\+\\-\\*\\/\\|\\&\\(\\)]|(\\<\\<)|(\\>\\>)|(\\~)");
955 }
956}
A Number, either integer, optionally [long, unsigned], or floating point, optionally [double].
final boolean isInteger
true if number is integer and value stored in i, otherwise false for floating point and value stored ...
final boolean isDouble
true if number is a double precision floating point, i.e.
final boolean isUnsigned
true if number is an unsigned isInteger.
final double f
The value if !isInteger.
final boolean isLong
true if number is a long isInteger.
CNumber(final boolean isLong, final boolean isUnsigned, final long value)
ctor for integer number
CNumber(final boolean isDouble, final double value)
ctor for floating point number
A valid java expression, including its result type, usually generated from a native [C] expression,...
JavaExpr(final String javaExpression, final CNumber resultType)
static JavaExpr compute(final ConstantDefinition constDef, final Map< String, ConstantDefinition.JavaExpr > constMap)
Computes a valid java expression based on the given ConstantDefinition, which may either be a single ...
Represents a [native] constant expression, comprises the [native] expression, see getNativeExpr() and...
static boolean isDecimalNumber(final String s)
Matches pattern for floating point number, compatible and described in Double#valueOf(String).
static boolean isHexNumber(final String s)
Matches patternHexNumber.
String getNativeExpr()
Returns the original [native] expression.
ConstantDefinition(final String name, final String nativeExpr, final CNumber number, final String enumName, final ASTLocusTag astLocus)
Constructor for enumerates.
static boolean isNumber(final String s)
Matches isHexNumber(String) or isDecimalOrIntNumber(String).
static Pattern patternCPPOperand
One of: + - * / | & ( ) << >> ~ @endiliteral.
ASTLocusTag getASTLocusTag()
Returns this instance's ASTLocusTag, if available, otherwise returns null.
static boolean isDecimalOrIntNumber(final String s)
Complete pattern for floating point and integer number, covering patternDecimalNumber and patternInte...
static final Pattern patternDecimalNumber
Complete pattern for floating point number, compatible and described in Double#valueOf(String).
final boolean equalSemantics(final SemanticEqualityOp arg)
Semantic equality test for Types exclusive its given name.
static CNumber decodeIntegerNumber(final String v)
If the given string isIntegerNumber(String), return the decoded integer value, represented as a ANumb...
static boolean isIdentifier(final String value)
boolean hasNumber()
Returns true if this instance represents has a number, otherwise false.
static final Pattern patternDecimalOrIntNumber
Complete pattern for floating point and integer number, covering patternDecimalNumber and patternInte...
static CNumber decodeANumber(final String v)
Returns either decodeIntegerNumber(String), decodeDecimalNumber(String) or null.
static final Pattern patternIntegerNumber
Complete pattern for integer number, including an optional sign [+-] and optional suffixes [uUlL].
CNumber getNumber()
Returns the parsed CNumber of the native expression, or null if the latter does not comprise a single...
static Pattern patternHexNumber
Complete pattern for hexadecimal number, including an optional sign [+-] and optional suffixes [uUlL]...
static boolean isConstantExpression(final String value)
String getEnumName()
Returns null if this definition was not part of an enumeration, or if the enumeration is anonymous.
ConstantDefinition(final String name, final String nativeExpr, final CNumber number, final ASTLocusTag astLocus)
Constructor for plain const-values, non-enumerates.
final int hashCodeSemantics()
Semantic hashcode for Types exclusive its given name.
static boolean isIntegerNumber(final String s)
Matches isHexNumber(String) or patternIntegerNumber.
final JavaExpr computeJavaExpr(final Map< String, ConstantDefinition.JavaExpr > constMap)
Computes the java expression based on this instance, see JavaExpr#create(ConstantDefinition).
static CNumber decodeDecimalNumber(final String v)
If the given string isDecimalNumber(String), return the decoded floating-point value,...
final boolean equals(final Object arg)
Equality test by its given name.
final int hashCode()
Hash by its given name.
static boolean isCPPOperand(final String s)
Matches pattern for valid CPP operands, see patternCPPOperand.
static final BigInteger UNSIGNED_LONG_MAX_VALUE
A generic exception for Jogamp errors used throughout the binding as a substitute for RuntimeExceptio...
Glue code generator for C functions and data structures.
Definition: GlueGen.java:59
Static Type config helper binding JavaConfiguration#relaxedEqualSemanticsTest() system wide.
Definition: TypeConfig.java:37
String getName()
Return the current-name, which is the last renamed-name if issued, or the original-name.
Interface tag for ASTLocusTag provider.
Supports common interface for SemanticEqualityOp and AliasedSymbol.
Supports semantic equality and hash functions for types.