All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jme3.lwjgl3.utils.APIUtil Maven / Gradle / Ivy

There is a newer version: 3.7.0-stable
Show newest version
/*
 * Copyright LWJGL. All rights reserved.
 * License terms: http://lwjgl.org/license.php
 */
package com.jme3.lwjgl3.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Utility class useful to API bindings. [INTERNAL USE ONLY]
 *
 * 

* Method names in this class are prefixed with {@code api} to avoid ambiguities * when used with static imports.

*/ public final class APIUtil { private static final ThreadLocal API_BUFFERS = ThreadLocal.withInitial(APIBuffer::new); private APIUtil() { } /** * Converts dynamic arguments to object array. * * @param arguments the list of arguments. * @return the object array. */ @SafeVarargs public static T[] toArray(T... arguments) { return arguments; } /** * Returns a thread-local {@link APIBuffer} that has been reset. */ public static APIBuffer apiBuffer() { return API_BUFFERS.get().reset(); } /** * Returns a thread-local {@link APIBuffer}, without resetting it. This * makes the APIBuffer work like a stack when used in nested API calls. The * user is responsible for resetting the {@link APIBuffer} to an appropriate * state before the nested call returns. * * @see APIBuffer#pop */ public static APIBuffer apiStack() { return API_BUFFERS.get().push(); } /** * A data class for API versioning information. */ public static class APIVersion { /** * Returns the API major version. */ public final int major; /** * Returns the API minor version. */ public final int minor; /** * Returns the API revision. May be null. */ public final String revision; /** * Returns the API implementation-specific versioning information. May * be null. */ public final String implementation; public APIVersion(int major, int minor) { this(major, minor, null, null); } public APIVersion(int major, int minor, String revision, String implementation) { this.major = major; this.minor = minor; this.revision = revision; this.implementation = implementation; } } /** * Parses a version string. The version string must have the format * {@code MAJOR.MINOR.REVISION IMPL}, where {@code MAJOR} is the major * version (integer), {@code MINOR} is the minor version (integer), * {@code REVISION} is the revision version (string, optional) and * {@code IMPL} is implementation-specific information (string, optional). * * @param version the API version string * * @return the parsed {@link APIVersion} */ public static APIVersion apiParseVersion(String version) { return apiParseVersion(version, null); } /** * Parses a version string. The version string must have the format * {@code PREFIX MAJOR.MINOR.REVISION IMPL}, where {@code PREFIX} is the * specified prefix (string, optional), {@code MAJOR} is the major version * (integer), {@code MINOR} is the minor version (integer), {@code REVISION} * is the revision version (string, optional) and {@code IMPL} is * implementation-specific information (string, optional). * * @param version the version string * @param prefix the version string prefix, may be null * * @return the parsed {@link APIVersion} */ public static APIVersion apiParseVersion(String version, String prefix) { String pattern = "([0-9]+)[.]([0-9]+)([.]\\S+)?\\s*(.+)?"; if (prefix != null) { pattern = prefix + "\\s+" + pattern; } Matcher matcher = Pattern.compile(pattern).matcher(version); if (!matcher.matches()) { throw new IllegalArgumentException(String.format("Malformed API version string [%s]", version)); } return new APIVersion( Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)), matcher.group(3), matcher.group(4) ); } public static String apiUnknownToken(int token) { return apiUnknownToken("Unknown", token); } public static String apiUnknownToken(String description, int token) { return String.format("%s [0x%X]", description, token); } /** * Returns a map of public static final integer fields in the specified * classes, to their String representations. An optional filter can be * specified to only include specific fields. The target map may be null, in * which case a new map is allocated and returned. * *

* This method is useful when debugging to quickly identify values returned * from an API.

* * @param filter the filter to use (optional) * @param target the target map (optional) * @param tokenClasses the classes to get tokens from * * @return the token map */ public static Map apiClassTokens(TokenFilter filter, Map target, Class... tokenClasses) { if (target == null) { target = new HashMap(64); } int TOKEN_MODIFIERS = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL; for (Class tokenClass : tokenClasses) { if (tokenClass == null) { continue; } for (Field field : tokenClass.getDeclaredFields()) { // Get only fields. if ((field.getModifiers() & TOKEN_MODIFIERS) == TOKEN_MODIFIERS && field.getType() == int.class) { try { int value = field.getInt(null); if (filter != null && !filter.accept(field, value)) { continue; } String name = target.get(value); target.put(value, name == null ? field.getName() : name + "|" + field.getName()); } catch (IllegalAccessException e) { // Ignore } } } } return target; } public static Class apiOptionalClass(String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { return null; } } /** * Simple interface for Field filtering. */ public interface TokenFilter { /** * Should return true if the specified Field passes the filter. * * @param field the Field to test * @param value the integer value of the field * * @return true if the Field is accepted */ boolean accept(Field field, int value); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy