Source code for /engineering/autohit-2003/src/autohit/vm/process/StringProcessors.javaOriginal file StringProcessors.java
   1 /**
   2  * AUTOHIT 2003
   3  * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
   4  * 
   5  * This program is free software; you can redistribute it and/or modify 
   6  * it under the terms of the GNU General Public License as published by 
   7  * the Free Software Foundation; either version 2 of the License, or (at
   8  * your option) any later version.
   9  * This program is distributed in the hope that it will be useful, but
  10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12  * more details.
  13  * 
  14  * You should have received a copy of the GNU General Public License along
  15  * with this program; if not, write to the Free Software Foundation, Inc.,
  16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17  *
  18  * Additional license information can be found in the documentation.
  19  * @author Erich P Gatejen
  20  */
  21 package autohit.vm.process;
  22 
  23 import java.io.BufferedInputStream;
  24 import java.io.BufferedOutputStream;
  25 import java.io.InputStream;
  26 import java.io.OutputStream;
  27 import java.io.StringReader;
  28 import java.io.StringWriter;
  29 
  30 import autohit.common.Constants;
  31 import autohit.vm.VMCore;
  32 import autohit.vm.VMException;
  33 
  34 /**
  35  * String processing routines.
  36  * 
  37  * @author Erich P. Gatejen
  38  * @version 1.0 <i>Version History </i> <code>EPG - Rewrite - 13Sep03</code>
  39  */
  40 public class StringProcessors {
  41 
  42 	private final static int STATE_FREE = 0;
  43 	private final static int STATE_VAR_ONE = 1;
  44 	private final static int STATE_VAR_IN = 2;
  45 	private final static int STATE_BUFFER_ONE = 3;
  46 	private final static int STATE_BUFFER_IN = 4;
  47 	private final static int STATE_UNIOBJ_ONE = 5;
  48 	private final static int STATE_UNIOBJ_IN = 6;
  49 
  50 	/**
  51 	 * Process String (as a byte stream) to Core (as a byte stream). If there is a problem, you'll get a VMException.
  52 	 * @param s
  53 	 *            String to eval
  54 	 * @param core
  55 	 *            The Core to use
  56 	 * @return The completed string
  57 	 * @throws VMException
  58 	 */
  59 	public static void evalStreams2Core(InputStream in, OutputStream out, VMCore core)
  60 			throws Exception {
  61 
  62 		StringBuffer working = null;
  63 		String result = null;
  64 		String variable;
  65 		Object thingthang;
  66 		int state = STATE_FREE;
  67 
  68 		BufferedInputStream bin = new BufferedInputStream(in);
  69 		BufferedOutputStream bout = new BufferedOutputStream(out);
  70 		int current = bin.read();
  71 		while (current >= 0) {
  72 
  73 			switch (state) {
  74 
  75 				case STATE_FREE :
  76 					switch (current) {
  77 						case Constants.VARIABLE :
  78 							state = STATE_VAR_ONE;
  79 							break;
  80 						case Constants.UNIOBJECT :
  81 							state = STATE_UNIOBJ_ONE;
  82 							break;
  83 						case Constants.BUFFER :
  84 							state = STATE_BUFFER_ONE;
  85 							break;
  86 						default :
  87 							bout.write(current);
  88 							break;
  89 					}
  90 					break;
  91 
  92 				case STATE_VAR_ONE :
  93 					switch (current) {
  94 						case Constants.VARIABLE :
  95 							// escaped
  96 							bout.write(Constants.VARIABLE);
  97 							state = STATE_FREE;
  98 							break;
  99 						case Constants.UNIOBJECT :
 100 						case Constants.BUFFER :
 101 						default :
 102 							working = new StringBuffer();
 103 							working.append((char) current);
 104 							state = STATE_VAR_IN;
 105 							break;
 106 					}
 107 					break;
 108 
 109 				case STATE_VAR_IN :
 110 					switch (current) {
 111 						case Constants.VARIABLE :
 112 							variable = working.toString();
 113 							if (core.exists(variable)) {
 114 								thingthang = core.fetch(variable);
 115 								if (thingthang instanceof String) {
 116 									bout.write( ((String)(thingthang)).getBytes() );
 117 								} else {
 118 									//	Blech! Something bad in this object
 119 									throw new VMException(
 120 											"Not an evaluatable type in variable.  name="
 121 													+ working,
 122 											VMException.CODE_VM_PROCESSOR_ERROR);
 123 								}
 124 							}
 125 							state = STATE_FREE;
 126 							break;
 127 						case Constants.UNIOBJECT :
 128 						case Constants.BUFFER :
 129 						default :
 130 							working.append((char) current);
 131 							break;
 132 					}
 133 					break;
 134 
 135 				case STATE_BUFFER_ONE :
 136 					switch (current) {
 137 						case Constants.BUFFER :
 138 							bout.write(Constants.BUFFER);
 139 							state = STATE_FREE;
 140 							break;
 141 						case Constants.VARIABLE :
 142 						case Constants.UNIOBJECT :
 143 						default :
 144 							working = new StringBuffer();
 145 							working.append((char) current);
 146 							state = STATE_BUFFER_IN;
 147 							break;
 148 					}
 149 					break;
 150 
 151 				case STATE_BUFFER_IN :
 152 					switch (current) {
 153 						case Constants.BUFFER :
 154 							variable = working.toString();
 155 							if (core.exists(variable)) {
 156 								thingthang = core.fetch(variable);
 157 								if (thingthang instanceof StringBuffer) {
 158 									bout.write( ((StringBuffer)(thingthang)).toString().getBytes() );
 159 								} else {
 160 									//	Blech! Something bad in this object
 161 									throw new VMException(
 162 											"Not an evaluatable type in buffer..  name="
 163 													+ working,
 164 											VMException.CODE_VM_PROCESSOR_ERROR);
 165 								}
 166 							}
 167 							state = STATE_FREE;
 168 							break;
 169 						case Constants.UNIOBJECT :
 170 						case Constants.VARIABLE :
 171 						default :
 172 							working.append((char) current);
 173 							break;
 174 					}
 175 					break;
 176 
 177 				case STATE_UNIOBJ_ONE :
 178 					switch (current) {
 179 						case Constants.UNIOBJECT :
 180 							bout.write(Constants.UNIOBJECT);
 181 							state = STATE_FREE;
 182 							break;
 183 						case Constants.VARIABLE :
 184 						case Constants.BUFFER :
 185 						default :
 186 							//working.append((char)current);
 187 							state = STATE_UNIOBJ_IN; // THIS WILL BE AN ERROR
 188 							break;
 189 					}
 190 					break;
 191 
 192 				case STATE_UNIOBJ_IN :
 193 					switch (current) {
 194 
 195 						case Constants.UNIOBJECT :
 196 							throw new VMException(
 197 									"UNIOBJECT not supported in SimVM",
 198 									VMException.CODE_VM_PROCESSOR_FAULT);
 199 						case Constants.VARIABLE :
 200 						case Constants.BUFFER :
 201 						default :
 202 							// IGNORE, SINCE THIS WILL BE AN ERROR.
 203 							break;
 204 					}
 205 					break;
 206 
 207 				default :
 208 					throw new VMException(
 209 							"evalString2Core hit impossible state.  state="
 210 									+ state,
 211 							VMException.CODE_VM_SOFTWARE_DETECTED_FAULT);
 212 
 213 			}
 214 			current = bin.read();
 215 		}
 216 
 217 		//CHECK STATES
 218 		switch (state) {
 219 			case STATE_FREE :
 220 				// HAPPY HAPPY
 221 				break;
 222 			case STATE_VAR_ONE :
 223 			case STATE_VAR_IN :
 224 				String vmessage;
 225 				if (working.length() > 30) {
 226 					vmessage = new String("Unbounded VARIABLE (oversize) '"
 227 							+ working.toString().substring(30) + "'");
 228 				} else {
 229 					vmessage = new String("Unbounded VARIABLE '"
 230 							+ working.toString() + "'");
 231 				}
 232 				throw new VMException(vmessage,
 233 						VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 234 
 235 			case STATE_BUFFER_ONE :
 236 			case STATE_BUFFER_IN :
 237 				String bmessage;
 238 				if (working.length() > 30) {
 239 					bmessage = new String("Unbounded BUFFER (oversize) '"
 240 							+ working.toString().substring(30) + "'");
 241 				} else {
 242 					bmessage = new String("Unbounded BUFFER '"
 243 							+ working.toString() + "'");
 244 				}
 245 				throw new VMException(bmessage,
 246 						VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 247 
 248 			case STATE_UNIOBJ_ONE :
 249 			case STATE_UNIOBJ_IN :
 250 				String umessage;
 251 				if (working.length() > 30) {
 252 					umessage = new String("Unbounded UNIOBJ (oversize) '"
 253 							+ working.toString().substring(30) + "'");
 254 				} else {
 255 					umessage = new String("Unbounded UNIOBJ '"
 256 							+ working.toString() + "'");
 257 				}
 258 				throw new VMException(umessage,
 259 						VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 260 			default :
 261 				throw new VMException(
 262 						"evalString2Core hit impossible state.  state=" + state,
 263 						VMException.CODE_VM_SOFTWARE_DETECTED_FAULT);
 264 		}
 265 		bout.flush();
 266 		
 267 	}
 268 
 269 	/**
 270 	 * Process String to Core (as a character stream). If there is a problem, you'll get a VMException.
 271 	 * 
 272 	 * @param s
 273 	 *            String to eval
 274 	 * @param core
 275 	 *            The Core to use
 276 	 * @return The completed string
 277 	 * @throws VMException
 278 	 */
 279 	public static String evalString2Core(String s, VMCore core)
 280 			throws Exception {
 281 
 282 		StringBuffer working = null;
 283 		String result = null;
 284 		String variable;
 285 		Object thingthang;
 286 		int state = STATE_FREE;
 287 
 288 		StringReader rin = new StringReader(s);
 289 		StringWriter rout = new StringWriter();
 290 		int current = rin.read();
 291 		while (current >= 0) {
 292 
 293 			switch (state) {
 294 
 295 				case STATE_FREE :
 296 					switch (current) {
 297 						case Constants.VARIABLE :
 298 							state = STATE_VAR_ONE;
 299 							break;
 300 						case Constants.UNIOBJECT :
 301 							state = STATE_UNIOBJ_ONE;
 302 							break;
 303 						case Constants.BUFFER :
 304 							state = STATE_BUFFER_ONE;
 305 							break;
 306 						default :
 307 							rout.write(current);
 308 							break;
 309 					}
 310 					break;
 311 
 312 				case STATE_VAR_ONE :
 313 					switch (current) {
 314 						case Constants.VARIABLE :
 315 							// escaped
 316 							rout.write(Constants.VARIABLE);
 317 							state = STATE_FREE;
 318 							break;
 319 						case Constants.UNIOBJECT :
 320 						case Constants.BUFFER :
 321 						default :
 322 							working = new StringBuffer();
 323 							working.append((char) current);
 324 							state = STATE_VAR_IN;
 325 							break;
 326 					}
 327 					break;
 328 
 329 				case STATE_VAR_IN :
 330 					switch (current) {
 331 						case Constants.VARIABLE :
 332 							variable = working.toString();
 333 							if (core.exists(variable)) {
 334 								thingthang = core.fetch(variable);
 335 								if (thingthang instanceof String) {
 336 									rout.write((String) (thingthang));
 337 								} else {
 338 									//	Blech! Something bad in this object
 339 									throw new VMException(
 340 											"Not an evaluatable type in variable.  name="
 341 													+ working,
 342 											VMException.CODE_VM_PROCESSOR_ERROR);
 343 								}
 344 							}
 345 							state = STATE_FREE;
 346 							break;
 347 						case Constants.UNIOBJECT :
 348 						case Constants.BUFFER :
 349 						default :
 350 							working.append((char) current);
 351 							break;
 352 					}
 353 					break;
 354 
 355 				case STATE_BUFFER_ONE :
 356 					switch (current) {
 357 						case Constants.BUFFER :
 358 							rout.write(Constants.BUFFER);
 359 							state = STATE_FREE;
 360 							break;
 361 						case Constants.VARIABLE :
 362 						case Constants.UNIOBJECT :
 363 						default :
 364 							working = new StringBuffer();
 365 							working.append((char) current);
 366 							state = STATE_BUFFER_IN;
 367 							break;
 368 					}
 369 					break;
 370 
 371 				case STATE_BUFFER_IN :
 372 					switch (current) {
 373 						case Constants.BUFFER :
 374 							variable = working.toString();
 375 							if (core.exists(variable)) {
 376 								thingthang = core.fetch(variable);
 377 								if (thingthang instanceof StringBuffer) {
 378 									rout.write(((StringBuffer) (thingthang))
 379 											.toString());
 380 								} else {
 381 									//	Blech! Something bad in this object
 382 									throw new VMException(
 383 											"Not an evaluatable type in buffer..  name="
 384 													+ working,
 385 											VMException.CODE_VM_PROCESSOR_ERROR);
 386 								}
 387 							}
 388 							state = STATE_FREE;
 389 							break;
 390 						case Constants.UNIOBJECT :
 391 						case Constants.VARIABLE :
 392 						default :
 393 							working.append((char) current);
 394 							break;
 395 					}
 396 					break;
 397 
 398 				case STATE_UNIOBJ_ONE :
 399 					switch (current) {
 400 						case Constants.UNIOBJECT :
 401 							rout.write(Constants.UNIOBJECT);
 402 							state = STATE_FREE;
 403 							break;
 404 						case Constants.VARIABLE :
 405 						case Constants.BUFFER :
 406 						default :
 407 							//working.append((char)current);
 408 							state = STATE_UNIOBJ_IN; // THIS WILL BE AN ERROR
 409 							break;
 410 					}
 411 					break;
 412 
 413 				case STATE_UNIOBJ_IN :
 414 					switch (current) {
 415 
 416 						case Constants.UNIOBJECT :
 417 							throw new VMException(
 418 									"UNIOBJECT not supported in SimVM",
 419 									VMException.CODE_VM_PROCESSOR_FAULT);
 420 						case Constants.VARIABLE :
 421 						case Constants.BUFFER :
 422 						default :
 423 							// IGNORE, SINCE THIS WILL BE AN ERROR.
 424 							break;
 425 					}
 426 					break;
 427 
 428 				default :
 429 					throw new VMException(
 430 							"evalString2Core hit impossible state.  state="
 431 									+ state,
 432 							VMException.CODE_VM_SOFTWARE_DETECTED_FAULT);
 433 
 434 			}
 435 			current = rin.read();
 436 		}
 437 
 438 		//CHECK STATES
 439 		switch (state) {
 440 			case STATE_FREE :
 441 				result = rout.toString();
 442 				break;
 443 			case STATE_VAR_ONE :
 444 			case STATE_VAR_IN :
 445 				String vmessage;
 446 				if (working.length() > 30) {
 447 					vmessage = new String("Unbounded VARIABLE (oversize) '"
 448 							+ working.toString().substring(30) + "'");
 449 				} else {
 450 					vmessage = new String("Unbounded VARIABLE '"
 451 							+ working.toString() + "'");
 452 				}
 453 				throw new VMException(vmessage,
 454 						VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 455 
 456 			case STATE_BUFFER_ONE :
 457 			case STATE_BUFFER_IN :
 458 				String bmessage;
 459 				if (working.length() > 30) {
 460 					bmessage = new String("Unbounded BUFFER (oversize) '"
 461 							+ working.toString().substring(30) + "'");
 462 				} else {
 463 					bmessage = new String("Unbounded BUFFER '"
 464 							+ working.toString() + "'");
 465 				}
 466 				throw new VMException(bmessage,
 467 						VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 468 
 469 			case STATE_UNIOBJ_ONE :
 470 			case STATE_UNIOBJ_IN :
 471 				String umessage;
 472 				if (working.length() > 30) {
 473 					umessage = new String("Unbounded UNIOBJ (oversize) '"
 474 							+ working.toString().substring(30) + "'");
 475 				} else {
 476 					umessage = new String("Unbounded UNIOBJ '"
 477 							+ working.toString() + "'");
 478 				}
 479 				throw new VMException(umessage,
 480 						VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 481 			default :
 482 				throw new VMException(
 483 						"evalString2Core hit impossible state.  state=" + state,
 484 						VMException.CODE_VM_SOFTWARE_DETECTED_FAULT);
 485 		}
 486 		return result;
 487 
 488 	}
 489 
 490 	/**
 491 	 * Process String to Core. If there is a problem, you'll get a VMException.
 492 	 * OLD VERSION
 493 	 * 
 494 	 * @param s
 495 	 *            String to eval
 496 	 * @param core
 497 	 *            The Core to use
 498 	 * @return The completed string
 499 	 * @throws VMException
 500 	 */
 501 	public static String evalString2CoreOLD(String s, VMCore core)
 502 			throws Exception {
 503 
 504 		StringBuffer buff = new StringBuffer();
 505 		String result = null;
 506 		String working;
 507 		Object thingthang;
 508 		int end = s.length();
 509 		int otherside;
 510 
 511 		try {
 512 
 513 			for (int i = 0; i < end; i++) {
 514 
 515 				switch (s.charAt(i)) {
 516 
 517 					case Constants.VARIABLE :
 518 						otherside = s.indexOf(Constants.VARIABLE, i + 1);
 519 						if ((otherside < 0) || (otherside < i)) {
 520 							throw new VMException(
 521 									"Unbounded VARIABLE",
 522 									VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 523 						}
 524 						if (otherside == (i + 1)) {
 525 							//escaped char
 526 							buff.append(Constants.VARIABLE);
 527 							i++; //skip escaped
 528 						} else {
 529 							working = s.substring(i + 1, otherside);
 530 							i = i + working.length() + 1;
 531 
 532 							if (core.exists(working)) {
 533 								thingthang = core.fetch(working);
 534 								if (thingthang instanceof String) {
 535 									buff.append((String) thingthang);
 536 								} else {
 537 									//	Blech! Something bad in this object
 538 									throw new VMException(
 539 											"Not an evaluatable type in variable.  name="
 540 													+ working,
 541 											VMException.CODE_VM_PROCESSOR_ERROR);
 542 								}
 543 							} //else {
 544 							// The variable doesn't exist. FAULT.
 545 							//	throw new Exception(
 546 							//		"Variable does not exist. name="
 547 							//			+ working);
 548 							//}
 549 						}
 550 						break;
 551 
 552 					case Constants.UNIOBJECT :
 553 						if ((i + 1 < end)
 554 								&& (s.charAt(i + 1) == Constants.UNIOBJECT)) {
 555 							//escaped char
 556 							buff.append(Constants.UNIOBJECT);
 557 							i++; //skip escaped
 558 						} else {
 559 							throw new VMException(
 560 									"UNIOBJECT not supported in SimVM",
 561 									VMException.CODE_VM_PROCESSOR_FAULT);
 562 						}
 563 						break;
 564 
 565 					case Constants.BUFFER :
 566 						otherside = s.indexOf(Constants.BUFFER, i + 1);
 567 						if ((otherside < 0) || (otherside < i)) {
 568 							throw new VMException(
 569 									"Unbounded BUFFER name",
 570 									VMException.CODE_VM_PROCESSOR_ERROR_UNBOUNDED);
 571 						}
 572 						if (otherside == (i + 1)) {
 573 							//escaped char
 574 							buff.append(Constants.BUFFER);
 575 							i++; //skip escaped
 576 						} else {
 577 							working = s.substring(i + 1, otherside);
 578 							i = i + working.length() + 1;
 579 
 580 							if (core.exists(working)) {
 581 								thingthang = core.fetch(working);
 582 								if (thingthang instanceof StringBuffer) {
 583 									buff.append(((StringBuffer) thingthang)
 584 											.toString());
 585 								} else {
 586 									//	Blech! Something bad in this object
 587 									throw new VMException(
 588 											"Not an evaluatable type in buffer.  name="
 589 													+ working,
 590 											VMException.CODE_VM_PROCESSOR_ERROR_NOTFOUND);
 591 								}
 592 							} else {
 593 								// The variable doesn't exist. FAULT.
 594 								throw new VMException(
 595 										"Buffer does not exist.  name="
 596 												+ working,
 597 										VMException.CODE_VM_PROCESSOR_ERROR_NOTFOUND);
 598 							}
 599 						}
 600 						break;
 601 
 602 					default :
 603 						buff.append(s.charAt(i));
 604 				}
 605 			}
 606 
 607 			// return it
 608 			result = buff.toString();
 609 
 610 		} catch (VMException ev) {
 611 			throw ev;
 612 		} catch (Exception ee) {
 613 			throw new VMException("Exception while evaluating.  message="
 614 					+ ee.getMessage(),
 615 					VMException.CODE_VM_PROCESSOR_ERROR_NOTFOUND, ee);
 616 		}
 617 		return result;
 618 
 619 	}
 620 
 621 }