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 (height < 1) { 047 throw new IllegalArgumentException("A non positive height=" + height + " cannot be accepted"); 048 } 049 if (index < s.length()) { 050 int pos = s.indexOf('\n', index); 051 if (pos == -1) { 052 return Pair.of(s.length() - index, height); 053 } else { 054 Pair<Integer, Integer> ret = size(s, pos + 1, height + 1); 055 return new Pair<Integer, Integer>(Math.max(pos - index, ret.getFirst()), ret.getSecond()); 056 } 057 } else { 058 return Pair.of(0, height); 059 } 060 } 061 062 public Pair<Integer, Integer>[] lines(final int width) { 063 return lines(linesIterator(width), 0); 064 } 065 066 private Pair<Integer, Integer>[] lines(Iterator<Pair<Integer, Integer>> i, int count) { 067 Pair<Integer, Integer>[] lines; 068 if (i.hasNext()) { 069 Pair<Integer, Integer> n = i.next(); 070 lines = lines(i, count + 1); 071 lines[count] = n; 072 } else { 073 lines = new Pair[count]; 074 } 075 return lines; 076 } 077 078 public Iterator<Pair<Integer, Integer>> linesIterator(final int width) { 079 if (width < 1) { 080 throw new IllegalArgumentException("A non positive width=" + width + " cannot be accepted"); 081 } 082 return new BaseIterator<Pair<Integer, Integer>>() { 083 084 /** . */ 085 int index = 0; 086 087 /** . */ 088 Pair<Integer, Integer> next = null; 089 090 public boolean hasNext() { 091 if (next == null) { 092 if (index != Integer.MAX_VALUE) { 093 int pos = value.indexOf('\n', index); 094 int nextIndex; 095 if (pos == -1) { 096 pos = Math.min(index + width, value.length()); 097 nextIndex = pos; 098 } else { 099 if (pos <= index + width) { 100 nextIndex = pos + 1; 101 } else { 102 nextIndex = pos = index + width; 103 } 104 } 105 next = Pair.of(index, pos); 106 if (pos < value.length()) { 107 index = nextIndex; 108 } else { 109 // Stop value 110 index = Integer.MAX_VALUE; 111 } 112 } 113 } 114 return next != null; 115 } 116 117 public Pair<Integer, Integer> next() { 118 if (!hasNext()) { 119 throw new NoSuchElementException(); 120 } 121 Pair<Integer, Integer> next = this.next; 122 this.next = null; 123 return next; 124 } 125 }; 126 } 127 }