InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
EscapeTable.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Florin Trofin
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //========================================================================================
23 
24 #ifndef __EscapeTable__
25 #define __EscapeTable__
26 
27 #include "AnsiBasedTypes.h"
28 #include <memory>
29 #include <string>
30 #include <map>
31 #include "K2Assert.h"
32 #include <boost/range/iterator_range.hpp>
33 #include <boost/range/as_literal.hpp>
34 #include "id_auto_ptr.h"
35 
36 // Defines the escaped character and the replacement escape sequence
37 template<typename T, typename U>
38 struct EscapePair
39 {
40  // A character range reference is merely a boost::iterato_range of simple pointers
41  typedef typename boost::iterator_range<U const*> char_range_ref;
42 
43  T ch; // char to be escaped
44  char_range_ref escapeSeq; // Escape sequence
45 };
46 
54 template <bool flag, typename T, typename U>
55 struct SelectType
56 {
57  typedef T Result;
58 };
59 template <typename T, typename U>
60 struct SelectType<false, T, U>
61 {
62  typedef U Result;
63 };
64 
65 
66 //
67 // Wrapper over a C-array of EscapePairs
68 //
69 // WARNING: this class does NOT copy the data passed in the constructor.
70 // It is rather a wrapper over a C-array of EscapePairs.
71 // The array that is passed in the constructor has to be valid for the lifetime of this object.
72 //
73 // All escape sequences must start with the same escape char AND they must either be the same length
74 // or they should have the same ending escape char.
75 //
76 // T is the character type for the character to be escaped
77 // U is the character type of the escape sequence
78 //
79 // The escape tables can come in two flavors:
80 // - all escape sequences have the same start escape marker and fixed length (the end escape marker doesn't exist)
81 // - all escape sequences have the same pair of start and end markers and they can be of different lengths.
82 //
83 
84 // EscapeTable is usually a shared const variable.
85 // However, initialization of the members can lead to undesirable
86 // race conditions unless synchronization is implemented.
87  void* AcquireEscapeTableLock();
88  void ReleaseEscapeTableLock(void* lock);
89 template<typename T, typename U>
91 {
92  // This class is not copyable
93  EscapeTable(const EscapeTable &);
94  EscapeTable& operator=(const EscapeTable &);
95 
96 
97 public:
98  typedef size_t size_type;
100  typedef EscapePair<T, U>& reference;
101  typedef EscapePair<T, U> const& const_reference;
102 // typedef std::map<T, std::basic_string<U> > EscapeMap;
103 // typedef std::map<std::basic_string<U>, T> UnescapeMap;
104  // Determine which char type is larger
105  typedef typename SelectType<(sizeof(T) > sizeof(U)), T, U>::Result BigCharType;
106 
107  // Select the bigger char type as lookup key and the smaller one as the value
108  // This will make it easier with the casts
109  // (always better to go from char->wide char take advantage of type promotion)
110  typedef BigCharType EscapeMapKey;
111  typedef typename EscapePair<T, U>::char_range_ref EscapeMapValue;
112 
113  typedef typename std::basic_string<BigCharType> UnescapeMapKey;
114  typedef T UnescapeMapValue;
115 
116  typedef typename std::map<EscapeMapKey, EscapeMapValue> EscapeMap;
117  typedef typename std::map<UnescapeMapKey, UnescapeMapValue> UnescapeMap;
118 
122  EscapeTable( EscapePair<T, U> escapes[], size_type count )
123  : array_(escapes), size_(count), endEscapeMarker_(U())
124  {
125  // Alias for easier reading
126  EscapeMapValue const& escapeSequence( array_[0].escapeSeq );
127  ASSERT( !escapeSequence.empty() );
128 
129  // Save the start escape marker (all start escape markers should be the same)
130  startEscapeMarker_ = escapeSequence.front();
131 
132  ASSERT( IsValid() );
133  }
134 
139  EscapeTable( EscapePair<T, U> escapes[], size_type count, U startEscapeMarker, U endEscapeMarker )
140  : array_(escapes), size_(count), startEscapeMarker_(startEscapeMarker), endEscapeMarker_(endEscapeMarker)
141  {
142  // The end marker can not be the nil character
143  ASSERT( endEscapeMarker_ != U() );
144  ASSERT( IsValid() );
145  }
146 
147  bool16 IsValidEscapeSequence( const EscapeMapValue& escapeSequence ) const
148  {
149  ASSERT( !escapeSequence.empty() );
150  // All escape sequences must start with the same escape char
151  // AND they either must be the same length or they should have the same ending escape char
152 
153  if ( endEscapeMarker_ != U() )
154  {
155  return (escapeSequence.front() == startEscapeMarker_ && escapeSequence.back() == endEscapeMarker_);
156  }
157 
158  // Must have the same length
159  return ( escapeSequence.front() == startEscapeMarker_ && escapeSequence.size() == array_[0].escapeSeq.size() );
160  }
161 
162  // Checks if this table is valid
163  bool16 IsValid() const
164  {
165  ASSERT( size() );
166  bool16 result( true );
167 
168  size_type i( 0 );
169  for (; i < size() && result; ++i )
170  {
171  // all escape sequences must start with the same escape char
172  // AND they either must be the same length or they should have the same ending escape char
173  result = IsValidEscapeSequence(array_[i].escapeSeq);
174  }
175  return result;
176  }
177 
178  // read-only access for an EscapePair at the specified index
179  const_reference operator[]( size_type index ) const
180  {
181  return array_[index];
182  }
183 
184  // number of elements in the array
185  size_type size() const
186  {
187  return size_;
188  }
189 
190  EscapeMap const& GetEscapeMap() const
191  {
192  if (!escapeMap_.get() )
193  {
194  void* lock = AcquireEscapeTableLock();
195  if ( !escapeMap_.get() )
196  escapeMap_.reset( CreateEscapeMap());
197  ReleaseEscapeTableLock(lock);
198  }
199  return *escapeMap_;
200  }
201 
202  UnescapeMap const& GetUnescapeMap() const
203  {
204  if ( !unescapeMap_.get() )
205  {
206  void* lock = AcquireEscapeTableLock();
207  if ( !unescapeMap_.get() )
208  {
209  unescapeMap_.reset( CreateUnescapeMap());
210  }
211  ReleaseEscapeTableLock(lock);
212  }
213  return *unescapeMap_;
214  }
215 
216 
217 private:
218 
219  EscapeMap* CreateEscapeMap( ) const
220  {
221  ASSERT( IsValid() );
222 
223  bool16 result(true);
224  EscapeMap* escapeMap = new EscapeMap;
225  size_type i(0);
226  for (; i < size() && result; ++i )
227  {
228  result = escapeMap->insert(
229  std::make_pair(array_[i].ch, array_[i].escapeSeq) ).second;
230  ASSERT_MSG( result, "CreateEscapeMap failed to insert escape seq! Check for duplicates!" );
231  }
232 
233  if (!result)
234  {
235  delete escapeMap;
236  escapeMap = nil;
237  }
238  return escapeMap;
239  }
240 
241  UnescapeMap* CreateUnescapeMap( ) const
242  {
243  ASSERT( IsValid() );
244  UnescapeMap* unescapeMap = new UnescapeMap;
245 
246  bool16 result(true);
247  size_type i(0);
248  for (; i < size() && result; ++i )
249  {
250  UnescapeMapKey key(array_[i].escapeSeq.begin(), array_[i].escapeSeq.end());
251 
252  result = unescapeMap->insert(
253  std::make_pair(key, array_[i].ch) ).second;
254  ASSERT_MSG( result, "CreateUnescapeMap failed to insert unescape seq! Check for duplicates!" );
255  }
256 
257  if ( !result )
258  {
259  delete unescapeMap;
260  unescapeMap = nil;
261  }
262  return unescapeMap;
263  }
264 
265  // Data
266  EscapePair<T, U> const* array_;
267  size_type size_;
268  U startEscapeMarker_;
269  U endEscapeMarker_;
270 
271  mutable std::unique_ptr<EscapeMap> escapeMap_;
272  mutable std::unique_ptr<UnescapeMap> unescapeMap_;
273 };
274 
275 #endif // __EscapeTable__ //