001/**************************************************************************** 002 * Copyright/Copyleft: 003 * 004 * For this source the LGPL Lesser General Public License, 005 * published by the Free Software Foundation is valid. 006 * It means: 007 * 1) You can use this source without any restriction for any desired purpose. 008 * 2) You can redistribute copies of this source to everybody. 009 * 3) Every user of this source, also the user of redistribute copies 010 * with or without payment, must accept this license for further using. 011 * 4) But the LPGL is not appropriate for a whole software product, 012 * if this source is only a part of them. It means, the user 013 * must publish this part of source, 014 * but don't need to publish the whole source of the own product. 015 * 5) You can study and modify (improve) this source 016 * for own using or for redistribution, but you have to license the 017 * modified sources likewise under this LGPL Lesser General Public License. 018 * You mustn't delete this Copyright/Copyleft inscription in this source file. 019 * 020 * @author Hartmut Schorrig: hartmut.schorrig@vishia.de, www.vishia.org 021 * @version 0.93 2011-01-05 (year-month-day) 022 *******************************************************************************/ 023package org.vishia.java2C.test; 024 025//import java.io.File; 026import java.io.File; 027import java.io.FileNotFoundException; 028import java.io.FileOutputStream; 029import java.io.IOException; 030import java.io.OutputStream; 031import java.text.SimpleDateFormat; 032import java.util.Date; 033 034/**This class contains some examples to test String functionality. 035 * <br><br> 036 * <b>Situation for String preparation in C:</b> 037 * A String preparation in C in embedded applications is often necessary in situations of error reporting 038 * or output of states. The typically choice is usage of <code>sprintf(buffer, "text-format", arguments, ...)</code>. 039 * This approach have some risks which may produce errors in runtime: 040 * <ul> 041 * <li>The type of arguments should be matched to the designation of parts in text-format. 042 * An error of detail is possible, the user should programmed carefully. The compiler doesn't detect errors. 043 * <li>If the size of <code>buffer</code> is less, an overflow isn't detect. An overflow may occur, if a value is unexpected, 044 * and the numbering formating produce a less longer output. <code>char*</code>-Arguments are critically too, 045 * because there length may be rate faulty because that is depending of outer code. 046 * <li>If a <code>char*</code> is used as argument, and the pointer is faulty, an unexpected buffer overflow 047 * may be produced in the <code>sprintf</code>. 048 * <li>The buffer should be provided by the users environment. If the buffer is defined in Stack, 049 * and the String is produced and used temporary, it's okay. But a software correction in calling routines, 050 * which doesn't uses to pointer to the buffer for copy, instead save the pointer, are not detected at compile time. 051 * </ul> 052 * The usage of <code>sprintf(...)</code> in C should implement carefully, it is sensitive. 053 * <br><br> 054 * The usage of Strings in Java is some more unsensitive and simple. But the standard-Java uses the system of garbage collection 055 * to accomplish this requirements. This may not able to use in all situations of embedded control-software. 056 * The preparation of Strings may realized in Java in three ways: 057 * <ul> 058 * <li>Simple concatenations of Strings just like <code>String result = "value=" + value</code>. This variant needs a buffer, 059 * which is allocated in the heap and managed by garbage collection. 060 * <li>Usage of a StringBuffer or StringBuilder. 061 * The adequate code is <code>result.setLength(0); result.append("value=").append(value);</code> 062 * The StringBuffer-Object can be allocated as an element of any class, the memory space is allocated 063 * in the instance including the buffer itself, hence no dynamic memory allocation is necessary. 064 * <li>Java knows a adequate to <code>sprintf</code> approach using <code>String.format(formatString, arguments ...)</code>. 065 * This method is some more safety as the C-<code>sprintf</code>, because a buffer overflow is detected and the types 066 * of arguments are well known. But the method works with dynamic memory only. 067 * </ul> 068 * If embedded software written in Java and translated to C shouldn't used dynamic memory and garbage collection, 069 * the second approach using <code>StringBuffer</code> is proper. The <code>StringBuffer</code> can be defined 070 * as embedded Buffer with a fix length inside a class type. Examples using such a fix <code>StringBuffer</code> 071 * allocated in the Stack too are test and shown in the method {@link #testStringBuffer()}. 072 * <br><br> 073 * If the garbage collector is able to use, a String concatenation is able to use. The user doesn't need to 074 * provide any buffers. 075 * 076 */ 077public class TestString 078{ 079 080 081 /**A reference to another struct. */ 082 StringBuilder buffer1; 083 084 /**A reference to another struct, but without need of garbage collection. @java2c=noGC. */ 085 final StringBuffer bufferInit; 086 087 088 final StringBuilder bufferEmbedded = new StringBuilder(1000); 089 090 final static String empty = " "; 091 092 /**A reference to a String in memory. The String may be a reference to a constant String 093 * or to the content inside a StringBuffer. see usages. */ 094 String stringRef; 095 096 /**Creates an embedded instance as StringBuffer with immediate space for the chars. */ 097 private final StringBuffer sbufferFix = new StringBuffer(250); 098 099 private final String[] strArray = new String[10]; 100 101 private String[] strArray2; 102 103 private char[] charArray = new char[10]; 104 105 TestString(StringBuffer bufferInit) 106 { 107 buffer1 = new StringBuilder(122); 108 this.bufferInit = bufferInit; 109 } 110 111 /**Help method which processes a String. */ 112 static int processString(String str) 113 { return str.length(); 114 } 115 116 117 118 /**Examples for String concatenations. 119 * <br><br> 120 * This method tests and shows a concatenation of String without using dynamic memory. 121 * it uses Stack instances only, because all Strings are used temporary. 122 * This patterns are able to use in a system without any dynamically memory, 123 * at example for String preparing in an interrupt routine of embedded control. 124 * <br><br> 125 * See comments on the code line of java source-code in comparision with the produced C-code 126 * in <a href="../xxx">xxx</a> 127 */ 128 void testStringConcatenationInStack(int value, float fValue) 129 { /**Because it is set 'java2c=StringBuilderInStack=100'. The concatenation will be done 130 * in an buffer created in Stack instead in an new allocated buffer in heap. 131 * The operation toString builds a reference to this stack instance anyway. 132 * The stack variable ssn refers the string in stack. 133 * Because it is set 'java2c=toStringNonPersist'. The StringBuilderJc in stack 134 * will not designated as 'freezed' for further usage. That are another aspect. 135 * The result is a temporary non persistent String in stack. 136 * @java2c=toStringNonPersist, StringBuilderInStack=100. 137 */ 138 String ssn = "test-Concatenation " + value + ", float " + fValue; 139 /**This String can be used as input for any method, which processed the String 140 * but not references the original source-string. Most of routines do so. 141 */ 142 processString(ssn); 143 /** 144 * The next statement reuses the buffer and changes the String. The reuse is done 145 * only because the same buffer in stack is dedicated with 'java2c=StringBuilderInStack', 146 * not derived from the previous used buffer. 147 * It is another way of controlling as on operation '+='. 148 * 149 * @java2c=toStringNonPersist, StringBuilderInStack=100. */ 150 ssn = "second " + value; 151 processString(ssn); 152 /** 153 * The next statement appends something on the String. It is a typically operation 154 * while preparing Strings in more as one line. The buffer can be enlarged, 155 * because the last operation for assign ssn was designated with 'java2c=toStringNonPersist'. 156 * Therefore the Buffer is not dedicated as 'freezed'. Which buffer is used? 157 * It is the buffer, which is used for the previous preparation of the String. 158 * The designation with 'java2c=toStringNonPersist' would have an effect 159 * for further '+='-operations with this variable. In this example it has an effect 160 * only for further usage of the same buffer. It is possible to use the buffer. 161 * The enlarging-operation of the buffer (call of append) doesn't depend on that designation. 162 * @java2c=toStringNonPersist. 163 */ 164 ssn += ", third"; 165 /** 166 * This String should be built in an own buffer, because ssn is used for concatenation too. 167 * but it may be @java2c=toStringNonPersist.*/ 168 //ssn = "forth, " + ssn; 169 /**Use it: */ 170 processString(ssn); 171 172 int pos = ssn.indexOf('.'); 173 if(pos < 0 ){ 174 pos = 0; 175 } 176 { int pos2 = ssn.indexOf("third"); 177 if(pos2 >=0){ 178 pos += pos2; 179 } 180 } 181 } 182 183 184 185 186 187 /**Examples for String concatenations. 188 * <br><br> 189 * This method tests and shows a concatenation of String using garbage collection. 190 * <br><br> 191 * <b>First example: concatenation and assignment</b>: The Java-code is: 192 * <pre class="Java"> 193 String ss = "test " + value + " miles"; 194 System.out.println(ss); 195 this.stringRef = ss; 196 * </pre> 197 * A String will be built stack-locally with concatenation. Than this String will be used 198 * first as parameter for a method, than it is saved in the instance (persistent). 199 * In C it is translated to: 200 * <pre> 201 StringJc ss; 202 ... 203 StringBufferJc *_tempString1_1=null; //J2C: temporary Stringbuffer for String concatenation 204 ... 205 ss = 206 ( _tempString1_1 = new_StringBufferJc(-1, _thCxt) 207 , setTemporary_StringBufferJc(_tempString1_1) 208 , append_z_StringBufferJc(_tempString1_1, "test ", _thCxt) 209 , append_I_StringBufferJc(_tempString1_1, value, _thCxt) 210 , append_z_StringBufferJc(_tempString1_1, " miles", _thCxt) 211 , toString_StringBufferJc(_tempString1_1) 212 ); 213 println_s_PrintStreamJc(REFJc(out_SystemJc), ss, _thCxt); 214 set_StringJc(&(ythis->stringRef), ss); 215 .... 216 activateGC_ObjectJc(&_tempString1_1->base.object, null, _thCxt); 217 * </pre> 218 * The following principles are used: 219 * <ul> 220 * <li>Adequate to the implementation in Java the concatenation uses a StringBuffer internally 221 * for the concatenation expression. The StringBuffer is allocated in heap 222 * calling <code>new_StringBufferJc(...)</code>. 223 * <li>There is a possibility of working without allocated memory 224 * for such embedded software systems, which should not use any dynamic memory and garbage collection: 225 * The new StringBuffer can be a thread-local existing buffer. In this case only one concatenation of Strings 226 * is able to use per Thread. The content of the produced String should be copied in the next instruction. 227 * That is a restriction of programming, but it allows to work without garbage collection. Commonly 228 * a garbage collector and dynamic memory should be able to use. The CRuntimeJavalike-Library provides a solution 229 * using blocks with equal size (<code>BlockHeap</code>). 230 * <li>The StringBuffer is dedicated as temporary. The reference to the StringBuffer isn't known 231 * in the users programming. Therefore the user can't work with it. Only the result String <code>ss</code> 232 * uses the buffer. 233 * <li>All concatenations are implemented using <code>append...(...)</code>-methods. 234 * <li>The last operation with the StringBuffer is the call of <code>toString(...)</code> to get the String. 235 * A String instance contains only the pointer to the text itself (<code>char* in Buffer</code>), 236 * the number of chars and a few special bits. That are at maximum 2 Registers with 32 bit, 237 * compendious in a <code>struct StringJc</code> and defined operation-system-depend 238 * in a <code>struct OS_ValuePtr</code> to support optimal memory and register usage for the target platform. 239 * <li>The String is stored and taken as parameter as value, never as a reference (not as <code>StringJc*</code>). 240 * The method <code>println(...)</code> got the String as value. 241 * <li>To store a String in class variables (persistent), the method <code>setref_StringJc(...)</code> is used. 242 * This method sets the backward reference to the memory block of the block-heap, which contains 243 * the pointer to the text and sets the index of backward reference in the reference in class (<code>ythis->stringRef</code>) 244 * With this operation the block is referenced now. 245 * <li>The temporary StringBufferJc is designated to managed by Garbage collection at least, before finish the routine. 246 * Because the String is referenced in this example, the garbage collector will test the reference. 247 * Elsewhere the block will be freed from garbage collector. That is typically if a String is prepared 248 * and used only locally. 249 * </ul> 250 */ 251 void testStringConcatenationWithTemps(int value, float fValue) 252 { String ssn = "test " + value + " miles"; 253 processString(ssn); 254 //System.out.println(ssn); 255 //this.stringRef = ssn; 256 ssn = "second " + value; 257 ssn += ", third"; 258 ssn = "forth, " + ssn; 259 //System.out.println(ssn); 260 processString(ssn); 261 /**A buffer in stack: @java2c=stackInstance. */ 262 //StringBuffer buffer = new StringBuffer(40); 263 //buffer.append("buffer:"); 264 //ssn = buffer + ssn; 265 /**Test substring, indexof. */ 266 //int pos = ssn.substring(4).indexOf('i'); 267 268 } 269 270 void testStringConcatenationUsingBuilder(int value) 271 { /**A buffer in stack: @java2c=stackInstance. */ 272 StringBuffer buffer = new StringBuffer(40); 273 buffer.append("buffer:"); 274 buffer.append(123); 275 String ssn = buffer.toString(); 276 /**Test substring, indexof. */ 277 int pos = ssn.substring(4).indexOf('i'); 278 279 } 280 281 282 283 String testStringParameter(String s1, String s2) 284 { /** @java2c=StringBuilderInThreadCxt.*/ 285 String ret = s1 + " to " + s2; 286 return ret; 287 288 } 289 290 291 void testStringParameter() 292 { 293 /**@java2c=stackInstance. */ 294 Date dateFrom = new Date(); 295 /**@java2c=stackInstance. */ 296 Date dateTo = new Date(dateFrom.getTime() + 3600000); 297 /**@java2c=stackInstance. */ 298 SimpleDateFormat dateFormat = new SimpleDateFormat("yy_MMM_dd_HHmmss_SS"); 299 String sResult= testStringParameter(dateFormat.format(dateFrom), dateFormat.format(dateTo)); 300 System.out.println(sResult); 301 } 302 303 304 305 /** 306 * @param value 307 * @param fValue 308 * @return 309 * @java2c=return-new. 310 */ 311 private String testFormat(int value, float fValue) 312 { 313 /**@java2c=toStringNonPersist. */ 314 String result = String.format("format intVal=%d floatVal=%3.4f test", value, fValue); 315 processString(result); 316 return result; 317 } 318 319 320 private void testReplace() 321 { 322 String src = "C:\\directory/myFolder/myFile.x"; 323 String dst = src.replace('\\', '/'); 324 buffer1.setLength(0); 325 buffer1.append(src.replace('\\', '/')); 326 buffer1.setLength(0); buffer1.append(src); 327 /**@java2c=toStringNonPersist. The replacement should done in the buffer itself. */ 328 src = buffer1.toString(); 329 /**This expression copies the replaced text in the buffer1. 330 * It is the same, if the original text is copied and than replaced in the buffer. 331 * But Java doesn't know a simple char replacement in a StringBuilder. 332 * The Java2C translates to ...TODO 333 */ 334 buffer1.replace(0, buffer1.length(), src.replace('\\', '/')); 335 336 } 337 338 339 private void testInsertCharArray() 340 { buffer1.setLength(0); 341 buffer1.append("1234"); 342 charArray[0] = 'A'; 343 charArray[1] = 'Q'; 344 charArray[2] = 'X' ; 345 buffer1.insert(2, charArray, 1,2); 346 /**@java2c=toStringNonPersist. */ 347 assert(buffer1.toString().equals("12QX34")); 348 } 349 350 351 352 public String toString() 353 { return stringRef; 354 } 355 356 357 void testGarbageString() 358 { 359 stringRef = "other String"; 360 361 } 362 363 /**Example for StringBuffer usage. 364 * <br><br> 365 * The StringBuffer {@link #bufferEmbedded} is created as an embedded part of this class structure. 366 * It has a fix length, the text is part of the instance, using immediate buffer. 367 * The usage of such an buffer for string preparing is a proper decision if no dynamic memory 368 * should be used, and the user has the controlling and responsibility about the String instances. 369 * <br> 370 * The Java-code to prepare a string is: 371 * <pre class="Java"> 372 bufferEmbedded.setLength(0); 373 bufferEmbedded.append("content:").append(stringRef); 374 System.out.println(bufferEmbedded); 375 String s1 = bufferEmbedded.toString(); 376 System.out.println(s1); 377 this.stringRef = s1; 378 * </pre> 379 * In this example the buffer is cleared, than a content is appended. The Result is used to print out 380 * with given StringBuffer. Than the buffer-content is stored in a String calling the <code>toString(...)</code>-method. 381 * That result is used to print out too. At last the String is stored in a class variable. 382 * <br><br> 383 * The resulting C-code is: 384 * <pre> 385 StringJc s1; 386 ... 387 setLength_StringBufferJc(& (ythis->bufferEmbedded.sb), 0, _thCxt); 388 ( append_s_StringBufferJc(& (ythis->bufferEmbedded.sb), s0_StringJc("content:"), _thCxt) 389 , append_s_StringBufferJc(& (ythis->bufferEmbedded.sb), ythis->stringRef, _thCxt) 390 ); 391 println_sb_PrintStreamJc(REFJc(out_SystemJc), & (ythis->bufferEmbedded.sb), _thCxt); 392 s1 = toString_StringBufferJc(& (ythis->bufferEmbedded.sb)); 393 println_s_PrintStreamJc(REFJc(out_SystemJc), s1, _thCxt); 394 set_StringJc(&(ythis->stringRef), s1); 395 * </pre> 396 * The C-code follows the Java-code. The concatenation of append is resolved like described in 397 * {@link TestAllConcepts#checkConcatenationSimple()}. 398 * <br><br> 399 * 400 */ 401 void testStringBuffer() 402 { bufferEmbedded.setLength(0); 403 bufferEmbedded.append("content:").append(stringRef); 404 System.out.println(bufferEmbedded); 405 /**@java2c=toStringNonPersist. */ 406 String s1 = bufferEmbedded.toString(); 407 System.out.println(s1); 408 this.stringRef = s1; 409 /**The StringBuffer is allocated in BlockHeapJc, containing the max possible buffer size, 410 * this size is limited in C implementation. */ 411 StringBuffer sb = new StringBuffer(); 412 sb.setLength(0); 413 sb.append("test ").append(5).append(" Stringbuffer"); 414 System.out.println(sb); 415 /**@java2c=toStringNonPersist. */ 416 /**The toString() is only used in the thread immediately. 417 * Therefore: @java2c=toStringNonPersist. */ 418 String ss = sb.toString(); 419 System.out.println(ss); 420 } 421 422 423 424 425 426 427 428 429 430 431 /** 432 * <b>Persistence of Strings</b> 433 * The method <code>toString(...)</code> needs to turn one's attentions: Generally, a String is constant. 434 * Because the buffer content of a StringBuffer may be changed after calling <code>toString(...)</code>, 435 * the text have to be copied to an independent buffer. The Java implementation do so. 436 * But this is an additional effort regarding typically applications in the fast real-time embedded world. 437 * Mostly the StringBuffer isn't change immediately, rather the got String is processed and thereby copied 438 * in the current thread like shown in the example {@link #testStringBuffer()}. 439 * <br><br> 440 * Thats why some methods <code>toString...(...)</code> in the CRuntimeJavalike-Library have two modes: 441 * <ul> 442 * <li>Compatible-mode with Java, but with more effort: <code>toString...(...)</code> creates an extra 443 * buffer for the returned String in heap. 444 * <li>Small-effort-mode: <code>toString_StringBufferJc</code> references the String in the 445 * StringBuffer-instance, no extra buffer is used. <code>toString...(...)</code> from other classes 446 * uses the thread-local Buffer, it can be used only one for one toString-result in thread, the result is to copy outside. 447 * This mode saves calculation time and prevent an extra memory allocation. 448 * In this case the String is dedicated with a bit <code>mNonPersists__StringJc</code>. 449 * </ul> 450 * Both modes are able to choice. The default is the compatible mode with Java. A method which uses 451 * the small-effort mode can be designated with a <code>@ java2c=optimize-toString</code> annotation 452 * in its description block. Than the small-effort-mode is valid for that method body. 453 * <br><br> 454 * The prevention of copy a String in a allocated buffer is not only a question of calculation time effort. 455 * If a routine in a fast interrupt uses a lightweight String preparation but an allocated buffer is necessary, 456 * that module needs resources, which are inadequately for it. Therefore the optimize mode is recommended. 457 * The Java-source should written in a form, which doesn't change a StringBuffer from which a derived 458 * temporary String is still in use. First do all with the String, than change the Buffer. 459 * Than the optimized C-code works correctly. 460 * <br><br> 461 * If the String is saved persistent in a class variable, it must copy to an own buffer. In this case 462 * an alteration of the StringBuffer content is able to expect while the persistent String is ready to use. 463 * It would be a non-obvious programming situation if the persistent String is referenced the buffer evermore. 464 * Thats why the assignment using <code>set_StringJc(...)</code> checks whether the String is non persistent. 465 * If it is so, a new StringBuffer is allocated in heap and the String is copied into. That StringBuffer 466 * is only referenced by this String, and therefore it is fix and managed by garbage collection. 467 * <br><br> 468 * An adequate problem are given by the <code>toString(...)</code> implementations of some other Objects. 469 * Because mostly the Strings will be processed immediately, at example as input for an concatenation, 470 * extra buffers should be saved to minimize effort. For preparing the returned String a thread-local StringBuffer 471 * is able to use. That is thread-save, but only one instance of that buffer exists per thread. 472 * This buffer have never to be referenced. Thats why the same dedication is used: <code>mNonPersists__StringJc</code>. 473 * The user can produce a faulty code, a code which runs in Java because Java is save but it doesn't run in C after translation. 474 * This is the disadvantage of this concept, the concession to the optimizing of calculation time and preventing 475 * additional dynamically memory management. The user may write minimal other statements to get a safety code. 476 * <br><br> 477 * This routine is designated with the <code>@ java2c=optimize-toString.</code>, but the code is faulty for that: 478 * <pre class="Java"> 479 bufferEmbedded.setLength(0); 480 String ss = bufferEmbedded.append("content:").append(234).toString(); 481 bufferEmbedded.setLength(0); 482 bufferEmbedded.append(" TEST ").append(ss); 483 ss = bufferEmbedded.toString(); 484 System.out.println(ss); 485 * </pre> 486 * The buffer content is saved in <code>ss</code>, but after them the buffer is changed. The translated C-code is: 487 * <pre> 488 bool _bOptimizeStringSave; //J2C: annotation optimize-toString 489 ... 490 _bOptimizeStringSave = optimizeString_ThCxt(_thCxt, true); 491 { 492 StringJc ss; 493 setLength_StringBufferJc(& (ythis->bufferEmbedded.sb), 0, _thCxt); 494 ss = 495 ( append_s_StringBufferJc(& (ythis->bufferEmbedded.sb), s0_StringJc("content:"), _thCxt) 496 , append_i_StringBufferJc(& (ythis->bufferEmbedded.sb), 234, _thCxt) 497 , toString_StringBufferJc(& (ythis->bufferEmbedded.sb), _thCxt) 498 ); 499 setLength_StringBufferJc(& (ythis->bufferEmbedded.sb), 0, _thCxt); 500 501 ( append_s_StringBufferJc(& (ythis->bufferEmbedded.sb), s0_StringJc(" TEST "), _thCxt) 502 , append_s_StringBufferJc(& (ythis->bufferEmbedded.sb), ss, _thCxt) 503 ); 504 ss = toString_StringBufferJc(& (ythis->bufferEmbedded.sb), _thCxt); 505 println_s_PrintStreamJc(REFJc(out_SystemJc), ss, _thCxt); 506 } 507 optimizeString_ThCxt(_thCxt, _bOptimizeStringSave); 508 * </pre> 509 * 510 * The optimizing is set in the Thread-context-data. After the routine the saved state of optimizing 511 * is recovered. 512 * 513 */ 514 void testNonPersistenceOfStrings() 515 { 516 bufferEmbedded.setLength(0); 517 /**@java2c=toStringNonPersist. */ 518 String ss = bufferEmbedded.append("content:").append(234).toString(); 519 bufferEmbedded.setLength(0); 520 bufferEmbedded.append(" TEST ").append(ss); 521 /**@java2c=toStringNonPersist. */ 522 ss = bufferEmbedded.toString(); 523 System.out.println(ss); 524 } 525 526 527 528 /**This routine has the same content like {@link #testNonPersistenceOfStrings()}, 529 * but the persistence is set per default, 530 * no <code>@ java2c=optimize-toString</code>. is written here. 531 * The result is correct. Debug it in C! 532 */ 533 void testPersistenceOfStrings() 534 { 535 bufferEmbedded.setLength(0); 536 String ss = bufferEmbedded.append("content:").append(234).toString(); 537 bufferEmbedded.setLength(0); 538 bufferEmbedded.append(" TEST ").append(ss); 539 ss = bufferEmbedded.toString(); 540 System.out.println(ss); 541 } 542 543 544 /**This routine uses the class java.lang.Date und SimpleFormatter 545 * to produce a String with a date and time information. 546 * The translated code uses the CRuntimeJavalike-classes Date etc. 547 * Some annotations cause, that only stack-instances and the buffer in the thread context 548 * is used, no dynamically memory. 549 */ 550 String testDateString(String sPath, int ident) 551 { /**@java2c=stackInstance. */ 552 Date date = new Date(); 553 /**@java2c=stackInstance. */ 554 SimpleDateFormat dateFormat = new SimpleDateFormat("yy_MMM_dd_HHmmss_SS"); 555 /**@java2c=toStringNonPersist.*/ 556 String sDateString = dateFormat.format(date); 557 /**@java2c=StringBuilderInStack:150. */ 558 String sFileName = sPath + "file_" + ident + "_" + sDateString + ".txt"; 559 /**@java2c=returnInThreadCxt. */ 560 return sFileName; 561 } 562 563 /**This routine uses the class java.lang.Date und SimpleFormatter 564 * to produce a String with a date and time information. 565 * The translated code uses the CRuntimeJavalike-classes Date etc. 566 * It is the same routine in Java like {@link #testDateString(String, int)}, 567 * but there are no annotations. Therefore dynamically memory is used. 568 */ 569 String testDateStringDynamic(String sPath, int ident) 570 { Date date = new Date(); 571 SimpleDateFormat dateFormat = new SimpleDateFormat("yy_MMM_dd_HHmmss_SS"); 572 String sDateString = dateFormat.format(date); 573 String sFileName = sPath + "file_" + ident + "_" + sDateString + ".txt"; 574 return sFileName; 575 } 576 577 /**@java2c=embedded Type:FileOutputStream. */ 578 FileOutputStream oStream1, oStream2; 579 580 581 void testOutStream(String sPath) 582 { try{ 583 /**@java2c=StringBuilderInStack:100, toStringNonPersist. */ 584 oStream1 = new FileOutputStream(sPath+ "file1.txt"); 585 /**@java2c=StringBuilderInStack=256,toStringNonPersist. */ 586 oStream2 = new FileOutputStream(sPath+ "file2.txt"); 587 oStream1.close(); 588 oStream2.close(); 589 } catch(FileNotFoundException exc){ 590 System.out.println("not found: " + sPath); 591 } catch (IOException e) { 592 System.out.println("file error: " + sPath); 593 } 594 } 595 596 private int testSomeSimpleStringMethods() 597 { int ret; 598 int pos; 599 boolean bOk; 600 final String s1 = "abcdecde"; 601 final String s2 = "abc"; 602 char cc = s1.charAt(3); 603 bOk = (cc == 'd'); 604 bOk = bOk && ! s1.equals(s2); 605 bOk = bOk && s1.startsWith(s2); 606 607 /**This case works in Java, but it is unnecessary. It doesn't work in Java2C. */ 608 //bOk = bOk && s1.equals((Object)s1); //error while compiling, fault type conversion. 609 //Object oString = s1; //error while translating Java2C, a StringJc is not an ObjectJc 610 611 ret = pos = s1.indexOf('c'); 612 ret += pos = s1.indexOf('c', 2); //pos = 2, same as above, but seach from position 2 only 613 ret += pos = s1.indexOf('c', 3); //pos = -1 because not found. 614 615 ret = pos = s1.indexOf("de"); 616 ret += pos = s1.indexOf("de", 2); //pos = 3, same as above, but seach from position 2 only 617 ret += pos = s1.indexOf( "de", 4); //pos = -1 because not found. 618 619 ret += pos = s1.indexOf("de", 99); //pos = -1 because not found. Not an exception 620 621 ret += pos = s1.indexOf("de", -1); //pos = 3 because search from 0. Not an exception. 622 623 ret = pos = s1.lastIndexOf('c'); 624 ret += pos = s1.lastIndexOf('c', 2); //pos = 2, same as above, but seach from position 2 only 625 ret += pos = s1.lastIndexOf('c', 3); //pos = -1 because not found. 626 627 ret = pos = s1.lastIndexOf("de"); 628 ret += pos = s1.lastIndexOf("de", 2); //pos = -1, because not found. 629 ret += pos = s1.lastIndexOf( "de", 3); //pos = 3 because the string starts at 3. 630 631 ret += pos = s1.lastIndexOf("de", 99); //pos = -1 because not found. Not an exception 632 633 ret += pos = s1.lastIndexOf("de", -1); //pos = 3 because search from 0. Not an exception. 634 635 636 return ret; 637 } 638 639 640 641 /**A CharSequence is the super-class of java.lang.String and java.lang.StringBuilder. 642 * In C it is the same as a StringJc, because the StringJc has the necessary methods 643 * and refers a sequence of chars. 644 * <br><br> 645 * The expression <code>CharSequence csq1 = buffer1</code> is a simple downcast 646 * from StringBuilder in Java, but in C it is a toString()-call. The text itself isn't copy 647 * thereby, it is referenced. This is the equal functionality. Note that the StringJc is 648 * a simple value-struct with reference and length. 649 * 650 */ 651 private void testCharSequence() 652 { 653 buffer1.setLength(0); buffer1.append("csq1"); 654 CharSequence csq1 = buffer1; //StringBuffer to charSequence 655 bufferEmbedded.setLength(0); 656 bufferEmbedded.append("be_").append(csq1); 657 /**@java2c=toStringNonPersist. */ 658 assert(bufferEmbedded.toString().equals("be_csq1")); 659 } 660 661 662 663 /**Calls the test routines. 664 * 665 */ 666 public String testStringProcessing() 667 { long timeStart, timeEnd; 668 int timeRun; 669 float adjustTime; 670 String str; 671 timeStart = System.nanoTime(); 672 try { 673 Thread.sleep(10); 674 } catch (InterruptedException e) { 675 } 676 timeEnd = System.nanoTime(); 677 timeRun = (int)(timeEnd - timeStart); 678 /**Runtime output @java2c=StringBuilderInStack=100, toStringNonPersist. */ 679 System.out.println("10 ms: " + timeRun + "ns"); 680 681 timeStart = System.nanoTime(); 682 try { 683 Thread.sleep(100); 684 } catch (InterruptedException e) { 685 } 686 timeEnd = System.nanoTime(); 687 timeRun = (int)(timeEnd - timeStart); 688 adjustTime = 100000.0F / timeRun; 689 /**Runtime output @java2c=StringBuilderInStack=100, toStringNonPersist. */ 690 System.out.println("100 ms: " + (timeRun * adjustTime) + "us"); 691 692 timeStart = System.nanoTime(); 693 timeEnd = System.nanoTime(); 694 timeRun = (int)(timeEnd - timeStart); 695 /**Runtime output @java2c=StringBuilderInStack=100, toStringNonPersist. */ 696 System.out.println("emtpy measurement: " + (timeRun * adjustTime) + "us"); 697 698 699 timeStart = System.nanoTime(); 700 TestString_classic.concatenate(456, 3.14F); 701 TestString_classic.concatenate(457, 3.14F); 702 TestString_classic.concatenate(458, 3.14F); 703 TestString_classic.concatenate(459, 3.14F); 704 TestString_classic.concatenate(42, 3.14F); 705 TestString_classic.concatenate(43, 3.14F); 706 TestString_classic.concatenate(44, 3.14F); 707 TestString_classic.concatenate(45, 3.14F); 708 TestString_classic.concatenate(46, 3.14F); 709 TestString_classic.concatenate(47, 3.14F); 710 timeEnd = System.nanoTime(); 711 timeRun = (int)(timeEnd - timeStart); 712 /**Runtime output @java2c=StringBuilderInStack=100, toStringNonPersist. */ 713 System.out.println("TestString_classic.concatenate: " + (timeRun * adjustTime) + "us"); 714 715 timeStart = System.nanoTime(); 716 testStringConcatenationInStack(456, 3.14F); 717 testStringConcatenationInStack(456, 3.14F); 718 testStringConcatenationInStack(456, 3.14F); 719 testStringConcatenationInStack(456, 3.14F); 720 testStringConcatenationInStack(456, 3.14F); 721 testStringConcatenationInStack(456, 3.14F); 722 testStringConcatenationInStack(456, 3.14F); 723 testStringConcatenationInStack(456, 3.14F); 724 testStringConcatenationInStack(456, 3.14F); 725 testStringConcatenationInStack(456, 3.14F); 726 timeEnd = System.nanoTime(); 727 timeRun = (int)(timeEnd - timeStart); 728 /**Runtime output @java2c=StringBuilderInStack=100, toStringNonPersist. */ 729 System.out.println("testStringConcatenationInStack: " + (timeRun * adjustTime) + "us"); 730 731 timeStart = System.nanoTime(); 732 testStringConcatenationWithTemps(456, 3.14F); 733 testStringConcatenationWithTemps(456, 3.14F); 734 testStringConcatenationWithTemps(456, 3.14F); 735 testStringConcatenationWithTemps(456, 3.14F); 736 testStringConcatenationWithTemps(456, 3.14F); 737 testStringConcatenationWithTemps(456, 3.14F); 738 testStringConcatenationWithTemps(456, 3.14F); 739 testStringConcatenationWithTemps(456, 3.14F); 740 testStringConcatenationWithTemps(456, 3.14F); 741 testStringConcatenationWithTemps(456, 3.14F); 742 timeEnd = System.nanoTime(); 743 timeRun = (int)(timeEnd - timeStart); 744 /**Runtime output @java2c=StringBuilderInStack=100, toStringNonPersist. */ 745 System.out.println("testStringConcatenationWithTemps: " + (timeRun * adjustTime) + "us"); 746 747 testFormat(234, 3.14F); 748 749 testStringConcatenationUsingBuilder(456); 750 testStringParameter(); 751 testStringBuffer(); 752 testReplace(); 753 testNonPersistenceOfStrings(); 754 testPersistenceOfStrings(); 755 str = testDateString("./", 123); 756 str = testDateStringDynamic("./", 123); 757 testInsertCharArray(); 758 String sPath = "."; 759 /**@java2c=StringBuilderInStack:100, toStringNonPersist. */ 760 testOutStream(sPath + "/"); 761 testSomeSimpleStringMethods(); 762 testCharSequence(); 763 String s9 = toString(); //calls override-able method 764 return s9; 765 } 766 767 768}