exp.cpp
Go to the documentation of this file.
00001 #include "exp.h"
00002 #include "yaml-cpp-pm/exceptions.h"
00003 #include <sstream>
00004 
00005 namespace YAML_PM
00006 {
00007         namespace Exp
00008         {
00009                 unsigned ParseHex(const std::string& str, const Mark& mark)
00010                 {
00011                         unsigned value = 0;
00012                         for(std::size_t i=0;i<str.size();i++) {
00013                                 char ch = str[i];
00014                                 int digit = 0;
00015                                 if('a' <= ch && ch <= 'f')
00016                                         digit = ch - 'a' + 10;
00017                                 else if('A' <= ch && ch <= 'F')
00018                                         digit = ch - 'A' + 10;
00019                                 else if('0' <= ch && ch <= '9')
00020                                         digit = ch - '0';
00021                                 else
00022                                         throw ParserException(mark, ErrorMsg::INVALID_HEX);
00023 
00024                                 value = (value << 4) + digit;
00025                         }
00026 
00027                         return value;
00028                 }
00029 
00030                 std::string Str(unsigned ch)
00031                 {
00032                         return std::string(1, static_cast<char>(ch));
00033                 }
00034 
00035                 // Escape
00036                 // . Translates the next 'codeLength' characters into a hex number and returns the result.
00037                 // . Throws if it's not actually hex.
00038                 std::string Escape(Stream& in, int codeLength)
00039                 {
00040                         // grab string
00041                         std::string str;
00042                         for(int i=0;i<codeLength;i++)
00043                                 str += in.get();
00044 
00045                         // get the value
00046                         unsigned value = ParseHex(str, in.mark());
00047 
00048                         // legal unicode?
00049                         if((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
00050                                 std::stringstream msg;
00051                                 msg << ErrorMsg::INVALID_UNICODE << value;
00052                                 throw ParserException(in.mark(), msg.str());
00053                         }
00054 
00055                         // now break it up into chars
00056                         if(value <= 0x7F)
00057                                 return Str(value);
00058                         else if(value <= 0x7FF)
00059                                 return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
00060                         else if(value <= 0xFFFF)
00061                                 return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
00062                         else
00063                                 return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
00064                                         Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
00065                 }
00066 
00067                 // Escape
00068                 // . Escapes the sequence starting 'in' (it must begin with a '\' or single quote)
00069                 //   and returns the result.
00070                 // . Throws if it's an unknown escape character.
00071                 std::string Escape(Stream& in)
00072                 {
00073                         // eat slash
00074                         char escape = in.get();
00075 
00076                         // switch on escape character
00077                         char ch = in.get();
00078 
00079                         // first do single quote, since it's easier
00080                         if(escape == '\'' && ch == '\'')
00081                                 return "\'";
00082 
00083                         // now do the slash (we're not gonna check if it's a slash - you better pass one!)
00084                         switch(ch) {
00085                                 case '0': return std::string(1, '\x00');
00086                                 case 'a': return "\x07";
00087                                 case 'b': return "\x08";
00088                                 case 't':
00089                 case '\t': return "\x09";
00090                                 case 'n': return "\x0A";
00091                                 case 'v': return "\x0B";
00092                                 case 'f': return "\x0C";
00093                                 case 'r': return "\x0D";
00094                                 case 'e': return "\x1B";
00095                                 case ' ': return "\x20";
00096                                 case '\"': return "\"";
00097                                 case '\'': return "\'";
00098                                 case '\\': return "\\";
00099                                 case '/': return "/";
00100                                 case 'N': return "\x85";
00101                                 case '_': return "\xA0";
00102                                 case 'L': return "\xE2\x80\xA8";  // LS (#x2028)
00103                                 case 'P': return "\xE2\x80\xA9";  // PS (#x2029)
00104                                 case 'x': return Escape(in, 2);
00105                                 case 'u': return Escape(in, 4);
00106                                 case 'U': return Escape(in, 8);
00107                         }
00108 
00109                         std::stringstream msg;
00110                         throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
00111                 }
00112         }
00113 }


upstream_src
Author(s):
autogenerated on Mon Oct 6 2014 10:27:39