summaryrefslogtreecommitdiffstats
blob: 6d7d40c532b443032131e54f4985f6b99b8b24e1 (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//  path.cpp  ----------------------------------------------------------------//

//  Copyright 2005 Beman Dawes

//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

//  See library home page at http://www.boost.org/libs/filesystem

//----------------------------------------------------------------------------// 

// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
// the library is being built (possibly exporting rather than importing code)
#define BOOST_FILESYSTEM_SOURCE 

#include <boost/filesystem/config.hpp>

#ifndef BOOST_FILESYSTEM_NARROW_ONLY

#include <boost/filesystem/path.hpp>
#include <boost/scoped_array.hpp>

#include <locale>
#include <boost/cerrno.hpp>
#include <boost/system/error_code.hpp>

#include <cwchar>     // for std::mbstate_t

namespace
{
  // std::locale construction can throw (if LC_MESSAGES is wrong, for example),
  // so a static at function scope is used to ensure that exceptions can be
  // caught. (A previous version was at namespace scope, so initialization
  // occurred before main(), preventing exceptions from being caught.)
  std::locale & loc()
  {
#if !defined(macintosh) && !defined(__APPLE__) && !defined(__APPLE_CC__) 
    // ISO C calls this "the locale-specific native environment":
    static std::locale lc("");
#else
    static std::locale lc = std::locale();  // Mac OS doesn't support locale("")
#endif
    return lc;
  }

  const std::codecvt<wchar_t, char, std::mbstate_t> *&
  converter()
  {
   static const std::codecvt<wchar_t, char, std::mbstate_t> *
     cvtr(
       &std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >
        ( loc() ) );
   return cvtr;
  }

  bool locked(false);
} // unnamed namespace

namespace boost
{
  namespace filesystem
  {
    bool wpath_traits::imbue( const std::locale & new_loc, const std::nothrow_t & )
    {
      if ( locked ) return false;
      locked = true;
      loc() = new_loc;
      converter() = &std::use_facet
        <std::codecvt<wchar_t, char, std::mbstate_t> >( loc() );
      return true;
    }

    void wpath_traits::imbue( const std::locale & new_loc )
    {
      if ( locked ) boost::throw_exception(
        wfilesystem_error(
          "boost::filesystem::wpath_traits::imbue() after lockdown",
          make_error_code( system::posix::not_supported ) ) );
      imbue( new_loc, std::nothrow );
    }

    //namespace detail
    //{
    //  BOOST_FILESYSTEM_DECL
    //  const char * what( const char * sys_err_what,
    //    const path & path1, const path & path2, std::string & target)
    //  {
    //    try
    //    {
    //      if ( target.empty() )
    //      {
    //        target = sys_err_what;
    //        if ( !path1.empty() )
    //        {
    //          target += ": \"";
    //          target += path1.file_string();
    //          target += "\"";
    //        }
    //        if ( !path2.empty() )
    //        {
    //          target += ", \"";
    //          target += path2.file_string();
    //          target += "\"";
    //        }
    //      }
    //      return target.c_str();
    //    }
    //    catch (...)
    //    {
    //      return sys_err_what;
    //    }
    //  }
    //}
    
# ifdef BOOST_POSIX_API

//  Because this is POSIX only code, we don't have to worry about ABI issues
//  described in http://www.boost.org/more/separate_compilation.html

    wpath_traits::external_string_type
    wpath_traits::to_external( const wpath & ph, 
      const internal_string_type & src )
    {
      locked = true;
      std::size_t work_size( converter()->max_length() * (src.size()+1) );
      boost::scoped_array<char> work( new char[ work_size ] );
      std::mbstate_t state = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
      const internal_string_type::value_type * from_next;
      external_string_type::value_type * to_next;
      if ( converter()->out( 
        state, src.c_str(), src.c_str()+src.size(), from_next, work.get(),
        work.get()+work_size, to_next ) != std::codecvt_base::ok )
        boost::throw_exception( boost::filesystem::wfilesystem_error(
          "boost::filesystem::wpath::to_external conversion error",
          ph, system::error_code( system::posix::invalid_argument, system::system_category ) ) );
      *to_next = '\0';
      return external_string_type( work.get() );
    }

    wpath_traits::internal_string_type
    wpath_traits::to_internal( const external_string_type & src )
    {
      locked = true;
      std::size_t work_size( src.size()+1 );
      boost::scoped_array<wchar_t> work( new wchar_t[ work_size ] );
      std::mbstate_t state  = std::mbstate_t();  // perhaps unneeded, but cuts bug reports
      const external_string_type::value_type * from_next;
      internal_string_type::value_type * to_next;
      if ( converter()->in( 
        state, src.c_str(), src.c_str()+src.size(), from_next, work.get(),
        work.get()+work_size, to_next ) != std::codecvt_base::ok )
        boost::throw_exception( boost::filesystem::wfilesystem_error(
          "boost::filesystem::wpath::to_internal conversion error",
          system::error_code( system::posix::invalid_argument, system::system_category ) ) );
      *to_next = L'\0';
      return internal_string_type( work.get() );
    }
# endif // BOOST_POSIX_API

  } // namespace filesystem
} // namespace boost

#endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY