001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.squid.text; 021 022 import java.io.IOException; 023 import java.io.Reader; 024 025 public class StringArrayReader extends Reader { 026 027 private String[] array; 028 private int rowIndex = 0; 029 private int rowIndexMark = 0; 030 private int colIndex = 0; 031 private int colIndexMark = 0; 032 private static final char END_OF_LINE_CHAR = '\n'; 033 private boolean ready = true; 034 035 public StringArrayReader(String array[]) { 036 this.array = array; 037 } 038 039 @Override 040 public void close() throws IOException { 041 array = null; 042 ready = false; 043 } 044 045 @Override 046 public boolean ready() throws IOException { 047 return ready; 048 } 049 050 @Override 051 public boolean markSupported() { 052 return true; 053 } 054 055 @Override 056 public void mark(int readAheadLimit) throws IOException { 057 rowIndexMark = rowIndex; 058 colIndexMark = colIndex; 059 } 060 061 @Override 062 public void reset() throws IOException { 063 rowIndex = rowIndexMark; 064 colIndex = colIndexMark; 065 } 066 067 @Override 068 public int read(char[] cbuf, int off, int len) throws IOException { 069 if (isEndOfArray()) { 070 return -1; 071 } 072 if (isEndOfCurrentLine()) { 073 switchToNewLine(cbuf, off); 074 if (len > 1) { 075 int numberOfReadChars = 1 + read(cbuf, off + 1, len - 1); 076 return (numberOfReadChars == 0 ? 1 : numberOfReadChars); 077 } else { 078 return 1; 079 } 080 } 081 if (isThereEnoughCharsOnCurrentLine(len)) { 082 getCurrentLine().getChars(colIndex, colIndex + len, cbuf, off); 083 colIndex += len; 084 return len; 085 } else { 086 getCurrentLine().getChars(colIndex, getCurrentLine().length(), cbuf, off); 087 int readLength = getCurrentLine().length() - colIndex; 088 colIndex = getCurrentLine().length(); 089 int nextReadLength = read(cbuf, off + readLength, len - readLength); 090 return readLength + (nextReadLength > -1 ? nextReadLength : 0); 091 } 092 } 093 094 private boolean isThereEnoughCharsOnCurrentLine(int len) { 095 return colIndex + len <= getCurrentLine().length(); 096 } 097 098 private boolean isEndOfArray() { 099 return array == null || array.length == 0 || (isEndOfCurrentLine() && rowIndex == array.length - 1); 100 } 101 102 private boolean isEndOfCurrentLine() { 103 return colIndex >= getCurrentLine().length(); 104 } 105 106 private String getCurrentLine() { 107 return array[rowIndex]; 108 } 109 110 private void switchToNewLine(char[] cbuf, int off) { 111 cbuf[off] = END_OF_LINE_CHAR; 112 colIndex = 0; 113 rowIndex++; 114 } 115 116 }