KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > Analyzer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor;
21
22 import java.io.Reader JavaDoc;
23 import java.io.Writer JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileReader JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Iterator JavaDoc;
29
30 import javax.swing.text.BadLocationException JavaDoc;
31 import javax.swing.text.Segment JavaDoc;
32
33 /**
34 * Various text analyzes over the document
35 *
36 * @author Miloslav Metelka
37 * @version 1.00
38 */

39
40 public class Analyzer {
41
42     /** Platform default line separator */
43     private static Object JavaDoc platformLS;
44
45     /** Empty char array */
46     public static final char[] EMPTY_CHAR_ARRAY = new char[0];
47
48     /** Buffer filled by spaces used for spaces filling and tabs expansion */
49     private static char spacesBuffer[] = new char[] { ' ' };
50
51     /** Buffer filled by tabs used for tabs filling */
52     private static char tabsBuffer[] = new char[] { '\t' };
53
54     /** Cache up to 50 spaces strings */
55     private static final int MAX_CACHED_SPACES_STRING_LENGTH = 50;
56
57     /** Spaces strings cache. */
58     private static final String JavaDoc[] spacesStrings
59         = new String JavaDoc[MAX_CACHED_SPACES_STRING_LENGTH + 1];
60
61     static {
62         spacesStrings[0] = "";
63         spacesStrings[MAX_CACHED_SPACES_STRING_LENGTH]
64             = new String JavaDoc(getSpacesBuffer(MAX_CACHED_SPACES_STRING_LENGTH),
65                 0, MAX_CACHED_SPACES_STRING_LENGTH);
66     }
67
68     private Analyzer() {
69         // no instantiation
70
}
71
72     /** Get platform default line separator */
73     public static Object JavaDoc getPlatformLS() {
74         if (platformLS == null) {
75             platformLS = System.getProperty("line.separator"); // NOI18N
76
}
77         return platformLS;
78     }
79
80     /** Test line separator on given semgment. This implementation simply checks
81     * the first line of file but it can be redefined to do more thorough test.
82     * @param seg segment where analyzes are performed
83     * @return line separator type found in the file
84     */

85     public static String JavaDoc testLS(char chars[], int len) {
86         for (int i = 0; i < len; i++) {
87             switch (chars[i]) {
88             case '\r':
89                 if (i + 1 < len && chars[i + 1] == '\n') {
90                     return BaseDocument.LS_CRLF;
91                 } else {
92                     return BaseDocument.LS_CR;
93                 }
94
95             case '\n':
96                 return BaseDocument.LS_LF;
97             }
98         }
99         return null; // signal unspecified line separator
100
}
101
102     /** Convert text with generic line separators to line feeds (LF).
103     * As the linefeeds are one char long there is no need to allocate
104     * another buffer since the only possibility is that the returned
105     * length will be smaller than previous (if there were some CRLF separators.
106     * @param chars char array with data to convert
107     * @param len valid portion of chars array
108     * @return new valid portion of chars array after conversion
109     */

110     public static int convertLSToLF(char chars[], int len) {
111         int tgtOffset = 0;
112         short lsLen = 0; // length of separator found
113
int moveStart = 0; // start of block that must be moved
114
int moveLen; // length of data moved back in buffer
115

116         for (int i = 0; i < len; i++) {
117             // first of all - there's no need to handle single '\n'
118
if (chars[i] == '\r') { // '\r' found
119
if (i + 1 < len && chars[i + 1] == '\n') { // '\n' follows
120
lsLen = 2; // '\r\n'
121
} else {
122                     lsLen = 1; // only '\r'
123
}
124             }
125
126             if (lsLen > 0) {
127                 moveLen = i - moveStart;
128                 if (moveLen > 0) {
129                     if (tgtOffset != moveStart) { // will need to arraycopy
130
System.arraycopy(chars, moveStart, chars, tgtOffset, moveLen);
131                     }
132                     tgtOffset += moveLen;
133                 }
134                 chars[tgtOffset++] = '\n';
135                 moveStart += moveLen + lsLen; // skip separator
136
i += lsLen - 1; // possibly skip '\n'
137
lsLen = 0; // signal no separator found
138
}
139         }
140
141         // now move the rest if it's necessary
142
moveLen = len - moveStart;
143         if (moveLen > 0) {
144             if (tgtOffset != moveStart) {
145                 System.arraycopy(chars, moveStart, chars, tgtOffset, moveLen);
146             }
147             tgtOffset += moveLen;
148         }
149
150         return tgtOffset; // return current length
151
}
152
153     /** Convert string with generic line separators to line feeds (LF).
154     * @param text string to convert
155     * @return new string with converted LSs to LFs
156     */

157     public static String JavaDoc convertLSToLF(String JavaDoc text) {
158         char[] tgtChars = null;
159         int tgtOffset = 0;
160         short lsLen = 0; // length of separator found
161
int moveStart = 0; // start of block that must be moved
162
int moveLen; // length of data moved back in buffer
163
int textLen = text.length();
164
165         for (int i = 0; i < textLen; i++) {
166             // first of all - there's no need to handle single '\n'
167
if (text.charAt(i) == '\r') { // '\r' found
168
if (i + 1 < textLen && text.charAt(i + 1) == '\n') { // '\n' follows
169
lsLen = 2; // '\r\n'
170
} else {
171                     lsLen = 1; // only '\r'
172
}
173             }
174
175             if (lsLen > 0) {
176                 if (tgtChars == null) {
177                     tgtChars = new char[textLen];
178                     text.getChars(0, textLen, tgtChars, 0); // copy whole array
179
}
180                 moveLen = i - moveStart;
181                 if (moveLen > 0) {
182                     if (tgtOffset != moveStart) { // will need to arraycopy
183
text.getChars(moveStart, moveStart + moveLen, tgtChars, tgtOffset);
184                     }
185                     tgtOffset += moveLen;
186                 }
187                 tgtChars[tgtOffset++] = '\n';
188                 moveStart += moveLen + lsLen; // skip separator
189
i += lsLen - 1; // possibly skip '\n'
190
lsLen = 0; // signal no separator found
191
}
192         }
193
194         // now move the rest if it's necessary
195
moveLen = textLen - moveStart;
196         if (moveLen > 0) {
197             if (tgtOffset != moveStart) {
198                 text.getChars(moveStart, moveStart + moveLen, tgtChars, tgtOffset);
199             }
200             tgtOffset += moveLen;
201         }
202
203         return (tgtChars == null) ? text : new String JavaDoc(tgtChars, 0, tgtOffset);
204     }
205
206     public static boolean isSpace(String JavaDoc s) {
207         int len = s.length();
208         for (int i = 0; i < len; i++) {
209             if (s.charAt(i) != ' ') {
210                 return false;
211             }
212         }
213         return true;
214     }
215
216     /** Return true if the array contains only space chars */
217     public static boolean isSpace(char[] chars, int offset, int len) {
218         while (len > 0) {
219             if (chars[offset++] != ' ') {
220                 return false;
221             }
222             len--;
223         }
224         return true;
225     }
226
227     /** Return true if the array contains only space or tab chars */
228     public static boolean isWhitespace(char[] chars, int offset, int len) {
229         while (len > 0) {
230             if (!Character.isWhitespace(chars[offset])) {
231                 return false;
232             }
233             offset++;
234             len--;
235         }
236         return true;
237     }
238
239     /** Return the first index that is not space */
240     public static int findFirstNonTab(char[] chars, int offset, int len) {
241         while (len > 0) {
242             if (chars[offset] != '\t') {
243                 return offset;
244             }
245             offset++;
246             len--;
247         }
248         return -1;
249     }
250
251     /** Return the first index that is not space */
252     public static int findFirstNonSpace(char[] chars, int offset, int len) {
253         while (len > 0) {
254             if (chars[offset] != ' ') {
255                 return offset;
256             }
257             offset++;
258             len--;
259         }
260         return -1;
261     }
262
263     /** Return the first index that is not space or tab or new-line char */
264     public static int findFirstNonWhite(char[] chars, int offset, int len) {
265         while (len > 0) {
266             if (!Character.isWhitespace(chars[offset])) {
267                 return offset;
268             }
269             offset++;
270             len--;
271         }
272         return -1;
273     }
274
275     /** Return the last index that is not space or tab or new-line char */
276     public static int findLastNonWhite(char[] chars, int offset, int len) {
277         int i = offset + len - 1;
278         while (i >= offset) {
279             if (!Character.isWhitespace(chars[i])) {
280                 return i;
281             }
282             i--;
283         }
284         return -1;
285     }
286
287     /** Count the number of line feeds in char array.
288     * @return number of LF characters contained in array.
289     */

290     public static int getLFCount(char chars[]) {
291         return getLFCount(chars, 0, chars.length);
292     }
293
294     public static int getLFCount(char chars[], int offset, int len) {
295         int lfCount = 0;
296         while (len > 0) {
297             if (chars[offset++] == '\n') {
298                 lfCount++;
299             }
300             len--;
301         }
302         return lfCount;
303     }
304
305     public static int getLFCount(String JavaDoc s) {
306         int lfCount = 0;
307         int len = s.length();
308         for (int i = 0; i < len; i++) {
309             if (s.charAt(i) == '\n') {
310                 lfCount++;
311             }
312         }
313         return lfCount;
314     }
315
316     public static int findFirstLFOffset(char[] chars, int offset, int len) {
317         while (len > 0) {
318             if (chars[offset++] == '\n') {
319                 return offset - 1;
320             }
321             len--;
322         }
323         return -1;
324     }
325
326     public static int findFirstLFOffset(String JavaDoc s) {
327         int len = s.length();
328         for (int i = 0; i < len; i++) {
329             if (s.charAt(i) == '\n') {
330                 return i;
331             }
332         }
333         return -1;
334     }
335
336     public static int findFirstTab(char[] chars, int offset, int len) {
337         while (len > 0) {
338             if (chars[offset++] == '\t') {
339                 return offset - 1;
340             }
341             len--;
342         }
343         return -1;
344     }
345
346     public static int findFirstTabOrLF(char[] chars, int offset, int len) {
347         while (len > 0) {
348             switch (chars[offset++]) {
349             case '\t':
350             case '\n':
351                 return offset - 1;
352             }
353             len--;
354         }
355         return -1;
356     }
357
358     /** Reverses the order of characters in the array. It works from
359     * the begining of the array, so no offset is given.
360     */

361     public static void reverse(char[] chars, int len) {
362         for (int i = ((--len - 1) >> 1); i >= 0; --i) {
363             char ch = chars[i];
364             chars[i] = chars[len - i];
365             chars[len - i] = ch;
366         }
367     }
368
369     public static boolean equals(String JavaDoc s, char[] chars) {
370         return equals(s, chars, 0, chars.length);
371     }
372
373     public static boolean equals(String JavaDoc s, char[] chars, int offset, int len) {
374         if (s.length() != len) {
375             return false;
376         }
377         for (int i = 0; i < len; i++) {
378             if (s.charAt(i) != chars[offset + i]) {
379                 return false;
380             }
381         }
382         return true;
383     }
384
385     /** Do initial reading of document. Translate any line separators
386     * found in document to line separators used by document. It also cares
387     * for elements that were already created on the empty document. Although
388     * the document must be empty there can be already marks created. Initial
389     * read is equivalent to inserting the string array of the whole document
390     * size at position 0 in the document. Therefore all the marks that are
391     * not insertAfter are removed and reinserted to the end of the document
392     * after the whole initial read is finished.
393     * @param doc document for which the initialization is performed
394     * @param reader reader from which document should be read
395     * @param lsType line separator type
396     * @param testLS test line separator of file and if it's consistent, use it
397     * @param markDistance the distance between the new syntax mark is put
398     */

399     public static void initialRead(BaseDocument doc, Reader JavaDoc reader, boolean testLS)
400     throws IOException JavaDoc {
401         // document MUST be empty
402
if (doc.getLength() > 0) {
403             return;
404         }
405
406         // for valid reader read the document
407
if (reader != null) {
408             // Size of the read buffer
409
int readBufferSize = ((Integer JavaDoc)doc.getProperty(
410                                       SettingsNames.READ_BUFFER_SIZE)).intValue();
411
412             if (testLS) {
413                 // Construct a reader that searches for initial line separator type
414
reader = new LineSeparatorConversion.InitialSeparatorReader(reader);
415             }
416
417             /* buffer into which the data from file will be read */
418             LineSeparatorConversion.ToLineFeed toLF = new LineSeparatorConversion.ToLineFeed(reader, readBufferSize);
419             
420             boolean firstRead = true; // first cycle of reading from stream
421
int pos = 0; // actual position in the document data
422
int line = 0; // Line counter
423
int maxLineLength = 0; // Longest line found
424
int lineStartPos = 0; // Start offset of the last line
425
int markCount = 0; // Total mark count - for debugging only
426

427 /* // array for getting mark array from renderer inner class
428             Mark[] origMarks = new Mark[doc.marks.getItemCount()];
429             ObjectArrayUtilities.copyItems(doc.marks, 0, origMarks.length,
430                 origMarks, 0);
431
432             // now remove all the marks that are not insert after
433             for (int i = 0; i < origMarks.length; i++) {
434                 Mark mark = origMarks[i];
435                 if (!(mark.getInsertAfter()
436                         || (mark instanceof MarkFactory.CaretMark))
437                    ) {
438                     try {
439                         mark.remove();
440                     } catch (InvalidMarkException e) {
441                         if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
442                             e.printStackTrace();
443                         }
444                     }
445                 }
446             }
447 */

448
449             // Enter the loop where all data from reader will be read
450
Segment JavaDoc text = toLF.nextConverted();
451             while (text != null) {
452                 try {
453                     doc.insertString(pos, new String JavaDoc(text.array, text.offset, text.count), null);
454                 } catch (BadLocationException JavaDoc e) {
455                     throw new IllegalStateException JavaDoc(e.toString());
456                 }
457                 pos += text.count;
458                 text = toLF.nextConverted();
459             }
460
461             if (testLS) {
462                 doc.putProperty(BaseDocument.READ_LINE_SEPARATOR_PROP,
463                     ((LineSeparatorConversion.InitialSeparatorReader)reader).getInitialSeparator());
464 // if (doc.getProperty(BaseDocument.WRITE_LINE_SEPARATOR_PROP) == null) {
465
// doc.putProperty(BaseDocument.WRITE_LINE_SEPARATOR_PROP, newLS);
466
// }
467
// The property above is left empty so the write() will default to the READ_LINE_SEPARATOR_PROP
468
}
469
470 /* // Now reinsert marks that were removed at begining to the end
471             for (int i = 0; i < origMarks.length; i++) {
472                 Mark mark = origMarks[i];
473                 if (!(mark.getInsertAfter()
474                         || (mark instanceof MarkFactory.CaretMark))
475                    ) {
476                     try {
477                         origMarks[i].insert(doc, pos);
478                     } catch (InvalidMarkException e) {
479                         if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
480                             e.printStackTrace();
481                         }
482                     } catch (BadLocationException e) {
483                         if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
484                             e.printStackTrace();
485                         }
486                     }
487                 }
488             }
489  */

490
491                 // Set the line limit document property
492
// [PENDING] doc.putProperty(BaseDocument.LINE_LIMIT_PROP, new Integer(maxLineLength));
493

494         }
495     }
496
497     /** Read from some reader and insert into document */
498     static void read(BaseDocument doc, Reader JavaDoc reader, int pos)
499     throws BadLocationException JavaDoc, IOException JavaDoc {
500         int readBufferSize = ((Integer JavaDoc)doc.getProperty(
501                                   SettingsNames.READ_BUFFER_SIZE)).intValue();
502         LineSeparatorConversion.ToLineFeed toLF
503             = new LineSeparatorConversion.ToLineFeed(reader, readBufferSize);
504         
505         Segment JavaDoc text = toLF.nextConverted();
506         while (text != null) {
507             doc.insertString(pos, new String JavaDoc(text.array, text.offset, text.count), null);
508             pos += text.count;
509             text = toLF.nextConverted();
510         }
511     }
512
513     /** Write from document to some writer */
514     static void write(BaseDocument doc, Writer JavaDoc writer, int pos, int len)
515     throws BadLocationException JavaDoc, IOException JavaDoc {
516         String JavaDoc lsType = (String JavaDoc)doc.getProperty(BaseDocument.WRITE_LINE_SEPARATOR_PROP);
517         if (lsType == null) {
518             lsType = (String JavaDoc)doc.getProperty(BaseDocument.READ_LINE_SEPARATOR_PROP);
519             if (lsType == null) {
520                 lsType = BaseDocument.LS_LF;
521             }
522         }
523         int writeBufferSize = ((Integer JavaDoc)doc.getProperty(
524                                    SettingsNames.WRITE_BUFFER_SIZE)).intValue();
525         char[] getBuf = new char[writeBufferSize];
526         char[] writeBuf = new char[2 * writeBufferSize];
527         int actLen = 0;
528
529         while (len > 0) {
530             actLen = Math.min(len, writeBufferSize);
531             doc.getChars(pos, getBuf, 0, actLen);
532             int tgtLen = convertLFToLS(getBuf, actLen, writeBuf, lsType);
533             writer.write(writeBuf, 0, tgtLen);
534             pos += actLen;
535             len -= actLen;
536         }
537
538         // Append new-line if not the last char
539
/* if (actLen > 0 && getBuf[actLen - 1] != '\n') {
540             writer.write(new char[] { '\n' }, 0, 1);
541         }
542  */

543
544     }
545
546     /** Get visual column. */
547     public static int getColumn(char buffer[], int offset,
548                                 int len, int tabSize, int startCol) {
549         int col = startCol;
550         int endOffset = offset + len;
551
552         // Check wrong tab values
553
if (tabSize <= 0) {
554             new Exception JavaDoc("Wrong tab size=" + tabSize).printStackTrace(); // NOI18N
555
tabSize = 8;
556         }
557
558         while (offset < endOffset) {
559             switch (buffer[offset++]) {
560             case '\t':
561                 col = (col + tabSize) / tabSize * tabSize;
562                 break;
563             default:
564                 col++;
565             }
566         }
567         return col;
568     }
569
570     /** Get buffer filled with appropriate number of spaces. The buffer
571     * can have actually more spaces than requested.
572     * @param numSpaces number of spaces
573     */

574     public static synchronized char[] getSpacesBuffer(int numSpaces) {
575         // check if there's enough space in white space array
576
while (numSpaces > spacesBuffer.length) {
577             char tmpBuf[] = new char[spacesBuffer.length * 2]; // new buffer
578
System.arraycopy(spacesBuffer, 0, tmpBuf, 0, spacesBuffer.length);
579             System.arraycopy(spacesBuffer, 0, tmpBuf, spacesBuffer.length, spacesBuffer.length);
580             spacesBuffer = tmpBuf;
581         }
582
583         return spacesBuffer;
584     }
585
586     /** Get string filled with space characters. There is optimization to return
587      * the same string instance for up to ceratin number of spaces.
588      * @param numSpaces number of spaces determining the resulting size of the string.
589      */

590     public static synchronized String JavaDoc getSpacesString(int numSpaces) {
591         if (numSpaces <= MAX_CACHED_SPACES_STRING_LENGTH) { // Cached
592
String JavaDoc ret = spacesStrings[numSpaces];
593             if (ret == null) {
594                 ret = spacesStrings[MAX_CACHED_SPACES_STRING_LENGTH].substring(0, numSpaces);
595                 spacesStrings[numSpaces] = ret;
596             }
597
598             return ret;
599
600         } else { // non-cached
601
return new String JavaDoc(getSpacesBuffer(numSpaces), 0, numSpaces);
602         }
603     }
604
605     /** Get buffer of the requested size filled entirely with space character.
606      * @param numSpaces number of spaces in the returned character buffer.
607      */

608     public static char[] createSpacesBuffer(int numSpaces) {
609         char[] ret = new char[numSpaces];
610         System.arraycopy(getSpacesBuffer(numSpaces), 0, ret, 0, numSpaces);
611         return ret;
612     }
613
614     /** Get buffer filled with appropriate number of tabs. The buffer
615     * can have actually more tabs than requested.
616     * @param numSpaces number of spaces
617     */

618     public static char[] getTabsBuffer(int numTabs) {
619         // check if there's enough space in white space array
620
if (numTabs > tabsBuffer.length) {
621             char tmpBuf[] = new char[numTabs * 2]; // new buffer
622

623             // initialize new buffer with spaces
624
for (int i = 0; i < tmpBuf.length; i += tabsBuffer.length) {
625                 System.arraycopy(tabsBuffer, 0, tmpBuf, i,
626                                  Math.min(tabsBuffer.length, tmpBuf.length - i));
627             }
628             tabsBuffer = tmpBuf;
629         }
630
631         return tabsBuffer;
632     }
633
634     /** Get the string that should be used for indentation of the given level.
635      * @param indent indentation level
636      * @param expandTabs whether tabs should be expanded to spaces or not
637      * @param tabSize size substituted visually for the '\t' character
638      */

639     public static String JavaDoc getIndentString(int indent, boolean expandTabs, int tabSize) {
640         return getWhitespaceString(0, indent, expandTabs, tabSize);
641     }
642
643     /** Get the string that should be used for indentation of the given level.
644      * @param indent indentation level
645      * @param expandTabs whether tabs should be expanded to spaces or not
646      * @param tabSize size of the '\t' character
647      */

648     public static String JavaDoc getWhitespaceString(int startCol, int endCol,
649     boolean expandTabs, int tabSize) {
650         return (expandTabs || tabSize <= 0)
651             ? getSpacesString(endCol - startCol)
652             : new String JavaDoc(createWhiteSpaceFillBuffer(startCol, endCol, tabSize));
653     }
654
655     /** createWhitespaceFillBuffer() with the non-capital 's' should be used.
656      * @deprecated
657      */

658     public static char[] createWhiteSpaceFillBuffer(int startCol, int endCol,
659     int tabSize) {
660         return createWhitespaceFillBuffer(startCol, endCol, tabSize);
661     }
662
663     /** Get buffer filled with spaces/tabs so that it reaches from
664     * some column to some other column.
665     * @param startCol starting visual column of the whitespace on the line
666     * @param endCol ending visual column of the whitespace on the line
667     * @param tabSize size substituted visually for the '\t' character
668     */

669     public static char[] createWhitespaceFillBuffer(int startCol, int endCol,
670     int tabSize) {
671         if (startCol >= endCol) {
672             return EMPTY_CHAR_ARRAY;
673         }
674
675         // Check wrong tab values
676
if (tabSize <= 0) {
677             new Exception JavaDoc("Wrong tab size=" + tabSize).printStackTrace(); // NOI18N
678
tabSize = 8;
679         }
680
681         int tabs = 0;
682         int spaces = 0;
683         int nextTab = (startCol + tabSize) / tabSize * tabSize;
684         if (nextTab > endCol) { // only spaces
685
spaces += endCol - startCol;
686         } else { // at least one tab
687
tabs++; // jump to first tab
688
int endSpaces = endCol - endCol / tabSize * tabSize;
689             tabs += (endCol - endSpaces - nextTab) / tabSize;
690             spaces += endSpaces;
691         }
692
693         char[] ret = new char[tabs + spaces];
694         if (tabs > 0) {
695             System.arraycopy(getTabsBuffer(tabs), 0, ret, 0, tabs);
696         }
697         if (spaces > 0) {
698             System.arraycopy(getSpacesBuffer(spaces), 0, ret, tabs, spaces);
699         }
700         return ret;
701     }
702
703     /** Loads the file and performs conversion of line separators to LF.
704     * This method can be used in debuging of syntax scanner or somewhere else.
705     * @param fileName the name of the file to load
706     * @return array of loaded characters with '\n' as line separator
707     */

708     public static char[] loadFile(String JavaDoc fileName) throws IOException JavaDoc {
709         File JavaDoc file = new File JavaDoc(fileName);
710         char chars[] = new char[(int)file.length()];
711         FileReader JavaDoc reader = new FileReader JavaDoc(file);
712         reader.read(chars);
713         reader.close();
714         int len = Analyzer.convertLSToLF(chars, chars.length);
715         if (len != chars.length) {
716             char copyChars[] = new char[len];
717             System.arraycopy(chars, 0, copyChars, 0, len);
718             chars = copyChars;
719         }
720         return chars;
721     }
722
723     /** Convert text with LF line separators to text that uses
724     * line separators of the document. This function is used when
725     * saving text into the file. Segment's data are converted inside
726     * the segment's data or new segment's data array is allocated.
727     * NOTE: Source segment must have just LFs as separators! Otherwise
728     * the conversion won't work correctly.
729     * @param src source chars to convert from
730     * @param len length of valid part of src data
731     * @param tgt target chars to convert to. The array MUST have twice
732     * the size of src otherwise index exception can be thrown
733     * @param lsType line separator type to be used i.e. LS_LF, LS_CR, LS_CRLF
734     * @return length of valid chars in tgt array
735     */

736     public static int convertLFToLS(char[] src, int len, char[] tgt, String JavaDoc lsType) {
737         if (lsType.equals(BaseDocument.LS_CR)) { // CR instead of LF
738
System.arraycopy(src, 0, tgt, 0, len);
739
740             // now do conversion for LS_CR
741
if (lsType == BaseDocument.LS_CR) { // will convert '\n' to '\r'
742
char chars[] = tgt;
743                 for (int i = 0; i < len; i++) {
744                     if (chars[i] == '\n') {
745                         chars[i] = '\r';
746                     }
747                 }
748             }
749             return len;
750         } else if (lsType.equals(BaseDocument.LS_CRLF)) {
751             int tgtLen = 0;
752             int moveStart = 0; // start of block that must be moved
753
int moveLen; // length of chars moved
754

755             for (int i = 0; i < len; i++) {
756                 if (src[i] == '\n') { // '\n' found
757
moveLen = i - moveStart;
758                     if (moveLen > 0) { // will need to arraycopy
759
System.arraycopy(src, moveStart, tgt, tgtLen, moveLen);
760                         tgtLen += moveLen;
761                     }
762                     tgt[tgtLen++] = '\r';
763                     tgt[tgtLen++] = '\n';
764                     moveStart = i + 1; // skip separator
765
}
766             }
767
768             // now move the rest if it's necessary
769
moveLen = len - moveStart;
770             if (moveLen > 0) {
771                 System.arraycopy(src, moveStart, tgt, tgtLen, moveLen);
772                 tgtLen += moveLen;
773             }
774             return tgtLen;
775         } else { // Using either \n or line separator is unknown
776
System.arraycopy(src,0, tgt, 0, len);
777             return len;
778         }
779     }
780
781     public static boolean startsWith(char[] chars, char[] prefix) {
782         if (chars == null || chars.length < prefix.length) {
783             return false;
784         }
785         for (int i = 0; i < prefix.length; i++) {
786             if (chars[i] != prefix[i]) {
787                 return false;
788             }
789         }
790         return true;
791     }
792
793     public static boolean endsWith(char[] chars, char[] suffix) {
794         if (chars == null || chars.length < suffix.length) {
795             return false;
796         }
797         for (int i = chars.length - suffix.length; i < chars.length; i++) {
798             if (chars[i] != suffix[i]) {
799                 return false;
800             }
801         }
802         return true;
803     }
804
805     public static char[] concat(char[] chars1, char[] chars2) {
806         if (chars1 == null || chars1.length == 0) {
807             return chars2;
808         }
809         if (chars2 == null || chars2.length == 0) {
810             return chars1;
811         }
812         char[] ret = new char[chars1.length + chars2.length];
813         System.arraycopy(chars1, 0, ret, 0, chars1.length);
814         System.arraycopy(chars2, 0, ret, chars1.length, chars2.length);
815         return ret;
816     }
817
818     public static char[] extract(char[] chars, int offset, int len) {
819         char[] ret = new char[len];
820         System.arraycopy(chars, offset, ret, 0, len);
821         return ret;
822     }
823
824     public static boolean blocksHit(int[] blocks, int startPos, int endPos) {
825         return (blocksIndex(blocks, startPos, endPos) >= 0);
826     }
827
828     public static int blocksIndex(int[] blocks, int startPos, int endPos) {
829         if (blocks.length > 0) {
830             int onlyEven = ~1;
831             int low = 0;
832             int high = blocks.length - 2;
833
834             while (low <= high) {
835                 int mid = ((low + high) / 2) & onlyEven;
836
837                 if (blocks[mid + 1] <= startPos) {
838                     low = mid + 2;
839                 } else if (blocks[mid] >= endPos) {
840                     high = mid - 2;
841                 } else {
842                     return low; // found
843
}
844             }
845         }
846
847         return -1;
848     }
849
850     /** Remove all spaces from the given string.
851      * @param s original string
852      * @return string with all spaces removed
853      */

854     public static String JavaDoc removeSpaces(String JavaDoc s) {
855         int spcInd = s.indexOf(' ');
856         if (spcInd >= 0) {
857             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(s.substring(0, spcInd));
858             int sLen = s.length();
859             for (int i = spcInd + 1; i < sLen; i++) {
860                 char ch = s.charAt(i);
861                 if (ch != ' ') {
862                     sb.append(ch);
863                 }
864             }
865             return sb.toString();
866         }
867         return s;
868     }
869
870 }
871
Popular Tags