|
From: <sg...@us...> - 2003-12-10 19:57:09
|
Update of /cvsroot/libfunutil/libfunutil/lib/toolbox/src
In directory sc8-pr-cvs1:/tmp/cvs-serv16731/lib/toolbox/src
Added Files:
aliaser.h
Log Message:
egg
--- NEW FILE: aliaser.h ---
#ifndef TOOLBOX_NAMESPACE_ALIASER_H_INCLUDED
#define TOOLBOX_NAMESPACE_ALIASER_H_INCLUDED 1
#include <map>
#include <string>
#include <TOOLBOX_NAMESPACE/debuggering_macros.h> // COUT/CERR
namespace TOOLBOX_NAMESPACE
{
/**
aliaser is a helper class for mapping single-token aliases
to arbitrary strings, e.g., similarly to typical Unix shell
alias support.
Parameterized on:
- ContextType: all aliasers with the same ContextType
share the same aliases map.
This class was written to support the creation of a
command-line-interface framework, thus it is designed
to allow disparate shell components to get at the same
aliases easily, without having to track an instance
all around the world.
*/
template <typename ContextType>
struct aliaser
{
typedef ContextType context_type;
typedef std::map<std::string,std::string> map_type;
typedef aliaser<ContextType> ThisType;
/**
Returns the map of aliases-to-expansions.
*/
static map_type & map()
{
static map_type bob;
return bob;
}
/**
Aliases <code>al</code> as a shortcut for <code>expanded</code>.
al should be exactly one token.
*/
static void alias( const std::string & al, const std::string & expanded )
{
// CERR << "alias("<<al<<",["<<expanded<<"])"<<std::endl;
if( expanded.empty() )
{
map_type::iterator it = map().find( al );
if( map().end() != it )
{
map().erase( it );
}
return;
}
map()[al] = expanded;
}
/**
Works similarly to Unix shells' alias expansion:
Expands the input token as an alias. This expansion
continues until the token can no longer be expanded
to a new string.
It returns the expanded string, which may be identical
to the input.
input should be exactly one token.
*/
static std::string expand( const std::string & input )
{
if( input.empty() ) return input;
string arg = input.substr( 0, input.find_first_of(" \t\n") );
map_type::const_iterator it = map().find( arg );
if( map().end() == it )
{
return input;
}
string code = (*it).second;
if( code == arg )
{
return arg;
}
string tmp = code + ( (arg.size() == input.size()) ? string() : input.substr( arg.size() ) ); // skip the first token
// CERR << "alias resolution for ["<<input<<"] = ["<<tmp<<"]"<<std::endl;
// not thread safe:
static unsigned int loopblocker = 0;
if( ++loopblocker > 9 )
{
CERR << "******************** WARNING ********************\n"
<< "expand() has been through "<<loopblocker
<< " iterations. That's probably too many, so we're aborting alias expansion. "
<< "You probably have aliases which expand to each other. Please check this content for possible problems: ["<<input<<"]."
<< "\nIf you believe this to be a bug, please fix it in " << __FILE__ <<", line " <<__LINE__<<"."
<< endl;
loopblocker = 0;
return tmp;
}
tmp = expand( tmp );
--loopblocker;
return tmp;
}
private:
aliaser(){}
~aliaser(){}
aliaser & operator=( const aliaser & ); // not implemented
aliaser( const aliaser & ); // not implemented
};
} // namespace TOOLBOX_NAMESPACE
#endif // TOOLBOX_NAMESPACE_ALIASER_H_INCLUDED
|