HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDG_ValuePattern.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * COMMENTS:
7  */
8 
9 #ifndef __PDG_VALUE_PATTERN_H__
10 #define __PDG_VALUE_PATTERN_H__
11 
12 #include "PDG_API.h"
13 #include "PDG_BasePattern.h"
14 
15 #include <UT/UT_Array.h>
16 #include <UT/UT_ArrayMap.h>
17 #include <UT/UT_StringArray.h>
18 #include <UT/UT_StringHolder.h>
19 #include <UT/UT_ValArray.h>
20 #include <UT/UT_VectorTypes.h>
21 #include <UT/UT_WorkBuffer.h>
22 #include <SYS/SYS_String.h>
23 
24 class UT_StringView;
25 
26 /**
27  * Creates a queryable representation of a sequence of values, but does not
28  * generate the sequence itself unless requested. For example:
29  *
30  * `1-10 20 30 40`
31  * `1-10:2 !3`
32  */
34 {
35 public:
39 
40 public:
41  /// Creates an empty pattern instance that will have it's contents loaded
42  /// later.
43  PDG_ValuePattern(char delimiter=' ');
44 
45  /// Parses a pattern into a PDG_ValuePattern instance
47  const UT_StringHolder& pattern,
48  char delimiter=' ');
49 
50  /// Checks if the specified string value is in the pattern
51  bool contains(
52  const UT_StringHolder& value,
53  bool inclusive) const
54  {
55  if (match(value, inclusive, nullptr))
56  return true;
57 
58  int len = value.length();
59  const char* data = value.c_str();
60  bool has_digit = false;
61  while (len--)
62  {
63  if (!SYSisdigit(data[len]))
64  break;
65 
66  has_digit = true;
67  }
68 
69  if (!has_digit)
70  return false;
71 
72  int suffix = atoi(data+len+1);
73  UT_StringView prefix(data, len+1);
74  return match(
75  suffix, prefix, inclusive, nullptr);
76  }
77 
78  /// Checks if the specified float value is in the pattern
79  bool contains(fpreal value, bool inclusive) const
80  { return match(value, inclusive, nullptr); }
81 
82  /// Checks if the specified integer value is in the pattern
83  bool contains(exint value, bool inclusive) const
84  { return match(value, inclusive, nullptr); }
85 
86 
87  /// Checks if the specified float value matches the pattern and returns
88  /// the range of values from the component that matches
91  fpreal value,
92  bool inclusive) const
93  {
94  return matchRange(
95  range, value, inclusive);
96  }
97 
98  /// Checks if the specified integer value matches the pattern and returns
99  /// the range of values from the component that matches
102  exint value,
103  bool inclusive) const
104  {
105  return matchRange(
106  range, value, inclusive);
107  }
108 
109 
110  /// Returns the array of string values that match the pattern
111  void array(
113  bool sorted,
114  bool inclusive) const
115  {
116  return append(
117  values, sorted, inclusive);
118  }
119 
120  /// Returns the array of float values that match the pattern
121  void array(
123  bool sorted,
124  bool inclusive) const
125  {
126  return append(
127  values, sorted, inclusive);
128  }
129 
130  /// Returns the array of integer values that match the pattern
131  void array(
133  bool sorted,
134  bool inclusive) const
135  {
136  return append(
137  values, sorted, inclusive);
138  }
139 
140 
141  /// Returns a map of component number -> string value array, after
142  /// considering exclusions
143  void arrayMap(
144  StringMap& values,
145  bool sorted,
146  bool inclusive) const
147  {
148  return appendMap(
149  values, sorted, inclusive);
150  }
151 
152  /// Returns a map of component number -> float value array, after
153  /// considering exclusions
154  void arrayMap(
155  FloatMap& values,
156  bool sorted,
157  bool inclusive) const
158  {
159  return appendMap(
160  values, sorted, inclusive);
161  }
162 
163  /// Returns a map of component number -> int value array, after
164  /// considering exclusions
165  void arrayMap(
166  IntMap& values,
167  bool sorted,
168  bool inclusive) const
169  {
170  return appendMap(
171  values, sorted, inclusive);
172  }
173 
174 
175  /// Returns the value range for the specified component number
178  exint index,
179  bool inclusive) const
180  {
181  if (index < 0 ||
182  index >= myMatches.size())
183  {
184  return false;
185  }
186 
187  if (myMatches[index].myIsExclusion)
188  return false;
189 
190  myMatches[index].setRange(
191  range, inclusive);
192 
193  return true;
194  }
195 
196  /// Returns the step value for the specified component number
198  {
199  if (index < 0 ||
200  index >= myMatches.size())
201  {
202  return false;
203  }
204 
205  return myMatches[index].floatValue(
206  2, 1);
207  }
208 
209  /// Returns true if the pattern is strictly numeric (has no string
210  /// values in it), otherwise returns false
211  bool isNumeric() const
212  { return myIsNumeric; }
213 
214  /// Returns true if the pattern has segments with different step sizes
215  bool hasVariableStep() const
216  { return myHasVariableStep; }
217 
218  /// Returns the minimum step size from all components in the pattern
220  { return myMinimumStep; }
221 
222  /// Resets the pattern to an unparsed state
223  bool reset(
224  const UT_StringHolder& pattern,
225  char delimiter=' ');
226 
227  /// Updates and reparses the pattern if the supplied pattern string is
228  /// different than the current pattern string
229  bool tryReset(
230  const UT_StringHolder& pattern,
231  char delimiter= ' ');
232 
233  /// Parses the input string into this pattern -- only valid if no pattern
234  /// has been parsed previously
235  bool parse(const UT_StringView& pattern);
236 
237 private:
238  /// Possible types for a value match
239  enum MatchType : uint8
240  {
241  /// A single constant value
242  eMatchTypeConstant,
243 
244  /// A simple range with a start and end point, and a step size of 1
245  eMatchTypeRange,
246 
247  /// A range with a custom step size
248  eMatchTypeRangeStep,
249  };
250 
251  /// Utility to do an inclusive vs. exclusive range end comparison
252  template <typename Value, typename Step, typename End>
253  static inline bool inclusiveComp(
254  bool i,
255  const Value& v,
256  const Step& step,
257  const End& end)
258  {
259  if (step > 0)
260  return i ? (v <= end) : (v < end);
261  else
262  return i ? (v >= end) : (v > end);
263  }
264 
265  /// Value containing a float, string and integer part
266  struct Value
267  {
268  /// Appends a constant string, integer or float value from this
269  /// match value into the input array
270  void append(UT_StringArray& array) const
271  { array.append(myString); }
272  void append(UT_ExintArray& array) const
273  { if (myHasInteger) array.append(myInteger); }
274  void append(UT_FprealArray& array) const
275  { if (myHasFloat) array.append(myFloat); }
276 
277 
278  /// Appends values between start and end to the input array
279  static void append(
280  UT_StringArray& array,
281  const Value& start,
282  const Value& end,
283  bool inclusive)
284  {
285  if (!start.myHasInteger || !end.myHasInteger)
286  return;
287 
288  for (exint i = start.myInteger;
289  inclusiveComp(
290  inclusive, i, 1, end.myInteger);
291  i++)
292  {
294  buffer.format("{}{}", start.myPrefix, i);
295  array.append(buffer.buffer());
296  }
297  }
298 
299  static void append(
300  UT_FprealArray& array,
301  const Value& start,
302  const Value& end,
303  bool inclusive)
304  {
305  if (!start.myHasFloat || !end.myHasFloat)
306  return;
307  for (fpreal i = start.myFloat;
308  inclusiveComp(
309  inclusive, i, 1.0, end.myFloat);
310  i += 1.0)
311  {
312  array.append(i);
313  }
314  }
315 
316  static void append(
317  UT_ExintArray& array,
318  const Value& start,
319  const Value& end,
320  bool inclusive)
321  {
322  if (!start.myHasInteger || !end.myHasInteger)
323  return;
324  for (exint i = start.myInteger;
325  inclusiveComp(
326  inclusive, i, 1, end.myInteger);
327  i++)
328  {
329  array.append(i);
330  }
331  }
332 
333 
334  /// Appends values between start and end, with the specified step
335  /// size, to the input array
336  static void append(
337  UT_StringArray& array,
338  const Value& start,
339  const Value& end,
340  const Value& step,
341  bool inclusive)
342  {
343  if (!start.myHasInteger ||
344  !end.myHasInteger ||
345  !step.myHasInteger)
346  return;
347  if (step.myInteger == 0)
348  return;
349 
350  for (exint i = start.myInteger;
351  inclusiveComp(
352  inclusive, i,
353  step.myInteger, end.myInteger);
354  i += step.myInteger)
355  {
357  buffer.format("{}{}", start.myPrefix, i);
358  array.append(buffer.buffer());
359  }
360  }
361 
362  static void append(
363  UT_FprealArray& array,
364  const Value& start,
365  const Value& end,
366  const Value& step,
367  bool inclusive)
368  {
369  if (!start.myHasFloat ||
370  !end.myHasFloat ||
371  !step.myHasFloat)
372  return;
373  if (SYSequalZero(step.myFloat))
374  return;
375 
376  for (fpreal i = start.myFloat;
377  inclusiveComp(
378  inclusive, i,
379  step.myFloat, end.myFloat);
380  i += step.myFloat)
381  {
382  array.append(i);
383  }
384  }
385 
386  static void append(
387  UT_ExintArray& array,
388  const Value& start,
389  const Value& end,
390  const Value& step,
391  bool inclusive)
392  {
393  if (!start.myHasInteger ||
394  !end.myHasInteger ||
395  !step.myHasFloat)
396  return;
397  if (SYSequalZero(step.myFloat))
398  return;
399 
400  for (fpreal i = start.myInteger;
401  inclusiveComp(
402  inclusive, i,
403  step.myFloat, end.myInteger);
404  i += step.myFloat)
405  {
406  array.append(exint(i));
407  }
408  }
409 
410 
411  /// Performs an exact match comparison between an input value and the
412  /// constant value in this match value instance
413  bool match(const UT_StringHolder& value) const
414  { return myString == value; }
415  bool match(fpreal value) const
416  {
417  return myHasFloat && SYSalmostEqual(
418  value, myFloat);
419  }
420  bool match(exint value) const
421  { return myHasInteger && (myInteger == value); }
422 
423 
424  /// Checks if the input value is less than the match value in this
425  /// instance
426  bool less(const UT_StringHolder& value, bool inclusive) const
427  { return true; }
428  bool less(exint value, bool inclusive) const
429  {
430  if (!myHasInteger) return true;
431  else if (inclusive) return value < myInteger;
432  else return value <= myInteger;
433  }
434  bool less(fpreal value, bool inclusive) const
435  {
436  if (!myHasFloat) return true;
437  else if (inclusive) return value < myFloat;
438  else return value <= myFloat;
439  }
440 
441  /// Checks if the input value is greater than the match value in this
442  /// instance
443  bool greater(
444  const UT_StringHolder& value,
445  bool inclusive) const
446  { return true; }
447  bool greater(exint value, bool inclusive) const
448  {
449  if (!myHasInteger) return true;
450  else if (inclusive) return value > myInteger;
451  else return value >= myInteger;
452  }
453  bool greater(fpreal value, bool inclusive) const
454  {
455  if (!myHasFloat) return true;
456  else if (inclusive) return value > myFloat;
457  else return value >= myFloat;
458  }
459 
460 
461  /// Checks if the input value is in the same value range as this match
462  /// value, module the step
463  bool step(
464  const Value& start,
465  const UT_StringHolder& value) const
466  { return false; }
467  bool step(const Value& start, exint value) const
468  {
469  if (!start.myHasInteger || !myHasFloat)
470  return false;
471 
472  fpreal delta = value - start.myInteger;
473  return SYSalmostEqual(
474  SYSfmod(delta, myFloat), 0);
475  }
476  bool step(const Value& start, fpreal value) const
477  {
478  if (!start.myHasFloat || !myHasFloat)
479  return false;
480 
481  fpreal delta = value - start.myFloat;
482  return SYSalmostEqual(
483  SYSfmod(delta, myFloat), 0);
484  }
485 
486 
487  UT_StringHolder myPrefix;
488  UT_StringHolder myString;
489  fpreal myFloat;
490  exint myInteger;
491 
492  bool myHasFloat : 1;
493  bool myHasInteger : 1;
494  bool myHasPrefix : 1;
495  };
496 
497  /// Value match entry
498  struct ValueMatch
499  {
500  /// Does a full match, including parsing the prefix if the value is a
501  /// string
502  bool matchFull(
503  const UT_StringHolder& value,
504  bool inclusive) const
505  {
506  if (match(value, nullptr, inclusive))
507  return true;
508 
509  int len = value.length();
510  const char* data = value.c_str();
511  bool has_digits = false;
512  while (len--)
513  {
514  if (!SYSisdigit(data[len]))
515  break;
516 
517  has_digits = true;
518  }
519 
520  if (!has_digits)
521  return false;
522 
523  exint suffix = atoi(data+len+1);
524  if (myHasPrefix)
525  {
526  if (len < 0)
527  return false;
528 
529  UT_StringView prefix(data, len+1);
530  return match(suffix, &prefix, inclusive);
531  }
532  else
533  {
534  if (len > 0)
535  return false;
536  return match(suffix, nullptr, inclusive);
537  }
538  }
539  bool matchFull(const exint& value, bool inclusive) const
540  { return match(value, nullptr, inclusive); }
541  bool matchFull(const fpreal& value, bool inclusive) const
542  { return match(value, nullptr, inclusive); }
543 
544  /// Matches the pattern with the specified value
545  template <typename T>
546  bool match(
547  const T& value,
548  const UT_StringView* prefix,
549  bool inclusive) const
550  {
551  // If the pattern does not have a prefix and we
552  // do, return early
553  if (!myMatchValues[0].myHasPrefix && prefix)
554  return false;
555 
556  // Constants only check the first value
557  if (myMatchType == eMatchTypeConstant)
558  {
559  if (!myMatchValues[0].match(value))
560  return false;
561  }
562  // Simple range check
563  else
564  {
565  if (myMatchValues[0].less(value, true))
566  return false;
567 
568  if (myMatchValues[1].greater(value, inclusive))
569  return false;
570  }
571 
572  // If the pattern has a prefix then we require
573  // a matching one
574  if (myMatchValues[0].myHasPrefix)
575  {
576  if (!prefix)
577  return false;
578  else if (*prefix !=
579  myMatchValues[0].myPrefix.c_str())
580  {
581  return false;
582  }
583  }
584 
585  // At this point, constants and ranges have matched
586  if (myMatchType <= eMatchTypeRange)
587  return true;
588  return myMatchValues[2].step(
589  myMatchValues[0], value);
590  }
591 
592  /// Appends the values from the match into the specified array
593  template <typename T>
594  void append(T& array, bool inclusive) const
595  {
596  if (myMatchType == eMatchTypeConstant)
597  myMatchValues[0].append(array);
598  else if (myMatchType == eMatchTypeRange)
599  {
600  Value::append(
601  array,
602  myMatchValues[0],
603  myMatchValues[1],
604  inclusive);
605  }
606  else
607  {
608  Value::append(
609  array,
610  myMatchValues[0],
611  myMatchValues[1],
612  myMatchValues[2],
613  inclusive);
614  }
615  }
616 
617  /// Returns the nth value from the match as a float
618  fpreal floatValue(int index, fpreal default_value) const
619  {
620  if (index > myMatchType)
621  return default_value;
622 
623  const Value& value = myMatchValues[index];
624  if (value.myHasFloat)
625  return value.myFloat;
626  if (value.myHasInteger)
627  return (fpreal)(value.myInteger);
628 
629  return 0;
630  }
631 
632  /// Returns the range of values in the match segment as a float
633  /// array
634  void setRange(UT_FprealArray& range, bool inclusive) const
635  {
636  fpreal start = floatValue(0, 0);
637  fpreal end = floatValue(1, start);
638  fpreal step = floatValue(2, 1);
639 
640  fpreal last = SYSfloor((end-start)/step);
641  last = last*step + start;
642  if (!inclusive && SYSalmostEqual(end, last))
643  last -= step;
644 
645  range.clear();
646  range.append(start);
647  range.append(last);
648  range.append(step);
649  }
650 
651  /// Values in the match entry
652  Value myMatchValues[3];
653 
654  /// The match type
655  MatchType myMatchType;
656 
657  /// Whether or not the value sequence is an exclusion
658  bool myIsExclusion;
659 
660  /// Whether or not the values in this match have a prefix
661  bool myHasPrefix;
662 
663  /// Whether or not the values in this match are all numeric
664  bool myIsNumeric;
665  };
666 
667  /// Array of value matches
668  using ValueMatchArray = UT_Array<ValueMatch>;
669 
670  /// Helper struct for parsing string data
671  struct ParseState
672  {
673  ParseState()
674  { reset(); }
675 
676  void reset()
677  {
678  myValueIndex = 0;
679  myRangeIndex = 0;
680  myLastChar = 0;
681  myIsQuoted = false;
682  myIsSkip = false;
683  myIsExclusion = false;
684 
685  for (int i = 0; i < 3; i++)
686  myValues[i].clear();
687  }
688 
689  UT_WorkBuffer myValues[3];
690  exint myRangeValues[3];
691  int myValueIndex;
692  int myRangeIndex;
693  char myLastChar;
694 
695  bool myIsQuoted;
696  bool myIsSkip;
697  bool myIsExclusion;
698  };
699 
700 private:
701  template <typename T>
702  bool match(
703  const T& value,
704  bool inclusive,
705  const ValueMatch** value_match) const
706  {
707  if (!myIsValid)
708  return false;
709 
710  bool found = false;
711  for (auto&& match : myMatches)
712  {
713  if (!match.match(value, nullptr, inclusive))
714  continue;
715 
716  if (!myHasExclusion)
717  {
718  if (value_match)
719  *value_match = &match;
720  return true;
721  }
722 
723  if (!match.myIsExclusion)
724  {
725  if (value_match)
726  *value_match = &match;
727  found = true;
728  }
729  else if (found)
730  return false;
731  }
732 
733  return found;
734  }
735 
736  bool match(
737  exint value,
738  const UT_StringView& prefix,
739  bool inclusive,
740  const ValueMatch** value_match) const
741  {
742  if (!myIsValid)
743  return false;
744 
745  bool found = false;
746  for (auto&& match : myMatches)
747  {
748  if (!match.match(value, &prefix, inclusive))
749  continue;
750 
751  if (!myHasExclusion)
752  {
753  if (value_match)
754  *value_match = &match;
755  return true;
756  }
757 
758  if (!match.myIsExclusion)
759  {
760  if (value_match)
761  *value_match = &match;
762  found = true;
763  }
764  else if (found)
765  return false;
766  }
767 
768  return found;
769  }
770 
771  template <typename T>
772  bool matchRange(
773  UT_FprealArray& range,
774  const T& value,
775  bool inclusive) const
776  {
777  const ValueMatch* value_match = nullptr;
778  if (!match(value, inclusive, &value_match))
779  return false;
780  if (!value_match)
781  return false;
782 
783  value_match->setRange(range, inclusive);
784  return true;
785  }
786 
787  template <typename T>
788  void append(
789  T& array,
790  bool sorted,
791  bool inclusive) const
792  {
793  if (!myIsValid)
794  return;
795 
796  T swap_array;
797  for (auto&& match : myMatches)
798  {
799  if (!match.myIsExclusion)
800  {
801  match.append(array, inclusive);
802  continue;
803  }
804 
805  for (auto&& entry : array)
806  {
807  if (match.matchFull(entry, inclusive))
808  continue;
809  swap_array.append(entry);
810  }
811 
812  std::swap(array, swap_array);
813  swap_array.clear();
814  }
815 
816  if (sorted)
817  array.sort();
818  }
819 
820  template <typename T>
821  void appendMap(
822  T& map,
823  bool sorted,
824  bool inclusive) const
825  {
826  if (!myIsValid)
827  return;
828 
829  typename T::mapped_type swap_array;
830  exint i = 0;
831  for (auto&& match : myMatches)
832  {
833  auto&& array = map[i++];
834 
835  if (!match.myIsExclusion)
836  {
837  match.append(array, inclusive);
838  continue;
839  }
840 
841  for (auto&& array : map)
842  {
843  for (auto&& entry : array.second)
844  {
845  if (match.matchFull(
846  entry, inclusive))
847  {
848  continue;
849  }
850 
851  swap_array.append(entry);
852  }
853 
854  std::swap(array.second, swap_array);
855  swap_array.clear();
856  }
857  }
858 
859  if (sorted)
860  {
861  for (auto&& array : map)
862  array.second.sort();
863  }
864  }
865 
866 
867  bool parse(const UT_StringHolder& pattern);
868  bool addPattern(ParseState& parse_state);
869 
870 private:
871  /// Array of patterns
872  ValueMatchArray myMatches;
873 
874  /// The minimum step size across all components in the pattern
875  fpreal myMinimumStep;
876 
877  /// The delimiter between components, if multiple value sequences are
878  /// specified in the same pattern. The default delimiter is a space ' '
879  /// character, For example `1-10 20 30`, but this can be changed in the
880  /// constructor.
881  char myDelimiter;
882 
883  /// Indicates that the pattern has ranges with a variable step size in
884  /// different segments, for example 1-10:0.5 and 2-6:0.3
885  bool myHasVariableStep;
886 
887  /// Indicates whether or not the match is entirely numeric values, or if
888  /// some of the patterns include segments that are non-numeric strings
889  bool myIsNumeric;
890 
891  /// Whether or not at least one of the patterns has an exclusion. We store
892  /// this so that the `match` method can return early if finds a match and
893  /// knows the pattern does not have an exclusion rule in it.
894  bool myHasExclusion;
895 };
896 
897 #endif
bool isNumeric() const
void arrayMap(IntMap &values, bool sorted, bool inclusive) const
GLenum GLint * range
Definition: glcorearb.h:1925
void array(UT_StringArray &values, bool sorted, bool inclusive) const
Returns the array of string values that match the pattern.
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1699
const GLdouble * v
Definition: glcorearb.h:837
GLuint start
Definition: glcorearb.h:475
GLsizei const GLfloat * value
Definition: glcorearb.h:824
#define PDG_API
Definition: PDG_API.h:23
void reset(const UT_StringHolder &pattern)
Resets the pattern.
int64 exint
Definition: SYS_Types.h:125
bool containsRange(UT_FprealArray &range, exint value, bool inclusive) const
SYS_FORCE_INLINE const char * buffer() const
GLuint buffer
Definition: glcorearb.h:660
unsigned char uint8
Definition: SYS_Types.h:36
bool contains(exint value, bool inclusive) const
Checks if the specified integer value is in the pattern.
A utility class to do read-only operations on a subset of an existing string.
Definition: UT_StringView.h:40
GLboolean reset
Definition: glad.h:5138
exint length() const
A generic, discriminated value, whose type may be queried dynamically.
Definition: Value.h:45
bool contains(fpreal value, bool inclusive) const
Checks if the specified float value is in the pattern.
GLuint GLuint end
Definition: glcorearb.h:475
SYS_API fpreal32 SYSfloor(const fpreal32 val)
SYS_FORCE_INLINE const char * c_str() const
void arrayMap(FloatMap &values, bool sorted, bool inclusive) const
void array(UT_FprealArray &values, bool sorted, bool inclusive) const
Returns the array of float values that match the pattern.
GLushort pattern
Definition: glad.h:2583
bool componentRange(UT_FprealArray &range, exint index, bool inclusive) const
Returns the value range for the specified component number.
exint append()
Definition: UT_Array.h:142
fpreal minimumStep() const
Returns the minimum step size from all components in the pattern.
void array(UT_ExintArray &values, bool sorted, bool inclusive) const
Returns the array of integer values that match the pattern.
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1071
bool containsRange(UT_FprealArray &range, fpreal value, bool inclusive) const
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
size_t format(const char *fmt, const Args &...args)
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
fpreal64 fpreal
Definition: SYS_Types.h:283
GLuint index
Definition: glcorearb.h:786
bool contains(const UT_StringHolder &value, bool inclusive) const
Checks if the specified string value is in the pattern.
fpreal componentStep(exint index) const
Returns the step value for the specified component number.
void arrayMap(StringMap &values, bool sorted, bool inclusive) const
void clear()
Resets list to an empty list.
Definition: UT_Array.h:753
bool hasVariableStep() const
Returns true if the pattern has segments with different step sizes.
Definition: format.h:1821