The Battle for Wesnoth  1.19.10+dev
tstring.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2004 - 2025
3  by Philippe Plantier <ayin@anathas.org>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include <memory>
19 #include <string>
20 #include <map>
21 #include <vector>
22 
23 /**
24  * Helper class for translatable strings.
25  */
27 {
28 public:
29  class walker
30  {
31  public:
32  explicit walker(const t_string_base& string);
33 
34  operator std::string_view() const { return std::string_view(string_.data() + begin_, end_ - begin_); }
35 
36  void next() { begin_ = end_; update(); }
37  bool eos() const { return begin_ == string_.size(); }
38  bool last() const { return end_ == string_.size(); }
39  bool translatable() const { return translatable_; }
40  bool countable() const { return countable_; }
41  int count() const { return count_; }
42  const std::string& textdomain() const { return textdomain_; }
43  std::string::const_iterator begin() const { return string_.begin() + begin_; }
44  std::string::const_iterator end() const { return string_.begin() + end_; }
45  std::string::const_iterator plural_begin() const;
46  std::string::const_iterator plural_end() const;
47 
48  private:
49  void update();
50 
51  const std::string& string_;
52  std::string::size_type begin_;
53  std::string::size_type end_;
54  std::string textdomain_;
56  int count_;
57  };
58 
59  friend class walker;
60 
61  t_string_base();
62 
63  /** Default implementation, but defined out-of-line for efficiency reasons. */
65 
66  /** Default implementation, but defined out-of-line for efficiency reasons. */
68  t_string_base(t_string_base&&) noexcept = default;
69  t_string_base(const std::string& string);
70  t_string_base(std::string&& string);
71  t_string_base(const std::string& string, const std::string& textdomain);
72  t_string_base(const std::string& sing, const std::string& pl, int count, const std::string& textdomain);
73  t_string_base(const char* string);
74 
75  static t_string_base from_serialized(const std::string& string);
76  std::string to_serialized() const;
77 
78  /** Default implementation, but defined out-of-line for efficiency reasons. */
79  t_string_base& operator=(const t_string_base&);
80  t_string_base& operator=(t_string_base&&) noexcept = default;
81  t_string_base& operator=(const std::string&);
82  t_string_base& operator=(const char*);
83 
84  t_string_base operator+(const t_string_base&) const;
85  t_string_base operator+(const std::string&) const;
86  t_string_base operator+(const char*) const;
87 
88  t_string_base& operator+=(const t_string_base&);
89  t_string_base& operator+=(const std::string&);
90  t_string_base& operator+=(const char*);
91 
92  bool operator==(const t_string_base &) const;
93  bool operator==(const std::string &) const;
94  bool operator==(const char* string) const;
95 
96  bool operator!=(const t_string_base &that) const
97  { return !operator==(that); }
98  bool operator!=(const std::string &that) const
99  { return !operator==(that); }
100  bool operator!=(const char *that) const
101  { return !operator==(that); }
102 
103  bool operator<(const t_string_base& string) const;
104 
105  bool empty() const { return value_.empty(); }
106  std::string::size_type size() const { return str().size(); }
107 
108  operator const std::string&() const { return str(); }
109  operator std::string_view() const { return str(); }
110  const std::string& str() const;
111  const char* c_str() const { return str().c_str(); }
112  bool translatable() const { return translatable_; }
113 
114  // Warning: value() may contain platform dependent prefix bytes !
115  // Consider base_str() for a more reliable untranslated string
116  const std::string& value() const { return value_; }
117  std::string base_str() const;
118 
119  std::size_t hash_value() const;
120 
121 private:
122  std::string value_;
123  mutable std::string translated_value_;
124  mutable unsigned translation_timestamp_;
126  static inline std::vector<std::string> id_to_textdomain;
127  static inline std::map<std::string, unsigned int> textdomain_to_id;
128 };
129 
130 inline std::size_t hash_value(const t_string_base& str) { return str.hash_value(); }
131 std::ostream& operator<<(std::ostream&, const t_string_base&);
132 
133 class t_string
134 {
135 public:
138 
139  /** Default implementation, but defined out-of-line for efficiency reasons. */
140  t_string();
141 
142  /** Default implementation, but defined out-of-line for efficiency reasons. */
143  ~t_string();
144 
145  /** Default implementation, but defined out-of-line for efficiency reasons. */
146  t_string(const t_string&);
147 
148  t_string(t_string&&) noexcept = default;
149 
150  /** Default implementation, but defined out-of-line for efficiency reasons. */
151  t_string& operator=(const t_string&);
152 
153  t_string& operator=(t_string&&) noexcept = default;
154 
155  t_string(const base &);
156  t_string(const char *);
157  t_string(const std::string &);
158  t_string(std::string&&);
159  t_string(const std::string &str, const std::string &textdomain);
160  t_string(const std::string& sing, const std::string& pl, int count, const std::string& textdomain);
161 
162  t_string& operator=(const char *o);
163 
164  static t_string from_serialized(const std::string& string) { return t_string(base::from_serialized(string)); }
165  std::string to_serialized() const { return get().to_serialized(); }
166 
167  operator const t_string_base &() const { return get(); }
168 
169  t_string operator+(const t_string& o) const { return get() + o.get(); }
170  t_string operator+(const std::string& o) const { return get() + o; }
171  t_string operator+(const char* o) const { return get() + o; }
172 
173 private:
174  template<typename T>
175  void increase_impl(const T& other)
176  {
177  base * nw = new base(get());
178  *nw += other;
179  val_.reset(nw);
180  }
181 
182 public:
183  t_string& operator+=(const t_string& o) { increase_impl(o.get()); return *this; }
184  t_string& operator+=(const std::string& o) { increase_impl(o); return *this; }
185  t_string& operator+=(const char* o) { increase_impl(o); return *this; }
186 
187  bool operator==(const t_string& o) const { return get() == o.get(); }
188  bool operator==(const std::string& o) const { return get() == o; }
189  bool operator==(const char* o) const { return get() == o; }
190 
191  bool operator!=(const t_string& o) const { return !operator==(o); }
192  bool operator!=(const std::string& o) const { return !operator==(o); }
193  bool operator!=(const char* o) const { return !operator==(o); }
194 
195  bool operator<(const t_string& o) const { return get() < o.get(); }
196 
197  bool empty() const { return get().empty(); }
198  std::string::size_type size() const { return get().size(); }
199 
200  operator const std::string&() const { return get(); }
201  const std::string& str() const { return get().str(); }
202  operator std::string_view() const { return get().str(); }
203  const char* c_str() const { return get().c_str(); }
204  bool translatable() const { return get().translatable(); }
205  const std::string& value() const { return get().value(); }
206  std::string base_str() const { return get().base_str(); }
207 
208  static void add_textdomain(const std::string &name, const std::string &path);
209  static void reset_translations();
210 
211  const t_string_base& get() const { return *val_; }
212  void swap(t_string& other) { val_.swap(other.val_); }
213 
214 private:
215  //never null
216  std::shared_ptr<const t_string_base> val_;
217 };
218 
219 /** Implement non-member swap function for std::swap (calls @ref t_string::swap). */
220 void swap(t_string& lhs, t_string& rhs);
221 
222 inline std::ostream& operator<<(std::ostream& os, const t_string& str) { return os << str.get(); }
223 inline bool operator==(const std::string &a, const t_string& b) { return b == a; }
224 inline bool operator==(const char *a, const t_string& b) { return b == a; }
225 inline bool operator!=(const std::string &a, const t_string& b) { return b != a; }
226 inline bool operator!=(const char *a, const t_string& b) { return b != a; }
227 inline t_string operator+(const std::string &a, const t_string& b) { return t_string(a) + b; }
228 inline t_string operator+(const char *a, const t_string& b) { return t_string(a) + b; }
std::string::const_iterator begin() const
Definition: tstring.hpp:43
bool countable() const
Definition: tstring.hpp:40
std::string::const_iterator end() const
Definition: tstring.hpp:44
std::string::size_type begin_
Definition: tstring.hpp:52
bool last() const
Definition: tstring.hpp:38
std::string::const_iterator plural_end() const
Definition: tstring.cpp:206
const std::string & textdomain() const
Definition: tstring.hpp:42
walker(const t_string_base &string)
Definition: tstring.cpp:56
std::string::const_iterator plural_begin() const
Definition: tstring.cpp:197
int count() const
Definition: tstring.hpp:41
bool translatable() const
Definition: tstring.hpp:39
const std::string & string_
Definition: tstring.hpp:51
std::string::size_type end_
Definition: tstring.hpp:53
std::string textdomain_
Definition: tstring.hpp:54
bool eos() const
Definition: tstring.hpp:37
Helper class for translatable strings.
Definition: tstring.hpp:27
bool operator!=(const char *that) const
Definition: tstring.hpp:100
bool last_untranslatable_
Definition: tstring.hpp:125
std::string::size_type size() const
Definition: tstring.hpp:106
t_string_base(t_string_base &&) noexcept=default
static std::map< std::string, unsigned int > textdomain_to_id
Definition: tstring.hpp:127
bool operator!=(const std::string &that) const
Definition: tstring.hpp:98
std::string translated_value_
Definition: tstring.hpp:123
std::string to_serialized() const
Definition: tstring.cpp:375
bool operator==(const t_string_base &) const
Definition: tstring.cpp:547
bool translatable() const
Definition: tstring.hpp:112
std::string value_
Definition: tstring.hpp:122
std::string base_str() const
Definition: tstring.cpp:365
const std::string & value() const
Definition: tstring.hpp:116
bool empty() const
Definition: tstring.hpp:105
bool operator<(const t_string_base &string) const
Definition: tstring.cpp:562
static std::vector< std::string > id_to_textdomain
Definition: tstring.hpp:126
~t_string_base()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: tstring.cpp:229
unsigned translation_timestamp_
Definition: tstring.hpp:124
bool translatable_
Definition: tstring.hpp:125
std::size_t hash_value() const
Definition: tstring.cpp:47
const std::string & str() const
Definition: tstring.cpp:567
static t_string_base from_serialized(const std::string &string)
Definition: tstring.cpp:340
const char * c_str() const
Definition: tstring.hpp:111
static void reset_translations()
Definition: tstring.cpp:665
static t_string from_serialized(const std::string &string)
Definition: tstring.hpp:164
static void add_textdomain(const std::string &name, const std::string &path)
Definition: tstring.cpp:657
t_string_base::walker walker
Definition: tstring.hpp:137
void swap(t_string &other)
Definition: tstring.hpp:212
const std::string & value() const
Definition: tstring.hpp:205
bool operator==(const t_string &o) const
Definition: tstring.hpp:187
bool translatable() const
Definition: tstring.hpp:204
t_string operator+(const t_string &o) const
Definition: tstring.hpp:169
~t_string()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: tstring.cpp:605
t_string & operator+=(const t_string &o)
Definition: tstring.hpp:183
std::shared_ptr< const t_string_base > val_
Definition: tstring.hpp:216
t_string & operator+=(const std::string &o)
Definition: tstring.hpp:184
bool operator==(const std::string &o) const
Definition: tstring.hpp:188
t_string operator+(const char *o) const
Definition: tstring.hpp:171
bool empty() const
Definition: tstring.hpp:197
t_string(t_string &&) noexcept=default
t_string operator+(const std::string &o) const
Definition: tstring.hpp:170
bool operator==(const char *o) const
Definition: tstring.hpp:189
bool operator!=(const std::string &o) const
Definition: tstring.hpp:192
const std::string & str() const
Definition: tstring.hpp:201
t_string_base base
Definition: tstring.hpp:136
std::string base_str() const
Definition: tstring.hpp:206
std::string to_serialized() const
Definition: tstring.hpp:165
void increase_impl(const T &other)
Definition: tstring.hpp:175
t_string & operator+=(const char *o)
Definition: tstring.hpp:185
const t_string_base & get() const
Definition: tstring.hpp:211
t_string()
Default implementation, but defined out-of-line for efficiency reasons.
Definition: tstring.cpp:600
const char * c_str() const
Definition: tstring.hpp:203
bool operator!=(const char *o) const
Definition: tstring.hpp:193
std::string::size_type size() const
Definition: tstring.hpp:198
bool operator<(const t_string &o) const
Definition: tstring.hpp:195
bool operator!=(const t_string &o) const
Definition: tstring.hpp:191
std::string path
Definition: filesystem.cpp:93
static map_location::direction nw
bool operator==(const std::string &a, const t_string &b)
Definition: tstring.hpp:223
bool operator!=(const std::string &a, const t_string &b)
Definition: tstring.hpp:225
void swap(t_string &lhs, t_string &rhs)
Implement non-member swap function for std::swap (calls t_string::swap).
Definition: tstring.cpp:670
t_string operator+(const std::string &a, const t_string &b)
Definition: tstring.hpp:227
std::size_t hash_value(const t_string_base &str)
Definition: tstring.hpp:130
std::ostream & operator<<(std::ostream &, const t_string_base &)
Definition: tstring.cpp:675
#define b