Technology

Quote shell characters

Sometimes it’s nice to be able to display a command being run and do it in a form that can be repeated from a terminal window. Unfortunately, I’ll build a command in python like this:

args = ['somecmd', 'WHERE=$(DESTDIR)', '--message', "Lot's of text" ]

The trivial answer of ‘ ‘.join (args) produces something that can’t be passed to the shell:

>>> ' '.join (args)
"somecmd WHERE=$(DESTDIR) --message Lot's of text"

Here is a code fragment and some attached tests that provide better quoting. It’s used like this:

>>> import shquote
>>> args = ['somecmd', 'WHERE=$(DESTDIR)', '--message', "Lot's of text" ]
>>> print ' '.join ([shquote.shquote (a) for a in args])
somecmd 'WHERE=$(DESTDIR)' --message "Lot's of text"
#!/usr/bin/env python
def shquote (arg):
    """
    Quote a single argument in the most readable way so it is safe from
    shell expansion.
    """
    # Return an empty string as double quoted
    if not arg:
        return '""'
    special = """ t[]{}()'*?|;"""   # These need double quotes
    superspecial = """$"!"""        # These need single quotes
    quotechar = None
    # See if we need single quotes
    for c in superspecial:
        if c in arg:
            quotechar = "'"
            break
    # See if we need double quotes
    if not quotechar:
        for c in special:
            if c in arg:
                quotechar = '"'
                break
    # No quoting necessary
    if not quotechar:
        return arg
    # If quotechar is present then escape it by dropping out of quotes
    if quotechar in arg:
        arg = arg.replace (quotechar, "%s\%s%s" % (quotechar, quotechar, quotechar))
    return quotechar + arg + quotechar
