00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00049 #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_COMMANDLINE_PARSER
00050 #define WINSTL_INCL_WINSTL_SYSTEM_HPP_COMMANDLINE_PARSER
00051
00052 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00053 # define WINSTL_VER_WINSTL_SYSTEM_HPP_COMMANDLINE_PARSER_MAJOR 2
00054 # define WINSTL_VER_WINSTL_SYSTEM_HPP_COMMANDLINE_PARSER_MINOR 1
00055 # define WINSTL_VER_WINSTL_SYSTEM_HPP_COMMANDLINE_PARSER_REVISION 2
00056 # define WINSTL_VER_WINSTL_SYSTEM_HPP_COMMANDLINE_PARSER_EDIT 36
00057 #endif
00058
00059
00060
00061
00062
00063 #ifndef WINSTL_INCL_WINSTL_H_WINSTL
00064 # include <winstl/winstl.h>
00065 #endif
00066 #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
00067 # include <stlsoft/memory/auto_buffer.hpp>
00068 #endif
00069 #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
00070 # include <winstl/memory/processheap_allocator.hpp>
00071 #endif
00072 #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CHAR_TRAITS
00073 # include <stlsoft/string/char_traits.hpp>
00074 #endif
00075 #ifndef STLSOFT_INCL_STLSOFT_SHIMS_ACCESS_HPP_STRING
00076 # include <stlsoft/shims/access/string.hpp>
00077 #endif
00078
00079 #ifndef STLSOFT_INCL_H_CTYPE
00080 # define STLSOFT_INCL_H_CTYPE
00081 # include <ctype.h>
00082 #endif
00083
00084
00085
00086
00087
00088 #ifndef _WINSTL_NO_NAMESPACE
00089 # if defined(_STLSOFT_NO_NAMESPACE) || \
00090 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00091
00092 namespace winstl
00093 {
00094 # else
00095
00096
00097 namespace stlsoft
00098 {
00099
00100 namespace winstl_project
00101 {
00102
00103 # endif
00104 #endif
00105
00106
00107
00108
00109
00124 template< ss_typename_param_k C
00125 , ss_typename_param_k T = stlsoft_ns_qual(stlsoft_char_traits)<C>
00126 >
00127 class basic_commandline_parser
00128 {
00131 public:
00133 typedef C char_type;
00135 typedef T traits_type;
00137 typedef basic_commandline_parser<C, T> class_type;
00138 private:
00139 typedef char_type* pointer_type_;
00140 typedef processheap_allocator<char_type> allocator_type_;
00141 typedef processheap_allocator<pointer_type_> pointers_allocator_type_;
00142 typedef stlsoft_ns_qual(auto_buffer)<
00143 char_type
00144 , 256
00145 , allocator_type_
00146 > buffer_type_;
00147 typedef stlsoft_ns_qual(auto_buffer)<
00148 pointer_type_
00149 , 20
00150 , pointers_allocator_type_
00151 > pointers_type_;
00152 typedef ss_typename_type_k buffer_type_::iterator iterator;
00153 public:
00155 typedef ss_typename_type_k pointers_type_::value_type value_type;
00157 typedef ss_typename_type_k pointers_type_::const_iterator const_iterator;
00159 typedef ss_size_t size_type;
00161
00164 public:
00168 ss_explicit_k basic_commandline_parser(char_type const* cmdLine)
00169 : m_buffer(1 + stlsoft_ns_qual(c_str_len)(cmdLine))
00170 , m_pointers(0)
00171 {
00172 init_(cmdLine, m_buffer.size() - 1);
00173 }
00177 ss_explicit_k basic_commandline_parser(char_type const* cmdLine, size_type len)
00178 : m_buffer(1 + len)
00179 , m_pointers(0)
00180 {
00181 init_(cmdLine, len);
00182 }
00183
00184 private:
00185 void init_(char_type const* cmdLine, size_type len)
00186 {
00187 WINSTL_MESSAGE_ASSERT("command-line may not be NULL, unless length is 0", (0 == len) || (NULL != cmdLine));
00188
00189 traits_type::copy(&m_buffer[0], cmdLine, len);
00190 m_buffer[len] = '\0';
00191
00192
00193
00194
00195
00196
00197 enum state_t
00198 {
00199 argument
00200 , quotedArgumentStart
00201 , quotedArgument
00202 , space
00203 };
00204
00205 state_t state = space;
00206 iterator b = m_buffer.begin();
00207 const iterator e = m_buffer.end() - 1;
00208
00209 for(; b != e; ++b)
00210 {
00211 const char_type ch = *b;
00212
00213 WINSTL_ASSERT('\0' != ch);
00214
00215 if('"' == ch)
00216 {
00217 if(quotedArgumentStart == state)
00218 {
00219 state = space;
00220 }
00221 else if(quotedArgument == state)
00222 {
00223 *b = '\0';
00224 state = space;
00225 }
00226 else if(space == state)
00227 {
00228 state = quotedArgumentStart;
00229 }
00230 else
00231 {
00232 }
00233 }
00234 else if(isspace(ch))
00235 {
00236 if(quotedArgumentStart == state)
00237 {
00238 state = quotedArgument;
00239
00240 add_pointer(&*b);
00241 }
00242 else if(quotedArgument == state)
00243 {
00244 }
00245 else if(space == state)
00246 {
00247 }
00248 else
00249 {
00250 WINSTL_ASSERT(argument == state);
00251
00252 *b = '\0';
00253
00254 state = space;
00255 }
00256 }
00257 else
00258 {
00259 if(quotedArgumentStart == state)
00260 {
00261 state = quotedArgument;
00262
00263 add_pointer(&*b);
00264 }
00265 else if(space == state)
00266 {
00267 state = argument;
00268
00269 add_pointer(&*b);
00270 }
00271 }
00272 }
00273 }
00275
00278 public:
00280 size_type size() const
00281 {
00282 return m_pointers.size();
00283 }
00284
00296 value_type const& operator [](size_type index) const
00297 {
00298 WINSTL_ASSERT(index <= size());
00299
00300 return m_pointers[index];
00301 }
00303
00306 public:
00308 const_iterator begin() const
00309 {
00310 return m_pointers.begin();
00311 }
00313 const_iterator end() const
00314 {
00315 return m_pointers.end();
00316 }
00318
00321 private:
00322 ws_bool_t add_pointer(pointer_type_ p)
00323 {
00324 if(!m_pointers.resize(1 + m_pointers.size()))
00325 {
00326 return false;
00327 }
00328
00329 m_pointers[m_pointers.size() - 1] = p;
00330
00331 return true;
00332 }
00334
00337 private:
00338 buffer_type_ m_buffer;
00339 pointers_type_ m_pointers;
00341 };
00342
00343
00344
00345
00346
00351 typedef basic_commandline_parser<ws_char_a_t> commandline_parser_a;
00356 typedef basic_commandline_parser<ws_char_w_t> commandline_parser_w;
00361 typedef basic_commandline_parser<TCHAR> commandline_parser;
00362
00364
00365
00366 #ifdef STLSOFT_UNITTEST
00367 # include "./unittest/commandline_parser_unittest_.h"
00368 #endif
00369
00370
00371
00372 #ifndef _WINSTL_NO_NAMESPACE
00373 # if defined(_STLSOFT_NO_NAMESPACE) || \
00374 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00375 }
00376 # else
00377 }
00378 }
00379 # endif
00380 #endif
00381
00382
00383
00384 #endif
00385
00386