/** **************************************************************************************** * Converts the given unsigned 64 bit integer value to a string representation.<br> * Negative numbers have to be converted to positive values when invoking this method. * The maximum number of digits written are 20. The given buffer has to be large * enough to receive the characters. The method does not check any overflow within the * given character buffer. * * \note This method is used internally by various AString conversion methods. It is * advisable to use AString methods to convert integer values. * * @param value The integer value to convert. * @param buffer The character array to write the value to. Depending on the value * given, a maximum of 20 characters need to be allocated prior to * invoking this method. * @param idx The index within the character array to write the value to. * @param minDigits The minimum number of digits to append. * If given value has less digits, '0' characters are prepended. * The given value is cut to the range 1..20 (max digits of an * unsigned 64 bit integer). * @param sizeHint The maximum number of digits found in the value. This is a hint * for optimizing the loop. If -1 is provided, the number is detected. * If a number is provided that is lower than the actual 'log10(value)', * the method produces unpredictable results. * * @return The index of the new new end of the buffer. ******************************************************************************************/ public int IntegerToString(ulong value, char[] buffer, int idx, int minDigits, int sizeHint) { // adjust minDigits to 1..20 and maxDigits to 1..minDigits if (minDigits < 1) { minDigits = 1; } if (minDigits > 20) { minDigits = 20; } if (sizeHint < minDigits) { sizeHint = minDigits; } if (sizeHint > 20) { sizeHint = 20; } int actDigit = sizeHint; bool printStarted = false; while (--actDigit >= 0) { // rest is zeros? if (value == 0) { while (actDigit >= 0) { if (!(printStarted |= actDigit-- < minDigits)) { continue; } buffer[idx++] = '0'; } return(idx); } // get next d ulong actBase = pow10_0to19[actDigit]; int digitValue = (int)(value / actBase); ALIB.ASSERT(digitValue <= 9); // did we hit i for the first time if (!(printStarted |= (digitValue != 0) || actDigit < minDigits)) { continue; } // print the digit buffer[idx++] = (char)(48 + digitValue); // 48= '0' // next value = value % actBase; } // return me for concatenated operations return(idx); }
/** **************************************************************************************** * Writes hash tables stored in a ScopeStore. Keys are AStrings. * Value types currently supported are LogData and int (in C# different method). * @param store The store to use. * @return The total number of hash table entries written. ******************************************************************************************/ public int writeStoreMap <T>(ScopeStore <Dictionary <AString, T> > store) { bool firstEntry = true; int cnt = 0; if (store.globalStore != null && store.globalStore.Count > 0) { cnt += store.globalStore.Count; if (firstEntry) { firstEntry = false; } else { target.NewLine(); } target._NC(" Scope.Global:").NewLine(); maxKeyLength = writeStoreMapHelper(store.globalStore, " "); } foreach (KeyValuePair <Thread, List <Dictionary <AString, T> > > thread in store.threadOuterStore) { if (thread.Value.Count == 0) { continue; } ALIB.ASSERT(thread.Value.Count == 1); if (firstEntry) { firstEntry = false; } else { target.NewLine(); } target._NC(" Scope.ThreadOuter "); storeThreadToScope(thread.Key)._(':').NewLine(); cnt += thread.Value[0].Count; maxKeyLength = writeStoreMapHelper(thread.Value[0], " "); } foreach (PathMap <Dictionary <AString, T> > map in store.languageStore) { if (firstEntry) { firstEntry = false; } else { target.NewLine(); } target._NC(" "); storeKeyToScope(map)._(':').NewLine(); cnt += map.Value.Count; maxKeyLength = writeStoreMapHelper(map.Value, " "); } foreach (KeyValuePair <Thread, List <Dictionary <AString, T> > > thread in store.threadInnerStore) { if (thread.Value.Count == 0) { continue; } ALIB.ASSERT(thread.Value.Count == 1); if (firstEntry) { firstEntry = false; } else { target.NewLine(); } target._NC(" Scope.ThreadInner "); storeThreadToScope(thread.Key)._(':').NewLine(); cnt += thread.Value[0].Count; maxKeyLength = writeStoreMapHelper(thread.Value[0], " "); } return(cnt); }
/** **************************************************************************************** * Appends the given double value as string representation. * * This method supports to write a variable or fixed number of digits for the integral * and the fractional part of the provided value, or in <em>scientific notation</em>. * In <em>scientific notation</em>, the value is multiplied with a power of 10 so that * the integral part of the number falls into the range of 0 and 9. Then, the the negative * value of the exponent of this multiplicand is appended, separated by the string defined in * #DecimalExponentSeparator. * * The output format is dependent on various settings provided in the fields of this class. * * @param value The double value to append. * @param buffer The character array to write the value into. * Depending on the value given and the format settings, a maximum of * 32 characters need to be allocated prior to invoking this method. * @param idx The index within the buffer to start writing to. * * @return The index pointing behind the last character written. ******************************************************************************************/ public int FloatToString(double value, char[] buffer, int idx) { // for debugging: // char* origBuffer= buffer; // for( int i= 0; i<24; i++ ) // origBuffer[i]= '\0'; const int maxFloatSignificantDigits = 16; // negative? -> turn positive if (value < 0.0) { buffer[idx++] = '-'; value = -value; } // calc dot position int exp10 = value != 0.0 ? (int)Math.Floor((Math.Log10(value))) : 0; // decide if we are using scientific format (with e) or not bool scientific = (ForceScientificFormat || (MinIntegralDigits < 0 && FractionalDigits < 0 && (exp10 > 6 || exp10 <= -5) )); int minIntegralDigits = Math.Min(MinIntegralDigits, 15); int fractionalDigits = Math.Min(FractionalDigits, 15); // result variables used for output ulong intPart; ulong fractPart; int unusedFractDigits; int firstNonZero; int intPartSize; // scientific output if (scientific) { int dotPos = maxFloatSignificantDigits - exp10; intPart = (ulong)(value * Math.Pow(10, dotPos)); fractPart = intPart % pow10_0to19[maxFloatSignificantDigits]; intPart = intPart / pow10_0to19[maxFloatSignificantDigits]; intPartSize = 1; // determine first non zero fract number firstNonZero = 0; if (fractPart > 0) { ALIB.ASSERT(maxFloatSignificantDigits - firstNonZero < 20); while (fractPart < pow10_0to19[maxFloatSignificantDigits - firstNonZero - 1]) { firstNonZero++; } ALIB.ASSERT(maxFloatSignificantDigits - firstNonZero > 0); } firstNonZero++; unusedFractDigits = fractionalDigits >= 0 ? maxFloatSignificantDigits - fractionalDigits : 1; } // normal output, number > 0 else if (exp10 >= 0) { intPartSize = maxFloatSignificantDigits - exp10; ALIB.ASSERT(intPartSize > 0 && intPartSize <= maxFloatSignificantDigits); intPart = (ulong)(value * Math.Pow(10, intPartSize)); fractPart = intPart % pow10_0to19[intPartSize]; intPart = intPart / pow10_0to19[intPartSize]; // determine first non zero fract number firstNonZero = 0; if (fractPart > 0) { ALIB.ASSERT(intPartSize - firstNonZero < 20); while (fractPart < pow10_0to19[intPartSize - firstNonZero - 1]) { firstNonZero++; } ALIB.ASSERT(intPartSize - firstNonZero > 0); } firstNonZero++; unusedFractDigits = fractionalDigits >= 0 ? intPartSize - fractionalDigits : 1; } // normal output, number < 0 else { // just zeros? -> write them and return firstNonZero = -exp10; intPart = 0; intPartSize = 1; fractPart = (ulong)(value * Math.Pow(10, maxFloatSignificantDigits + firstNonZero)); unusedFractDigits = fractionalDigits >= 0 ? maxFloatSignificantDigits - (fractionalDigits - firstNonZero) : 1; } // cut fract digits and round it up if ((fractionalDigits < 0 || fractionalDigits >= firstNonZero - 1) && unusedFractDigits > 0 && unusedFractDigits <= 18) { ulong rest = fractPart % pow10_0to19[unusedFractDigits]; fractPart = fractPart / pow10_0to19[unusedFractDigits]; if (rest > pow10_0to19[unusedFractDigits] / 2) { fractPart++; int overflowDigit = 0; bool overflow = false; while (overflowDigit <= fractionalDigits && !(overflow |= fractPart == pow10_0to19[overflowDigit]) && fractPart > pow10_0to19[overflowDigit] ) { overflowDigit++; } if (overflow) { if (overflowDigit == fractionalDigits) { fractPart = 0; intPart++; } else { ALIB.ASSERT(firstNonZero > 1); firstNonZero--; } } } } // write int part if (intPart != 0L || minIntegralDigits != 0) { idx = IntegerToString(intPart, buffer, idx, minIntegralDigits, intPartSize); } // write dot buffer[idx++] = DecimalPointCharacter; // write fract part if (fractionalDigits != 0) { int fractZeros = firstNonZero - 1; if (fractionalDigits > 0 && fractZeros > fractionalDigits) { fractZeros = fractionalDigits; } for (int i = 0; i < fractZeros; i++) { buffer[idx++] = '0'; } int qtyDigits = fractionalDigits - fractZeros; int actDigit = maxFloatSignificantDigits + 1; int cntOmittedZeros = 0; int cntDigits = 0; bool printStarted = false; while (fractPart > 0 && (qtyDigits < 0 || cntDigits < qtyDigits) ) { actDigit--; // get next d uint digitValue = (uint)(fractPart / pow10_0to19[actDigit]); ALIB.ASSERT(digitValue <= 9); // don't write, yet? if (!(printStarted |= (digitValue != 0))) { continue; } cntDigits++; // write digtit unless its a '0' if (digitValue == 0) { cntOmittedZeros++; } else { for (int i = 0; i < cntOmittedZeros; i++) { buffer[idx++] = '0'; } cntOmittedZeros = 0; buffer[idx++] = (char)(48 + digitValue); // 48= '0' } // next fractPart = fractPart % pow10_0to19[actDigit]; } // assure that if -1 for fractDigits if given,at least 1 digit is printed if (fractionalDigits < 0) { qtyDigits = 1; } // write omitted zeros if (cntDigits < qtyDigits) { for (int i = 0; i < cntOmittedZeros; i++) { buffer[idx++] = '0'; } cntDigits += cntOmittedZeros; // write missing digits for (int i = cntDigits; i < qtyDigits; i++) { buffer[idx++] = '0'; } } } // write eNN if (scientific) { for (int i = 0; i < DecimalExponentSeparator.Length; i++) { buffer[idx++] = DecimalExponentSeparator[i]; } if (exp10 < 0) { buffer[idx++] = '-'; } else if (WriteExponentPlusSign) { buffer[idx++] = '+'; } idx = IntegerToString((ulong)(exp10 >= 0 ? exp10 : -exp10), buffer, idx, 2, 3); } return(idx); }