cvmstringtable.java

来自「This is a resource based on j2me embedde」· Java 代码 · 共 365 行

JAVA
365
字号
/* * @(#)CVMStringTable.java	1.38 06/10/22 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */package runtime;import java.util.Enumeration;import consts.Const;import components.*;import vm.*;import util.*;public class CVMStringTable extends vm.StringTable {    CVMStringIntern internTable;    private CVMInitInfo initInfo;    CVMStringTable(CVMInitInfo initInfo)     {	this.initInfo = initInfo;    }        final boolean writeStringData( String dataName, String charArrayClassBlockName, CCodeWriter out ){	int n = arrangeStringData();	if ( n == 0 ) return false; // nothing to do here.	char v[] = new char[n];	this.fillInChars( 0, n, v, 0 );	//	// first typedef the structure we're about to create	/* 	 * The following structure has to reflect CVMArrayOfChar which	 * has a padding field for 64 bit platforms to be sure	 * that the membler elems has the same offset for all	 * CVMArrayOf<type> structures.	 */	out.print("const struct { CVMObjectHeader hdr;\n    CVMJavaInt	length;\n#ifdef CVM_64\n    CVMUint32 pad;\n#endif\n    CVMJavaChar stringData["+n+"]; } ");	out.print( dataName );	out.println( " = {" );	//	// fill in the header information	// hdr.various = {{0}} ??	int hashCode = 0;	out.println("	CVM_ROM_OBJECT_HDR_INIT0("+charArrayClassBlockName+	    ","+hashCode+"),");	out.println("	"+n+",\n#ifdef CVM_64\n	0,\n#endif\n	{");	//	// finally write the char array.	int mod = 0;	for (int i = 0; i < n; i++) { 	    if (mod == 0) 	        out.write('\t');	    out.printHexInt(v[i]);	    out.write(',');	    if (++mod == 12) { 	        out.write('\n');		mod = 0;	    }	} 	if (mod != 0)	    out.write('\n');	out.print(" } };\n\n");	return true;    }    private final static int maxCom = 20;    private static byte cbuf[] = new byte[maxCom + 3];    private void commentary( String s, CCodeWriter out ){	int m = Math.min( maxCom, s.length() );	for ( int i = 0; i < m; i++ ){	    char c = s.charAt(i);	    if ( ' ' <= c && c <= '~' ) {		if (c == '*') {		    /*		     * Prevent damage to C comment by replacing * with ?.		     */		    c = '?';		}		cbuf[i] = (byte) c;	    } else {		cbuf[i] = (byte)'?';	    }	}	out.write( out.commentLeader, 0, out.commentLeader.length );	out.write( cbuf, 0, m );	if ( m < s.length() ){	    out.write('.');	    out.write('.');	    out.write('.');	}	out.write( out.commentTrailer, 0, out.commentTrailer.length );    }    public int writeStrings(CCodeWriter out, String tableName ) {	String dataName = tableName+"_data";	ClassInfo charArrayClass = ClassTable.lookupClass("[C");	if ( charArrayClass == null ){	    System.err.println(Localizer.getString("javacodecompact.cannot_find_array_of_char"));	    return 0;	}	if ( ! writeStringData( dataName, ((CVMClass)(charArrayClass.vmClass)).getNativeName()+"_Classblock" , out ) )	    return 0;	out.println("const CVMUint16 " + tableName + "[] = {");	StringConstant stringTable[] = allStrings();	internTable = new CVMStringIntern( initInfo, stringTable.length );	int currentLength = -1;	int currentLengthCount = -1;	int numCompressedEntries = 0;		for ( int i = 0; i < stringTable.length; i++ ){	    StringConstant s = stringTable[i];	    String string = s.str.string;	    int hashCode = 0;	    if (currentLength != string.length()) {		if (currentLengthCount >= 0) {		    out.println("/* COUNTS:   "+				currentLengthCount+				" instances of "+				currentLength+				"-character-long strings */");		    out.println("\t"+currentLengthCount+", "+				currentLength+",");		    numCompressedEntries++;		}				currentLength = string.length();		currentLengthCount = 0;			    }	    currentLengthCount++;	    out.print("\t");	    commentary(string, out);	    internTable.internStringConstant( s );	}	if (currentLengthCount >= 0) {	    out.println("/* COUNTS:   "+			currentLengthCount+			" instances of "+			currentLength+			"-character-long strings */");	    out.println("\t"+currentLengthCount+", "+			currentLength+",");	    numCompressedEntries++;	}			out.println("};\n\n");	out.println("const int CVM_nROMStringsCompressedEntries = "+numCompressedEntries+";");	return stringTable.length;    }    /*      * Moved global variables to CVMROMGlobals     * That makes it necessary to pass the global header out file into writeInternTable.     */    public void writeStringInternTable( CCodeWriter out, CCodeWriter globalHeaderOut, String tableName, String stringArrayName ){	internTable.writeInternTable( out, globalHeaderOut, tableName, stringArrayName );    }}class CVMInternSegment {    int 	     capacity;    int		     content = 0;    StringConstant   data[];    private static final int primeFactors[] = {	3, 5, 7, 11, 13, 37 };    private static final int nPrimeFactors = primeFactors.length;    CVMInternSegment( int size ){	/*	 * apply our usual emptyness parameter.	 * then make sure its relatively prime to	 * the secondary hash h1, where 1 <= h1 <= 16	 * and also to 37. This means testing against	 * 2, 3, 5, 7, 11, 13, and 37.	 * This loop WILL terminate, because eventually	 * we will hit either a relative prime to all these	 * factors, or an actual prime.	 */	size = ( size*100 ) / 65; 	size |= 1; /* not a multiple of 2 */	boolean changed = true;	while ( changed ) {	    changed = false;	    for ( int i = 0; i < nPrimeFactors; i++ ){		if (size%primeFactors[i] == 0 ){		    size += 2;		    changed = true;		    break; /* out of for loop */		}	    }	}	capacity = size;	data = new StringConstant[ size ];    }    void writeSegment(	String segmentName,	String stringArrayName,	String link,	CCodeWriter out )    {	//	// first typedef the array we're about to create	out.print("const struct { CVM_INTERN_SEGMENT_HEADER\n\tCVMStringICell data[");	out.print( capacity );	out.print( "];\n\tCVMUint8	refCount[" );	out.print( capacity );	out.print( "]; } " );	out.print( segmentName );	out.print(" = {\n    &" );	/* 	 * Moved globals to CVMROMGlobals.	 */	out.print("CVMROMGlobals." + link);	out.print(", ");	out.print(capacity);	out.print(", ");	out.print(content);	out.println(", 1, {");	//	// write the String reference array.	for (int i = 0; i < capacity; i++) { 	    StringConstant sc = data[i];	    if ( sc == null ){		out.println("    {0},");	    } else {		/* 		 * Moved globals to CVMROMGlobals.		 */		out.println("    {(CVMObject*)&CVMROMGlobals."+stringArrayName+"["+sc.unicodeIndex+"]},");	    }	}	out.print("}, {\n    ");	// now the reference counts: all either unused or sticky	int perLine = 0;	for (int i = 0; i < capacity; i++) { 	    StringConstant sc = data[i];	    if ( sc == null ){		out.print("StrU, ");	    } else {		out.print("StrS, ");	    }	    if (++perLine > 8 ){		out.print("\n    ");		perLine = 0;	    }	}	out.println("\n}};");    }}class CVMStringIntern{    CVMInternSegment internTable;    CVMInitInfo      initInfo;    CVMStringIntern( CVMInitInfo initInfo, int maxSize ){	this.initInfo = initInfo;	internTable = new CVMInternSegment( maxSize );    }    StringConstant internStringConstant( StringConstant val ){	String s = val.str.string;	CVMInternSegment curseg = internTable;	int h = 0, n;	// Hash function.	// Identical to the one in the runtime interning code.	n = Math.min( s.length(), 16 );	for ( int i = 0; i < n; i++ ){	    h = (h*37) + s.charAt(i);	}	int h1 = (h&0x7fffffff) % curseg.capacity;	int h2 = (h&15)+1;	int i = h1;	StringConstant candidate;	while ( (candidate=curseg.data[i]) != null ){	    if ( val.equals( candidate ) ){		return candidate;	    }	    i += h2;	    if ( i >= curseg.capacity ){		i -= curseg.capacity;	    }	}	// not found in this table.	// insert at current location.	curseg.data[i] = val;	curseg.content += 1;	return val;    }    /*      * Moved global variables to CVMROMGlobals     * That makes it necessary to pass the global header out file into writeInternTable.     */    public void writeInternTable(	CCodeWriter out,	CCodeWriter globalHeaderOut,	String tableName,	String stringArrayName )    {	/* the StringIntern class has no EMV equivalent -- it becomes	 * part of java.lang.String. Only the InternSegment exists.	 * Go write it out.	 */	String linkname;	// Note : define more compact representation of	// CVMInternUnused and CVMInternSticky to reduce our	// output volumn	out.print("#undef StrS\n#undef StrU\n");	out.print("#define StrS	CVMInternSticky\n");	out.print("#define StrU	CVMInternUnused\n");	//	// write out the indirect next cell, and see that it gets	// initialized.	linkname = tableName+"NextCell";	/* 	 * Moved global variables to CVMROMGlobals	 */	globalHeaderOut.println("    struct CVMInternSegment * "+linkname+";");	initInfo.addInfo("NULL", "&CVMROMGlobals."+linkname, "sizeof (CVMROMGlobals."+linkname+")" );	internTable.writeSegment( tableName, stringArrayName, linkname, out );    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?