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-06-02 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