Ignore:
Timestamp:
Jun 18, 2000, 2:55:17 PM (25 years ago)
Author:
phaller
Message:

Fix: GetNumberFormat, memory leak

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/heapstring.cpp

    r3690 r3730  
    1 /* $Id: heapstring.cpp,v 1.27 2000-06-12 12:20:05 phaller Exp $ */
     1/* $Id: heapstring.cpp,v 1.28 2000-06-18 12:55:17 phaller Exp $ */
    22
    33/*
     
    2020#include <stdlib.h>
    2121#include <string.h>
     22#include <stdio.h>
    2223#include <winnls.h>
    2324#include <unicode.h>
     
    10521053
    10531054
     1055
     1056/**************************************************************************
     1057 *           This function is used just locally !
     1058 *  Description: Inverts a string.
     1059 */
     1060static void OLE_InvertString(char* string)
     1061{   
     1062    char    sTmpArray[128];
     1063    INT     counter, i = 0;
     1064
     1065    for (counter = strlen(string); counter > 0; counter--)
     1066    {
     1067        memcpy(sTmpArray + i, string + counter-1, 1);
     1068        i++;
     1069    }
     1070    memcpy(sTmpArray + i, "\0", 1);
     1071    strcpy(string, sTmpArray);
     1072}
     1073
     1074/***************************************************************************************
     1075 *           This function is used just locally !
     1076 *  Description: Test if the given string (psNumber) is valid or not.
     1077 *               The valid characters are the following:
     1078 *               - Characters '0' through '9'.
     1079 *               - One decimal point (dot) if the number is a floating-point value.
     1080 *               - A minus sign in the first character position if the number is
     1081 *                 a negative value.
     1082 *              If the function succeeds, psBefore/psAfter will point to the string
     1083 *              on the right/left of the decimal symbol. pbNegative indicates if the
     1084 *              number is negative.
     1085 */
     1086static INT OLE_GetNumberComponents(char* pInput, char* psBefore, char* psAfter, BOOL* pbNegative)
     1087{
     1088char    sNumberSet[] = "0123456789";
     1089BOOL    bInDecimal = FALSE;
     1090
     1091        /* Test if we do have a minus sign */
     1092        if ( *pInput == '-' )
     1093        {
     1094                *pbNegative = TRUE;
     1095                pInput++; /* Jump to the next character. */
     1096        }
     1097       
     1098        while(*pInput != '\0')
     1099        {
     1100                /* Do we have a valid numeric character */
     1101                if ( strchr(sNumberSet, *pInput) != NULL )
     1102                {
     1103                        if (bInDecimal == TRUE)
     1104                *psAfter++ = *pInput;
     1105                        else
     1106                *psBefore++ = *pInput;
     1107                }
     1108                else
     1109                {
     1110                        /* Is this a decimal point (dot) */
     1111                        if ( *pInput == '.' )
     1112                        {
     1113                                /* Is it the first time we find it */
     1114                                if ((bInDecimal == FALSE))
     1115                                        bInDecimal = TRUE;
     1116                                else
     1117                                        return -1; /* ERROR: Invalid parameter */
     1118                        }
     1119                        else
     1120                        {
     1121                                /* It's neither a numeric character, nor a decimal point.
     1122                                 * Thus, return an error.
     1123                 */
     1124                                return -1;
     1125                        }
     1126                }
     1127        pInput++;
     1128        }
     1129       
     1130        /* Add an End of Line character to the output buffers */
     1131        *psBefore = '\0';
     1132        *psAfter = '\0';
     1133
     1134        return 0;
     1135}
     1136
     1137/**************************************************************************
     1138 *           This function is used just locally !
     1139 *  Description: A number could be formatted using different numbers
     1140 *               of "digits in group" (example: 4;3;2;0).
     1141 *               The first parameter of this function is an array
     1142 *               containing the rule to be used. It's format is the following:
     1143 *               |NDG|DG1|DG2|...|0|
     1144 *               where NDG is the number of used "digits in group" and DG1, DG2,
     1145 *               are the corresponding "digits in group".
     1146 *               Thus, this function returns the grouping value in the array
     1147 *               pointed by the second parameter.
     1148 */
     1149static INT OLE_GetGrouping(char* sRule, INT index)
     1150{
     1151    char    sData[2], sRuleSize[2];
     1152    INT     nData, nRuleSize;
     1153
     1154    memcpy(sRuleSize, sRule, 1);
     1155    memcpy(sRuleSize+1, "\0", 1);
     1156    nRuleSize = atoi(sRuleSize);
     1157
     1158    if (index > 0 && index < nRuleSize)
     1159    {
     1160        memcpy(sData, sRule+index, 1);
     1161        memcpy(sData+1, "\0", 1);
     1162        nData = atoi(sData);           
     1163    }
     1164       
     1165    else
     1166    {
     1167        memcpy(sData, sRule+nRuleSize-1, 1);
     1168        memcpy(sData+1, "\0", 1);
     1169        nData = atoi(sData);           
     1170    }
     1171   
     1172    return nData;
     1173}
     1174
     1175
    10541176/*****************************************************************************
    10551177 * Name      : GetNumberFormat
     
    10581180 * Variables :
    10591181 * Result    :
    1060  * Remark    :
     1182 * Remark    : KERNEL32.355
    10611183 * Status    :
    10621184 *
     
    10651187
    10661188
    1067 ODINFUNCTION6(int,               GetNumberFormatA,
    1068               LCID,              Locale,
    1069               DWORD,             dwFlags,
    1070               LPCSTR,            lpValue,
     1189ODINFUNCTION6(INT,               GetNumberFormatA,
     1190              LCID,              locale,
     1191              DWORD,             dwflags,
     1192              LPCSTR,            lpvalue,
    10711193              CONST NUMBERFMTA *,lpFormat,
    10721194              LPSTR,             lpNumberStr,
    10731195              int,               cchNumber)
    10741196{
    1075   dprintf(("GetNumberFormatA(%08x,%08x,%s,%08x,%s,%08x) not properly implemented.\n",
    1076            Locale,
    1077            dwFlags,
    1078            lpValue,
    1079            lpFormat,
    1080            lpNumberStr,
    1081            cchNumber));
     1197  dprintf(("not properly implemented.\n"));
    10821198 
    1083   // @@@PH cheap ass emulation
    1084   lstrcpynA(lpNumberStr,
    1085             lpValue,
    1086             cchNumber);
    1087  
    1088   return lstrlenA(lpNumberStr);
    1089 }
     1199  char   sNumberDigits[3], sDecimalSymbol[5], sDigitsInGroup[11], sDigitGroupSymbol[5], sILZero[2];
     1200  INT    nNumberDigits, nNumberDecimal, i, j, nCounter, nStep, nRuleIndex, nGrouping, nDigits, retVal, nLZ;
     1201  char   sNumber[128], sDestination[128], sDigitsAfterDecimal[10], sDigitsBeforeDecimal[128];
     1202  char   sRule[10], sSemiColumn[]=";", sBuffer[5], sNegNumber[2];
     1203  char   *pStr = NULL, *pTmpStr = NULL;
     1204  LCID   systemDefaultLCID;
     1205  BOOL   bNegative = FALSE;
     1206  enum   Operations
     1207  {
     1208    USE_PARAMETER,
     1209    USE_LOCALEINFO,
     1210    USE_SYSTEMDEFAULT,
     1211    RETURN_ERROR
     1212  } used_operation;
     1213
     1214  strncpy(sNumber, lpvalue, 128);
     1215  sNumber[127] = '\0';
     1216
     1217  /* Make sure we have a valid input string, get the number
     1218   * of digits before and after the decimal symbol, and check
     1219   * if this is a negative number.
     1220   */
     1221  if ( OLE_GetNumberComponents(sNumber, sDigitsBeforeDecimal, sDigitsAfterDecimal, &bNegative) != -1)
     1222  {
     1223    nNumberDecimal = strlen(sDigitsBeforeDecimal);
     1224    nDigits = strlen(sDigitsAfterDecimal);
     1225  }
     1226  else
     1227  {
     1228    SetLastError(ERROR_INVALID_PARAMETER);
     1229    return 0;
     1230  }
     1231
     1232  /* Which source will we use to format the string */
     1233  used_operation = RETURN_ERROR;
     1234  if (lpFormat != NULL)
     1235  {
     1236    if (dwflags == 0)
     1237      used_operation = USE_PARAMETER;
     1238  }
     1239  else
     1240  {
     1241    if (dwflags & LOCALE_NOUSEROVERRIDE)
     1242      used_operation = USE_LOCALEINFO;
     1243    else
     1244      used_operation = USE_SYSTEMDEFAULT;
     1245  }
     1246
     1247  /* Load the fields we need */
     1248  switch(used_operation)
     1249  {
     1250    case USE_LOCALEINFO:
     1251        GetLocaleInfoA(locale, LOCALE_IDIGITS, sNumberDigits, sizeof(sNumberDigits));
     1252        GetLocaleInfoA(locale, LOCALE_SDECIMAL, sDecimalSymbol, sizeof(sDecimalSymbol));
     1253        GetLocaleInfoA(locale, LOCALE_SGROUPING, sDigitsInGroup, sizeof(sDigitsInGroup));
     1254        GetLocaleInfoA(locale, LOCALE_STHOUSAND, sDigitGroupSymbol, sizeof(sDigitGroupSymbol));
     1255        GetLocaleInfoA(locale, LOCALE_ILZERO, sILZero, sizeof(sILZero));
     1256        GetLocaleInfoA(locale, LOCALE_INEGNUMBER, sNegNumber, sizeof(sNegNumber));
     1257        break;
     1258    case USE_PARAMETER:
     1259        sprintf(sNumberDigits, "%d",lpFormat->NumDigits);
     1260        strcpy(sDecimalSymbol, lpFormat->lpDecimalSep);
     1261        sprintf(sDigitsInGroup, "%d;0",lpFormat->Grouping);
     1262        strcpy(sDigitGroupSymbol, lpFormat->lpThousandSep);
     1263        sprintf(sILZero, "%d",lpFormat->LeadingZero);
     1264        sprintf(sNegNumber, "%d",lpFormat->NegativeOrder);
     1265        break;
     1266    case USE_SYSTEMDEFAULT:
     1267        systemDefaultLCID = GetSystemDefaultLCID();
     1268        GetLocaleInfoA(systemDefaultLCID, LOCALE_IDIGITS, sNumberDigits, sizeof(sNumberDigits));
     1269        GetLocaleInfoA(systemDefaultLCID, LOCALE_SDECIMAL, sDecimalSymbol, sizeof(sDecimalSymbol));
     1270        GetLocaleInfoA(systemDefaultLCID, LOCALE_SGROUPING, sDigitsInGroup, sizeof(sDigitsInGroup));
     1271        GetLocaleInfoA(systemDefaultLCID, LOCALE_STHOUSAND, sDigitGroupSymbol, sizeof(sDigitGroupSymbol));
     1272        GetLocaleInfoA(systemDefaultLCID, LOCALE_ILZERO, sILZero, sizeof(sILZero));
     1273        GetLocaleInfoA(systemDefaultLCID, LOCALE_INEGNUMBER, sNegNumber, sizeof(sNegNumber));
     1274        break;
     1275    default:
     1276        SetLastError(ERROR_INVALID_PARAMETER);
     1277        return 0;
     1278    }
     1279
     1280    nNumberDigits = atoi(sNumberDigits);
     1281   
     1282    /* Remove the ";" */
     1283    i=0;
     1284    j = 1;
     1285    for (nCounter=0; nCounter<strlen(sDigitsInGroup); nCounter++)
     1286    {
     1287        if ( memcmp(sDigitsInGroup + nCounter, sSemiColumn, 1) != 0 )
     1288        {
     1289            memcpy(sRule + j, sDigitsInGroup + nCounter, 1);
     1290            i++;
     1291            j++;
     1292        }
     1293    }
     1294    sprintf(sBuffer, "%d", i);
     1295    memcpy(sRule, sBuffer, 1); /* Number of digits in the groups ( used by OLE_GetGrouping() ) */
     1296    memcpy(sRule + j, "\0", 1);
     1297   
     1298    /* First, format the digits before the decimal. */
     1299    if ((nNumberDecimal>0) && (atoi(sDigitsBeforeDecimal) != 0))
     1300    {
     1301        /* Working on an inverted string is easier ! */
     1302        OLE_InvertString(sDigitsBeforeDecimal);
     1303
     1304        nStep = nCounter = i = j = 0;
     1305        nRuleIndex = 1;
     1306        nGrouping = OLE_GetGrouping(sRule, nRuleIndex);
     1307       
     1308        /* Here, we will loop until we reach the end of the string.
     1309         * An internal counter (j) is used in order to know when to
     1310         * insert the "digit group symbol".
     1311         */
     1312        while (nNumberDecimal > 0)
     1313        {
     1314            i = nCounter + nStep;
     1315            memcpy(sDestination + i, sDigitsBeforeDecimal + nCounter, 1);
     1316            nCounter++;
     1317            j++;
     1318            if (j >= nGrouping)
     1319            {
     1320                j = 0;
     1321                if (nRuleIndex < sRule[0])
     1322                    nRuleIndex++;
     1323                nGrouping = OLE_GetGrouping(sRule, nRuleIndex);
     1324                memcpy(sDestination + i+1, sDigitGroupSymbol, strlen(sDigitGroupSymbol));
     1325                nStep+= strlen(sDigitGroupSymbol);
     1326            }
     1327
     1328            nNumberDecimal--;
     1329        }
     1330
     1331        memcpy(sDestination + i+1, "\0", 1);
     1332        /* Get the string in the right order ! */
     1333        OLE_InvertString(sDestination);
     1334     }
     1335     else
     1336     {
     1337        nLZ = atoi(sILZero);
     1338        if (nLZ != 0)
     1339        {       
     1340            /* Use 0.xxx instead of .xxx */
     1341            memcpy(sDestination, "0", 1);
     1342            memcpy(sDestination+1, "\0", 1);
     1343        }
     1344        else
     1345            memcpy(sDestination, "\0", 1);
     1346
     1347     }
     1348
     1349    /* Second, format the digits after the decimal. */
     1350    j = 0;
     1351    nCounter = nNumberDigits;
     1352    if ( (nDigits>0) && (pStr = strstr (sNumber, ".")) )
     1353    {
     1354        i = strlen(sNumber) - strlen(pStr) + 1;       
     1355        strncpy ( sDigitsAfterDecimal, sNumber + i, nNumberDigits);
     1356        j = strlen(sDigitsAfterDecimal);
     1357        if (j < nNumberDigits)
     1358            nCounter = nNumberDigits-j;           
     1359    }
     1360    for (i=0;i<nCounter;i++)
     1361         memcpy(sDigitsAfterDecimal+i+j, "0", 1);   
     1362    memcpy(sDigitsAfterDecimal + nNumberDigits, "\0", 1);   
     1363
     1364    i = strlen(sDestination);
     1365    j = strlen(sDigitsAfterDecimal);
     1366    /* Finally, construct the resulting formatted string. */
     1367       
     1368    for (nCounter=0; nCounter<i; nCounter++)
     1369        memcpy(sNumber + nCounter, sDestination + nCounter, 1);
     1370       
     1371    memcpy(sNumber + nCounter, sDecimalSymbol, strlen(sDecimalSymbol));
     1372
     1373    for (i=0; i<j; i++)
     1374        memcpy(sNumber + nCounter+i+strlen(sDecimalSymbol), sDigitsAfterDecimal + i, 1);
     1375    memcpy(sNumber + nCounter+i+strlen(sDecimalSymbol), "\0", 1);
     1376       
     1377    /* Is it a negative number */
     1378    if (bNegative == TRUE)
     1379    {
     1380        i = atoi(sNegNumber);
     1381        pStr = sDestination;
     1382        pTmpStr = sNumber;
     1383        switch (i)
     1384        {         
     1385        case 0:
     1386            *pStr++ = '(';
     1387            while (*sNumber != '\0')
     1388                *pStr++ =  *pTmpStr++;
     1389            *pStr++ = ')';               
     1390            break; 
     1391        case 1:
     1392            *pStr++ = '-';
     1393            while (*pTmpStr != '\0')
     1394                *pStr++ =  *pTmpStr++;
     1395            break;
     1396        case 2:
     1397            *pStr++ = '-';
     1398            *pStr++ = ' ';
     1399            while (*pTmpStr != '\0')
     1400                *pStr++ =  *pTmpStr++;
     1401            break;
     1402        case 3:
     1403            while (*pTmpStr != '\0')
     1404                *pStr++ =  *pTmpStr++;
     1405            *pStr++ = '-';
     1406            break;
     1407        case 4:
     1408            while (*pTmpStr != '\0')
     1409                *pStr++ =  *pTmpStr++;
     1410            *pStr++ = ' ';
     1411            *pStr++ = '-';
     1412            break;
     1413        default:
     1414            while (*pTmpStr != '\0')
     1415                *pStr++ =  *pTmpStr++;
     1416            break;
     1417        }
     1418    }
     1419    else
     1420        strcpy(sDestination, sNumber);
     1421
     1422    /* If cchNumber is zero, then returns the number of bytes or characters
     1423     * required to hold the formatted number string
     1424     */
     1425    if (cchNumber==0)
     1426        retVal = strlen(sDestination) + 1;
     1427    else           
     1428    {
     1429        strncpy (lpNumberStr, sDestination, cchNumber-1);
     1430        *(lpNumberStr+cchNumber-1) = '\0';   /* ensure we got a NULL at the end */
     1431        retVal = strlen(lpNumberStr);
     1432    }
     1433         
     1434    return retVal;
     1435}
     1436
     1437
    10901438
    10911439
     
    11031451
    11041452int WIN32API GetNumberFormatW(LCID     Locale,
    1105                                  DWORD    dwFlags,
    1106                                  LPCWSTR lpValue,
    1107                                  CONST NUMBERFMTW *lpFormat,
    1108                                  LPWSTR  lpNumberStr,
    1109                                  int      cchNumber)
     1453                              DWORD    dwFlags,
     1454                              LPCWSTR lpValue,
     1455                              CONST NUMBERFMTW *lpFormat,
     1456                              LPWSTR  lpNumberStr,
     1457                              int      cchNumber)
    11101458{
    11111459  dprintf(("GetNumberFormatW(%08x,%08x,%s,%08x,%s,%08x) not properly implemented.\n",
Note: See TracChangeset for help on using the changeset viewer.