Replace formatter with context
diff --git a/fmt/format.cc b/fmt/format.cc
index 55ece67..5ec8e41 100644
--- a/fmt/format.cc
+++ b/fmt/format.cc
@@ -446,7 +446,7 @@
             format_args args);
 
 FMT_FUNC int vfprintf(std::FILE *f, CStringRef format,
-                      basic_format_args<PrintfFormatter<char>> args) {
+                      basic_format_args<printf_context<char>> args) {
   MemoryWriter w;
   printf(w, format, args);
   std::size_t size = w.size();
@@ -463,7 +463,7 @@
 
 template void internal::ArgMap<char>::init(const format_args &args);
 
-template void PrintfFormatter<char>::format(Writer &writer, CStringRef format);
+template void printf_context<char>::format(Writer &writer);
 
 template int internal::CharTraits<char>::format_float(
     char *buffer, std::size_t size, const char *format,
@@ -479,8 +479,7 @@
 
 template void internal::ArgMap<wchar_t>::init(const format_args &args);
 
-template void PrintfFormatter<wchar_t>::format(WWriter &writer,
-                                               WCStringRef format);
+template void printf_context<wchar_t>::format(WWriter &writer);
 
 template int internal::CharTraits<wchar_t>::format_float(
     wchar_t *buffer, std::size_t size, const wchar_t *format,
diff --git a/fmt/format.h b/fmt/format.h
index 9d9359b..303091f 100644
--- a/fmt/format.h
+++ b/fmt/format.h
@@ -377,8 +377,11 @@
 template <typename Impl, typename Char>
 class BasicPrintfArgFormatter;
 
-template <typename Char, typename ArgFormatter = fmt::ArgFormatter<Char> >
-class basic_formatter;
+template <typename Char>
+class basic_format_context;
+
+typedef basic_format_context<char> format_context;
+typedef basic_format_context<wchar_t> wformat_context;
 
 /**
   \rst
@@ -993,7 +996,7 @@
   };
 
   typedef void (*FormatFunc)(
-      void *writer, const void *arg, void *formatter, void *format_str_ptr);
+      void *writer, const void *arg, void *ctx);
 
   struct CustomValue {
     const void *value;
@@ -1230,10 +1233,10 @@
 constexpr Type type() { return gettype<typename std::decay<T>::type>(); }
 
 // Makes an Arg object from any type.
-template <typename Formatter>
+template <typename Context>
 class MakeValue : public Arg {
  public:
-  typedef typename Formatter::char_type Char;
+  typedef typename Context::char_type Char;
 
  private:
   // The following two methods are private to disallow formatting of
@@ -1271,12 +1274,10 @@
   // Formats an argument of a custom type, such as a user-defined class.
   template <typename T>
   static void format_custom_arg(
-      void *writer, const void *arg, void *formatter, void *format_str_ptr) {
-    typedef BasicWriter<typename Formatter::char_type> Writer;
-    format_value(*static_cast<Writer*>(writer),
+      void *writer, const void *arg, void *context) {
+    format_value(*static_cast<BasicWriter<Char>*>(writer),
                  *static_cast<const T*>(arg),
-                 *static_cast<Formatter*>(formatter),
-                 *static_cast<const Char**>(format_str_ptr));
+                 *static_cast<Context*>(context));
   }
 
  public:
@@ -1406,7 +1407,7 @@
 
   template <typename T>
   NamedArg(BasicStringRef<Char> argname, const T &value)
-  : Arg(MakeArg< basic_formatter<Char> >(value)), name(argname) {}
+  : Arg(MakeArg< basic_format_context<Char> >(value)), name(argname) {}
 };
 
 class RuntimeError : public std::runtime_error {
@@ -1430,7 +1431,7 @@
 enum { MAX_PACKED_ARGS = 16 };
 }  // namespace internal
 
-template <typename Formatter, typename ...Args>
+template <typename Context, typename ...Args>
 class format_arg_store {
  private:
   static const size_t NUM_ARGS = sizeof...(Args);
@@ -1443,26 +1444,25 @@
   std::array<value_type, NUM_ARGS + (IS_PACKED ? 0 : 1)> data_;
 
   template <typename ...A>
-  friend format_arg_store<Formatter, A...> make_format_args(const A & ... args);
+  friend format_arg_store<Context, A...> make_format_args(const A & ... args);
 
  public:
   static const uint64_t TYPES = internal::make_type<Args..., void>();
 
-  format_arg_store(const Args &... args, Formatter *)
-    : data_{{internal::MakeValue<Formatter>(args)...}} {}
+  format_arg_store(const Args &... args)
+    : data_{{internal::MakeValue<Context>(args)...}} {}
 
   const value_type *data() const { return data_.data(); }
 };
 
-template <typename Formatter, typename ...Args>
-inline format_arg_store<Formatter, Args...>
+template <typename Context, typename ...Args>
+inline format_arg_store<Context, Args...>
     make_format_args(const Args & ... args) {
-  Formatter *f = nullptr;
-  return format_arg_store<Formatter, Args...>(args..., f);
+  return format_arg_store<Context, Args...>(args...);
 }
 
 /** Formatting arguments. */
-template <typename Formatter>
+template <typename Context>
 class basic_format_args {
  private:
   // To reduce compiled code size per formatting function call, types of first
@@ -1496,7 +1496,7 @@
   basic_format_args() : types_(0) {}
 
   template <typename... Args>
-  basic_format_args(const format_arg_store<Formatter, Args...> &store)
+  basic_format_args(const format_arg_store<Context, Args...> &store)
   : types_(store.TYPES) {
     set_data(store.data());
   }
@@ -1527,8 +1527,8 @@
   }
 };
 
-typedef basic_format_args<basic_formatter<char>> format_args;
-typedef basic_format_args<basic_formatter<wchar_t>> wformat_args;
+typedef basic_format_args<basic_format_context<char>> format_args;
+typedef basic_format_args<basic_format_context<wchar_t>> wformat_args;
 
 #define FMT_DISPATCH(call) static_cast<Impl*>(this)->call
 
@@ -2014,6 +2014,8 @@
   }
 
  public:
+  typedef Char char_type;
+
   ArgFormatterBase(BasicWriter<Char> &w, FormatSpec &s)
   : writer_(w), spec_(s) {}
 
@@ -2082,21 +2084,35 @@
   }
 };
 
