readonly_cstring.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // The simple non-mutable null-terminated string class
  2. // with automatic memory management
  3. //
  4. // Platform: ISO C++ 98/11
  5. // $Id$
  6. //
  7. // (c) __vic 2007
  8. #ifndef __VIC_READONLY_CSTRING_H
  9. #define __VIC_READONLY_CSTRING_H
  10. #include<__vic/defs.h>
  11. #include __VIC_SWAP_HEADER
  12. #include<cstring>
  13. namespace __vic {
  14. //////////////////////////////////////////////////////////////////////////////
  15. class readonly_cstring
  16. {
  17. const char *st;
  18. static const char empty_str[1];
  19. static const char *nonnull(const char *s) { return s ? s : empty_str; }
  20. static const char *dup(const char * , size_t = size_t(-1));
  21. public:
  22. __VIC_CONSTEXPR_FUNC readonly_cstring() : st(nullptr) {}
  23. readonly_cstring(const char *s) : st(dup(s)) {}
  24. readonly_cstring(const char *begin, const char *end) : st(dup(begin, end-begin)) {}
  25. readonly_cstring(const char *s, size_t n) : st(dup(s, n)) {}
  26. readonly_cstring(const readonly_cstring &s) : st(dup(s.st)) {}
  27. ~readonly_cstring() noexcept; // for error.h
  28. readonly_cstring &operator=(const char *s) { return assign(s); }
  29. readonly_cstring &operator=(const readonly_cstring &s) { return assign(s.st); }
  30. readonly_cstring &assign(const char *s) { return assign(s, size_t(-1)); }
  31. readonly_cstring &assign(const char * , size_t );
  32. readonly_cstring &assign(const char *begin, const char *end)
  33. { return assign(begin, end - begin); }
  34. #if __cpp_rvalue_references
  35. readonly_cstring(readonly_cstring &&s) noexcept : st(s.st) { s.st = nullptr; }
  36. readonly_cstring &operator=(readonly_cstring &&s) noexcept
  37. { swap(s); return *this; }
  38. #endif
  39. // allocates internal buffer and returns pointer to it. Use with care!
  40. // specified size must include space for '\0' terminator!
  41. char *reserve(size_t );
  42. friend int compare(const readonly_cstring &s1, const readonly_cstring &s2)
  43. {
  44. return std::strcmp(s1, s2);
  45. }
  46. friend int compare(const readonly_cstring &s1, const char *s2)
  47. {
  48. return std::strcmp(s1, nonnull(s2));
  49. }
  50. friend int compare(const char *s1, const readonly_cstring &s2)
  51. {
  52. return std::strcmp(nonnull(s1), s2);
  53. }
  54. bool empty() const { return !st || *st == '\0'; }
  55. const char *c_str() const { return nonnull(st); }
  56. operator const char*() const { return c_str(); }
  57. void swap(readonly_cstring &s) noexcept { std::swap(st, s.st); }
  58. };
  59. //////////////////////////////////////////////////////////////////////////////
  60. //----------------------------------------------------------------------------
  61. // readonly_cstring compare operators
  62. //----------------------------------------------------------------------------
  63. #define __VIC_DEFINE_OP(OP,T1,T2) \
  64. inline bool operator OP(T1 s1, T2 s2) { return compare(s1, s2) OP 0; }
  65. __VIC_DEFINE_OP(==, const readonly_cstring &, const readonly_cstring &)
  66. __VIC_DEFINE_OP(!=, const readonly_cstring &, const readonly_cstring &)
  67. __VIC_DEFINE_OP(< , const readonly_cstring &, const readonly_cstring &)
  68. __VIC_DEFINE_OP(> , const readonly_cstring &, const readonly_cstring &)
  69. __VIC_DEFINE_OP(<=, const readonly_cstring &, const readonly_cstring &)
  70. __VIC_DEFINE_OP(>=, const readonly_cstring &, const readonly_cstring &)
  71. __VIC_DEFINE_OP(==, const readonly_cstring &, const char *)
  72. __VIC_DEFINE_OP(!=, const readonly_cstring &, const char *)
  73. __VIC_DEFINE_OP(< , const readonly_cstring &, const char *)
  74. __VIC_DEFINE_OP(> , const readonly_cstring &, const char *)
  75. __VIC_DEFINE_OP(<=, const readonly_cstring &, const char *)
  76. __VIC_DEFINE_OP(>=, const readonly_cstring &, const char *)
  77. __VIC_DEFINE_OP(==, const char *, const readonly_cstring &)
  78. __VIC_DEFINE_OP(!=, const char *, const readonly_cstring &)
  79. __VIC_DEFINE_OP(< , const char *, const readonly_cstring &)
  80. __VIC_DEFINE_OP(> , const char *, const readonly_cstring &)
  81. __VIC_DEFINE_OP(<=, const char *, const readonly_cstring &)
  82. __VIC_DEFINE_OP(>=, const char *, const readonly_cstring &)
  83. #undef __VIC_DEFINE_OP
  84. //----------------------------------------------------------------------------
  85. inline void swap(readonly_cstring &s1, readonly_cstring &s2) noexcept
  86. {
  87. s1.swap(s2);
  88. }
  89. //----------------------------------------------------------------------------
  90. } // namespace
  91. #endif // header guard