• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "xmlProtoConverter.h"
18 
19 #include <algorithm>
20 
21 using namespace std;
22 using namespace xmlProtoFuzzer;
23 
removeNonAscii(string const & _utf8)24 string ProtoConverter::removeNonAscii(string const& _utf8)
25 {
26 	string asciiStr{_utf8};
27 	asciiStr.erase(remove_if(asciiStr.begin(), asciiStr.end(), [=](char c) -> bool {
28                         return !(std::isalpha(c) || std::isdigit(c));
29                 }), asciiStr.end());
30 	return asciiStr.empty() ? "fuzz" : asciiStr;
31 }
32 
33 
visit(Misc const & _x)34 void ProtoConverter::visit(Misc const& _x)
35 {
36 	switch (_x.misc_oneof_case())
37 	{
38 	case Misc::kComment:
39 		m_output << "<!--" << _x.comment() << "-->\n";
40 		break;
41 	case Misc::kInst:
42 		visit(_x.inst());
43 		break;
44 	case Misc::MISC_ONEOF_NOT_SET:
45 		break;
46 	}
47 }
48 
visit(Prolog const & _x)49 void ProtoConverter::visit(Prolog const& _x)
50 {
51 	visit(_x.decl());
52 	visit(_x.doctype());
53 	for (auto const& misc: _x.misc())
54 		visit(misc);
55 }
56 
visit(KeyValue const & _x)57 void ProtoConverter::visit(KeyValue const& _x)
58 {
59 	if (!KeyValue::XmlNamespace_IsValid(_x.type()))
60 		return;
61 
62 	switch (_x.type())
63 	{
64 	case KeyValue::ATTRIBUTES:
65 		m_output << "xml:attributes=\"" << removeNonAscii(_x.value()) << "\" ";
66 		break;
67 	case KeyValue::BASE:
68 		m_output << "xml:base=\"" << removeNonAscii(_x.value()) << "\" ";
69 		break;
70 	case KeyValue::CATALOG:
71 		m_output << "xml:catalog=\"" << removeNonAscii(_x.value()) << "\" ";
72 		break;
73 	case KeyValue::ID:
74 		m_output << "xml:id=\"" << removeNonAscii(_x.value()) << "\" ";
75 		break;
76 	case KeyValue::LANG:
77 		m_output << "xml:lang=\"" << removeNonAscii(_x.value()) << "\" ";
78 		break;
79 	case KeyValue::LINK:
80 		m_output << "xml:link=\"" << removeNonAscii(_x.value()) << "\" ";
81 		break;
82 	case KeyValue::SPACE:
83 		m_output << "xml:space=\"" << removeNonAscii(_x.value()) << "\" ";
84 		break;
85 	case KeyValue::SPECIAL:
86 		m_output << "xml:special=\"" << removeNonAscii(_x.value()) << "\" ";
87 		break;
88 	case KeyValue::TEST:
89 		m_output << "xml:test=\"" << removeNonAscii(_x.value()) << "\" ";
90 		break;
91 	case KeyValue::FUZZ:
92 		if (_x.ByteSizeLong() % 2)
93 			m_output << "xmlns:" << removeNonAscii(_x.key()) << "=\"" << removeNonAscii(_x.value()) << "\" ";
94 		else
95 			m_output << removeNonAscii(_x.key()) << "=\"" << removeNonAscii(_x.value()) << "\" ";
96 		break;
97 	case KeyValue_XmlNamespace_KeyValue_XmlNamespace_INT_MIN_SENTINEL_DO_NOT_USE_:
98 	case KeyValue_XmlNamespace_KeyValue_XmlNamespace_INT_MAX_SENTINEL_DO_NOT_USE_:
99 		break;
100 	}
101 }
102 
visit(ProcessingInstruction const & _x)103 void ProtoConverter::visit(ProcessingInstruction const& _x)
104 {
105 	m_output << "<?" << removeNonAscii(_x.name()) << " ";
106 	for (auto const& prop: _x.kv())
107 		visit(prop);
108 	m_output << "?>\n";
109 }
110 
visit(Content const & _x)111 void ProtoConverter::visit(Content const& _x)
112 {
113 	switch (_x.content_oneof_case())
114 	{
115 	case Content::kStr:
116 		m_output << _x.str() << "\n";
117 		break;
118 	case Content::kE:
119 		visit(_x.e());
120 		m_output << "\n";
121 		break;
122 	case Content::kC:
123 		visit(_x.c());
124 		m_output << "\n";
125 		break;
126 	case Content::CONTENT_ONEOF_NOT_SET:
127 		break;
128 	}
129 }
130 
visit(ElementDecl const & _x)131 void ProtoConverter::visit(ElementDecl const& _x)
132 {
133 	if (!ElementDecl::ContentSpec_IsValid(_x.spec()))
134 		return;
135 
136 	m_output << "<!ELEMENT " << _x.name() << " ";
137 	switch (_x.spec())
138 	{
139 	case ElementDecl::EMPTY:
140 		m_output << "EMPTY>";
141 		break;
142 	case ElementDecl::ANY:
143 		m_output << "ANY>";
144 		break;
145 	case ElementDecl::FUZZ:
146 		m_output << "FUZZ>";
147 		break;
148 	case ElementDecl::MIXED:
149 		m_output << "(#PCDATA";
150 		for (auto const& pcdata: _x.cdata())
151 			m_output << "|" << pcdata;
152 		m_output << ")";
153 		if (_x.cdata_size() > 0)
154 			m_output << "*";
155 		m_output << ">";
156 		break;
157 	case ElementDecl::CHILDREN:
158 	{
159 		m_output << "(";
160 		string delim = "";
161 		for (auto const& str: _x.cdata()) {
162 			m_output << delim << removeNonAscii(str);
163 			delim = ", ";
164 		}
165 		m_output << ")>";
166 		break;
167 	}
168 	case ElementDecl_ContentSpec_ElementDecl_ContentSpec_INT_MIN_SENTINEL_DO_NOT_USE_:
169 	case ElementDecl_ContentSpec_ElementDecl_ContentSpec_INT_MAX_SENTINEL_DO_NOT_USE_:
170 		break;
171 	}
172 }
173 
visit(AttValue const & _x)174 void ProtoConverter::visit(AttValue const& _x)
175 {
176 	if (!isValid(_x))
177 		return;
178 
179 	m_output << "\"";
180 	string prefix;
181 	switch (_x.type())
182 	{
183 	case AttValue::ENTITY:
184 		prefix = "&";
185 		break;
186 	case AttValue::CHAR:
187 		if (_x.ByteSizeLong() % 2)
188 			prefix = "&#";
189 		else
190 			// TODO: Value that follows this must be a
191 			// sequence of hex digits.
192 			prefix = "&#x";
193 		break;
194 	case AttValue::FUZZ:
195 		prefix = "fuzz";
196 		break;
197 	case AttValue_Type_AttValue_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
198 	case AttValue_Type_AttValue_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
199 		break;
200 	}
201 	for (auto const& name: _x.value())
202 		m_output << prefix << removeNonAscii(name) << ";";
203 	m_output << "\"";
204 }
205 
visit(DefaultDecl const & _x)206 void ProtoConverter::visit(DefaultDecl const& _x)
207 {
208 	if (!isValid(_x))
209 		return;
210 
211 	switch (_x.type())
212 	{
213 	case DefaultDecl::REQUIRED:
214 		m_output << "#REQUIRED";
215 		break;
216 	case DefaultDecl::IMPLIED:
217 		m_output << "#IMPLIED";
218 		break;
219 	case DefaultDecl::FIXED:
220 		m_output << "#FIXED ";
221 		visit(_x.att());
222 		break;
223 	case DefaultDecl::FUZZ:
224 		m_output << "#FUZZ";
225 		break;
226 	case DefaultDecl_Type_DefaultDecl_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
227 	case DefaultDecl_Type_DefaultDecl_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
228 		break;
229 	}
230 }
231 
visit(AttDef const & _x)232 void ProtoConverter::visit(AttDef const& _x)
233 {
234 	if (!isValid(_x))
235 		return;
236 
237 	m_output << " " << removeNonAscii(_x.name()) << " ";
238 	switch (_x.type())
239 	{
240 	case AttDef::CDATA:
241 		m_output << "CDATA ";
242 		break;
243 	case AttDef::ID:
244 		m_output << "ID ";
245 		break;
246 	case AttDef::IDREF:
247 		m_output << "IDREF ";
248 		break;
249 	case AttDef::IDREFS:
250 		m_output << "IDREFS ";
251 		break;
252 	case AttDef::ENTITY:
253 		m_output << "ENTITY ";
254 		break;
255 	case AttDef::ENTITIES:
256 		m_output << "ENTITIES ";
257 		break;
258 	case AttDef::NMTOKEN:
259 		m_output << "NMTOKEN ";
260 		break;
261 	case AttDef::NMTOKENS:
262 		m_output << "NMTOKENS ";
263 		break;
264 	case AttDef::FUZZ:
265 		m_output << "FUZZ ";
266 		break;
267 	case AttDef_Type_AttDef_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
268 	case AttDef_Type_AttDef_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
269 		break;
270 	}
271 	visit(_x.def());
272 }
273 
visit(AttListDecl const & _x)274 void ProtoConverter::visit(AttListDecl const& _x)
275 {
276 	m_output << "<!ATTLIST " << removeNonAscii(_x.name());
277 	for (auto const& att: _x.attdefs())
278 		visit(att);
279 	m_output << ">";
280 }
281 
visit(NotationDecl const & _x)282 void ProtoConverter::visit(NotationDecl const& _x)
283 {
284 	m_output << "<!NOTATION " << removeNonAscii(_x.name()) << " ";
285 	switch (_x.notation_oneof_case())
286 	{
287 	case NotationDecl::kExt:
288 		visit(_x.ext());
289 		break;
290 	case NotationDecl::kPub:
291 		m_output << "PUBLIC " << _x.pub();
292 		break;
293 	case NotationDecl::kFuzz:
294 		m_output << "FUZZ " << _x.fuzz();
295 		break;
296 	case NotationDecl::NOTATION_ONEOF_NOT_SET:
297 		break;
298 	}
299 	m_output << ">";
300 }
301 
visit(NDataDecl const & _x)302 void ProtoConverter::visit(NDataDecl const& _x)
303 {
304 	m_output << " NDATA " << _x.name();
305 }
306 
visit(EntityDef const & _x)307 void ProtoConverter::visit(EntityDef const& _x)
308 {
309 	switch (_x.entity_oneof_case())
310 	{
311 	case EntityDef::kExt:
312 		visit(_x.ext());
313 		if (_x.ByteSizeLong() % 2)
314 			visit(_x.ndata());
315 		break;
316 	case EntityDef::kVal:
317 		visit(_x.val());
318 		break;
319 	case EntityDef::ENTITY_ONEOF_NOT_SET:
320 		break;
321 	}
322 }
323 
visit(PEDef const & _x)324 void ProtoConverter::visit(PEDef const& _x)
325 {
326 	switch (_x.pedef_oneof_case())
327 	{
328 	case PEDef::kVal:
329 		visit(_x.val());
330 		break;
331 	case PEDef::kId:
332 		visit(_x.id());
333 		break;
334 	case PEDef::PEDEF_ONEOF_NOT_SET:
335 		break;
336 	}
337 }
338 
visit(EntityValue const & _x)339 void ProtoConverter::visit(EntityValue const& _x)
340 {
341 	if (!isValid(_x))
342 		return;
343 
344 	m_output << "\"";
345 	string prefix;
346 	switch (_x.type())
347 	{
348 	case EntityValue::ENTITY:
349 		prefix = "&";
350 		break;
351 	case EntityValue::CHAR:
352 		if (_x.ByteSizeLong() % 2)
353 			prefix = "&#";
354 		else
355 			prefix = "&#x";
356 		break;
357 	case EntityValue::PEREF:
358 		prefix = "%";
359 		break;
360 	case EntityValue::FUZZ:
361 		prefix = "fuzz";
362 		break;
363 	case EntityValue_Type_EntityValue_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
364 	case EntityValue_Type_EntityValue_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
365 		break;
366 	}
367 	for (auto const& ref: _x.name())
368 		m_output << prefix << ref << ";";
369 	m_output << "\"";
370 }
371 
visit(EntityDecl const & _x)372 void ProtoConverter::visit(EntityDecl const& _x)
373 {
374 	if (!isValid(_x))
375 		return;
376 
377 	m_output << "<!ENTITY ";
378 	switch (_x.type())
379 	{
380 	case EntityDecl::GEDECL:
381 		m_output << _x.name() << " ";
382 		visit(_x.ent());
383 		break;
384 	case EntityDecl::PEDECL:
385 		m_output << "% " << _x.name() << " ";
386 		visit(_x.pedef());
387 		break;
388 	case EntityDecl_Type_EntityDecl_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
389 	case EntityDecl_Type_EntityDecl_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
390 		break;
391 	}
392 	m_output << ">";
393 }
394 
visit(ConditionalSect const & _x)395 void ProtoConverter::visit(ConditionalSect const& _x)
396 {
397 	if (!isValid(_x))
398 		return;
399 
400 	switch (_x.type())
401 	{
402 	case ConditionalSect::INCLUDE:
403 		m_output << "<![ INCLUDE [";
404 		visit(_x.ext());
405 		m_output << "]]>";
406 		break;
407 	case ConditionalSect::IGNORE:
408 		m_output << "<![ IGNORE [";
409 		for (auto const& str: _x.ignores())
410 			m_output << "<![" << removeNonAscii(str) << "]]>";
411 		m_output << "]]>";
412 		break;
413 	case ConditionalSect::FUZZ:
414 		m_output << "<![ FUZZ [";
415 		visit(_x.ext());
416 		m_output << "]]>";
417 		break;
418 	case ConditionalSect_Type_ConditionalSect_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
419 	case ConditionalSect_Type_ConditionalSect_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
420 		break;
421 	}
422 }
423 
424 
visit(OneExtSubsetDecl const & _x)425 void ProtoConverter::visit(OneExtSubsetDecl const& _x)
426 {
427 	switch (_x.extsubset_oneof_case())
428 	{
429 	case OneExtSubsetDecl::kM:
430 		visit(_x.m());
431 		break;
432 	case OneExtSubsetDecl::kC:
433 		visit(_x.c());
434 		break;
435 	case OneExtSubsetDecl::EXTSUBSET_ONEOF_NOT_SET:
436 		break;
437 	}
438 }
439 
440 
visit(ExtSubsetDecl const & _x)441 void ProtoConverter::visit(ExtSubsetDecl const& _x)
442 {
443 	for (auto const& decl: _x.decls())
444 		visit(decl);
445 }
446 
visit(CData const & _x)447 void ProtoConverter::visit(CData const& _x)
448 {
449 	m_output << "<![CDATA[" << removeNonAscii(_x.data()) << "]]>";
450 }
451 
visit(MarkupDecl const & _x)452 void ProtoConverter::visit(MarkupDecl const& _x)
453 {
454 	switch (_x.markup_oneof_case())
455 	{
456 	case MarkupDecl::kE:
457 		visit(_x.e());
458 		break;
459 	case MarkupDecl::kA:
460 		visit(_x.a());
461 		break;
462 	case MarkupDecl::kN:
463 		visit(_x.n());
464 		break;
465 	case MarkupDecl::kM:
466 		visit(_x.m());
467 		break;
468 	case MarkupDecl::kEntity:
469 		visit(_x.entity());
470 		break;
471 	case MarkupDecl::kExt:
472 		visit(_x.ext());
473 		break;
474 	case MarkupDecl::MARKUP_ONEOF_NOT_SET:
475 		break;
476 	}
477 }
478 
479 /// Returns predefined element from an Element_Id enum
480 /// @param _x is an enum that holds the desired type of predefined value
481 /// @param _prop is a string that holds the value of the desired type
482 /// @return string holding the predefined value of the form
483 /// name attribute=\"value\"
getPredefined(Element_Id _x,string const & _prop)484 string ProtoConverter::getPredefined(Element_Id _x, string const& _prop)
485 {
486 	string output{};
487 	switch (_x)
488 	{
489 	case Element::XIINCLUDE:
490 	case Element::XIFALLBACK:
491 	case Element::XIHREF:
492 		output = "xi:include href=\"fuzz.xml\"";
493 	case Element::XIPARSE:
494 		output = "xi:include parse=\"xml\"";
495 	case Element::XIXPOINTER:
496 		output = "xi:include xpointer=\"" + removeNonAscii(_prop) + "\"";
497 	case Element::XIENCODING:
498 		output = "xi:include encoding=\"" + removeNonAscii(_prop) + "\"";
499 	case Element::XIACCEPT:
500 		output = "xi:include accept=\"" + removeNonAscii(_prop) + "\"";
501 	case Element::XIACCEPTLANG:
502 		output = "xi:include accept-language=\"" + removeNonAscii(_prop) + "\"";
503 	case Element_Id_Element_Id_INT_MIN_SENTINEL_DO_NOT_USE_:
504 	case Element_Id_Element_Id_INT_MAX_SENTINEL_DO_NOT_USE_:
505 		output = "xi:fuzz xifuzz=\"fuzz\"";
506 	}
507 	return output;
508 }
509 
510 /// Returns uri string for a given Element_Id type
getUri(Element_Id _x)511 string ProtoConverter::getUri(Element_Id _x)
512 {
513 	if (!Element::Id_IsValid(_x))
514 		return s_XInclude;
515 
516 	switch (_x)
517 	{
518 	case Element::XIINCLUDE:
519 	case Element::XIFALLBACK:
520 	case Element::XIHREF:
521 	case Element::XIPARSE:
522 	case Element::XIXPOINTER:
523 	case Element::XIENCODING:
524 	case Element::XIACCEPT:
525 	case Element::XIACCEPTLANG:
526 	case Element_Id_Element_Id_INT_MIN_SENTINEL_DO_NOT_USE_:
527 	case Element_Id_Element_Id_INT_MAX_SENTINEL_DO_NOT_USE_:
528 		return s_XInclude;
529 	}
530 }
531 
visit(Element const & _x)532 void ProtoConverter::visit(Element const& _x)
533 {
534 	if (!isValid(_x))
535 		return;
536 
537 	// Predefined child node
538 	string child = {};
539 	// Predefined uri for child node
540 	string pUri = {};
541 	// Element name
542 	string name = removeNonAscii(_x.name());
543 
544 	switch (_x.type())
545 	{
546 	case Element::PREDEFINED:
547 		child = getPredefined(_x.id(), _x.childprop());
548 		pUri = getUri(_x.id());
549 		break;
550 	case Element::FUZZ:
551 	case Element_Type_Element_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
552 	case Element_Type_Element_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
553 		break;
554 	}
555 
556 	// <name k1=v1 k2=v2 k3=v3>
557 	// <content>
558 	// </name>
559 
560 	// Start name tag: Must be Ascii?
561 	m_output << "<" << name << " ";
562 
563 	// Add uri to name tag
564 	if (!pUri.empty())
565 		m_output << pUri << " ";
566 	for (auto const& prop: _x.kv())
567 		visit(prop);
568 	m_output << ">\n";
569 
570 	// Add attribute
571 	if (!child.empty())
572 		m_output << "<" << child << "/>\n";
573 
574 	// Add content
575 	visit(_x.content());
576 
577 	// Close name tag
578 	m_output << "</" << name << ">\n";
579 }
580 
visit(ExternalId const & _x)581 void ProtoConverter::visit(ExternalId const& _x)
582 {
583 	if (!isValid(_x))
584 		return;
585 
586 	switch (_x.type())
587 	{
588 	case ExternalId::SYSTEM:
589 		m_output << "SYSTEM " << "\"" << removeNonAscii(_x.system()) << "\"";
590 		break;
591 	case ExternalId::PUBLIC:
592 		m_output << "PUBLIC " << "\"" << removeNonAscii(_x.pub()) << "\""
593 			<< " " << "\"" << removeNonAscii(_x.system()) << "\"";
594 		break;
595 	case ExternalId::FUZZ:
596 		m_output << "FUZZ " << "\"" << removeNonAscii(_x.pub()) << "\"";
597 		break;
598 	case ExternalId_Type_ExternalId_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
599 	case ExternalId_Type_ExternalId_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
600 		break;
601 	}
602 }
603 
visit(DocTypeDecl const & _x)604 void ProtoConverter::visit(DocTypeDecl const& _x)
605 {
606 	m_output << "<!DOCTYPE " << removeNonAscii(_x.name()) << " ";
607 	visit(_x.ext());
608 	m_output << "[";
609 	for (auto const& m: _x.mdecl())
610 		visit(m);
611 	m_output << "]";
612 	m_output << ">\n";
613 }
614 
visit(VersionNum const & _x)615 void ProtoConverter::visit(VersionNum const& _x)
616 {
617 	if (!isValid(_x))
618 		return;
619 
620 	switch (_x.type())
621 	{
622 	case VersionNum::STANDARD:
623 		m_output << "\"1.0\"";
624 		break;
625 	case VersionNum::FUZZ:
626 	case VersionNum_Type_VersionNum_Type_INT_MIN_SENTINEL_DO_NOT_USE_:
627 	case VersionNum_Type_VersionNum_Type_INT_MAX_SENTINEL_DO_NOT_USE_:
628 		m_output << "\"" << _x.major() << "." << _x.minor() << "\"";
629 		break;
630 	}
631 }
632 
visit(Encodings const & _x)633 void ProtoConverter::visit(Encodings const& _x)
634 {
635 	if (!Encodings::Enc_IsValid(_x.name()))
636 		return;
637 
638 	m_output << " encoding=\"";
639 	switch (_x.name())
640 	{
641 	case Encodings::BIG5:
642 		m_output << "BIG5";
643 		break;
644 	case Encodings::EUCJP:
645 		m_output << "EUC-JP";
646 		break;
647 	case Encodings::EUCKR:
648 		m_output << "EUC-KR";
649 		break;
650 	case Encodings::GB18030:
651 		m_output << "GB18030";
652 		break;
653 	case Encodings::ISO2022JP:
654 		m_output << "ISO-2022-JP";
655 		break;
656 	case Encodings::ISO2022KR:
657 		m_output << "ISO-2022-KR";
658 		break;
659 	case Encodings::ISO88591:
660 		m_output << "ISO-8859-1";
661 		break;
662 	case Encodings::ISO88592:
663 		m_output << "ISO-8859-2";
664 		break;
665 	case Encodings::ISO88593:
666 		m_output << "ISO-8859-3";
667 		break;
668 	case Encodings::ISO88594:
669 		m_output << "ISO-8859-4";
670 		break;
671 	case Encodings::ISO88595:
672 		m_output << "ISO-8859-5";
673 		break;
674 	case Encodings::ISO88596:
675 		m_output << "ISO-8859-6";
676 		break;
677 	case Encodings::ISO88597:
678 		m_output << "ISO-8859-7";
679 		break;
680 	case Encodings::ISO88598:
681 		m_output << "ISO-8859-8";
682 		break;
683 	case Encodings::ISO88599:
684 		m_output << "ISO-8859-9";
685 		break;
686 	case Encodings::SHIFTJIS:
687 		m_output << "SHIFT_JIS";
688 		break;
689 	case Encodings::TIS620:
690 		m_output << "TIS-620";
691 		break;
692 	case Encodings::USASCII:
693 		m_output << "US-ASCII";
694 		break;
695 	case Encodings::UTF8:
696 		m_output << "UTF-8";
697 		break;
698 	case Encodings::UTF16:
699 		m_output << "UTF-16";
700 		break;
701 	case Encodings::UTF16BE:
702 		m_output << "UTF-16BE";
703 		break;
704 	case Encodings::UTF16LE:
705 		m_output << "UTF-16LE";
706 		break;
707 	case Encodings::WINDOWS31J:
708 		m_output << "WINDOWS-31J";
709 		break;
710 	case Encodings::WINDOWS1255:
711 		m_output << "WINDOWS-1255";
712 		break;
713 	case Encodings::WINDOWS1256:
714 		m_output << "WINDOWS-1256";
715 		break;
716 	case Encodings::FUZZ:
717 		m_output << removeNonAscii(_x.fuzz());
718 		break;
719 	case Encodings_Enc_Encodings_Enc_INT_MIN_SENTINEL_DO_NOT_USE_:
720 	case Encodings_Enc_Encodings_Enc_INT_MAX_SENTINEL_DO_NOT_USE_:
721 		break;
722 	}
723 	m_output << "\"";
724 }
725 
visit(XmlDeclaration const & _x)726 void ProtoConverter::visit(XmlDeclaration const& _x)
727 {
728 	m_output << R"(<?xml version=)";
729 	visit(_x.ver());
730 	visit(_x.enc());
731 	switch (_x.standalone())
732 	{
733 	case XmlDeclaration::YES:
734 		m_output << " standalone=\'yes\'";
735 		break;
736 	case XmlDeclaration::NO:
737 		m_output << " standalone=\'no\'";
738 		break;
739 	case XmlDeclaration_Standalone_XmlDeclaration_Standalone_INT_MIN_SENTINEL_DO_NOT_USE_:
740 	case XmlDeclaration_Standalone_XmlDeclaration_Standalone_INT_MAX_SENTINEL_DO_NOT_USE_:
741 	default:
742 		break;
743 	}
744 	m_output << "?>\n";
745 }
746 
visit(XmlDocument const & _x)747 void ProtoConverter::visit(XmlDocument const& _x)
748 {
749 	visit(_x.p());
750 	for (auto const& element: _x.e())
751 		visit(element);
752 }
753 
protoToString(XmlDocument const & _x)754 string ProtoConverter::protoToString(XmlDocument const& _x)
755 {
756 	visit(_x);
757 	return m_output.str();
758 }
759