-template <typename Formatter>
-class FormatterBase {
-private:
-  basic_format_args<Formatter> args_;
+template <typename Char>
+inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
+  if (start != end)
+    w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
+}
+
+template <typename Char, typename Context>
+class format_context_base {
+ private:
+  const Char *ptr_;
+  basic_format_args<Context> args_;
   int next_arg_index_;
 
+ protected:
+  format_context_base(const Char *format_str, basic_format_args<Context> args)
+  : ptr_(format_str), args_(args), next_arg_index_(0) {}
+  ~format_context_base() {}
+
+  basic_format_args<Context> args() const { return args_; }
+
   // Returns the argument with specified index.
-  Arg do_get_arg(unsigned arg_index, const char *&error) {
-    Arg arg = args_[arg_index];
+  format_arg do_get_arg(unsigned arg_index, const char *&error) {
+    format_arg arg = args_[arg_index];
     switch (arg.type) {
-      case Arg::NONE:
+      case format_arg::NONE:
         error = "argument index out of range";
         break;
-      case Arg::NAMED_ARG:
-        arg = *static_cast<const internal::Arg*>(arg.pointer);
+      case format_arg::NAMED_ARG:
+        arg = *static_cast<const format_arg*>(arg.pointer);
         break;
       default:
         /*nothing*/;
@@ -2104,24 +2120,19 @@
     return arg;
   }
 
- protected:
-  FormatterBase(basic_format_args<Formatter> args)
-  : args_(args), next_arg_index_(0) {}
-
-  const basic_format_args<Formatter> &args() const { return args_; }
-
-  // Returns the next argument.
-  Arg next_arg(const char *&error) {
-    if (next_arg_index_ >= 0)
-      return do_get_arg(internal::to_unsigned(next_arg_index_++), error);
-    error = "cannot switch from manual to automatic argument indexing";
-    return Arg();
-  }
-
   // Checks if manual indexing is used and returns the argument with
   // specified index.
-  Arg get_arg(unsigned arg_index, const char *&error) {
-    return check_no_auto_index(error) ? do_get_arg(arg_index, error) : Arg();
+  format_arg get_arg(unsigned arg_index, const char *&error) {
+    return this->check_no_auto_index(error) ?
+      this->do_get_arg(arg_index, error) : format_arg();
+  }
+
+  // Returns the next argument.
+  format_arg next_arg(const char *&error) {
+    if (next_arg_index_ >= 0)
+      return this->do_get_arg(internal::to_unsigned(next_arg_index_++), error);
+    error = "cannot switch from manual to automatic argument indexing";
+    return format_arg();
   }
 
   bool check_no_auto_index(const char *&error) {
@@ -2132,13 +2143,11 @@
     next_arg_index_ = -1;
     return true;
   }
-};
 
-template <typename Char>
-inline void write(BasicWriter<Char> &w, const Char *start, const Char *end) {
-  if (start != end)
-    w << BasicStringRef<Char>(start, internal::to_unsigned(end - start));
-}
+ public:
+  // Returns a pointer to the current position in the format string.
+  const Char *&ptr() { return ptr_; }
+};
 }  // namespace internal
 
 /**
@@ -2161,8 +2170,7 @@
 template <typename Impl, typename Char>
 class BasicArgFormatter : public internal::ArgFormatterBase<Impl, Char> {
  private:
-  basic_formatter<Char, Impl> &formatter_;
-  const Char *format_;
+  basic_format_context<Char> &ctx_;
 
  public:
   /**
@@ -2173,15 +2181,13 @@
     to the part of the format string being parsed for custom argument types.
     \endrst
    */
-  BasicArgFormatter(BasicWriter<Char> &writer,
-                    basic_formatter<Char, Impl> &formatter,
-                    FormatSpec &spec, const Char *fmt)
-  : internal::ArgFormatterBase<Impl, Char>(writer, spec),
-    formatter_(formatter), format_(fmt) {}
+  BasicArgFormatter(BasicWriter<Char> &writer, basic_format_context<Char> &ctx,
+                    FormatSpec &spec)
+  : internal::ArgFormatterBase<Impl, Char>(writer, spec), ctx_(ctx) {}
 
   /** Formats an argument of a custom (user-defined) type. */
   void visit_custom(internal::Arg::CustomValue c) {
-    c.format(&this->writer(), c.value, &formatter_, &format_);
+    c.format(&this->writer(), c.value, &ctx_);
   }
 };
 
