Ignore:
Timestamp:
Apr 7, 2003, 8:40:53 PM (22 years ago)
Author:
sandervl
Message:

PF: NTDLL update for GCC 3.2.1 + resync with Wine

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/NTDLL/large_int.c

    r9684 r9986  
    33 *
    44 * Copyright 2000 Alexandre Julliard
     5 * Copyright 2003 Thomas Mertes
    56 *
    67 * This library is free software; you can redistribute it and/or
     
    185186 * This function computes (a * b) >> (64 + shift)
    186187 *
    187  * This allows replacing a division by a longlong constant
    188  * by a multiplication by the inverse constant.
    189  *
    190  * If 'c' is the constant divisor, the constants 'b' and 'shift'
    191  * must be chosen such that b = 2^(64+shift) / c.
    192  * Then we have RtlExtendedMagicDivide(a,b,shift) == a * b / 2^(64+shift) == a / c.
    193  *
    194  * I'm too lazy to implement it right now...
    195  */
    196 /* LONGLONG WINAPI RtlExtendedMagicDivide( LONGLONG a, LONGLONG b, INT shift )
    197  * {
    198  *     return 0;
    199  * }
    200  */
     188 * RETURNS
     189 *  (a * b) >> (64 + shift)
     190 *
     191 * NOTES
     192 *  This allows replacing a division by a longlong constant
     193 *  by a multiplication by the inverse constant.
     194 *
     195 *  If 'c' is the constant divisor, the constants 'b' and 'shift'
     196 *  must be chosen such that b = 2^(64+shift) / c.
     197 *  Then we have RtlExtendedMagicDivide(a,b,shift) == a * b / 2^(64+shift) == a / c.
     198 *
     199 *  The Parameter b although defined as LONGLONG is used as ULONGLONG.
     200 */
     201#define LOWER_32(A) ((A) & 0xffffffff)
     202#define UPPER_32(A) ((A) >> 32)
     203LONGLONG WINAPI RtlExtendedMagicDivide(
     204    LONGLONG a, /* [I] Dividend to be divided by the constant divisor */
     205    LONGLONG b, /* [I] Constant computed manually as 2^(64+shift) / divisor */
     206    INT shift)  /* [I] Constant shift chosen to make b as big as possible for 64 bits */
     207{
     208    ULONGLONG a_high;
     209    ULONGLONG a_low;
     210    ULONGLONG b_high;
     211    ULONGLONG b_low;
     212    ULONGLONG ah_bl;
     213    ULONGLONG al_bh;
     214    LONGLONG result;
     215    int positive;
     216
     217    if (a < 0) {
     218        a_high = UPPER_32((ULONGLONG) -a);
     219        a_low =  LOWER_32((ULONGLONG) -a);
     220        positive = 0;
     221    } else {
     222        a_high = UPPER_32((ULONGLONG) a);
     223        a_low =  LOWER_32((ULONGLONG) a);
     224        positive = 1;
     225    } /* if */
     226    b_high = UPPER_32((ULONGLONG) b);
     227    b_low =  LOWER_32((ULONGLONG) b);
     228
     229    ah_bl = a_high * b_low;
     230    al_bh = a_low * b_high;
     231
     232    result = (LONGLONG) ((a_high * b_high +
     233            UPPER_32(ah_bl) +
     234            UPPER_32(al_bh) +
     235            UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) + UPPER_32(a_low * b_low))) >> shift);
     236
     237    if (positive) {
     238        return result;
     239    } else {
     240        return -result;
     241    } /* if */
     242}
     243
     244
     245/******************************************************************************
     246 *      RtlLargeIntegerToChar   [NTDLL.@]
     247 *
     248 * Convert an unsigned large integer to a character string.
     249 *
     250 * RETURNS
     251 *  Success: STATUS_SUCCESS. str contains the converted number
     252 *  Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
     253 *           STATUS_BUFFER_OVERFLOW, if str would be larger than length.
     254 *           STATUS_ACCESS_VIOLATION, if str is NULL.
     255 *
     256 * NOTES
     257 *  Instead of base 0 it uses 10 as base.
     258 *  Writes at most length characters to the string str.
     259 *  Str is '\0' terminated when length allowes it.
     260 *  When str fits exactly in length characters the '\0' is ommitted.
     261 *  If value_ptr is NULL it crashes, as the native function does.
     262 *
     263 * DIFFERENCES
     264 * - Accept base 0 as 10 instead of crashing as native function does.
     265 * - The native function does produce garbage or STATUS_BUFFER_OVERFLOW for
     266 *   base 2, 8 and 16 when the value is larger than 0xFFFFFFFF.
     267 */
     268NTSTATUS WINAPI RtlLargeIntegerToChar(
     269    const ULONGLONG *value_ptr, /* [I] Pointer to the value to be converted */
     270    ULONG base,                 /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
     271    ULONG length,               /* [I] Length of the str buffer in bytes */
     272    PCHAR str)                  /* [O] Destination for the converted value */
     273{
     274    ULONGLONG value = *value_ptr;
     275    CHAR buffer[65];
     276    PCHAR pos;
     277    CHAR digit;
     278    ULONG len;
     279
     280    if (base == 0) {
     281        base = 10;
     282    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
     283        return STATUS_INVALID_PARAMETER;
     284    } /* if */
     285
     286    pos = &buffer[64];
     287    *pos = '\0';
     288
     289    do {
     290        pos--;
     291        digit = value % base;
     292        value = value / base;
     293        if (digit < 10) {
     294            *pos = '0' + digit;
     295        } else {
     296            *pos = 'A' + digit - 10;
     297        } /* if */
     298    } while (value != 0L);
     299
     300    len = &buffer[64] - pos;
     301    if (len > length) {
     302        return STATUS_BUFFER_OVERFLOW;
     303    } else if (str == NULL) {
     304        return STATUS_ACCESS_VIOLATION;
     305    } else if (len == length) {
     306        memcpy(str, pos, len);
     307    } else {
     308        memcpy(str, pos, len + 1);
     309    } /* if */
     310    return STATUS_SUCCESS;
     311}
     312
     313
     314/**************************************************************************
     315 *      RtlInt64ToUnicodeString (NTDLL.@)
     316 *
     317 * Convert a large unsigned integer to a '\0' terminated unicode string.
     318 *
     319 * RETURNS
     320 *  Success: STATUS_SUCCESS. str contains the converted number
     321 *  Failure: STATUS_INVALID_PARAMETER, if base is not 0, 2, 8, 10 or 16.
     322 *           STATUS_BUFFER_OVERFLOW, if str is too small to hold the string
     323 *                  (with the '\0' termination). In this case str->Length
     324 *                  is set to the length, the string would have (which can
     325 *                  be larger than the MaximumLength).
     326 *
     327 * NOTES
     328 *  Instead of base 0 it uses 10 as base.
     329 *  If str is NULL it crashes, as the native function does.
     330 *
     331 * DIFFERENCES
     332 * - Accept base 0 as 10 instead of crashing as native function does.
     333 * - Do not return STATUS_BUFFER_OVERFLOW when the string is long enough.
     334 *   The native function does this when the string would be longer than 31
     335 *   characters even when the string parameter is long enough.
     336 * - The native function does produce garbage or STATUS_BUFFER_OVERFLOW for
     337 *   base 2, 8 and 16 when the value is larger than 0xFFFFFFFF.
     338 */
     339NTSTATUS WINAPI RtlInt64ToUnicodeString(
     340    ULONGLONG value,     /* [I] Value to be converted */
     341    ULONG base,          /* [I] Number base for conversion (allowed 0, 2, 8, 10 or 16) */
     342    UNICODE_STRING *str) /* [O] Destination for the converted value */
     343{
     344    WCHAR buffer[65];
     345    PWCHAR pos;
     346    WCHAR digit;
     347
     348    if (base == 0) {
     349        base = 10;
     350    } else if (base != 2 && base != 8 && base != 10 && base != 16) {
     351        return STATUS_INVALID_PARAMETER;
     352    } /* if */
     353
     354    pos = &buffer[64];
     355    *pos = '\0';
     356
     357    do {
     358        pos--;
     359        digit = value % base;
     360        value = value / base;
     361        if (digit < 10) {
     362            *pos = '0' + digit;
     363        } else {
     364            *pos = 'A' + digit - 10;
     365        } /* if */
     366    } while (value != 0L);
     367
     368    str->Length = (&buffer[64] - pos) * sizeof(WCHAR);
     369    if (str->Length >= str->MaximumLength) {
     370        return STATUS_BUFFER_OVERFLOW;
     371    } else {
     372        memcpy(str->Buffer, pos, str->Length + sizeof(WCHAR));
     373    } /* if */
     374    return STATUS_SUCCESS;
     375}
    201376
    202377
     
    244419    return a % b;
    245420}
    246 
Note: See TracChangeset for help on using the changeset viewer.