Source Code Cross Referenced for StrBuilder.java in  » Library » Apache-common-lang » org » apache » commons » lang » text » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache common lang » org.apache.commons.lang.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:        package org.apache.commons.lang.text;
0018:
0019:        import java.io.Reader;
0020:        import java.io.Writer;
0021:        import java.util.Collection;
0022:        import java.util.Iterator;
0023:        import java.util.List;
0024:
0025:        import org.apache.commons.lang.ArrayUtils;
0026:        import org.apache.commons.lang.SystemUtils;
0027:
0028:        /**
0029:         * Builds a string from constituent parts providing a more flexible and powerful API
0030:         * than StringBuffer.
0031:         * <p>
0032:         * The main differences from StringBuffer/StringBuilder are:
0033:         * <ul>
0034:         * <li>Not synchronized</li>
0035:         * <li>Not final</li>
0036:         * <li>Subclasses have direct access to character array</li>
0037:         * <li>Additional methods
0038:         *  <ul>
0039:         *   <li>appendWithSeparators - adds an array of values, with a separator</li>
0040:         *   <li>appendPadding - adds a length padding characters</li>
0041:         *   <li>appendFixedLength - adds a fixed width field to the builder</li>
0042:         *   <li>toCharArray/getChars - simpler ways to get a range of the character array</li>
0043:         *   <li>delete - delete char or string</li>
0044:         *   <li>replace - search and replace for a char or string</li>
0045:         *   <li>leftString/rightString/midString - substring without exceptions</li>
0046:         *   <li>contains - whether the builder contains a char or string</li>
0047:         *   <li>size/clear/isEmpty - collections style API methods</li>
0048:         *  </ul>
0049:         * </li>
0050:         * </ul>
0051:         * <li>Views
0052:         *  <ul>
0053:         *   <li>asTokenizer - uses the internal buffer as the source of a StrTokenizer</li>
0054:         *   <li>asReader - uses the internal buffer as the source of a Reader</li>
0055:         *   <li>asWriter - allows a Writer to write directly to the internal buffer</li>
0056:         *  </ul>
0057:         * </li>
0058:         * </ul>
0059:         * <p>
0060:         * The aim has been to provide an API that mimics very closely what StringBuffer
0061:         * provides, but with additional methods. It should be noted that some edge cases,
0062:         * with invalid indices or null input, have been altered - see individual methods.
0063:         * The biggest of these changes is that by default, null will not output the text
0064:         * 'null'. This can be controlled by a property, {@link #setNullText(String)}.
0065:         *
0066:         * @author Stephen Colebourne
0067:         * @since 2.2
0068:         * @version $Id: StrBuilder.java 492371 2007-01-04 00:42:05Z scolebourne $
0069:         */
0070:        public class StrBuilder implements  Cloneable {
0071:
0072:            /**
0073:             * The extra capacity for new builders.
0074:             */
0075:            static final int CAPACITY = 32;
0076:
0077:            /**
0078:             * Required for serialization support.
0079:             * 
0080:             * @see java.io.Serializable
0081:             */
0082:            private static final long serialVersionUID = 7628716375283629643L;
0083:
0084:            /** Internal data storage. */
0085:            protected char[] buffer;
0086:            /** Current size of the buffer. */
0087:            protected int size;
0088:            /** The new line. */
0089:            private String newLine;
0090:            /** The null text. */
0091:            private String nullText;
0092:
0093:            //-----------------------------------------------------------------------
0094:            /**
0095:             * Constructor that creates an empty builder initial capacity 32 characters.
0096:             */
0097:            public StrBuilder() {
0098:                this (CAPACITY);
0099:            }
0100:
0101:            /**
0102:             * Constructor that creates an empty builder the specified initial capacity.
0103:             *
0104:             * @param initialCapacity  the initial capacity, zero or less will be converted to 32
0105:             */
0106:            public StrBuilder(int initialCapacity) {
0107:                super ();
0108:                if (initialCapacity <= 0) {
0109:                    initialCapacity = CAPACITY;
0110:                }
0111:                buffer = new char[initialCapacity];
0112:            }
0113:
0114:            /**
0115:             * Constructor that creates a builder from the string, allocating
0116:             * 32 extra characters for growth.
0117:             *
0118:             * @param str  the string to copy, null treated as blank string
0119:             */
0120:            public StrBuilder(String str) {
0121:                super ();
0122:                if (str == null) {
0123:                    buffer = new char[CAPACITY];
0124:                } else {
0125:                    buffer = new char[str.length() + CAPACITY];
0126:                    append(str);
0127:                }
0128:            }
0129:
0130:            //-----------------------------------------------------------------------
0131:            /**
0132:             * Gets the text to be appended when a new line is added.
0133:             *
0134:             * @return the new line text, null means use system default
0135:             */
0136:            public String getNewLineText() {
0137:                return newLine;
0138:            }
0139:
0140:            /**
0141:             * Sets the text to be appended when a new line is added.
0142:             *
0143:             * @param newLine  the new line text, null means use system default
0144:             * @return this, to enable chaining
0145:             */
0146:            public StrBuilder setNewLineText(String newLine) {
0147:                this .newLine = newLine;
0148:                return this ;
0149:            }
0150:
0151:            //-----------------------------------------------------------------------
0152:            /**
0153:             * Gets the text to be appended when null is added.
0154:             *
0155:             * @return the null text, null means no append
0156:             */
0157:            public String getNullText() {
0158:                return nullText;
0159:            }
0160:
0161:            /**
0162:             * Sets the text to be appended when null is added.
0163:             *
0164:             * @param nullText  the null text, null means no append
0165:             * @return this, to enable chaining
0166:             */
0167:            public StrBuilder setNullText(String nullText) {
0168:                if (nullText != null && nullText.length() == 0) {
0169:                    nullText = null;
0170:                }
0171:                this .nullText = nullText;
0172:                return this ;
0173:            }
0174:
0175:            //-----------------------------------------------------------------------
0176:            /**
0177:             * Gets the length of the string builder.
0178:             *
0179:             * @return the length
0180:             */
0181:            public int length() {
0182:                return size;
0183:            }
0184:
0185:            /**
0186:             * Updates the length of the builder by either dropping the last characters
0187:             * or adding filler of unicode zero.
0188:             *
0189:             * @param length  the length to set to, must be zero or positive
0190:             * @return this, to enable chaining
0191:             * @throws IndexOutOfBoundsException if the length is negative
0192:             */
0193:            public StrBuilder setLength(int length) {
0194:                if (length < 0) {
0195:                    throw new StringIndexOutOfBoundsException(length);
0196:                }
0197:                if (length < size) {
0198:                    size = length;
0199:                } else if (length > size) {
0200:                    ensureCapacity(length);
0201:                    int oldEnd = size;
0202:                    int newEnd = length;
0203:                    size = length;
0204:                    for (int i = oldEnd; i < newEnd; i++) {
0205:                        buffer[i] = '\0';
0206:                    }
0207:                }
0208:                return this ;
0209:            }
0210:
0211:            //-----------------------------------------------------------------------
0212:            /**
0213:             * Gets the current size of the internal character array buffer.
0214:             *
0215:             * @return the capacity
0216:             */
0217:            public int capacity() {
0218:                return buffer.length;
0219:            }
0220:
0221:            /**
0222:             * Checks the capacity and ensures that it is at least the size specified.
0223:             *
0224:             * @param capacity  the capacity to ensure
0225:             * @return this, to enable chaining
0226:             */
0227:            public StrBuilder ensureCapacity(int capacity) {
0228:                if (capacity > buffer.length) {
0229:                    char[] old = buffer;
0230:                    buffer = new char[capacity];
0231:                    System.arraycopy(old, 0, buffer, 0, size);
0232:                }
0233:                return this ;
0234:            }
0235:
0236:            /**
0237:             * Minimizes the capacity to the actual length of the string.
0238:             *
0239:             * @return this, to enable chaining
0240:             */
0241:            public StrBuilder minimizeCapacity() {
0242:                if (buffer.length > length()) {
0243:                    char[] old = buffer;
0244:                    buffer = new char[length()];
0245:                    System.arraycopy(old, 0, buffer, 0, size);
0246:                }
0247:                return this ;
0248:            }
0249:
0250:            //-----------------------------------------------------------------------
0251:            /**
0252:             * Gets the length of the string builder.
0253:             * <p>
0254:             * This method is the same as {@link #length()} and is provided to match the
0255:             * API of Collections.
0256:             *
0257:             * @return the length
0258:             */
0259:            public int size() {
0260:                return size;
0261:            }
0262:
0263:            /**
0264:             * Checks is the string builder is empty (convenience Collections API style method).
0265:             * <p>
0266:             * This method is the same as checking {@link #length()} and is provided to match the
0267:             * API of Collections.
0268:             *
0269:             * @return <code>true</code> if the size is <code>0</code>.
0270:             */
0271:            public boolean isEmpty() {
0272:                return size == 0;
0273:            }
0274:
0275:            /**
0276:             * Clears the string builder (convenience Collections API style method).
0277:             * <p>
0278:             * This method does not reduce the size of the internal character buffer.
0279:             * To do that, call <code>clear()</code> followed by {@link #minimizeCapacity()}.
0280:             * <p>
0281:             * This method is the same as {@link #setLength(int)} called with zero
0282:             * and is provided to match the API of Collections.
0283:             *
0284:             * @return this, to enable chaining
0285:             */
0286:            public StrBuilder clear() {
0287:                size = 0;
0288:                return this ;
0289:            }
0290:
0291:            //-----------------------------------------------------------------------
0292:            /**
0293:             * Gets the character at the specified index.
0294:             *
0295:             * @see #setCharAt(int, char)
0296:             * @see #deleteCharAt(int)
0297:             * @param index  the index to retrieve, must be valid
0298:             * @return the character at the index
0299:             * @throws IndexOutOfBoundsException if the index is invalid
0300:             */
0301:            public char charAt(int index) {
0302:                if (index < 0 || index >= length()) {
0303:                    throw new StringIndexOutOfBoundsException(index);
0304:                }
0305:                return buffer[index];
0306:            }
0307:
0308:            /**
0309:             * Sets the character at the specified index.
0310:             *
0311:             * @see #charAt(int)
0312:             * @see #deleteCharAt(int)
0313:             * @param index  the index to set
0314:             * @param ch  the new character
0315:             * @return this, to enable chaining
0316:             * @throws IndexOutOfBoundsException if the index is invalid
0317:             */
0318:            public StrBuilder setCharAt(int index, char ch) {
0319:                if (index < 0 || index >= length()) {
0320:                    throw new StringIndexOutOfBoundsException(index);
0321:                }
0322:                buffer[index] = ch;
0323:                return this ;
0324:            }
0325:
0326:            /**
0327:             * Deletes the character at the specified index.
0328:             *
0329:             * @see #charAt(int)
0330:             * @see #setCharAt(int, char)
0331:             * @param index  the index to delete
0332:             * @return this, to enable chaining
0333:             * @throws IndexOutOfBoundsException if the index is invalid
0334:             */
0335:            public StrBuilder deleteCharAt(int index) {
0336:                if (index < 0 || index >= size) {
0337:                    throw new StringIndexOutOfBoundsException(index);
0338:                }
0339:                deleteImpl(index, index + 1, 1);
0340:                return this ;
0341:            }
0342:
0343:            //-----------------------------------------------------------------------
0344:            /**
0345:             * Copies the builder's character array into a new character array.
0346:             * 
0347:             * @return a new array that represents the contents of the builder
0348:             */
0349:            public char[] toCharArray() {
0350:                if (size == 0) {
0351:                    return ArrayUtils.EMPTY_CHAR_ARRAY;
0352:                }
0353:                char chars[] = new char[size];
0354:                System.arraycopy(buffer, 0, chars, 0, size);
0355:                return chars;
0356:            }
0357:
0358:            /**
0359:             * Copies part of the builder's character array into a new character array.
0360:             * 
0361:             * @param startIndex  the start index, inclusive, must be valid
0362:             * @param endIndex  the end index, exclusive, must be valid except that
0363:             *  if too large it is treated as end of string
0364:             * @return a new array that holds part of the contents of the builder
0365:             * @throws IndexOutOfBoundsException if startIndex is invalid,
0366:             *  or if endIndex is invalid (but endIndex greater than size is valid)
0367:             */
0368:            public char[] toCharArray(int startIndex, int endIndex) {
0369:                endIndex = validateRange(startIndex, endIndex);
0370:                int len = endIndex - startIndex;
0371:                if (len == 0) {
0372:                    return ArrayUtils.EMPTY_CHAR_ARRAY;
0373:                }
0374:                char chars[] = new char[len];
0375:                System.arraycopy(buffer, startIndex, chars, 0, len);
0376:                return chars;
0377:            }
0378:
0379:            /**
0380:             * Copies the character array into the specified array.
0381:             * 
0382:             * @param destination  the destination array, null will cause an array to be created
0383:             * @return the input array, unless that was null or too small
0384:             */
0385:            public char[] getChars(char[] destination) {
0386:                int len = length();
0387:                if (destination == null || destination.length < len) {
0388:                    destination = new char[len];
0389:                }
0390:                System.arraycopy(buffer, 0, destination, 0, len);
0391:                return destination;
0392:            }
0393:
0394:            /**
0395:             * Copies the character array into the specified array.
0396:             *
0397:             * @param startIndex  first index to copy, inclusive, must be valid
0398:             * @param endIndex  last index, exclusive, must be valid
0399:             * @param destination  the destination array, must not be null or too small
0400:             * @param destinationIndex  the index to start copying in destination
0401:             * @throws NullPointerException if the array is null
0402:             * @throws IndexOutOfBoundsException if any index is invalid
0403:             */
0404:            public void getChars(int startIndex, int endIndex,
0405:                    char destination[], int destinationIndex) {
0406:                if (startIndex < 0) {
0407:                    throw new StringIndexOutOfBoundsException(startIndex);
0408:                }
0409:                if (endIndex < 0 || endIndex > length()) {
0410:                    throw new StringIndexOutOfBoundsException(endIndex);
0411:                }
0412:                if (startIndex > endIndex) {
0413:                    throw new StringIndexOutOfBoundsException("end < start");
0414:                }
0415:                System.arraycopy(buffer, startIndex, destination,
0416:                        destinationIndex, endIndex - startIndex);
0417:            }
0418:
0419:            //-----------------------------------------------------------------------
0420:            /**
0421:             * Appends the new line string to this string builder.
0422:             * <p>
0423:             * The new line string can be altered using {@link #setNewLineText(String)}.
0424:             * This might be used to force the output to always use Unix line endings
0425:             * even when on Windows.
0426:             *
0427:             * @return this, to enable chaining
0428:             */
0429:            public StrBuilder appendNewLine() {
0430:                if (newLine == null) {
0431:                    append(SystemUtils.LINE_SEPARATOR);
0432:                    return this ;
0433:                }
0434:                return append(newLine);
0435:            }
0436:
0437:            /**
0438:             * Appends the text representing <code>null</code> to this string builder.
0439:             *
0440:             * @return this, to enable chaining
0441:             */
0442:            public StrBuilder appendNull() {
0443:                if (nullText == null) {
0444:                    return this ;
0445:                }
0446:                return append(nullText);
0447:            }
0448:
0449:            /**
0450:             * Appends an object to this string builder.
0451:             * Appending null will call {@link #appendNull()}.
0452:             *
0453:             * @param obj  the object to append
0454:             * @return this, to enable chaining
0455:             */
0456:            public StrBuilder append(Object obj) {
0457:                if (obj == null) {
0458:                    return appendNull();
0459:                }
0460:                return append(obj.toString());
0461:            }
0462:
0463:            /**
0464:             * Appends a string to this string builder.
0465:             * Appending null will call {@link #appendNull()}.
0466:             *
0467:             * @param str  the string to append
0468:             * @return this, to enable chaining
0469:             */
0470:            public StrBuilder append(String str) {
0471:                if (str == null) {
0472:                    return appendNull();
0473:                }
0474:                int strLen = str.length();
0475:                if (strLen > 0) {
0476:                    int len = length();
0477:                    ensureCapacity(len + strLen);
0478:                    str.getChars(0, strLen, buffer, len);
0479:                    size += strLen;
0480:                }
0481:                return this ;
0482:            }
0483:
0484:            /**
0485:             * Appends part of a string to this string builder.
0486:             * Appending null will call {@link #appendNull()}.
0487:             *
0488:             * @param str  the string to append
0489:             * @param startIndex  the start index, inclusive, must be valid
0490:             * @param length  the length to append, must be valid
0491:             * @return this, to enable chaining
0492:             */
0493:            public StrBuilder append(String str, int startIndex, int length) {
0494:                if (str == null) {
0495:                    return appendNull();
0496:                }
0497:                if (startIndex < 0 || startIndex > str.length()) {
0498:                    throw new StringIndexOutOfBoundsException(
0499:                            "startIndex must be valid");
0500:                }
0501:                if (length < 0 || (startIndex + length) > str.length()) {
0502:                    throw new StringIndexOutOfBoundsException(
0503:                            "length must be valid");
0504:                }
0505:                if (length > 0) {
0506:                    int len = length();
0507:                    ensureCapacity(len + length);
0508:                    str.getChars(startIndex, startIndex + length, buffer, len);
0509:                    size += length;
0510:                }
0511:                return this ;
0512:            }
0513:
0514:            /**
0515:             * Appends a string buffer to this string builder.
0516:             * Appending null will call {@link #appendNull()}.
0517:             *
0518:             * @param str  the string buffer to append
0519:             * @return this, to enable chaining
0520:             */
0521:            public StrBuilder append(StringBuffer str) {
0522:                if (str == null) {
0523:                    return appendNull();
0524:                }
0525:                int strLen = str.length();
0526:                if (strLen > 0) {
0527:                    int len = length();
0528:                    ensureCapacity(len + strLen);
0529:                    str.getChars(0, strLen, buffer, len);
0530:                    size += strLen;
0531:                }
0532:                return this ;
0533:            }
0534:
0535:            /**
0536:             * Appends part of a string buffer to this string builder.
0537:             * Appending null will call {@link #appendNull()}.
0538:             *
0539:             * @param str  the string to append
0540:             * @param startIndex  the start index, inclusive, must be valid
0541:             * @param length  the length to append, must be valid
0542:             * @return this, to enable chaining
0543:             */
0544:            public StrBuilder append(StringBuffer str, int startIndex,
0545:                    int length) {
0546:                if (str == null) {
0547:                    return appendNull();
0548:                }
0549:                if (startIndex < 0 || startIndex > str.length()) {
0550:                    throw new StringIndexOutOfBoundsException(
0551:                            "startIndex must be valid");
0552:                }
0553:                if (length < 0 || (startIndex + length) > str.length()) {
0554:                    throw new StringIndexOutOfBoundsException(
0555:                            "length must be valid");
0556:                }
0557:                if (length > 0) {
0558:                    int len = length();
0559:                    ensureCapacity(len + length);
0560:                    str.getChars(startIndex, startIndex + length, buffer, len);
0561:                    size += length;
0562:                }
0563:                return this ;
0564:            }
0565:
0566:            /**
0567:             * Appends another string builder to this string builder.
0568:             * Appending null will call {@link #appendNull()}.
0569:             *
0570:             * @param str  the string builder to append
0571:             * @return this, to enable chaining
0572:             */
0573:            public StrBuilder append(StrBuilder str) {
0574:                if (str == null) {
0575:                    return appendNull();
0576:                }
0577:                int strLen = str.length();
0578:                if (strLen > 0) {
0579:                    int len = length();
0580:                    ensureCapacity(len + strLen);
0581:                    System.arraycopy(str.buffer, 0, buffer, len, strLen);
0582:                    size += strLen;
0583:                }
0584:                return this ;
0585:            }
0586:
0587:            /**
0588:             * Appends part of a string builder to this string builder.
0589:             * Appending null will call {@link #appendNull()}.
0590:             *
0591:             * @param str  the string to append
0592:             * @param startIndex  the start index, inclusive, must be valid
0593:             * @param length  the length to append, must be valid
0594:             * @return this, to enable chaining
0595:             */
0596:            public StrBuilder append(StrBuilder str, int startIndex, int length) {
0597:                if (str == null) {
0598:                    return appendNull();
0599:                }
0600:                if (startIndex < 0 || startIndex > str.length()) {
0601:                    throw new StringIndexOutOfBoundsException(
0602:                            "startIndex must be valid");
0603:                }
0604:                if (length < 0 || (startIndex + length) > str.length()) {
0605:                    throw new StringIndexOutOfBoundsException(
0606:                            "length must be valid");
0607:                }
0608:                if (length > 0) {
0609:                    int len = length();
0610:                    ensureCapacity(len + length);
0611:                    str.getChars(startIndex, startIndex + length, buffer, len);
0612:                    size += length;
0613:                }
0614:                return this ;
0615:            }
0616:
0617:            /**
0618:             * Appends a char array to the string builder.
0619:             * Appending null will call {@link #appendNull()}.
0620:             *
0621:             * @param chars  the char array to append
0622:             * @return this, to enable chaining
0623:             */
0624:            public StrBuilder append(char[] chars) {
0625:                if (chars == null) {
0626:                    return appendNull();
0627:                }
0628:                int strLen = chars.length;
0629:                if (strLen > 0) {
0630:                    int len = length();
0631:                    ensureCapacity(len + strLen);
0632:                    System.arraycopy(chars, 0, buffer, len, strLen);
0633:                    size += strLen;
0634:                }
0635:                return this ;
0636:            }
0637:
0638:            /**
0639:             * Appends a char array to the string builder.
0640:             * Appending null will call {@link #appendNull()}.
0641:             *
0642:             * @param chars  the char array to append
0643:             * @param startIndex  the start index, inclusive, must be valid
0644:             * @param length  the length to append, must be valid
0645:             * @return this, to enable chaining
0646:             */
0647:            public StrBuilder append(char[] chars, int startIndex, int length) {
0648:                if (chars == null) {
0649:                    return appendNull();
0650:                }
0651:                if (startIndex < 0 || startIndex > chars.length) {
0652:                    throw new StringIndexOutOfBoundsException(
0653:                            "Invalid startIndex: " + length);
0654:                }
0655:                if (length < 0 || (startIndex + length) > chars.length) {
0656:                    throw new StringIndexOutOfBoundsException(
0657:                            "Invalid length: " + length);
0658:                }
0659:                if (length > 0) {
0660:                    int len = length();
0661:                    ensureCapacity(len + length);
0662:                    System.arraycopy(chars, startIndex, buffer, len, length);
0663:                    size += length;
0664:                }
0665:                return this ;
0666:            }
0667:
0668:            /**
0669:             * Appends a boolean value to the string builder.
0670:             *
0671:             * @param value  the value to append
0672:             * @return this, to enable chaining
0673:             */
0674:            public StrBuilder append(boolean value) {
0675:                if (value) {
0676:                    ensureCapacity(size + 4);
0677:                    buffer[size++] = 't';
0678:                    buffer[size++] = 'r';
0679:                    buffer[size++] = 'u';
0680:                    buffer[size++] = 'e';
0681:                } else {
0682:                    ensureCapacity(size + 5);
0683:                    buffer[size++] = 'f';
0684:                    buffer[size++] = 'a';
0685:                    buffer[size++] = 'l';
0686:                    buffer[size++] = 's';
0687:                    buffer[size++] = 'e';
0688:                }
0689:                return this ;
0690:            }
0691:
0692:            /**
0693:             * Appends a char value to the string builder.
0694:             *
0695:             * @param ch  the value to append
0696:             * @return this, to enable chaining
0697:             */
0698:            public StrBuilder append(char ch) {
0699:                int len = length();
0700:                ensureCapacity(len + 1);
0701:                buffer[size++] = ch;
0702:                return this ;
0703:            }
0704:
0705:            /**
0706:             * Appends an int value to the string builder using <code>String.valueOf</code>.
0707:             *
0708:             * @param value  the value to append
0709:             * @return this, to enable chaining
0710:             */
0711:            public StrBuilder append(int value) {
0712:                return append(String.valueOf(value));
0713:            }
0714:
0715:            /**
0716:             * Appends a long value to the string builder using <code>String.valueOf</code>.
0717:             *
0718:             * @param value  the value to append
0719:             * @return this, to enable chaining
0720:             */
0721:            public StrBuilder append(long value) {
0722:                return append(String.valueOf(value));
0723:            }
0724:
0725:            /**
0726:             * Appends a float value to the string builder using <code>String.valueOf</code>.
0727:             *
0728:             * @param value  the value to append
0729:             * @return this, to enable chaining
0730:             */
0731:            public StrBuilder append(float value) {
0732:                return append(String.valueOf(value));
0733:            }
0734:
0735:            /**
0736:             * Appends a double value to the string builder using <code>String.valueOf</code>.
0737:             *
0738:             * @param value  the value to append
0739:             * @return this, to enable chaining
0740:             */
0741:            public StrBuilder append(double value) {
0742:                return append(String.valueOf(value));
0743:            }
0744:
0745:            //-----------------------------------------------------------------------
0746:            /**
0747:             * Appends an object followed by a new line to this string builder.
0748:             * Appending null will call {@link #appendNull()}.
0749:             *
0750:             * @param obj  the object to append
0751:             * @return this, to enable chaining
0752:             * @since 2.3
0753:             */
0754:            public StrBuilder appendln(Object obj) {
0755:                return append(obj).appendNewLine();
0756:            }
0757:
0758:            /**
0759:             * Appends a string followed by a new line to this string builder.
0760:             * Appending null will call {@link #appendNull()}.
0761:             *
0762:             * @param str  the string to append
0763:             * @return this, to enable chaining
0764:             * @since 2.3
0765:             */
0766:            public StrBuilder appendln(String str) {
0767:                return append(str).appendNewLine();
0768:            }
0769:
0770:            /**
0771:             * Appends part of a string followed by a new line to this string builder.
0772:             * Appending null will call {@link #appendNull()}.
0773:             *
0774:             * @param str  the string to append
0775:             * @param startIndex  the start index, inclusive, must be valid
0776:             * @param length  the length to append, must be valid
0777:             * @return this, to enable chaining
0778:             * @since 2.3
0779:             */
0780:            public StrBuilder appendln(String str, int startIndex, int length) {
0781:                return append(str, startIndex, length).appendNewLine();
0782:            }
0783:
0784:            /**
0785:             * Appends a string buffer followed by a new line to this string builder.
0786:             * Appending null will call {@link #appendNull()}.
0787:             *
0788:             * @param str  the string buffer to append
0789:             * @return this, to enable chaining
0790:             * @since 2.3
0791:             */
0792:            public StrBuilder appendln(StringBuffer str) {
0793:                return append(str).appendNewLine();
0794:            }
0795:
0796:            /**
0797:             * Appends part of a string buffer followed by a new line to this string builder.
0798:             * Appending null will call {@link #appendNull()}.
0799:             *
0800:             * @param str  the string to append
0801:             * @param startIndex  the start index, inclusive, must be valid
0802:             * @param length  the length to append, must be valid
0803:             * @return this, to enable chaining
0804:             * @since 2.3
0805:             */
0806:            public StrBuilder appendln(StringBuffer str, int startIndex,
0807:                    int length) {
0808:                return append(str, startIndex, length).appendNewLine();
0809:            }
0810:
0811:            /**
0812:             * Appends another string builder followed by a new line to this string builder.
0813:             * Appending null will call {@link #appendNull()}.
0814:             *
0815:             * @param str  the string builder to append
0816:             * @return this, to enable chaining
0817:             * @since 2.3
0818:             */
0819:            public StrBuilder appendln(StrBuilder str) {
0820:                return append(str).appendNewLine();
0821:            }
0822:
0823:            /**
0824:             * Appends part of a string builder followed by a new line to this string builder.
0825:             * Appending null will call {@link #appendNull()}.
0826:             *
0827:             * @param str  the string to append
0828:             * @param startIndex  the start index, inclusive, must be valid
0829:             * @param length  the length to append, must be valid
0830:             * @return this, to enable chaining
0831:             * @since 2.3
0832:             */
0833:            public StrBuilder appendln(StrBuilder str, int startIndex,
0834:                    int length) {
0835:                return append(str, startIndex, length).appendNewLine();
0836:            }
0837:
0838:            /**
0839:             * Appends a char array followed by a new line to the string builder.
0840:             * Appending null will call {@link #appendNull()}.
0841:             *
0842:             * @param chars  the char array to append
0843:             * @return this, to enable chaining
0844:             * @since 2.3
0845:             */
0846:            public StrBuilder appendln(char[] chars) {
0847:                return append(chars).appendNewLine();
0848:            }
0849:
0850:            /**
0851:             * Appends a char array followed by a new line to the string builder.
0852:             * Appending null will call {@link #appendNull()}.
0853:             *
0854:             * @param chars  the char array to append
0855:             * @param startIndex  the start index, inclusive, must be valid
0856:             * @param length  the length to append, must be valid
0857:             * @return this, to enable chaining
0858:             * @since 2.3
0859:             */
0860:            public StrBuilder appendln(char[] chars, int startIndex, int length) {
0861:                return append(chars, startIndex, length).appendNewLine();
0862:            }
0863:
0864:            /**
0865:             * Appends a boolean value followed by a new line to the string builder.
0866:             *
0867:             * @param value  the value to append
0868:             * @return this, to enable chaining
0869:             * @since 2.3
0870:             */
0871:            public StrBuilder appendln(boolean value) {
0872:                return append(value).appendNewLine();
0873:            }
0874:
0875:            /**
0876:             * Appends a char value followed by a new line to the string builder.
0877:             *
0878:             * @param ch  the value to append
0879:             * @return this, to enable chaining
0880:             * @since 2.3
0881:             */
0882:            public StrBuilder appendln(char ch) {
0883:                return append(ch).appendNewLine();
0884:            }
0885:
0886:            /**
0887:             * Appends an int value followed by a new line to the string builder using <code>String.valueOf</code>.
0888:             *
0889:             * @param value  the value to append
0890:             * @return this, to enable chaining
0891:             * @since 2.3
0892:             */
0893:            public StrBuilder appendln(int value) {
0894:                return append(value).appendNewLine();
0895:            }
0896:
0897:            /**
0898:             * Appends a long value followed by a new line to the string builder using <code>String.valueOf</code>.
0899:             *
0900:             * @param value  the value to append
0901:             * @return this, to enable chaining
0902:             * @since 2.3
0903:             */
0904:            public StrBuilder appendln(long value) {
0905:                return append(value).appendNewLine();
0906:            }
0907:
0908:            /**
0909:             * Appends a float value followed by a new line to the string builder using <code>String.valueOf</code>.
0910:             *
0911:             * @param value  the value to append
0912:             * @return this, to enable chaining
0913:             * @since 2.3
0914:             */
0915:            public StrBuilder appendln(float value) {
0916:                return append(value).appendNewLine();
0917:            }
0918:
0919:            /**
0920:             * Appends a double value followed by a new line to the string builder using <code>String.valueOf</code>.
0921:             *
0922:             * @param value  the value to append
0923:             * @return this, to enable chaining
0924:             * @since 2.3
0925:             */
0926:            public StrBuilder appendln(double value) {
0927:                return append(value).appendNewLine();
0928:            }
0929:
0930:            //-----------------------------------------------------------------------
0931:            /**
0932:             * Appends each item in an array to the builder without any separators.
0933:             * Appending a null array will have no effect.
0934:             * Each object is appended using {@link #append(Object)}.
0935:             *
0936:             * @param array  the array to append
0937:             * @return this, to enable chaining
0938:             * @since 2.3
0939:             */
0940:            public StrBuilder appendAll(Object[] array) {
0941:                if (array != null && array.length > 0) {
0942:                    for (int i = 0; i < array.length; i++) {
0943:                        append(array[i]);
0944:                    }
0945:                }
0946:                return this ;
0947:            }
0948:
0949:            /**
0950:             * Appends each item in a collection to the builder without any separators.
0951:             * Appending a null collection will have no effect.
0952:             * Each object is appended using {@link #append(Object)}.
0953:             *
0954:             * @param coll  the collection to append
0955:             * @return this, to enable chaining
0956:             * @since 2.3
0957:             */
0958:            public StrBuilder appendAll(Collection coll) {
0959:                if (coll != null && coll.size() > 0) {
0960:                    Iterator it = coll.iterator();
0961:                    while (it.hasNext()) {
0962:                        append(it.next());
0963:                    }
0964:                }
0965:                return this ;
0966:            }
0967:
0968:            /**
0969:             * Appends each item in an iterator to the builder without any separators.
0970:             * Appending a null iterator will have no effect.
0971:             * Each object is appended using {@link #append(Object)}.
0972:             *
0973:             * @param it  the iterator to append
0974:             * @return this, to enable chaining
0975:             * @since 2.3
0976:             */
0977:            public StrBuilder appendAll(Iterator it) {
0978:                if (it != null) {
0979:                    while (it.hasNext()) {
0980:                        append(it.next());
0981:                    }
0982:                }
0983:                return this ;
0984:            }
0985:
0986:            //-----------------------------------------------------------------------
0987:            /**
0988:             * Appends an array placing separators between each value, but
0989:             * not before the first or after the last.
0990:             * Appending a null array will have no effect.
0991:             * Each object is appended using {@link #append(Object)}.
0992:             *
0993:             * @param array  the array to append
0994:             * @param separator  the separator to use, null means no separator
0995:             * @return this, to enable chaining
0996:             */
0997:            public StrBuilder appendWithSeparators(Object[] array,
0998:                    String separator) {
0999:                if (array != null && array.length > 0) {
1000:                    separator = (separator == null ? "" : separator);
1001:                    append(array[0]);
1002:                    for (int i = 1; i < array.length; i++) {
1003:                        append(separator);
1004:                        append(array[i]);
1005:                    }
1006:                }
1007:                return this ;
1008:            }
1009:
1010:            /**
1011:             * Appends a collection placing separators between each value, but
1012:             * not before the first or after the last.
1013:             * Appending a null collection will have no effect.
1014:             * Each object is appended using {@link #append(Object)}.
1015:             *
1016:             * @param coll  the collection to append
1017:             * @param separator  the separator to use, null means no separator
1018:             * @return this, to enable chaining
1019:             */
1020:            public StrBuilder appendWithSeparators(Collection coll,
1021:                    String separator) {
1022:                if (coll != null && coll.size() > 0) {
1023:                    separator = (separator == null ? "" : separator);
1024:                    Iterator it = coll.iterator();
1025:                    while (it.hasNext()) {
1026:                        append(it.next());
1027:                        if (it.hasNext()) {
1028:                            append(separator);
1029:                        }
1030:                    }
1031:                }
1032:                return this ;
1033:            }
1034:
1035:            /**
1036:             * Appends an iterator placing separators between each value, but
1037:             * not before the first or after the last.
1038:             * Appending a null iterator will have no effect.
1039:             * Each object is appended using {@link #append(Object)}.
1040:             *
1041:             * @param it  the iterator to append
1042:             * @param separator  the separator to use, null means no separator
1043:             * @return this, to enable chaining
1044:             */
1045:            public StrBuilder appendWithSeparators(Iterator it, String separator) {
1046:                if (it != null) {
1047:                    separator = (separator == null ? "" : separator);
1048:                    while (it.hasNext()) {
1049:                        append(it.next());
1050:                        if (it.hasNext()) {
1051:                            append(separator);
1052:                        }
1053:                    }
1054:                }
1055:                return this ;
1056:            }
1057:
1058:            //-----------------------------------------------------------------------
1059:            /**
1060:             * Appends a separator if the builder is currently non-empty.
1061:             * Appending a null separator will have no effect.
1062:             * The separator is appended using {@link #append(String)}.
1063:             * <p>
1064:             * This method is useful for adding a separator each time around the
1065:             * loop except the first.
1066:             * <pre>
1067:             * for (Iterator it = list.iterator(); it.hasNext(); ) {
1068:             *   appendSeparator(",");
1069:             *   append(it.next());
1070:             * }
1071:             * </pre>
1072:             * Note that for this simple example, you should use
1073:             * {@link #appendWithSeparators(Collection, String)}.
1074:             * 
1075:             * @param separator  the separator to use, null means no separator
1076:             * @return this, to enable chaining
1077:             * @since 2.3
1078:             */
1079:            public StrBuilder appendSeparator(String separator) {
1080:                if (separator != null && size() > 0) {
1081:                    append(separator);
1082:                }
1083:                return this ;
1084:            }
1085:
1086:            /**
1087:             * Appends a separator if the builder is currently non-empty.
1088:             * The separator is appended using {@link #append(char)}.
1089:             * <p>
1090:             * This method is useful for adding a separator each time around the
1091:             * loop except the first.
1092:             * <pre>
1093:             * for (Iterator it = list.iterator(); it.hasNext(); ) {
1094:             *   appendSeparator(',');
1095:             *   append(it.next());
1096:             * }
1097:             * </pre>
1098:             * Note that for this simple example, you should use
1099:             * {@link #appendWithSeparators(Collection, String)}.
1100:             * 
1101:             * @param separator  the separator to use
1102:             * @return this, to enable chaining
1103:             * @since 2.3
1104:             */
1105:            public StrBuilder appendSeparator(char separator) {
1106:                if (size() > 0) {
1107:                    append(separator);
1108:                }
1109:                return this ;
1110:            }
1111:
1112:            /**
1113:             * Appends a separator to the builder if the loop index is greater than zero.
1114:             * Appending a null separator will have no effect.
1115:             * The separator is appended using {@link #append(String)}.
1116:             * <p>
1117:             * This method is useful for adding a separator each time around the
1118:             * loop except the first.
1119:             * <pre>
1120:             * for (int i = 0; i < list.size(); i++) {
1121:             *   appendSeparator(",", i);
1122:             *   append(list.get(i));
1123:             * }
1124:             * </pre>
1125:             * Note that for this simple example, you should use
1126:             * {@link #appendWithSeparators(Collection, String)}.
1127:             * 
1128:             * @param separator  the separator to use, null means no separator
1129:             * @param loopIndex  the loop index
1130:             * @return this, to enable chaining
1131:             * @since 2.3
1132:             */
1133:            public StrBuilder appendSeparator(String separator, int loopIndex) {
1134:                if (separator != null && loopIndex > 0) {
1135:                    append(separator);
1136:                }
1137:                return this ;
1138:            }
1139:
1140:            /**
1141:             * Appends a separator to the builder if the loop index is greater than zero.
1142:             * The separator is appended using {@link #append(char)}.
1143:             * <p>
1144:             * This method is useful for adding a separator each time around the
1145:             * loop except the first.
1146:             * <pre>
1147:             * for (int i = 0; i < list.size(); i++) {
1148:             *   appendSeparator(",", i);
1149:             *   append(list.get(i));
1150:             * }
1151:             * </pre>
1152:             * Note that for this simple example, you should use
1153:             * {@link #appendWithSeparators(Collection, String)}.
1154:             * 
1155:             * @param separator  the separator to use
1156:             * @param loopIndex  the loop index
1157:             * @return this, to enable chaining
1158:             * @since 2.3
1159:             */
1160:            public StrBuilder appendSeparator(char separator, int loopIndex) {
1161:                if (loopIndex > 0) {
1162:                    append(separator);
1163:                }
1164:                return this ;
1165:            }
1166:
1167:            //-----------------------------------------------------------------------
1168:            /**
1169:             * Appends the pad character to the builder the specified number of times.
1170:             * 
1171:             * @param length  the length to append, negative means no append
1172:             * @param padChar  the character to append
1173:             * @return this, to enable chaining
1174:             */
1175:            public StrBuilder appendPadding(int length, char padChar) {
1176:                if (length >= 0) {
1177:                    ensureCapacity(size + length);
1178:                    for (int i = 0; i < length; i++) {
1179:                        buffer[size++] = padChar;
1180:                    }
1181:                }
1182:                return this ;
1183:            }
1184:
1185:            //-----------------------------------------------------------------------
1186:            /**
1187:             * Appends an object to the builder padding on the left to a fixed width.
1188:             * The <code>toString</code> of the object is used.
1189:             * If the object is larger than the length, the left hand side is lost.
1190:             * If the object is null, the null text value is used.
1191:             * 
1192:             * @param obj  the object to append, null uses null text
1193:             * @param width  the fixed field width, zero or negative has no effect
1194:             * @param padChar  the pad character to use
1195:             * @return this, to enable chaining
1196:             */
1197:            public StrBuilder appendFixedWidthPadLeft(Object obj, int width,
1198:                    char padChar) {
1199:                if (width > 0) {
1200:                    ensureCapacity(size + width);
1201:                    String str = (obj == null ? getNullText() : obj.toString());
1202:                    int strLen = str.length();
1203:                    if (strLen >= width) {
1204:                        str.getChars(strLen - width, strLen, buffer, size);
1205:                    } else {
1206:                        int padLen = width - strLen;
1207:                        for (int i = 0; i < padLen; i++) {
1208:                            buffer[size + i] = padChar;
1209:                        }
1210:                        str.getChars(0, strLen, buffer, size + padLen);
1211:                    }
1212:                    size += width;
1213:                }
1214:                return this ;
1215:            }
1216:
1217:            /**
1218:             * Appends an object to the builder padding on the left to a fixed width.
1219:             * The <code>String.valueOf</code> of the <code>int</code> value is used.
1220:             * If the formatted value is larger than the length, the left hand side is lost.
1221:             * 
1222:             * @param value  the value to append
1223:             * @param width  the fixed field width, zero or negative has no effect
1224:             * @param padChar  the pad character to use
1225:             * @return this, to enable chaining
1226:             */
1227:            public StrBuilder appendFixedWidthPadLeft(int value, int width,
1228:                    char padChar) {
1229:                return appendFixedWidthPadLeft(String.valueOf(value), width,
1230:                        padChar);
1231:            }
1232:
1233:            /**
1234:             * Appends an object to the builder padding on the right to a fixed length.
1235:             * The <code>toString</code> of the object is used.
1236:             * If the object is larger than the length, the right hand side is lost.
1237:             * If the object is null, null text value is used.
1238:             * 
1239:             * @param obj  the object to append, null uses null text
1240:             * @param width  the fixed field width, zero or negative has no effect
1241:             * @param padChar  the pad character to use
1242:             * @return this, to enable chaining
1243:             */
1244:            public StrBuilder appendFixedWidthPadRight(Object obj, int width,
1245:                    char padChar) {
1246:                if (width > 0) {
1247:                    ensureCapacity(size + width);
1248:                    String str = (obj == null ? getNullText() : obj.toString());
1249:                    int strLen = str.length();
1250:                    if (strLen >= width) {
1251:                        str.getChars(0, width, buffer, size);
1252:                    } else {
1253:                        int padLen = width - strLen;
1254:                        str.getChars(0, strLen, buffer, size);
1255:                        for (int i = 0; i < padLen; i++) {
1256:                            buffer[size + strLen + i] = padChar;
1257:                        }
1258:                    }
1259:                    size += width;
1260:                }
1261:                return this ;
1262:            }
1263:
1264:            /**
1265:             * Appends an object to the builder padding on the right to a fixed length.
1266:             * The <code>String.valueOf</code> of the <code>int</code> value is used.
1267:             * If the object is larger than the length, the right hand side is lost.
1268:             * 
1269:             * @param value  the value to append
1270:             * @param width  the fixed field width, zero or negative has no effect
1271:             * @param padChar  the pad character to use
1272:             * @return this, to enable chaining
1273:             */
1274:            public StrBuilder appendFixedWidthPadRight(int value, int width,
1275:                    char padChar) {
1276:                return appendFixedWidthPadRight(String.valueOf(value), width,
1277:                        padChar);
1278:            }
1279:
1280:            //-----------------------------------------------------------------------
1281:            /**
1282:             * Inserts the string representation of an object into this builder.
1283:             * Inserting null will use the stored null text value.
1284:             *
1285:             * @param index  the index to add at, must be valid
1286:             * @param obj  the object to insert
1287:             * @return this, to enable chaining
1288:             * @throws IndexOutOfBoundsException if the index is invalid
1289:             */
1290:            public StrBuilder insert(int index, Object obj) {
1291:                if (obj == null) {
1292:                    return insert(index, nullText);
1293:                }
1294:                return insert(index, obj.toString());
1295:            }
1296:
1297:            /**
1298:             * Inserts the string into this builder.
1299:             * Inserting null will use the stored null text value.
1300:             *
1301:             * @param index  the index to add at, must be valid
1302:             * @param str  the string to insert
1303:             * @return this, to enable chaining
1304:             * @throws IndexOutOfBoundsException if the index is invalid
1305:             */
1306:            public StrBuilder insert(int index, String str) {
1307:                validateIndex(index);
1308:                if (str == null) {
1309:                    str = nullText;
1310:                }
1311:                int strLen = (str == null ? 0 : str.length());
1312:                if (strLen > 0) {
1313:                    int newSize = size + strLen;
1314:                    ensureCapacity(newSize);
1315:                    System.arraycopy(buffer, index, buffer, index + strLen,
1316:                            size - index);
1317:                    size = newSize;
1318:                    str.getChars(0, strLen, buffer, index);
1319:                }
1320:                return this ;
1321:            }
1322:
1323:            /**
1324:             * Inserts the character array into this builder.
1325:             * Inserting null will use the stored null text value.
1326:             *
1327:             * @param index  the index to add at, must be valid
1328:             * @param chars  the char array to insert
1329:             * @return this, to enable chaining
1330:             * @throws IndexOutOfBoundsException if the index is invalid
1331:             */
1332:            public StrBuilder insert(int index, char chars[]) {
1333:                validateIndex(index);
1334:                if (chars == null) {
1335:                    return insert(index, nullText);
1336:                }
1337:                int len = chars.length;
1338:                if (len > 0) {
1339:                    ensureCapacity(size + len);
1340:                    System.arraycopy(buffer, index, buffer, index + len, size
1341:                            - index);
1342:                    System.arraycopy(chars, 0, buffer, index, len);
1343:                    size += len;
1344:                }
1345:                return this ;
1346:            }
1347:
1348:            /**
1349:             * Inserts part of the character array into this builder.
1350:             * Inserting null will use the stored null text value.
1351:             *
1352:             * @param index  the index to add at, must be valid
1353:             * @param chars  the char array to insert
1354:             * @param offset  the offset into the character array to start at, must be valid
1355:             * @param length  the length of the character array part to copy, must be positive
1356:             * @return this, to enable chaining
1357:             * @throws IndexOutOfBoundsException if any index is invalid
1358:             */
1359:            public StrBuilder insert(int index, char chars[], int offset,
1360:                    int length) {
1361:                validateIndex(index);
1362:                if (chars == null) {
1363:                    return insert(index, nullText);
1364:                }
1365:                if (offset < 0 || offset > chars.length) {
1366:                    throw new StringIndexOutOfBoundsException(
1367:                            "Invalid offset: " + offset);
1368:                }
1369:                if (length < 0 || offset + length > chars.length) {
1370:                    throw new StringIndexOutOfBoundsException(
1371:                            "Invalid length: " + length);
1372:                }
1373:                if (length > 0) {
1374:                    ensureCapacity(size + length);
1375:                    System.arraycopy(buffer, index, buffer, index + length,
1376:                            size - index);
1377:                    System.arraycopy(chars, offset, buffer, index, length);
1378:                    size += length;
1379:                }
1380:                return this ;
1381:            }
1382:
1383:            /**
1384:             * Inserts the value into this builder.
1385:             *
1386:             * @param index  the index to add at, must be valid
1387:             * @param value  the value to insert
1388:             * @return this, to enable chaining
1389:             * @throws IndexOutOfBoundsException if the index is invalid
1390:             */
1391:            public StrBuilder insert(int index, boolean value) {
1392:                validateIndex(index);
1393:                if (value) {
1394:                    ensureCapacity(size + 4);
1395:                    System.arraycopy(buffer, index, buffer, index + 4, size
1396:                            - index);
1397:                    buffer[index++] = 't';
1398:                    buffer[index++] = 'r';
1399:                    buffer[index++] = 'u';
1400:                    buffer[index] = 'e';
1401:                    size += 4;
1402:                } else {
1403:                    ensureCapacity(size + 5);
1404:                    System.arraycopy(buffer, index, buffer, index + 5, size
1405:                            - index);
1406:                    buffer[index++] = 'f';
1407:                    buffer[index++] = 'a';
1408:                    buffer[index++] = 'l';
1409:                    buffer[index++] = 's';
1410:                    buffer[index] = 'e';
1411:                    size += 5;
1412:                }
1413:                return this ;
1414:            }
1415:
1416:            /**
1417:             * Inserts the value into this builder.
1418:             *
1419:             * @param index  the index to add at, must be valid
1420:             * @param value  the value to insert
1421:             * @return this, to enable chaining
1422:             * @throws IndexOutOfBoundsException if the index is invalid
1423:             */
1424:            public StrBuilder insert(int index, char value) {
1425:                validateIndex(index);
1426:                ensureCapacity(size + 1);
1427:                System
1428:                        .arraycopy(buffer, index, buffer, index + 1, size
1429:                                - index);
1430:                buffer[index] = value;
1431:                size++;
1432:                return this ;
1433:            }
1434:
1435:            /**
1436:             * Inserts the value into this builder.
1437:             *
1438:             * @param index  the index to add at, must be valid
1439:             * @param value  the value to insert
1440:             * @return this, to enable chaining
1441:             * @throws IndexOutOfBoundsException if the index is invalid
1442:             */
1443:            public StrBuilder insert(int index, int value) {
1444:                return insert(index, String.valueOf(value));
1445:            }
1446:
1447:            /**
1448:             * Inserts the value into this builder.
1449:             *
1450:             * @param index  the index to add at, must be valid
1451:             * @param value  the value to insert
1452:             * @return this, to enable chaining
1453:             * @throws IndexOutOfBoundsException if the index is invalid
1454:             */
1455:            public StrBuilder insert(int index, long value) {
1456:                return insert(index, String.valueOf(value));
1457:            }
1458:
1459:            /**
1460:             * Inserts the value into this builder.
1461:             *
1462:             * @param index  the index to add at, must be valid
1463:             * @param value  the value to insert
1464:             * @return this, to enable chaining
1465:             * @throws IndexOutOfBoundsException if the index is invalid
1466:             */
1467:            public StrBuilder insert(int index, float value) {
1468:                return insert(index, String.valueOf(value));
1469:            }
1470:
1471:            /**
1472:             * Inserts the value into this builder.
1473:             *
1474:             * @param index  the index to add at, must be valid
1475:             * @param value  the value to insert
1476:             * @return this, to enable chaining
1477:             * @throws IndexOutOfBoundsException if the index is invalid
1478:             */
1479:            public StrBuilder insert(int index, double value) {
1480:                return insert(index, String.valueOf(value));
1481:            }
1482:
1483:            //-----------------------------------------------------------------------
1484:            /**
1485:             * Internal method to delete a range without validation.
1486:             *
1487:             * @param startIndex  the start index, must be valid
1488:             * @param endIndex  the end index (exclusive), must be valid
1489:             * @param len  the length, must be valid
1490:             * @throws IndexOutOfBoundsException if any index is invalid
1491:             */
1492:            private void deleteImpl(int startIndex, int endIndex, int len) {
1493:                System.arraycopy(buffer, endIndex, buffer, startIndex, size
1494:                        - endIndex);
1495:                size -= len;
1496:            }
1497:
1498:            /**
1499:             * Deletes the characters between the two specified indices.
1500:             *
1501:             * @param startIndex  the start index, inclusive, must be valid
1502:             * @param endIndex  the end index, exclusive, must be valid except
1503:             *  that if too large it is treated as end of string
1504:             * @return this, to enable chaining
1505:             * @throws IndexOutOfBoundsException if the index is invalid
1506:             */
1507:            public StrBuilder delete(int startIndex, int endIndex) {
1508:                endIndex = validateRange(startIndex, endIndex);
1509:                int len = endIndex - startIndex;
1510:                if (len > 0) {
1511:                    deleteImpl(startIndex, endIndex, len);
1512:                }
1513:                return this ;
1514:            }
1515:
1516:            //-----------------------------------------------------------------------
1517:            /**
1518:             * Deletes the character wherever it occurs in the builder.
1519:             *
1520:             * @param ch  the character to delete
1521:             * @return this, to enable chaining
1522:             */
1523:            public StrBuilder deleteAll(char ch) {
1524:                for (int i = 0; i < size; i++) {
1525:                    if (buffer[i] == ch) {
1526:                        int start = i;
1527:                        while (++i < size) {
1528:                            if (buffer[i] != ch) {
1529:                                break;
1530:                            }
1531:                        }
1532:                        int len = i - start;
1533:                        deleteImpl(start, i, len);
1534:                        i -= len;
1535:                    }
1536:                }
1537:                return this ;
1538:            }
1539:
1540:            /**
1541:             * Deletes the character wherever it occurs in the builder.
1542:             *
1543:             * @param ch  the character to delete
1544:             * @return this, to enable chaining
1545:             */
1546:            public StrBuilder deleteFirst(char ch) {
1547:                for (int i = 0; i < size; i++) {
1548:                    if (buffer[i] == ch) {
1549:                        deleteImpl(i, i + 1, 1);
1550:                        break;
1551:                    }
1552:                }
1553:                return this ;
1554:            }
1555:
1556:            //-----------------------------------------------------------------------
1557:            /**
1558:             * Deletes the string wherever it occurs in the builder.
1559:             *
1560:             * @param str  the string to delete, null causes no action
1561:             * @return this, to enable chaining
1562:             */
1563:            public StrBuilder deleteAll(String str) {
1564:                int len = (str == null ? 0 : str.length());
1565:                if (len > 0) {
1566:                    int index = indexOf(str, 0);
1567:                    while (index >= 0) {
1568:                        deleteImpl(index, index + len, len);
1569:                        index = indexOf(str, index);
1570:                    }
1571:                }
1572:                return this ;
1573:            }
1574:
1575:            /**
1576:             * Deletes the string wherever it occurs in the builder.
1577:             *
1578:             * @param str  the string to delete, null causes no action
1579:             * @return this, to enable chaining
1580:             */
1581:            public StrBuilder deleteFirst(String str) {
1582:                int len = (str == null ? 0 : str.length());
1583:                if (len > 0) {
1584:                    int index = indexOf(str, 0);
1585:                    if (index >= 0) {
1586:                        deleteImpl(index, index + len, len);
1587:                    }
1588:                }
1589:                return this ;
1590:            }
1591:
1592:            //-----------------------------------------------------------------------
1593:            /**
1594:             * Deletes all parts of the builder that the matcher matches.
1595:             * <p>
1596:             * Matchers can be used to perform advanced deletion behaviour.
1597:             * For example you could write a matcher to delete all occurances
1598:             * where the character 'a' is followed by a number.
1599:             *
1600:             * @param matcher  the matcher to use to find the deletion, null causes no action
1601:             * @return this, to enable chaining
1602:             */
1603:            public StrBuilder deleteAll(StrMatcher matcher) {
1604:                return replace(matcher, null, 0, size, -1);
1605:            }
1606:
1607:            /**
1608:             * Deletes the first match within the builder using the specified matcher.
1609:             * <p>
1610:             * Matchers can be used to perform advanced deletion behaviour.
1611:             * For example you could write a matcher to delete
1612:             * where the character 'a' is followed by a number.
1613:             *
1614:             * @param matcher  the matcher to use to find the deletion, null causes no action
1615:             * @return this, to enable chaining
1616:             */
1617:            public StrBuilder deleteFirst(StrMatcher matcher) {
1618:                return replace(matcher, null, 0, size, 1);
1619:            }
1620:
1621:            //-----------------------------------------------------------------------
1622:            /**
1623:             * Internal method to delete a range without validation.
1624:             *
1625:             * @param startIndex  the start index, must be valid
1626:             * @param endIndex  the end index (exclusive), must be valid
1627:             * @param removeLen  the length to remove (endIndex - startIndex), must be valid
1628:             * @param insertStr  the string to replace with, null means delete range
1629:             * @param insertLen  the length of the insert string, must be valid
1630:             * @throws IndexOutOfBoundsException if any index is invalid
1631:             */
1632:            private void replaceImpl(int startIndex, int endIndex,
1633:                    int removeLen, String insertStr, int insertLen) {
1634:                int newSize = size - removeLen + insertLen;
1635:                if (insertLen != removeLen) {
1636:                    ensureCapacity(newSize);
1637:                    System.arraycopy(buffer, endIndex, buffer, startIndex
1638:                            + insertLen, size - endIndex);
1639:                    size = newSize;
1640:                }
1641:                if (insertLen > 0) {
1642:                    insertStr.getChars(0, insertLen, buffer, startIndex);
1643:                }
1644:            }
1645:
1646:            /**
1647:             * Replaces a portion of the string builder with another string.
1648:             * The length of the inserted string does not have to match the removed length.
1649:             *
1650:             * @param startIndex  the start index, inclusive, must be valid
1651:             * @param endIndex  the end index, exclusive, must be valid except
1652:             *  that if too large it is treated as end of string
1653:             * @param replaceStr  the string to replace with, null means delete range
1654:             * @return this, to enable chaining
1655:             * @throws IndexOutOfBoundsException if the index is invalid
1656:             */
1657:            public StrBuilder replace(int startIndex, int endIndex,
1658:                    String replaceStr) {
1659:                endIndex = validateRange(startIndex, endIndex);
1660:                int insertLen = (replaceStr == null ? 0 : replaceStr.length());
1661:                replaceImpl(startIndex, endIndex, endIndex - startIndex,
1662:                        replaceStr, insertLen);
1663:                return this ;
1664:            }
1665:
1666:            //-----------------------------------------------------------------------
1667:            /**
1668:             * Replaces the search character with the replace character
1669:             * throughout the builder.
1670:             *
1671:             * @param search  the search character
1672:             * @param replace  the replace character
1673:             * @return this, to enable chaining
1674:             */
1675:            public StrBuilder replaceAll(char search, char replace) {
1676:                if (search != replace) {
1677:                    for (int i = 0; i < size; i++) {
1678:                        if (buffer[i] == search) {
1679:                            buffer[i] = replace;
1680:                        }
1681:                    }
1682:                }
1683:                return this ;
1684:            }
1685:
1686:            /**
1687:             * Replaces the first instance of the search character with the
1688:             * replace character in the builder.
1689:             *
1690:             * @param search  the search character
1691:             * @param replace  the replace character
1692:             * @return this, to enable chaining
1693:             */
1694:            public StrBuilder replaceFirst(char search, char replace) {
1695:                if (search != replace) {
1696:                    for (int i = 0; i < size; i++) {
1697:                        if (buffer[i] == search) {
1698:                            buffer[i] = replace;
1699:                            break;
1700:                        }
1701:                    }
1702:                }
1703:                return this ;
1704:            }
1705:
1706:            //-----------------------------------------------------------------------
1707:            /**
1708:             * Replaces the search string with the replace string throughout the builder.
1709:             *
1710:             * @param searchStr  the search string, null causes no action to occur
1711:             * @param replaceStr  the replace string, null is equivalent to an empty string
1712:             * @return this, to enable chaining
1713:             */
1714:            public StrBuilder replaceAll(String searchStr, String replaceStr) {
1715:                int searchLen = (searchStr == null ? 0 : searchStr.length());
1716:                if (searchLen > 0) {
1717:                    int replaceLen = (replaceStr == null ? 0 : replaceStr
1718:                            .length());
1719:                    int index = indexOf(searchStr, 0);
1720:                    while (index >= 0) {
1721:                        replaceImpl(index, index + searchLen, searchLen,
1722:                                replaceStr, replaceLen);
1723:                        index = indexOf(searchStr, index + replaceLen);
1724:                    }
1725:                }
1726:                return this ;
1727:            }
1728:
1729:            /**
1730:             * Replaces the first instance of the search string with the replace string.
1731:             *
1732:             * @param searchStr  the search string, null causes no action to occur
1733:             * @param replaceStr  the replace string, null is equivalent to an empty string
1734:             * @return this, to enable chaining
1735:             */
1736:            public StrBuilder replaceFirst(String searchStr, String replaceStr) {
1737:                int searchLen = (searchStr == null ? 0 : searchStr.length());
1738:                if (searchLen > 0) {
1739:                    int index = indexOf(searchStr, 0);
1740:                    if (index >= 0) {
1741:                        int replaceLen = (replaceStr == null ? 0 : replaceStr
1742:                                .length());
1743:                        replaceImpl(index, index + searchLen, searchLen,
1744:                                replaceStr, replaceLen);
1745:                    }
1746:                }
1747:                return this ;
1748:            }
1749:
1750:            //-----------------------------------------------------------------------
1751:            /**
1752:             * Replaces all matches within the builder with the replace string.
1753:             * <p>
1754:             * Matchers can be used to perform advanced replace behaviour.
1755:             * For example you could write a matcher to replace all occurances
1756:             * where the character 'a' is followed by a number.
1757:             *
1758:             * @param matcher  the matcher to use to find the deletion, null causes no action
1759:             * @param replaceStr  the replace string, null is equivalent to an empty string
1760:             * @return this, to enable chaining
1761:             */
1762:            public StrBuilder replaceAll(StrMatcher matcher, String replaceStr) {
1763:                return replace(matcher, replaceStr, 0, size, -1);
1764:            }
1765:
1766:            /**
1767:             * Replaces the first match within the builder with the replace string.
1768:             * <p>
1769:             * Matchers can be used to perform advanced replace behaviour.
1770:             * For example you could write a matcher to replace
1771:             * where the character 'a' is followed by a number.
1772:             *
1773:             * @param matcher  the matcher to use to find the deletion, null causes no action
1774:             * @param replaceStr  the replace string, null is equivalent to an empty string
1775:             * @return this, to enable chaining
1776:             */
1777:            public StrBuilder replaceFirst(StrMatcher matcher, String replaceStr) {
1778:                return replace(matcher, replaceStr, 0, size, 1);
1779:            }
1780:
1781:            // -----------------------------------------------------------------------
1782:            /**
1783:             * Advanced search and replaces within the builder using a matcher.
1784:             * <p>
1785:             * Matchers can be used to perform advanced behaviour.
1786:             * For example you could write a matcher to delete all occurances
1787:             * where the character 'a' is followed by a number.
1788:             *
1789:             * @param matcher  the matcher to use to find the deletion, null causes no action
1790:             * @param replaceStr  the string to replace the match with, null is a delete
1791:             * @param startIndex  the start index, inclusive, must be valid
1792:             * @param endIndex  the end index, exclusive, must be valid except
1793:             *  that if too large it is treated as end of string
1794:             * @param replaceCount  the number of times to replace, -1 for replace all
1795:             * @return this, to enable chaining
1796:             * @throws IndexOutOfBoundsException if start index is invalid
1797:             */
1798:            public StrBuilder replace(StrMatcher matcher, String replaceStr,
1799:                    int startIndex, int endIndex, int replaceCount) {
1800:                endIndex = validateRange(startIndex, endIndex);
1801:                return replaceImpl(matcher, replaceStr, startIndex, endIndex,
1802:                        replaceCount);
1803:            }
1804:
1805:            /**
1806:             * Replaces within the builder using a matcher.
1807:             * <p>
1808:             * Matchers can be used to perform advanced behaviour.
1809:             * For example you could write a matcher to delete all occurances
1810:             * where the character 'a' is followed by a number.
1811:             *
1812:             * @param matcher  the matcher to use to find the deletion, null causes no action
1813:             * @param replaceStr  the string to replace the match with, null is a delete
1814:             * @param from  the start index, must be valid
1815:             * @param to  the end index (exclusive), must be valid
1816:             * @param replaceCount  the number of times to replace, -1 for replace all
1817:             * @return this, to enable chaining
1818:             * @throws IndexOutOfBoundsException if any index is invalid
1819:             */
1820:            private StrBuilder replaceImpl(StrMatcher matcher,
1821:                    String replaceStr, int from, int to, int replaceCount) {
1822:                if (matcher == null || size == 0) {
1823:                    return this ;
1824:                }
1825:                int replaceLen = (replaceStr == null ? 0 : replaceStr.length());
1826:                char[] buf = buffer;
1827:                for (int i = from; i < to && replaceCount != 0; i++) {
1828:                    int removeLen = matcher.isMatch(buf, i, from, to);
1829:                    if (removeLen > 0) {
1830:                        replaceImpl(i, i + removeLen, removeLen, replaceStr,
1831:                                replaceLen);
1832:                        to = to - removeLen + replaceLen;
1833:                        i = i + replaceLen - 1;
1834:                        if (replaceCount > 0) {
1835:                            replaceCount--;
1836:                        }
1837:                    }
1838:                }
1839:                return this ;
1840:            }
1841:
1842:            //-----------------------------------------------------------------------
1843:            /**
1844:             * Reverses the string builder placing each character in the opposite index.
1845:             * 
1846:             * @return this, to enable chaining
1847:             */
1848:            public StrBuilder reverse() {
1849:                if (size == 0) {
1850:                    return this ;
1851:                }
1852:
1853:                int half = size / 2;
1854:                char[] buf = buffer;
1855:                for (int leftIdx = 0, rightIdx = size - 1; leftIdx < half; leftIdx++, rightIdx--) {
1856:                    char swap = buf[leftIdx];
1857:                    buf[leftIdx] = buf[rightIdx];
1858:                    buf[rightIdx] = swap;
1859:                }
1860:                return this ;
1861:            }
1862:
1863:            //-----------------------------------------------------------------------
1864:            /**
1865:             * Trims the builder by removing characters less than or equal to a space
1866:             * from the beginning and end.
1867:             *
1868:             * @return this, to enable chaining
1869:             */
1870:            public StrBuilder trim() {
1871:                if (size == 0) {
1872:                    return this ;
1873:                }
1874:                int len = size;
1875:                char[] buf = buffer;
1876:                int pos = 0;
1877:                while (pos < len && buf[pos] <= ' ') {
1878:                    pos++;
1879:                }
1880:                while (pos < len && buf[len - 1] <= ' ') {
1881:                    len--;
1882:                }
1883:                if (len < size) {
1884:                    delete(len, size);
1885:                }
1886:                if (pos > 0) {
1887:                    delete(0, pos);
1888:                }
1889:                return this ;
1890:            }
1891:
1892:            //-----------------------------------------------------------------------
1893:            /**
1894:             * Checks whether this builder starts with the specified string.
1895:             * <p>
1896:             * Note that this method handles null input quietly, unlike String.
1897:             * 
1898:             * @param str  the string to search for, null returns false
1899:             * @return true if the builder starts with the string
1900:             */
1901:            public boolean startsWith(String str) {
1902:                if (str == null) {
1903:                    return false;
1904:                }
1905:                int len = str.length();
1906:                if (len == 0) {
1907:                    return true;
1908:                }
1909:                if (len > size) {
1910:                    return false;
1911:                }
1912:                for (int i = 0; i < len; i++) {
1913:                    if (buffer[i] != str.charAt(i)) {
1914:                        return false;
1915:                    }
1916:                }
1917:                return true;
1918:            }
1919:
1920:            /**
1921:             * Checks whether this builder ends with the specified string.
1922:             * <p>
1923:             * Note that this method handles null input quietly, unlike String.
1924:             * 
1925:             * @param str  the string to search for, null returns false
1926:             * @return true if the builder ends with the string
1927:             */
1928:            public boolean endsWith(String str) {
1929:                if (str == null) {
1930:                    return false;
1931:                }
1932:                int len = str.length();
1933:                if (len == 0) {
1934:                    return true;
1935:                }
1936:                if (len > size) {
1937:                    return false;
1938:                }
1939:                int pos = size - len;
1940:                for (int i = 0; i < len; i++, pos++) {
1941:                    if (buffer[pos] != str.charAt(i)) {
1942:                        return false;
1943:                    }
1944:                }
1945:                return true;
1946:            }
1947:
1948:            //-----------------------------------------------------------------------
1949:            /**
1950:             * Extracts a portion of this string builder as a string.
1951:             * 
1952:             * @param start  the start index, inclusive, must be valid
1953:             * @return the new string
1954:             * @throws IndexOutOfBoundsException if the index is invalid
1955:             */
1956:            public String substring(int start) {
1957:                return substring(start, size);
1958:            }
1959:
1960:            /**
1961:             * Extracts a portion of this string builder as a string.
1962:             * <p>
1963:             * Note: This method treats an endIndex greater than the length of the
1964:             * builder as equal to the length of the builder, and continues
1965:             * without error, unlike StringBuffer or String.
1966:             * 
1967:             * @param startIndex  the start index, inclusive, must be valid
1968:             * @param endIndex  the end index, exclusive, must be valid except
1969:             *  that if too large it is treated as end of string
1970:             * @return the new string
1971:             * @throws IndexOutOfBoundsException if the index is invalid
1972:             */
1973:            public String substring(int startIndex, int endIndex) {
1974:                endIndex = validateRange(startIndex, endIndex);
1975:                return new String(buffer, startIndex, endIndex - startIndex);
1976:            }
1977:
1978:            /**
1979:             * Extracts the leftmost characters from the string builder without
1980:             * throwing an exception.
1981:             * <p>
1982:             * This method extracts the left <code>length</code> characters from
1983:             * the builder. If this many characters are not available, the whole
1984:             * builder is returned. Thus the returned string may be shorter than the
1985:             * length requested.
1986:             * 
1987:             * @param length  the number of characters to extract, negative returns empty string
1988:             * @return the new string
1989:             */
1990:            public String leftString(int length) {
1991:                if (length <= 0) {
1992:                    return "";
1993:                } else if (length >= size) {
1994:                    return new String(buffer, 0, size);
1995:                } else {
1996:                    return new String(buffer, 0, length);
1997:                }
1998:            }
1999:
2000:            /**
2001:             * Extracts the rightmost characters from the string builder without
2002:             * throwing an exception.
2003:             * <p>
2004:             * This method extracts the right <code>length</code> characters from
2005:             * the builder. If this many characters are not available, the whole
2006:             * builder is returned. Thus the returned string may be shorter than the
2007:             * length requested.
2008:             * 
2009:             * @param length  the number of characters to extract, negative returns empty string
2010:             * @return the new string
2011:             */
2012:            public String rightString(int length) {
2013:                if (length <= 0) {
2014:                    return "";
2015:                } else if (length >= size) {
2016:                    return new String(buffer, 0, size);
2017:                } else {
2018:                    return new String(buffer, size - length, length);
2019:                }
2020:            }
2021:
2022:            /**
2023:             * Extracts some characters from the middle of the string builder without
2024:             * throwing an exception.
2025:             * <p>
2026:             * This method extracts <code>length</code> characters from the builder
2027:             * at the specified index.
2028:             * If the index is negative it is treated as zero.
2029:             * If the index is greater than the builder size, it is treated as the builder size.
2030:             * If the length is negative, the empty string is returned.
2031:             * If insufficient characters are available in the builder, as much as possible is returned.
2032:             * Thus the returned string may be shorter than the length requested.
2033:             * 
2034:             * @param index  the index to start at, negative means zero
2035:             * @param length  the number of characters to extract, negative returns empty string
2036:             * @return the new string
2037:             */
2038:            public String midString(int index, int length) {
2039:                if (index < 0) {
2040:                    index = 0;
2041:                }
2042:                if (length <= 0 || index >= size) {
2043:                    return "";
2044:                }
2045:                if (size <= index + length) {
2046:                    return new String(buffer, index, size - index);
2047:                } else {
2048:                    return new String(buffer, index, length);
2049:                }
2050:            }
2051:
2052:            //-----------------------------------------------------------------------
2053:            /**
2054:             * Checks if the string builder contains the specified char.
2055:             *
2056:             * @param ch  the character to find
2057:             * @return true if the builder contains the character
2058:             */
2059:            public boolean contains(char ch) {
2060:                char[] this Buf = buffer;
2061:                for (int i = 0; i < this .size; i++) {
2062:                    if (this Buf[i] == ch) {
2063:                        return true;
2064:                    }
2065:                }
2066:                return false;
2067:            }
2068:
2069:            /**
2070:             * Checks if the string builder contains the specified string.
2071:             *
2072:             * @param str  the string to find
2073:             * @return true if the builder contains the string
2074:             */
2075:            public boolean contains(String str) {
2076:                return indexOf(str, 0) >= 0;
2077:            }
2078:
2079:            /**
2080:             * Checks if the string builder contains a string matched using the
2081:             * specified matcher.
2082:             * <p>
2083:             * Matchers can be used to perform advanced searching behaviour.
2084:             * For example you could write a matcher to search for the character
2085:             * 'a' followed by a number.
2086:             *
2087:             * @param matcher  the matcher to use, null returns -1
2088:             * @return true if the matcher finds a match in the builder
2089:             */
2090:            public boolean contains(StrMatcher matcher) {
2091:                return indexOf(matcher, 0) >= 0;
2092:            }
2093:
2094:            //-----------------------------------------------------------------------
2095:            /**
2096:             * Searches the string builder to find the first reference to the specified char.
2097:             * 
2098:             * @param ch  the character to find
2099:             * @return the first index of the character, or -1 if not found
2100:             */
2101:            public int indexOf(char ch) {
2102:                return indexOf(ch, 0);
2103:            }
2104:
2105:            /**
2106:             * Searches the string builder to find the first reference to the specified char.
2107:             * 
2108:             * @param ch  the character to find
2109:             * @param startIndex  the index to start at, invalid index rounded to edge
2110:             * @return the first index of the character, or -1 if not found
2111:             */
2112:            public int indexOf(char ch, int startIndex) {
2113:                startIndex = (startIndex < 0 ? 0 : startIndex);
2114:                if (startIndex >= size) {
2115:                    return -1;
2116:                }
2117:                char[] this Buf = buffer;
2118:                for (int i = startIndex; i < size; i++) {
2119:                    if (this Buf[i] == ch) {
2120:                        return i;
2121:                    }
2122:                }
2123:                return -1;
2124:            }
2125:
2126:            /**
2127:             * Searches the string builder to find the first reference to the specified string.
2128:             * <p>
2129:             * Note that a null input string will return -1, whereas the JDK throws an exception.
2130:             * 
2131:             * @param str  the string to find, null returns -1
2132:             * @return the first index of the string, or -1 if not found
2133:             */
2134:            public int indexOf(String str) {
2135:                return indexOf(str, 0);
2136:            }
2137:
2138:            /**
2139:             * Searches the string builder to find the first reference to the specified
2140:             * string starting searching from the given index.
2141:             * <p>
2142:             * Note that a null input string will return -1, whereas the JDK throws an exception.
2143:             * 
2144:             * @param str  the string to find, null returns -1
2145:             * @param startIndex  the index to start at, invalid index rounded to edge
2146:             * @return the first index of the string, or -1 if not found
2147:             */
2148:            public int indexOf(String str, int startIndex) {
2149:                startIndex = (startIndex < 0 ? 0 : startIndex);
2150:                if (str == null || startIndex >= size) {
2151:                    return -1;
2152:                }
2153:                int strLen = str.length();
2154:                if (strLen == 1) {
2155:                    return indexOf(str.charAt(0), startIndex);
2156:                }
2157:                if (strLen == 0) {
2158:                    return startIndex;
2159:                }
2160:                if (strLen > size) {
2161:                    return -1;
2162:                }
2163:                char[] this Buf = buffer;
2164:                int len = size - strLen + 1;
2165:                outer: for (int i = startIndex; i < len; i++) {
2166:                    for (int j = 0; j < strLen; j++) {
2167:                        if (str.charAt(j) != this Buf[i + j]) {
2168:                            continue outer;
2169:                        }
2170:                    }
2171:                    return i;
2172:                }
2173:                return -1;
2174:            }
2175:
2176:            /**
2177:             * Searches the string builder using the matcher to find the first match.
2178:             * <p>
2179:             * Matchers can be used to perform advanced searching behaviour.
2180:             * For example you could write a matcher to find the character 'a'
2181:             * followed by a number.
2182:             *
2183:             * @param matcher  the matcher to use, null returns -1
2184:             * @return the first index matched, or -1 if not found
2185:             */
2186:            public int indexOf(StrMatcher matcher) {
2187:                return indexOf(matcher, 0);
2188:            }
2189:
2190:            /**
2191:             * Searches the string builder using the matcher to find the first
2192:             * match searching from the given index.
2193:             * <p>
2194:             * Matchers can be used to perform advanced searching behaviour.
2195:             * For example you could write a matcher to find the character 'a'
2196:             * followed by a number.
2197:             *
2198:             * @param matcher  the matcher to use, null returns -1
2199:             * @param startIndex  the index to start at, invalid index rounded to edge
2200:             * @return the first index matched, or -1 if not found
2201:             */
2202:            public int indexOf(StrMatcher matcher, int startIndex) {
2203:                startIndex = (startIndex < 0 ? 0 : startIndex);
2204:                if (matcher == null || startIndex >= size) {
2205:                    return -1;
2206:                }
2207:                int len = size;
2208:                char[] buf = buffer;
2209:                for (int i = startIndex; i < len; i++) {
2210:                    if (matcher.isMatch(buf, i, startIndex, len) > 0) {
2211:                        return i;
2212:                    }
2213:                }
2214:                return -1;
2215:            }
2216:
2217:            //-----------------------------------------------------------------------
2218:            /**
2219:             * Searches the string builder to find the last reference to the specified char.
2220:             * 
2221:             * @param ch  the character to find
2222:             * @return the last index of the character, or -1 if not found
2223:             */
2224:            public int lastIndexOf(char ch) {
2225:                return lastIndexOf(ch, size - 1);
2226:            }
2227:
2228:            /**
2229:             * Searches the string builder to find the last reference to the specified char.
2230:             * 
2231:             * @param ch  the character to find
2232:             * @param startIndex  the index to start at, invalid index rounded to edge
2233:             * @return the last index of the character, or -1 if not found
2234:             */
2235:            public int lastIndexOf(char ch, int startIndex) {
2236:                startIndex = (startIndex >= size ? size - 1 : startIndex);
2237:                if (startIndex < 0) {
2238:                    return -1;
2239:                }
2240:                for (int i = startIndex; i >= 0; i--) {
2241:                    if (buffer[i] == ch) {
2242:                        return i;
2243:                    }
2244:                }
2245:                return -1;
2246:            }
2247:
2248:            /**
2249:             * Searches the string builder to find the last reference to the specified string.
2250:             * <p>
2251:             * Note that a null input string will return -1, whereas the JDK throws an exception.
2252:             * 
2253:             * @param str  the string to find, null returns -1
2254:             * @return the last index of the string, or -1 if not found
2255:             */
2256:            public int lastIndexOf(String str) {
2257:                return lastIndexOf(str, size - 1);
2258:            }
2259:
2260:            /**
2261:             * Searches the string builder to find the last reference to the specified
2262:             * string starting searching from the given index.
2263:             * <p>
2264:             * Note that a null input string will return -1, whereas the JDK throws an exception.
2265:             * 
2266:             * @param str  the string to find, null returns -1
2267:             * @param startIndex  the index to start at, invalid index rounded to edge
2268:             * @return the last index of the string, or -1 if not found
2269:             */
2270:            public int lastIndexOf(String str, int startIndex) {
2271:                startIndex = (startIndex >= size ? size - 1 : startIndex);
2272:                if (str == null || startIndex < 0) {
2273:                    return -1;
2274:                }
2275:                int strLen = str.length();
2276:                if (strLen > 0 && strLen <= size) {
2277:                    if (strLen == 1) {
2278:                        return lastIndexOf(str.charAt(0), startIndex);
2279:                    }
2280:
2281:                    outer: for (int i = startIndex - strLen + 1; i >= 0; i--) {
2282:                        for (int j = 0; j < strLen; j++) {
2283:                            if (str.charAt(j) != buffer[i + j]) {
2284:                                continue outer;
2285:                            }
2286:                        }
2287:                        return i;
2288:                    }
2289:
2290:                } else if (strLen == 0) {
2291:                    return startIndex;
2292:                }
2293:                return -1;
2294:            }
2295:
2296:            /**
2297:             * Searches the string builder using the matcher to find the last match.
2298:             * <p>
2299:             * Matchers can be used to perform advanced searching behaviour.
2300:             * For example you could write a matcher to find the character 'a'
2301:             * followed by a number.
2302:             *
2303:             * @param matcher  the matcher to use, null returns -1
2304:             * @return the last index matched, or -1 if not found
2305:             */
2306:            public int lastIndexOf(StrMatcher matcher) {
2307:                return lastIndexOf(matcher, size);
2308:            }
2309:
2310:            /**
2311:             * Searches the string builder using the matcher to find the last
2312:             * match searching from the given index.
2313:             * <p>
2314:             * Matchers can be used to perform advanced searching behaviour.
2315:             * For example you could write a matcher to find the character 'a'
2316:             * followed by a number.
2317:             *
2318:             * @param matcher  the matcher to use, null returns -1
2319:             * @param startIndex  the index to start at, invalid index rounded to edge
2320:             * @return the last index matched, or -1 if not found
2321:             */
2322:            public int lastIndexOf(StrMatcher matcher, int startIndex) {
2323:                startIndex = (startIndex >= size ? size - 1 : startIndex);
2324:                if (matcher == null || startIndex < 0) {
2325:                    return -1;
2326:                }
2327:                char[] buf = buffer;
2328:                int endIndex = startIndex + 1;
2329:                for (int i = startIndex; i >= 0; i--) {
2330:                    if (matcher.isMatch(buf, i, 0, endIndex) > 0) {
2331:                        return i;
2332:                    }
2333:                }
2334:                return -1;
2335:            }
2336:
2337:            //-----------------------------------------------------------------------
2338:            /**
2339:             * Creates a tokenizer that can tokenize the contents of this builder.
2340:             * <p>
2341:             * This method allows the contents of this builder to be tokenized.
2342:             * The tokenizer will be setup by default to tokenize on space, tab,
2343:             * newline and formfeed (as per StringTokenizer). These values can be
2344:             * changed on the tokenizer class, before retrieving the tokens.
2345:             * <p>
2346:             * The returned tokenizer is linked to this builder. You may intermix
2347:             * calls to the buider and tokenizer within certain limits, however
2348:             * there is no synchronization. Once the tokenizer has been used once,
2349:             * it must be {@link StrTokenizer#reset() reset} to pickup the latest
2350:             * changes in the builder. For example:
2351:             * <pre>
2352:             * StrBuilder b = new StrBuilder();
2353:             * b.append("a b ");
2354:             * StrTokenizer t = b.asTokenizer();
2355:             * String[] tokens1 = t.getTokenArray();  // returns a,b
2356:             * b.append("c d ");
2357:             * String[] tokens2 = t.getTokenArray();  // returns a,b (c and d ignored)
2358:             * t.reset();              // reset causes builder changes to be picked up
2359:             * String[] tokens3 = t.getTokenArray();  // returns a,b,c,d
2360:             * </pre>
2361:             * In addition to simply intermixing appends and tokenization, you can also
2362:             * call the set methods on the tokenizer to alter how it tokenizes. Just
2363:             * remember to call reset when you want to pickup builder changes.
2364:             * <p>
2365:             * Calling {@link StrTokenizer#reset(String)} or {@link StrTokenizer#reset(char[])}
2366:             * with a non-null value will break the link with the builder.
2367:             *
2368:             * @return a tokenizer that is linked to this builder
2369:             */
2370:            public StrTokenizer asTokenizer() {
2371:                return new StrBuilderTokenizer();
2372:            }
2373:
2374:            //-----------------------------------------------------------------------
2375:            /**
2376:             * Gets the contents of this builder as a Reader.
2377:             * <p>
2378:             * This method allows the contents of the builder to be read
2379:             * using any standard method that expects a Reader.
2380:             * <p>
2381:             * To use, simply create a <code>StrBuilder</code>, populate it with
2382:             * data, call <code>asReader</code>, and then read away.
2383:             * <p>
2384:             * The internal character array is shared between the builder and the reader.
2385:             * This allows you to append to the builder after creating the reader,
2386:             * and the changes will be picked up.
2387:             * Note however, that no synchronization occurs, so you must perform
2388:             * all operations with the builder and the reader in one thread.
2389:             * <p>
2390:             * The returned reader supports marking, and ignores the flush method.
2391:             *
2392:             * @return a reader that reads from this builder
2393:             */
2394:            public Reader asReader() {
2395:                return new StrBuilderReader();
2396:            }
2397:
2398:            //-----------------------------------------------------------------------
2399:            /**
2400:             * Gets this builder as a Writer that can be written to.
2401:             * <p>
2402:             * This method allows you to populate the contents of the builder
2403:             * using any standard method that takes a Writer.
2404:             * <p>
2405:             * To use, simply create a <code>StrBuilder</code>,
2406:             * call <code>asWriter</code>, and populate away. The data is available
2407:             * at any time using the methods of the <code>StrBuilder</code>.
2408:             * <p>
2409:             * The internal character array is shared between the builder and the writer.
2410:             * This allows you to intermix calls that append to the builder and
2411:             * write using the writer and the changes will be occur correctly.
2412:             * Note however, that no synchronization occurs, so you must perform
2413:             * all operations with the builder and the writer in one thread.
2414:             * <p>
2415:             * The returned writer ignores the close and flush methods.
2416:             *
2417:             * @return a writer that populates this builder
2418:             */
2419:            public Writer asWriter() {
2420:                return new StrBuilderWriter();
2421:            }
2422:
2423:            //-----------------------------------------------------------------------
2424:            //    /**
2425:            //     * Gets a String version of the string builder by calling the internal
2426:            //     * constructor of String by reflection.
2427:            //     * <p>
2428:            //     * WARNING: You must not use the StrBuilder after calling this method
2429:            //     * as the buffer is now shared with the String object. To ensure this,
2430:            //     * the internal character array is set to null, so you will get
2431:            //     * NullPointerExceptions on all method calls.
2432:            //     *
2433:            //     * @return the builder as a String
2434:            //     */
2435:            //    public String toSharedString() {
2436:            //        try {
2437:            //            Constructor con = String.class.getDeclaredConstructor(
2438:            //                new Class[] {int.class, int.class, char[].class});
2439:            //            con.setAccessible(true);
2440:            //            char[] buffer = buf;
2441:            //            buf = null;
2442:            //            size = -1;
2443:            //            nullText = null;
2444:            //            return (String) con.newInstance(
2445:            //                new Object[] {new Integer(0), new Integer(size), buffer});
2446:            //            
2447:            //        } catch (Exception ex) {
2448:            //            ex.printStackTrace();
2449:            //            throw new UnsupportedOperationException("StrBuilder.toSharedString is unsupported: " + ex.getMessage());
2450:            //        }
2451:            //    }
2452:
2453:            //-----------------------------------------------------------------------
2454:            /**
2455:             * Checks the contents of this builder against another to see if they
2456:             * contain the same character content ignoring case.
2457:             *
2458:             * @param other  the object to check, null returns false
2459:             * @return true if the builders contain the same characters in the same order
2460:             */
2461:            public boolean equalsIgnoreCase(StrBuilder other) {
2462:                if (this  == other) {
2463:                    return true;
2464:                }
2465:                if (this .size != other.size) {
2466:                    return false;
2467:                }
2468:                char this Buf[] = this .buffer;
2469:                char otherBuf[] = other.buffer;
2470:                for (int i = size - 1; i >= 0; i--) {
2471:                    char c1 = this Buf[i];
2472:                    char c2 = otherBuf[i];
2473:                    if (c1 != c2
2474:                            && Character.toUpperCase(c1) != Character
2475:                                    .toUpperCase(c2)) {
2476:                        return false;
2477:                    }
2478:                }
2479:                return true;
2480:            }
2481:
2482:            /**
2483:             * Checks the contents of this builder against another to see if they
2484:             * contain the same character content.
2485:             *
2486:             * @param other  the object to check, null returns false
2487:             * @return true if the builders contain the same characters in the same order
2488:             */
2489:            public boolean equals(StrBuilder other) {
2490:                if (this  == other) {
2491:                    return true;
2492:                }
2493:                if (this .size != other.size) {
2494:                    return false;
2495:                }
2496:                char this Buf[] = this .buffer;
2497:                char otherBuf[] = other.buffer;
2498:                for (int i = size - 1; i >= 0; i--) {
2499:                    if (this Buf[i] != otherBuf[i]) {
2500:                        return false;
2501:                    }
2502:                }
2503:                return true;
2504:            }
2505:
2506:            /**
2507:             * Checks the contents of this builder against another to see if they
2508:             * contain the same character content.
2509:             *
2510:             * @param obj  the object to check, null returns false
2511:             * @return true if the builders contain the same characters in the same order
2512:             */
2513:            public boolean equals(Object obj) {
2514:                if (obj instanceof  StrBuilder) {
2515:                    return equals((StrBuilder) obj);
2516:                }
2517:                return false;
2518:            }
2519:
2520:            /**
2521:             * Gets a suitable hash code for this builder.
2522:             *
2523:             * @return a hash code
2524:             */
2525:            public int hashCode() {
2526:                char buf[] = buffer;
2527:                int hash = 0;
2528:                for (int i = size - 1; i >= 0; i--) {
2529:                    hash = 31 * hash + buf[i];
2530:                }
2531:                return hash;
2532:            }
2533:
2534:            //-----------------------------------------------------------------------
2535:            /**
2536:             * Gets a String version of the string builder, creating a new instance
2537:             * each time the method is called.
2538:             * <p>
2539:             * Note that unlike StringBuffer, the string version returned is
2540:             * independent of the string builder.
2541:             *
2542:             * @return the builder as a String
2543:             */
2544:            public String toString() {
2545:                return new String(buffer, 0, size);
2546:            }
2547:
2548:            /**
2549:             * Gets a StringBuffer version of the string builder, creating a
2550:             * new instance each time the method is called.
2551:             *
2552:             * @return the builder as a StringBuffer
2553:             */
2554:            public StringBuffer toStringBuffer() {
2555:                return new StringBuffer(size).append(buffer, 0, size);
2556:            }
2557:
2558:            //-----------------------------------------------------------------------
2559:            /**
2560:             * Validates parameters defining a range of the builder.
2561:             * 
2562:             * @param startIndex  the start index, inclusive, must be valid
2563:             * @param endIndex  the end index, exclusive, must be valid except
2564:             *  that if too large it is treated as end of string
2565:             * @return the new string
2566:             * @throws IndexOutOfBoundsException if the index is invalid
2567:             */
2568:            protected int validateRange(int startIndex, int endIndex) {
2569:                if (startIndex < 0) {
2570:                    throw new StringIndexOutOfBoundsException(startIndex);
2571:                }
2572:                if (endIndex > size) {
2573:                    endIndex = size;
2574:                }
2575:                if (startIndex > endIndex) {
2576:                    throw new StringIndexOutOfBoundsException("end < start");
2577:                }
2578:                return endIndex;
2579:            }
2580:
2581:            /**
2582:             * Validates parameters defining a single index in the builder.
2583:             * 
2584:             * @param index  the index, must be valid
2585:             * @throws IndexOutOfBoundsException if the index is invalid
2586:             */
2587:            protected void validateIndex(int index) {
2588:                if (index < 0 || index > size) {
2589:                    throw new StringIndexOutOfBoundsException(index);
2590:                }
2591:            }
2592:
2593:            //-----------------------------------------------------------------------
2594:            /**
2595:             * Inner class to allow StrBuilder to operate as a tokenizer.
2596:             */
2597:            class StrBuilderTokenizer extends StrTokenizer {
2598:
2599:                /** {@inheritDoc} */
2600:                StrBuilderTokenizer() {
2601:                    super ();
2602:                }
2603:
2604:                /** {@inheritDoc} */
2605:                protected List tokenize(char[] chars, int offset, int count) {
2606:                    if (chars == null) {
2607:                        return super .tokenize(StrBuilder.this .buffer, 0,
2608:                                StrBuilder.this .size());
2609:                    } else {
2610:                        return super .tokenize(chars, offset, count);
2611:                    }
2612:                }
2613:
2614:                /** {@inheritDoc} */
2615:                public String getContent() {
2616:                    String str = super .getContent();
2617:                    if (str == null) {
2618:                        return StrBuilder.this .toString();
2619:                    } else {
2620:                        return str;
2621:                    }
2622:                }
2623:            }
2624:
2625:            //-----------------------------------------------------------------------
2626:            /**
2627:             * Inner class to allow StrBuilder to operate as a writer.
2628:             */
2629:            class StrBuilderReader extends Reader {
2630:                /** The current stream position. */
2631:                private int pos;
2632:                /** The last mark position. */
2633:                private int mark;
2634:
2635:                /** {@inheritDoc} */
2636:                StrBuilderReader() {
2637:                    super ();
2638:                }
2639:
2640:                /** {@inheritDoc} */
2641:                public void close() {
2642:                    // do nothing
2643:                }
2644:
2645:                /** {@inheritDoc} */
2646:                public int read() {
2647:                    if (ready() == false) {
2648:                        return -1;
2649:                    }
2650:                    return StrBuilder.this .charAt(pos++);
2651:                }
2652:
2653:                /** {@inheritDoc} */
2654:                public int read(char b[], int off, int len) {
2655:                    if (off < 0 || len < 0 || off > b.length
2656:                            || (off + len) > b.length || (off + len) < 0) {
2657:                        throw new IndexOutOfBoundsException();
2658:                    }
2659:                    if (len == 0) {
2660:                        return 0;
2661:                    }
2662:                    if (pos >= StrBuilder.this .size()) {
2663:                        return -1;
2664:                    }
2665:                    if (pos + len > size()) {
2666:                        len = StrBuilder.this .size() - pos;
2667:                    }
2668:                    StrBuilder.this .getChars(pos, pos + len, b, off);
2669:                    pos += len;
2670:                    return len;
2671:                }
2672:
2673:                /** {@inheritDoc} */
2674:                public long skip(long n) {
2675:                    if (pos + n > StrBuilder.this .size()) {
2676:                        n = StrBuilder.this .size() - pos;
2677:                    }
2678:                    if (n < 0) {
2679:                        return 0;
2680:                    }
2681:                    pos += n;
2682:                    return n;
2683:                }
2684:
2685:                /** {@inheritDoc} */
2686:                public boolean ready() {
2687:                    return pos < StrBuilder.this .size();
2688:                }
2689:
2690:                /** {@inheritDoc} */
2691:                public boolean markSupported() {
2692:                    return true;
2693:                }
2694:
2695:                /** {@inheritDoc} */
2696:                public void mark(int readAheadLimit) {
2697:                    mark = pos;
2698:                }
2699:
2700:                /** {@inheritDoc} */
2701:                public void reset() {
2702:                    pos = mark;
2703:                }
2704:            }
2705:
2706:            //-----------------------------------------------------------------------
2707:            /**
2708:             * Inner class to allow StrBuilder to operate as a writer.
2709:             */
2710:            class StrBuilderWriter extends Writer {
2711:
2712:                /** {@inheritDoc} */
2713:                StrBuilderWriter() {
2714:                    super ();
2715:                }
2716:
2717:                /** {@inheritDoc} */
2718:                public void close() {
2719:                    // do nothing
2720:                }
2721:
2722:                /** {@inheritDoc} */
2723:                public void flush() {
2724:                    // do nothing
2725:                }
2726:
2727:                /** {@inheritDoc} */
2728:                public void write(int c) {
2729:                    StrBuilder.this .append((char) c);
2730:                }
2731:
2732:                /** {@inheritDoc} */
2733:                public void write(char[] cbuf) {
2734:                    StrBuilder.this .append(cbuf);
2735:                }
2736:
2737:                /** {@inheritDoc} */
2738:                public void write(char[] cbuf, int off, int len) {
2739:                    StrBuilder.this .append(cbuf, off, len);
2740:                }
2741:
2742:                /** {@inheritDoc} */
2743:                public void write(String str) {
2744:                    StrBuilder.this .append(str);
2745:                }
2746:
2747:                /** {@inheritDoc} */
2748:                public void write(String str, int off, int len) {
2749:                    StrBuilder.this.append(str, off, len);
2750:                }
2751:            }
2752:
2753:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.