@@ -2190,49 +2196,45 @@
 class ArgFormatter : public BasicArgFormatter<ArgFormatter<Char>, Char> {
  public:
   /** Constructs an argument formatter object. */
-  ArgFormatter(BasicWriter<Char> &writer, basic_formatter<Char> &formatter,
-               FormatSpec &spec, const Char *fmt)
-  : BasicArgFormatter<ArgFormatter<Char>, Char>(writer, formatter, spec, fmt) {}
+  ArgFormatter(BasicWriter<Char> &writer, basic_format_context<Char> &ctx,
+               FormatSpec &spec)
+  : BasicArgFormatter<ArgFormatter<Char>, Char>(writer, ctx, spec) {}
 };
 
-/** This template formats data and writes the output to a writer. */
-template <typename Char, typename ArgFormatter>
-class basic_formatter :
-  private internal::FormatterBase<basic_formatter<Char, ArgFormatter>> {
- public:
-  /** The character type for the output. */
-  typedef Char char_type;
-
+template <typename Char>
+class basic_format_context :
+  public internal::format_context_base<Char, basic_format_context<Char>> {
  private:
   internal::ArgMap<Char> map_;
 
-  FMT_DISALLOW_COPY_AND_ASSIGN(basic_formatter);
+  FMT_DISALLOW_COPY_AND_ASSIGN(basic_format_context);
 
-  typedef internal::FormatterBase<basic_formatter> Base;
+  typedef internal::format_context_base<Char, basic_format_context> Base;
+
   using Base::get_arg;
 
   // Checks if manual indexing is used and returns the argument with
   // specified name.
-  internal::Arg get_arg(BasicStringRef<Char> arg_name, const char *&error);
+  format_arg get_arg(BasicStringRef<Char> name, const char *&error);
 
  public:
+  /** The character type for the output. */
+  typedef Char char_type;
+
   /**
    \rst
-   Constructs a ``basic_formatter`` object. References to the arguments are
-   stored in the formatter object so make sure they have appropriate lifetimes.
+   Constructs a ``basic_format_context`` object. References to the arguments are
+   stored in the object so make sure they have appropriate lifetimes.
    \endrst
    */
-  basic_formatter(basic_format_args<basic_formatter> args) : Base(args) {}
+  basic_format_context(const Char *format_str,
+                       basic_format_args<basic_format_context> args)
+  : Base(format_str, args) {}
 
-  // Parses argument index and returns corresponding argument.
-  internal::Arg parse_arg_index(const Char *&s);
-  
-  // Parses argument name and returns corresponding argument.
-  internal::Arg parse_arg_name(const Char *&s);
+  // Parses argument id and returns corresponding argument.
+  format_arg parse_arg_id();
 
-  // Formats a single argument and advances format_str, a format string pointer.
-  const Char *format(BasicWriter<Char> &writer, const Char *&format_str,
-                     const internal::Arg &arg);
+  using Base::ptr;
 };
 
 /**
@@ -2269,7 +2271,7 @@
   */
   template <typename... Args>
   SystemError(int error_code, CStringRef message, const Args & ... args) {
-    init(error_code, message, make_format_args<basic_formatter<char>>(args...));
+    init(error_code, message, make_format_args<format_context>(args...));
   }
 
   ~SystemError() throw();
@@ -2464,10 +2466,7 @@
   }
 
   void vwrite(BasicCStringRef<Char> format,
-              basic_format_args<basic_formatter<Char>> args) {
-    vformat(*this, format, args);
-  }
-
+              basic_format_args<basic_format_context<Char>> args);
   /**
     \rst
     Writes formatted data.
@@ -2495,7 +2494,7 @@
    */
   template <typename... Args>
   void write(BasicCStringRef<Char> format, const Args & ... args) {
-    vwrite(format, make_format_args<fmt::basic_formatter<Char>>(args...));
+    vwrite(format, make_format_args<basic_format_context<Char>>(args...));
   }
 
   BasicWriter &operator<<(int value) {
@@ -3123,7 +3122,7 @@
   */
   template <typename... Args>
   WindowsError(int error_code, CStringRef message, const Args & ... args) {
-    init(error_code, message, make_format_args<basic_formatter<char>>(args...));
+    init(error_code, message, make_format_args<format_context>(args...));
   }
 };
 
