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
00036
00037
00038 std::string Escape(Stream& in, int codeLength)
00039 {
00040
00041 std::string str;
00042 for(int i=0;i<codeLength;i++)
00043 str += in.get();
00044
00045
00046 unsigned value = ParseHex(str, in.mark());
00047
00048
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
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
00068
00069
00070
00071 std::string Escape(Stream& in)
00072 {
00073
00074 char escape = in.get();
00075
00076
00077 char ch = in.get();
00078
00079
00080 if(escape == '\'' && ch == '\'')
00081 return "\'";
00082
00083
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";
00103 case 'P': return "\xE2\x80\xA9";
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 }