OpenImageIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ustring.h
Go to the documentation of this file.
1 /*
2  Copyright 2008 Larry Gritz and the other authors and contributors.
3  All Rights Reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  * Neither the name of the software's owners nor the names of its
14  contributors may be used to endorse or promote products derived from
15  this software without specific prior written permission.
16  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28  (This is the Modified BSD License)
29 */
30 
31 
35 
36 
119 
120 
121 #ifndef OPENIMAGEIO_USTRING_H
122 #define OPENIMAGEIO_USTRING_H
123 
124 #if defined(_MSC_VER)
125 // Ignore warnings about DLL exported classes with member variables that are template classes.
126 // This happens with the std::string empty_std_string static member variable of ustring below.
127 // Also remove a warning about the strncpy function not being safe and deprecated in MSVC.
128 // There is no equivalent safe and portable function and trying to fix this is more trouble than
129 // its worth. (see http://stackoverflow.com/questions/858252/alternatives-to-ms-strncpy-s)
130 # pragma warning (disable : 4251 4996)
131 #endif
132 
133 #include <string>
134 #include <iostream>
135 #include <cstring>
136 #include "export.h"
137 #include "strutil.h"
138 #include "dassert.h"
139 #include "version.h"
140 
141 #ifndef NULL
142 #define NULL 0
143 #endif
144 
145 OIIO_NAMESPACE_ENTER
146 {
147 
148 class OIIO_API ustring {
149 public:
150  typedef char value_type;
151  typedef value_type * pointer;
152  typedef value_type & reference;
153  typedef const value_type & const_reference;
154  typedef size_t size_type;
155  static const size_type npos = static_cast<size_type>(-1);
156  typedef std::string::const_iterator const_iterator;
157  typedef std::string::const_reverse_iterator const_reverse_iterator;
158 
161  ustring (void) : m_chars(NULL) { }
162 
165  explicit ustring (const char *str) {
166  m_chars = str ? make_unique(str) : NULL;
167  }
168 
171  ustring (const char *str, size_type pos, size_type n)
172  : m_chars (make_unique(std::string(str,pos,n).c_str())) { }
173 
176  ustring (const char *str, size_type n)
177  : m_chars (make_unique(std::string(str,n).c_str())) { }
178 
181  ustring (size_type n, char c)
182  : m_chars (make_unique(std::string(n,c).c_str())) { }
183 
186  explicit ustring (const std::string &str) { *this = ustring(str.c_str()); }
187 
190  ustring (const std::string &str, size_type pos, size_type n=npos)
191  : m_chars (make_unique(std::string(str, pos, n).c_str())) { }
192 
195  ustring (const ustring &str) : m_chars(str.m_chars) { }
196 
199  ustring (const ustring &str, size_type pos, size_type n=npos)
200  : m_chars (make_unique(std::string(str.c_str(),pos,n).c_str())) { }
201 
204  ~ustring () { }
205 
208  const ustring & assign (const ustring &str) {
209  m_chars = str.m_chars;
210  return *this;
211  }
212 
215  const ustring & assign (const ustring &str, size_type pos, size_type n=npos)
216  { *this = ustring(str,pos,n); return *this; }
217 
220  const ustring & assign (const std::string &str) {
221  assign (str.c_str());
222  return *this;
223  }
224 
227  const ustring & assign (const std::string &str, size_type pos,
228  size_type n=npos)
229  { *this = ustring(str,pos,n); return *this; }
230 
233  const ustring & assign (const char *str) {
234  m_chars = str ? make_unique(str) : NULL;
235  return *this;
236  }
237 
240  const ustring & assign (const char *str, size_type n)
241  { *this = ustring(str,n); return *this; }
242 
245  const ustring & assign (size_type n, char c)
246  { *this = ustring(n,c); return *this; }
247 
250  const ustring & operator= (const ustring &str) { return assign(str); }
251 
254  const ustring & operator= (const char *str) { return assign(str); }
255 
258  const ustring & operator= (const std::string &str) { return assign(str); }
259 
262  const ustring & operator= (char c) {
263  char s[2];
264  s[0] = c; s[1] = 0;
265  *this = ustring (s);
266  return *this;
267  }
268 
271  const char *c_str () const {
272  return m_chars;
273  }
274 
277  const char *data () const { return c_str(); }
278 
281  const std::string & string () const {
282  if (m_chars) {
283  const TableRep *rep = (const TableRep *)m_chars - 1;
284  return rep->str;
285  }
286  else return empty_std_string;
287  }
288 
291  void clear (void) {
292  m_chars = NULL;
293  }
294 
297  size_t length (void) const {
298  if (! m_chars)
299  return 0;
300  const TableRep *rep = ((const TableRep *)m_chars) - 1;
301  return rep->length;
302  }
303 
306  size_t hash (void) const {
307  if (! m_chars)
308  return 0;
309  const TableRep *rep = ((const TableRep *)m_chars) - 1;
310  return rep->hashed;
311  }
312 
315  size_t size (void) const { return length(); }
316 
319  bool empty (void) const { return (size() == 0); }
320 
324  operator int (void) const { return !empty(); }
325 
328  const_iterator begin () const { return string().begin(); }
329 
332  const_iterator end () const { return string().end(); }
333 
336  const_reverse_iterator rbegin () const { return string().rbegin(); }
337 
340  const_reverse_iterator rend () const { return string().rend(); }
341 
345  const_reference operator[] (size_type pos) const { return c_str()[pos]; }
346 
349  size_type copy (char* s, size_type n, size_type pos = 0) const {
350  if (m_chars == NULL) {
351  s[0] = 0;
352  return 0;
353  }
354  char *c = strncpy (s, c_str()+pos, n);
355  return (size_type)(c-s);
356  }
357 
360  ustring substr (size_type pos = 0, size_type n = npos) const {
361  return ustring (*this, pos, n);
362  }
363 
364  // FIXME: implement compare.
365 
366  size_type find(const ustring &str, size_type pos = 0) const {
367  return string().find(str.string(), pos);
368  }
369 
370  size_type find(const std::string &str, size_type pos = 0) const {
371  return string().find(str, pos);
372  }
373 
374  size_type find(const char *s, size_type pos, size_type n) const {
375  return string().find(s, pos, n);
376  }
377 
378  size_type find(const char *s, size_type pos = 0) const {
379  return string().find(s, pos);
380  }
381 
382  size_type find(char c, size_type pos = 0) const {
383  return string().find(c, pos);
384  }
385 
386  size_type rfind(const ustring &str, size_type pos = npos) const {
387  return string().rfind(str.string(), pos);
388  }
389 
390  size_type rfind(const std::string &str, size_type pos = npos) const {
391  return string().rfind(str, pos);
392  }
393 
394  size_type rfind(const char *s, size_type pos, size_type n) const {
395  return string().rfind(s, pos, n);
396  }
397 
398  size_type rfind(const char *s, size_type pos = npos) const {
399  return string().rfind(s, pos);
400  }
401 
402  size_type rfind(char c, size_type pos = npos) const {
403  return string().rfind(c, pos);
404  }
405 
406  size_type find_first_of(const ustring &str, size_type pos = 0) const {
407  return string().find_first_of(str.string(), pos);
408  }
409 
410  size_type find_first_of(const std::string &str, size_type pos = 0) const {
411  return string().find_first_of(str, pos);
412  }
413 
414  size_type find_first_of(const char *s, size_type pos, size_type n) const {
415  return string().find_first_of(s, pos, n);
416  }
417 
418  size_type find_first_of(const char *s, size_type pos = 0) const {
419  return string().find_first_of(s, pos);
420  }
421 
422  size_type find_first_of(char c, size_type pos = 0) const {
423  return string().find_first_of(c, pos);
424  }
425 
426  size_type find_last_of(const ustring &str, size_type pos = npos) const {
427  return string().find_last_of(str.string(), pos);
428  }
429 
430  size_type find_last_of(const std::string &str, size_type pos = npos) const {
431  return string().find_last_of(str, pos);
432  }
433 
434  size_type find_last_of(const char *s, size_type pos, size_type n) const {
435  return string().find_last_of(s, pos, n);
436  }
437 
438  size_type find_last_of(const char *s, size_type pos = npos) const {
439  return string().find_last_of(s, pos);
440  }
441 
442  size_type find_last_of(char c, size_type pos = npos) const {
443  return string().find_last_of(c, pos);
444  }
445 
446  size_type find_first_not_of(const ustring &str, size_type pos = 0) const {
447  return string().find_first_not_of(str.string(), pos);
448  }
449 
450  size_type find_first_not_of(const std::string &str, size_type pos = 0) const {
451  return string().find_first_not_of(str, pos);
452  }
453 
454  size_type find_first_not_of(const char *s, size_type pos, size_type n) const {
455  return string().find_first_not_of(s, pos, n);
456  }
457 
458  size_type find_first_not_of(const char *s, size_type pos = 0) const {
459  return string().find_first_not_of(s, pos);
460  }
461 
462  size_type find_first_not_of(char c, size_type pos = 0) const {
463  return string().find_first_not_of(c, pos);
464  }
465 
466  size_type find_last_not_of(const ustring &str, size_type pos = npos) const {
467  return string().find_last_not_of(str.string(), pos);
468  }
469 
470  size_type find_last_not_of(const std::string &str, size_type pos = npos) const {
471  return string().find_last_not_of(str, pos);
472  }
473 
474  size_type find_last_not_of(const char *s, size_type pos, size_type n) const {
475  return string().find_last_not_of(s, pos, n);
476  }
477 
478  size_type find_last_not_of(const char *s, size_type pos = npos) const {
479  return string().find_last_not_of(s, pos);
480  }
481 
482  size_type find_last_not_of(char c, size_type pos = npos) const {
483  return string().find_last_not_of(c, pos);
484  }
485 
489 
490  int compare (const ustring& str) const {
491  return (c_str() == str.c_str()) ? 0
492  : strcmp (c_str() ? c_str() : "", str.c_str() ? str.c_str() : "");
493  }
494 
498  int compare (const std::string& str) const {
499  return strcmp (c_str() ? c_str() : "", str.c_str());
500  }
501 
505  friend int compare (const std::string& a, const ustring &b) {
506  return strcmp (a.c_str(), b.c_str() ? b.c_str() : "");
507  }
508 
513  bool operator== (const ustring &str) const {
514  return c_str() == str.c_str();
515  }
516 
521  bool operator!= (const ustring &str) const {
522  return c_str() != str.c_str();
523  }
524 
527  bool operator== (const std::string &x) const { return compare(x) == 0; }
528 
531  friend bool operator== (const std::string &a, const ustring &b) {
532  return b.compare(a) == 0;
533  }
534 
537  bool operator!= (const std::string &x) const { return compare(x) != 0; }
538 
541  friend bool operator!= (const std::string &a, const ustring &b) {
542  return b.compare(a) != 0;
543  }
544 
547  bool operator< (const ustring &x) const { return compare(x) < 0; }
548 
557  TINYFORMAT_WRAP_FORMAT (static ustring, format, ,
558  std::ostringstream msg;, msg, return ustring(msg.str());)
559 
562  friend std::ostream & operator<< (std::ostream &out, const ustring &str) {
563  if (str.c_str())
564  out << str.c_str();
565  return out;
566  }
567 
570  static std::string getstats (bool verbose = true);
571 
574  static size_t memory ();
575 
582  static const char * make_unique (const char *str);
583 
586  static bool is_unique (const char *str) {
587  return str == NULL || make_unique(str) == str;
588  }
589 
593  static ustring from_unique (const char *unique) {
594  DASSERT (is_unique(unique)); // DEBUG builds -- check it!
595  ustring u;
596  u.m_chars = unique;
597  return u;
598  }
599 
600 private:
601 
602  // Individual ustring internal representation -- the unique characters.
603  //
604  const char *m_chars;
605 
606 public:
607  // Representation within the hidden string table -- DON'T EVER CREATE
608  // ONE OF THESE YOURSELF!
609  // The characters are found directly after the rep. So that means that
610  // if you know the rep, the chars are at (char *)(rep+1), and if you
611  // know the chars, the rep is at ((TableRep *)chars - 1).
612  struct TableRep {
613  size_t hashed; // precomputed Hash value
614  std::string str; // String representation
615  size_t length; // Length of the string; must be right before cap
616  size_t dummy_capacity; // Dummy field! must be right before refcount
617  int dummy_refcount; // Dummy field! must be right before chars
618  TableRep (const char *s, size_t len);
619  ~TableRep ();
620  const char *c_str () const { return (const char *)(this + 1); }
621  };
622 
623 private:
624  static std::string empty_std_string;
625 };
626 
627 
628 
632 {
633 public:
634  size_t operator() (const ustring &s) const { return s.hash(); }
635 };
636 
637 
638 
641 inline bool iequals (ustring a, ustring b) {
642  return a==b || Strutil::iequals(a.string(), b.string());
643 }
644 inline bool iequals (ustring a, const std::string &b) {
645  return Strutil::iequals(a.string(), b);
646 }
647 inline bool iequals (const std::string &a, ustring b) {
648  return Strutil::iequals(a, b.string());
649 }
650 
651 
652 }
653 OIIO_NAMESPACE_EXIT
654 
655 #endif // OPENIMAGEIO_USTRING_H