string_utils-inl.h 5.81 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
// Copyright (c) 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// string_utils-inl.h: Safer string manipulation on Windows, supporting
// pre-MSVC8 environments.

#ifndef COMMON_WINDOWS_STRING_UTILS_INL_H_
#define COMMON_WINDOWS_STRING_UTILS_INL_H_

#include <stdarg.h>
#include <wchar.h>

#include <string>

// The "ll" printf format size specifier corresponding to |long long| was
// intrudced in MSVC8.  Earlier versions did not provide this size specifier,
// but "I64" can be used to print 64-bit types.  Don't use "I64" where "ll"
// is available, in the event of oddball systems where |long long| is not
// 64 bits wide.
#if _MSC_VER >= 1400  // MSVC 2005/8
#define WIN_STRING_FORMAT_LL "ll"
#else  // MSC_VER >= 1400
#define WIN_STRING_FORMAT_LL "I64"
#endif  // MSC_VER >= 1400

// A nonconforming version of swprintf, without the length argument, was
// included with the CRT prior to MSVC8.  Although a conforming version was
// also available via an overload, it is not reliably chosen.  _snwprintf
// behaves as a standards-confirming swprintf should, so force the use of
// _snwprintf when using older CRTs.
#if _MSC_VER < 1400  // MSVC 2005/8
#define swprintf _snwprintf
#else
// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently,
// it takes the same argument list as swprintf.
#define swprintf swprintf_s
#endif  // MSC_VER < 1400

namespace google_breakpad {

using std::string;
using std::wstring;

class WindowsStringUtils {
 public:
  // Roughly equivalent to MSVC8's wcscpy_s, except pre-MSVC8, this does
  // not fail if source is longer than destination_size.  The destination
  // buffer is always 0-terminated.
  static void safe_wcscpy(wchar_t *destination, size_t destination_size,
                          const wchar_t *source);

  // Roughly equivalent to MSVC8's wcsncpy_s, except that _TRUNCATE cannot
  // be passed directly, and pre-MSVC8, this will not fail if source or count
  // are longer than destination_size.  The destination buffer is always
  // 0-terminated.
  static void safe_wcsncpy(wchar_t *destination, size_t destination_size,
                           const wchar_t *source, size_t count);

  // Performs multi-byte to wide character conversion on C++ strings, using
  // mbstowcs_s (MSVC8) or mbstowcs (pre-MSVC8).  Returns false on failure,
  // without setting wcs.
  static bool safe_mbstowcs(const string &mbs, wstring *wcs);

  // The inverse of safe_mbstowcs.
  static bool safe_wcstombs(const wstring &wcs, string *mbs);

  // Returns the base name of a file, e.g. strips off the path.
  static wstring GetBaseName(const wstring &filename);

 private:
  // Disallow instantiation and other object-based operations.
  WindowsStringUtils();
  WindowsStringUtils(const WindowsStringUtils&);
  ~WindowsStringUtils();
  void operator=(const WindowsStringUtils&);
};

// static
inline void WindowsStringUtils::safe_wcscpy(wchar_t *destination,
                                            size_t destination_size,
                                            const wchar_t *source) {
#if _MSC_VER >= 1400  // MSVC 2005/8
  wcscpy_s(destination, destination_size, source);
#else  // _MSC_VER >= 1400
  // Pre-MSVC 2005/8 doesn't have wcscpy_s.  Simulate it with wcsncpy.
  // wcsncpy doesn't 0-terminate the destination buffer if the source string
  // is longer than size.  Ensure that the destination is 0-terminated.
  wcsncpy(destination, source, destination_size);
  if (destination && destination_size)
    destination[destination_size - 1] = 0;
#endif  // _MSC_VER >= 1400
}

// static
inline void WindowsStringUtils::safe_wcsncpy(wchar_t *destination,
                                             size_t destination_size,
                                             const wchar_t *source,
                                             size_t count) {
#if _MSC_VER >= 1400  // MSVC 2005/8
  wcsncpy_s(destination, destination_size, source, count);
#else  // _MSC_VER >= 1400
  // Pre-MSVC 2005/8 doesn't have wcsncpy_s.  Simulate it with wcsncpy.
  // wcsncpy doesn't 0-terminate the destination buffer if the source string
  // is longer than size.  Ensure that the destination is 0-terminated.
  if (destination_size < count)
    count = destination_size;

  wcsncpy(destination, source, count);
  if (destination && count)
    destination[count - 1] = 0;
#endif  // _MSC_VER >= 1400
}

}  // namespace google_breakpad

#endif  // COMMON_WINDOWS_STRING_UTILS_INL_H_