VirtualBox

Changeset 59734 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Feb 19, 2016 2:15:41 AM (9 years ago)
Author:
vboxsync
Message:

USBIdDatabaseGenerator: Reduced the string copying during parsing.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/USBIdDatabaseGenerator.cpp

    r59733 r59734  
    5858/** For verbose output.   */
    5959static bool g_fVerbose = false;
    60 /** Output prefix for informational output. */
    61 #define INFO_PREF "USBIdDatabaseGenerator: Info: "
    62 
    63 
    64 using namespace std;
    6560
    6661static const char * const header =
     
    151146};
    152147
    153 
    154 namespace State
    155 {
    156     typedef int Value;
    157     enum
    158     {
    159         lookForStartBlock,
    160         lookForEndBlock,
    161         finished
    162     };
    163 }
    164 
    165 typedef vector<ProductRecord> ProductsSet;
    166 typedef vector<VendorRecord> VendorsSet;
     148typedef std::vector<ProductRecord> ProductsSet;
     149typedef std::vector<VendorRecord> VendorsSet;
    167150
    168151
     
    202185 * Input file parsing.
    203186 */
    204 int ParseAlias(const string& src, size_t& id, string& desc)
    205 {
    206     unsigned int i = 0;
    207     if (sscanf(src.c_str(), "%x", &i) != 1)
    208         return ERROR_IN_PARSE_LINE;
    209 
    210     /* skip the number and following whitespace. */
    211     size_t offNext = src.find_first_of(" \t", 1);
    212     offNext = src.find_first_not_of(" \t", offNext);
    213     if (offNext != string::npos)
    214     {
    215         size_t cchLength = src.length() - offNext;
    216         if (cchLength <= USB_ID_DATABASE_MAX_STRING)
    217         {
    218             id = i;
    219             desc = src.substr(offNext);
    220 
    221             /* Check the string encoding. */
    222             int rc = RTStrValidateEncoding(desc.c_str());
     187int ParseAlias(char *pszLine, size_t& id, std::string& desc)
     188{
     189    /* First there's a hexadeciman number. */
     190    uint32_t uVal;
     191    char *pszNext;
     192    int rc = RTStrToUInt32Ex(pszLine, &pszNext, 16, &uVal);
     193    if (   rc == VWRN_TRAILING_CHARS
     194        || rc == VWRN_TRAILING_SPACES
     195        || rc == VINF_SUCCESS)
     196    {
     197        /* Skip the whipespace following it and at the end of the line. */
     198        pszNext = RTStrStripL(pszNext);
     199        if (*pszNext != '\0')
     200        {
     201            rc = RTStrValidateEncoding(pszNext);
    223202            if (RT_SUCCESS(rc))
    224203            {
    225                 g_cbRawStrings += desc.length() + 1;
    226                 return RTEXITCODE_SUCCESS;
     204                size_t cchDesc = strlen(pszNext);
     205                if (cchDesc <= USB_ID_DATABASE_MAX_STRING)
     206                {
     207                    id   = uVal;
     208                    desc = pszNext;
     209                    g_cbRawStrings += cchDesc + 1;
     210                    return RTEXITCODE_SUCCESS;
     211                }
     212                RTMsgError("String to long: %zu", cchDesc);
    227213            }
    228 
    229             RTMsgError("Invalid encoding: '%s' (rc=%Rrc)", desc.c_str(), rc);
     214            else
     215                RTMsgError("Invalid encoding: '%s' (rc=%Rrc)", pszNext, rc);
    230216        }
    231217        else
    232             RTMsgError("String to long: %zu", cchLength);
     218            RTMsgError("Error parsing '%s'", pszLine);
    233219    }
    234220    else
    235         RTMsgError("Error parsing '%s'", src.c_str());
     221        RTMsgError("Error converting number at the start of '%s': %Rrc", pszLine, rc);
    236222    return ERROR_IN_PARSE_LINE;
    237223}
    238224
    239 bool IsCommentOrEmptyLine(const string& str)
    240 {
    241     size_t index = str.find_first_not_of(" \t");// skip left spaces
    242     return index == string::npos || str[index] == '#';
    243 }
    244 
    245 bool getline(PRTSTREAM instream, string& resString)
    246 {
    247     const size_t szBuf = 4096;
    248     char buf[szBuf] = { 0 };
    249 
    250     int rc = RTStrmGetLine(instream, buf, szBuf);
    251     if (RT_SUCCESS(rc))
    252     {
    253         resString = buf;
    254         return true;
    255     }
    256 
    257     if (rc != VERR_EOF)
    258         RTMsgWarning("RTStrmGetLine failed: %Rrc", rc);
    259     return false;
     225bool IsCommentOrEmptyLine(const char *pszLine)
     226{
     227    pszLine = RTStrStripL(pszLine);
     228    return *pszLine == '#' || *pszLine == '\0';
    260229}
    261230
    262231int ParseUsbIds(PRTSTREAM instream)
    263232{
    264     State::Value state = State::lookForStartBlock;
    265     string line;
    266     int res = 0;
     233    /*
     234     * State data.
     235     * We check for a certain comment string before processing data.
     236     */
     237    bool fLookingForData = false;
    267238    VendorRecord vendor = { 0, 0, 0, "" };
    268239
    269     while (state != State::finished && getline(instream, line))
    270     {
    271         switch (state)
    272         {
    273             case State::lookForStartBlock:
     240    /*
     241     * Process the file line-by-line.
     242     */
     243    for (;;)
     244    {
     245        char szLine[_4K];
     246        int rc = RTStrmGetLine(instream, szLine, sizeof(szLine));
     247        if (RT_SUCCESS(rc))
     248        {
     249            if (!fLookingForData)
    274250            {
    275                 if (line.find(start_block) != string::npos)
    276                     state = State::lookForEndBlock;
    277                 break;
    278             }
    279             case State::lookForEndBlock:
    280             {
    281                 if (line.find(end_block) != string::npos)
    282                     state = State::finished;
    283                 else
     251                if (!strstr(szLine, end_block))
    284252                {
    285                     if (!IsCommentOrEmptyLine(line))
     253                    if (!IsCommentOrEmptyLine(szLine))
    286254                    {
    287                         if (line[0] == '\t')
     255                        if (szLine[0] == '\t')
    288256                        {
    289257                            // Parse Product line
     
    291259                            if (vendor.vendorID == 0)
    292260                                return RTMsgErrorExit((RTEXITCODE)ERROR_WRONG_FILE_FORMAT,
    293                                                       "Wrong file format. Product before vendor: '%s'", line.c_str());
     261                                                      "Wrong file format. Product before vendor: '%s'", szLine);
    294262                            ProductRecord product = { 0, vendor.vendorID, 0, "" };
    295                             if (ParseAlias(line.substr(1), product.productID, product.str) != 0)
     263                            if (ParseAlias(&szLine[1], product.productID, product.str) != 0)
    296264                                return RTMsgErrorExit((RTEXITCODE)ERROR_IN_PARSE_LINE,
    297                                                       "Error in parsing product line: '", line.c_str());
     265                                                      "Error in parsing product line: '%s'", szLine);
    298266                            product.key = RT_MAKE_U32(product.productID, product.vendorID);
    299267                            Assert(product.vendorID == vendor.vendorID);
     
    303271                        {
    304272                            // Parse vendor line
    305                             if (ParseAlias(line, vendor.vendorID, vendor.str) != 0)
     273                            if (ParseAlias(szLine, vendor.vendorID, vendor.str) != 0)
    306274                                return RTMsgErrorExit((RTEXITCODE)ERROR_IN_PARSE_LINE,
    307                                                       "Error in parsing vendor line: '", line.c_str());
     275                                                      "Error in parsing vendor line: '%s'", szLine);
    308276                            g_vendors.push_back(vendor);
    309277                        }
    310278                    }
    311279                }
    312                 break;
     280                else
     281                    return RTEXITCODE_SUCCESS;
    313282            }
    314         }
    315     }
    316     if (state == State::lookForStartBlock)
    317         return RTMsgErrorExit((RTEXITCODE)ERROR_WRONG_FILE_FORMAT,
    318                               "wrong format of input file. Start line is not found.");
    319     return 0;
     283            else if (strstr(szLine, start_block))
     284                fLookingForData = false;
     285        }
     286        else if (rc == VERR_EOF)
     287            return RTEXITCODE_SUCCESS;
     288        else
     289            return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTStrmGetLine failed: %Rrc", rc);
     290    }
    320291}
    321292
     
    442413
    443414    /*
    444      * Print stats.
     415     * Print stats.  Making a little extra effort to get it all on one line.
    445416     */
    446417    size_t const cbVendorEntry  = sizeof(USBIdDatabase::s_aVendors[0]) + sizeof(USBIdDatabase::s_aVendorNames[0]);
     
    453424    cbActual += sizeof(StrTab.aCompDict);
    454425#endif
    455     cout << INFO_PREF "Total " << dec << cbActual << " bytes";
     426
     427    char szMsg1[32];
     428    RTStrPrintf(szMsg1, sizeof(szMsg1),"Total %zu bytes", cbActual);
     429    char szMsg2[64];
     430    RTStrPrintf(szMsg2, sizeof(szMsg2)," old version %zu bytes + relocs (%zu%% save)",
     431                cbOldRaw, (cbOldRaw - cbActual) * 100 / cbOldRaw);
    456432    if (cbActual < cbRaw)
    457         cout << " saving " << dec << ((cbRaw - cbActual) * 100 / cbRaw) << "% (" << (cbRaw - cbActual) << " bytes)";
     433        RTMsgInfo("%s - saving %zu%% (%zu bytes);%s", szMsg1, (cbRaw - cbActual) * 100 / cbRaw, cbRaw - cbActual, szMsg2);
    458434    else
    459         cout << " wasting " << dec << (cbActual - cbRaw) << " bytes";
    460     cout << "; old version " << cbOldRaw << " bytes + relocs ("
    461          << ((cbOldRaw - cbActual) * 100 / cbOldRaw) << "% save)." << endl;
    462 
     435        RTMsgInfo("%s - wasting %zu bytes;%s", szMsg1, cbActual - cbRaw, szMsg2);
    463436
    464437    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette