Source Code Cross Referenced for Text.java in  » Development » Javolution » javolution » 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 » Development » Javolution » javolution.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
0003:         * Copyright (C) 2005 - Javolution (http://javolution.org/)
0004:         * All rights reserved.
0005:         * 
0006:         * Permission to use, copy, modify, and distribute this software is
0007:         * freely granted, provided that this notice is preserved.
0008:         */
0009:        package javolution.text;
0010:
0011:        import java.io.IOException;
0012:        import java.io.Writer;
0013:
0014:        import j2me.lang.CharSequence;
0015:        import j2me.lang.Comparable;
0016:        import j2me.lang.Number;
0017:        import j2me.lang.ThreadLocal;
0018:        import j2mex.realtime.MemoryArea;
0019:        import javolution.JavolutionError;
0020:        import javolution.context.ObjectFactory;
0021:        import javolution.io.UTF8StreamWriter;
0022:        import javolution.lang.MathLib;
0023:        import javolution.lang.Realtime;
0024:        import javolution.lang.ValueType;
0025:        import javolution.util.FastComparator;
0026:        import javolution.util.FastMap;
0027:        import javolution.xml.XMLSerializable;
0028:
0029:        /**
0030:         * <p> This class represents an immutable character sequence with 
0031:         *     fast {@link #concat concatenation}, {@link #insert insertion} and 
0032:         *     {@link #delete deletion} capabilities (O[Log(n)]) instead of 
0033:         *     O[n] for StringBuffer/StringBuilder).</p>
0034:         * <p> This class has the same methods as 
0035:         *     <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html">
0036:         *     Java String</a> and 
0037:         *     <a href="http://msdn2.microsoft.com/en-us/library/system.string.aspx">
0038:         *     .NET String</a> with the following benefits:<ul>
0039:         *     <li> No need for an intermediate 
0040:         *          {@link StringBuffer}/{@link StringBuilder} in order to manipulate 
0041:         *          textual documents (insertion, deletion or concatenation).</li>
0042:         *     <li> Bug free. They are not plagued by the {@link String#substring} <a
0043:         *          href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4513622">
0044:         *          memory leak bug</a> (when small substrings prevent memory from 
0045:         *          larger string from being garbage collected).</li>
0046:         *     <li> More flexible as they allows for search and comparison with any 
0047:         *          <code>java.lang.String</code> or <code>CharSequence</code>.</li>
0048:         *     <li> Support custom allocation policies (instances allocated on the 
0049:         *          "stack" when executing in a 
0050:         *          {@link javolution.context.StackContext StackContext}).</li>
0051:         *     </ul></p>
0052:         * <p> {@link Text} literals should be explicitely {@link #intern interned}. 
0053:         *     Unlike strings literals and strings-value constant expressions,
0054:         *     interning is not implicit. For example:[code]
0055:         *         final static Text TRUE = Text.intern("true");
0056:         *         final static Text FALSE = Text.intern("false");
0057:         *     [/code]
0058:         *     Interned texts are always allocated in ImmortalMemory (RTSJ VMs).</p>
0059:         * <p> {@link Text} instances can be {@link #println printed out} directly 
0060:         *     (no intermediate <code>String</code> allocated). For example:[code]
0061:         *           FastTable myTable ...;
0062:         *           myTable.toText().println(); // Prints to System.out
0063:         *     [/code]</p>           
0064:         *     
0065:         * <p><i> Implementation Note: To avoid expensive copy operations , 
0066:         *        {@link Text} instances are broken down into smaller immutable 
0067:         *        sequences, they form a minimal-depth binary tree.
0068:         *        The tree is maintained balanced automatically through <a 
0069:         *        href="http://en.wikipedia.org/wiki/Tree_rotation">tree rotations</a>. 
0070:         *        Insertion/deletions are performed in <code>O[Log(n)]</code>
0071:         *        instead of <code>O[n]</code> for 
0072:         *        <code>StringBuffer/StringBuilder</code>.</i></p>
0073:         * 
0074:         * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
0075:         * @author Wilfried Middleton
0076:         * @version 5.1, July 1, 2007
0077:         */
0078:        public final class Text implements  CharSequence, Comparable,
0079:                XMLSerializable, ValueType, Realtime {
0080:
0081:            /**
0082:             * Holds the default size for primitive blocks of characters.
0083:             */
0084:            private static final int BLOCK_SIZE = 1 << 5;
0085:
0086:            /**
0087:             * Holds the mask used to ensure a block boundary cesures.
0088:             */
0089:            private static final int BLOCK_MASK = ~(BLOCK_SIZE - 1);
0090:
0091:            /**
0092:             * Holds the primitive text factory.
0093:             */
0094:
0095:            /**
0096:             * Holds the texts interned in ImmortalMemory
0097:             */
0098:            private static final FastMap INTERN_INSTANCES = new FastMap()
0099:                    .setKeyComparator(FastComparator.LEXICAL);
0100:
0101:            /**
0102:             * Holds the text builder used to create small text instances.
0103:             */
0104:            private static final ThreadLocal TEXT_BUILDER = new ThreadLocal() {
0105:                protected Object initialValue() {
0106:                    return new TextBuilder();
0107:                }
0108:            };
0109:
0110:            /**
0111:             * Holds an empty character sequence.
0112:             */
0113:            public static final Text EMPTY = Text.intern("");
0114:
0115:            /**
0116:             * Holds the raw data (primitive) or <code>null</code> (composite).
0117:             */
0118:            private final char[] _data;
0119:
0120:            /**
0121:             * Holds the total number of characters.
0122:             */
0123:            private int _count;
0124:
0125:            /**
0126:             * Holds the head block of character (composite).
0127:             */
0128:            private Text _head;
0129:
0130:            /**
0131:             * Holds the tail block of character (composite).
0132:             */
0133:            private Text _tail;
0134:
0135:            /**
0136:             * Creates a new text instance.
0137:             * 
0138:             * @param isPrimitive indicates if primitive or composite.
0139:             */
0140:            private Text(boolean isPrimitive) {
0141:                _data = isPrimitive ? new char[BLOCK_SIZE] : null;
0142:            }
0143:
0144:            /**
0145:             * Creates a text holding the characters from the specified <code>String
0146:             * </code>.
0147:             * 
0148:             * @param str the string holding the character content. 
0149:             */
0150:            public Text(String str) {
0151:                this (str.length() <= BLOCK_SIZE);
0152:                _count = str.length();
0153:                if (_data != null) { // Primitive.
0154:                    str.getChars(0, _count, _data, 0);
0155:                } else { // Composite, splits on a block boundary. 
0156:                    int half = ((_count + BLOCK_SIZE) >> 1) & BLOCK_MASK;
0157:                    _head = new Text(str.substring(0, half));
0158:                    _tail = new Text(str.substring(half, _count));
0159:                }
0160:            }
0161:
0162:            /**
0163:             * Returns the text representing the specified object.
0164:             * If the object is an instance of {@link Realtime} 
0165:             * then {@link Realtime#toText()} is returned.
0166:             *
0167:             * @param  obj the object to represent as text.
0168:             * @return the textual representation of the specified object.
0169:             */
0170:            public static Text valueOf(Object obj) {
0171:                if (obj instanceof  Realtime)
0172:                    return ((Realtime) obj).toText();
0173:                if (obj instanceof  Number) // Use faster primitive formatting.
0174:                    return Text.valueOfNumber(obj);
0175:                return Text.valueOf(String.valueOf(obj));
0176:            }
0177:
0178:            private static Text valueOf(String str) {
0179:                return Text.valueOf(str, 0, str.length());
0180:            }
0181:
0182:            private static Text valueOf(String str, int start, int end) {
0183:                int length = end - start;
0184:                if (length <= BLOCK_SIZE) {
0185:                    Text text = newPrimitive(length);
0186:                    str.getChars(start, end, text._data, 0);
0187:                    return text;
0188:                } else { // Splits on a block boundary.
0189:                    int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
0190:                    return newComposite(Text.valueOf(str, start, start + half),
0191:                            Text.valueOf(str, start + half, end));
0192:                }
0193:            }
0194:
0195:            // For Integer, Long, Float and Double use direct formatting.
0196:            private static Text valueOfNumber(Object num) {
0197:                if (num instanceof  Integer)
0198:                    return Text.valueOf(((Integer) num).intValue());
0199:                if (num instanceof  Long)
0200:                    return Text.valueOf(((Long) num).longValue());
0201:                /* @JVM-1.1+@
0202:                 if (num instanceof Float)
0203:                 return Text.valueOf(((Float)num).floatValue());
0204:                 if (num instanceof Double)
0205:                 return Text.valueOf(((Double)num).doubleValue());
0206:                 /**/
0207:                return Text.valueOf(String.valueOf(num));
0208:            }
0209:
0210:            /**
0211:             * Returns the text that contains the characters from the specified 
0212:             * array.
0213:             *
0214:             * @param chars the array source of the characters.
0215:             * @return the corresponding instance.
0216:             */
0217:            public static Text valueOf(char[] chars) {
0218:                return Text.valueOf(chars, 0, chars.length);
0219:            }
0220:
0221:            /**
0222:             * Returns the text that contains the characters from the specified 
0223:             * subarray of characters.
0224:             *
0225:             * @param chars the source of the characters.
0226:             * @param offset the index of the first character in the data soure.
0227:             * @param length the length of the text returned.
0228:             * @return the corresponding instance.
0229:             * @throws IndexOutOfBoundsException if <code>(offset < 0) || 
0230:             *         (length < 0) || ((offset + length) > chars.length)</code>
0231:             */
0232:            public static Text valueOf(char[] chars, int offset, int length) {
0233:                if ((offset < 0) || (length < 0)
0234:                        || ((offset + length) > chars.length))
0235:                    throw new IndexOutOfBoundsException();
0236:                if (length <= BLOCK_SIZE) {
0237:                    Text text = Text.newPrimitive(length);
0238:                    System.arraycopy(chars, offset, text._data, 0, length);
0239:                    return text;
0240:                } else { // Splits on a block boundary.
0241:                    int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
0242:                    return Text.newComposite(Text.valueOf(chars, offset, half),
0243:                            Text.valueOf(chars, offset + half, length - half));
0244:                }
0245:            }
0246:
0247:            /**
0248:             * Converts a text builder to a text instance (optimization for 
0249:             * TextBuilder.toText()).
0250:             * 
0251:             * @param  start the index of the first character inclusive.
0252:             * @param  end the index of the last character exclusive.
0253:             * @return the corresponding text instance.
0254:             */
0255:            static Text valueOf(TextBuilder tb, int start, int end) {
0256:                int length = end - start;
0257:                if (length <= BLOCK_SIZE) {
0258:                    Text text = Text.newPrimitive(length);
0259:                    tb.getChars(start, end, text._data, 0);
0260:                    return text;
0261:                } else { // Splits on a block boundary.
0262:                    int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
0263:                    return Text.newComposite(Text.valueOf(tb, start, start
0264:                            + half), Text.valueOf(tb, start + half, end));
0265:                }
0266:            }
0267:
0268:            /**
0269:             * Returns the text representation of the <code>boolean</code> argument.
0270:             *
0271:             * @param b a <code>boolean</code>.
0272:             * @return if the argument is <code>true</code>, the text 
0273:             *          <code>"true"</code> is returned; otherwise, the text 
0274:             *          <code>"false"</code> is returned.
0275:             */
0276:            public static Text valueOf(boolean b) {
0277:                return b ? TRUE : FALSE;
0278:            }
0279:
0280:            private static final Text TRUE = Text.intern("true");
0281:
0282:            private static final Text FALSE = Text.intern("false");
0283:
0284:            /**
0285:             * Returns the text instance corresponding to the specified character. 
0286:             *
0287:             * @param c a character.
0288:             * @return a text of length <code>1</code> containing <code>'c'</code>.
0289:             */
0290:            public static Text valueOf(char c) {
0291:                Text text = Text.newPrimitive(1);
0292:                text._data[0] = c;
0293:                return text;
0294:            }
0295:
0296:            /**
0297:             * Returns the decimal representation of the specified <code>int</code>
0298:             * argument.
0299:             *
0300:             * @param  i the <code>int</code> to format.
0301:             * @return the corresponding text instance.
0302:             */
0303:            public static Text valueOf(int i) {
0304:                TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0305:                tmp.clear().append(i);
0306:                return tmp.toText();
0307:            }
0308:
0309:            /**
0310:             * Returns the radix representation of the specified <code>int</code>
0311:             * argument.
0312:             *
0313:             * @param  i the <code>int</code> to format.
0314:             * @param  radix the radix (e.g. <code>16</code> for hexadecimal).
0315:             * @return the corresponding text instance.
0316:             */
0317:            public static Text valueOf(int i, int radix) {
0318:                TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0319:                tmp.clear().append(i, radix);
0320:                return tmp.toText();
0321:            }
0322:
0323:            /**
0324:             * Returns the decimal representation of the specified <code>long</code>
0325:             * argument.
0326:             *
0327:             * @param  l the <code>long</code> to format.
0328:             * @return the corresponding text instance.
0329:             */
0330:            public static Text valueOf(long l) {
0331:                TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0332:                tmp.clear().append(l);
0333:                return tmp.toText();
0334:            }
0335:
0336:            /**
0337:             * Returns the radix representation of the specified <code>long</code>
0338:             * argument.
0339:             *
0340:             * @param  l the <code>long</code> to format.
0341:             * @param  radix the radix (e.g. <code>16</code> for hexadecimal).
0342:             * @return the corresponding text instance.
0343:             */
0344:            public static Text valueOf(long l, int radix) {
0345:                TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0346:                tmp.clear().append(l, radix);
0347:                return tmp.toText();
0348:            }
0349:
0350:            /**
0351:             * Returns the textual representation of the specified <code>float</code>
0352:             * instance.
0353:             *
0354:             * @param  f the <code>float</code> to format.
0355:             * @return the corresponding text instance.
0356:             /*@JVM-1.1+@
0357:             public static Text valueOf(float f) {
0358:             TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0359:             tmp.clear().append(f);
0360:             return tmp.toText();
0361:             }
0362:             /**/
0363:
0364:            /**
0365:             * Returns the textual representation of the specified <code>double</code>
0366:             * argument.
0367:             *
0368:             * @param  d the <code>double</code> to format.
0369:             * @return the corresponding text instance.
0370:             /*@JVM-1.1+@
0371:             public static Text valueOf(double d) {
0372:             TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0373:             tmp.clear().append(d);
0374:             return tmp.toText();
0375:             }
0376:             /**/
0377:
0378:            /**
0379:             * Returns the textual representation of the specified <code>double</code>
0380:             * argument formatted as specified.
0381:             *
0382:             * @param  d the <code>double</code> to format.
0383:             * @param  digits the number of significative digits (excludes exponent) or
0384:             *         <code>-1</code> to mimic the standard library (16 or 17 digits).
0385:             * @param  scientific <code>true</code> to forces the use of the scientific 
0386:             *         notation (e.g. <code>1.23E3</code>); <code>false</code> 
0387:             *         otherwise. 
0388:             * @param  showZero <code>true</code> if trailing fractional zeros are 
0389:             *         represented; <code>false</code> otherwise.
0390:             * @return the corresponding text instance.
0391:             * @throws IllegalArgumentException if <code>(digits &gt; 19)</code>)
0392:             /*@JVM-1.1+@
0393:             public static Text valueOf(double d, int digits,
0394:             boolean scientific, boolean showZero) {
0395:             TextBuilder tmp = (TextBuilder) TEXT_BUILDER.get();
0396:             tmp.clear().append(d, digits, scientific, showZero);
0397:             return tmp.toText();
0398:             }
0399:             /**/
0400:
0401:            /**
0402:             * Returns the length of this text.
0403:             *
0404:             * @return the number of characters (16-bits Unicode) composing this text.
0405:             */
0406:            public int length() {
0407:                return _count;
0408:            }
0409:
0410:            /**
0411:             * Returns the concatenation of this text and the textual 
0412:             * representation of the specified object.
0413:             * 
0414:             * @param  obj the object whose textual representation is appended.
0415:             * @return <code>this.concat(Text.valueOf(obj))</code>
0416:             */
0417:            public Text plus(Object obj) {
0418:                return this .concat(Text.valueOf(obj));
0419:            }
0420:
0421:            /**
0422:             * Concatenates the specified text to the end of this text. 
0423:             * This method is very fast (faster even than 
0424:             * <code>StringBuffer.append(String)</code>) and still returns
0425:             * a text instance with an internal binary tree of minimal depth!
0426:             *
0427:             * @param  that the text that is concatenated.
0428:             * @return <code>this + that</code>
0429:             */
0430:            public Text concat(Text that) {
0431:                // All Text instances are maintained balanced:
0432:                //   (head < tail * 2) & (tail < head * 2)
0433:
0434:                final int length = this ._count + that._count;
0435:                if (length <= BLOCK_SIZE) { // Merges to primitive.
0436:                    Text text = Text.newPrimitive(length);
0437:                    this .getChars(0, this ._count, text._data, 0);
0438:                    that.getChars(0, that._count, text._data, this ._count);
0439:                    return text;
0440:
0441:                } else { // Returns a composite.
0442:                    Text head = this ;
0443:                    Text tail = that;
0444:                    if (((head._count << 1) < tail._count)
0445:                            && (tail._data == null)) { // tail is composite
0446:                        // head too small, returns (head + tail/2) + (tail/2) 
0447:                        if (tail._head._count > tail._tail._count) {
0448:                            // Rotates to concatenate with smaller part.
0449:                            tail = tail.rightRotation();
0450:                        }
0451:                        head = head.concat(tail._head);
0452:                        tail = tail._tail;
0453:
0454:                    } else if (((tail._count << 1) < head._count)
0455:                            && (head._data == null)) { // head is composite.
0456:                        // tail too small, returns (head/2) + (head/2 concat tail)
0457:                        if (head._tail._count > head._head._count) {
0458:                            // Rotates to concatenate with smaller part.
0459:                            head = head.leftRotation();
0460:                        }
0461:                        tail = head._tail.concat(tail);
0462:                        head = head._head;
0463:                    }
0464:                    return Text.newComposite(head, tail);
0465:                }
0466:            }
0467:
0468:            private Text rightRotation() {
0469:                // See: http://en.wikipedia.org/wiki/Tree_rotation
0470:                Text P = this ._head;
0471:                if (P._data != null)
0472:                    return this ; // Head not a composite, cannot rotate.
0473:                Text A = P._head;
0474:                Text B = P._tail;
0475:                Text C = this ._tail;
0476:                return Text.newComposite(A, Text.newComposite(B, C));
0477:            }
0478:
0479:            private Text leftRotation() {
0480:                // See: http://en.wikipedia.org/wiki/Tree_rotation
0481:                Text Q = this ._tail;
0482:                if (Q._data != null)
0483:                    return this ; // Tail not a composite, cannot rotate.
0484:                Text B = Q._head;
0485:                Text C = Q._tail;
0486:                Text A = this ._head;
0487:                return Text.newComposite(Text.newComposite(A, B), C);
0488:            }
0489:
0490:            /**
0491:             * Returns a portion of this text.
0492:             * 
0493:             * @param  start the index of the first character inclusive.
0494:             * @return the sub-text starting at the specified position.
0495:             * @throws IndexOutOfBoundsException if <code>(start < 0) || 
0496:             *          (start > this.length())</code>
0497:             */
0498:            public Text subtext(int start) {
0499:                return subtext(start, length());
0500:            }
0501:
0502:            /**
0503:             * Returns the text having the specified text inserted at 
0504:             * the specified location.
0505:             *
0506:             * @param index the insertion position.
0507:             * @param txt the text being inserted.
0508:             * @return <code>subtext(0, index).concat(txt).concat(subtext(index))</code>
0509:             * @throws IndexOutOfBoundsException if <code>(index < 0) ||
0510:             *            (index > this.length())</code>
0511:             */
0512:            public Text insert(int index, Text txt) {
0513:                return subtext(0, index).concat(txt).concat(subtext(index));
0514:            }
0515:
0516:            /**
0517:             * Returns the text without the characters between the specified indexes.
0518:             *
0519:             * @param start the beginning index, inclusive.
0520:             * @param end the ending index, exclusive.
0521:             * @return <code>subtext(0, start).concat(subtext(end))</code>
0522:             * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
0523:             *         (start > end) || (end > this.length()</code>
0524:             */
0525:            public Text delete(int start, int end) {
0526:                if (start > end)
0527:                    throw new IndexOutOfBoundsException();
0528:                return subtext(0, start).concat(subtext(end));
0529:            }
0530:
0531:            /**
0532:             * Replaces each character sequence of this text that matches the specified 
0533:             * target sequence with the specified replacement sequence.
0534:             *
0535:             * @param target the character sequence to be replaced.
0536:             * @param replacement the replacement sequence.
0537:             * @return the resulting text.
0538:             */
0539:            public Text replace(CharSequence target, CharSequence replacement) {
0540:                int i = indexOf(target);
0541:                return (i < 0) ? this  : // No target sequence found.
0542:                        subtext(0, i).concat(Text.valueOf(replacement)).concat(
0543:                                subtext(i + target.length()).replace(target,
0544:                                        replacement));
0545:            }
0546:
0547:            /**
0548:             * Replaces the specified characters in this text with the specified 
0549:             * replacement sequence.
0550:             *
0551:             * @param charSet the set of characters to be replaced.
0552:             * @param replacement the replacement sequence.
0553:             * @return the resulting text.
0554:             */
0555:            public Text replace(CharSet charSet, CharSequence replacement) {
0556:                int i = indexOfAny(charSet);
0557:                return (i < 0) ? this  : // No character to replace.
0558:                        subtext(0, i).concat(Text.valueOf(replacement)).concat(
0559:                                subtext(i + 1).replace(charSet, replacement));
0560:            }
0561:
0562:            /**
0563:             * Returns {@link #subtext(int, int) subtext(start, end)}.
0564:             *
0565:             * @param  start the index of the first character inclusive.
0566:             * @param  end the index of the last character exclusive.
0567:             * @return <code>this.subtext(start, end)</code>
0568:             * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
0569:             *         (start > end) || (end > this.length())</code>
0570:             */
0571:            public CharSequence subSequence(int start, int end) {
0572:                return subtext(start, end);
0573:            }
0574:
0575:            /**
0576:             * Returns the index within this text of the first occurrence
0577:             * of the specified character sequence searching forward.
0578:             *
0579:             * @param  csq a character sequence.
0580:             * @return the index of the first character of the character sequence found;
0581:             *         or <code>-1</code> if the character sequence is not found.
0582:             */
0583:            public int indexOf(CharSequence csq) {
0584:                return indexOf(csq, 0);
0585:            }
0586:
0587:            /**
0588:             * Returns the index within this text of the first occurrence
0589:             * of the specified characters sequence searching forward from
0590:             * the specified index.
0591:             *
0592:             * @param  csq a character sequence.
0593:             * @param  fromIndex the index to start the search from.
0594:             * @return the index in the range
0595:             *         <code>[fromIndex, length() - csq.length()]</code> 
0596:             *         or <code>-1</code> if the character sequence is not found.
0597:             */
0598:            public int indexOf(CharSequence csq, int fromIndex) {
0599:
0600:                // Limit cases.
0601:                final int csqLength = csq.length();
0602:                final int min = Math.max(0, fromIndex);
0603:                final int max = _count - csqLength;
0604:                if (csqLength == 0) {
0605:                    return (min > max) ? -1 : min;
0606:                }
0607:
0608:                // Searches for csq.
0609:                final char c = csq.charAt(0);
0610:                for (int i = indexOf(c, min); (i >= 0) && (i <= max); i = indexOf(
0611:                        c, ++i)) {
0612:                    boolean match = true;
0613:                    for (int j = 1; j < csqLength; j++) {
0614:                        if (this .charAt(i + j) != csq.charAt(j)) {
0615:                            match = false;
0616:                            break;
0617:                        }
0618:                    }
0619:                    if (match) {
0620:                        return i;
0621:                    }
0622:                }
0623:                return -1;
0624:            }
0625:
0626:            /**
0627:             * Returns the index within this text of the last occurrence of
0628:             * the specified characters sequence searching backward.
0629:             *
0630:             * @param  csq a character sequence.
0631:             * @return the index of the first character of the character sequence found;
0632:             *         or <code>-1</code> if the character sequence is not found.
0633:             */
0634:            public int lastIndexOf(CharSequence csq) {
0635:                return lastIndexOf(csq, _count);
0636:            }
0637:
0638:            /**
0639:             * Returns the index within this text of the last occurrence of
0640:             * the specified character sequence searching backward from the specified
0641:             * index.
0642:             *
0643:             * @param  csq a character sequence.
0644:             * @param  fromIndex the index to start the backward search from.
0645:             * @return the index in the range <code>[0, fromIndex]</code> or
0646:             *         <code>-1</code> if the character sequence is not found.
0647:             */
0648:            public int lastIndexOf(CharSequence csq, int fromIndex) {
0649:
0650:                // Limit cases.
0651:                final int csqLength = csq.length();
0652:                final int min = 0;
0653:                final int max = Math.min(fromIndex, _count - csqLength);
0654:                if (csqLength == 0) {
0655:                    return (min > max) ? -1 : max;
0656:                }
0657:
0658:                // Searches for csq.
0659:                final char c = csq.charAt(0);
0660:                for (int i = lastIndexOf(c, max); (i >= 0); i = lastIndexOf(c,
0661:                        --i)) {
0662:                    boolean match = true;
0663:                    for (int j = 1; j < csqLength; j++) {
0664:                        if (this .charAt(i + j) != csq.charAt(j)) {
0665:                            match = false;
0666:                            break;
0667:                        }
0668:                    }
0669:                    if (match) {
0670:                        return i;
0671:                    }
0672:                }
0673:                return -1;
0674:
0675:            }
0676:
0677:            /**
0678:             * Indicates if this text starts with the specified prefix.
0679:             *
0680:             * @param  prefix the prefix.
0681:             * @return <code>true</code> if the character sequence represented by the
0682:             *         argument is a prefix of the character sequence represented by
0683:             *         this text; <code>false</code> otherwise.
0684:             */
0685:            public boolean startsWith(CharSequence prefix) {
0686:                return startsWith(prefix, 0);
0687:            }
0688:
0689:            /**
0690:             * Indicates if this text ends with the specified suffix.
0691:             *
0692:             * @param  suffix the suffix.
0693:             * @return <code>true</code> if the character sequence represented by the
0694:             *         argument is a suffix of the character sequence represented by
0695:             *         this text; <code>false</code> otherwise.
0696:             */
0697:            public boolean endsWith(CharSequence suffix) {
0698:                return startsWith(suffix, length() - suffix.length());
0699:            }
0700:
0701:            /**
0702:             * Indicates if this text starts with the specified prefix
0703:             * at the specified index.
0704:             *
0705:             * @param  prefix the prefix.
0706:             * @param  index the index of the prefix location in this string.
0707:             * @return <code>this.substring(index).startsWith(prefix)</code>
0708:             */
0709:            public boolean startsWith(CharSequence prefix, int index) {
0710:                final int prefixLength = prefix.length();
0711:                if ((index >= 0) && (index <= (this .length() - prefixLength))) {
0712:                    for (int i = 0, j = index; i < prefixLength;) {
0713:                        if (prefix.charAt(i++) != this .charAt(j++)) {
0714:                            return false;
0715:                        }
0716:                    }
0717:                    return true;
0718:                } else {
0719:                    return false;
0720:                }
0721:            }
0722:
0723:            /**
0724:             * Returns a copy of this text, with leading and trailing
0725:             * whitespace omitted.
0726:             *
0727:             * @return a copy of this text with leading and trailing white
0728:             *          space removed, or this text if it has no leading or
0729:             *          trailing white space.
0730:             */
0731:            public Text trim() {
0732:                int first = 0; // First character index.
0733:                int last = length() - 1; // Last character index.
0734:                while ((first <= last) && (charAt(first) <= ' ')) {
0735:                    first++;
0736:                }
0737:                while ((last >= first) && (charAt(last) <= ' ')) {
0738:                    last--;
0739:                }
0740:                return subtext(first, last + 1);
0741:            }
0742:
0743:            /**
0744:             * Returns a text equals to the specified character sequence from a pool of
0745:             * unique text instances in <code>ImmortalMemory</code>.  
0746:             * 
0747:             * @return an unique text instance allocated in <code>ImmortalMemory</code>.
0748:             */
0749:            public static Text intern(final CharSequence csq) {
0750:                Text text = (Text) INTERN_INSTANCES.get(csq); // Thread-Safe - No entry removed.
0751:                return (text != null) ? text : Text.internImpl(csq.toString());
0752:            }
0753:
0754:            /**
0755:             * Returns a text equals to the specified string from a pool of
0756:             * unique text instances in <code>ImmortalMemory</code>.  
0757:             * 
0758:             * @return an unique text instance allocated in <code>ImmortalMemory</code>.
0759:             */
0760:            public static Text intern(final String str) {
0761:                Text text = (Text) INTERN_INSTANCES.get(str); // Thread-Safe - No entry removed.
0762:                return (text != null) ? text : Text.internImpl(str);
0763:            }
0764:
0765:            private static synchronized Text internImpl(final String str) {
0766:                if (!INTERN_INSTANCES.containsKey(str)) { // Synchronized check.
0767:                    MemoryArea.getMemoryArea(INTERN_INSTANCES).executeInArea(
0768:                            new Runnable() {
0769:                                public void run() {
0770:                                    Text txt = new Text(str);
0771:                                    INTERN_INSTANCES.put(txt, txt);
0772:                                }
0773:                            });
0774:                }
0775:                return (Text) INTERN_INSTANCES.get(str);
0776:            }
0777:
0778:            /**
0779:             * Indicates if this text has the same character content as the specified
0780:             * character sequence.
0781:             *
0782:             * @param csq the character sequence to compare with.
0783:             * @return <code>true</code> if the specified character sequence has the 
0784:             *        same character content as this text; <code>false</code> otherwise.
0785:             */
0786:            public boolean contentEquals(CharSequence csq) {
0787:                if (csq.length() != _count)
0788:                    return false;
0789:                for (int i = 0; i < _count;) {
0790:                    if (this .charAt(i) != csq.charAt(i++))
0791:                        return false;
0792:                }
0793:                return true;
0794:            }
0795:
0796:            /**
0797:             * Indicates if this text has the same character contend as the specified
0798:             * character sequence ignoring case considerations. 
0799:             *
0800:             * @param  csq the <code>CharSequence</code> to compare this text against.
0801:             * @return <code>true</code> if the argument and this text are equal, 
0802:             *         ignoring case; <code>false</code> otherwise.
0803:             */
0804:            public boolean contentEqualsIgnoreCase(CharSequence csq) {
0805:                if (this ._count != csq.length())
0806:                    return false;
0807:                for (int i = 0; i < _count;) {
0808:                    char u1 = this .charAt(i);
0809:                    char u2 = csq.charAt(i++);
0810:                    if (u1 != u2) {
0811:                        u1 = Character.toUpperCase(u1);
0812:                        u2 = Character.toUpperCase(u2);
0813:                        if ((u1 != u2)
0814:                                && (Character.toLowerCase(u1) != Character
0815:                                        .toLowerCase(u2)))
0816:                            return false;
0817:
0818:                    }
0819:                }
0820:                return true;
0821:            }
0822:
0823:            /**
0824:             * Compares this text against the specified object for equality.
0825:             * Returns <code>true</code> if the specified object is a text having
0826:             * the same character sequence as this text. 
0827:             * For generic comparaison with any character sequence the 
0828:             * {@link #contentEquals(CharSequence)} should be used.
0829:             * 
0830:             * @param  obj the object to compare with or <code>null</code>.
0831:             * @return <code>true</code> if that is a text with the same character
0832:             *         sequence as this text; <code>false</code> otherwise.
0833:             */
0834:            public boolean equals(Object obj) {
0835:                if (this  == obj)
0836:                    return true;
0837:                if (!(obj instanceof  Text))
0838:                    return false;
0839:                final Text that = (Text) obj;
0840:                if (this ._count != that._count)
0841:                    return false;
0842:                for (int i = 0; i < _count;) {
0843:                    if (this .charAt(i) != that.charAt(i++))
0844:                        return false;
0845:                }
0846:                return true;
0847:            }
0848:
0849:            /**
0850:             * Returns the hash code for this text.
0851:             *
0852:             * @return the hash code value.
0853:             */
0854:            public int hashCode() {
0855:                int h = 0;
0856:                final int length = this .length();
0857:                for (int i = 0; i < length;) {
0858:                    h = 31 * h + charAt(i++);
0859:                }
0860:                return h;
0861:            }
0862:
0863:            /**
0864:             * Compares this text to another character sequence or string 
0865:             * lexicographically.
0866:             *
0867:             * @param   csq the character sequence to be compared.
0868:             * @return  <code>TypeFormat.LEXICAL_COMPARATOR.compare(this, csq)</code>
0869:             * @throws  ClassCastException if the specifed object is not a
0870:             *          <code>CharSequence</code> or a <code>String</code>.
0871:             */
0872:            public int compareTo(Object csq) {
0873:                return ((FastComparator) FastComparator.LEXICAL).compare(this ,
0874:                        csq);
0875:            }
0876:
0877:            /**
0878:             * Returns <code>this</code> (implements 
0879:             * {@link javolution.lang.ValueType Realtime} interface).
0880:             *
0881:             * @return <code>this</code>
0882:             */
0883:            public Text toText() {
0884:                return this ;
0885:            }
0886:
0887:            /**
0888:             * Prints out this text to <code>System.out</code> (UTF-8 encoding).
0889:             * This method is equivalent to:[code]
0890:             *     synchronized(OUT) {
0891:             *         print(OUT);
0892:             *         OUT.flush();
0893:             *     }
0894:             *     ...
0895:             *     static final OUT = new UTF8StreamWriter().setOutput(System.out);
0896:             * [/code]
0897:             */
0898:            public void print() {
0899:                try {
0900:                    synchronized (SYSTEM_OUT_WRITER) {
0901:                        print(SYSTEM_OUT_WRITER);
0902:                        SYSTEM_OUT_WRITER.flush();
0903:                    }
0904:                } catch (IOException e) { // Should never happen.
0905:                    throw new JavolutionError(e);
0906:                }
0907:            }
0908:
0909:            private static final UTF8StreamWriter SYSTEM_OUT_WRITER = new UTF8StreamWriter()
0910:                    .setOutput(System.out);
0911:
0912:            /**
0913:             * Prints out this text to <code>System.out</code> and then terminates the
0914:             * line. This method is equivalent to:[code]
0915:             *     synchronized(OUT) {
0916:             *         println(OUT);
0917:             *         OUT.flush();
0918:             *     }
0919:             *     ...
0920:             *     static final OUT = new UTF8StreamWriter().setOutput(System.out);
0921:             * [/code]
0922:             */
0923:            public void println() {
0924:                try {
0925:                    synchronized (SYSTEM_OUT_WRITER) {
0926:                        println(SYSTEM_OUT_WRITER);
0927:                        SYSTEM_OUT_WRITER.flush();
0928:                    }
0929:                } catch (IOException e) { // Should never happen.
0930:                    throw new JavolutionError(e);
0931:                }
0932:            }
0933:
0934:            /**
0935:             * Prints out this text to the specified writer.
0936:             * 
0937:             * @param writer the destination writer.
0938:             */
0939:            public void print(Writer writer) throws IOException {
0940:                if (_data != null) { // Primitive
0941:                    writer.write(_data, 0, _count);
0942:                } else { // Composite.
0943:                    _head.print(writer);
0944:                    _tail.print(writer);
0945:                }
0946:            }
0947:
0948:            /**
0949:             * Prints out this text to the specified writer and then terminates 
0950:             * the line.
0951:             * 
0952:             * @param writer the destination writer.
0953:             */
0954:            public void println(Writer writer) throws IOException {
0955:                print(writer);
0956:                writer.write('\n');
0957:            }
0958:
0959:            /**
0960:             * Converts the characters of this text to lower case.
0961:             * 
0962:             * @return the text in lower case.
0963:             * @see Character#toLowerCase(char) 
0964:             */
0965:            public Text toLowerCase() {
0966:                if (_data == null) // Composite.
0967:                    return Text.newComposite(_head.toLowerCase(), _tail
0968:                            .toLowerCase());
0969:                Text text = Text.newPrimitive(_count);
0970:                for (int i = 0; i < _count;) {
0971:                    text._data[i] = Character.toLowerCase(_data[i++]);
0972:                }
0973:                return text;
0974:            }
0975:
0976:            /**
0977:             * Converts the characters of this text to upper case.
0978:             * 
0979:             * @return the text in lower case.
0980:             * @see Character#toUpperCase(char) 
0981:             */
0982:            public Text toUpperCase() {
0983:                if (_data == null) // Composite.
0984:                    return newComposite(_head.toUpperCase(), _tail
0985:                            .toUpperCase());
0986:                Text text = Text.newPrimitive(_count);
0987:                for (int i = 0; i < _count;) {
0988:                    text._data[i] = Character.toUpperCase(_data[i++]);
0989:                }
0990:                return text;
0991:            }
0992:
0993:            /**
0994:             * Returns the depth of the internal tree used to represent this text.
0995:             *
0996:             * @return the maximum depth of the text internal binary tree.
0997:             */
0998:            public int depth() {
0999:                if (_data != null) // Primitive.
1000:                    return 0;
1001:                return MathLib.max(_head.depth(), _tail.depth()) + 1;
1002:            }
1003:
1004:            /**
1005:             * Returns the character at the specified index.
1006:             *
1007:             * @param  index the index of the character.
1008:             * @return the character at the specified index.
1009:             * @throws IndexOutOfBoundsException if <code>(index < 0) || 
1010:             *         (index >= this.length())</code>
1011:             */
1012:            public char charAt(int index) {
1013:                if (index >= _count)
1014:                    throw new IndexOutOfBoundsException();
1015:                return (_data != null) ? _data[index]
1016:                        : (index < _head._count) ? _head.charAt(index) : _tail
1017:                                .charAt(index - _head._count);
1018:            }
1019:
1020:            /**
1021:             * Returns the index within this text of the first occurrence of the
1022:             * specified character, starting the search at the specified index.
1023:             *
1024:             * @param c the character to search for.
1025:             * @param fromIndex the index to start the search from.
1026:             * @return the index of the first occurrence of the character in this text
1027:             *         that is greater than or equal to <code>fromIndex</code>, 
1028:             *         or <code>-1</code> if the character does not occur.
1029:             */
1030:            public int indexOf(char c, int fromIndex) {
1031:                if (_data != null) { // Primitive.
1032:                    for (int i = MathLib.max(fromIndex, 0); i < _count; i++) {
1033:                        if (_data[i] == c)
1034:                            return i;
1035:                    }
1036:                    return -1;
1037:                } else { // Composite.
1038:                    final int cesure = _head._count;
1039:                    if (fromIndex < cesure) {
1040:                        final int headIndex = _head.indexOf(c, fromIndex);
1041:                        if (headIndex >= 0)
1042:                            return headIndex; // Found in head.
1043:                    }
1044:                    final int tailIndex = _tail.indexOf(c, fromIndex - cesure);
1045:                    return (tailIndex >= 0) ? tailIndex + cesure : -1;
1046:                }
1047:            }
1048:
1049:            /**
1050:             * Returns the index within this text of the first occurrence of the
1051:             * specified character, searching backward and starting at the specified
1052:             * index.
1053:             *
1054:             * @param c the character to search for.
1055:             * @param fromIndex the index to start the search backward from.
1056:             * @return the index of the first occurrence of the character in this text
1057:             *         that is less than or equal to <code>fromIndex</code>, 
1058:             *         or <code>-1</code> if the character does not occur.
1059:             */
1060:            public int lastIndexOf(char c, int fromIndex) {
1061:                if (_data != null) { // Primitive.
1062:                    for (int i = MathLib.min(fromIndex, _count - 1); i >= 0; i--) {
1063:                        if (_data[i] == c)
1064:                            return i;
1065:                    }
1066:                    return -1;
1067:                } else { // Composite.
1068:                    final int cesure = _head._count;
1069:                    if (fromIndex >= cesure) {
1070:                        final int tailIndex = _tail.lastIndexOf(c, fromIndex
1071:                                - cesure);
1072:                        if (tailIndex >= 0)
1073:                            return tailIndex + cesure; // Found in tail.
1074:                    }
1075:                    return _head.lastIndexOf(c, fromIndex);
1076:                }
1077:            }
1078:
1079:            /**
1080:             * Returns a portion of this text.
1081:             *
1082:             * @param  start the index of the first character inclusive.
1083:             * @param  end the index of the last character exclusive.
1084:             * @return the sub-text starting at the specified start position and 
1085:             *         ending just before the specified end position.
1086:             * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
1087:             *         (start > end) || (end > this.length())</code>
1088:             */
1089:            public Text subtext(int start, int end) {
1090:                if (_data != null) { // Primitive.
1091:                    if ((start < 0) || (start > end) || (end > _count))
1092:                        throw new IndexOutOfBoundsException();
1093:                    if ((start == 0) && (end == _count))
1094:                        return this ;
1095:                    if (start == end)
1096:                        return Text.EMPTY;
1097:                    int length = end - start;
1098:                    Text text = Text.newPrimitive(length);
1099:                    System.arraycopy(_data, start, text._data, 0, length);
1100:                    return text;
1101:                } else { // Composite.
1102:                    final int cesure = _head._count;
1103:                    if (end <= cesure)
1104:                        return _head.subtext(start, end);
1105:                    if (start >= cesure)
1106:                        return _tail.subtext(start - cesure, end - cesure);
1107:                    if ((start == 0) && (end == _count))
1108:                        return this ;
1109:                    // Overlaps head and tail.
1110:                    return _head.subtext(start, cesure).concat(
1111:                            _tail.subtext(0, end - cesure));
1112:                }
1113:            }
1114:
1115:            /**
1116:             * Copies the characters from this text into the destination
1117:             * character array.
1118:             *
1119:             * @param start the index of the first character to copy.
1120:             * @param end the index after the last character to copy.
1121:             * @param dest the destination array.
1122:             * @param destPos the start offset in the destination array.
1123:             * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
1124:             *         (start > end) || (end > this.length())</code>
1125:             */
1126:            public void getChars(int start, int end, char dest[], int destPos) {
1127:                if (_data != null) { // Primitive.
1128:                    if ((start < 0) || (end > _count) || (start > end))
1129:                        throw new IndexOutOfBoundsException();
1130:                    System.arraycopy(_data, start, dest, destPos, end - start);
1131:                } else { // Composite.
1132:                    final int cesure = _head._count;
1133:                    if (end <= cesure) {
1134:                        _head.getChars(start, end, dest, destPos);
1135:                    } else if (start >= cesure) {
1136:                        _tail.getChars(start - cesure, end - cesure, dest,
1137:                                destPos);
1138:                    } else { // Overlaps head and tail.
1139:                        _head.getChars(start, cesure, dest, destPos);
1140:                        _tail.getChars(0, end - cesure, dest, destPos + cesure
1141:                                - start);
1142:                    }
1143:                }
1144:            }
1145:
1146:            /**
1147:             * Returns the <code>String</code> representation of this text.
1148:             *
1149:             * @return the <code>java.lang.String</code> for this text.
1150:             */
1151:            public String toString() {
1152:                if (_data != null) { // Primitive.
1153:                    return new String(_data, 0, _count);
1154:                } else { // Composite.
1155:                    char[] data = new char[_count];
1156:                    this .getChars(0, _count, data, 0);
1157:                    return new String(data, 0, _count);
1158:                }
1159:            }
1160:
1161:            // Implements ValueType interface.
1162:            public Object/*{Text}*/copy() {
1163:                if (_data != null) { // Primitive.
1164:                    Text text = Text.newPrimitive(_count);
1165:                    System.arraycopy(_data, 0, text._data, 0, _count);
1166:                    return text;
1167:                } else { // Composite.
1168:                    return Text.newComposite((Text) _head.copy(), (Text) _tail
1169:                            .copy());
1170:                }
1171:            }
1172:
1173:            //////////////////////////////////////////////////////////////////
1174:            // Wilfried add-ons (methods provided by Microsoft .Net in C#)
1175:            //
1176:
1177:            /**
1178:             * Returns the text that contains a specific length sequence of the
1179:             * character specified.
1180:             *
1181:             * @param c the character to fill this text with.
1182:             * @param length the length of the text returned.
1183:             * @return the corresponding instance.
1184:             * @throws IndexOutOfBoundsException if <code>(length < 0)</code>
1185:             */
1186:            public static Text valueOf(char c, int length) {
1187:                if (length < 0)
1188:                    throw new IndexOutOfBoundsException();
1189:                if (length <= BLOCK_SIZE) {
1190:                    Text text = Text.newPrimitive(length);
1191:                    for (int i = 0; i < length;) {
1192:                        text._data[i++] = c;
1193:                    }
1194:                    return text;
1195:                } else {
1196:                    final int middle = (length >> 1);
1197:                    return Text.newComposite(Text.valueOf(c, middle), Text
1198:                            .valueOf(c, length - middle));
1199:                }
1200:            }
1201:
1202:            /**
1203:             * Indicates if all characters of this text are whitespaces
1204:             * (no characters greater than the space character).
1205:             *
1206:             *@return <code>true</code> if this text  contains only whitespace.
1207:             */
1208:            public boolean isBlank() {
1209:                return isBlank(0, length());
1210:            }
1211:
1212:            /**
1213:             * Indicates if the specified sub-range of characters of this text
1214:             * are whitespaces (no characters greater than the space character).
1215:             *
1216:             *@param start the start index.
1217:             *@param length the number of characters to inspect.
1218:             */
1219:            public boolean isBlank(int start, int length) {
1220:                for (; start < length; start++) {
1221:                    if (charAt(start) > ' ')
1222:                        return false;
1223:                }
1224:                return true;
1225:            }
1226:
1227:            /**
1228:             * Returns a copy of this text, with leading whitespace omitted.
1229:             *
1230:             * @return a copy of this text with leading white space removed,
1231:             * or this text if it has no leading white space.
1232:             */
1233:            public Text trimStart() {
1234:                int first = 0; // First character index.
1235:                int last = length() - 1; // Last character index.
1236:                while ((first <= last) && (charAt(first) <= ' ')) {
1237:                    first++;
1238:                }
1239:                return subtext(first, last + 1);
1240:            }
1241:
1242:            /**
1243:             * Returns a copy of this text, with trailing
1244:             * whitespace omitted.
1245:             *
1246:             * @return a copy of this text with trailing white space removed,
1247:             * or this text if it has no trailing white space.
1248:             */
1249:            public Text trimEnd() {
1250:                int first = 0; // First character index.
1251:                int last = length() - 1; // Last character index.
1252:                while ((last >= first) && (charAt(last) <= ' ')) {
1253:                    last--;
1254:                }
1255:                return subtext(first, last + 1);
1256:            }
1257:
1258:            /**
1259:             * Pads this text on the left with spaces to make the minimum total length
1260:             * as specified.
1261:             * The new length of the new text is equal to the original length plus
1262:             * <code>(length()-len)</code> spaces.
1263:             *
1264:             * @param len the total number of characters to make this text equal to.
1265:             * @return a new text or the same text if no padding required.
1266:             * @throws an IllegalArgumentException if the <code>(len<0)</code>.
1267:             */
1268:            public Text padLeft(int len) {
1269:                return padLeft(len, ' ');
1270:            }
1271:
1272:            /**
1273:             * Pads this text on the left to make the minimum total length as specified.
1274:             * Spaces or the given Unicode character are used to pad with.
1275:             * <br>
1276:             * The new length of the new text is equal to the original length plus
1277:             * <code>(length()-len)</code> pad characters.
1278:             *
1279:             * @param len the total number of characters to make this text equal to.
1280:             * @param c the character to pad using.
1281:             * @return a new text or the same text if no padding required.
1282:             * @throws an IllegalArgumentException if the <code>(len<0)</code>.
1283:             */
1284:            public Text padLeft(int len, char c) {
1285:                final int padSize = (len <= length()) ? 0 : len - length();
1286:                return insert(0, Text.valueOf(c, padSize));
1287:            }
1288:
1289:            /**
1290:             * Pads this text on the right with spaces to make the minimum total length
1291:             * as specified.
1292:             * The new length of the new text is equal to the original length plus
1293:             * <code>(length()-len)</code> spaces.
1294:             *
1295:             * @param len the total number of characters to make this text equal to.
1296:             * @return a new text or the same text if no padding required.
1297:             * @throws an IllegalArgumentException if the <code>(len<0)</code>.
1298:             */
1299:            public Text padRight(int len) {
1300:                return padRight(len, ' ');
1301:            }
1302:
1303:            /**
1304:             * Pads this text on the right to make the minimum total length as specified.
1305:             * Spaces or the given Unicode character are used to pad with.
1306:             * <br>
1307:             * The new length of the new text is equal to the original length plus
1308:             * <code>(length()-len)</code> pad characters.
1309:             *
1310:             * @param len the total number of characters to make this text equal to.
1311:             * @param c the character to pad using.
1312:             * @return a new text or the same text if no padding required.
1313:             * @throws an IllegalArgumentException if the <code>(len<0)</code>.
1314:             */
1315:            public Text padRight(int len, char c) {
1316:                final int padSize = (len <= length()) ? 0 : len - length();
1317:                return concat(Text.valueOf(c, padSize));
1318:            }
1319:
1320:            /**
1321:             * Returns the index within this text of the first occurrence
1322:             * of any character in the specified character set.
1323:             *
1324:             * @param  charSet the character set.
1325:             * @return the index of the first character that matches one of the
1326:             *         characters in the supplied set; or <code>-1</code> if none.
1327:             */
1328:            public int indexOfAny(CharSet charSet) {
1329:                return indexOfAny(charSet, 0, length());
1330:            }
1331:
1332:            /**
1333:             * Returns the index within a region of this text of the first occurrence
1334:             * of any character in the specified character set.
1335:             *
1336:             * @param charSet the character set.
1337:             * @param start the index of the start of the search region in this text.
1338:             * @return the index of the first character that matches one of the
1339:             *         characters in the supplied set; or <code>-1</code> if none.
1340:             */
1341:            public int indexOfAny(CharSet charSet, int start) {
1342:                return indexOfAny(charSet, start, length() - start);
1343:            }
1344:
1345:            /**
1346:             * Returns the index within a region of this text of the first occurrence
1347:             * of any character in the specified character set.
1348:             *
1349:             * @param charSet the character set.
1350:             * @param start the index of the start of the search region in this text.
1351:             * @param length the length of the region to search.
1352:             * @return the index of the first character that matches one of the
1353:             *         characters in the supplied array; or <code>-1</code> if none.
1354:             */
1355:            public int indexOfAny(CharSet charSet, int start, int length) {
1356:                final int stop = start + length;
1357:                for (int i = start; i < stop; i++) {
1358:                    if (charSet.contains(charAt(i)))
1359:                        return i;
1360:                }
1361:                return -1;
1362:            }
1363:
1364:            /**
1365:             * Returns the index within this text of the last occurrence
1366:             * of any character in the specified character set.
1367:             *
1368:             * @param charSet the character set.
1369:             * @return the index of the last character that matches one of the
1370:             *         characters in the supplied array; or <code>-1</code> if none.
1371:             */
1372:            public int lastIndexOfAny(CharSet charSet) {
1373:                return lastIndexOfAny(charSet, 0, length());
1374:            }
1375:
1376:            /**
1377:             * Returns the index within a region of this text of the last occurrence
1378:             * of any character in the specified character set.
1379:             *
1380:             * @param charSet the character set.
1381:             * @param start the index of the start of the search region in this text.
1382:             * @return the index of the last character that matches one of the
1383:             *         characters in the supplied array; or <code>-1</code> if none.
1384:             */
1385:            public int lastIndexOfAny(CharSet charSet, int start) {
1386:                return lastIndexOfAny(charSet, start, length() - start);
1387:            }
1388:
1389:            /**
1390:             * Returns the index within a region of this text of the last occurrence
1391:             * of any character in the specified character set.
1392:             *
1393:             * @param charSet the character set.
1394:             * @param start the index of the start of the search region in this text.
1395:             * @param length the length of the region to search.
1396:             * @return the index of the last character that matches one of the
1397:             *         characters in the supplied array; or <code>-1</code> if none.
1398:             */
1399:            public int lastIndexOfAny(CharSet charSet, int start, int length) {
1400:                for (int i = start + length; --i >= start;) {
1401:                    if (charSet.contains(charAt(i)))
1402:                        return i;
1403:                }
1404:                return -1;
1405:            }
1406:
1407:            //
1408:            ////////////////////////////////////////////////////////////////////////////
1409:
1410:            /**
1411:             * Returns a {@link javolution.context.AllocatorContext context allocated}
1412:             * primitive text instance.
1413:             *
1414:             * @param length the primitive length.
1415:             */
1416:            private static Text newPrimitive(int length) {
1417:                Text text = (Text) PRIMITIVE_FACTORY.object();
1418:                text._count = length;
1419:                return text;
1420:            }
1421:
1422:            private static final ObjectFactory PRIMITIVE_FACTORY = new ObjectFactory() {
1423:
1424:                public Object create() {
1425:                    return new Text(true);
1426:                }
1427:            };
1428:
1429:            /**
1430:             * Returns a {@link javolution.context.AllocatorContext context allocated}
1431:             * composite text instance.
1432:             *
1433:             * @param head the composite head.
1434:             * @param tail the composite tail.
1435:             */
1436:            private static Text newComposite(Text head, Text tail) {
1437:                Text text = (Text) COMPOSITE_FACTORY.object();
1438:                text._count = head._count + tail._count;
1439:                text._head = head;
1440:                text._tail = tail;
1441:                return text;
1442:            }
1443:
1444:            private static final ObjectFactory COMPOSITE_FACTORY = new ObjectFactory() {
1445:
1446:                public Object create() {
1447:                    return new Text(false);
1448:                }
1449:            };
1450:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.