1//
2// impl/error_code.ipp
3// ~~~~~~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef ASIO_IMPL_ERROR_CODE_IPP
12#define ASIO_IMPL_ERROR_CODE_IPP
13
14#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15# pragma once
16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18#include "asio/detail/config.hpp"
19#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
20# include <winerror.h>
21#elif defined(ASIO_WINDOWS_RUNTIME)
22# include <windows.h>
23#else
24# include <cerrno>
25# include <cstring>
26# include <string>
27#endif
28#include "asio/detail/local_free_on_block_exit.hpp"
29#include "asio/detail/socket_types.hpp"
30#include "asio/error_code.hpp"
31
32#include "asio/detail/push_options.hpp"
33
34namespace clmdep_asio {
35namespace detail {
36
37class system_category : public error_category
38{
39public:
40  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT
41  {
42    return "asio.system";
43  }
44
45  std::string message(int value) const
46  {
47#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
48    char* msg = 0;
49    DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
50        | FORMAT_MESSAGE_FROM_SYSTEM
51        | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value,
52        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0);
53    detail::local_free_on_block_exit local_free_obj(msg);
54    if (length && msg[length - 1] == '\n')
55      msg[--length] = '\0';
56    if (length && msg[length - 1] == '\r')
57      msg[--length] = '\0';
58    if (length)
59      return msg;
60    else
61      return "asio.system error";
62#elif defined(ASIO_WINDOWS_RUNTIME)
63    std::wstring wmsg(128, wchar_t());
64    for (;;)
65    {
66      DWORD wlength = ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
67          | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value,
68          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wmsg[0], wmsg.size(), 0);
69      if (wlength == 0 && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
70      {
71        wmsg.resize(wmsg.size() + wmsg.size() / 2);
72        continue;
73      }
74      if (wlength && wmsg[wlength - 1] == '\n')
75        --wlength;
76      if (wlength && wmsg[wlength - 1] == '\r')
77        --wlength;
78      if (wlength)
79      {
80        std::string msg(wlength * 2, char());
81        int length = ::WideCharToMultiByte(CP_ACP, 0,
82            wmsg.c_str(), static_cast<int>(wlength),
83            &msg[0], static_cast<int>(wlength * 2), 0, 0);
84        if (length <= 0)
85          return "asio.system error";
86        msg.resize(static_cast<std::size_t>(length));
87        return msg;
88      }
89      else
90        return "asio.system error";
91    }
92#else // defined(ASIO_WINDOWS)
93#if !defined(__sun)
94    if (value == ECANCELED)
95      return "Operation aborted.";
96#endif // !defined(__sun)
97#if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__)
98    using namespace std;
99    return strerror(value);
100#elif defined(__MACH__) && defined(__APPLE__) \
101  || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
102  || defined(_AIX) || defined(__hpux) || defined(__osf__) \
103  || defined(__ANDROID__)
104    char buf[256] = "";
105    using namespace std;
106    strerror_r(value, buf, sizeof(buf));
107    return buf;
108#else
109    char buf[256] = "";
110    return strerror_r(value, buf, sizeof(buf));
111#endif
112#endif // defined(ASIO_WINDOWS)
113  }
114};
115
116} // namespace detail
117
118const error_category& system_category()
119{
120  static detail::system_category instance;
121  return instance;
122}
123
124} // namespace clmdep_asio
125
126#include "asio/detail/pop_options.hpp"
127
128#endif // ASIO_IMPL_ERROR_CODE_IPP
129