Pretty much streamlined Skin parsing and rendering,

trying to reduce the number of objects created.
This commit is contained in:
hns 2002-05-15 17:18:32 +00:00
parent e618c5c8a2
commit 1085f83d02

View file

@ -13,15 +13,17 @@ import java.io.*;
import java.util.*; import java.util.*;
/** /**
* This represents a Helma skin, i.e. a template created from JavaScript. It uses the request path array * This represents a Helma skin, i.e. a template created from containing Macro tags
* from the RequestEvaluator object to resolve dynamic tokens. * that will be dynamically evaluated.. It uses the request path array
* from the RequestEvaluator object to resolve Macro handlers by type name.
*/ */
public class Skin { public class Skin {
Object[] parts; Macro[] parts;
Application app; Application app;
String source; char[] source;
int sourceLength;
HashSet sandbox; HashSet sandbox;
/** /**
@ -37,48 +39,55 @@ public class Skin {
public Skin (String content, Application app, HashSet sandbox) { public Skin (String content, Application app, HashSet sandbox) {
this.app = app; this.app = app;
this.sandbox = sandbox; this.sandbox = sandbox;
parse (content); source = content.toCharArray ();
sourceLength = source.length;
parse ();
}
/**
* Create a skin without any restrictions on the macros from a char array.
*/
public Skin (char[] content, int length, Application app) {
this.app = app;
this.sandbox = null;
this.source = content;
this.sourceLength = length;
parse ();
} }
/** /**
* Parse a skin object from source text * Parse a skin object from source text
*/ */
public void parse (String content) { private void parse () {
this.source = content;
ArrayList partBuffer = new ArrayList (); ArrayList partBuffer = new ArrayList ();
int l = content.length ();
char cnt[] = new char[l];
content.getChars (0, l, cnt, 0);
int lastIdx = 0; int start = 0;
for (int i = 0; i < l-1; i++) { for (int i = 0; i < sourceLength-1; i++) {
if (cnt[i] == '<' && cnt[i+1] == '%') { if (source[i] == '<' && source[i+1] == '%') {
// found macro start tag
int j = i+2; int j = i+2;
while (j < l-1 && (cnt[j] != '%' || cnt[j+1] != '>')) { // search macr end tag
while (j < sourceLength-1 && (source[j] != '%' || source[j+1] != '>')) {
j++; j++;
} }
if (j > i+2) { if (j > i+2) {
if (i - lastIdx > 0) partBuffer.add (new Macro (i, j+2));
partBuffer.add (new String (cnt, lastIdx, i - lastIdx)); start = j+2;
String macrotext = new String (cnt, i+2, (j-i)-2);
partBuffer.add (new Macro (macrotext));
lastIdx = j+2;
} }
i = j+1; i = j+1;
} }
} }
if (lastIdx < l)
partBuffer.add (new String (cnt, lastIdx, l - lastIdx));
parts = partBuffer.toArray (); parts = new Macro[partBuffer.size()];
partBuffer.toArray (parts);
} }
/** /**
* Get the raw source text this skin was parsed from * Get the raw source text this skin was parsed from
*/ */
public String getSource () { public String getSource () {
return source; return new String (source, 0, sourceLength);
} }
/** /**
@ -87,14 +96,17 @@ public class Skin {
public void render (RequestEvaluator reval, Object thisObject, HashMap paramObject) throws RedirectException { public void render (RequestEvaluator reval, Object thisObject, HashMap paramObject) throws RedirectException {
if (parts == null) if (parts == null)
return; reval.res.writeCharArray (source, 0, sourceLength);
int written = 0;
for (int i=0; i<parts.length; i++) { for (int i=0; i<parts.length; i++) {
if (parts[i] instanceof Macro) if (parts[i].start > written)
((Macro) parts[i]).render (reval, thisObject, paramObject); reval.res.writeCharArray (source, written, parts[i].start-written);
else parts[i].render (reval, thisObject, paramObject);
reval.res.write (parts[i]); written = parts[i].end;
} }
if (written < sourceLength)
reval.res.writeCharArray (source, written, sourceLength-written);
} }
/** /**
@ -128,56 +140,56 @@ public class Skin {
class Macro { class Macro {
int start, end;
String handler; String handler;
String name; String name;
String fullname; String fullname;
HashMap parameters; HashMap parameters;
public Macro (String str) { public Macro (int start, int end) {
this.start = start;
this.end = end;
parameters = new HashMap (); parameters = new HashMap ();
int l = str.length ();
char cnt[] = new char[l];
str.getChars (0, l, cnt, 0);
int state = HANDLER; int state = HANDLER;
boolean escape = false; boolean escape = false;
char quotechar = '\u0000'; char quotechar = '\u0000';
String lastParamName = null; String lastParamName = null;
StringBuffer b = new StringBuffer(); StringBuffer b = new StringBuffer();
for (int i=0; i<l; i++) { for (int i=start+2; i<end-2; i++) {
switch (cnt[i]) { switch (source[i]) {
case '.': case '.':
if (state == HANDLER) { if (state == HANDLER) {
handler = b.toString ().trim(); handler = b.toString ().trim();
b.setLength (0); b.setLength (0);
state = MACRO; state = MACRO;
} else } else
b.append (cnt[i]); b.append (source[i]);
break; break;
case '\\': case '\\':
if (escape) if (escape)
b.append (cnt[i]); b.append (source[i]);
escape = !escape; escape = !escape;
break; break;
case '"': case '"':
case '\'': case '\'':
if (!escape && state == PARAMVALUE) { if (!escape && state == PARAMVALUE) {
if (quotechar == cnt[i]) { if (quotechar == source[i]) {
parameters.put (lastParamName, b.toString()); parameters.put (lastParamName, b.toString());
lastParamName = null; lastParamName = null;
b.setLength (0); b.setLength (0);
state = PARAMNAME; state = PARAMNAME;
quotechar = '\u0000'; quotechar = '\u0000';
} else if (quotechar == '\u0000') { } else if (quotechar == '\u0000') {
quotechar = cnt[i]; quotechar = source[i];
b.setLength (0); b.setLength (0);
} else } else
b.append (cnt[i]); b.append (source[i]);
} else } else
b.append (cnt[i]); b.append (source[i]);
escape = false; escape = false;
break; break;
case ' ': case ' ':
@ -195,7 +207,7 @@ public class Skin {
b.setLength (0); b.setLength (0);
state = PARAMNAME; state = PARAMNAME;
} else if (state == PARAMVALUE) } else if (state == PARAMVALUE)
b.append (cnt[i]); b.append (source[i]);
else else
b.setLength (0); b.setLength (0);
break; break;
@ -205,10 +217,10 @@ public class Skin {
b.setLength (0); b.setLength (0);
state = PARAMVALUE; state = PARAMVALUE;
} else } else
b.append (cnt[i]); b.append (source[i]);
break; break;
default: default:
b.append (cnt[i]); b.append (source[i]);
escape = false; escape = false;
} }
} }
@ -415,7 +427,6 @@ public class Skin {
} }
} }