1 4 package gnu.text; 5 import java.io.*; 6 7 25 26 public class LineBufferedReader extends FilterReader 27 { 28 29 final static int BUFFER_SIZE = 1024; 30 31 32 public char[] buffer; 33 34 35 public int pos; 36 37 38 public int limit; 39 40 41 int highestPos; 42 43 public char readState = '\n'; 44 48 public char getReadState () { return readState; } 49 50 private int flags; 51 52 66 67 private static final int CONVERT_CR = 1; 68 69 70 private static final int USER_BUFFER = 2; 71 72 73 private static final int PREV_WAS_CR = 4; 74 75 76 public final boolean getConvertCR () { return (flags & CONVERT_CR) != 0; } 77 78 public final void setConvertCR(boolean convertCR) 79 { 80 if (convertCR) 81 flags |= CONVERT_CR; 82 else 83 flags &= ~CONVERT_CR; 84 } 85 86 94 int lineStartPos; 95 96 Object name; 97 98 99 protected int lineNumber; 100 101 104 protected int readAheadLimit = 0; 105 106 108 protected int markPos; 109 110 public LineBufferedReader (InputStream in) 111 { 112 super (new InputStreamReader(in)); 113 } 114 115 public LineBufferedReader (Reader in) 116 { 117 super (in); 118 } 119 120 125 public void lineStart (boolean revisited) throws java.io.IOException 126 { 127 } 128 129 134 public int fill (int len) throws java.io.IOException 135 { 136 return in.read(buffer, pos, len); 137 } 138 139 private void clearMark () 140 { 141 readAheadLimit = 0; 143 int i = lineStartPos < 0 ? 0 : lineStartPos; 145 for (;;) 146 { 147 if (++i >= pos) 148 break; 149 char ch = buffer[i-1]; 150 if (ch == '\n' 151 || (ch == '\r' && (!getConvertCR() || buffer[i] != '\n'))) 152 { 153 lineNumber++; 154 lineStartPos = i; 155 } 156 157 } 158 } 159 160 161 public void setBuffer (char[] buffer) 162 throws java.io.IOException 163 { 164 if (buffer == null) 165 { 166 if (this.buffer != null) 167 { 168 buffer = new char[this.buffer.length]; 169 System.arraycopy(this.buffer, 0, buffer, 0, this.buffer.length); 170 this.buffer = buffer; 171 } 172 flags &= ~USER_BUFFER; 173 } 174 else 175 { 176 if (limit - pos > buffer.length) 177 throw new java.io.IOException ("setBuffer - too short"); 178 flags |= USER_BUFFER; 179 reserve (buffer, 0); 180 } 181 } 182 183 184 185 private void reserve (char[] buffer, int reserve) 186 throws java.io.IOException 187 { 188 int saveStart; 189 reserve += limit; 190 if (reserve <= buffer.length) 191 saveStart = 0; 192 else 193 { 194 saveStart = pos; 195 if (readAheadLimit > 0 && markPos < pos) 196 { 197 if (pos - markPos > readAheadLimit 198 || ((flags & USER_BUFFER) != 0 199 && reserve - markPos > buffer.length)) 200 clearMark(); 201 else 202 saveStart = markPos; 203 } 204 205 reserve -= buffer.length; 206 if (saveStart < lineStartPos && reserve <= saveStart) 207 ; 208 else if (reserve <= lineStartPos && saveStart > lineStartPos) 209 saveStart = lineStartPos; 210 else if ((flags & USER_BUFFER) != 0) 211 saveStart -= (saveStart - reserve) >> 2; 212 else 213 { 214 if (lineStartPos >= 0) 215 saveStart = lineStartPos; 216 buffer = new char[2 * buffer.length]; 217 } 218 219 lineStartPos -= saveStart; 220 limit -= saveStart; 221 markPos -= saveStart; 222 pos -= saveStart; 223 highestPos -= saveStart; 224 } 225 if (limit > 0) 226 System.arraycopy(this.buffer, saveStart, buffer, 0, limit); 227 this.buffer = buffer; 228 } 229 230 public int read () throws java.io.IOException 231 { 232 char prev; 233 if (pos > 0) 234 prev = buffer[pos-1]; 235 else if ((flags & PREV_WAS_CR) != 0) 236 prev = '\r'; 237 else if (lineStartPos >= 0) 238 prev = '\n'; 239 else 240 prev = '\0'; 241 if (prev == '\r' || prev == '\n') 242 { 243 if (lineStartPos < pos && (readAheadLimit == 0 || pos <= markPos)) 244 { 245 lineStartPos = pos; 246 lineNumber++; 247 } 248 boolean revisited = pos < highestPos; 249 if (prev != '\n' 250 || (pos <= 1 ? (flags & PREV_WAS_CR) == 0 : buffer[pos-2] != '\r')) 251 { 252 lineStart(revisited); 253 } 254 if (! revisited) 255 highestPos = pos + 1; } 257 258 if (pos >= limit) 259 { 260 if (buffer == null) 261 buffer = new char[BUFFER_SIZE]; 262 else if (limit == buffer.length) 263 reserve(buffer, 1); 264 if (pos == 0) 265 { 266 if (prev == '\r') 267 flags |= PREV_WAS_CR; 268 else 269 flags &= ~PREV_WAS_CR; 270 } 271 int readCount = fill(buffer.length - pos); 272 if (readCount <= 0) 273 return -1; 274 limit += readCount; 275 } 276 277 int ch = buffer[pos++]; 278 if (ch == '\n') 279 { 280 if (prev == '\r') 281 { 282 if (lineStartPos == pos - 1) 287 { 288 lineNumber--; 289 lineStartPos--; 290 } 291 if (getConvertCR()) 292 return read(); 293 } 294 } 295 else if (ch == '\r') 296 { 297 if (getConvertCR()) 298 return '\n'; 299 } 300 return ch; 301 } 302 303 public int read (char[] cbuf, int off, int len) throws java.io.IOException 304 { 305 int ch; 307 if (pos >= limit) 308 ch = '\0'; 309 else if (pos > 0) 310 ch = buffer[pos-1]; 311 else if ((flags & PREV_WAS_CR) != 0 || lineStartPos >= 0) 312 ch = '\n'; 313 else 314 ch = '\0'; 315 int to_do = len; 316 while (to_do > 0) 317 { 318 if (pos >= limit || ch == '\n' || ch == '\r') 319 { 320 if (pos >= limit && to_do < len) 323 return len - to_do; 324 ch = read(); 325 if (ch < 0) 326 { 327 len -= to_do; 328 return len <= 0 ? -1 : len; 329 } 330 cbuf[off++] = (char) ch; 331 to_do--; 332 } 333 else 334 { 335 int p = pos; 336 int lim = limit; 337 if (to_do < lim - p) 338 lim = p + to_do; 339 while (p < lim) 340 { 341 ch = buffer[p]; 342 if (ch == '\n' || ch == '\r') 345 break; 346 cbuf[off++] = (char) ch; 347 p++; 348 } 349 to_do -= p - pos; 350 pos = p; 351 } 352 } 353 return len; 354 } 355 356 357 public Object getURI () 358 { 359 return name; 360 } 361 362 public String getName () 363 { 364 return name == null ? null : name.toString(); 365 } 366 367 public void setName (Object name) 368 { 369 this.name = name; 370 } 371 372 374 public int getLineNumber () 375 { 376 int lineno = lineNumber; 377 if (readAheadLimit == 0) { 379 if (pos > 0 && pos > lineStartPos) 380 { 381 char prev = buffer[pos-1]; 382 if (prev == '\n' || prev == '\r') 383 lineno++; 384 } 385 } 386 else 387 lineno += countLines(buffer, lineStartPos < 0 ? 0 : lineStartPos, pos); 388 return lineno; 389 } 390 391 public void setLineNumber (int lineNumber) 392 { 393 this.lineNumber += lineNumber - getLineNumber(); 394 } 395 396 397 public int getColumnNumber () 398 { 399 if (pos > 0) 400 { 401 char prev = buffer[pos-1]; 402 if (prev == '\n' || prev == '\r') 403 return 0; 404 } 405 if (readAheadLimit <= 0) return pos - lineStartPos; 407 408 int start = lineStartPos < 0 ? 0 : lineStartPos; 411 for (int i = start; i < pos; ) 412 { 413 char ch = buffer[i++]; 414 if (ch == '\n' || ch == '\r') 415 start = i; 416 } 417 int col = pos - start; 418 if (lineStartPos < 0) 419 col -= lineStartPos; 420 return col; 421 } 422 423 public boolean markSupported () 424 { 425 return true; 426 } 427 428 public synchronized void mark (int readAheadLimit) 429 { 430 if (this.readAheadLimit > 0) 431 clearMark(); 432 this.readAheadLimit = readAheadLimit; 433 markPos = pos; 434 } 435 436 public void reset () throws IOException 437 { 438 if (readAheadLimit <= 0) 439 throw new IOException ("mark invalid"); 440 if (pos > highestPos) 441 highestPos = pos; 442 pos = markPos; 443 readAheadLimit = 0; 444 } 445 446 451 452 public void readLine(StringBuffer sbuf, char mode) 453 throws IOException 454 { 455 for (;;) 456 { 457 int ch = read(); 458 if (ch < 0) 459 return; 460 int start = --pos; 461 while (pos < limit) 462 { 463 ch = buffer[pos++]; 464 if (ch == '\r' || ch == '\n') 465 { 466 sbuf.append(buffer, start, pos - 1 - start); 467 if (mode == 'P') 468 { 469 pos--; 470 return; 471 } 472 if (getConvertCR () || ch == '\n') 473 { 474 if (mode != 'I') 475 sbuf.append('\n'); 476 } 477 else 478 { 479 if (mode != 'I') 480 sbuf.append('\r'); 481 ch = read(); 482 if (ch == '\n') 483 { 484 if (mode != 'I') 485 sbuf.append('\n'); 486 } 487 else if (ch >= 0) 488 unread_quick(); 489 } 490 return; 491 } 492 } 493 sbuf.append(buffer, start, pos - start); 494 } 495 } 496 497 public String readLine() throws IOException 498 { 499 int ch = read(); 500 if (ch < 0) 501 return null; 502 if (ch == '\r' || ch == 'n') 503 return ""; 504 int start = pos - 1; 505 while (pos < limit) 506 { 507 ch = buffer[pos++]; 508 if (ch == '\r' || ch == '\n') 509 { 510 if (ch != '\n' && ! getConvertCR()) 511 { 512 if (pos >= limit) 513 { 514 pos--; 515 break; 516 } 517 if (buffer[pos] == '\n') 518 pos++; 519 } 520 return new String (buffer, start, pos - start); 521 } 522 } 523 StringBuffer sbuf = new StringBuffer (100); 524 sbuf.append(buffer, start, pos); 525 readLine(sbuf, 'I'); 526 return sbuf.toString(); 527 } 528 529 530 public int skip(int n) throws IOException 531 { 532 if (n < 0) 533 { 534 int to_do = -n; 535 for (; to_do > 0 && pos > 0; to_do--) 536 unread(); 537 return n + to_do; 538 } 539 else 540 { 541 int to_do = n; 543 int ch; 544 if (pos >= limit) 545 ch = '\0'; 546 else if (pos > 0) 547 ch = buffer[pos-1]; 548 else if ((flags & PREV_WAS_CR) != 0 || lineStartPos >= 0) 549 ch = '\n'; 550 else 551 ch = '\0'; 552 while (to_do > 0) 553 { 554 if (ch == '\n' || ch == '\r' || pos >= limit) 555 { 556 ch = read(); 557 if (ch < 0) 558 return n - to_do; 559 to_do--; 560 } 561 else 562 { 563 int p = pos; 564 int lim = limit; 565 if (to_do < lim - p) 566 lim = p + to_do; 567 while (p < lim) 568 { 569 ch = buffer[p]; 570 if (ch == '\n' || ch == '\r') 573 break; 574 p++; 575 } 576 to_do -= p - pos; 577 pos = p; 578 } 579 } 580 return n; 581 } 582 } 583 584 public boolean ready () throws java.io.IOException 585 { 586 return pos < limit || in.ready(); 587 } 588 589 590 public final void skip_quick () throws java.io.IOException 591 { 592 pos++; 593 } 594 595 public void skip () throws java.io.IOException 596 { 597 read(); 598 } 599 600 static int countLines (char[] buffer, int start, int limit) 601 { 602 int count = 0; 603 char prev = '\0'; 604 for (int i = start; i < limit; i++) 605 { 606 char ch = buffer[i]; 607 if ((ch == '\n' && prev != '\r') || ch == '\r') 608 count++; 609 prev = ch; 610 } 611 return count; 612 } 613 614 615 public void skipRestOfLine () 616 throws java.io.IOException 617 { 618 for (;;) 619 { 620 int c = read(); 621 if (c < 0) 622 return; 623 if (c == '\r') 624 { 625 c = read(); 626 if (c >= 0 && c != '\n') 627 unread(); 628 break; 629 } 630 else if (c == '\n') 631 break; 632 } 633 } 634 635 636 public void unread () 637 throws java.io.IOException 638 { 639 if (pos == 0) 640 throw new java.io.IOException ("unread too much"); 641 pos--; 642 char ch = buffer[pos]; 643 if (ch == '\n' || ch == '\r') 644 { 645 if (pos > 0 && ch == '\n' && getConvertCR() && buffer[pos-1] == '\r') 646 pos--; 647 if (pos < lineStartPos) 648 { 649 lineNumber--; 650 int i; 651 for (i = pos; i > 0; ) 652 { 653 ch = buffer[--i]; 654 if (ch == '\r' || ch == '\n') 655 { 656 i++; 657 break; 658 } 659 } 660 lineStartPos = i; 661 } 662 } 663 } 664 665 668 public void unread_quick () 669 { 670 pos--; 671 } 672 673 public int peek () 674 throws java.io.IOException 675 { 676 if (pos < limit && pos > 0) 677 { 678 char ch = buffer[pos - 1]; 679 if (ch != '\n' && ch != '\r') 680 { 681 ch = buffer[pos]; 682 if (ch == '\r' && getConvertCR()) 683 ch = '\n'; 684 return ch; 685 } 686 } 687 int c = read (); 688 if (c >= 0) 689 unread_quick(); 690 return c; 691 } 692 693 } 694 | Popular Tags |