Skip to content

Commit ea61366

Browse files
committed
Merge branch '2.3.x' of github.com:grails/grails-core into 2.3.x
2 parents 20131df + 60b4951 commit ea61366

File tree

21 files changed

+912
-130
lines changed

21 files changed

+912
-130
lines changed

grails-core/src/main/groovy/org/codehaus/groovy/grails/support/encoding/AbstractEncodedAppender.java

Lines changed: 21 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* @since 2.3
2525
*/
2626
public abstract class AbstractEncodedAppender implements EncodedAppender {
27+
private boolean ignoreEncodingState;
28+
2729
/**
2830
* Append a portion of a char array to the buffer and attach the
2931
* encodingState information to it
@@ -97,9 +99,9 @@ public void append(Encoder encoder, EncodingState encodingState, char[] b, int o
9799
return;
98100
}
99101
if (shouldEncode(encoder, encodingState)) {
100-
EncodingState newEncoders = appendEncoders(encoder, encodingState);
102+
EncodingState newEncoders = createNewEncodingState(encoder, encodingState);
101103
if (encoder instanceof StreamingEncoder) {
102-
((StreamingEncoder)encoder).encodeToStream(encoder, new CharArrayCharSequence(b, off, len), 0, len, this,
104+
((StreamingEncoder)encoder).encodeToStream(encoder, CharSequences.createCharSequence(b, off, len), 0, len, this,
103105
newEncoders);
104106
}
105107
else {
@@ -111,7 +113,7 @@ public void append(Encoder encoder, EncodingState encodingState, char[] b, int o
111113
}
112114
}
113115

114-
private EncodingState appendEncoders(Encoder encoder, EncodingState encodingState) {
116+
protected EncodingState createNewEncodingState(Encoder encoder, EncodingState encodingState) {
115117
if (encodingState == null) {
116118
return new EncodingStateImpl(encoder);
117119
}
@@ -132,13 +134,13 @@ public void append(Encoder encoder, EncodingState encodingState, CharSequence st
132134
return;
133135
}
134136
if (shouldEncode(encoder, encodingState)) {
135-
EncodingState newEncoders = appendEncoders(encoder, encodingState);
137+
EncodingState newEncoders = createNewEncodingState(encoder, encodingState);
136138
if (encoder instanceof StreamingEncoder) {
137139
((StreamingEncoder)encoder).encodeToStream(encoder, str, off, len, this, newEncoders);
138140
}
139141
else {
140142
CharSequence source;
141-
if (off == 0 && len == str.length()) {
143+
if (CharSequences.canUseOriginalForSubSequence(str, off, len)) {
142144
source = str;
143145
}
144146
else {
@@ -154,12 +156,12 @@ public void append(Encoder encoder, EncodingState encodingState, CharSequence st
154156

155157
public void appendEncoded(Encoder encoder, EncodingState encodingState, char[] b, int off, int len)
156158
throws IOException {
157-
write(appendEncoders(encoder, encodingState), b, off, len);
159+
write(createNewEncodingState(encoder, encodingState), b, off, len);
158160
}
159161

160162
public void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequence str, int off, int len)
161163
throws IOException {
162-
appendCharSequence(appendEncoders(encoder, encodingState), str, off, off + len);
164+
appendCharSequence(createNewEncodingState(encoder, encodingState), str, off, off + len);
163165
}
164166

165167
/**
@@ -172,9 +174,13 @@ public void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequ
172174
* @return true, if should encode
173175
*/
174176
protected boolean shouldEncode(Encoder encoderToApply, EncodingState encodingState) {
175-
return encoderToApply != null
176-
&& (encodingState == null || DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply,
177-
encodingState));
177+
return ignoreEncodingState || (encoderToApply != null
178+
&& (encodingState == null || shouldEncodeWith(encoderToApply, encodingState)));
179+
}
180+
181+
protected boolean shouldEncodeWith(Encoder encoderToApply, EncodingState encodingState) {
182+
return DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply,
183+
encodingState);
178184
}
179185

