/ src / common / windows / string_utils.cc
string_utils.cc
  1  // Copyright 2006 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  #ifdef HAVE_CONFIG_H
 30  #include <config.h>  // Must come first
 31  #endif
 32  
 33  #include <cassert>
 34  #include <vector>
 35  
 36  #include "common/windows/string_utils-inl.h"
 37  
 38  namespace google_breakpad {
 39  
 40  // static
 41  wstring WindowsStringUtils::GetBaseName(const wstring& filename) {
 42    wstring base_name(filename);
 43    size_t slash_pos = base_name.find_last_of(L"/\\");
 44    if (slash_pos != wstring::npos) {
 45      base_name.erase(0, slash_pos + 1);
 46    }
 47    return base_name;
 48  }
 49  
 50  // static
 51  bool WindowsStringUtils::safe_mbstowcs(const string& mbs, wstring* wcs) {
 52    assert(wcs);
 53  
 54    // First, determine the length of the destination buffer.
 55    size_t wcs_length;
 56  
 57  #if _MSC_VER >= 1400  // MSVC 2005/8
 58    errno_t err;
 59    if ((err = mbstowcs_s(&wcs_length, NULL, 0, mbs.c_str(), _TRUNCATE)) != 0) {
 60      return false;
 61    }
 62    assert(wcs_length > 0);
 63  #else  // _MSC_VER >= 1400
 64    if ((wcs_length = mbstowcs(NULL, mbs.c_str(), mbs.length())) == (size_t)-1) {
 65      return false;
 66    }
 67  
 68    // Leave space for the 0-terminator.
 69    ++wcs_length;
 70  #endif  // _MSC_VER >= 1400
 71  
 72    std::vector<wchar_t> wcs_v(wcs_length);
 73  
 74    // Now, convert.
 75  #if _MSC_VER >= 1400  // MSVC 2005/8
 76    if ((err = mbstowcs_s(NULL, &wcs_v[0], wcs_length, mbs.c_str(),
 77                          _TRUNCATE)) != 0) {
 78      return false;
 79    }
 80  #else  // _MSC_VER >= 1400
 81    if (mbstowcs(&wcs_v[0], mbs.c_str(), mbs.length()) == (size_t)-1) {
 82      return false;
 83    }
 84  
 85    // Ensure presence of 0-terminator.
 86    wcs_v[wcs_length - 1] = '\0';
 87  #endif  // _MSC_VER >= 1400
 88  
 89    *wcs = &wcs_v[0];
 90    return true;
 91  }
 92  
 93  // static
 94  bool WindowsStringUtils::safe_wcstombs(const wstring& wcs, string* mbs) {
 95    assert(mbs);
 96  
 97    // First, determine the length of the destination buffer.
 98    size_t mbs_length;
 99  
100  #if _MSC_VER >= 1400  // MSVC 2005/8
101    errno_t err;
102    if ((err = wcstombs_s(&mbs_length, NULL, 0, wcs.c_str(), _TRUNCATE)) != 0) {
103      return false;
104    }
105    assert(mbs_length > 0);
106  #else  // _MSC_VER >= 1400
107    if ((mbs_length = wcstombs(NULL, wcs.c_str(), wcs.length())) == (size_t)-1) {
108      return false;
109    }
110  
111    // Leave space for the 0-terminator.
112    ++mbs_length;
113  #endif  // _MSC_VER >= 1400
114  
115    std::vector<char> mbs_v(mbs_length);
116  
117    // Now, convert.
118  #if _MSC_VER >= 1400  // MSVC 2005/8
119    if ((err = wcstombs_s(NULL, &mbs_v[0], mbs_length, wcs.c_str(),
120                          _TRUNCATE)) != 0) {
121      return false;
122    }
123  #else  // _MSC_VER >= 1400
124    if (wcstombs(&mbs_v[0], wcs.c_str(), wcs.length()) == (size_t)-1) {
125      return false;
126    }
127  
128    // Ensure presence of 0-terminator.
129    mbs_v[mbs_length - 1] = '\0';
130  #endif  // _MSC_VER >= 1400
131  
132    *mbs = &mbs_v[0];
133    return true;
134  }
135  
136  }  // namespace google_breakpad