Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:49:03

0001 //
0002 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // https://www.boost.org/LICENSE_1_0.txt
0006 
0007 #ifndef BOOST_NOWIDE_ARGS_HPP_INCLUDED
0008 #define BOOST_NOWIDE_ARGS_HPP_INCLUDED
0009 
0010 #include <boost/config.hpp>
0011 #ifdef BOOST_WINDOWS
0012 #include <boost/nowide/stackstring.hpp>
0013 #include <boost/nowide/windows.hpp>
0014 #include <stdexcept>
0015 #include <vector>
0016 #endif
0017 
0018 namespace boost {
0019 namespace nowide {
0020 #if !defined(BOOST_WINDOWS) && !defined(BOOST_NOWIDE_DOXYGEN)
0021     class args
0022     {
0023     public:
0024         args(int&, char**&)
0025         {}
0026         args(int&, char**&, char**&)
0027         {}
0028     };
0029 
0030 #else
0031 
0032     ///
0033     /// \brief \c args is a class that temporarily replaces standard main() function arguments with their
0034     /// equal, but UTF-8 encoded values under Microsoft Windows for the lifetime of the instance.
0035     ///
0036     /// The class uses \c GetCommandLineW(), \c CommandLineToArgvW() and \c GetEnvironmentStringsW()
0037     /// in order to obtain Unicode-encoded values.
0038     /// It does not relate to actual values of argc, argv and env under Windows.
0039     ///
0040     /// It restores the original values in its destructor (usually at the end of the \c main function).
0041     ///
0042     /// If any of the system calls fails, an exception of type std::runtime_error will be thrown
0043     /// and argc, argv, env remain unchanged.
0044     ///
0045     /// \note The class owns the memory of the newly allocated strings.
0046     /// So you need to keep it alive as long as you use the values.
0047     ///
0048     /// Usage:
0049     /// \code
0050     /// int main(int argc, char** argv, char** env) {
0051     ///   boost::nowide::args _(argc, argv, env); // Note the _ as a "don't care" name for the instance
0052     ///   // Use argv and env as usual, they are now UTF-8 encoded on Windows
0053     ///   return 0; // Memory held by args is released
0054     /// }
0055     /// \endcode
0056     class args
0057     {
0058     public:
0059         ///
0060         /// Fix command line arguments
0061         ///
0062         args(int& argc, char**& argv) :
0063             old_argc_(argc), old_argv_(argv), old_env_(0), old_argc_ptr_(&argc), old_argv_ptr_(&argv), old_env_ptr_(0)
0064         {
0065             fix_args(argc, argv);
0066         }
0067         ///
0068         /// Fix command line arguments and environment
0069         ///
0070         args(int& argc, char**& argv, char**& env) :
0071             old_argc_(argc), old_argv_(argv), old_env_(env), old_argc_ptr_(&argc), old_argv_ptr_(&argv),
0072             old_env_ptr_(&env)
0073         {
0074             fix_args(argc, argv);
0075             fix_env(env);
0076         }
0077         ///
0078         /// Restore original argc, argv, env values, if changed
0079         ///
0080         ~args()
0081         {
0082             if(old_argc_ptr_)
0083                 *old_argc_ptr_ = old_argc_;
0084             if(old_argv_ptr_)
0085                 *old_argv_ptr_ = old_argv_;
0086             if(old_env_ptr_)
0087                 *old_env_ptr_ = old_env_;
0088         }
0089 
0090     private:
0091         class wargv_ptr
0092         {
0093             wchar_t** p;
0094             int argc;
0095 
0096         public:
0097             wargv_ptr()
0098             {
0099                 p = CommandLineToArgvW(GetCommandLineW(), &argc);
0100             }
0101             ~wargv_ptr()
0102             {
0103                 if(p)
0104                     LocalFree(p);
0105             }
0106             wargv_ptr(const wargv_ptr&) = delete;
0107             wargv_ptr& operator=(const wargv_ptr&) = delete;
0108 
0109             int size() const
0110             {
0111                 return argc;
0112             }
0113             operator bool() const
0114             {
0115                 return p != nullptr;
0116             }
0117             const wchar_t* operator[](size_t i) const
0118             {
0119                 return p[i];
0120             }
0121         };
0122         class wenv_ptr
0123         {
0124             wchar_t* p;
0125 
0126         public:
0127             wenv_ptr() : p(GetEnvironmentStringsW())
0128             {}
0129             ~wenv_ptr()
0130             {
0131                 if(p)
0132                     FreeEnvironmentStringsW(p);
0133             }
0134             wenv_ptr(const wenv_ptr&) = delete;
0135             wenv_ptr& operator=(const wenv_ptr&) = delete;
0136 
0137             operator const wchar_t*() const
0138             {
0139                 return p;
0140             }
0141         };
0142 
0143         void fix_args(int& argc, char**& argv)
0144         {
0145             const wargv_ptr wargv;
0146             if(!wargv)
0147                 throw std::runtime_error("Could not get command line!");
0148             args_.resize(wargv.size() + 1, 0);
0149             arg_values_.resize(wargv.size());
0150             for(int i = 0; i < wargv.size(); i++)
0151                 args_[i] = arg_values_[i].convert(wargv[i]);
0152             argc = wargv.size();
0153             argv = &args_[0];
0154         }
0155         void fix_env(char**& env)
0156         {
0157             const wenv_ptr wstrings;
0158             if(!wstrings)
0159                 throw std::runtime_error("Could not get environment strings!");
0160             const wchar_t* wstrings_end = 0;
0161             int count = 0;
0162             for(wstrings_end = wstrings; *wstrings_end; wstrings_end += wcslen(wstrings_end) + 1)
0163                 count++;
0164             env_.convert(wstrings, wstrings_end);
0165             envp_.resize(count + 1, 0);
0166             char* p = env_.get();
0167             int pos = 0;
0168             for(int i = 0; i < count; i++)
0169             {
0170                 if(*p != '=')
0171                     envp_[pos++] = p;
0172                 p += strlen(p) + 1;
0173             }
0174             env = &envp_[0];
0175         }
0176 
0177         std::vector<char*> args_;
0178         std::vector<short_stackstring> arg_values_;
0179         stackstring env_;
0180         std::vector<char*> envp_;
0181 
0182         int old_argc_;
0183         char** old_argv_;
0184         char** old_env_;
0185 
0186         int* old_argc_ptr_;
0187         char*** old_argv_ptr_;
0188         char*** old_env_ptr_;
0189     };
0190 
0191 #endif
0192 
0193 } // namespace nowide
0194 } // namespace boost
0195 #endif