001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.util;
021
022 import java.util.Iterator;
023 import java.util.NoSuchElementException;
024
025 public class CharSlicer {
026
027 /** . */
028 private final String value;
029
030 /** . */
031 private Pair<Integer, Integer> size;
032
033 public CharSlicer(String value) {
034 this.value = value;
035 this.size = size();
036 }
037
038 public Pair<Integer, Integer> size() {
039 if (size == null) {
040 size = size(value, 0, 1);
041 }
042 return size;
043 }
044
045 private static Pair<Integer, Integer> size(String s, int index, int height) {
046 if (index < s.length()) {
047 int pos = s.indexOf('\n', index);
048 if (pos == -1) {
049 return Pair.of(s.length() - index, height);
050 } else {
051 Pair<Integer, Integer> ret = size(s, pos + 1, height + 1);
052 return new Pair<Integer, Integer>(Math.max(pos - index, ret.getFirst()), ret.getSecond());
053 }
054 } else {
055 return Pair.of(0, height);
056 }
057 }
058
059 public Pair<Integer, Integer>[] lines(final int width) {
060 return lines(linesIterator(width), 0);
061 }
062
063 private Pair<Integer, Integer>[] lines(Iterator<Pair<Integer, Integer>> i, int count) {
064 Pair<Integer, Integer>[] lines;
065 if (i.hasNext()) {
066 Pair<Integer, Integer> n = i.next();
067 lines = lines(i, count + 1);
068 lines[count] = n;
069 } else {
070 lines = new Pair[count];
071 }
072 return lines;
073 }
074
075 public Iterator<Pair<Integer, Integer>> linesIterator(final int width) {
076
077 return new BaseIterator<Pair<Integer, Integer>>() {
078
079 /** . */
080 int index = 0;
081
082 /** . */
083 Pair<Integer, Integer> next = null;
084
085 public boolean hasNext() {
086 if (next == null) {
087 if (index != Integer.MAX_VALUE) {
088 int pos = value.indexOf('\n', index);
089 int nextIndex;
090 if (pos == -1) {
091 pos = Math.min(index + width, value.length());
092 nextIndex = pos;
093 } else {
094 if (pos <= index + width) {
095 nextIndex = pos + 1;
096 } else {
097 nextIndex = pos = index + width;
098 }
099 }
100 next = Pair.of(index, pos);
101 if (pos < value.length()) {
102 index = nextIndex;
103 } else {
104 // Stop value
105 index = Integer.MAX_VALUE;
106 }
107 }
108 }
109 return next != null;
110 }
111
112 public Pair<Integer, Integer> next() {
113 if (!hasNext()) {
114 throw new NoSuchElementException();
115 }
116 Pair<Integer, Integer> next = this.next;
117 this.next = null;
118 return next;
119 }
120 };
121 }
122 }