Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- JsonSupport.h - JSON Output Utilities --------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_CLANG_BASIC_JSONSUPPORT_H
  10. #define LLVM_CLANG_BASIC_JSONSUPPORT_H
  11.  
  12. #include "clang/Basic/LLVM.h"
  13. #include "clang/Basic/SourceManager.h"
  14. #include "llvm/ADT/StringRef.h"
  15. #include "llvm/Support/Path.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. #include <iterator>
  18.  
  19. namespace clang {
  20.  
  21. inline raw_ostream &Indent(raw_ostream &Out, const unsigned int Space,
  22.                            bool IsDot) {
  23.   for (unsigned int I = 0; I < Space * 2; ++I)
  24.     Out << (IsDot ? "&nbsp;" : " ");
  25.   return Out;
  26. }
  27.  
  28. inline std::string JsonFormat(StringRef RawSR, bool AddQuotes) {
  29.   if (RawSR.empty())
  30.     return "null";
  31.  
  32.   // Trim special characters.
  33.   std::string Str = RawSR.trim().str();
  34.   size_t Pos = 0;
  35.  
  36.   // Escape backslashes.
  37.   while (true) {
  38.     Pos = Str.find('\\', Pos);
  39.     if (Pos == std::string::npos)
  40.       break;
  41.  
  42.     // Prevent bad conversions.
  43.     size_t TempPos = (Pos != 0) ? Pos - 1 : 0;
  44.  
  45.     // See whether the current backslash is not escaped.
  46.     if (TempPos != Str.find("\\\\", Pos)) {
  47.       Str.insert(Pos, "\\");
  48.       ++Pos; // As we insert the backslash move plus one.
  49.     }
  50.  
  51.     ++Pos;
  52.   }
  53.  
  54.   // Escape double quotes.
  55.   Pos = 0;
  56.   while (true) {
  57.     Pos = Str.find('\"', Pos);
  58.     if (Pos == std::string::npos)
  59.       break;
  60.  
  61.     // Prevent bad conversions.
  62.     size_t TempPos = (Pos != 0) ? Pos - 1 : 0;
  63.  
  64.     // See whether the current double quote is not escaped.
  65.     if (TempPos != Str.find("\\\"", Pos)) {
  66.       Str.insert(Pos, "\\");
  67.       ++Pos; // As we insert the escape-character move plus one.
  68.     }
  69.  
  70.     ++Pos;
  71.   }
  72.  
  73.   // Remove new-lines.
  74.   llvm::erase_value(Str, '\n');
  75.  
  76.   if (!AddQuotes)
  77.     return Str;
  78.  
  79.   return '\"' + Str + '\"';
  80. }
  81.  
  82. inline void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc,
  83.                                       const SourceManager &SM,
  84.                                       bool AddBraces = true) {
  85.   // Mostly copy-pasted from SourceLocation::print.
  86.   if (!Loc.isValid()) {
  87.     Out << "null";
  88.     return;
  89.   }
  90.  
  91.   if (Loc.isFileID()) {
  92.     PresumedLoc PLoc = SM.getPresumedLoc(Loc);
  93.  
  94.     if (PLoc.isInvalid()) {
  95.       Out << "null";
  96.       return;
  97.     }
  98.     // The macro expansion and spelling pos is identical for file locs.
  99.     if (AddBraces)
  100.       Out << "{ ";
  101.     std::string filename(PLoc.getFilename());
  102.     if (is_style_windows(llvm::sys::path::Style::native)) {
  103.       // Remove forbidden Windows path characters
  104.       llvm::erase_if(filename, [](auto Char) {
  105.         static const char ForbiddenChars[] = "<>*?\"|";
  106.         return llvm::is_contained(ForbiddenChars, Char);
  107.       });
  108.       // Handle windows-specific path delimiters.
  109.       std::replace(filename.begin(), filename.end(), '\\', '/');
  110.     }
  111.     Out << "\"line\": " << PLoc.getLine()
  112.         << ", \"column\": " << PLoc.getColumn()
  113.         << ", \"file\": \"" << filename << "\"";
  114.     if (AddBraces)
  115.       Out << " }";
  116.     return;
  117.   }
  118.  
  119.   // We want 'location: { ..., spelling: { ... }}' but not
  120.   // 'location: { ... }, spelling: { ... }', hence the dance
  121.   // with braces.
  122.   Out << "{ ";
  123.   printSourceLocationAsJson(Out, SM.getExpansionLoc(Loc), SM, false);
  124.   Out << ", \"spelling\": ";
  125.   printSourceLocationAsJson(Out, SM.getSpellingLoc(Loc), SM, true);
  126.   Out << " }";
  127. }
  128. } // namespace clang
  129.  
  130. #endif // LLVM_CLANG_BASIC_JSONSUPPORT_H
  131.