Skip to content

Commit 3727919

Browse files
committed
Merge branch '2.3.x' into 2.4.x
Conflicts: grails-encoder/src/main/groovy/org/codehaus/groovy/grails/support/encoding/AbstractEncodedAppender.java grails-encoder/src/main/groovy/org/codehaus/groovy/grails/support/encoding/StreamingStatelessEncoder.java grails-test-suite-uber/src/test/groovy/org/codehaus/groovy/grails/web/util/StreamCharBufferSpec.groovy
2 parents f9e2f74 + 60b4951 commit 3727919

File tree

19 files changed

+856
-132
lines changed

19 files changed

+856
-132
lines changed

grails-encoder/src/main/groovy/org/codehaus/groovy/grails/plugins/codecs/AbstractCharReplacementEncoder.java

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@
2121
import org.codehaus.groovy.grails.support.encoding.CodecIdentifier;
2222
import org.codehaus.groovy.grails.support.encoding.EncodedAppender;
2323
import org.codehaus.groovy.grails.support.encoding.Encoder;
24+
import org.codehaus.groovy.grails.support.encoding.EncodesToWriter;
2425
import org.codehaus.groovy.grails.support.encoding.EncodingState;
2526
import org.codehaus.groovy.grails.support.encoding.StreamingEncoder;
26-
import org.codehaus.groovy.grails.support.encoding.StreamingStatelessEncoder;
27-
import org.codehaus.groovy.grails.support.encoding.WriterEncodedAppender;
2827

2928
/**
3029
* Abstract base class for implementing encoders that do character replacements
@@ -34,7 +33,7 @@
3433
* @author Lari Hotari
3534
* @since 2.3
3635
*/
37-
public abstract class AbstractCharReplacementEncoder implements Encoder, StreamingEncoder, StreamingStatelessEncoder {
36+
public abstract class AbstractCharReplacementEncoder implements Encoder, StreamingEncoder, EncodesToWriter {
3837
protected CodecIdentifier codecIdentifier;
3938

4039
public AbstractCharReplacementEncoder(CodecIdentifier codecIdentifier) {
@@ -126,8 +125,66 @@ protected Object escapeCharSequence(CharSequence str) {
126125
}
127126
}
128127

129-
public void encodeToWriter(CharSequence str, Writer writer) throws IOException {
130-
encodeToStream(this, str, 0, str.length(), new WriterEncodedAppender(writer), null);
128+
@Override
129+
public void encodeToWriter(CharSequence str, int off, int len, Writer writer, EncodingState encodingState) throws IOException {
130+
if (str == null || len <= 0) {
131+
return;
132+
}
133+
int n = Math.min(str.length(), off + len);
134+
int i;
135+
int startPos = -1;
136+
char prevChar = (char)0;
137+
for (i = off; i < n; i++) {
138+
char ch = str.charAt(i);
139+
if (startPos == -1) {
140+
startPos = i;
141+
}
142+
String escaped = escapeCharacter(ch, prevChar);
143+
if (escaped != null) {
144+
if (i - startPos > 0) {
145+
writer.append(str, startPos, i - startPos);
146+
}
147+
if (escaped.length() > 0) {
148+
writer.write(escaped);
149+
}
150+
startPos = -1;
151+
}
152+
prevChar = ch;
153+
}
154+
if (startPos > -1 && i - startPos > 0) {
155+
writer.append(str, startPos, i - startPos);
156+
}
157+
}
158+
159+
@Override
160+
public void encodeToWriter(char[] buf, int off, int len, Writer writer, EncodingState encodingState) throws IOException {
161+
if (buf == null || len <= 0) {
162+
return;
163+
}
164+
int n = Math.min(buf.length, off + len);
165+
int i;
166+
int startPos = -1;
167+
char prevChar = (char)0;
168+
for (i = off; i < n; i++) {
169+
char ch = buf[i];
170+
if (startPos == -1) {
171+
startPos = i;
172+
}
173+
String escaped = escapeCharacter(ch, prevChar);
174+
if (escaped != null) {
175+
if (i - startPos > 0) {
176+
writer.write(buf, startPos, i - startPos);
177+
}
178+
if (escaped.length() > 0) {
179+
writer.write(escaped);
180+
}
181+
startPos = -1;
182+
}
183+
prevChar = ch;
184+
}
185+
if (startPos > -1 && i - startPos > 0) {
186+
writer.write(buf, startPos, i - startPos);
187+
}
131188
}
132189

133190
/* (non-Javadoc)

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

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ public void append(Encoder encoder, EncodingState encodingState, char[] b, int o
9999
return;
100100
}
101101
if (shouldEncode(encoder, encodingState)) {
102-
EncodingState newEncoders = appendEncoders(encoder, encodingState);
102+
EncodingState newEncoders = createNewEncodingState(encoder, encodingState);
103103
if (encoder instanceof StreamingEncoder) {
104-
((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,
105105
newEncoders);
106106
}
107107
else {
@@ -113,7 +113,7 @@ public void append(Encoder encoder, EncodingState encodingState, char[] b, int o
113113
}
114114
}
115115

116-
private EncodingState appendEncoders(Encoder encoder, EncodingState encodingState) {
116+
protected EncodingState createNewEncodingState(Encoder encoder, EncodingState encodingState) {
117117
if (encodingState == null) {
118118
return new EncodingStateImpl(encoder);
119119
}
@@ -134,13 +134,13 @@ public void append(Encoder encoder, EncodingState encodingState, CharSequence st
134134
return;
135135
}
136136
if (shouldEncode(encoder, encodingState)) {
137-
EncodingState newEncoders = appendEncoders(encoder, encodingState);
137+
EncodingState newEncoders = createNewEncodingState(encoder, encodingState);
138138
if (encoder instanceof StreamingEncoder) {
139139
((StreamingEncoder)encoder).encodeToStream(encoder, str, off, len, this, newEncoders);
140140
}
141141
else {
142142
CharSequence source;
143-
if (off == 0 && len == str.length()) {
143+
if (CharSequences.canUseOriginalForSubSequence(str, off, len)) {
144144
source = str;
145145
}
146146
else {
@@ -156,12 +156,12 @@ public void append(Encoder encoder, EncodingState encodingState, CharSequence st
156156

157157
public void appendEncoded(Encoder encoder, EncodingState encodingState, char[] b, int off, int len)
158158
throws IOException {
159-
write(appendEncoders(encoder, encodingState), b, off, len);
159+
write(createNewEncodingState(encoder, encodingState), b, off, len);
160160
}
161161

162162
public void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequence str, int off, int len)
163163
throws IOException {
164-
appendCharSequence(appendEncoders(encoder, encodingState), str, off, off + len);
164+
appendCharSequence(createNewEncodingState(encoder, encodingState), str, off, off + len);
165165
}
166166

167167
/**
@@ -175,8 +175,12 @@ public void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequ
175175
*/
176176
protected boolean shouldEncode(Encoder encoderToApply, EncodingState encodingState) {
177177
return ignoreEncodingState || (encoderToApply != null
178-
&& (encodingState == null || DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply,
179-
encodingState)));
178+
&& (encodingState == null || shouldEncodeWith(encoderToApply, encodingState)));
179+
}
180+
181+
protected boolean shouldEncodeWith(Encoder encoderToApply, EncodingState encodingState) {
182+
return DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply,
183+
encodingState);
180184
}
181185