180186
/**
@@ -217,55 +223,11 @@ public void flush() throws IOException {
217223

218224
}
219225

220-
private static final class CharArrayCharSequence implements CharSequence, CharArrayAccessible {
221-
private final char[] chars;
222-
private final int count;
223-
private final int start;
224-
225-
public CharArrayCharSequence(char[] chars, int start, int count) {
226-
if (start + count > chars.length)
227-
throw new StringIndexOutOfBoundsException(start);
228-
this.chars = chars;
229-
this.start = start;
230-
this.count = count;
231-
}
232-
233-
public char charAt(int index) {
234-
if ((index < 0) || (index + start >= chars.length))
235-
throw new StringIndexOutOfBoundsException(index);
236-
return chars[index + start];
237-
}
238-
239-
public int length() {
240-
return count;
241-
}
242-
243-
public CharSequence subSequence(int start, int end) {
244-
if (start < 0)
245-
throw new StringIndexOutOfBoundsException(start);
246-
if (end > count)
247-
throw new StringIndexOutOfBoundsException(end);
248-
if (start > end)
249-
throw new StringIndexOutOfBoundsException(end - start);
250-
if (start == 0 && end == count) {
251-
return this;
252-
}
253-
return new CharArrayCharSequence(chars, this.start + start, end - start);
254-
}
255-
256-
@Override
257-
public String toString() {
258-
return new String(chars, start, count);
259-
}
226+
public boolean isIgnoreEncodingState() {
227+
return ignoreEncodingState;
228+
}
260229

261-
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
262-
if (srcBegin < 0)
263-
throw new StringIndexOutOfBoundsException(srcBegin);
264-
if ((srcEnd < 0) || (srcEnd > start+count))
265-
throw new StringIndexOutOfBoundsException(srcEnd);
266-
if (srcBegin > srcEnd)
267-
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
268-
System.arraycopy(chars, start + srcBegin, dst, dstBegin, srcEnd - srcBegin);
269-
}
230+
public void setIgnoreEncodingState(boolean ignoreEncodingState) {
231+
this.ignoreEncodingState = ignoreEncodingState;
270232
}
271233
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.codehaus.groovy.grails.support.encoding;
17+
18+
/**
19+
* Wraps a char array and implements CharSequence interface
20+
*
21+
*
22+
* @author Lari Hotari
23+
* @since 2.3.10
24+
*
25+
*/
26+
class CharArrayCharSequence implements CharSequence, CharArrayAccessible {
27+
private final char[] chars;
28+
private final int count;
29+
private final int start;
30+
31+
CharArrayCharSequence(char[] chars, int start, int count) {
32+
if (start + count > chars.length)
33+
throw new StringIndexOutOfBoundsException(start);
34+
this.chars = chars;
35+
this.start = start;
36+
this.count = count;
37+
}
38+
39+
public char charAt(int index) {
40+
if ((index < 0) || (index + start >= chars.length))
41+
throw new StringIndexOutOfBoundsException(index);
42+
return chars[index + start];
43+
}
44+
45+
public int length() {
46+
return count;
47+
}
48+
49+
public CharSequence subSequence(int start, int end) {
50+
if (start < 0)
51+
throw new StringIndexOutOfBoundsException(start);
52+
if (end > count)
53+
throw new StringIndexOutOfBoundsException(end);
54+
if (start > end)
55+
throw new StringIndexOutOfBoundsException(end - start);
56+
if (start == 0 && end == count) {
57+
return this;
58+
}
59+
return new CharArrayCharSequence(chars, this.start + start, end - start);
60+
}
61+
62+
@Override
63+
public String toString() {
64+
return new String(chars, start, count);
65+
}
66+
67+
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
68+
if (srcBegin < 0)
69+
throw new StringIndexOutOfBoundsException(srcBegin);
70+
if ((srcEnd < 0) || (srcEnd > start+count))
71+
throw new StringIndexOutOfBoundsException(srcEnd);
72+
if (srcBegin > srcEnd)
73+
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
74+
System.arraycopy(chars, start + srcBegin, dst, dstBegin, srcEnd - srcBegin);
75+
}
76+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
* Copyright 2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.codehaus.groovy.grails.support.encoding;
17+
18+
import java.io.IOException;
19+
import java.io.Writer;
20+
21+
/**
22+
* Utility functions for handling java.lang.CharSequence instances
23+
*
24+
*
25+
* @author Lari Hotari
26+
* @since 2.3.10
27+
*
28+
*/
29+
public class CharSequences {
30+
public static CharSequence createCharSequence(char[] chars) {
31+
return new CharArrayCharSequence(chars, 0, chars.length);
32+
}
33+
34+
public static CharSequence createCharSequence(char[] chars, int start, int count) {
35+
return new CharArrayCharSequence(chars, start, count);
36+
}
37+
38+
public static CharSequence createCharSequence(CharSequence str, int start, int count) {
39+
if(canUseOriginalForSubSequence(str, start, count)) {
40+
return str;
41+
} else {
42+
return new SubCharSequence(str, start, count);
43+
}
44+
}
45+
46+
/**
47+
* Checks if start == 0 and count == length of CharSequence
48+
* It does this check only for String, StringBuilder and StringBuffer classes which have a fast way to check length
49+
*
50+
* Calculating length on GStringImpl requires building the result which is costly.
51+
* This helper method is to avoid calling length on other that String, StringBuilder and StringBuffer classes
52+
* when checking if the input CharSequence instance is already the same as the requested sub sequence
53+
*
54+
* @param str CharSequence input
55+
* @param start start index
56+
* @param count length on sub sequence
57+
* @return true if input is String, StringBuilder or StringBuffer class, start is 0 and count is length of input sequence
58+
*/
59+
public static boolean canUseOriginalForSubSequence(CharSequence str, int start, int count) {
60+
if (start != 0) return false;
61+
final Class<?> csqClass = str.getClass();
62+
return (csqClass == String.class || csqClass == StringBuilder.class || csqClass == StringBuffer.class) && count == str.length();
63+
}
64+
65+
public static CharSequence createSingleCharSequence(int c) {
66+
return new SingleCharCharSequence(c);
67+
}
68+
69+
public static CharSequence createSingleCharSequence(char ch) {
70+
return new SingleCharCharSequence(ch);
71+
}
72+
73+
/**
74+
* Writes a CharSequence instance in the most optimal way to the target writer
75+
*
76+
*
77+
* @param target writer
78+
* @param csq source CharSequence instance
79+
* @param start start/offset index
80+
* @param end end index + 1
81+
* @throws IOException
82+
*/
83+
public static void writeCharSequence(Writer target, CharSequence csq, int start, int end) throws IOException {
84+
final Class<?> csqClass = csq.getClass();
85+
if (csqClass == String.class) {
86+
target.write((String)csq, start, end - start);
87+
}
88+
else if (csqClass == StringBuffer.class) {
89+
char[] buf = new char[end - start];
90+
((StringBuffer)csq).getChars(start, end, buf, 0);
91+
target.write(buf);
92+
}
93+
else if (csqClass == StringBuilder.class) {
94+
char[] buf = new char[end - start];
95+
((StringBuilder)csq).getChars(start, end, buf, 0);
96+
target.write(buf);
97+
}
98+
else if (csq instanceof CharArrayAccessible) {
99+
char[] buf = new char[end - start];
100+
((CharArrayAccessible)csq).getChars(start, end, buf, 0);
101+
target.write(buf);
102+
}
103+
else {
104+
String str = csq.subSequence(start, end).toString();
105+
target.write(str, 0, str.length());
106+
}
107+
}
108+
109+
public static void writeCharSequence(Writer target, CharSequence csq) throws IOException {
110+
writeCharSequence(target, csq, 0, csq.length());
111+
}
112+
113+
/**
114+
* Provides an optimized way to copy CharSequence content to target array.
115+
* Uses getChars method available on String, StringBuilder and StringBuffer classes.
116+
*
117+
* Characters are copied from the source sequence <code>csq</code> into the
118+
* destination character array <code>dst</code>. The first character to
119+
* be copied is at index <code>srcBegin</code>; the last character to
120+
* be copied is at index <code>srcEnd-1</code>. The total number of
121+
* characters to be copied is <code>srcEnd-srcBegin</code>. The
122+
* characters are copied into the subarray of <code>dst</code> starting
123+
* at index <code>dstBegin</code> and ending at index:
124+
* <p><blockquote><pre>
125+
* dstbegin + (srcEnd-srcBegin) - 1
126+
* </pre></blockquote>
127+
*
128+
* @param csq the source CharSequence instance.
129+
* @param srcBegin start copying at this offset.
130+
* @param srcEnd stop copying at this offset.
131+
* @param dst the array to copy the data into.
132+
* @param dstBegin offset into <code>dst</code>.
133+
* @throws NullPointerException if <code>dst</code> is
134+
* <code>null</code>.
135+
* @throws IndexOutOfBoundsException if any of the following is true:
136+
* <ul>
137+
* <li><code>srcBegin</code> is negative
138+
* <li><code>dstBegin</code> is negative
139+
* <li>the <code>srcBegin</code> argument is greater than
140+
* the <code>srcEnd</code> argument.
141+
* <li><code>srcEnd</code> is greater than
142+
* <code>this.length()</code>.
143+
* <li><code>dstBegin+srcEnd-srcBegin</code> is greater than
144+
* <code>dst.length</code>
145+
* </ul>
146+
*/
147+
public static void getChars(CharSequence csq, int srcBegin, int srcEnd, char dst[], int dstBegin) {
148+
final Class<?> csqClass = csq.getClass();
149+
if (csqClass == String.class) {
150+
((String)csq).getChars(srcBegin, srcEnd, dst, dstBegin);
151+
}
152+
else if (csqClass == StringBuffer.class) {
153+
((StringBuffer)csq).getChars(srcBegin, srcEnd, dst, dstBegin);
154+
}
155+
else if (csqClass == StringBuilder.class) {
156+
((StringBuilder)csq).getChars(srcBegin, srcEnd, dst, dstBegin);
157+
}
158+
else if (csq instanceof CharArrayAccessible) {
159+
((CharArrayAccessible)csq).getChars(srcBegin, srcEnd, dst, dstBegin);
160+
}
161+
else {
162+
String str = csq.subSequence(srcBegin, srcEnd).toString();
163+
str.getChars(0, str.length(), dst, dstBegin);
164+
}
165+
}
166+
}

0 commit comments

Comments
 (0)