1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package Torello.CSS;

import Torello.Java.Additional.ByRef;

import java.util.Vector;
import java.util.function.Consumer;

/** Any sequence of Whitespace */
@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="CSS_TOK")
public class Whitespace extends CSSToken
    implements CharSequence, java.io.Serializable, Comparable<CharSequence>
{
    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
    protected static final long serialVersionUID = 1;


    // ********************************************************************************************
    // ********************************************************************************************
    // Private Constructor, API "is" and "if" Methods
    // ********************************************************************************************
    // ********************************************************************************************


    private Whitespace(final int[] css, final int sPos, final int ePos)
    { super(css, sPos, ePos); }

    @Override 
    public final boolean isWhitespace() { return true; }

    @Override
    public final Whitespace ifWhitespace() { return this; }


    // ********************************************************************************************
    // ********************************************************************************************
    // Tokenizer's "is" Method(s)
    // ********************************************************************************************
    // ********************************************************************************************


    // Currently this is Nearly Identical to what the CSSWG.org website says.  I am just not
    // going to analyze \n\r today.  I truly have no way of testing this type of crap.
    //
    // Note that the JDK-21 JavaDoc has a rather lengthy list of what will make Java's
    // java.lang.Character(int) is WhiteSpace return TRUE.
    // 
    // I will possibly change this to Character.isWhitespace(int codePoint) later...
    // For Now - the Plan is to follow the "W3" ==> 
    //      https://drafts.csswg.org/css-syntax/#whitespace

    private static final char[] WHITE_SPACE_ARR =
        { '\t', ' ', '\n', '\r', '\f', '\u000B' };

    static boolean is(final int c)
    {
        for (char ws : WHITE_SPACE_ARR) if (c == ws) return true;
        return false;
    }


    // ********************************************************************************************
    // ********************************************************************************************
    // User's Constructor: a static "build" method
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * <EMBED CLASS=defs DATA-TOK=Whitespace DATA-P=ws>
     * <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_DESC>
     * @param ws <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_PARAM>
     * @return <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_RET>
     * @throws TokenizeException <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_TOK_EX>
     */
    @SuppressWarnings("unchecked")
    public static Whitespace build(final String ws)
    { return (Whitespace) CSSToken.build(ws, INPUT_CHECKER, Whitespace::consume); }

    private static final CSSToken.InputChecker INPUT_CHECKER = (int[] css) ->
    {
        if (css.length == 0) throw new TokenizeException 
            ("Input-String cannot have length 0.");

        if (! is(css[0])) throw new TokenizeException
            ("Input String does not start with a white-space character");
    };


    // ********************************************************************************************
    // ********************************************************************************************
    // CONSUME
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * This is a tokenizer method which <B>"consumes"</B> as much white-space as possible for the
     * purpose of building a Whitespace Token.
     * 
     * <EMBED CLASS=defs DATA-TOK=Whitespace-Token DATA-URL=whitespace-token-diagram
     *      DATA-OP=Consume>
     * <EMBED CLASS=external-html DATA-FILE-ID=COPIED_CSS_WG_RR>
     * <EMBED CLASS=external-html DATA-FILE-ID=WS_STAR_SVG>
     * <EMBED CLASS=external-html DATA-FILE-ID=WHITESPACE_SVG>
     * <EMBED CLASS=external-html DATA-FILE-ID=WHITESPACE_TOK_SVG>
     */
    protected static void consume(                          // When invoked from 'CSSTokenizer'
            final int[]                 css,                // C, int[] css
            final ByRef<Integer>        POS,                // P, array-pos loop-variable
            final Consumer<CSSToken>    returnParsedToken   // T, Vector<CSSToken>.add
        )
    {
        // NOTE: The algorithm will have already checked that css[0] is whitespace, or else it
        //       would have not invoked this method in the first place.  This is what the CSS
        //       Working Group Web-Site Pseudo-Code says, and this package "Sticks to the Plan"

        int pos=(POS.f+1); // input-pos + 1 !!  Doesn't check the first character

        TOP:
        for (; pos < css.length; pos++)
        {
            int c = css[pos];
            for (char ws : WHITE_SPACE_ARR) if (c == ws) continue TOP;
            break TOP;
        }

        returnParsedToken.accept(new Whitespace(css, POS.f, pos));
        POS.f = pos;
    }
}