runtime: Remove unordered_map usage in writer

Using an explicit switch statement is just as clear and saves ~12KB from
the release build on Linux.
runtime: Don't set locale on init

Number formatting, string sorting, etc is tightly defined by R7RS. The
C++ locale should be left as "C" to prevent any unexpected formatting or
conversions.
runtime: Don't buffer string likes and write

When writing symbols and strings we were writing to a temporary
ostringstream until we determined if the string-like needed quotes. This
has a number of disadvantages:

- Constructing an ostringstream is expensive (at least on libstdc++) due
  to locale setup

- This requires allocating additional memory for the output string with
  no clean way to reserve a buffer. This can lead to many allocations
  for large strings.

- The writing code mixed rendering logic with quote tracking logic. This
  makes it difficult to follow

Instead first do a pass on symbols to determine if they need a quote.
This can abort on the first quote-requiring character and can be skipped
completely for strings which are always quoted. Then, write the output
directly to the writer's output stream

On a modified version of generate-cxr-library.scm that outputs ~50K
lines of Scheme this more than halved its runtime. This should be even
more dramatic for strings which can skip the quote detection completely.
runtime: Optimise UTF-8 encoding

Currently fromUnicodeChars() and toConvertedString() use
encodeUtf8Char() to repeatedly insert a temporary vector to the end of
an output vector. This requires a temporary allocation which is very
slow.

Instead, introduce appendUtf8Char() which will append the encoded
character to any output iterator. This allows us to use
std::back_inserter to append to the UTF-8 output vector without using a
temporary. utf8::encodeUtf8Char() is reimplemented as a simple wrapper
on top of appendUtf8Char() for use cases that only need a single
character.

This results in an approximately 15% speedup in the generate-cxr-library
benchmark which calls ::fromUnicodeChars() via (list->string)