Home | History | Annotate | Download | only in json
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/json/string_escape.h"
      6 
      7 #include <string>
      8 
      9 #include "base/string_util.h"
     10 
     11 namespace base {
     12 
     13 namespace {
     14 
     15 // Try to escape |c| as a "SingleEscapeCharacter" (\n, etc).  If successful,
     16 // returns true and appends the escape sequence to |dst|.  This isn't required
     17 // by the spec, but it's more readable by humans than the \uXXXX alternatives.
     18 template<typename CHAR>
     19 static bool JsonSingleEscapeChar(const CHAR c, std::string* dst) {
     20   // WARNING: if you add a new case here, you need to update the reader as well.
     21   // Note: \v is in the reader, but not here since the JSON spec doesn't
     22   // allow it.
     23   switch (c) {
     24     case '\b':
     25       dst->append("\\b");
     26       break;
     27     case '\f':
     28       dst->append("\\f");
     29       break;
     30     case '\n':
     31       dst->append("\\n");
     32       break;
     33     case '\r':
     34       dst->append("\\r");
     35       break;
     36     case '\t':
     37       dst->append("\\t");
     38       break;
     39     case '\\':
     40       dst->append("\\\\");
     41       break;
     42     case '"':
     43       dst->append("\\\"");
     44       break;
     45     default:
     46       return false;
     47   }
     48   return true;
     49 }
     50 
     51 template <class STR>
     52 void JsonDoubleQuoteT(const STR& str,
     53                       bool put_in_quotes,
     54                       std::string* dst) {
     55   if (put_in_quotes)
     56     dst->push_back('"');
     57 
     58   for (typename STR::const_iterator it = str.begin(); it != str.end(); ++it) {
     59     typename ToUnsigned<typename STR::value_type>::Unsigned c = *it;
     60     if (!JsonSingleEscapeChar(c, dst)) {
     61       if (c < 32 || c > 126) {
     62         // Technically, we could also pass through c > 126 as UTF8, but this is
     63         // also optional.  It would also be a pain to implement here.
     64         unsigned int as_uint = static_cast<unsigned int>(c);
     65         StringAppendF(dst, "\\u%04X", as_uint);
     66       } else {
     67         unsigned char ascii = static_cast<unsigned char>(*it);
     68         dst->push_back(ascii);
     69       }
     70     }
     71   }
     72 
     73   if (put_in_quotes)
     74     dst->push_back('"');
     75 }
     76 
     77 }  // namespace
     78 
     79 void JsonDoubleQuote(const std::string& str,
     80                      bool put_in_quotes,
     81                      std::string* dst) {
     82   JsonDoubleQuoteT(str, put_in_quotes, dst);
     83 }
     84 
     85 void JsonDoubleQuote(const string16& str,
     86                      bool put_in_quotes,
     87                      std::string* dst) {
     88   JsonDoubleQuoteT(str, put_in_quotes, dst);
     89 }
     90 
     91 }  // namespace base
     92