@@ -3147,8 +3146,7 @@
 template <typename... Args>
 inline void print_colored(Color c, CStringRef format_str,
                           const Args & ... args) {
-  vprint_colored(c, format_str,
-                 make_format_args<basic_formatter<char>>(args...));
+  vprint_colored(c, format_str, make_format_args<format_context>(args...));
 }
 
 inline std::string vformat(CStringRef format_str, format_args args) {
@@ -3168,7 +3166,7 @@
 */
 template <typename... Args>
 inline std::string format(CStringRef format_str, const Args & ... args) {
-  return vformat(format_str, make_format_args<basic_formatter<char>>(args...));
+  return vformat(format_str, make_format_args<format_context>(args...));
 }
 
 inline std::wstring vformat(WCStringRef format_str, wformat_args args) {
@@ -3179,7 +3177,7 @@
 
 template <typename... Args>
 inline std::wstring format(WCStringRef format_str, const Args & ... args) {
-  auto vargs = make_format_args<basic_formatter<wchar_t>>(args...);
+  auto vargs = make_format_args<wformat_context>(args...);
   return vformat(format_str, vargs);
 }
 
@@ -3196,7 +3194,7 @@
  */
 template <typename... Args>
 inline void print(std::FILE *f, CStringRef format_str, const Args & ... args) {
-  vprint(f, format_str, make_format_args<basic_formatter<char>>(args...));
+  vprint(f, format_str, make_format_args<format_context>(args...));
 }
 
 FMT_API void vprint(CStringRef format_str, format_args args);
@@ -3212,7 +3210,7 @@
  */
 template <typename... Args>
 inline void print(CStringRef format_str, const Args & ... args) {
-  vprint(format_str, make_format_args<basic_formatter<char>>(args...));
+  vprint(format_str, make_format_args<format_context>(args...));
 }
 
 /**
@@ -3405,57 +3403,55 @@
 }
 }  // namespace internal
 
-template <typename Char, typename AF>
-inline internal::Arg basic_formatter<Char, AF>::get_arg(
-    BasicStringRef<Char> arg_name, const char *&error) {
+template <typename Char>
+inline format_arg basic_format_context<Char>::get_arg(
+    BasicStringRef<Char> name, const char *&error) {
   if (this->check_no_auto_index(error)) {
     map_.init(this->args());
-    const internal::Arg *arg = map_.find(arg_name);
+    const internal::Arg *arg = map_.find(name);
     if (arg)
       return *arg;
     error = "argument not found";
   }
-  return internal::Arg();
+  return format_arg();
 }
 
-template <typename Char, typename AF>
-inline internal::Arg basic_formatter<Char, AF>::parse_arg_index(
-    const Char *&s) {
-  const char *error = 0;
-  internal::Arg arg = *s < '0' || *s > '9' ?
-    this->next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
-  if (error) {
-    FMT_THROW(format_error(
-                *s != '}' && *s != ':' ? "invalid format string" : error));
+template <typename Char>
+inline format_arg basic_format_context<Char>::parse_arg_id() {
+  const Char *&s = this->ptr();
+  if (!internal::is_name_start(*s)) {
+    const char *error = 0;
+    format_arg arg = *s < '0' || *s > '9' ?
+      this->next_arg(error) : get_arg(internal::parse_nonnegative_int(s), error);
+    if (error) {
+      FMT_THROW(format_error(
+                  *s != '}' && *s != ':' ? "invalid format string" : error));
+    }
+    return arg;
   }
-  return arg;
-}
-
-template <typename Char, typename AF>
-inline internal::Arg basic_formatter<Char, AF>::parse_arg_name(const Char *&s) {
-  assert(internal::is_name_start(*s));
   const Char *start = s;
   Char c;
   do {
     c = *++s;
   } while (internal::is_name_start(c) || ('0' <= c && c <= '9'));
   const char *error = 0;
-  internal::Arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
+  format_arg arg = get_arg(BasicStringRef<Char>(start, s - start), error);
   if (error)
     FMT_THROW(format_error(error));
   return arg;
 }
 
-template <typename Char, typename ArgFormatter>
-const Char *basic_formatter<Char, ArgFormatter>::format(
-    BasicWriter<Char> &writer, const Char *&format_str, const internal::Arg &arg) {
+// Formats a single argument.
+template <typename ArgFormatter, typename Char, typename Context>
+void format_arg(BasicWriter<Char> &writer, const internal::Arg &arg,
+                Context &ctx) {
   using internal::Arg;
-  const Char *s = format_str;
+  const Char *&s = ctx.ptr();
   FormatSpec spec;
   if (*s == ':') {
     if (arg.type == Arg::CUSTOM) {
-      arg.custom.format(&writer, arg.custom.value, this, &s);
-      return s;
+      arg.custom.format(&writer, arg.custom.value, &ctx);
+      return;
     }
     ++s;
     // Parse fill and alignment.
@@ -3527,8 +3523,7 @@
       spec.width_ = internal::parse_nonnegative_int(s);
     } else if (*s == '{') {
       ++s;
-      Arg width_arg = internal::is_name_start(*s) ?
-            parse_arg_name(s) : parse_arg_index(s);
+      Arg width_arg = ctx.parse_arg_id();
       if (*s++ != '}')
         FMT_THROW(format_error("invalid format string"));
       ULongLong value = 0;
@@ -3565,8 +3560,7 @@
         spec.precision_ = internal::parse_nonnegative_int(s);
       } else if (*s == '{') {
         ++s;
-        Arg precision_arg = internal::is_name_start(*s) ?
-              parse_arg_name(s) : parse_arg_index(s);
+        Arg precision_arg = ctx.parse_arg_id();
         if (*s++ != '}')
           FMT_THROW(format_error("invalid format string"));
         ULongLong value = 0;
@@ -3608,20 +3602,19 @@
       spec.type_ = static_cast<char>(*s++);
   }
 
-  if (*s++ != '}')
+  if (*s != '}')
     FMT_THROW(format_error("missing '}' in format string"));
 
   // Format argument.
-  ArgFormatter(writer, *this, spec, s - 1).visit(arg);
-  return s;
+  ArgFormatter(writer, ctx, spec).visit(arg);
 }
 
 /** Formats arguments and writes the output to the writer. */
-template <typename ArgFormatter, typename Char = typename ArgFormatter::Char>
+template <typename ArgFormatter, typename Char, typename Context>
 void vformat(BasicWriter<Char> &writer, BasicCStringRef<Char> format_str,
-             basic_format_args<basic_formatter<Char, ArgFormatter>> args) {
-  basic_formatter<Char, ArgFormatter> formatter(args);
-  const Char *s = format_str.c_str();
+             basic_format_args<Context> args) {
+  basic_format_context<Char> ctx(format_str.c_str(), args);
+  const Char *&s = ctx.ptr();
   const Char *start = s;
   while (*s) {
     Char c = *s++;
@@ -3634,12 +3627,19 @@
     if (c == '}')
       FMT_THROW(format_error("unmatched '}' in format string"));
     internal::write(writer, start, s - 1);
-    internal::Arg arg = internal::is_name_start(*s) ?
-    formatter.parse_arg_name(s) : formatter.parse_arg_index(s);
-    start = s = formatter.format(writer, s, arg);
+    format_arg<ArgFormatter>(writer, ctx.parse_arg_id(), ctx);
+    assert(*s == '}');
+    start = ++s;
   }
   internal::write(writer, start, s);
 }
+
+template <typename Char>
+inline void BasicWriter<Char>::vwrite(
+    BasicCStringRef<Char> format,
+    basic_format_args<basic_format_context<Char>> args) {
+  vformat<ArgFormatter<Char>>(*this, format, args);
+}
 }  // namespace fmt
 
 #if FMT_USE_USER_DEFINED_LITERALS
diff --git a/fmt/ostream.h b/fmt/ostream.h
index 6173e68..feafc3b 100644
--- a/fmt/ostream.h
+++ b/fmt/ostream.h
@@ -82,14 +82,13 @@
 }  // namespace internal
 
 // Formats a value.
