001package Torello.CSS; 002 003import Torello.Java.Additional.ByRef; 004 005import java.util.Vector; 006import java.util.function.Consumer; 007 008/** Any sequence of Whitespace */ 009@Torello.JavaDoc.JDHeaderBackgroundImg(EmbedTagFileID="CSS_TOK") 010public class Whitespace extends CSSToken 011 implements CharSequence, java.io.Serializable, Comparable<CharSequence> 012{ 013 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 014 protected static final long serialVersionUID = 1; 015 016 017 // ******************************************************************************************** 018 // ******************************************************************************************** 019 // Private Constructor, API "is" and "if" Methods 020 // ******************************************************************************************** 021 // ******************************************************************************************** 022 023 024 private Whitespace(final int[] css, final int sPos, final int ePos) 025 { super(css, sPos, ePos); } 026 027 @Override 028 public final boolean isWhitespace() { return true; } 029 030 @Override 031 public final Whitespace ifWhitespace() { return this; } 032 033 034 // ******************************************************************************************** 035 // ******************************************************************************************** 036 // Tokenizer's "is" Method(s) 037 // ******************************************************************************************** 038 // ******************************************************************************************** 039 040 041 // Currently this is Nearly Identical to what the CSSWG.org website says. I am just not 042 // going to analyze \n\r today. I truly have no way of testing this type of crap. 043 // 044 // Note that the JDK-21 JavaDoc has a rather lengthy list of what will make Java's 045 // java.lang.Character(int) is WhiteSpace return TRUE. 046 // 047 // I will possibly change this to Character.isWhitespace(int codePoint) later... 048 // For Now - the Plan is to follow the "W3" ==> 049 // https://drafts.csswg.org/css-syntax/#whitespace 050 051 private static final char[] WHITE_SPACE_ARR = 052 { '\t', ' ', '\n', '\r', '\f', '\u000B' }; 053 054 static boolean is(final int c) 055 { 056 for (char ws : WHITE_SPACE_ARR) if (c == ws) return true; 057 return false; 058 } 059 060 061 // ******************************************************************************************** 062 // ******************************************************************************************** 063 // User's Constructor: a static "build" method 064 // ******************************************************************************************** 065 // ******************************************************************************************** 066 067 068 /** 069 * <EMBED CLASS=defs DATA-TOK=Whitespace DATA-P=ws> 070 * <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_DESC> 071 * @param ws <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_PARAM> 072 * @return <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_RET> 073 * @throws TokenizeException <EMBED CLASS='external-html' DATA-FILE-ID=BUILD_TOK_EX> 074 */ 075 @SuppressWarnings("unchecked") 076 public static Whitespace build(final String ws) 077 { return (Whitespace) CSSToken.build(ws, INPUT_CHECKER, Whitespace::consume); } 078 079 private static final CSSToken.InputChecker INPUT_CHECKER = (int[] css) -> 080 { 081 if (css.length == 0) throw new TokenizeException 082 ("Input-String cannot have length 0."); 083 084 if (! is(css[0])) throw new TokenizeException 085 ("Input String does not start with a white-space character"); 086 }; 087 088 089 // ******************************************************************************************** 090 // ******************************************************************************************** 091 // CONSUME 092 // ******************************************************************************************** 093 // ******************************************************************************************** 094 095 096 /** 097 * This is a tokenizer method which <B>"consumes"</B> as much white-space as possible for the 098 * purpose of building a Whitespace Token. 099 * 100 * <EMBED CLASS=defs DATA-TOK=Whitespace-Token DATA-URL=whitespace-token-diagram 101 * DATA-OP=Consume> 102 * <EMBED CLASS=external-html DATA-FILE-ID=COPIED_CSS_WG_RR> 103 * <EMBED CLASS=external-html DATA-FILE-ID=WS_STAR_SVG> 104 * <EMBED CLASS=external-html DATA-FILE-ID=WHITESPACE_SVG> 105 * <EMBED CLASS=external-html DATA-FILE-ID=WHITESPACE_TOK_SVG> 106 */ 107 protected static void consume( // When invoked from 'CSSTokenizer' 108 final int[] css, // C, int[] css 109 final ByRef<Integer> POS, // P, array-pos loop-variable 110 final Consumer<CSSToken> returnParsedToken // T, Vector<CSSToken>.add 111 ) 112 { 113 // NOTE: The algorithm will have already checked that css[0] is whitespace, or else it 114 // would have not invoked this method in the first place. This is what the CSS 115 // Working Group Web-Site Pseudo-Code says, and this package "Sticks to the Plan" 116 117 int pos=(POS.f+1); // input-pos + 1 !! Doesn't check the first character 118 119 TOP: 120 for (; pos < css.length; pos++) 121 { 122 int c = css[pos]; 123 for (char ws : WHITE_SPACE_ARR) if (c == ws) continue TOP; 124 break TOP; 125 } 126 127 returnParsedToken.accept(new Whitespace(css, POS.f, pos)); 128 POS.f = pos; 129 } 130}