xpcom/io/nsLocalFile.h
author Henri Sivonen <hsivonen@hsivonen.fi>
Fri, 06 Jul 2018 10:44:43 +0300
changeset 489140 4ef0f163fdeb9afeddd87b37bfd987298c038542
parent 456777 d7c27819bb205985798645ebecc7bd1ca4d5338e
child 508163 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Bug 1402247 - Use encoding_rs for XPCOM string encoding conversions. r=Nika,erahm,froydnj. Correctness improvements: * UTF errors are handled safely per spec instead of dangerously truncating strings. * There are fewer converter implementations. Performance improvements: * The old code did exact buffer length math, which meant doing UTF math twice on each input string (once for length calculation and another time for conversion). Exact length math is more complicated when handling errors properly, which the old code didn't do. The new code does UTF math on the string content only once (when converting) but risks allocating more than once. There are heuristics in place to lower the probability of reallocation in cases where the double math avoidance isn't enough of a saving to absorb an allocation and memcpy. * Previously, in UTF-16 <-> UTF-8 conversions, an ASCII prefix was optimized but a single non-ASCII code point pessimized the rest of the string. The new code tries to get back on the fast ASCII path. * UTF-16 to Latin1 conversion guarantees less about handling of out-of-range input to eliminate an operation from the inner loop on x86/x86_64. * When assigning to a pre-existing string, the new code tries to reuse the old buffer instead of first releasing the old buffer and then allocating a new one. * When reallocating from the new code, the memcpy covers only the data that is part of the logical length of the old string instead of memcpying the whole capacity. (For old callers old excess memcpy behavior is preserved due to bogus callers. See bug 1472113.) * UTF-8 strings in XPConnect that are in the Latin1 range are passed to SpiderMonkey as Latin1. New features: * Conversion between UTF-8 and Latin1 is added in order to enable faster future interop between Rust code (or otherwise UTF-8-using code) and text node and SpiderMonkey code that uses Latin1. MozReview-Commit-ID: JaJuExfILM9

/* -*- 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/. */

#ifndef _NS_LOCAL_FILE_H_
#define _NS_LOCAL_FILE_H_

#include "nscore.h"

#define NS_LOCAL_FILE_CID {0x2e23e220, 0x60be, 0x11d3, {0x8c, 0x4a, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74}}

#define NS_DECL_NSLOCALFILE_UNICODE_METHODS                                                      \
  nsresult AppendUnicode(const char16_t *aNode);                                              \
  nsresult GetUnicodeLeafName(char16_t **aLeafName);                                          \
  nsresult SetUnicodeLeafName(const char16_t *aLeafName);                                     \
  nsresult CopyToUnicode(nsIFile *aNewParentDir, const char16_t *aNewLeafName);               \
  nsresult CopyToFollowingLinksUnicode(nsIFile *aNewParentDir, const char16_t *aNewLeafName); \
  nsresult MoveToUnicode(nsIFile *aNewParentDir, const char16_t *aNewLeafName);               \
  nsresult GetUnicodeTarget(char16_t **aTarget);                                              \
  nsresult GetUnicodePath(char16_t **aPath);                                                  \
  nsresult InitWithUnicodePath(const char16_t *aPath);                                        \
  nsresult AppendRelativeUnicodePath(const char16_t *aRelativePath);

// XPCOMInit needs to know about how we are implemented,
// so here we will export it.  Other users should not depend
// on this.

#include <errno.h>
#include "nsIFile.h"

#ifdef XP_WIN
#include "nsLocalFileWin.h"
#elif defined(XP_UNIX)
#include "nsLocalFileUnix.h"
#else
#error NOT_IMPLEMENTED
#endif

#define NSRESULT_FOR_RETURN(ret) (((ret) < 0) ? NSRESULT_FOR_ERRNO() : NS_OK)

inline nsresult
nsresultForErrno(int aErr)
{
  switch (aErr) {
    case 0:
      return NS_OK;
#ifdef EDQUOT
    case EDQUOT: /* Quota exceeded */
      // FALLTHROUGH to return NS_ERROR_FILE_DISK_FULL
#endif
    case ENOSPC:
      return NS_ERROR_FILE_DISK_FULL;
#ifdef EISDIR
    case EISDIR:    /*      Is a directory. */
      return NS_ERROR_FILE_IS_DIRECTORY;
#endif
    case ENAMETOOLONG:
      return NS_ERROR_FILE_NAME_TOO_LONG;
    case ENOEXEC:  /*     Executable file format error. */
      return NS_ERROR_FILE_EXECUTION_FAILED;
    case ENOENT:
      return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
    case ENOTDIR:
      return NS_ERROR_FILE_DESTINATION_NOT_DIR;
#ifdef ELOOP
    case ELOOP:
      return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
#endif /* ELOOP */
#ifdef ENOLINK
    case ENOLINK:
      return NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
#endif /* ENOLINK */
    case EEXIST:
      return NS_ERROR_FILE_ALREADY_EXISTS;
#ifdef EPERM
    case EPERM:
#endif /* EPERM */
    case EACCES:
      return NS_ERROR_FILE_ACCESS_DENIED;
#ifdef EROFS
    case EROFS: /*     Read-only file system. */
      return NS_ERROR_FILE_READ_ONLY;
#endif
    /*
     * On AIX 4.3, ENOTEMPTY is defined as EEXIST,
     * so there can't be cases for both without
     * preprocessing.
     */
#if ENOTEMPTY != EEXIST
    case ENOTEMPTY:
      return NS_ERROR_FILE_DIR_NOT_EMPTY;
#endif /* ENOTEMPTY != EEXIST */
    /* Note that nsIFile.createUnique() returns
       NS_ERROR_FILE_TOO_BIG when it cannot create a temporary
       file with a unique filename.
       See https://developer.mozilla.org/en-US/docs/Table_Of_Errors
       Other usages of NS_ERROR_FILE_TOO_BIG in the source tree
       are in line with the POSIX semantics of EFBIG.
       So this is a reasonably good approximation.
    */
    case EFBIG: /*     File too large. */
      return NS_ERROR_FILE_TOO_BIG;

    default:
      return NS_ERROR_FAILURE;
  }
}

#define NSRESULT_FOR_ERRNO() nsresultForErrno(errno)

#endif