1 package ch.qos.logback.core.pattern.parser;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import ch.qos.logback.core.pattern.util.IEscapeUtil;
7 import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
8
9 public class OptionTokenizer {
10
11 private final static int EXPECTING_STATE = 0;
12 private final static int COLLECTING_STATE = 1;
13 private final static int QUOTED_COLLECTING_STATE = 2;
14
15 private static final char ESCAPE_CHAR = '\\';
16 private static final char COMMA_CHAR = ',';
17 private static final char DOUBLE_QUOTE_CHAR = '"';
18 private static final char SINGLE_QUOTE_CHAR = '\'';
19
20 final String pattern;
21 final int patternLength;
22 final IEscapeUtil escapeUtil;
23
24 char quoteChar;
25 int pointer = 0;
26 int state = EXPECTING_STATE;
27
28
29
30
31
32 OptionTokenizer(String pattern) {
33 this(pattern, new RegularEscapeUtil());
34 }
35
36 OptionTokenizer(String pattern, IEscapeUtil escapeUtil) {
37 this.pattern = pattern;
38 patternLength = pattern.length();
39 this.escapeUtil = escapeUtil;
40 }
41
42 List tokenize() throws ScanException {
43 List<String> tokenList = new ArrayList<String>();
44 StringBuffer buf = new StringBuffer();
45
46 while (pointer < patternLength) {
47 char c = pattern.charAt(pointer);
48 pointer++;
49
50 switch (state) {
51 case EXPECTING_STATE:
52 switch (c) {
53 case ' ':
54 case '\t':
55 case '\r':
56 case '\n':
57 break;
58 case SINGLE_QUOTE_CHAR:
59 case DOUBLE_QUOTE_CHAR:
60 state = QUOTED_COLLECTING_STATE;
61 quoteChar = c;
62 break;
63 default:
64 buf.append(c);
65 state = COLLECTING_STATE;
66 }
67 break;
68 case COLLECTING_STATE:
69 switch (c) {
70 case COMMA_CHAR:
71 tokenList.add(buf.toString().trim());
72 buf.setLength(0);
73 state = EXPECTING_STATE;
74 break;
75 default:
76 buf.append(c);
77 }
78 break;
79 case QUOTED_COLLECTING_STATE:
80 if (c == quoteChar) {
81 tokenList.add(buf.toString());
82 buf.setLength(0);
83 state = EXPECTING_STATE;
84 } else if (c == ESCAPE_CHAR) {
85 escape(String.valueOf(quoteChar), buf);
86 } else {
87 buf.append(c);
88 }
89
90 break;
91 }
92 }
93
94
95 switch (state) {
96 case EXPECTING_STATE:
97 break;
98 case COLLECTING_STATE:
99 tokenList.add(buf.toString().trim());
100 break;
101 default:
102 throw new ScanException("Unexpected end of pattern string");
103 }
104
105 return tokenList;
106 }
107
108 void escape(String escapeChars, StringBuffer buf) {
109 if ((pointer < patternLength)) {
110 char next = pattern.charAt(pointer++);
111 escapeUtil.escape(escapeChars, buf, next, pointer);
112 }
113 }
114 }