/*=======================================================
* ApwtclObj.java
*
* "A Tcl like language implementation in Java named APWTCL
* ((Java) Arnulf's Preferred Web Tcl)"
*
* APWTCL ApwtclObj class
*
* Released under same BSD license as Tcl.
* (Tcl BSD license found at <http://www.tcl.tk/software/tcltk/license.html>)
*
* Copyright 2012 Arnulf P. Wiedemann
*
*/
package org.apwtcl.lang;
//#if memdebug
//#endif
import java.util.ArrayList;
import java.util.HashMap;
import org.apwtcl.lang.objtype.*;
import com.sun.xml.internal.ws.util.StringUtils;
public class ApwtclObj extends Token implements Debug {
//#if memdebug
/* keep track on how many ApwtclObjs have been created */
static long oid = 0;
//#endif
public static ApwtclObj free_obj_list = null;
public static ApwtclObj live_obj_list = null;
public long id;
private Interp interp;
private ApwtclObj next_obj_ptr;
private ApwtclObj prev_obj_ptr;
private ObjTypeBase obj_type_base;
private Object value1;
private Object value2;
private Object value3;
public StringBuffer bytes;
public int len;
public String allocated;
public String freed;
public ArrayList<String> incr_lst;
public ArrayList<String> decr_lst;
public boolean check_allocate;
public int ref_count;
public int obj_type;
/* ==================== ApwtclObj ================================== */
public ApwtclObj(Interp interp) {
this.interp = interp;
++oid;
id = oid;
bytes = new StringBuffer();
len = 0;
allocated = null;
freed = null;
obj_type_base = new ObjTypeBase(interp);
incr_lst = new ArrayList<String>();
decr_lst = new ArrayList<String>();
check_allocate = true;
}
/* ==================== mySelf ================================== */
public String mySelf() {
String str = "ApwtclObj!"+id+"!";
return str;
}
/* ==================== toString ===================================== */
public String toString() {
return getString();
}
/* ==================== toDebugString ===================================== */
public String toDebugString() {
StringBuffer str = new StringBuffer(mySelf()+"\n");
str.append(" ref_count: "+ref_count+"\n");
str.append(" len: "+len+"\n");
str.append(" obj_type: "+getObjTypeString(obj_type)+"\n");
str.append(" allocated: "+allocated+"\n");
str.append(" freed: "+freed+"\n");
str.append(" incr: "+incr_lst+"\n");
str.append(" decr: "+decr_lst+"\n");
str.append(" bytes: "+((bytes == null) ? "<null>" : getString())+"\n");
if (obj_type > 0) {
switch (obj_type) {
case OBJ_TYPE_LIST:
str.append(" list_elem: "+listValue_GetElem()+"\n");
break;
case OBJ_TYPE_INT:
str.append(" value: "+wideValue_GetValue()+"\n");
break;
}
}
return str.toString();
}
/* ==================== arrayValue_GetVarNameObjPtr ================================== */
public ApwtclObj arrayValue_GetVarNameObjPtr() {
return (ApwtclObj)value1;
}
/* ==================== arrayValue_SetVarNameObjPtr ================================== */
public ApwtclObj arrayValue_SetVarNameObjPtr(ApwtclObj var_name_obj_ptr) {
value1 = (Object)var_name_obj_ptr;
return var_name_obj_ptr;
}
/* ==================== arrayValue_GetIndexObjPtr ================================== */
public ApwtclObj arrayValue_GetIndexObjPtr() {
return (ApwtclObj)value2;
}
/* ==================== arrayValue_SetIndexObjPtr ================================== */
public ApwtclObj arrayValue_SetIndexObjPtr(ApwtclObj index_obj_ptr) {
value2 = (Object)index_obj_ptr;
return index_obj_ptr;
}
/* ==================== binaryValue_GetData ================================== */
public Object binaryValue_GetData() {
return value1;
}
/* ==================== binaryValue_SetData ================================== */
public Object binaryValue_SetVarNameObj(Object data) {
value1 = data;
return data;
}
/* ==================== binaryValue_GetLen ================================== */
public int binaryValue_GetLen() {
return (Integer)value2;
}
/* ==================== binaryValue_SetLen ================================== */
public int binaryValue_SetLen(int len) {
value2 = (Object)len;
return len;
}
/* ==================== cmdValue_GetEpoch ================================== */
public int cmdValue_GetEpoch() {
return (Integer)value1;
}
/* ==================== cmdValue_SetEpoch ================================== */
public int cmdValue_SetEpoch(int epoch) {
value1 = epoch;
return epoch;
}
/* ==================== cmdValue_GetResolvedCmdNamePtr ================================== */
public ResolvedCmdName cmdValue_GetResolvedCmdNamePtr() {
return (ResolvedCmdName)value2;
}
/* ==================== cmdValue_SetResolvedCmdNamePtr ================================== */
public ResolvedCmdName cmdValue_SetResolvedCmdNamePtr(ResolvedCmdName cmd_ptr) {
value2 = (Object)cmd_ptr;
return cmd_ptr;
}
/* ==================== doubleValue_GetValue ================================== */
public double doubleValue_GetValue() {
return (Double)value1;
}
/* ==================== doubleValue_SetValue ================================== */
public double doubleValue_SetValue(double val) {
value1 = (Object)((Double)val);
return val;
}
/* ==================== hashValue_GetValue ================================== */
public Object hashValue_GetValue() {
return value1;
}
/* ==================== hashValue_SetValue ================================== */
public Object hashValue_SetValue(Object val) {
value1 = val;
return val;
}
/* ==================== indexValue_GetValue ================================== */
public int indexValue_GetValue() {
return (Integer)value1;
}
/* ==================== indexValue_SetValue ================================== */
public int indexValue_SetValue(int val) {
value1 = (Object)val;
return val;
}
/* ==================== itclClassValue_GetClassDef ================================== */
public ApwtclObj itclClassValue_GetClassDef() {
return (ApwtclObj)value1;
}
/* ==================== itclClassValue_SetClassDef ================================== */
public ApwtclObj itclClassValue_SetClassDef(ApwtclObj class_def) {
value1 = (Object)class_def;
return class_def;
}
/* ==================== itclClassValue_GetClassType ================================== */
public int itclClassValue_GetClassType() {
return (Integer)value2;
}
/* ==================== itclClassValue_SetClassType ================================== */
public int itclClassValue_SetClassType(int class_type) {
value2 = (Object)class_type;
return class_type;
}
/* ==================== itclClassValue_GetClassObjects ================================== */
public ApwtclObj itclClassValue_GetClassObjects() {
return (ApwtclObj)value3;
}
/* ==================== itclClassValue_SetClassObjects ================================== */
public ApwtclObj itclClassValue_SetMaxLen(ApwtclObj class_objects) {
value3 = (ApwtclObj)class_objects;
return class_objects;
}
/* ==================== listValue_GetElem ================================== */
public ArrayList<ApwtclObj> listValue_GetElem() {
return (ArrayList<ApwtclObj>)value1;
}
/* ==================== listValue_SetElem ================================== */
public ArrayList<ApwtclObj> listValue_SetElem(ArrayList<ApwtclObj> elem) {
value1 = (Object)elem;
return elem;
}
/* ==================== listValue_GetLen ================================== */
public int listValue_GetLen() {
return (Integer)value2;
}
/* ==================== listValue_SetLen ================================== */
public int listValue_SetLen(int len) {
value2 = (Object)len;
return len;
}
/* ==================== listValue_GetMaxLen ================================== */
public int listValue_GetMaxLen() {
return (Integer)value3;
}
/* ==================== listValue_SetMaxLen ================================== */
public int listValue_SetMaxLen(int max_len) {
value3 = (Object)max_len;
return max_len;
}
/* ==================== namespaceValue_GetNamespace ================================== */
public ApwtclObj namespaceValue_GetNamespace() {
return (ApwtclObj)value1;
}
/* ==================== namespaceValue_SetNamespace ================================== */
public ApwtclObj namespaceValue_SetNamespace(ApwtclObj namespace) {
value1 = (Object)namespace;
return namespace;
}
/* ==================== namespaceValue_GetFullName ================================== */
public String namespaceValue_GetFullName() {
return (String)value2;
}
/* ==================== namespaceValue_SetFullName ================================== */
public String namespaceValue_SetFullName(String full_name) {
value2 = (Object)full_name;
return full_name;
}
/* ==================== paramInfoValue_GetParams ================================== */
public FunctionArgList paramInfoValue_GetParams() {
return (FunctionArgList)value1;
}
/* ==================== paramInfoValue_SetParams ================================== */
public FunctionArgList paramInfoValue_SetParams(FunctionArgList params) {
value1 = (Object)params;
return params;
}
/* ==================== paramInfoValue_GetOrigParams ================================== */
public FunctionArgList paramInfoValue_GetOrigParams() {
return (FunctionArgList)value2;
}
/* ==================== paramInfoValue_SetOrigParams ================================== */
public FunctionArgList paramInfoValue_SetOrigParams(FunctionArgList orig_params) {
value2 = (Object)orig_params;
return orig_params;
}
/* ==================== ptrAndLongRepValue_GetPtr ================================== */
public ApwtclObj ptrAndLongRepValue_GetPtr() {
return (ApwtclObj)value1;
}
/* ==================== ptrAndLongRepValue_SetPtr ================================== */
public ApwtclObj ptrAndLongRepValue_SetPtr(ApwtclObj ptr) {
value1 = (Object)ptr;
return ptr;
}
/* ==================== ptrAndLongRepValue_GetValue ============================= */
public long ptrAndLongRepValue_GetValue() {
return (Long)value2;
}
/* ==================== ptrAndLongRepValue_SetValue ============================= */
public long ptrAndLongRepValue_SetValue(long val) {
value2 = (Object)val;
return val;
}
/* ==================== ptrValue_GetPtr ================================== */
public Object ptrValue_GetPtr() {
return (Object)value1;
}
/* ==================== ptrValue_SetPtr ================================== */
public Object ptrValue_SetPtr(Object ptr) {
value1 = (Object)ptr;
return ptr;
}
/* ==================== refValue_GetRefPtr ================================== */
public ApwtclObj refValue_GetRefPtr() {
return (ApwtclObj)value1;
}
/* ==================== refValue_SetRefPtr ================================== */
public ApwtclObj refValue_SetRefPtr(ApwtclObj ref_ptr) {
value1 = (Object)ref_ptr;
return ref_ptr;
}
/* ==================== refValue_GetId ================================== */
public int refValue_GetId() {
return (Integer)value2;
}
/* ==================== refValue_SetId ================================== */
public int refValue_SetId(int id) {
value2 = (Object)id;
return id;
}
/* ==================== regexpValue_GetCompre ================================== */
public String regexpValue_GetCompre() {
return (String)value1;
}
/* ==================== regexpValue_SetCompre ================================== */
public String regexpValue_SetCompre(String compre) {
value1 = (Object)compre;
return compre;
}
/* ==================== regexpValue_GetFlags ================================== */
public int regexpValue_GetFlags() {
return (Integer)value2;
}
/* ==================== regexpValue_SetFlags ================================== */
public int regexpValue_SetFlags(int flags) {
value2 = (Object)flags;
return flags;
}
/* ==================== returnCodeValue_GetReturnCode ================================== */
public int returnCodeValue_GetReturnCode() {
return (Integer)value1;
}
/* ==================== returnCodeValue_SetReturnCode ================================== */
public int returnCodeValue_SetReturnCode(int return_code) {
value1 = (Object)return_code;
return return_code;
}
/* ==================== scriptLineValue_GetLine ================================== */
public int scriptLineValue_GetLine() {
return (Integer)value1;
}
/* ==================== scriptLineValue_SetLine ================================== */
public int scriptLineValue_SetLine(int val) {
value1 = (Object)val;
return val;
}
/* ==================== scriptLineValue_GetArgc ================================== */
public int scriptLineValue_GetArgc() {
return (Integer)value2;
}
/* ==================== scriptLineValue_SetArgc ================================== */
public int scriptLineValue_SetArgc(int val) {
value2 = (Object)val;
return val;
}
/* ==================== scriptValue_GetScript ================================== */
public Script scriptValue_GetScript() {
return (Script)value1;
}
/* ==================== scriptValue_SetScript ================================== */
public Script scriptValue_SetScript(Script script) {
value1 = (Object)script;
return script;
}
/* ==================== sourceValue_GetFileNameObj ================================== */
public ApwtclObj sourceValue_GetFileNameObj() {
return (ApwtclObj)value1;
}
/* ==================== sourceValue_SetFileNameObj ================================== */
public ApwtclObj sourceValue_SetFileNameObj(ApwtclObj file_name_obj) {
value1 = (Object)file_name_obj;
return file_name_obj;
}
/* ==================== sourceValue_GetLineNumber ================================== */
public int sourceValue_GetLineNumber() {
return (Integer)value2;
}
/* ==================== sourceValue_SetLineNumber ================================== */
public int sourceValue_SetLineNumber(int line_number) {
value2 = (Object)line_number;
return line_number;
}
/* ==================== strValue_GetCharLength ================================== */
public int strValue_GetCharLength() {
return (Integer)value1;
}
/* ==================== strValue_SetCharLength ================================== */
public int strValue_SetCharLength(int char_length) {
value1 = (Object)char_length;
return char_length;
}
/* ==================== strValue_GetMaxLength ================================== */
public int strValue_GetMaxLength() {
return (Integer)value1;
}
/* ==================== strValue_SetMaxLength ================================== */
public int strValue_SetMaxLength(int max_length) {
value1 = (Object)max_length;
return max_length;
}
/* ==================== twoPtrValue_GetPtr1 ================================== */
public Object twoPtrValue_GetPtr1() {
return value1;
}
/* ==================== twoPtrValue_SetPtr1 ================================== */
public Object twoPtrValue_SetPtr1(Object ptr1) {
value1 = ptr1;
return ptr1;
}
/* ==================== twoPtrValue_GetPtr2 ================================== */
public Object twoPtrValue_GetPtr2() {
return value2;
}
/* ==================== twoPtrValue_SetPtr2 ================================== */
public Object twoPtrValue_SetPtr2(Object ptr2) {
value2 = ptr2;
return ptr2;
}
/* ==================== varValue_GetCallFrame ================================== */
public CallFrame varValue_GetCallFrame() {
return (CallFrame)value1;
}
/* ==================== varValue_SetCallFrame ================================== */
public CallFrame varValue_SetCallFrame(CallFrame call_frame) {
value1 = (Object)call_frame;
return call_frame;
}
/* ==================== varValue_GetNamespace ================================== */
public Namespace varValue_GetNamespace() {
return (Namespace)value2;
}
/* ==================== varValue_SetNamespace ================================== */
public Namespace varValue_SetNamespace(Namespace namespace) {
value2 = (Object)namespace;
return namespace;
}
/* ==================== varValue_GetVarPtr ================================== */
public Variable varValue_GetVarPtr() {
return (Variable)value3;
}
/* ==================== varValue_SetVarPtr ================================== */
public Variable varValue_SetVarPtr(Variable var_ptr) {
value3 = (Object)var_ptr;
return var_ptr;
}
/* ==================== wideValue_GetValue ================================== */
public long wideValue_GetValue() {
return (Long)value1;
}
/* ==================== wideValue_SetValue ================================== */
public long wideValue_SetValue(long val) {
value1 = (Object)val;
return val;
}
/* ==================== updateString ================================== */
public int updateString() {
return OK;
}
/* =========================== newObj ===================================== */
public ApwtclObj newObj() {
ApwtclObj my_obj_ptr;
/* -- Check if there are objects in the free list -- */
if (free_obj_list != null) {
/* -- Unlink the object from the free list -- */
my_obj_ptr = free_obj_list;
free_obj_list = my_obj_ptr.next_obj_ptr;
} else {
/* -- No ready to use objects: allocate a new one -- */
my_obj_ptr = new ApwtclObj(interp);
}
/* Object is returned with ref_count of 0. Every
* kind of GC implemented should take care to don't try
* to scan objects with ref_count == 0. */
my_obj_ptr.ref_count = 0;
/* All the other fields are left not initialized to save time.
* The caller will probably want to set them to the right
* value anyway. */
/* -- Put the object into the live list -- */
my_obj_ptr.prev_obj_ptr = null;
my_obj_ptr.next_obj_ptr = live_obj_list;
if (live_obj_list != null) {
live_obj_list.prev_obj_ptr = my_obj_ptr;
}
live_obj_list = my_obj_ptr;
my_obj_ptr.obj_type = 0;
my_obj_ptr.bytes = null;
return my_obj_ptr;
}
/* ==================== freeNewObj ===================================== */
public void freeNewObj(String where) {
freeObj(where);
freed = where;
}
/* ==================== freeObj ===================================== */
/* Free an Obj. Actually Objs are never freed, but
* just moved to the free obj list, where they will be
* reused by NewObj().
*/
public void freeObj(String where) {
//print("freeObj!"+mySelf()+"!"+obj_type+"!"+getString()+"!");
/* Check if the object was already freed, panic. */
panic(ref_count != 0, "!!! "+mySelf()+" freed with bad ref_count "+ref_count+", type="+getObjTypeString(obj_type)+"!"+toDebugString()+"!");
freeIntRep();
/* Free the string representation */
if (bytes != null) {
bytes = null;
}
/* Unlink the object from the live objects list */
if (prev_obj_ptr != null) {
prev_obj_ptr.next_obj_ptr = next_obj_ptr;
}
if (next_obj_ptr != null) {
next_obj_ptr.prev_obj_ptr = prev_obj_ptr;
}
if (live_obj_list == this) {
live_obj_list = next_obj_ptr;
}
/* Link the object into the free objects list */
prev_obj_ptr = null;
next_obj_ptr = free_obj_list;
if (free_obj_list != null) {
free_obj_list.prev_obj_ptr = this;
}
free_obj_list = this;
ref_count = -1;
freed = where;
}
/* ==================== dumpObjLists ===================================== */
public void dumpObjLists() {
ApwtclObj obj_ptr;
print("live_list!"+live_obj_list+"!");
obj_ptr = live_obj_list;
while (obj_ptr != null) {
print(obj_ptr.toDebugString());
// print(obj_ptr.mySelf());
obj_ptr = obj_ptr.next_obj_ptr;
}
print("free_list!"+free_obj_list+"!");
obj_ptr = free_obj_list;
while (obj_ptr != null) {
print(obj_ptr.toDebugString());
// print(obj_ptr.mySelf());
obj_ptr = obj_ptr.next_obj_ptr;
}
}
/* ==================== invalidateStringRep ===================================== */
public void invalidateStringRep() {
if (bytes != null) {
bytes = null;
}
}
/* ==================== setIntRepPtr ===================================== */
public void setIntRepPtr(Object ptr) {
ptrValue_SetPtr(ptr);
}
/* ==================== freeIntRep ===================================== */
public void freeIntRep() {
obj_type_base.callFreeIntRepProc(obj_type, this);
}
/* ==================== setStringRep ===================================== */
public void setStringRep(ApwtclObj obj_ptr, String str, int len) {
obj_ptr.bytes.append(str);
obj_ptr.len = len;
}
/* ==================== initStringRep ===================================== */
/* Set the initial string representation for an object. */
public void initStringRep(ApwtclObj obj_ptr, String str, int len) {
obj_ptr.bytes.append(str);
obj_ptr.len = len;
}
/* Xdigitval and Odigitval are helper functions for escapeBackslash() */
/* ==================== xdigitval ===================================== */
public int xdigitval(char ch) {
if (ch >= '0' && ch <= '9') {
return ch - '0';
}
if (ch >= 'a' && ch <= 'f') {
return ch - 'a' + 10;
}
if (ch >= 'A' && ch <= 'F') {
return ch - 'A' + 10;
}
return -1;
}
/* ==================== odigitval ===================================== */
public int odigitval(char ch) {
if (ch >= '0' && ch <= '7') {
return ch - '0';
}
return -1;
}
/* ==================== escapeBackslash ================================== */
/* Perform Tcl escape substitution of 's', storing the result
* string into 'dest'. The escaped string is guaranteed to
* be the same length or shorted than the source string.
* Slen is the length of the string at 's', if it's -1 the string
* length will be calculated by the function.
*
* The function returns the length of the resulting string.
*/
public int escapeBackslash(ArrayList<String> dest_ptr, String str, int slen) {
int result;
int i;
int len;
StringBuffer p = new StringBuffer("");
if (slen == -1) {
slen = str.length();
}
for (i = 0; i < slen; i++) {
switch (str.charAt(i)) {
case '\\':
switch (str.charAt(i + 1)) {
case 'b':
p.append("\b");
i++;
break;
case 'f':
p.append("\f");
i++;
break;
case 'n':
p.append("\n");
i++;
break;
case 'r':
p.append("\r");
i++;
break;
case 't':
p.append("\t");
i++;
break;
case 'u':
case 'x':
/* A unicode or hex sequence.
* \u1111 Expect 1-4 hex chars and convert to utf-8.
* \x Expect 1-2 hex chars and convert to hex.
* An invalid sequence means simply the escaped char.
*/
int val = 0;
int k;
i++;
for (k = 0; k < (str.charAt(i) == 'u' ? 4 : 2); k++) {
int c = xdigitval(str.charAt(i + k + 1));
if (c == -1) {
break;
}
val = (val << 4) | c;
}
if (k > 0) {
/* Got a valid sequence, so convert */
if (str.charAt(i) == 'u') {
// p.append(utf8_fromunicode(p, val));
} else {
p.append(val);
}
i += k;
break;
}
/* Not a valid codepoint, just an escaped char */
p.append(str.charAt(i));
break;
case 'v':
p.append(0xb);
i++;
break;
case '\n':
/* Replace all spaces and tabs after backslash newline with a single space*/
p.append(" ");
do {
i++;
} while (str.charAt(i) == ' ' || str.charAt(i) == '\t');
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
/* octal escape */
val = 0;
int c = odigitval(str.charAt(i + 1));
val = c;
c = odigitval(str.charAt(i + 2));
if (c == -1) {
p.append(val);
i++;
break;
}
val = (val * 8) + c;
// c = odigitval(str, i + 3);
if (c == -1) {
p.append(val);
i += 2;
break;
}
val = (val * 8) + c;
p.append(val);
i += 3;
break;
default:
p.append(str.charAt(i + 1));
i++;
break;
}
break;
default:
p.append(str.charAt(i));
break;
}
}
len = p.length();
dest_ptr.add(p.toString());
return len;
}
/* ==================== isShared ================================== */
public boolean isShared() {
return (ref_count > 1);
}
/* ==================== isListObj ================================== */
public boolean isListObj() {
return (obj_type == OBJ_TYPE_LIST);
}
/* ==================== getIntRepPtr ================================== */
public Object getIntRepPtr() {
return ptrValue_GetPtr();
}
/* ==================== incrRefCount ================================== */
public int incrRefCount(String where) {
ref_count++;
if (check_allocate) {
incr_lst.add(where);
}
return ref_count;
}
/* ==================== decrRefCount ================================== */
public int decrRefCount(String where) {
ref_count--;
if (check_allocate) {
decr_lst.add(where);
}
if (ref_count <= 0) {
freeObj(where);
}
return ref_count;
}
/* ==================== getString ===================================== */
public String getString() {
if (bytes == null) {
/* Invalid string repr. Generate it. */
panic(obj_type == 0, "UpdateStringProc called against '<none>' type."+mySelf()+"!");
panic(!obj_type_base.haveUpdateString(obj_type), "UpdateString called against '"+getObjTypeString(obj_type)+"' type.");
obj_type_base.callUpdateString(obj_type, this);
}
return bytes.substring(0, len);
}
/* ==================== getStringLength ===================================== */
public int getStringLength() {
if (bytes == null) {
/* Invalid string repr. Generate it. */
panic(obj_type == 0, "UpdateStringProc called against '<none>' type."+mySelf()+"!");
panic(obj_type_base.haveUpdateString(obj_type), "UpdateString called against '"+getObjTypeString(obj_type)+"' type.");
obj_type_base.callUpdateString(obj_type, this);
}
return len;
}
/* ==================== getStringFromArray ===================================== */
public String getStringFromArray(ArrayList<ApwtclObj> list, int nested) {
ArrayList<String> res = new ArrayList<String>();
String str;
for (int i = 0; i < list.size(); i++) {
str = list.get(i).getString();
if (isList(str) && !isNested(str)) {
res.add("{"+str+"}");
} else {
if (str == "") {
res.add("{}");
} else {
res.add(str);
}
}
}
if (res.size() == 1) {
return res.get(0);
}
StringBuilder sb = new StringBuilder();
for (String s : res){
sb.append(s);
sb.append(" ");
}
return sb.toString();
}
/* ==================== findHashEntry ===================================== */
public ApwtclObj findHashEntry(HashMap<String, ApwtclObj> hash_table, String key) {
return hash_table.get(key);
}
/* ==================== deleteHashEntry ===================================== */
public int deleteHashEntry(HashMap<String, ApwtclObj> hash_table, String key) {
if (hash_table.get(key) == null) {
return ERROR;
}
hash_table.remove(key);
return OK;
}
/* ==================== addHashEntry ===================================== */
public int addHashEntry(HashMap<String, ApwtclObj> hash_table, String key, ApwtclObj val) {
/* Check if the new element already exists. */
if (hash_table.get(key) != null) {
return ERROR;
}
/* stores key */
hash_table.put(key, val);
return OK;
}
/* ==================== concatObj ===================================== */
public ApwtclObj concatObj(int objc, ArrayList<ApwtclObj> objv) {
int i;
/* If all the objects in objv are lists,
* it's possible to return a list as result, that's the
* concatenation of all the lists.
*/
for (i = 0; i < objc; i++) {
if (!objv.get(i).isListObj()) {
break;
}
}
if (i == objc) {
ApwtclObj obj_ptr = interp.list_obj_type.newListObj(null, 0);
for (i = 0; i < objc; i++) {
interp.list_obj_type.listAppendList(obj_ptr, objv.get(i));
}
return obj_ptr;
} else {
/* Else... we have to glue strings together */
int len = 0;
int obj_len;
StringBuffer p;
/* Compute the length */
for (i = 0; i < objc; i++) {
len += objv.get(i).getStringLength();
}
if (objc > 0) {
len += objc - 1;
}
/* Create the string rep, and a string object holding it. */
p = new StringBuffer("");
for (i = 0; i < objc; i++) {
String s = objv.get(i).getString();
int j = 0;
obj_len = objv.get(i).getStringLength();
/* Remove leading space */
while (obj_len > 0 && (s.charAt(j) == ' ' || s.charAt(j) == '\t' || s.charAt(j) == '\n')) {
j++;
obj_len--;
len--;
}
/* And trailing space */
while (obj_len > 0 && (s.charAt(obj_len - 1) == ' ' || s.charAt(obj_len - 1) == '\n' || s.charAt(obj_len - 1) == '\t')) {
/* Handle trailing backslash-space case */
if (obj_len > 1 && s.charAt(obj_len - 2) == '\\') {
break;
}
obj_len--;
len--;
}
p.append(s.substring(j, obj_len));
j += obj_len;
if (obj_len != 0 && i + 1 != objc) {
p.append(" ");
} else {
if (i + 1 != objc) {
/* Drop the space calcuated for this
* element that is instead null. */
len--;
}
}
}
return interp.string_obj_type.newStringObjNoAlloc(p.toString(), len, "OBJ_1");
}
}
/* ==================== duplicateObj ===================================== */
public ApwtclObj duplicateObj() {
ApwtclObj dup_ptr;
dup_ptr = newObj();
if (bytes == null) {
/* Object does not have a valid string representation. */
dup_ptr.bytes = null;
} else {
initStringRep(dup_ptr, bytes.toString(), len);
}
/* By default, the new object has the same type as the old object */
dup_ptr.obj_type = obj_type;
if (obj_type > 0) {
if (!obj_type_base.haveDupInternalRep(obj_type)) {
dup_ptr.value1 = value1;
dup_ptr.value2 = value2;
dup_ptr.value3 = value3;
} else {
/* The dup proc may set a different type, e.g. null */
obj_type_base.callDupInternalRep(obj_type, this, dup_ptr);
}
}
return dup_ptr;
}
/* ==================== utf8_tounicode_case ===================================== */
public int utf8_tounicode_case(char ch, ArrayList<Character> result_ch, int upper) {
/* this is just a dummy right now, real utf8 support is missing !! */
ArrayList<Character> res_ch_ptr = new ArrayList<Character>();
int l = utf8_tounicode(ch, res_ch_ptr);
Character res_ch = res_ch_ptr.get(0);
if (upper != 0) {
result_ch.add(Character.toUpperCase(res_ch));
} else {
result_ch.add(res_ch);
}
return l;
}
/* ==================== utf8_tounicode ===================================== */
public int utf8_tounicode(char ch, ArrayList<Character>result_ch) {
/*
String s = str;
if (s.charCodeAt(0) < 0xc0) {
result_ch.add(s.charAt(0));
return 1;
}
if (s.charCodeAt(0) < 0xe0) {
if ((s.charCodeAt(1) & 0xc0) == 0x80) {
result_ch[0] = string.fromCharCode(((s.charCodeAt(0) & ~0xc0) << 6) | (s.charCodeAt(1) & ~0x80));
return 2;
}
} else {
if (s.charCodeAt(0) < 0xf0) {
if (((str.charCodeAt(1) & 0xc0) == 0x80) && ((strcharCodeAt(2) & 0xc0) == 0x80)) {
result_ch[0] = string.fromCharCode(((s.charCodeAt(0) & ~0xe0) << 12) | ((s.charCodeAt(1) & ~0x80) << 6) | (s.charCodeAt(2) & ~0x80));
return 3;
}
}
}
/* Invalid sequence, so just return the byte */
/* this is just a dummy right now, real utf8 support is missing !! */
result_ch.add(ch);
return 1;
/* this is just a dummy right now, real utf8 support is missing !! */
// result_ch[0] = str.charAt(0);
// return 1;
}
/* ==================== utf8_tounicode ===================================== */
public int utf8_tounicode(String str, ArrayList<Character>result_ch) {
/*
String s = str;
if (s.charCodeAt(0) < 0xc0) {
result_ch.add(s.charAt(0));
return 1;
}
if (s.charCodeAt(0) < 0xe0) {
if ((s.charCodeAt(1) & 0xc0) == 0x80) {
result_ch[0] = string.fromCharCode(((s.charCodeAt(0) & ~0xc0) << 6) | (s.charCodeAt(1) & ~0x80));
return 2;
}
} else {
if (s.charCodeAt(0) < 0xf0) {
if (((str.charCodeAt(1) & 0xc0) == 0x80) && ((strcharCodeAt(2) & 0xc0) == 0x80)) {
result_ch[0] = string.fromCharCode(((s.charCodeAt(0) & ~0xe0) << 12) | ((s.charCodeAt(1) & ~0x80) << 6) | (s.charCodeAt(2) & ~0x80));
return 3;
}
}
}
/* Invalid sequence, so just return the byte */
/*
result_ch.add(ch);
return 1;
/* this is just a dummy right now, real utf8 support is missing !! */
result_ch.add(str.charAt(0));
return 1;
}
/* ==================== utf8_memchr ===================================== */
/*
utf8_memchr: function (str, len, ch) {
var obj = this;
/* need code for UTF8! */
/* now it's without that */
/*
return str.indexOf(ch);
},
/* ==================== utf8_prev_len ===================================== */
public int utf8_prev_len(String str, int len) {
int n = 1;
/* Look up to len chars backward for a start-of-char byte */
// while (--len) {
// if ((str.chatAt(len) & 0x80) == 0) {
// /* Start of a 1-byte char */
// break;
// }
// if ((str.charAt(len) & 0xc0) == 0xc0) {
// /* Start of a multi-byte char */
// break;
// }
// n++;
// }
return n;
}
/* ==================== utf8_length ===================================== */
public int utf8_length(ApwtclObj obj_ptr) {
/* no utf8 support yet !! */
return obj_ptr.getStringLength();
}
/* ==================== utf8_index ===================================== */
public int utf8_index(String str, int index) {
int idx = 0;
while (index-- > 0) {
ArrayList<Character> c_ptr = new ArrayList<Character>();
idx += utf8_tounicode(str.substring(idx), c_ptr);
}
return idx;
}
/* ==================== globMatch ===================================== */
public int globMatch(String pattern, String str, int nocase) {
ArrayList<Character> c = new ArrayList<Character>();
ArrayList<Character> pchar = new ArrayList<Character>();
int i = 0;
int j = 0;
while (i < pattern.length()) {
switch (pattern.charAt(i)) {
case '*':
i++;
while (pattern.charAt(i) == '*') {
i++;
}
if (pattern.charAt(i) == '\0' || i >= pattern.length()) {
return 1; /* match */
}
pattern = pattern.substring(i);
i = 0;
while (str.length() > j) {
/* Recursive call - Does the remaining pattern match anywhere? */
if (globMatch(pattern.substring(i), str.substring(j), nocase) == 1) {
return 1; /* match */
}
j += utf8_tounicode(str.charAt(j), c);
}
return 0; /* no match */
case '?':
j += utf8_tounicode(str.charAt(j), c);
break;
case '[':
j += utf8_tounicode(str.charAt(j), c);
// pattern = JimCharsetMatch(pattern + 1, c, nocase != 0 ? NOCASE : 0);
if (pattern != "") {
return 0;
}
if (pattern.length() <= i) {
/* Ran out of pattern (no ']') */
continue;
}
break;
case '\\':
if (pattern.length() < i) {
i++;
}
/* fall through */
default:
c = new ArrayList<Character>();
pchar = new ArrayList<Character>();
int k = utf8_tounicode_case(str.charAt(j), c, nocase);
str = str.substring(k);
utf8_tounicode_case(pattern.charAt(i), pchar, nocase);
if (pchar.get(0) != c.get(0)) {
return 0;
}
break;
}
i += utf8_tounicode_case(pattern.charAt(0), pchar, nocase);
if (str.length() <= j) {
while (pattern.charAt(i) == '*') {
i++;
}
break;
}
}
if (pattern.length() <= i && str.length() <= j) {
return 1;
}
return 0;
}
/* ==================== stringMatch ===================================== */
public int stringMatch(String str, int nocase) {
return globMatch(getString(), str, nocase);
}
/* ==================== stringMatchObj ===================================== */
public int stringMatchObj(ApwtclObj obj_ptr, int nocase) {
return stringMatch(obj_ptr.getString(), nocase);
}
/* ==================== getSign ===================================== */
public int getSign(long wide_value) {
if (wide_value == 0) {
return 0;
} else {
if (wide_value < 0) {
return -1;
}
return 1;
}
}
/* ==================== stringCompareNoCase ===================================== */
/*
* No-case version.
*
* If maxchars is -1, compares to end of string.
* Otherwise compares at most 'max_chars' characters.
*/
public int stringCompareNoCase(String s1, String s2, int max_chars) {
int idx1 = 0;
int idx2 = 0;
while (idx1 < s1.length() && idx2 < s2.length() && max_chars != 0) {
ArrayList<Character> c1_ptr = new ArrayList<Character>();
ArrayList<Character> c2_ptr = new ArrayList<Character>();
idx1 += utf8_tounicode_case(s1.charAt(idx1), c1_ptr, 1);
idx2 += utf8_tounicode_case(s2.charAt(idx2), c2_ptr, 1);
if (c1_ptr.get(0) != c2_ptr.get(0)) {
char c1 = c1_ptr.get(0);
char c2 = c2_ptr.get(0);
return getSign(c1 - c2);
}
max_chars--;
}
if (max_chars != 0) {
return 0;
}
/* One string or both terminated */
if (idx1 < s1.length()) {
return 1;
}
if (idx2 < s2.length()) {
return -1;
}
return 0;
}
/* ==================== stringCompare ===================================== */
public int stringCompare(String s1, int l1, String s2, int l2) {
int idx1 = 0;
int idx2 = 0;
while (idx1 < l1 && idx2 < l2) {
ArrayList<Character> c1_ptr = new ArrayList<Character>();
ArrayList<Character> c2_ptr = new ArrayList<Character>();
idx1 += utf8_tounicode_case(s1.charAt(idx1), c1_ptr, 1);
idx2 += utf8_tounicode_case(s2.charAt(idx2), c2_ptr, 1);
if (c1_ptr.get(0) != c2_ptr.get(0)) {
char c1 = c1_ptr.get(0);
char c2 = c2_ptr.get(0);
return getSign(c1 - c2);
}
}
/* One string or both terminated */
if (idx1 < l1) {
return 1;
}
if (idx2 < l2) {
return -1;
}
return 0;
}
/* ==================== stringCompareObj ===================================== */
public int stringCompareObj(ApwtclObj second_obj_ptr, int nocase) {
ApwtclObj first_obj_ptr = this;
String s1;
String s2;
int l1;
int l2;
s1 = first_obj_ptr.getString();
l1 = first_obj_ptr.getStringLength();
s2 = second_obj_ptr.getString();
l2 = second_obj_ptr.getStringLength();
if (nocase != 0) {
return stringCompareNoCase(s1, s2, -1);
}
return stringCompare(s1, l1, s2, l2);
}
/* ==================== stringEqObj ===================================== */
public boolean stringEqObj(ApwtclObj second_obj_ptr) {
String a_str;
String b_str;
int a_len;
int b_len;
if (this == second_obj_ptr) {
return true;
}
a_str = getString();
a_len = getStringLength();
b_str = second_obj_ptr.getString();
b_len = second_obj_ptr.getStringLength();
if (a_len != b_len) {
return false;
}
return (a_str == b_str);
}
}