if __name__ == '__main__':
    tests = [('',       '""'),
             ('*.cpp',  '"*.cpp"'),
             ('test.[ch]', '"test.[ch]"'),
             ('(',      '"("'),
             (')',      '")"'),
             ('a',      'a'),
             ('$',      """'$'"""),
             ('$a',     """'$a'"""),
             ('abc|def', '"abc|def"'),
             ('abc;def', '"abc;def"'),
             ('a b',    '"a b"'),
             ('"abc"',  """'"abc"'"""),
             ("""It's mine""", '"It's mine"'),
             ('abc | def ABC=$(XYC)', """'abc | def ABC=$(XYC)'"""),
             (""""That's impossible!" he said.""", """'"That'\''s impossible!" he said.'"""),
          ]
    for (input, expected) in tests:
        output = shquote (input)
        if output != expected:
            print 'input    = ', input
            print 'expected = ', expected
            print 'got      = ', output
        else:
            print "%-30s => %s" % (input, output)

And the result of running this:

bash-3.2$ ./shquote.py
                               => ""
*.cpp                          => "*.cpp"
test.[ch]                      => "test.[ch]"
(                              => "("
)                              => ")"
a                              => a
$                              => '$'
$a                             => '$a'
abc|def                        => "abc|def"
abc;def                        => "abc;def"
a b                            => "a b"
"abc"                          => '"abc"'
It's mine                      => "It's mine"
abc | def ABC=$(XYC)           => 'abc | def ABC=$(XYC)'
"That's impossible!" he said.  => '"That'''s impossible!" he said.'
Technology

Passing extra arguments to output operator

I usually implement the output operator for a class, operator<<().
I find it useful for debugging and regression testing purposes.
Occasionally when defining a class hierarchy with polymorphism in mind
I’ll instead define a virtual print() method.

Base  base;
std::cout << "base = " << base << std::endl;

Here’s the typical implementation:

class Base {
// ...
public:
    /// print Base with flags indicating hw much extra to include
    virtual void print (std::ostream &out, int flags);
};
std::ostream &
operator<< (std::ostream &out, const Base &base)
{
    base.print (out, 0);
}

So everything is great except… I now want to pass that extra
argument. I could write the following ugly code:

std::cout << "base = ";
base.print (std::cout, 1);
std::cout << std::endl;

Instead, I’m going to follow the example from <iomanip> and define a struct
that saves the arguments and then define an output operator for that
struct. The following code makes it so you can write the above as:

std::cout << "base = " << printstream (base, 1) << std::endl;

Here is the implementation of that. This expects the class to implement a method print() that takes a std::ostream and a second argument. It’s pretty easy to extend this to a print() that takes a third argument.

#ifndef INCLUDED_PRINTSTREAM_H
#define INCLUDED_PRINTSTREAM_H
#include 
namespace printstream_impl {
template
struct PrintStream1
{
    const ObjectType &  m_object;
    const Arg1Type &    m_arg1;
    PrintStream1 (const ObjectType &object, const Arg1Type &arg1)
        : m_object (object),
          m_arg1 (arg1)
    {
    }
    std::ostream &print (std::ostream &out) const
    {
        m_object.print (out, m_arg1);
        return out;
    }
};
template
std::ostream &operator<<(std::ostream &out, const PrintStream1 &ps)
{
    ps.print (out);
    return out;
}
} // End namespace printstream
template
printstream_impl::PrintStream1
printstream (const ObjectType &object,
             const Arg1Type &arg1)
{
    return printstream_impl::PrintStream1 (object, arg1);
}
#endif /*  INCLUDED_PRINTSTREAM_H */
Technology

Switching keys in values in a map

A functor that reverses a pair: first becomes second,
second becomes first. Useful for switching
from a map to another map (or multimap in this example) where
the value becomes the key and the key the value.

std::map<std::string, int> m;
std::multimap<int,std::string> m2;
m["a"] = 0;
m["b"] = 1;
m["c"] = 0;
std::transform (m.begin(), m.end(), std::inserter (m2, m2.begin()),
                pair_switch());

And the actual code:

template<class PairType>
struct pair_switcher : public std::unary_function<PairType, std::pair<a,b>
{
 typedef std::pair result_type;
 typedef PairType argument_type;
 result_type operator()(const argument_type &p) const
 {
     return result_type (p.second, p.first);
 }
};
Technology

Functor for deleting objects

In a destructor for a class, I had a std::vector of pointers that I wanted to delete. I started to write the usual for(;;) loop and realized I do this often enough I should make it easy to use std::for_each().
Here’s the functor (based on std::unary_function):

template
struct deleter: public std::unary_function
{
    bool operator()(Type * ptr) const
    {
        delete ptr;
        return true;
    }
};

And here’s some sample code using it:

std::vector m_symbols;
// ...
std::for_each (m_symbols.begin(), m_symbols.end(), deleter());

I added a return of true because some other template code wasn’t happy about “return void” — supposedly something fixed in recent compilers.

Technology

A better output_iterator

I was using the std::stream_iterator, for example:

    std::vector    vals;
    vals.push_back (12);
    vals.push_back (22);
    vals.push_back (5);
    vals.push_back (30);
    // The std::ostream_iterator appends the ","
    std::ostringstream  str3;
    std::copy (vals.begin(), vals.end(), std::ostream_iterator (str3, ","));
    CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30,"), str3.str());

It has the “,” after the last item.
So here’s an implementation that doesn’t append the seperator after the last one:

#ifndef INCLUDED_OUTITER_H
#define INCLUDED_OUTITER_H
#include 
/**
 * A replacement for std::ostream_iterator that doesn't put the
 * seperator after the last item.
 */
template<typename Type, typename CharType = char,
     typename Traits = std::char_traits >
class outiter : public std::iterator
{
public:
    typedef CharType            char_type;
    typedef Traits          traits_type;
    typedef std::basic_ostream    ostream_type;
    /// Initialize from a stream
    outiter (ostream_type &stream)
    : m_stream (&stream),
      m_string (0),
      m_started (false)
    {}
    /// Copy constructor
    outiter (const outiter &copy)
    : m_stream (copy.m_stream),
      m_string (copy.m_string),
      m_started (copy.m_started)
    {}
    /// Initialize from a stream and the seperator
    outiter (ostream_type &stream, const CharType *str)
    : m_stream (&stream),
      m_string (str),
      m_started (false)
    {}
    /// Assignment actually does the output
    outiter &
    operator=(const Type &value)
    {
    if (!m_started)
    {
        m_started = true;
    }
    else if (m_string)
    {
            (*m_stream) << m_string;
    }
    (*m_stream) << value;
    return *this;
    }
    /// Just return a reference to this
    outiter &
    operator*()
    {
    return *this;
    }
    /// Just return a reference to this
    outiter &
    operator++()
    {
    return *this;
    }
    /// Just return a reference to this
    outiter &
    operator++(int)
    {
    return *this;
    }
private:
    /// The stream to write to
    ostream_type *      m_stream;
    /// The seperator (may be NULL)
    const char_type *       m_string;
    /// Flag to indicate if we've output anything
    bool            m_started;
};
#endif /* INCLUDED_OUTITER_H */

And here’s the corresponding code to use it:

    std::ostringstream  str;
    std::copy (vals.begin(), vals.end(), outiter (str, ","));
    CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30"), str.str());
Technology

Copying a std::vector into a std::map

I had two vector’s with the first being the keys and the second being the values. It took a couple tries before I got the STL working for me!
The first thing was to check if the std::map constructors had something useful. It certainly seems like taking two sets of iterators would be a great way to initialize a map. No such luck.
So how about one of the std algorithms to copy the keys and values into the map? std::copy seemed likely but it only takes a single sequence. A little more digging and std::transform. The second version of std::transform takes two sequences, an output iterator, and a binary function to convert the two values from the two sequences into something that can be inserted into the output iterator. Perfect.
So how to turn the two values into a pair suitable for std::map? The std::make_pair
is exactly what is needed. The hard part is getting the syntax so you can pass it as a function: make_pair in this example.
So the code finally looks like:

#include 
#include 
#include 
#include 
#include 
#include 
void test()
{
    std::map  m;
    std::vector    keys;
    std::vector        values;
    std::transform (keys.begin(), keys.end(),
                    values.begin(),
                    std::inserter (m, m.begin()),
                    std::make_pair);
}
Technology

Setting the timezone

I’ve gotten pretty careful about keeping time in UTC and then converting it to localtime for the user to understand. For the first time, I actually had to find the localtime in a non-local timezone. It’s ugly. It seems you have to mess with the TZ environment variable. Here’s what I wrote:

#include 

And here’s a code fragment that uses it:

std::string oldzone = changeTimeZone("US/Pacific");
time_t  seconds = ::time(0);
struct tm   tm_time;
localtime_r (&seconds, tm_time);
changeTimeZone(oldzone);