Posts tagged c#

Xcode: notes

To reset Xcode to the default settings:

$ defaults delete com.apple.Xcode
$ rm -rf ~/Library/Application\ Support/Xcode

First, I dislike having a lot of popup windows so I set the layout to “All-In-One” to keep most things within a single window:

grab-001.png

And my usual indentation style:

grab-003.png

I like having the files autosaved on build:

=grab-007.png

sqlite3 rocks

I’d been using the sqlite3 that came installed on Mac OS X but I ran into some portability issues — not every system has it installed. So I decided to bite the bullet and include it with my code.

It was trivial! I downloaded a zip with 3 files (sqlite3.c,sqlite3.h, and sqlite3ext.h). Added sqlite3.c to my list of sources and it just compiled! No configuration, no trickly flags, it just worked!

Getting the keys from a std::map

So last week I wrote about initializing a std::map from two std::vectors. How about doing the reverse? How do I get a list of the keys or a list of the values into a vector?

So I wrote a functor, based on std::unary_function, that returns the pair.first and another that returns the pair.second:

#include <utility>
#include <functional>
 
    /**
     * A functor that returns the first in a pair
     */
    template<typename PairType>
    struct first: public std::unary_function<PairType, typename PairType::first_type>
    {
	typedef typename PairType::first_type result_type;
	typedef PairType argument_type;
 
	result_type operator()(argument_type &p) const
	{
	    return p.first;
	}
 
	result_type operator()(const argument_type &p) const
	{
	    return p.first;
	}
    };
 
    /**
     * A functor that returns the second in a pair
     */
    template<typename PairType>
    struct second: public std::unary_function<PairType, typename PairType::second_type>
    {
	typedef typename PairType::second_type result_type;
	typedef PairType argument_type;
 
	result_type operator()(argument_type &p) const
	{
	    return p.second;
	}
	result_type operator()(const argument_type &p) const
	{
	    return p.second;
	}
    };

The first() template functor (from above) is used as the functor that returns the key to the std::transform() alogrithm. Here is a little fragment code that uses first(). (The test code part of a larger CPPUNIT test suite):

void TestUtils::testFirst()
{
    typedef std::map<std::string,std::string> String2StringMap;
    String2StringMap m;
 
    m["a"] = "0";
    m["z"] = "1";
    m["x"] = "2";
 
    std::vector<std::string>	keys;
    std::transform (m.begin(), m.end(),
		    std::back_inserter (keys),
		    first<String2StringMap::value_type>());
    CPPUNIT_ASSERT_EQUAL (m.size(), keys.size());
    CPPUNIT_ASSERT_EQUAL (std::string ("x"), keys[1]);
}

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):

    #include <functional>
 
    template<typename Type>
    struct deleter: public std::unary_function<Type *, bool>
    {
	bool operator()(Type * ptr) const
	{
	    delete ptr;
	    return true;
	}
    };

And here’s some sample code using it:

std::vector<Symbol *> m_symbols;
// ...
std::for_each (m_symbols.begin(), m_symbols.end(), deleter<Symbol>());

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

A better output_iterator

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

    std::vector<int>	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<int> (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 <iterator>
 
/**
 * 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<CharType> >
class outiter : public std::iterator<std::output_iterator_tag, void, void, void, void>
{
public:
    typedef CharType			char_type;
    typedef Traits			traits_type;
    typedef std::basic_ostream<CharType, Traits>	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<int> (str, ","));
    CPPUNIT_ASSERT_EQUAL (std::string ("12,22,5,30"), str.str());

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<std::string,int> in this example.

So the code finally looks like:

#include <map>
#include <vector>
#include <algorithm>
#include <utility>
#include <string>
#include <iterator>
 
void test()
{
		std::map<std::string, int>	m;
		std::vector<std::string>		keys;
		std::vector<int>			values;
 
		std::transform (keys.begin(), keys.end(),
						values.begin(),
						std::inserter (m, m.begin()),
						std::make_pair<std::string,int>);
}

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 <time.h>
#include <string>
 
std::string changeTimeZone (const std::string &tzname)
{
	char *tzptr = getenv ("TZ");
	std::string  tzold;
 
	if (tzptr)
		tzold = tzptr;
	if (tzname.empty())
		unsetenv ("TZ");
	else
		setenv ("TZ", tzname.c_str(), 1);
	tzset();
	return tzold;
}

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);