-template <typename Char, typename ArgFormatter, typename T>
+template <typename Char, typename T>
 void format_value(BasicWriter<Char> &w, const T &value,
-                  basic_formatter<Char, ArgFormatter> &f,
-                  const Char *&format_str) {
+                  basic_format_context<Char> &ctx) {
   internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
   auto str = internal::format_value(buffer, value);
-  typedef internal::MakeArg< basic_formatter<Char> > MakeArg;
-  format_str = f.format(w, format_str, MakeArg(str));
+  typedef internal::MakeArg< basic_format_context<Char> > MakeArg;
+  format_arg< ArgFormatter<Char> >(w, MakeArg(str), ctx);
 }
 
 FMT_API void vprint(std::ostream &os, CStringRef format_str, format_args args);
@@ -106,7 +105,7 @@
 template <typename... Args>
 inline void print(std::ostream &os, CStringRef format_str,
                   const Args & ... args) {
-  vprint(os, format_str, make_format_args<basic_formatter<char>>(args...));
+  vprint(os, format_str, make_format_args<format_context>(args...));
 }
 }  // namespace fmt
 
diff --git a/fmt/posix.h b/fmt/posix.h
index 5fd1785..c6c6c13 100644
--- a/fmt/posix.h
+++ b/fmt/posix.h
@@ -172,7 +172,7 @@
 
   template <typename... Args>
   inline void print(CStringRef format_str, const Args & ... args) {
-    vprint(format_str, make_format_args<basic_formatter<char>>(args...));
+    vprint(format_str, make_format_args<format_context>(args...));
   }
 };
 
diff --git a/fmt/printf.h b/fmt/printf.h
index 7d17125..42728b7 100644
--- a/fmt/printf.h
+++ b/fmt/printf.h
@@ -262,11 +262,10 @@
 
   /** Formats an argument of a custom (user-defined) type. */
   void visit_custom(internal::Arg::CustomValue c) {
-    typedef basic_formatter<Char> Formatter;
-    Formatter formatter((basic_format_args<Formatter>()));
-    const Char format_str[] = {'}', 0};
-    const Char *format = format_str;
-    c.format(&this->writer(), c.value, &formatter, &format);
+    const Char format_str[] = {'}', '\0'};
+    auto args = basic_format_args<basic_format_context<Char>>();
+    basic_format_context<Char> ctx(format_str, args);
+    c.format(&this->writer(), c.value, &ctx);
   }
 };
 
@@ -283,14 +282,15 @@
 /** This template formats data and writes the output to a writer. */
 template <typename Char,
           typename ArgFormatter = PrintfArgFormatter<Char> >
