Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  nsINIParser.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


// Moz headers (alphabetical)
#include "nsCRTGlue.h"
#include "nsError.h"
#include "nsIFile.h"
#include "nsINIParser.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/Try.h"
#include "mozilla/URLPreloader.h"

using namespace mozilla;

nsresult nsINIParser::Init(nsIFile* aFile) {
  nsCString result;
  MOZ_TRY_VAR(result, URLPreloader::ReadFile(aFile));

  return InitFromString(result);
}

static const char kNL[] = "\r\n";
static const char kEquals[] = "=";
static const char kWhitespace[] = " \t";
static const char kRBracket[] = "]";

nsresult nsINIParser::InitFromString(const nsCString& aStr) {
  nsCString fileContents;
  char* buffer;

  if (StringHead(aStr, 3) == "\xEF\xBB\xBF") {
    // Someone set us up the Utf-8 BOM
    // This case is easy, since we assume that BOM-less
    // files are Utf-8 anyway.  Just skip the BOM and process as usual.
    fileContents.Append(aStr);
    buffer = fileContents.BeginWriting() + 3;
  } else {
    if (StringHead(aStr, 2) == "\xFF\xFE") {
      // Someone set us up the Utf-16LE BOM
      nsDependentSubstring str(reinterpret_cast<const char16_t*>(aStr.get()),
                               aStr.Length() / 2);

      AppendUTF16toUTF8(Substring(str, 1), fileContents);
    } else {
      fileContents.Append(aStr);
    }

    buffer = fileContents.BeginWriting();
  }

  char* currSection = nullptr;

  // outer loop tokenizes into lines
  while (char* token = NS_strtok(kNL, &buffer)) {
    if (token[0] == '#' || token[0] == ';') {  // it's a comment
      continue;
    }

    token = (char*)NS_strspnp(kWhitespace, token);
    if (!*token) {  // empty line
      continue;
    }

    if (token[0] == '[') {  // section header!
      ++token;
      currSection = token;

      char* rb = NS_strtok(kRBracket, &token);
      if (!rb || NS_strtok(kWhitespace, &token)) {
        // there's either an unclosed [Section or a [Section]Moretext!
        // we could frankly decide that this INI file is malformed right
        // here and stop, but we won't... keep going, looking for
        // a well-formed [section] to continue working with
        currSection = nullptr;
      }

      continue;
    }

    if (!currSection) {
      // If we haven't found a section header (or we found a malformed
      // section header), don't bother parsing this line.
      continue;
    }

    char* key = token;
    char* e = NS_strtok(kEquals, &token);
    if (!e || !token) {
      continue;
    }

    SetString(currSection, key, token);
  }

  return NS_OK;
}

bool nsINIParser::IsValidSection(const char* aSection) {
  if (aSection[0] == '\0') {
    return false;
  }

  const char* found = strpbrk(aSection, "\r\n[]");
  return found == nullptr;
}

bool nsINIParser::IsValidKey(const char* aKey) {
  if (aKey[0] == '\0') {
    return false;
  }

  const char* found = strpbrk(aKey, "\r\n=");
  return found == nullptr;
}

bool nsINIParser::IsValidValue(const char* aValue) {
  const char* found = strpbrk(aValue, "\r\n");
  return found == nullptr;
}

nsresult nsINIParser::GetString(const char* aSection, const char* aKey,
                                nsACString& aResult) {
  if (!IsValidSection(aSection) || !IsValidKey(aKey)) {
    return NS_ERROR_INVALID_ARG;
  }

  INIValue* val;
  mSections.Get(aSection, &val);

  while (val) {
    if (strcmp(val->key, aKey) == 0) {
      aResult.Assign(val->value);
      return NS_OK;
    }

    val = val->next.get();
  }

  return NS_ERROR_FAILURE;
}

nsresult nsINIParser::GetString(const char* aSection, const char* aKey,
                                char* aResult, uint32_t aResultLen) {
  if (!IsValidSection(aSection) || !IsValidKey(aKey)) {
    return NS_ERROR_INVALID_ARG;
  }

  INIValue* val;
  mSections.Get(aSection, &val);

  while (val) {
    if (strcmp(val->key, aKey) == 0) {
      strncpy(aResult, val->value, aResultLen);
      aResult[aResultLen - 1] = '\0';
      if (strlen(val->value) >= aResultLen) {
        return NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
      }

      return NS_OK;
    }

    val = val->next.get();
  }

  return NS_ERROR_FAILURE;
}

