001/** 002 * Java Web Archive Toolkit - Software to read and validate ARC, WARC 003 * and GZip files. (http://jwat.org/) 004 * Copyright 2011-2012 Netarkivet.dk (http://netarkivet.dk/) 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.jwat.common; 019 020import java.io.ByteArrayOutputStream; 021import java.util.Arrays; 022 023/** 024 * Base2 encoder/decoder implementation. 025 * 026 * @author nicl 027 */ 028public class Base2 { 029 030 /** Ascii table used to encode. */ 031 public static String[] encodeTab = { 032 "0000", 033 "0001", 034 "0010", 035 "0011", 036 "0100", 037 "0101", 038 "0110", 039 "0111", 040 "1000", 041 "1001", 042 "1010", 043 "1011", 044 "1100", 045 "1101", 046 "1110", 047 "1111" 048 }; 049 050 /** Table used to decode. */ 051 public static byte[] decodeTab = new byte[ 256 ]; 052 053 /** Populate decode table. */ 054 static { 055 Arrays.fill( decodeTab, (byte)0xff ); 056 decodeTab[ '0' ] = 0; 057 decodeTab[ '1' ] = 1; 058 } 059 060 /** 061 * Static class. 062 */ 063 protected Base2() { 064 } 065 066 /** 067 * Decodes an encoded string. 068 * @param in encoded string. 069 * @return decoded string or null 070 */ 071 public static String decodeToString(String in) { 072 if (in == null) { 073 return null; 074 } 075 if (in.length() == 0) { 076 return ""; 077 } 078 StringBuffer out = new StringBuffer( 256 ); 079 boolean b = true; 080 int idx = 0; 081 char cin; 082 int mod = 0; 083 int cIdx; 084 int cout = 0; 085 while ( b ) { 086 if ( idx < in.length() ) { 087 cin = in.charAt( idx++ ); 088 cIdx = decodeTab[ cin ]; 089 if ( cIdx != -1 ) { 090 cout = (cout << 1) | cIdx; 091 mod = ( mod + 1 ) % 8; 092 if ( mod == 0 ) { 093 out.append( (char)cout ); 094 cout = 0; 095 } 096 } 097 else { 098 return null; 099 } 100 } 101 else { 102 b = false; 103 } 104 } 105 if ( mod == 0 ) { 106 return out.toString(); 107 } 108 else { 109 return null; 110 } 111 } 112 113 /** 114 * Decodes an encoded string. 115 * @param in encoded string. 116 * @return decoded byte array or null 117 */ 118 public static byte[] decodeToArray(String in) { 119 if (in == null) { 120 return null; 121 } 122 if (in.length() == 0) { 123 return new byte[0]; 124 } 125 ByteArrayOutputStream out = new ByteArrayOutputStream(); 126 boolean b = true; 127 int idx = 0; 128 char cin; 129 int mod = 0; 130 int cIdx; 131 int cout = 0; 132 while ( b ) { 133 if ( idx < in.length() ) { 134 cin = in.charAt( idx++ ); 135 cIdx = decodeTab[ cin ]; 136 if ( cIdx != -1 ) { 137 cout = (cout << 1) | cIdx; 138 mod = ( mod + 1 ) % 8; 139 if ( mod == 0 ) { 140 out.write( cout ); 141 } 142 } 143 else { 144 return null; 145 } 146 } 147 else { 148 b = false; 149 } 150 } 151 if ( mod == 0 ) { 152 return out.toByteArray(); 153 } 154 else { 155 return null; 156 } 157 } 158 159 /** 160 * Encodes a string. 161 * @param in unencoded text string. 162 * @return encoded string or null 163 */ 164 public static String encodeString(String in) { 165 if (in == null) { 166 return null; 167 } 168 if (in.length() == 0) { 169 return ""; 170 } 171 StringBuffer out = new StringBuffer( in.length() << 3 ); 172 int cin; 173 for ( int i=0; i<in.length(); ++i ) { 174 cin = in.charAt( i ); 175 if ( cin < 256 ) { 176 out.append( encodeTab[ (cin >> 4) & 15 ] ); 177 out.append( encodeTab[ cin & 15 ] ); 178 } 179 else { 180 return null; 181 } 182 } 183 return out.toString(); 184 } 185 186 /** 187 * Encodes a byte array. 188 * @param in byte array. 189 * @return encoded string or null 190 */ 191 public static String encodeArray(byte[] in) { 192 if (in == null) { 193 return null; 194 } 195 if (in.length == 0) { 196 return ""; 197 } 198 StringBuffer out = new StringBuffer( in.length << 3 ); 199 for ( int i=0; i<in.length; ++i ) { 200 out.append( encodeTab[ (in[ i ] >> 4) & 15 ] ); 201 out.append( encodeTab[ in[ i ] & 15 ] ); 202 } 203 return out.toString(); 204 } 205 206 /** 207 * Insert regular delimiters in a string. 208 * @param inStr input string 209 * @param width interval width 210 * @param delimiter delimit character 211 * @return input string with delimiters inserted at specified intervals 212 */ 213 public static String delimit(String inStr, int width, char delimiter) { 214 if (inStr == null) { 215 return null; 216 } 217 if (inStr.length() == 0) { 218 return ""; 219 } 220 if ( width <= 0 ) { 221 return inStr; 222 } 223 StringBuffer outSb = new StringBuffer( inStr.length() + (inStr.length() + width - 1) / width ); 224 int idx = 0; 225 int lIdx = width; 226 while ( idx < inStr.length() ) { 227 if ( idx == lIdx ) { 228 outSb.append( delimiter ); 229 lIdx += width; 230 } 231 outSb.append( inStr.charAt( idx++ ) ); 232 } 233 return outSb.toString(); 234 } 235 236}