Twine.h revision 2d8bc0fe70c55664b89605dbfa5c2f591446469c
1a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// 2a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// 3a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// The LLVM Compiler Infrastructure 4a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// 5a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// This file is distributed under the University of Illinois Open Source 6a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// License. See LICENSE.TXT for details. 7a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch// 8a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch//===----------------------------------------------------------------------===// 9a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 10a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#ifndef LLVM_ADT_TWINE_H 11a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#define LLVM_ADT_TWINE_H 12a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 13a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "llvm/ADT/StringRef.h" 14a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "llvm/Support/DataTypes.h" 15a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <cassert> 16a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include <string> 17a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 18a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochnamespace llvm { 19a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch template <typename T> 20a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch class SmallVectorImpl; 21a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch class StringRef; 22a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch class raw_ostream; 23a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 24a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Twine - A lightweight data structure for efficiently representing the 25a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// concatenation of temporary values as strings. 26a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// 27a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A Twine is a kind of rope, it represents a concatenated string using a 28a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// binary-tree, where the string is the preorder of the nodes. Since the 29a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Twine can be efficiently rendered into a buffer when its result is used, 30a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// it avoids the cost of generating temporary values for intermediate string 31a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// results -- particularly in cases when the Twine result is never 32a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// required. By explicitly tracking the type of leaf nodes, we can also avoid 33a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// the creation of temporary strings for conversions operations (such as 34a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// appending an integer to a string). 35a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// 36a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A Twine is not intended for use directly and should not be stored, its 37a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// implementation relies on the ability to store pointers to temporary stack 38a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// objects which may be deallocated at the end of a statement. Twines should 39a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// only be used accepted as const references in arguments, when an API wishes 40a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// to accept possibly-concatenated strings. 41a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// 42a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Twines support a special 'null' value, which always concatenates to form 43a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// itself, and renders as an empty string. This can be returned from APIs to 44a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// effectively nullify any concatenations performed on the result. 45a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// 46a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// \b Implementation \n 47f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// 48f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// Given the nature of a Twine, it is not possible for the Twine's 49f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// concatenation method to construct interior nodes; the result must be 50f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// represented inside the returned value. For this reason a Twine object 51f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// actually holds two values, the left- and right-hand sides of a 52f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// concatenation. We also have nullary Twine objects, which are effectively 53f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// sentinel values that represent empty strings. 54f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// 55f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// Thus, a Twine can effectively have zero, one, or two children. The \see 56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for 57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// testing the number of children. 58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// 59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// We maintain a number of invariants on Twine objects (FIXME: Why): 60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// - Nullary twines are always represented with their Kind on the left-hand 61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// side, and the Empty kind on the right-hand side. 62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// - Unary twines are always represented with the value on the left-hand 63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// side, and the Empty kind on the right-hand side. 64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// - If a Twine has another Twine as a child, that child should always be 65f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// binary (otherwise it could have been folded into the parent). 66f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// 67f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// These invariants are check by \see isValid(). 68f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// 69f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// \b Efficiency Considerations \n 70f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// 71323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// The Twine is designed to yield efficient and small code for common 72323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// situations. For this reason, the concat() method is inlined so that 73323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// concatenations of leaf nodes can be optimized into stores directly into a 74323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// single stack allocated object. 75323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// 76323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// In practice, not all compilers can be trusted to optimize concat() fully, 77323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// so we provide two additional methods (and accompanying operator+ 78323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// overloads) to guarantee that particularly important cases (cstring plus 79323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// StringRef) codegen as desired. 80323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) class Twine { 81323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// NodeKind - Represent the type of an argument. 82323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) enum NodeKind { 83323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// An empty string; the result of concatenating anything with it is also 84323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// empty. 85323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) NullKind, 86323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 87323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// The empty string. 88323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) EmptyKind, 89323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 90323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// A pointer to a Twine instance. 91323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) TwineKind, 92323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) 93323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) /// A pointer to a C string instance. 94323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) CStringKind, 95a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 96a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to an std::string instance. 97a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch StdStringKind, 98a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 99a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to a StringRef instance. 100a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch StringRefKind, 101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 102a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to an unsigned int value, to render as an unsigned decimal 103a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// integer. 104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DecUIKind, 105a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 106a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to an int value, to render as a signed decimal integer. 107a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DecIKind, 108a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 109a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to an unsigned long value, to render as an unsigned decimal 110a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// integer. 111a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DecULKind, 112a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 113a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to a long value, to render as a signed decimal integer. 114a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DecLKind, 115a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 116a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to an unsigned long long value, to render as an unsigned 117a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// decimal integer. 118a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DecULLKind, 119a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 120a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to a long long value, to render as a signed decimal integer. 121a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch DecLLKind, 122a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 123a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// A pointer to a uint64_t value, to render as an unsigned hexadecimal 124a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// integer. 125a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch UHexKind 126a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch }; 127a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 128a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch private: 129a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// LHS - The prefix in the concatenation, which may be uninitialized for 130a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Null or Empty kinds. 131a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const void *LHS; 132a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// RHS - The suffix in the concatenation, which may be uninitialized for 133a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Null or Empty kinds. 134a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const void *RHS; 135a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). 136a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NodeKind LHSKind : 8; 137a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). 138a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NodeKind RHSKind : 8; 139a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch private: 141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a nullary twine; the kind must be NullKind or EmptyKind. 142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(NodeKind Kind) 143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHSKind(Kind), RHSKind(EmptyKind) { 144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isNullary() && "Invalid kind!"); 145a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 146a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a binary twine. 148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const Twine &_LHS, const Twine &_RHS) 149a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&_LHS), RHS(&_RHS), LHSKind(TwineKind), RHSKind(TwineKind) { 150a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 152a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 153a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a twine from explicit values. 154a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const void *_LHS, NodeKind _LHSKind, 155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const void *_RHS, NodeKind _RHSKind) 156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { 157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 158a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// isNull - Check for the null twine. 161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isNull() const { 162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return getLHSKind() == NullKind; 163a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 164a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 165a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// isEmpty - Check for the empty twine. 166a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isEmpty() const { 167a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return getLHSKind() == EmptyKind; 168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// isNullary - Check if this is a nullary twine (null or empty). 171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isNullary() const { 172a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return isNull() || isEmpty(); 173a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 174a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 175a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// isUnary - Check if this is a unary twine. 176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isUnary() const { 177a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return getRHSKind() == EmptyKind && !isNullary(); 178a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 179a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 180a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// isBinary - Check if this is a binary twine. 181a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isBinary() const { 182a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return getLHSKind() != NullKind && getRHSKind() != EmptyKind; 183a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 184a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 185a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// isValid - Check if this is a valid twine (satisfying the invariants on 186a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// order and number of arguments). 187a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch bool isValid() const { 188a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Nullary twines always have Empty on the RHS. 189a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (isNullary() && getRHSKind() != EmptyKind) 190a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return false; 191a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 192a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Null should never appear on the RHS. 193a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (getRHSKind() == NullKind) 194a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return false; 195a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 196a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // The RHS cannot be non-empty if the LHS is empty. 197a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) 198a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return false; 199a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 200a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // A twine child should always be binary. 201a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (getLHSKind() == TwineKind && 202a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch !static_cast<const Twine*>(LHS)->isBinary()) 203a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return false; 204a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (getRHSKind() == TwineKind && 205a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch !static_cast<const Twine*>(RHS)->isBinary()) 206a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return false; 207a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 208a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return true; 209a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 210a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 211a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// getLHSKind - Get the NodeKind of the left-hand side. 212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NodeKind getLHSKind() const { return LHSKind; } 213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// getRHSKind - Get the NodeKind of the left-hand side. 215a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NodeKind getRHSKind() const { return RHSKind; } 216a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 217a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// printOneChild - Print one child from a twine. 218a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const; 219a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 220a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// printOneChildRepr - Print the representation of one child from a twine. 221a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void printOneChildRepr(raw_ostream &OS, const void *Ptr, 222a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NodeKind Kind) const; 223a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 224a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch public: 225a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @name Constructors 226a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @{ 227a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 228a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct from an empty string. 229a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { 230a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 231a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 232a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 233a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct from a C string. 234a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// 235a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// We take care here to optimize "" into the empty twine -- this will be 236a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// optimized out for string constants. This allows Twine arguments have 237a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// default "" values, without introducing unnecessary string constants. 238a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /*implicit*/ Twine(const char *Str) 239a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : RHSKind(EmptyKind) { 240a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (Str[0] != '\0') { 241a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch LHS = Str; 242a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch LHSKind = CStringKind; 243a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } else 244a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch LHSKind = EmptyKind; 245a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 246a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 247a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 248a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 249a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct from an std::string. 250a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /*implicit*/ Twine(const std::string &Str) 251a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) { 252a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 253a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 254a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 255a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct from a StringRef. 256a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /*implicit*/ Twine(const StringRef &Str) 257a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) { 258a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 259a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 260a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 261a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a twine to print \arg Val as an unsigned decimal integer. 262a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const unsigned int &Val) 263a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { 264a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 265a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 266a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a twine to print \arg Val as a signed decimal integer. 267a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const int &Val) 268a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Val), LHSKind(DecIKind), RHSKind(EmptyKind) { 269a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 270a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 271a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a twine to print \arg Val as an unsigned decimal integer. 272a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const unsigned long &Val) 273a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { 274a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 275a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 276a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a twine to print \arg Val as a signed decimal integer. 277a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const long &Val) 278a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { 279a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 280a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 281a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct a twine to print \arg Val as an unsigned decimal integer. 282a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const unsigned long long &Val) 283a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { 284a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 285a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 286f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// Construct a twine to print \arg Val as a signed decimal integer. 287a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch explicit Twine(const long long &Val) 288f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { 289a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 290a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 291a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // FIXME: Unfortunately, to make sure this is as efficient as possible we 292a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // need extra binary constructors from particular types. We can't rely on 293a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // the compiler to be smart enough to fold operator+()/concat() down to the 294a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // right thing. Yet. 295a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 296a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct as the concatenation of a C string and a StringRef. 297a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) 298a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(_LHS), RHS(&_RHS), LHSKind(CStringKind), RHSKind(StringRefKind) { 299a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 300f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 301a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 302a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Construct as the concatenation of a StringRef and a C string. 303a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) 304a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch : LHS(&_LHS), RHS(_RHS), LHSKind(StringRefKind), RHSKind(CStringKind) { 305a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch assert(isValid() && "Invalid twine!"); 306a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 307a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 308a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Create a 'null' string, which is an empty string that always 309a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// concatenates to form another empty string. 310a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch static Twine createNull() { 311a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Twine(NullKind); 312a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 313a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 314a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @} 315a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @name Numeric Conversions 316a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @{ 317a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 318a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Construct a twine to print \arg Val as an unsigned hexadecimal integer. 319a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch static Twine utohexstr(const uint64_t &Val) { 320a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Twine(&Val, UHexKind, 0, EmptyKind); 321a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 322a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 323a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @} 324a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @name String Operations 325a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @{ 326a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 327a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch Twine concat(const Twine &Suffix) const; 328a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 329a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @} 330a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @name Output & Conversion. 331a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @{ 332a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 333a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// str - Return the twine contents as a std::string. 334a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch std::string str() const; 335a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 336a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// toVector - Write the concatenated string into the given SmallString or 337f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// SmallVector. 338f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu void toVector(SmallVectorImpl<char> &Out) const; 339f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 340f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// print - Write the concatenated string represented by this twine to the 341f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// stream \arg OS. 342f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu void print(raw_ostream &OS) const; 343f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 344f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu /// dump - Dump the concatenated string represented by this twine to stderr. 345a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void dump() const; 346a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 347a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// print - Write the representation of this twine to the stream \arg OS. 348a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void printRepr(raw_ostream &OS) const; 349a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 350a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// dumpRepr - Dump the representation of this twine to stderr. 351a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch void dumpRepr() const; 352a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 353a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @} 354a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch }; 355a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 356a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @name Twine Inline Implementations 357a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @{ 358a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 359a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch inline Twine Twine::concat(const Twine &Suffix) const { 360a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Concatenation with null is null. 361a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (isNull() || Suffix.isNull()) 362a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Twine(NullKind); 363a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 364a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Concatenation with empty yields the other side. 365a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (isEmpty()) 366a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Suffix; 367a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (Suffix.isEmpty()) 368a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return *this; 369a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 370a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Otherwise we need to create a new node, taking care to fold in unary 371a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // twines. 372a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const void *NewLHS = this, *NewRHS = &Suffix; 373a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; 374a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (isUnary()) { 375a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NewLHS = LHS; 376a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NewLHSKind = getLHSKind(); 377a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 378a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch if (Suffix.isUnary()) { 379a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NewRHS = Suffix.LHS; 380a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch NewRHSKind = Suffix.getLHSKind(); 381a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 382a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 383a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); 384a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 385a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 386a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch inline Twine operator+(const Twine &LHS, const Twine &RHS) { 387a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return LHS.concat(RHS); 388a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 389a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 390a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Additional overload to guarantee simplified codegen; this is equivalent to 391a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// concat(). 392a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 393a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch inline Twine operator+(const char *LHS, const StringRef &RHS) { 394a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Twine(LHS, RHS); 395a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 396a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 397a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// Additional overload to guarantee simplified codegen; this is equivalent to 398a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// concat(). 399a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 400a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch inline Twine operator+(const StringRef &LHS, const char *RHS) { 401a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return Twine(LHS, RHS); 402a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 403a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 404a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { 405a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch RHS.print(OS); 406a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch return OS; 407a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch } 408a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 409a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch /// @} 410a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch} 411a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch 412a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#endif 413a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch