123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- <chapter xml:id="string_buffer.h">
- <title><tt>__vic/string_buffer.h</tt></title>
- <chapter xml:id="string_buffer">
- <title><tt>string_buffer</tt></title>
- <code-block lang="C++"><![CDATA[
- class string_buffer : public std::string
- {
- public:
- string_buffer();
- explicit string_buffer(size_type n);
- string_buffer(const char *str);
- string_buffer(std::string str);
- string_buffer(string_ref sr);
- string_buffer(const std::string &str, size_type off, size_type n = npos);
- string_buffer(const char *char_buf, size_type n);
- string_buffer(const char *begin, const char *end);
- template<class InputIterator>
- string_buffer(InputIterator begin, InputIterator end);
- string_buffer &operator<<(const char *str);
- string_buffer &operator<<(const std::string &str);
- string_buffer &operator<<(string_ref sr);
- string_buffer &operator<<(char ch);
- string_buffer &operator<<(long long n);
- string_buffer &operator<<(long n);
- string_buffer &operator<<(int n);
- string_buffer &operator<<(short n);
- string_buffer &operator<<(signed char ch);
- string_buffer &operator<<(unsigned long long n);
- string_buffer &operator<<(unsigned long n);
- string_buffer &operator<<(unsigned n);
- string_buffer &operator<<(unsigned short n);
- string_buffer &operator<<(unsigned char ch);
- string_buffer &operator<<(long double n);
- string_buffer &operator<<(double n);
- string_buffer &operator<<(float n);
- string_buffer &operator<<(bool flag);
- string_buffer &operator<<(const void *p);
- string_buffer &operator=(string_ref sr);
- string_buffer &operator+=(string_ref sr);
- string_buffer &assign(string_ref sr);
- string_buffer &append(string_ref sr);
- // improved std::string calls
- string_buffer &assign(const std::string &str,
- size_type off, size_type n = npos);
- string_buffer &append(const std::string &str,
- size_type off, size_type n = npos);
- string_buffer &insert(size_type pos, const std::string &str,
- size_type off, size_type n = npos);
- string_buffer &reserve(size_type n);
- string_buffer &clear();
- // missing container interface of std::string
- reference front();
- reference back();
- const_reference front() const;
- const_reference back() const;
- void pop_back();
- operator const char *() const;
- };
- string_buffer operator+(const string_buffer &s1, const string_buffer &s2);
- string_buffer operator+(const string_buffer &s1, const std::string &s2);
- string_buffer operator+(const std::string &s1, const string_buffer &s2);
- string_buffer operator+(const string_buffer &s1, const char *s2);
- string_buffer operator+(const char *s1, const string_buffer &s2);
- string_buffer operator+(const string_buffer &s, char ch);
- string_buffer operator+(char ch, const string_buffer &s);
- template<class T>
- string_buffer &operator<<(string_buffer &&s, const T &v); // C++11
- using msg = string_buffer;
- ]]></code-block>
- <p>Класс является улучшенным и расширенным <tt>std::string</tt>. Он имеет
- следующие преимущества:</p>
- <list style="numbered">
- <item>Лево-ассоциативная операция конкатенации (<tt><<</tt>),
- позволяющая конструкции, вроде:
- <code-block lang="C++"><![CDATA[
- str << "Error message: " << err_msg << "\n";
- ]]></code-block></item>
- <item>В конструкторе можно зарезервировать место под строку в целях
- оптимизации, чтобы избежать многократного перераспределения буфера, что
- значительно улучшает производительность. Часто имеется возможность оценить
- максимальный размер строки. Но если она вдруг окажется длиннее, то буфер
- автоматически расширится, как и у <tt>std::string</tt>.
- <code-block lang="C++">
- __vic::string_buffer st(4096);
- // Эффект аналогичен
- std::string st;
- st.reserve(4096);
- </code-block></item>
- <item>Оператор <tt><<</tt> воспринимает все фундаментальные типы:
- числа, символы, указатели, <tt>bool</tt>.
- <code-block lang="C++"><![CDATA[
- for(int i=0; i<10; i++)
- str << "i = " << i << '\n';
- ]]></code-block></item>
- <item>Все операции, работающие с <tt>const char *</tt>, корректно воспринимают
- пустой указатель как пустую строку. Реализации <tt>std::string</tt> не
- проверяют указатель на пустоту и пытаются читать по нему в любом случае.
- <code-block lang="C++">
- std::string s1("Str");
- const char *p = nullptr;
- s1.append(p); // Oops.... Null pointer access!
- __vic::string_buffer s2("Str");
- s2.append(p); // Ok. s2 == "Str" still
- s2 = p; // Ok. s2.empty() == true
- </code-block></item>
- <item>Автоматическое преобразование в <tt>const char *</tt> позволяет
- использовать объекты в контекстах, требующих C-строку без явного преобразования.
- <code-block lang="C++">
- std::string fname(...);
- FILE *fp = fopen(fname.c_str(), "r");
- __vic::string_buffer fname(...);
- FILE *fp = fopen(fname, "r");)
- </code-block></item>
- <item>Исправлены нерегулярности в дизайне класса <tt>std::string</tt>. Например,
- класс является полноценным контейнером с доступом к его началу и концу, но у
- него отсутствуют операции <tt>front()</tt> и <tt>back()</tt> в C++98.
- Также класс имеет операцию <tt>push_back()</tt>, но не имеет симметричной
- <tt>pop_back()</tt>.</item>
- </list>
- <p>При всех этих улучшениях, объекты данного типа полностью совместимы по
- структуре с <tt>std::string</tt> и могут передаваться в контексты, требующие
- <tt>std::string</tt>. Никаких дополнительных членов-данных в классе нет.</p>
- <p>Использование инсертера (оператора <tt><<</tt>) данного класса –
- это простейший способ преобразовать число или указатель в строку. Механизм,
- конечно, не такой мощный, как использование <tt>std::ostringstream</tt>,
- например нельзя задать основание системы счисления или форматирование, но зато
- самый простой и эффективный. Для вывода диагностики, к примеру, обычно его
- вполне достаточно.</p>
- <p>Также для данного типа введён синоним <tt>msg</tt>, который удобно
- использовать для конструирования составных сообщений на лету одним
- выражением без введения дополнительных переменных:</p>
- <code-block lang="C++"><![CDATA[
- oresult res = db_open(db_name);
- if(res != 0) throw __vic::exception(
- __vic::msg(64) << "Cannot open DB " << db_name << ". res = " << res
- );
- ]]></code-block>
- <p>Как видно в примере, в конструктор в целях оптимизации передан максимальный
- ожидаемый размер строки.</p>
- <section><title>Члены класса</title>
- <synopsis>
- <prototype>string_buffer()</prototype>
- <p>Создаёт пустую строку.</p>
- <postcondition><tt>empty() == true</tt></postcondition>
- </synopsis>
- <synopsis>
- <prototype>explicit string_buffer(size_type n)</prototype>
- <p>Вызывает <tt>reserve(n)</tt>.</p>
- <postcondition><tt>capacity() >= n</tt></postcondition>
- </synopsis>
- <synopsis>
- <prototype>string_buffer(const char *str)</prototype>
- <prototype>string_buffer(std::string str)</prototype>
- <p>Создаёт копию <tt>str</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer(const std::string &str, size_type off, size_type n = npos)</prototype>
- <p>Создаёт копию подстроки <tt>str</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer(const char *char_buf, size_type n)</prototype>
- <p>Создаёт строку из буфера и его длины.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer(string_ref sr)</prototype>
- <prototype>string_buffer(const char *begin, const char *end)</prototype>
- <prototype>template<class InputIterator>
- string_buffer(InputIterator begin, InputIterator end)</prototype>
- <p>Создаёт строку из диапазона символов.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer &operator<<(const char *str)</prototype>
- <prototype>string_buffer &operator<<(const std::string &str)</prototype>
- <prototype>string_buffer &operator<<(string_ref sr)</prototype>
- <prototype>string_buffer &operator<<(char ch)</prototype>
- <p>Вызывает <tt>std::string::append()</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer &operator<<(long long n)</prototype>
- <prototype>string_buffer &operator<<(long n)</prototype>
- <prototype>string_buffer &operator<<(int n)</prototype>
- <prototype>string_buffer &operator<<(short n)</prototype>
- <prototype>string_buffer &operator<<(signed char ch)</prototype>
- <prototype>string_buffer &operator<<(unsigned long long n)</prototype>
- <prototype>string_buffer &operator<<(unsigned long n)</prototype>
- <prototype>string_buffer &operator<<(unsigned n)</prototype>
- <prototype>string_buffer &operator<<(unsigned short n)</prototype>
- <prototype>string_buffer &operator<<(unsigned char ch)</prototype>
- <prototype>string_buffer &operator<<(long double n)</prototype>
- <prototype>string_buffer &operator<<(double n)</prototype>
- <prototype>string_buffer &operator<<(float n)</prototype>
- <p>Добавляет к строке десятичное представление <tt>n</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer &operator<<(const void *p)</prototype>
- <p>Добавляет к строке значение указателя в формате <tt>std::printf</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer &operator<<(bool flag)</prototype>
- <p>Добавляет к строке <tt>1</tt> (для <tt>true</tt>) или <tt>0</tt> (для
- <tt>false</tt>).</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer &operator=(string_ref sr)</prototype>
- <prototype>string_buffer &operator+=(string_ref sr)</prototype>
- <prototype>string_buffer &assign(string_ref sr)</prototype>
- <prototype>string_buffer &append(string_ref sr)</prototype>
- <p>Операции для <tt>string_ref</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer &reserve(size_type n)</prototype>
- <prototype>string_buffer &clear()</prototype>
- <p>Вызывают одноимённую операцию <tt>std::string</tt> и дополнительно возвращают
- ссылку на себя, что позволяет использовать вызовы в составных выражениях.</p>
- </synopsis>
- <synopsis>
- <prototype>reference front()</prototype>
- <prototype>reference back()</prototype>
- <prototype>const_reference front() const</prototype>
- <prototype>const_reference back() const</prototype>
- <prototype>void pop_back()</prototype>
- <p>Недостающие операции интерфейса <tt>std::string</tt> в C++98.</p>
- </synopsis>
- <synopsis>
- <prototype>operator const char *() const</prototype>
- <p>Вызывает <tt>std::string::c_str()</tt>.</p>
- </synopsis>
- <synopsis>
- <prototype>string_buffer operator+(const string_buffer &s1, const string_buffer &s2)</prototype>
- <prototype>string_buffer operator+(const string_buffer &s1, const std::string &s2)</prototype>
- <prototype>string_buffer operator+(const std::string &s1, const string_buffer &s2)</prototype>
- <prototype>string_buffer operator+(const string_buffer &s1, const char *s2)</prototype>
- <prototype>string_buffer operator+(const char *s1, const string_buffer &s2)</prototype>
- <prototype>string_buffer operator+(const string_buffer &s, char ch)</prototype>
- <prototype>string_buffer operator+(char ch, const string_buffer &s)</prototype>
- <p>Конкатенация строк и символов.</p>
- </synopsis>
- <synopsis>
- <prototype><![CDATA[template<class T>
- string_buffer &operator<<(string_buffer &&s, const T &v)]]> <sign>C++11</sign></prototype>
- <p>Вызывает <tt>operator<<(string_buffer &s, const T &v)</tt>.</p>
- </synopsis>
- </section>
- </chapter>
- </chapter>
|