/branches/opensp_1_4/sp/lib/MessageFormatter.cxx

# · C++ · 175 lines · 155 code · 17 blank · 3 comment · 34 complexity · 0143dfdadf6f9d75ff9dfd498b61f731 MD5 · raw file

  1. // Copyright (c) 1994, 1995, 1997 James Clark
  2. // See the file COPYING for copying permission.
  3. #ifdef __GNUG__
  4. #pragma implementation
  5. #endif
  6. #include "splib.h"
  7. #include "MessageFormatter.h"
  8. #include "OutputCharStream.h"
  9. #include "rtti.h"
  10. #include "MessageArg.h"
  11. #include "ErrnoMessageArg.h"
  12. #include "SearchResultMessageArg.h"
  13. #include "MessageFormatterMessages.h"
  14. #include <string.h>
  15. #include <errno.h>
  16. #ifdef DECLARE_STRERROR
  17. extern "C" {
  18. char *strerror(int);
  19. }
  20. #endif
  21. #ifdef SP_NAMESPACE
  22. namespace SP_NAMESPACE {
  23. #endif
  24. MessageFormatter::MessageFormatter()
  25. {
  26. }
  27. void MessageFormatter::formatOpenElements(const Vector<OpenElementInfo> &openElementInfo,
  28. OutputCharStream &os)
  29. {
  30. unsigned nOpenElements = openElementInfo.size();
  31. for (unsigned i = 0;; i++) {
  32. if (i > 0
  33. && (i == nOpenElements || openElementInfo[i].included)) {
  34. // describe last match in previous open element
  35. const OpenElementInfo &prevInfo = openElementInfo[i - 1];
  36. if (prevInfo.matchType.size() != 0) {
  37. os << " (" << prevInfo.matchType;
  38. if (prevInfo.matchIndex != 0)
  39. os << '[' << (unsigned long)prevInfo.matchIndex << ']';
  40. os << ')';
  41. }
  42. }
  43. if (i == nOpenElements)
  44. break;
  45. const OpenElementInfo &e = openElementInfo[i];
  46. os << ' ' << e.gi;
  47. if (i > 0 && !e.included) {
  48. unsigned long n = openElementInfo[i - 1].matchIndex;
  49. if (n != 0)
  50. os << '[' << n << ']';
  51. }
  52. }
  53. }
  54. void MessageFormatter::formatMessage(const MessageFragment &frag,
  55. const Vector<CopyOwner<MessageArg> > &args,
  56. OutputCharStream &os, bool noquote)
  57. {
  58. StringC text;
  59. if (!getMessageText(frag, text)) {
  60. formatFragment(MessageFormatterMessages::invalidMessage, os);
  61. return;
  62. }
  63. Builder builder(this, os, noquote || (text.size() == 2));
  64. size_t i = 0;
  65. while (i < text.size()) {
  66. if (text[i] == '%') {
  67. i++;
  68. if (i >= text.size())
  69. break;
  70. if (text[i] >= '1' && text[i] <= '9') {
  71. if (unsigned(text[i] - '1') < args.size())
  72. args[text[i] - '1']->append(builder);
  73. }
  74. else
  75. os.put(text[i]);
  76. i++;
  77. }
  78. else {
  79. os.put(text[i]);
  80. i++;
  81. }
  82. }
  83. }
  84. Boolean MessageFormatter::formatFragment(const MessageFragment &frag,
  85. OutputCharStream &os)
  86. {
  87. StringC text;
  88. if (!getMessageText(frag, text))
  89. return 0;
  90. os << text;
  91. return 1;
  92. }
  93. void MessageFormatter::Builder::appendNumber(unsigned long n)
  94. {
  95. os() << n;
  96. }
  97. void MessageFormatter::Builder::appendOrdinal(unsigned long n)
  98. {
  99. os() << n;
  100. switch (n % 10) {
  101. case 1:
  102. appendFragment(MessageFormatterMessages::ordinal1);
  103. break;
  104. case 2:
  105. appendFragment(MessageFormatterMessages::ordinal2);
  106. break;
  107. case 3:
  108. appendFragment(MessageFormatterMessages::ordinal3);
  109. break;
  110. default:
  111. appendFragment(MessageFormatterMessages::ordinaln);
  112. break;
  113. }
  114. }
  115. void MessageFormatter::Builder::appendChars(const Char *p, size_t n)
  116. {
  117. if (argIsCompleteMessage_)
  118. os().write(p, n);
  119. else
  120. os().put('"').write(p, n).put('"');
  121. }
  122. void MessageFormatter::Builder::appendOther(const OtherMessageArg *p)
  123. {
  124. const ErrnoMessageArg *ea = DYNAMIC_CAST_CONST_PTR(ErrnoMessageArg, p);
  125. if (ea) {
  126. os() << strerror(ea->errnum());
  127. return;
  128. }
  129. const SearchResultMessageArg *sr
  130. = DYNAMIC_CAST_CONST_PTR(SearchResultMessageArg, p);
  131. if (sr) {
  132. for (size_t i = 0; i < sr->nTried(); i++) {
  133. if (i > 0)
  134. os() << ", ";
  135. const StringC &f = sr->filename(i);
  136. appendChars(f.data(), f.size());
  137. switch (sr->errnum(i)) {
  138. default:
  139. os() << " (";
  140. os() << strerror(sr->errnum(i));
  141. os() << ")";
  142. #ifdef ENOENT
  143. case ENOENT:
  144. #endif
  145. break;
  146. }
  147. }
  148. return;
  149. }
  150. appendFragment(MessageFormatterMessages::invalidArgumentType);
  151. }
  152. void MessageFormatter::Builder::appendFragment(const MessageFragment &frag)
  153. {
  154. formatter_->formatFragment(frag, os());
  155. }
  156. #ifdef SP_NAMESPACE
  157. }
  158. #endif