nsresult nsINIParser::GetSections(
    std::function<bool(const char*)>&& aCallback) {
  for (const auto& key : mSections.Keys()) {
    if (!aCallback(key)) {
      break;
    }
  }
  return NS_OK;
}

nsresult nsINIParser::GetStrings(
    const char* aSection,
    std::function<bool(const char*, const char*)>&& aCallback) {
  if (!IsValidSection(aSection)) {
    return NS_ERROR_INVALID_ARG;
  }

  INIValue* val;

  for (mSections.Get(aSection, &val); val; val = val->next.get()) {
    if (!aCallback(val->key, val->value)) {
      return NS_OK;
    }
  }

  return NS_OK;
}

nsresult nsINIParser::SetString(const char* aSection, const char* aKey,
                                const char* aValue) {
  if (!IsValidSection(aSection) || !IsValidKey(aKey) || !IsValidValue(aValue)) {
    return NS_ERROR_INVALID_ARG;
  }

  mSections.WithEntryHandle(aSection, [&](auto&& entry) {
    if (!entry) {
      entry.Insert(MakeUnique<INIValue>(aKey, aValue));
      return;
    }

    INIValue* v = entry->get();

    // Check whether this key has already been specified; overwrite
    // if so, or append if not.
    while (v) {
      if (!strcmp(aKey, v->key)) {
        v->SetValue(aValue);
        break;
      }
      if (!v->next) {
        v->next = MakeUnique<INIValue>(aKey, aValue);
        break;
      }
      v = v->next.get();
    }
    NS_ASSERTION(v, "v should never be null coming out of this loop");
  });

  return NS_OK;
}

nsresult nsINIParser::DeleteString(const char* aSection, const char* aKey) {
  if (!IsValidSection(aSection) || !IsValidKey(aKey)) {
    return NS_ERROR_INVALID_ARG;
  }

  INIValue* val;
  if (!mSections.Get(aSection, &val)) {
    return NS_ERROR_FAILURE;
  }

  // Special case the first result
  if (strcmp(val->key, aKey) == 0) {
    if (!val->next) {
      mSections.Remove(aSection);
    } else {
      mSections.InsertOrUpdate(aSection, std::move(val->next));
    }
    return NS_OK;
  }

  while (val->next) {
    if (strcmp(val->next->key, aKey) == 0) {
      val->next = std::move(val->next->next);

      return NS_OK;
    }

    val = val->next.get();
  }

  return NS_ERROR_FAILURE;
}

nsresult nsINIParser::DeleteSection(const char* aSection) {
  if (!IsValidSection(aSection)) {
    return NS_ERROR_INVALID_ARG;
  }

  if (!mSections.Remove(aSection)) {
    return NS_ERROR_FAILURE;
  }
  return NS_OK;
}

nsresult nsINIParser::RenameSection(const char* aSection,
                                    const char* aNewName) {
  if (!IsValidSection(aSection) || !IsValidSection(aNewName)) {
    return NS_ERROR_INVALID_ARG;
  }

  if (mSections.Contains(aNewName)) {
    return NS_ERROR_ILLEGAL_VALUE;
  }

  mozilla::UniquePtr<INIValue> val;
  if (mSections.Remove(aSection, &val)) {
    mSections.InsertOrUpdate(aNewName, std::move(val));
  } else {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}

nsresult nsINIParser::WriteToFile(nsIFile* aFile) {
  nsCString buffer;

  WriteToString(buffer);

  FILE* writeFile;
  nsresult rv = aFile->OpenANSIFileDesc("w", &writeFile);
  NS_ENSURE_SUCCESS(rv, rv);

  unsigned int length = buffer.Length();

  if (fwrite(buffer.get(), sizeof(char), length, writeFile) != length) {
    fclose(writeFile);
    return NS_ERROR_UNEXPECTED;
  }

  fclose(writeFile);
  return NS_OK;
}

void nsINIParser::WriteToString(nsACString& aOutput) {
  for (const auto& entry : mSections) {
    aOutput.AppendPrintf("[%s]\n", entry.GetKey());
    INIValue* val = entry.GetWeak();
    while (val) {
      aOutput.AppendPrintf("%s=%s\n", val->key, val->value);
      val = val->next.get();
    }
    aOutput.AppendLiteral("\n");
  }
}

90%


¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge