1 /* $RCSfile$ 2 * $Author$ 3 * $Date$ 4 * $Revision$ 5 * 6 * Copyright (C) 2006 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23 * 02110-1301, USA. 24 */ 25 26 package org.jmol.util; 27 28 import javajs.util.PT; 29 30 import javajs.util.BS; 31 32 public class Parser { 33 34 /** 35 * parses a "dirty" string for floats. If there are non-float tokens, 36 * they are ignored. A bitset is used to assign values only to specific 37 * atoms in the set, not changing the values of the data array for other atoms. 38 * thus, a data set can be incrementally added to in this way. 39 * 40 * @param str the string to parse 41 * @param bs the atom positions to assign 42 * @param data the (sparce) array to fill 43 * @return number of floats 44 */ parseStringInfestedFloatArray(String str, BS bs, float[] data)45 public static int parseStringInfestedFloatArray(String str, BS bs, float[] data) { 46 return Parser.parseFloatArrayBsData(PT.getTokens(str), bs, data); 47 } 48 parseFloatArrayBsData(String[] tokens, BS bs, float[] data)49 public static int parseFloatArrayBsData(String[] tokens, BS bs, float[] data) { 50 int len = data.length; 51 int nTokens = tokens.length; 52 int n = 0; 53 int max = 0; 54 boolean haveBitSet = (bs != null); 55 for (int i = (haveBitSet ? bs.nextSetBit(0) : 0); i >= 0 && i < len && n < nTokens; i = (haveBitSet ? bs.nextSetBit(i + 1) : i + 1)) { 56 float f; 57 while (Float.isNaN(f = PT.parseFloat(tokens[n++])) 58 && n < nTokens) { 59 } 60 if (!Float.isNaN(f)) 61 data[(max = i)] = f; 62 if (n == nTokens) 63 break; 64 } 65 return max + 1; 66 } 67 68 /** 69 * the major lifter here. 70 * 71 * @param str string containing the data 72 * @param bs selects specific rows of the data 73 * @param fieldMatch a free-format field pointer, or a column pointer 74 * @param fieldMatchColumnCount specifies a column count -- not free-format 75 * @param matchData an array of data to match (atom numbers) 76 * @param field a free-format field pointer, or a column pointer 77 * @param fieldColumnCount specifies a column count -- not free-format 78 * @param data float array to modify or null if size unknown 79 * @param firstLine first line to parse (1 indicates all) 80 * @return data 81 */ parseFloatArrayFromMatchAndField( String str, BS bs, int fieldMatch, int fieldMatchColumnCount, int[] matchData, int field, int fieldColumnCount, float[] data, int firstLine)82 public static float[] parseFloatArrayFromMatchAndField( 83 String str, 84 BS bs, 85 int fieldMatch, 86 int fieldMatchColumnCount, 87 int[] matchData, 88 int field, 89 int fieldColumnCount, 90 float[] data, int firstLine) { 91 float f; 92 int i = -1; 93 boolean isMatch = (matchData != null); 94 int[] lines = markLines(str, (str.indexOf('\n') >= 0 ? '\n' : ';')); 95 int iLine = (firstLine <= 1 || firstLine >= lines.length ? 0 : firstLine - 1); 96 int pt = (iLine == 0 ? 0 : lines[iLine - 1]); 97 int nLines = lines.length; 98 if (data == null) 99 data = new float[nLines - iLine]; 100 int len = data.length; 101 int minLen = (fieldColumnCount <= 0 ? Math.max(field, fieldMatch) : Math 102 .max(field + fieldColumnCount, fieldMatch + fieldMatchColumnCount) - 1); 103 boolean haveBitSet = (bs != null); 104 for (; iLine < nLines; iLine++) { 105 String line = str.substring(pt, lines[iLine]).trim(); 106 pt = lines[iLine]; 107 String[] tokens = (fieldColumnCount <= 0 ? PT.getTokens(line) : null); 108 // check for inappropriate data -- line too short or too few tokens or NaN for data 109 // and parse data 110 if (fieldColumnCount <= 0) { 111 if (tokens.length < minLen 112 || Float.isNaN(f = PT.parseFloat(tokens[field - 1]))) 113 continue; 114 } else { 115 if (line.length() < minLen 116 || Float.isNaN(f = PT.parseFloat(line.substring(field - 1, field 117 + fieldColumnCount - 1)))) 118 continue; 119 } 120 int iData; 121 if (isMatch) { 122 iData = PT.parseInt(tokens == null ? line.substring(fieldMatch - 1, 123 fieldMatch + fieldMatchColumnCount - 1) : tokens[fieldMatch - 1]); 124 // in the fieldMatch column we have an integer pointing into matchData 125 // we replace that number then with the corresponding number in matchData 126 if (iData == Integer.MIN_VALUE || iData < 0 || iData >= len 127 || (iData = matchData[iData]) < 0) 128 continue; 129 // and we set bs to indicate we are updating that value 130 if (haveBitSet) 131 bs.set(iData); 132 } else { 133 // no match data 134 // bs here indicates the specific data elements that need filling 135 if (haveBitSet) 136 i = bs.nextSetBit(i + 1); 137 else 138 i++; 139 if (i < 0 || i >= len) 140 return data; 141 iData = i; 142 } 143 data[iData] = f; 144 //System.out.println("data[" + iData + "] = " + data[iData]); 145 } 146 return data; 147 } 148 fixDataString(String str)149 public static String fixDataString(String str) { 150 str = str.replace(';', str.indexOf('\n') < 0 ? '\n' : ' '); 151 str = PT.trim(str, "\n \t"); 152 str = PT.rep(str, "\n ", "\n"); 153 str = PT.rep(str, "\n\n", "\n"); 154 return str; 155 } 156 markLines(String data, char eol)157 public static int[] markLines(String data, char eol) { 158 int nLines = 0; 159 for (int i = data.length(); --i >=0;) 160 if (data.charAt(i) == eol) 161 nLines++; 162 int[] lines = new int[nLines + 1]; 163 nLines = 0; 164 int pt = 0; 165 while ((pt = data.indexOf(eol, pt)) >= 0) 166 lines[nLines++] = ++pt; 167 lines[nLines] = data.length(); 168 return lines; 169 } 170 171 172 } 173