alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (GlobalFunctions.java)

This example Java source code file (GlobalFunctions.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789\@\*_, class, encode_uri, globalfunctions, infinity, is_finite, methodhandle, nan, numberformatexception, object, parseint, string, stringbuilder, unescape, util

The GlobalFunctions.java Java example source code

/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.runtime;

import static jdk.nashorn.internal.runtime.JSType.digit;
import static jdk.nashorn.internal.lookup.Lookup.MH;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Locale;

/**
 * Utilities used by Global class.
 */
public final class GlobalFunctions {

    /** Methodhandle to implementation of ECMA 15.1.2.2, parseInt */
    public static final MethodHandle PARSEINT = findOwnMH("parseInt",   double.class, Object.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.2.3, parseFloat */
    public static final MethodHandle PARSEFLOAT = findOwnMH("parseFloat", double.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.2.4, isNaN */
    public static final MethodHandle IS_NAN = findOwnMH("isNaN",      boolean.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.2.5, isFinite */
    public static final MethodHandle IS_FINITE = findOwnMH("isFinite",   boolean.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.3.3, encodeURI */
    public static final MethodHandle ENCODE_URI = findOwnMH("encodeURI",  Object.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.3.4, encodeURIComponent */
    public static final MethodHandle ENCODE_URICOMPONENT = findOwnMH("encodeURIComponent", Object.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.3.1, decodeURI */
    public static final MethodHandle DECODE_URI = findOwnMH("decodeURI", Object.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.1.3.2, decodeURIComponent */
    public static final MethodHandle DECODE_URICOMPONENT = findOwnMH("decodeURIComponent", Object.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA B.2.1, escape */
    public static final MethodHandle ESCAPE = findOwnMH("escape",    String.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA B.2.2, unescape */
    public static final MethodHandle UNESCAPE = findOwnMH("unescape",  String.class, Object.class, Object.class);

    /** Methodhandle to implementation of ECMA 15.3.4, "anonymous" - Properties of the Function Prototype Object. */
    public static final MethodHandle ANONYMOUS = findOwnMH("anonymous", Object.class, Object.class);

    private static final String UNESCAPED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@*_+-./";

    private GlobalFunctions() {
    }

    /**
     * ECMA 15.1.2.2 parseInt implementation
     *
     * TODO: specialize
     *
     * @param self   self reference
     * @param string string to parse
     * @param rad    radix
     *
     * @return numeric type representing string contents as an int (TODO: specialize for int case)
     */
    //TODO specialize
    public static double parseInt(final Object self, final Object string, final Object rad) {
        final String str    = JSType.trimLeft(JSType.toString(string));
        final int    length = str.length();
        int          radix  = JSType.toInt32(rad);

        // empty string is not valid
        if (length == 0) {
            return Double.NaN;
        }

        boolean negative = false;
        int idx = 0;

        // checking for the sign character
        final char firstChar = str.charAt(idx);
        if (firstChar < '0') {
            // Possible leading "+" or "-"
            if (firstChar == '-') {
                negative = true;
            } else if (firstChar != '+') {
                return Double.NaN;
            }
            // skip the sign character
            idx++;
        }

        boolean stripPrefix = true;

        if (radix != 0) {
            if (radix < 2 || radix > 36) {
                return Double.NaN;
            }
            if (radix != 16) {
                stripPrefix = false;
            }
        } else {
            // default radix
            radix = 10;
        }
        // strip "0x" or "0X" and treat radix as 16
        if (stripPrefix && ((idx + 1) < length)) {
            final char c1 = str.charAt(idx);
            final char c2 = str.charAt(idx + 1);
            if (c1 == '0' && (c2 == 'x' || c2 == 'X')) {
                radix = 16;
                // skip "0x" or "0X"
                idx += 2;
            }
        }

        double result = 0.0;
        int digit;
        // we should see atleast one valid digit
        boolean entered = false;
        while (idx < length) {
            digit = digit(str.charAt(idx++), radix, true);
            if (digit < 0) {
                break;
            }
            // we have seen atleast one valid digit in the specified radix
            entered = true;
            result *= radix;
            result += digit;
        }

        return entered ? (negative ? -result : result) : Double.NaN;
    }

    /**
     * ECMA 15.1.2.3 parseFloat implementation
     *
     * @param self   self reference
     * @param string string to parse
     *
     * @return numeric type representing string contents
     */
    public static double parseFloat(final Object self, final Object string) {
        final String str    = JSType.trimLeft(JSType.toString(string));
        final int    length = str.length();

        // empty string is not valid
        if (length == 0) {
            return Double.NaN;
        }

        int     start    = 0;
        boolean negative = false;
        char    ch       = str.charAt(0);

        if (ch == '-') {
            start++;
            negative = true;
        } else if (ch == '+') {
            start++;
        } else if (ch == 'N') {
            if (str.startsWith("NaN")) {
                return Double.NaN;
            }
        }

        if (start == length) {
            // just the sign character
            return Double.NaN;
        }

        ch = str.charAt(start);
        if (ch == 'I') {
            if (str.substring(start).startsWith("Infinity")) {
                return negative? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
            }
        }

        boolean dotSeen    = false;
        boolean exponentOk = false;
        int exponentOffset = -1;
        int end;

loop:
        for (end = start; end < length; end++) {
            ch = str.charAt(end);

            switch (ch) {
            case '.':
                // dot allowed only once
                if (exponentOffset != -1 || dotSeen) {
                    break loop;
                }
                dotSeen = true;
                break;

            case 'e':
            case 'E':
                // 'e'/'E' allow only once
                if (exponentOffset != -1) {
                    break loop;
                }
                exponentOffset = end;
                break;

            case '+':
            case '-':
                // Sign of the exponent. But allowed only if the
                // previous char in the string was 'e' or 'E'.
                if (exponentOffset != end - 1) {
                    break loop;
                }
                break;

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                if (exponentOffset != -1) {
                    // seeing digit after 'e' or 'E'
                    exponentOk = true;
                }
                break;

            default: // ignore garbage at the end
                break loop;
            }
        }

        // ignore 'e'/'E' followed by '+/-' if not real exponent found
        if (exponentOffset != -1 && !exponentOk) {
            end = exponentOffset;
        }

        if (start == end) {
            return Double.NaN;
        }

        try {
            final double result = Double.valueOf(str.substring(start, end));
            return negative ? -result : result;
        } catch (final NumberFormatException e) {
            return Double.NaN;
        }
    }

    /**
     * ECMA 15.1.2.4, isNaN implementation
     *
     * @param self    self reference
     * @param number  number to check
     *
     * @return true if number is NaN
     */
    public static boolean isNaN(final Object self, final Object number) {
        return Double.isNaN(JSType.toNumber(number));
    }

    /**
     * ECMA 15.1.2.5, isFinite implementation
     *
     * @param self   self reference
     * @param number number to check
     *
     * @return true if number is infinite
     */
    public static boolean isFinite(final Object self, final Object number) {
        final double value = JSType.toNumber(number);
        return ! (Double.isInfinite(value) || Double.isNaN(value));
    }


    /**
     * ECMA 15.1.3.3, encodeURI implementation
     *
     * @param self  self reference
     * @param uri   URI to encode
     *
     * @return encoded URI
     */
    public static Object encodeURI(final Object self, final Object uri) {
        return URIUtils.encodeURI(self, JSType.toString(uri));
    }

    /**
     * ECMA 15.1.3.4, encodeURIComponent implementation
     *
     * @param self  self reference
     * @param uri   URI component to encode
     *
     * @return encoded URIComponent
     */
    public static Object encodeURIComponent(final Object self, final Object uri) {
        return URIUtils.encodeURIComponent(self, JSType.toString(uri));
    }

    /**
     * ECMA 15.1.3.1, decodeURI implementation
     *
     * @param self  self reference
     * @param uri   URI to decode
     *
     * @return decoded URI
     */
    public static Object decodeURI(final Object self, final Object uri) {
        return URIUtils.decodeURI(self, JSType.toString(uri));
    }

    /**
     * ECMA 15.1.3.2, decodeURIComponent implementation
     *
     * @param self  self reference
     * @param uri   URI component to encode
     *
     * @return decoded URI
     */
    public static Object decodeURIComponent(final Object self, final Object uri) {
        return URIUtils.decodeURIComponent(self, JSType.toString(uri));
    }

    /**
     * ECMA B.2.1, escape implementation
     *
     * @param self    self reference
     * @param string  string to escape
     *
     * @return escaped string
     */
    public static String escape(final Object self, final Object string) {
        final String str = JSType.toString(string);
        final int length = str.length();

        if (length == 0) {
            return str;
        }

        final StringBuilder sb = new StringBuilder();
        for (int k = 0; k < length; k++) {
            final char ch = str.charAt(k);
            if (UNESCAPED.indexOf(ch) != -1) {
                sb.append(ch);
            } else if (ch < 256) {
                sb.append('%');
                if (ch < 16) {
                    sb.append('0');
                }
                sb.append(Integer.toHexString(ch).toUpperCase(Locale.ENGLISH));
            } else {
                sb.append("%u");
                if (ch < 4096) {
                    sb.append('0');
                }
                sb.append(Integer.toHexString(ch).toUpperCase(Locale.ENGLISH));
            }
        }

        return sb.toString();
    }

    /**
     * ECMA B.2.2, unescape implementation
     *
     * @param self    self reference
     * @param string  string to unescape
     *
     * @return unescaped string
     */
    public static String unescape(final Object self, final Object string) {
        final String str    = JSType.toString(string);
        final int    length = str.length();

        if (length == 0) {
            return str;
        }

        final StringBuilder sb = new StringBuilder();
        for (int k = 0; k < length; k++) {
            char ch = str.charAt(k);
            if (ch != '%') {
                sb.append(ch);
            } else {
                if (k < (length - 5)) {
                   if (str.charAt(k + 1) == 'u') {
                       try {
                           ch = (char) Integer.parseInt(str.substring(k + 2, k + 6), 16);
                           sb.append(ch);
                           k += 5;
                           continue;
                       } catch (final NumberFormatException e) {
                           //ignored
                       }
                   }
                }

                if (k < (length - 2)) {
                    try {
                        ch = (char) Integer.parseInt(str.substring(k + 1, k + 3), 16);
                        sb.append(ch);
                        k += 2;
                        continue;
                    } catch (final NumberFormatException e) {
                        //ignored
                    }
                }

                // everything fails
                sb.append(ch);
            }
        }

        return sb.toString();
    }


    /**
     * ECMA 15.3.4 Properties of the Function Prototype Object.
     * The Function prototype object is itself a Function object
     * (its [[Class]] is "Function") that, when invoked, accepts
     * any arguments and returns undefined. This method is used to
     * implement that anonymous function.
     *
     * @param self  self reference
     *
     * @return undefined
     */
    public static Object anonymous(final Object self) {
        return ScriptRuntime.UNDEFINED;
    }

    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class... types) {
        return MH.findStatic(MethodHandles.lookup(), GlobalFunctions.class, name, MH.type(rtype, types));
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java GlobalFunctions.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.