182186
/**
@@ -219,62 +223,6 @@ public void flush() throws IOException {
219223

220224
}
221225

222-
static final class CharArrayCharSequence implements CharSequence, CharArrayAccessible {
223-
private final char[] chars;
224-
private final int count;
225-
private final int start;
226-
227-
public CharArrayCharSequence(char[] chars) {
228-
this(chars, 0, chars.length);
229-
}
230-
231-
public CharArrayCharSequence(char[] chars, int start, int count) {
232-
if (start + count > chars.length)
233-
throw new StringIndexOutOfBoundsException(start);
234-
this.chars = chars;
235-
this.start = start;
236-
this.count = count;
237-
}
238-
239-
public char charAt(int index) {
240-
if ((index < 0) || (index + start >= chars.length))
241-
throw new StringIndexOutOfBoundsException(index);
242-
return chars[index + start];
243-
}
244-
245-
public int length() {
246-
return count;
247-
}
248-
249-
public CharSequence subSequence(int start, int end) {
250-
if (start < 0)
251-
throw new StringIndexOutOfBoundsException(start);
252-
if (end > count)
253-
throw new StringIndexOutOfBoundsException(end);
254-
if (start > end)
255-
throw new StringIndexOutOfBoundsException(end - start);
256-
if (start == 0 && end == count) {
257-
return this;
258-
}
259-
return new CharArrayCharSequence(chars, this.start + start, end - start);
260-
}
261-
262-
@Override
263-
public String toString() {
264-
return new String(chars, start, count);
265-
}
266-
267-
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
268-
if (srcBegin < 0)
269-
throw new StringIndexOutOfBoundsException(srcBegin);
270-
if ((srcEnd < 0) || (srcEnd > start+count))
271-
throw new StringIndexOutOfBoundsException(srcEnd);
272-
if (srcBegin > srcEnd)
273-
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
274-
System.arraycopy(chars, start + srcBegin, dst, dstBegin, srcEnd - srcBegin);
275-
}
276-
}
277-
278226
public boolean isIgnoreEncodingState() {
279227
return ignoreEncodingState;
280228
}
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+
}

0 commit comments

Comments
 (0)