gfx/graphite2/src/XmlTraceLog.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:7a1c4a51f835
1 /* GRAPHITE2 LICENSING
2
3 Copyright 2010, SIL International
4 All rights reserved.
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should also have received a copy of the GNU Lesser General Public
17 License along with this library in the file named "LICENSE".
18 If not, write to the Free Software Foundation, 51 Franklin Street,
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 internet at http://www.fsf.org/licenses/lgpl.html.
21
22 Alternatively, the contents of this file may be used under the terms of the
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 License, as published by the Free Software Foundation, either version 2
25 of the License or (at your option) any later version.
26 */
27
28 #include <cstring>
29 #include <cstdarg>
30 #include "Main.h"
31 #include "XmlTraceLog.h"
32
33
34 using namespace graphite2;
35
36 #ifndef DISABLE_TRACING
37
38 /*static*/ XmlTraceLog XmlTraceLog::sm_NullLog(NULL, NULL, GRLOG_NONE);
39 XmlTraceLog * XmlTraceLog::sLog = &sm_NullLog;
40
41 XmlTraceLog::XmlTraceLog(FILE * file, const char * ns, GrLogMask logMask)
42 : m_file(file), m_depth(0), m_mask(logMask)
43 {
44 if (!m_file) return;
45 int deep = 0;
46 #ifdef ENABLE_DEEP_TRACING
47 deep = 1;
48 #endif
49 fprintf(m_file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<%s xmlns=\"%s\" mask=\"%x\" deep=\"%d\">",
50 xmlTraceLogElements[ElementTopLevel].mName, ns, logMask, deep);
51 m_elementStack[m_depth++] = ElementTopLevel;
52 m_elementEmpty = true;
53 m_inElement = false;
54 m_lastNodeText = false;
55 }
56
57 XmlTraceLog::~XmlTraceLog()
58 {
59 if (m_file && m_file != stdout && m_file != stderr)
60 {
61 assert(m_depth == 1);
62 while (m_depth > 0)
63 {
64 closeElement(m_elementStack[m_depth-1]);
65 }
66 fclose(m_file);
67 m_file = NULL;
68 }
69 }
70
71 void XmlTraceLog::addSingleElement(XmlTraceLogElement eId, const int value)
72 {
73 if (!m_file) return;
74 if (m_inElement)
75 {
76 if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
77 fprintf(m_file, ">");
78 }
79 if (xmlTraceLogElements[eId].mFlags & m_mask)
80 {
81 if (!m_lastNodeText)
82 {
83 fprintf(m_file, "\n");
84 for (size_t i = 0; i < m_depth; i++)
85 {
86 fprintf(m_file, " ");
87 }
88 }
89 fprintf(m_file, "<%s val=\"%d\"/>", xmlTraceLogElements[eId].mName, value);
90 }
91 m_inElement = false;
92 m_lastNodeText = false;
93 }
94
95 void XmlTraceLog::writeElementArray(XmlTraceLogElement eId, XmlTraceLogAttribute aId, int16 values [], size_t length)
96 {
97 if (!m_file) return;
98 if (xmlTraceLogElements[eId].mFlags & m_mask)
99 {
100 if(m_inElement && xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
101 {
102 fprintf(m_file, ">");
103 m_inElement = false;
104 }
105 // line break after 5 columns
106 for (size_t i = 0; i < length; i++)
107 {
108 if (i % 5 == 0)
109 {
110 fprintf(m_file, "\n");
111 for (size_t j = 0; j < m_depth; j++)
112 {
113 fprintf(m_file, " ");
114 }
115 }
116 fprintf(m_file, "<%s index=\"%d\" %s=\"%d\"/>", xmlTraceLogElements[eId].mName, int(i),
117 xmlTraceLogAttributes[aId], (int)values[i]);
118 }
119 }
120 }
121
122 void XmlTraceLog::writeText(const char * utf8)
123 {
124 if (!m_file) return;
125 if (m_inElement)
126 {
127 if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
128 {
129 fprintf(m_file, ">");
130 }
131 m_inElement = false;
132 }
133 if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
134 {
135 escapeIfNeeded(utf8);
136 }
137 m_lastNodeText = true;
138 }
139
140 void XmlTraceLog::writeUnicode(const uint32 code)
141 {
142 if (!m_file) return;
143 if (m_inElement)
144 {
145 if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
146 {
147 fprintf(m_file, ">");
148 }
149 m_inElement = false;
150 }
151 if (xmlTraceLogElements[m_elementStack[m_depth-1]].mFlags & m_mask)
152 {
153 fprintf(m_file, "&#x%02x;", code);
154 }
155 m_lastNodeText = true;
156 }
157
158 void XmlTraceLog::escapeIfNeeded(const char * data)
159 {
160 size_t length = strlen(data);
161 for (size_t i = 0; i < length; i++)
162 {
163 switch (data[i])
164 {
165 case '<':
166 fprintf(m_file, "&lt;");
167 break;
168 case '>':
169 fprintf(m_file, "&gt;");
170 break;
171 case '&':
172 fprintf(m_file, "&amp;");
173 break;
174 case '"':
175 fprintf(m_file, "&#34;");
176 break;
177 default:
178 fprintf(m_file, "%c", data[i]);
179 }
180 }
181 }
182
183 static const int MAX_MSG_LEN = 1024;
184
185 void XmlTraceLog::error(const char * msg, ...)
186 {
187 if (!m_file) return;
188 openElement(ElementError);
189 va_list args;
190 va_start(args, msg);
191 char buffer[MAX_MSG_LEN];
192 #ifndef NDEBUG
193 int len =
194 #endif
195 vsnprintf(buffer, MAX_MSG_LEN, msg, args);
196 assert(len + 1 < MAX_MSG_LEN);
197 writeText(buffer);
198 va_end(args);
199 closeElement(ElementError);
200 }
201
202 void XmlTraceLog::warning(const char * msg, ...)
203 {
204 if (!m_file) return;
205 openElement(ElementWarning);
206 va_list args;
207 va_start(args, msg);
208 char buffer[MAX_MSG_LEN];
209 #ifndef NDEBUG
210 int len =
211 #endif
212 vsnprintf(buffer, MAX_MSG_LEN, msg, args);
213 assert(len + 1 < MAX_MSG_LEN);
214 writeText(buffer);
215 va_end(args);
216 closeElement(ElementWarning);
217 }
218
219 #endif //!DISABLE_TRACING

mercurial