Explorar el Código

Add Args class to manage command line arguments.

Daniele Bartolini hace 13 años
padre
commit
45b49ee1da
Se han modificado 2 ficheros con 255 adiciones y 0 borrados
  1. 1 0
      src/CMakeLists.txt
  2. 254 0
      src/core/Args.h

+ 1 - 0
src/CMakeLists.txt

@@ -60,6 +60,7 @@ set (CORE_HEADERS
 	core/Types.h
 	core/VertexData.h
 	core/WithProperties.h
+	core/Args.h
 )
 
 set (BV_SRC

+ 254 - 0
src/core/Args.h

@@ -0,0 +1,254 @@
+/*
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+#include <cassert>
+#include "Types.h"
+#include "String.h"
+
+namespace crown
+{
+
+enum ArgsOptionType
+{
+	AOT_SHORT				= 1,
+	AOT_LONG				= 2,
+	AOT_NOT_OPTION			= 3
+};
+
+enum ArgsOptionArgument
+{
+	AOA_NO_ARGUMENT			= 1,
+	AOA_REQUIRED_ARGUMENT	= 2
+};
+
+struct ArgsOption
+{
+	const char*				name;
+	int32_t					has_arg;
+	int32_t*				flag;
+	int32_t					val;
+};
+
+/// Parses the command line arguments in a way very similar to GNU getopt.
+class Args
+{
+public:
+
+					
+public:
+
+						Args(int argc, char** argv, const char* shortopts, const ArgsOption* longopts);
+						~Args();
+
+	int32_t				next_option();
+	int32_t				option_index() const;
+	const char*			option_argument() const;
+	
+
+private:
+
+						// Returns the @option type
+						// Returns AOT_SHORT if @option starts with "-"
+						// Returns AOT_LONG if @option starts with "--"
+	ArgsOptionType		option_type(const char* option);
+	int32_t				long_option(const char* option);
+	int32_t				short_option(const char* option);
+
+private:
+
+	int					m_argc;
+	char**				m_argv;
+	const char*			m_shortopts;
+	const ArgsOption*	m_longopts;
+
+	int					m_current_arg;
+
+	int					m_option_index;
+	char*				m_option_argument;
+};
+
+//-----------------------------------------------------------------------------
+inline Args::Args(int argc, char** argv, const char* shortopts, const ArgsOption* longopts) :
+	m_argc(argc),
+	m_argv(argv),
+	m_shortopts(shortopts),
+	m_longopts(longopts),
+	m_current_arg(1),			// Do not consider argv[0]
+	m_option_index(0),
+	m_option_argument(NULL)
+{
+	assert(argv != NULL);
+	assert(shortopts != NULL);
+	// longopts could be NULL
+}
+
+//-----------------------------------------------------------------------------
+inline Args::~Args()
+{
+}
+
+//-----------------------------------------------------------------------------
+inline int32_t Args::next_option()
+{
+	// End of arguments
+	if (m_current_arg >= m_argc)
+	{
+		return -1;
+	}
+
+	const char* current_arg = m_argv[m_current_arg];
+
+	ArgsOptionType type = option_type(current_arg);
+
+	int32_t return_value = -1;
+
+	switch (type)
+	{
+		case AOT_SHORT:
+		{
+			printf("Found short option\n");
+			return_value = short_option(current_arg);
+			break;
+		}
+		case AOT_LONG:
+		{
+			printf("Found long option\n");
+			return_value = long_option(current_arg);
+			break;
+		}
+		case AOT_NOT_OPTION:
+		{
+			printf("Found NOT option\n");
+			return_value = '?';
+			break;
+		}
+		default:
+		{
+			return_value = '?';
+			break;
+		}
+	}
+
+	m_current_arg++;
+
+	return return_value;
+}
+
+//-----------------------------------------------------------------------------
+inline int32_t Args::option_index() const
+{
+	return m_option_index;
+}
+
+//-----------------------------------------------------------------------------
+inline const char* Args::option_argument() const
+{
+	return m_option_argument;
+}
+
+//-----------------------------------------------------------------------------
+inline ArgsOptionType Args::option_type(const char* option)
+{
+	size_t option_len = string::strlen(option);
+
+	if (option_len > 2)
+	{
+		if (option[0] == '-' && option[1] == '-')
+		{
+			return AOT_LONG;
+		}
+	}
+
+	if (option_len > 1)
+	{
+		if (option[0] == '-')
+		{
+			return AOT_SHORT;
+		}
+	}
+
+	return AOT_NOT_OPTION;
+}
+
+//-----------------------------------------------------------------------------
+int32_t Args::long_option(const char* option)
+{
+	int32_t option_index = 0;
+	const ArgsOption* current_option = m_longopts;
+
+	while (1)
+	{
+		if (current_option->name == NULL && current_option->has_arg == 0 && current_option->flag == NULL && current_option->val == 0)
+		{
+			break;
+		}
+
+		if (string::strcmp(current_option->name, &option[2]) == 0)
+		{
+			m_option_index = option_index;
+
+			if (current_option->has_arg == AOA_REQUIRED_ARGUMENT)
+			{
+				if (m_argc > m_current_arg + 1)
+				{
+					m_option_argument = m_argv[m_current_arg + 1];
+				}
+
+				m_current_arg += 1;
+			}
+			else
+			{
+				m_option_argument = NULL;
+			}
+
+			if (current_option->flag == NULL)
+			{
+				return current_option->val;
+			}
+			else
+			{
+				(*current_option->flag) = current_option->val;
+
+				return 0;
+			}
+		}
+
+		option_index++;
+		current_option++;
+	}
+
+	return -1;
+}
+
+//-----------------------------------------------------------------------------
+int32_t Args::short_option(const char* option)
+{
+	(void)option;
+}
+
+} // namespace crown
+