cmXMLSafe.cxx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmXMLSafe.h"
  11. #include <cmsys/ios/iostream>
  12. #include <cmsys/ios/sstream>
  13. #include <string.h>
  14. #include <stdio.h>
  15. //----------------------------------------------------------------------------
  16. cmXMLSafe::cmXMLSafe(const char* s):
  17. Data(s),
  18. Size(static_cast<unsigned long>(strlen(s))),
  19. DoQuotes(true)
  20. {
  21. }
  22. //----------------------------------------------------------------------------
  23. cmXMLSafe::cmXMLSafe(cmsys_stl::string const& s):
  24. Data(s.c_str()),
  25. Size(static_cast<unsigned long>(s.length())),
  26. DoQuotes(true)
  27. {
  28. }
  29. //----------------------------------------------------------------------------
  30. cmXMLSafe& cmXMLSafe::Quotes(bool b)
  31. {
  32. this->DoQuotes = b;
  33. return *this;
  34. }
  35. //----------------------------------------------------------------------------
  36. cmsys_stl::string cmXMLSafe::str()
  37. {
  38. cmsys_ios::ostringstream ss;
  39. ss << *this;
  40. return ss.str();
  41. }
  42. //----------------------------------------------------------------------------
  43. cmsys_ios::ostream& operator<<(cmsys_ios::ostream& os, cmXMLSafe const& self)
  44. {
  45. char const* first = self.Data;
  46. char const* last = self.Data + self.Size;
  47. for(char const* ci = first; ci != last; ++ci)
  48. {
  49. unsigned char c = static_cast<unsigned char>(*ci);
  50. switch(c)
  51. {
  52. case '&': os << "&amp;"; break;
  53. case '<': os << "&lt;"; break;
  54. case '>': os << "&gt;"; break;
  55. case '"': os << (self.DoQuotes? "&quot;" : "\""); break;
  56. case '\'': os << (self.DoQuotes? "&apos;" : "'"); break;
  57. case '\t': os << "\t"; break;
  58. case '\n': os << "\n"; break;
  59. case '\r': break; // Ignore CR
  60. default:
  61. if(c >= 0x20 && c <= 0x7f)
  62. {
  63. os.put(static_cast<char>(c));
  64. }
  65. else
  66. {
  67. // TODO: More complete treatment of program output character
  68. // encoding. Instead of escaping these bytes, we should
  69. // handle the current locale and its encoding.
  70. char buf[16];
  71. // http://www.w3.org/TR/REC-xml/#NT-Char
  72. if(c >= 0x80)
  73. {
  74. sprintf(buf, "&#x%hx;", static_cast<unsigned short>(c));
  75. }
  76. else
  77. {
  78. // We cannot use "&#x%hx;" here because this value is not
  79. // valid in XML. Instead use a human-readable hex value.
  80. sprintf(buf, "&lt;0x%hx&gt;", static_cast<unsigned short>(c));
  81. }
  82. os << buf;
  83. }
  84. break;
  85. }
  86. }
  87. return os;
  88. }