LCOV - app.info - objdir/xpcom/build/nsINIParser.cpp

LCOV - code coverage report
| Current view: | directory - objdir/xpcom/build - nsINIParser.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 107 | 77 | 72.0 %
| Date: | 2012-07-07 | Functions: | 13 | 10 | 76.9 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is Mozilla Communicator client code, released
          16                 :  * March 31, 1998.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Netscape Communications Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   Samir Gehani <sgehani@netscape.com>
          25                 :  *   Benjamin Smedberg <bsmedberg@covad.net>
          26                 :  *
          27                 :  * Alternatively, the contents of this file may be used under the terms of
          28                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          29                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          31                 :  * of those above. If you wish to allow use of your version of this file only
          32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          33                 :  * use your version of this file under the terms of the MPL, indicate your
          34                 :  * decision by deleting the provisions above and replace them with the notice
          35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          36                 :  * the provisions above, a recipient may use your version of this file under
          37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : #include "nsINIParser.h"
          42                 : #include "nsError.h"
          43                 : #include "nsILocalFile.h"
          44                 : #include "nsCRTGlue.h"
          45                 :
          46                 : #include <stdlib.h>
          47                 : #include <stdio.h>
          48                 : #ifdef XP_WIN
          49                 : #include <windows.h>
          50                 : #endif
          51                 :
          52                 : #if defined(XP_WIN)
          53                 : #define READ_BINARYMODE L"rb"
          54                 : #elif defined(XP_OS2)
          55                 : #define READ_BINARYMODE "rb"
          56                 : #else
          57                 : #define READ_BINARYMODE "r"
          58                 : #endif
          59                 :
          60                 : #ifdef XP_WIN
          61                 : inline FILE *TS_tfopen (const char *path, const wchar_t *mode)
          62                 : {
          63                 :     wchar_t wPath[MAX_PATH];
          64                 :     MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, MAX_PATH);
          65                 :     return _wfopen(wPath, mode);
          66                 : }
          67                 : #else
          68               0 : inline FILE *TS_tfopen (const char *path, const char *mode)
          69                 : {
          70               0 :     return fopen(path, mode);
          71                 : }
          72                 : #endif
          73                 :
          74                 : // Stack based FILE wrapper to ensure that fclose is called, copied from
          75                 : // toolkit/mozapps/update/updater/readstrings.cpp
          76                 :
          77                 : class AutoFILE {
          78                 : public:
          79            1214 :   AutoFILE(FILE *fp = nsnull) : fp_(fp) {}
          80            1214 :   ~AutoFILE() { if (fp_) fclose(fp_); }
          81            2428 :   operator FILE *() { return fp_; }
          82                 :   FILE** operator &() { return &fp_; }
          83            1214 :   void operator=(FILE *fp) { fp_ = fp; }
          84                 : private:
          85                 :   FILE *fp_;
          86                 : };
          87                 :
          88                 : nsresult
          89            1214 : nsINIParser::Init(nsILocalFile* aFile)
          90                 : {
          91                 :     /* open the file. Don't use OpenANSIFileDesc, because you mustn't
          92                 :        pass FILE* across shared library boundaries, which may be using
          93                 :        different CRTs */
          94                 :
          95            2428 :     AutoFILE fd;
          96                 :
          97                 : #ifdef XP_WIN
          98                 :     nsAutoString path;
          99                 :     nsresult rv = aFile->GetPath(path);
         100                 :     NS_ENSURE_SUCCESS(rv, rv);
         101                 :
         102                 :     fd = _wfopen(path.get(), READ_BINARYMODE);
         103                 : #else
         104            2428 :     nsCAutoString path;
         105            1214 :     aFile->GetNativePath(path);
         106                 :
         107            1214 :     fd = fopen(path.get(), READ_BINARYMODE);
         108                 : #endif
         109                 :
         110            1214 :     if (!fd)
         111               0 :       return NS_ERROR_FAILURE;
         112                 :
         113            1214 :     return InitFromFILE(fd);
         114                 : }
         115                 :
         116                 : nsresult
         117               0 : nsINIParser::Init(const char *aPath)
         118                 : {
         119                 :     /* open the file */
         120               0 :     AutoFILE fd = TS_tfopen(aPath, READ_BINARYMODE);
         121                 :
         122               0 :     if (!fd)
         123               0 :         return NS_ERROR_FAILURE;
         124                 :
         125               0 :     return InitFromFILE(fd);
         126                 : }
         127                 :
         128                 : static const char kNL[] = "\r\n";
         129                 : static const char kEquals[] = "=";
         130                 : static const char kWhitespace[] = " \t";
         131                 : static const char kRBracket[] = "]";
         132                 :
         133                 : nsresult
         134            1214 : nsINIParser::InitFromFILE(FILE *fd)
         135                 : {
         136            1214 :     if (!mSections.Init())
         137               0 :         return NS_ERROR_OUT_OF_MEMORY;
         138                 :
         139                 :     /* get file size */
         140            1214 :     if (fseek(fd, 0, SEEK_END) != 0)
         141               0 :         return NS_ERROR_FAILURE;
         142                 :
         143            1214 :     long flen = ftell(fd);
         144            1214 :     if (flen == 0)
         145               0 :         return NS_ERROR_FAILURE;
         146                 :
         147                 :     /* malloc an internal buf the size of the file */
         148            2428 :     mFileContents = new char[flen + 1];
         149            1214 :     if (!mFileContents)
         150               0 :         return NS_ERROR_OUT_OF_MEMORY;
         151                 :
         152                 :     /* read the file in one swoop */
         153            1214 :     if (fseek(fd, 0, SEEK_SET) != 0)
         154               0 :         return NS_BASE_STREAM_OSERROR;
         155                 :
         156            1214 :     int rd = fread(mFileContents, sizeof(char), flen, fd);
         157            1214 :     if (rd != flen)
         158               0 :         return NS_BASE_STREAM_OSERROR;
         159                 :
         160            1214 :     mFileContents[flen] = '\0';
         161                 :
         162            1214 :     char *buffer = mFileContents;
         163            1214 :     char *currSection = nsnull;
         164                 :
         165                 :     // outer loop tokenizes into lines
         166           11732 :     while (char *token = NS_strtok(kNL, &buffer)) {
         167            5259 :         if (token[0] == '#' || token[0] == ';') // it's a comment
         168               5 :             continue;
         169                 :
         170            5254 :         token = (char*) NS_strspnp(kWhitespace, token);
         171            5254 :         if (!*token) // empty line
         172               0 :             continue;
         173                 :
         174            5254 :         if (token[0] == '[') { // section header!
         175            2410 :             ++token;
         176            2410 :             currSection = token;
         177                 :
         178            2410 :             char *rb = NS_strtok(kRBracket, &token);
         179            2410 :             if (!rb || NS_strtok(kWhitespace, &token)) {
         180                 :                 // there's either an unclosed [Section or a [Section]Moretext!
         181                 :                 // we could frankly decide that this INI file is malformed right
         182                 :                 // here and stop, but we won't... keep going, looking for
         183                 :                 // a well-formed [section] to continue working with
         184               2 :                 currSection = nsnull;
         185                 :             }
         186                 :
         187            2410 :             continue;
         188                 :         }
         189                 :
         190            2844 :         if (!currSection) {
         191                 :             // If we haven't found a section header (or we found a malformed
         192                 :             // section header), don't bother parsing this line.
         193               0 :             continue;
         194                 :         }
         195                 :
         196            2844 :         char *key = token;
         197            2844 :         char *e = NS_strtok(kEquals, &token);
         198            2844 :         if (!e || !token)
         199               1 :             continue;
         200                 :
         201                 :         INIValue *v;
         202            2843 :         if (!mSections.Get(currSection, &v)) {
         203            1533 :             v = new INIValue(key, token);
         204            1533 :             if (!v)
         205               0 :                 return NS_ERROR_OUT_OF_MEMORY;
         206                 :
         207            1533 :             mSections.Put(currSection, v);
         208            1533 :             continue;
         209                 :         }
         210                 :
         211                 :         // Check whether this key has already been specified; overwrite
         212                 :         // if so, or append if not.
         213            4764 :         while (v) {
         214            3454 :             if (!strcmp(key, v->key)) {
         215               1 :                 v->value = token;
         216               1 :                 break;
         217                 :             }
         218            3453 :             if (!v->next) {
         219            1309 :                 v->next = new INIValue(key, token);
         220            1309 :                 if (!v->next)
         221               0 :                     return NS_ERROR_OUT_OF_MEMORY;
         222            1309 :                 break;
         223                 :             }
         224            2144 :             v = v->next;
         225                 :         }
         226            1310 :         NS_ASSERTION(v, "v should never be null coming out of this loop");
         227                 :     }
         228                 :
         229            1214 :     return NS_OK;
         230                 : }
         231                 :
         232                 : nsresult
         233            2820 : nsINIParser::GetString(const char *aSection, const char *aKey,
         234                 :                        nsACString &aResult)
         235                 : {
         236                 :     INIValue *val;
         237            2820 :     mSections.Get(aSection, &val);
         238                 :
         239            9070 :     while (val) {
         240            6249 :         if (strcmp(val->key, aKey) == 0) {
         241            2819 :             aResult.Assign(val->value);
         242            2819 :             return NS_OK;
         243                 :         }
         244                 :
         245            3430 :         val = val->next;
         246                 :     }
         247                 :
         248               1 :     return NS_ERROR_FAILURE;
         249                 : }
         250                 :
         251                 : nsresult
         252               0 : nsINIParser::GetString(const char *aSection, const char *aKey,
         253                 :                        char *aResult, PRUint32 aResultLen)
         254                 : {
         255                 :     INIValue *val;
         256               0 :     mSections.Get(aSection, &val);
         257                 :
         258               0 :     while (val) {
         259               0 :         if (strcmp(val->key, aKey) == 0) {
         260               0 :             strncpy(aResult, val->value, aResultLen);
         261               0 :             aResult[aResultLen - 1] = '\0';
         262               0 :             if (strlen(val->value) >= aResultLen)
         263               0 :                 return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
         264                 :
         265               0 :             return NS_OK;
         266                 :         }
         267                 :
         268               0 :         val = val->next;
         269                 :     }
         270                 :
         271               0 :     return NS_ERROR_FAILURE;
         272                 : }
         273                 :
         274                 : PLDHashOperator
         275              31 : nsINIParser::GetSectionsCB(const char *aKey, INIValue *aData,
         276                 :                            void *aClosure)
         277                 : {
         278              31 :     GSClosureStruct *cs = reinterpret_cast<GSClosureStruct*>(aClosure);
         279                 :
         280              31 :     return cs->usercb(aKey, cs->userclosure) ? PL_DHASH_NEXT : PL_DHASH_STOP;
         281                 : }
         282                 :
         283                 : nsresult
         284              27 : nsINIParser::GetSections(INISectionCallback aCB, void *aClosure)
         285                 : {
         286                 :     GSClosureStruct gs = {
         287                 :         aCB,
         288                 :         aClosure
         289              27 :     };
         290                 :
         291              27 :     mSections.EnumerateRead(GetSectionsCB, &gs);
         292              27 :     return NS_OK;
         293                 : }
         294                 :
         295                 : nsresult
         296            2389 : nsINIParser::GetStrings(const char *aSection,
         297                 :                         INIStringCallback aCB, void *aClosure)
         298                 : {
         299                 :     INIValue *val;
         300                 :
         301            5207 :     for (mSections.Get(aSection, &val);
         302                 :          val;
         303            2818 :          val = val->next) {
         304                 :
         305            2818 :         if (!aCB(val->key, val->value, aClosure))
         306               0 :             return NS_OK;
         307                 :     }
         308                 :
         309            2389 :     return NS_OK;
         310                 : }

Generated by: LCOV version 1.7