-class PrintfFormatter :
-  private internal::FormatterBase<PrintfFormatter<Char, ArgFormatter>> {
+class printf_context :
+  private internal::format_context_base<
+    Char, printf_context<Char, ArgFormatter>> {
  public:
   /** The character type for the output. */
   typedef Char char_type;
 
  private:
-  typedef internal::FormatterBase<PrintfFormatter> Base;
+  typedef internal::format_context_base<Char, printf_context> Base;
 
   void parse_flags(FormatSpec &spec, const Char *&s);
 
@@ -306,21 +306,21 @@
  public:
   /**
    \rst
-   Constructs a ``PrintfFormatter`` object. References to the arguments and
-   the writer are stored in the formatter object so make sure they have
+   Constructs a ``printf_context`` object. References to the arguments and
+   the writer are stored in the context object so make sure they have
    appropriate lifetimes.
    \endrst
    */
-  explicit PrintfFormatter(basic_format_args<PrintfFormatter> args)
-    : Base(args) {}
-  
+  explicit printf_context(BasicCStringRef<Char> format_str,
+                          basic_format_args<printf_context> args)
+    : Base(format_str.c_str(), args) {}
+
   /** Formats stored arguments and writes the output to the writer. */
-  FMT_API void format(BasicWriter<Char> &writer,
-                      BasicCStringRef<Char> format_str);
+  FMT_API void format(BasicWriter<Char> &writer);
 };
 
 template <typename Char, typename AF>
-void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
+void printf_context<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
   for (;;) {
     switch (*s++) {
       case '-':
@@ -346,8 +346,8 @@
 }
 
 template <typename Char, typename AF>
-internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
-                                                 unsigned arg_index) {
+internal::Arg printf_context<Char, AF>::get_arg(const Char *s,
+                                                unsigned arg_index) {
   (void)s;
   const char *error = 0;
   internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
@@ -358,7 +358,7 @@
 }
 
 template <typename Char, typename AF>
-unsigned PrintfFormatter<Char, AF>::parse_header(
+unsigned printf_context<Char, AF>::parse_header(
   const Char *&s, FormatSpec &spec) {
   unsigned arg_index = std::numeric_limits<unsigned>::max();
   Char c = *s;
@@ -392,9 +392,8 @@
 }
 
 template <typename Char, typename AF>
-void PrintfFormatter<Char, AF>::format(BasicWriter<Char> &writer,
-                                       BasicCStringRef<Char> format_str) {
-  const Char *start = format_str.c_str();
+void printf_context<Char, AF>::format(BasicWriter<Char> &writer) {
+  const Char *start = this->ptr();
   const Char *s = start;
   while (*s) {
     Char c = *s++;
@@ -495,19 +494,19 @@
 // Formats a value.
 template <typename Char, typename T>
 void format_value(BasicWriter<Char> &w, const T &value,
-                  PrintfFormatter<Char> &f, const Char *&) {
+                  printf_context<Char>& ctx) {
   internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
   w << internal::format_value(buffer, value);
 }
 
 template <typename Char>
 void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format,
-            basic_format_args<PrintfFormatter<Char>> args) {
-  PrintfFormatter<Char>(args).format(w, format);
+            basic_format_args<printf_context<Char>> args) {
+  printf_context<Char>(format, args).format(w);
 }
 
 inline std::string vsprintf(CStringRef format,
-                            basic_format_args<PrintfFormatter<char>> args) {
+                            basic_format_args<printf_context<char>> args) {
   MemoryWriter w;
   printf(w, format, args);
   return w.str();
@@ -524,11 +523,11 @@
 */
 template <typename... Args>
 inline std::string sprintf(CStringRef format_str, const Args & ... args) {
-  return vsprintf(format_str, make_format_args<PrintfFormatter<char>>(args...));
+  return vsprintf(format_str, make_format_args<printf_context<char>>(args...));
 }
 
 inline std::wstring vsprintf(WCStringRef format,
-                             basic_format_args<PrintfFormatter<wchar_t>> args) {
+                             basic_format_args<printf_context<wchar_t>> args) {
   WMemoryWriter w;
   printf(w, format, args);
   return w.str();
@@ -536,12 +535,12 @@
 
 template <typename... Args>
 inline std::wstring sprintf(WCStringRef format_str, const Args & ... args) {
-  auto vargs = make_format_args<PrintfFormatter<wchar_t>>(args...);
+  auto vargs = make_format_args<printf_context<wchar_t>>(args...);
   return vsprintf(format_str, vargs);
 }
 
 FMT_API int vfprintf(std::FILE *f, CStringRef format,
-                     basic_format_args<PrintfFormatter<char>> args);
+                     basic_format_args<printf_context<char>> args);
 
 /**
   \rst
@@ -554,12 +553,12 @@
  */
 template <typename... Args>
 inline int fprintf(std::FILE *f, CStringRef format_str, const Args & ... args) {
-  auto vargs = make_format_args<PrintfFormatter<char>>(args...);
+  auto vargs = make_format_args<printf_context<char>>(args...);
   return vfprintf(f, format_str, vargs);
 }
 
 inline int vprintf(CStringRef format,
-                   basic_format_args<PrintfFormatter<char>> args) {
+                   basic_format_args<printf_context<char>> args) {
   return vfprintf(stdout, format, args);
 }
 
@@ -574,11 +573,11 @@
  */
 template <typename... Args>
 inline int printf(CStringRef format_str, const Args & ... args) {
-  return vprintf(format_str, make_format_args<PrintfFormatter<char>>(args...));
+  return vprintf(format_str, make_format_args<printf_context<char>>(args...));
 }
 
 inline int vfprintf(std::ostream &os, CStringRef format_str,
-                    basic_format_args<PrintfFormatter<char>> args) {
+                    basic_format_args<printf_context<char>> args) {
   MemoryWriter w;
   printf(w, format_str, args);
   internal::write(os, w);
@@ -597,7 +596,7 @@
 template <typename... Args>
 inline int fprintf(std::ostream &os, CStringRef format_str,
                    const Args & ... args) {
-  auto vargs = make_format_args<PrintfFormatter<char>>(args...);
+  auto vargs = make_format_args<printf_context<char>>(args...);
   return vfprintf(os, format_str, vargs);
 }
 }  // namespace fmt
diff --git a/fmt/time.h b/fmt/time.h
index 5b40a93..ad7ab9c 100644
--- a/fmt/time.h
+++ b/fmt/time.h
@@ -15,19 +15,17 @@
 
 namespace fmt {
 
-template <typename ArgFormatter>
-void format_value(Writer &w, const std::tm &tm,
-                  basic_formatter<char, ArgFormatter> &f,
-                  const char *&format_str) {
-  if (*format_str == ':')
-    ++format_str;
-  const char *end = format_str;
+void format_value(Writer &w, const std::tm &tm, format_context &ctx) {
+  const char *&s = ctx.ptr();
+  if (*s == ':')
+    ++s;
+  const char *end = s;
   while (*end && *end != '}')
     ++end;
   if (*end != '}')
     FMT_THROW(format_error("missing '}' in format string"));
   internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
-  format.append(format_str, end + 1);
+  format.append(s, end + 1);
   format[format.size() - 1] = '\0';
   Buffer<char> &buffer = w.buffer();
   std::size_t start = buffer.size();
@@ -48,7 +46,7 @@
     const std::size_t MIN_GROWTH = 10;
     buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
   }
-  format_str = end + 1;
+  s = end;
 }
 }
 
diff --git a/test/custom-formatter-test.cc b/test/custom-formatter-test.cc
index 499e07a..65888b2 100644
--- a/test/custom-formatter-test.cc
+++ b/test/custom-formatter-test.cc
@@ -17,10 +17,9 @@
 class CustomArgFormatter
   : public fmt::BasicArgFormatter<CustomArgFormatter, char> {
  public:
-  CustomArgFormatter(fmt::Writer &w,
-                     fmt::basic_formatter<char, CustomArgFormatter> &f,
-                     fmt::FormatSpec &s, const char *fmt)
-  : fmt::BasicArgFormatter<CustomArgFormatter, char>(w, f, s, fmt) {}
+  CustomArgFormatter(fmt::Writer &w, fmt::basic_format_context<char> &ctx,
+                     fmt::FormatSpec &s)
+  : fmt::BasicArgFormatter<CustomArgFormatter, char>(w, ctx, s) {}
 
   void visit_double(double value) {
     if (round(value * pow(10, spec().precision())) == 0)
@@ -46,10 +45,7 @@
   }
 };
 
-typedef fmt::basic_formatter<char, CustomArgFormatter> CustomFormatter;
-
-std::string custom_vformat(fmt::CStringRef format_str,
-                           fmt::basic_format_args<CustomFormatter> args) {
+std::string custom_vformat(fmt::CStringRef format_str, fmt::format_args args) {
   fmt::MemoryWriter writer;
   // Pass custom argument formatter as a template arg to vformat.
   fmt::vformat<CustomArgFormatter>(writer, format_str, args);
@@ -58,19 +54,19 @@
 
 template <typename... Args>
 std::string custom_format(const char *format_str, const Args & ... args) {
-  auto va = fmt::make_format_args<CustomFormatter>(args...);
+  auto va = fmt::make_format_args<fmt::format_context>(args...);
   return custom_vformat(format_str, va);
 }
 
-typedef fmt::PrintfFormatter<char, CustomPrintfArgFormatter>
+typedef fmt::printf_context<char, CustomPrintfArgFormatter>
   CustomPrintfFormatter;
 
 std::string custom_vsprintf(
     const char* format_str,
     fmt::basic_format_args<CustomPrintfFormatter> args) {
   fmt::MemoryWriter writer;
-  CustomPrintfFormatter formatter(args);
-  formatter.format(writer, format_str);
+  CustomPrintfFormatter formatter(format_str, args);
+  formatter.format(writer);
   return writer.str();
 }
 
diff --git a/test/format-test.cc b/test/format-test.cc
index 4493d00..1e919b7 100644
--- a/test/format-test.cc
+++ b/test/format-test.cc
@@ -1355,8 +1355,7 @@
   EXPECT_EQ("test", format("{0}", CStringRef("test")));
 }
 
-void format_value(fmt::Writer &w, const Date &d, fmt::basic_formatter<char> &f,
-                  const char *) {
+void format_value(fmt::Writer &w, const Date &d, fmt::format_context &) {
   w << d.year() << '-' << d.month() << '-' << d.day();
 }
 
@@ -1369,8 +1368,7 @@
 class Answer {};
 
 template <typename Char>
-void format_value(BasicWriter<Char> &w, Answer, fmt::basic_formatter<Char> &f,
-                  const Char *) {
+void format_value(BasicWriter<Char> &w, Answer, fmt::format_context &) {
   w << "42";
 }
 
@@ -1561,7 +1559,7 @@
 
 template <typename... Args>
 std::string format_message(int id, const char *format, const Args & ... args) {
-  auto va = fmt::make_format_args<fmt::basic_formatter<char>>(args...);
+  auto va = fmt::make_format_args<fmt::format_context>(args...);
   return vformat_message(id, format, va);
 }
 
@@ -1626,9 +1624,8 @@
  public:
   typedef fmt::internal::ArgFormatterBase<MockArgFormatter, char> Base;
 
-  MockArgFormatter(fmt::Writer &w,
-                   fmt::basic_formatter<char, MockArgFormatter> &f,
-                   fmt::FormatSpec &s, const char *)
+  MockArgFormatter(fmt::Writer &w, fmt::format_context &ctx,
+                   fmt::FormatSpec &s)
     : fmt::internal::ArgFormatterBase<MockArgFormatter, char>(w, s) {
     EXPECT_CALL(*this, visit_int(42));
   }
@@ -1636,17 +1633,14 @@
   MOCK_METHOD1(visit_int, void (int value));
 };
 
-typedef fmt::basic_formatter<char, MockArgFormatter> CustomFormatter;
-
-void custom_vformat(fmt::CStringRef format_str,
-                    fmt::basic_format_args<CustomFormatter> args) {
+void custom_vformat(fmt::CStringRef format_str, fmt::format_args args) {
   fmt::MemoryWriter writer;
-  vformat(writer, format_str, args);
+  fmt::vformat<MockArgFormatter>(writer, format_str, args);
 }
 
 template <typename... Args>
 void custom_format(const char *format_str, const Args & ... args) {
-  auto va = fmt::make_format_args<CustomFormatter>(args...);
+  auto va = fmt::make_format_args<fmt::format_context>(args...);
   return custom_vformat(format_str, va);
 }
 
diff --git a/test/ostream-test.cc b/test/ostream-test.cc
index 17c9d07..2d1ace6 100644
--- a/test/ostream-test.cc
+++ b/test/ostream-test.cc
@@ -59,19 +59,17 @@
 }
 
 struct TestArgFormatter : fmt::BasicArgFormatter<TestArgFormatter, char> {
-  TestArgFormatter(fmt::Writer &w,
-                   fmt::basic_formatter<char, TestArgFormatter> &f,
-                   fmt::FormatSpec &s, const char *fmt)
-    : fmt::BasicArgFormatter<TestArgFormatter, char>(w, f, s, fmt) {}
+  TestArgFormatter(fmt::Writer &w, fmt::format_context &ctx,
+                   fmt::FormatSpec &s)
+    : fmt::BasicArgFormatter<TestArgFormatter, char>(w, ctx, s) {}
 };
 
 TEST(OStreamTest, CustomArg) {
   fmt::MemoryWriter writer;
-  typedef fmt::basic_formatter<char, TestArgFormatter> Formatter;
-  Formatter formatter((fmt::basic_format_args<Formatter>()));
+  fmt::format_context ctx("}", fmt::format_args());
   fmt::FormatSpec spec;
-  TestArgFormatter af(writer, formatter, spec, "}");
-  af.visit(fmt::internal::MakeArg<Formatter>(TestEnum()));
+  TestArgFormatter af(writer, ctx, spec);
+  af.visit(fmt::internal::MakeArg<fmt::format_context>(TestEnum()));
   EXPECT_EQ("TestEnum", writer.str());
 }
 
diff --git a/test/util-test.cc b/test/util-test.cc
index 87ad25e..b553427 100644
--- a/test/util-test.cc
+++ b/test/util-test.cc
@@ -65,13 +65,13 @@
 
 template <typename Char>
 void format_value(fmt::BasicWriter<Char> &w, Test,
-                  fmt::basic_formatter<Char> &f, const Char *) {
+                  fmt::basic_format_context<Char> &) {
   w << "test";
 }
 
 template <typename Char, typename T>
 Arg make_arg(const T &value) {
-  typedef fmt::internal::MakeValue< fmt::basic_formatter<Char> > MakeValue;
+  typedef fmt::internal::MakeValue< fmt::basic_format_context<Char> > MakeValue;
   Arg arg = MakeValue(value);
   arg.type = fmt::internal::type<T>();
   return arg;
@@ -567,9 +567,8 @@
   EXPECT_EQ(fmt::internal::Arg::CUSTOM, arg.type);
   EXPECT_EQ(&t, arg.custom.value);
   fmt::MemoryWriter w;
-  fmt::basic_formatter<char> formatter((fmt::format_args()));
-  const char *s = "}";
-  arg.custom.format(&w, &formatter, &t, &s);
+  fmt::format_context ctx("}", fmt::format_args());
+  arg.custom.format(&w, &t, &ctx);
   EXPECT_EQ("test", w.str());
 }
 
@@ -580,21 +579,20 @@
 
 struct CustomFormatter {
   typedef char char_type;
+  bool called;
 };
 
-void format_value(fmt::Writer &, const Test &, CustomFormatter &,
-                  const char *&s) {
-  s = "custom_format";
+void format_value(fmt::Writer &, const Test &, CustomFormatter &ctx) {
+  ctx.called = true;
 }
 
 TEST(UtilTest, MakeValueWithCustomFormatter) {
   ::Test t;
   Arg arg = fmt::internal::MakeValue<CustomFormatter>(t);
-  CustomFormatter formatter;
-  const char *s = "";
+  CustomFormatter ctx = {false};
   fmt::MemoryWriter w;
-  arg.custom.format(&w, &formatter, &t, &s);
-  EXPECT_STREQ("custom_format", s);
+  arg.custom.format(&w, &t, &ctx);
+  EXPECT_TRUE(ctx.called);
 }
 
 struct Result {