Jamoma API  0.6.0.a19
TTElement.h
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup foundationLibrary
4  *
5  * @brief Jamoma Foundation class for representing values
6  *
7  * @details
8  *
9  * @author Tim Place, Théo de la Hogue, Nathan Wolek, Julien Rabin, Nils Peters, Trond Lossius
10  *
11  * @copyright Copyright © 2008, Timothy Place @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
17 #ifndef __TT_ELEMENT_H__
18 #define __TT_ELEMENT_H__
19 
20 #include "TTBase.h"
21 #include "TTString.h"
22 #include "TTLimits.h"
23 #include "TTSymbol.h"
24 #include "TTSymbolTable.h"
25 #include "TTObject.h"
26 #include "TTMatrix.h"
27 
28 #ifndef DISABLE_NODELIB
29 #include "TTAddress.h"
30 #include "TTAddressTable.h"
31 #include "TTAddressCache.h"
32 #endif
33 
34 #include <cinttypes>
35 class TTDictionary;
36 
37 
38 //#define USE_TTInt32 // to -- To easily change for TTInt32 instead of int in order to make test
39 
40 // macro for converting from one type to another regardless of type
41 #define TTELEMENT_CONVERT switch(mType) {\
42  case kTypeInt8:\
43  value = mValue.int8;\
44  break;\
45  case kTypeUInt8:\
46  value = mValue.uint8;\
47  break;\
48  case kTypeInt16:\
49  value = mValue.int16;\
50  break;\
51  case kTypeUInt16:\
52  value = mValue.uint16;\
53  break;\
54  case kTypeFloat32:\
55  value = mValue.float32;\
56  break;\
57  case kTypeFloat64:\
58  value = mValue.float64;\
59  break;\
60  case kTypeInt32:\
61  value = mValue.int32;\
62  break;\
63  case kTypeUInt32:\
64  value = mValue.uint32;\
65  break;\
66  case kTypeInt64:\
67  value = mValue.int64;\
68  break;\
69  case kTypeUInt64:\
70  value = mValue.uint64;\
71  break;\
72  case kTypeBoolean:\
73  value = mValue.boolean;\
74  break;\
75  case kTypeError:\
76  value = mValue.error;\
77  break;\
78  default:\
79  value = 0;\
80  break;\
81  }
82 
83 
84 /****************************************************************************************************/
85 // Class Specification
86 
87 /** Individual items found in a #TTValue
88  */
89 class TTFOUNDATION_EXPORT TT_ALIGN_16 TTElement {
90  friend class TTDictionary;
91 
92  /** The data value of TTValue is stored using a union, which means that
93  the size of TTDataValue is the size of the largest type in this list.
94 
95  For performance and interoperability we need to align each TTElement on 16-byte boundaries.
96  Therefore we need to be careful to keep the size of TTDataValue + TTDataType to a maximum of 16-bytes.
97 
98  For non-trivial data types we store pointers (8 bytes on 64-bit), but we do so by
99  creating a new instance and making a copy (as done in STL containers).
100  That means also be careful in how we refcount and free these cases.
101 
102  @see http://en.wikipedia.org/wiki/Data_structure_alignment
103 
104  Additionally we can return an error using TTValue.
105  This permits you return a TTValue from a function while still maintaining the ability to return error codes.
106  */
107  union TTDataValue {
108  TTFloat32 float32;
109  TTFloat64 float64;
110  TTInt8 int8;
111  TTUInt8 uint8;
112  TTInt16 int16;
113  TTUInt16 uint16;
114  TTInt32 int32;
115  TTUInt32 uint32;
116  TTInt64 int64;
117  TTUInt64 uint64;
118  TTBoolean boolean;
119  TTSymbol* mSymbol;
120  TTAddress* mAddress;
121  TTString* stringPtr;
122  TTObject* mObject;
123  TTMatrix* mMatrix;
124  TTPtr ptr;
125  TTSymbolBase* dictionary; ///< dictionaries are referenced by name
126  TTErr error;
127  };
128 
129  /* It is _essential_ that the first item is the value itself.
130  This allows us to cast the memory directly to a primitive value (e.g. a double)
131  in performance sensitive code where we don't want to check types or sizes
132  returned by a function.
133  */
134  TTDataValue mValue;
135  TTDataType mType;
136 
137 public:
138 
139  /** We use custom #new and #delete operators for TTElement to ensure that all memory
140  allocated on the heap is aligned on 16-byte boundaries.
141 
142  For memory allocated on the stack we rely on the #TT_ALIGN_16 macro used in the class definition.
143  */
144  void* operator new(size_t size)
145  {
146  void *mem = TTMalloc16(size);
147 
148  if (!mem)
149  throw "allocation fail : no free memory";
150  return mem;
151  }
152 
153 
154  /** We use custom #new and #delete operators for TTElement to ensure that all memory
155  allocated on the heap is aligned on 16-byte boundaries.
156 
157  For memory allocated on the stack we rely on the #TT_ALIGN_16 macro used in the class definition.
158  */
159  void operator delete(void* mem)
160  {
161  TTFree16(mem);
162  }
163 
164 
165  TTElement() :
166  mType(kTypeNone)
167  {
168  mValue.ptr = NULL; // windows doesn't permit using an initializer for a union?
169  }
170 
171  template<class T>
172  TTElement(const T& anInitialValue) :
173  mType(kTypeNone)
174  {
175  *this = anInitialValue;
176  }
177 
178  /** Copy constructor. */
179  TTElement(const TTElement& anOtherElement) :
180  mType(kTypeNone)
181  {
182  *this = anOtherElement;
183  }
184 
185  virtual ~TTElement();
186 
187 private:
188  /** Internal use only: Free memory of the item if it is a non-trivial type. */
189  void chuck()
190  {
191  if (mType == kTypeSymbol)
192  delete mValue.mSymbol;
193  // TODO: JamomaCore #281 : review the use of TTAddress
194  //else if (mType == kTypeAddress)
195  // delete mValue.mAddress;
196  else if (mType == kTypeObject)
197  delete mValue.mObject;
198  mValue.ptr = NULL;
199  mType = kTypeNone;
200  }
201 
202 public:
203  /** query an element for its type */
204  TTDataType type() const
205  {
206  return mType;
207  }
208 
209 #if 0
210 #pragma mark -
211 #pragma mark casting
212 #endif
213 
214  operator TTFloat32() const
215  {
216  if (mType == kTypeFloat32)
217  return mValue.float32;
218  else {
219  TTFloat32 value;
220  TTELEMENT_CONVERT;
221  return value;
222  }
223  }
224 
225  operator TTFloat64() const
226  {
227  if (mType == kTypeFloat64)
228  return mValue.float64;
229  else {
230  TTFloat64 value;
231  TTELEMENT_CONVERT;
232  return value;
233  }
234  }
235 
236  // fast (but less safe) version of the above
237  TTFloat64 float64() const
238  {
239  return mValue.float64;
240  }
241 
242  operator TTInt8() const
243  {
244  if (mType == kTypeInt8)
245  return mValue.int8;
246  else {
247  TTInt8 value;
248  TTELEMENT_CONVERT;
249  return value;
250  }
251  }
252 
253  operator TTUInt8() const
254  {
255  if (mType == kTypeUInt8)
256  return mValue.uint8;
257  else {
258  TTUInt8 value;
259  TTELEMENT_CONVERT;
260  return value;
261  }
262  }
263 
264  operator TTInt16() const
265  {
266  if (mType == kTypeInt16)
267  return mValue.int16;
268  else {
269  TTInt16 value;
270  TTELEMENT_CONVERT;
271  return value;
272  }
273  }
274 
275  operator TTUInt16() const
276  {
277  if (mType == kTypeUInt16)
278  return mValue.uint16;
279  else {
280  TTUInt16 value;
281  TTELEMENT_CONVERT;
282  return value;
283  }
284  }
285 
286  operator TTInt32() const
287  {
288  if (mType == kTypeInt32)
289  return mValue.int32;
290  else {
291  TTInt32 value;
292  TTELEMENT_CONVERT;
293  return value;
294  }
295  }
296 
297  operator TTUInt32() const
298  {
299  if (mType == kTypeUInt32)
300  return mValue.uint32;
301  else {
302  TTUInt32 value;
303  TTELEMENT_CONVERT;
304  return value;
305  }
306  }
307 
308  operator TTInt64() const
309  {
310  if (mType == kTypeInt64)
311  return mValue.int64;
312  else {
313  TTInt64 value;
314  TTELEMENT_CONVERT;
315  return value;
316  }
317  }
318 
319  operator TTUInt64() const
320  {
321  if (mType == kTypeUInt64)
322  return mValue.uint64;
323  else {
324  TTUInt64 value;
325  TTELEMENT_CONVERT;
326  return value;
327  }
328  }
329 
330  operator TTBoolean() const
331  {
332  if (mType == kTypeBoolean)
333  return mValue.boolean;
334  else {
335  // setting as int and then casting after the macro (with the extra logic) is done to silence warnings on MSVC
336  int value;
337  TTELEMENT_CONVERT;
338  return (TTBoolean)(value != 0);
339  }
340  }
341 
342  operator TTSymbol() const
343  {
344  if (mType == kTypeSymbol)
345  return *mValue.mSymbol;
346  else
347  return kTTSymEmpty;
348  }
349 
350 #ifndef DISABLE_NODELIB
351  operator TTAddress() const
352  {
353  // TODO: JamomaCore #281 : review the use of TTAddress
354  //if (mType == kTypeAddress)
355  // return *mValue.mAddress;
356  if (mType == kTypeSymbol)
357  return TTAddress(*mValue.mSymbol);
358  else
359  return kTTAdrsEmpty;
360  }
361 #endif
362 
363  operator TTString() const
364  {
365  TT_ASSERT(ttvalue_cast_to_string_ref, (mType == kTypeString));
366  return *mValue.stringPtr;
367  }
368 
369  // OBJECT
370  operator TTObject() const
371  {
372  TT_ASSERT(ttvalue_cast_to_object, (mType == kTypeObject));
373  return *mValue.mObject;
374  }
375 
376  operator TTMatrix() const
377  {
378  TT_ASSERT(ttvalue_cast_to_matrix, (mType == kTypeMatrix));
379  return *mValue.mMatrix;
380  }
381 
382  operator TTPtr() const
383  {
384  if (mType == kTypePointer)
385  return mValue.ptr;
386  else
387  return NULL;
388  }
389 
390  operator TTErr() const
391  {
392  if (mType == kTypeError)
393  return mValue.error;
394  else
395  return kTTErrNone;
396  }
397 
398  operator TTDictionary() const;
399 
400 
401 #if 0
402 #pragma mark -
403 #pragma mark assignment
404 #endif
405 
406  TTElement& operator = (const TTElement& anOtherValue)
407  {
408  chuck();
409 
410  mType = anOtherValue.mType;
411 
412  if (anOtherValue.mType == kTypeSymbol)
413  mValue.mSymbol = new TTSymbol(*anOtherValue.mValue.mSymbol);
414  // TODO: JamomaCore #281 : review the use of TTAddress
415  //else if (anOtherValue.mType == kTypeAddress)
416  // mValue.mAddress = new TTAddress(*anOtherValue.mValue.mAddress);
417  else if (anOtherValue.mType == kTypeObject)
418  mValue.mObject = new TTObject(*anOtherValue.mValue.mObject);
419  else
420  mValue = anOtherValue.mValue;
421 
422  return *this;
423  }
424 
425  TTElement& operator = (TTFloat32 value)
426  {
427  chuck();
428  mType = kTypeFloat32;
429  mValue.float32 = value;
430  return *this;
431  }
432 
433  TTElement& operator = (TTFloat64 value)
434  {
435  chuck();
436  mType = kTypeFloat64;
437  mValue.float64 = value;
438  return *this;
439  }
440 
441  // fast (but less safe) version of the above
442  void float64(TTFloat64 value)
443  {
444  mType = kTypeFloat64;
445  mValue.float64 = value;
446  }
447 
448  TTElement& operator = (TTInt8 value)
449  {
450  chuck();
451  mType = kTypeInt8;
452  mValue.int8 = value;
453  return *this;
454  }
455 
456  TTElement& operator = (TTUInt8 value)
457  {
458  chuck();
459  mType = kTypeUInt8;
460  mValue.uint8 = value;
461  return *this;
462  }
463 
464  TTElement& operator = (TTInt16 value)
465  {
466  chuck();
467  mType = kTypeInt16;
468  mValue.int16 = value;
469  return *this;
470  }
471 
472  TTElement& operator = (TTUInt16 value)
473  {
474  chuck();
475  mType = kTypeUInt16;
476  mValue.uint16 = value;
477  return *this;
478  }
479 
480  TTElement& operator = (TTInt32 value)
481  {
482  chuck();
483  mType = kTypeInt32;
484  mValue.int32 = value;
485  return *this;
486  }
487 
488  TTElement& operator = (TTUInt32 value)
489  {
490  chuck();
491  mType = kTypeUInt32;
492  mValue.uint32 = value;
493  return *this;
494  }
495 
496  TTElement& operator = (TTInt64 value)
497  {
498  chuck();
499  mType = kTypeInt64;
500  mValue.int64 = value;
501  return *this;
502  }
503 
504  TTElement& operator = (TTUInt64 value)
505  {
506  chuck();
507  mType = kTypeUInt64;
508  mValue.uint64 = value;
509  return *this;
510  }
511 
512  TTElement& operator = (TTBoolean value)
513  {
514  chuck();
515  mType = kTypeBoolean;
516  mValue.boolean = value;
517  return *this;
518  }
519 
520  TTElement& operator = (const char* value)
521  {
522  return *this = TTSymbol(value);
523  }
524 
525  TTElement& operator = (const TTSymbol value)
526  {
527  chuck();
528  mType = kTypeSymbol;
529  mValue.mSymbol = new TTSymbol(value);
530  return *this;
531  }
532 
533 #ifndef DISABLE_NODELIB
534  TTElement& operator = (const TTAddress value)
535  {
536  chuck();
537  // TODO: JamomaCore #281 : review the use of TTAddress
538  //mType = kTypeAddress;
539  mType = kTypeSymbol;
540  // TODO: JamomaCore #281 : review the use of TTAddress
541  //mValue.mAddress = new TTAddress(value);
542  mValue.mSymbol = new TTAddress(value);
543  return *this;
544  }
545 #endif
546 
547  TTElement& operator = (const TTString value)
548  {
549  chuck();
550  // if (!stringsPresent && *type != kTypeString)
551  // data->stringPtr = new TTString;
552  if (mType != kTypeString)
553  mValue.stringPtr = new TTString;
554  mType = kTypeString;
555  // stringsPresent = true;
556  *mValue.stringPtr = value;
557  return *this;
558  }
559 
560  TTElement& operator = (const TTObject value)
561  {
562  chuck();
563  mType = kTypeObject;
564  mValue.mObject = new TTObject(value);
565  return *this;
566  }
567 
568  TTElement& operator = (const TTMatrix value)
569  {
570  chuck();
571  mType = kTypeMatrix;
572  mValue.mMatrix = new TTMatrix(value);
573  return *this;
574  }
575 
576  TTElement& operator = (TTPtr value)
577  {
578  chuck();
579  mType = kTypePointer;
580  mValue.ptr = value;
581  return *this;
582  }
583 
584  TTElement& operator = (TTErr value)
585  {
586  chuck();
587  mType = kTypeError;
588  mValue.error = value;
589  return *this;
590  }
591 
592  // TODO: an assignment to a different type (like the above) will leak the dictionary!
593 
594  TTElement& operator = (const TTDictionary value);
595 
596 
597 #if 0
598 #pragma mark -
599 #pragma mark conversion
600 #endif
601 
602 #define TTELEMENT_TEMP_STRINGLEN 32
603 
604  void string(TTString& aString, TTBoolean quotes = YES) const
605  {
606  char temp[TTELEMENT_TEMP_STRINGLEN];
607  TTBoolean addQuotes;
608 
609 
610  temp[0] = 0;
611 
612  switch (mType) {
613  case kTypeFloat32:
614  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%f", mValue.float32);
615  break;
616  case kTypeFloat64:
617  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%lf", mValue.float64);
618  break;
619  case kTypeInt8:
620  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRId8, mValue.int8);
621  break;
622  case kTypeUInt8:
623  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRIu8 "u", mValue.uint8);
624  break;
625  case kTypeInt16:
626  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRId16, mValue.int16);
627  break;
628  case kTypeUInt16:
629  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRIu16 "u", mValue.uint16);
630  break;
631  case kTypeInt32:
632  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRId32, mValue.int32);
633  break;
634  case kTypeUInt32:
635  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRIu32 "u", mValue.uint32);
636  break;
637  case kTypeInt64:
638  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRId64, mValue.int64);
639  break;
640  case kTypeUInt64:
641  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "%" PRIu64 "u", mValue.uint64);
642  break;
643  case kTypeBoolean:
644  if (mValue.boolean)
645  aString.append("1");
646  else
647  aString.append("0");
648  break;
649  case kTypeSymbol:
650  addQuotes = quotes && strchr(mValue.mSymbol->c_str(), ' ') != 0;
651  if (addQuotes)
652  aString.append("\"");
653  aString.append(mValue.mSymbol->c_str());
654  if (addQuotes)
655  aString.append("\"");
656  break;
657  case kTypeString:
658  aString.append(*mValue.stringPtr);
659  break;
660  case kTypeObject:
661  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "<object %p>", mValue.mObject);
662  break;
663  case kTypePointer:
664  snprintf(temp, TTELEMENT_TEMP_STRINGLEN, "<pointer %p>", mValue.ptr);
665  break;
666  default:
667  break;
668  }
669 
670  if (temp[0])
671  aString.append(temp);
672  }
673 
674 
675 
676  // comparison overloads
677 
678 
679  // make sure this is a friend so that it can access the private members of the other element
680  friend bool operator == (const TTElement& a1, const TTElement& a2)
681  {
682  if (a1.mType != a2.mType)
683  return false;
684  else {
685  switch (a1.mType) {
686  case kTypeInt8:
687  if ( a1.mValue.int8 != a2.mValue.int8 )
688  return false;
689  break;
690  case kTypeUInt8:
691  if ( a1.mValue.uint8 != a2.mValue.uint8 )
692  return false;
693  break;
694  case kTypeInt16:
695  if ( a1.mValue.int16 != a2.mValue.int16 )
696  return false;
697  break;
698  case kTypeUInt16:
699  if ( a1.mValue.uint16 != a2.mValue.uint16 )
700  return false;
701  break;
702  case kTypeInt32:
703  if ( a1.mValue.int32 != a2.mValue.int32 )
704  return false;
705  break;
706  case kTypeUInt32:
707  if ( a1.mValue.uint32 != a2.mValue.uint32 )
708  return false;
709  break;
710  case kTypeInt64:
711  if ( a1.mValue.int64 != a2.mValue.int64 )
712  return false;
713  break;
714  case kTypeUInt64:
715  if ( a1.mValue.uint64 != a2.mValue.uint64 )
716  return false;
717  break;
718  case kTypeFloat32:
719  if ( a1.mValue.float32 != a2.mValue.float32 )
720  return false;
721  break;
722  case kTypeFloat64:
723  if ( a1.mValue.float64 != a2.mValue.float64 )
724  return false;
725  break;
726  case kTypeBoolean:
727  if ( a1.mValue.boolean != a2.mValue.boolean )
728  return false;
729  break;
730  case kTypeSymbol:
731  if ( *a1.mValue.mSymbol != *a2.mValue.mSymbol )
732  return false;
733  break;
734  case kTypeString:
735  if ( *a1.mValue.stringPtr != *a2.mValue.stringPtr )
736  return false;
737  break;
738  case kTypeObject:
739  if ( *a1.mValue.mObject != *a2.mValue.mObject )
740  return false;
741  break;
742  case kTypePointer:
743  if ( a1.mValue.ptr != a2.mValue.ptr )
744  return false;
745  break;
746  case kTypeError:
747  if ( a1.mValue.error != a2.mValue.error )
748  return false;
749  break;
750  default: // the type is not currently handled
751  return false;
752  }
753  }
754  return true;
755  }
756 
757  friend bool operator != (const TTElement& a1, const TTElement& a2)
758  {
759  return !(a1 == a2);
760  }
761 
762  friend bool operator == (const TTElement& a1, const int& i)
763  {
764  switch (a1.mType) {
765  case kTypeInt8:
766  if ( a1.mValue.int8 != i )
767  return false;
768  break;
769  case kTypeUInt8:
770  if ( a1.mValue.uint8 != i )
771  return false;
772  break;
773  case kTypeInt16:
774  if ( a1.mValue.int16 != i )
775  return false;
776  break;
777  case kTypeUInt16:
778  if ( a1.mValue.uint16 != i )
779  return false;
780  break;
781  case kTypeInt32:
782  if ( a1.mValue.int32 != i )
783  return false;
784  break;
785  case kTypeUInt32:
786  {
787  unsigned int tmp = i;
788  if ( a1.mValue.uint32 != tmp )
789  return false;
790  break;
791  }
792  case kTypeInt64:
793  if ( a1.mValue.int64 != i )
794  return false;
795  break;
796  case kTypeUInt64:
797  {
798  long unsigned int tmp = i;
799  if ( a1.mValue.uint64 != tmp )
800  return false;
801  break;
802  }
803  case kTypeError:
804  if ( a1.mValue.error != i )
805  return false;
806  break;
807  default: // the type is not currently handled
808  return false;
809  }
810  return true;
811  }
812 
813  // clang compiler considers TTErr conversion ambiguous so we manually need to overload for this case
814  friend bool operator == (const TTElement& a1, TTErr err)
815  {
816  if (a1.mType == kTypeError && a1.mValue.error == err)
817  return true;
818  else
819  return false;
820  }
821 
822 
823  friend bool operator == (const TTElement& a1, const double& f)
824  {
825  switch (a1.mType) {
826  case kTypeFloat64:
827  if ( a1.mValue.float64 != f )
828  return false;
829  break;
830  case kTypeFloat32:
831  if ( a1.mValue.float32 != f )
832  return false;
833  break;
834  default: // the type is not currently handled
835  return false;
836  }
837  return true;
838  }
839 
840 
841  friend bool operator == (const TTElement& a1, const float& f)
842  {
843  switch (a1.mType) {
844  case kTypeFloat32:
845  if ( a1.mValue.float32 != f )
846  return false;
847  break;
848  case kTypeFloat64:
849  if ( a1.mValue.float64 != f )
850  return false;
851  break;
852  default: // the type is not currently handled
853  return false;
854  }
855  return true;
856  }
857 
858 
859  /**
860  We define the < operator for sorting of linked-list and other STL calls that require sorting ability of TTValue.
861  */
862 
863  // make sure this is a friend so that it can access the private members of the other atom
864  friend bool operator < (const TTElement& a1, const TTElement& a2)
865  {
866  switch(a1.mType) {
867  case kTypeInt8:
868  if ( a1.mValue.int8 >= a2.mValue.int8 )
869  return false;
870  break;
871  case kTypeUInt8:
872  if ( a1.mValue.uint8 >= a2.mValue.uint8 )
873  return false;
874  break;
875  case kTypeInt16:
876  if ( a1.mValue.int16 >= a2.mValue.int16 )
877  return false;
878  break;
879  case kTypeUInt16:
880  if ( a1.mValue.uint16 >= a2.mValue.uint16 )
881  return false;
882  break;
883  case kTypeInt32:
884  if ( a1.mValue.int32 >= a2.mValue.int32 )
885  return false;
886  break;
887  case kTypeUInt32:
888  if ( a1.mValue.uint32 >= a2.mValue.uint32 )
889  return false;
890  break;
891  case kTypeInt64:
892  if ( a1.mValue.int64 >= a2.mValue.int64 )
893  return false;
894  break;
895  case kTypeUInt64:
896  if ( a1.mValue.uint64 >= a2.mValue.uint64 )
897  return false;
898  break;
899  case kTypeFloat32:
900  if ( a1.mValue.float32 >= a2.mValue.float32 )
901  return false;
902  break;
903  case kTypeFloat64:
904  if ( a1.mValue.float64 >= a2.mValue.float64 )
905  return false;
906  break;
907  case kTypeBoolean:
908  if ( a1.mValue.boolean >= a2.mValue.boolean )
909  return false;
910  break;
911  case kTypeSymbol:
912  if ( strcmp( a1.mValue.mSymbol->c_str(), a2.mValue.mSymbol->c_str() ) >= 0 )
913  return false;
914  break;
915  case kTypeString:
916  if ( strcmp( a1.mValue.stringPtr->c_str(), a2.mValue.stringPtr->c_str() ) >= 0 )
917  return false;
918  break;
919  case kTypeObject: // TODO: how should we actually be sorting objects, if at all?
920  if ( a1.mValue.mObject >= a2.mValue.mObject )
921  return false;
922  break;
923  case kTypePointer:
924  if ( a1.mValue.ptr >= a2.mValue.ptr )
925  return false;
926  break;
927  case kTypeError:
928  if ( a1.mValue.error >= a2.mValue.error )
929  return false;
930  break;
931  default:
932  return false;
933  }
934  return true;
935  }
936 
937 
938 #if 0
939 #pragma mark -
940 #pragma mark transformation
941 #endif
942 
943  void clip(const TTFloat64& lowBound, const TTFloat64& highBound)
944  {
945  if (TTDataInfo::getIsNumerical(mType)) {
946  // TODO: find a way to make this routine faster
947  switch (mType) {
948  case kTypeFloat32:
949  TTLimit<TTFloat32>(mValue.float32, lowBound, highBound);
950  break;
951  case kTypeFloat64:
952  TTLimit<TTFloat64>(mValue.float64, lowBound, highBound);
953  break;
954  case kTypeInt8:
955  TTLimit<TTInt8>(mValue.int8, lowBound, highBound);
956  break;
957  case kTypeUInt8:
958  TTLimit<TTUInt8>(mValue.uint8, lowBound, highBound);
959  break;
960  case kTypeInt16:
961  TTLimit<TTInt16>(mValue.int16, lowBound, highBound);
962  break;
963  case kTypeUInt16:
964  TTLimit<TTUInt16>(mValue.uint16, lowBound, highBound);
965  break;
966  case kTypeInt32:
967  TTLimit<TTInt32>(mValue.int32, lowBound, highBound);
968  break;
969  case kTypeUInt32:
970  TTLimit<TTUInt32>(mValue.uint32, lowBound, highBound);
971  break;
972  case kTypeInt64:
973  TTLimit<TTInt64>(mValue.int64, lowBound, highBound);
974  break;
975  case kTypeUInt64:
976  TTLimit<TTUInt64>(mValue.uint64, lowBound, highBound);
977  break;
978  default:
979  break;
980  }
981  }
982  }
983 
984 
985  void cliplow(const TTFloat64& lowBound)
986  {
987  if (TTDataInfo::getIsNumerical(mType)) {
988  // TODO: find a way to make this routine faster
989  switch (mType) {
990  case kTypeFloat32:
991  TTLimitMin<TTFloat32>(mValue.float32, lowBound);
992  break;
993  case kTypeFloat64:
994  TTLimitMin<TTFloat64>(mValue.float64, lowBound);
995  break;
996  case kTypeInt8:
997  TTLimitMin<TTInt8>(mValue.int8, lowBound);
998  break;
999  case kTypeUInt8:
1000  TTLimitMin<TTUInt8>(mValue.uint8, lowBound);
1001  break;
1002  case kTypeInt16:
1003  TTLimitMin<TTInt16>(mValue.int16, lowBound);
1004  break;
1005  case kTypeUInt16:
1006  TTLimitMin<TTUInt16>(mValue.uint16, lowBound);
1007  break;
1008  case kTypeInt32:
1009  TTLimitMin<TTInt32>(mValue.int32, lowBound);
1010  break;
1011  case kTypeUInt32:
1012  TTLimitMin<TTUInt32>(mValue.uint32, lowBound);
1013  break;
1014  case kTypeInt64:
1015  TTLimitMin<TTInt64>(mValue.int64, lowBound);
1016  break;
1017  case kTypeUInt64:
1018  TTLimitMin<TTUInt64>(mValue.uint64, lowBound);
1019  break;
1020  default:
1021  break;
1022  }
1023  }
1024  }
1025 
1026 
1027  void cliphigh(const TTFloat64& highBound)
1028  {
1029  if (TTDataInfo::getIsNumerical(mType)) {
1030  // TODO: find a way to make this routine faster
1031  switch (mType) {
1032  case kTypeFloat32:
1033  TTLimitMax<TTFloat32>(mValue.float32, highBound);
1034  break;
1035  case kTypeFloat64:
1036  TTLimitMax<TTFloat64>(mValue.float64, highBound);
1037  break;
1038  case kTypeInt8:
1039  TTLimitMax<TTInt8>(mValue.int8, highBound);
1040  break;
1041  case kTypeUInt8:
1042  TTLimitMax<TTUInt8>(mValue.uint8, highBound);
1043  break;
1044  case kTypeInt16:
1045  TTLimitMax<TTInt16>(mValue.int16, highBound);
1046  break;
1047  case kTypeUInt16:
1048  TTLimitMax<TTUInt16>(mValue.uint16, highBound);
1049  break;
1050  case kTypeInt32:
1051  TTLimitMax<TTInt32>(mValue.int32, highBound);
1052  break;
1053  case kTypeUInt32:
1054  TTLimitMax<TTUInt32>(mValue.uint32, highBound);
1055  break;
1056  case kTypeInt64:
1057  TTLimitMax<TTInt64>(mValue.int64, highBound);
1058  break;
1059  case kTypeUInt64:
1060  TTLimitMax<TTUInt64>(mValue.uint64, highBound);
1061  break;
1062  default:
1063  break;
1064  }
1065  }
1066  }
1067 
1068 
1069  void fold(const TTFloat64& lowBound, const TTFloat64& highBound)
1070  {
1071  if (TTDataInfo::getIsNumerical(mType)) {
1072  // TODO: find a way to make this routine faster
1073  switch (mType) {
1074  case kTypeFloat32:
1075  TTFold<TTFloat32>(mValue.float32, lowBound, highBound);
1076  break;
1077  case kTypeFloat64:
1078  TTFold<TTFloat64>(mValue.float64, lowBound, highBound);
1079  break;
1080  case kTypeInt8:
1081  TTFold<TTInt8>(mValue.int8, lowBound, highBound);
1082  break;
1083  case kTypeUInt8:
1084  TTFold<TTUInt8>(mValue.uint8, lowBound, highBound);
1085  break;
1086  case kTypeInt16:
1087  TTFold<TTInt16>(mValue.int16, lowBound, highBound);
1088  break;
1089  case kTypeUInt16:
1090  TTFold<TTUInt16>(mValue.uint16, lowBound, highBound);
1091  break;
1092  case kTypeInt32:
1093  TTFold<TTInt32>(mValue.int32, lowBound, highBound);
1094  break;
1095  case kTypeUInt32:
1096  TTFold<TTUInt32>(mValue.uint32, lowBound, highBound);
1097  break;
1098  case kTypeInt64:
1099  TTFold<TTInt64>(mValue.int64, lowBound, highBound);
1100  break;
1101  case kTypeUInt64:
1102  TTFold<TTUInt64>(mValue.uint64, lowBound, highBound);
1103  break;
1104  default:
1105  break;
1106  }
1107  }
1108  }
1109 
1110 
1111  void wrap(const TTFloat64& lowBound, const TTFloat64& highBound)
1112  {
1113  if (TTDataInfo::getIsNumerical(mType)) {
1114  // TODO: find a way to make this routine faster
1115  switch (mType) {
1116  case kTypeFloat32:
1117  TTInfWrap<TTFloat32>(mValue.float32, lowBound, highBound);
1118  break;
1119  case kTypeFloat64:
1120  TTInfWrap<TTFloat64>(mValue.float64, lowBound, highBound);
1121  break;
1122  case kTypeInt8:
1123  TTInfWrap<TTInt8>(mValue.int8, lowBound, highBound);
1124  break;
1125  case kTypeUInt8:
1126  TTInfWrap<TTUInt8>(mValue.uint8, lowBound, highBound);
1127  break;
1128  case kTypeInt16:
1129  TTInfWrap<TTInt16>(mValue.int16, lowBound, highBound);
1130  break;
1131  case kTypeUInt16:
1132  TTInfWrap<TTUInt16>(mValue.uint16, lowBound, highBound);
1133  break;
1134  case kTypeInt32:
1135  TTInfWrap<TTInt32>(mValue.int32, lowBound, highBound);
1136  break;
1137  case kTypeUInt32:
1138  TTInfWrap<TTUInt32>(mValue.uint32, lowBound, highBound);
1139  break;
1140  case kTypeInt64:
1141  TTInfWrap<TTInt64>(mValue.int64, lowBound, highBound);
1142  break;
1143  case kTypeUInt64:
1144  TTInfWrap<TTUInt64>(mValue.uint64, lowBound, highBound);
1145  break;
1146  default:
1147  break;
1148  }
1149  }
1150  }
1151 
1152 
1153  void round()
1154  {
1155  if (TTDataInfo::getIsNumerical(mType)) {
1156  // TODO: find a way to make this routine faster
1157  switch (mType) {
1158  case kTypeFloat32:
1159  mValue.float32 = (TTFloat32)TTRound(mValue.float32);
1160  break;
1161  case kTypeFloat64:
1162  mValue.float64 = TTRound(mValue.float64);
1163  break;
1164  case kTypeInt8:
1165  mValue.int8 = (TTInt8)TTRound(mValue.int8);
1166  break;
1167  case kTypeUInt8:
1168  mValue.uint8 = (TTUInt8)TTRound(mValue.uint8);
1169  break;
1170  case kTypeInt16:
1171  mValue.int16 = (TTInt16)TTRound(mValue.int16);
1172  break;
1173  case kTypeUInt16:
1174  mValue.uint16 = (TTUInt16)TTRound(mValue.uint16);
1175  break;
1176  case kTypeInt32:
1177  mValue.int32 = TTRound(mValue.int32);
1178  break;
1179  case kTypeUInt32:
1180  mValue.uint32 = TTRound(mValue.uint32);
1181  break;
1182  case kTypeInt64:
1183  mValue.int64 = TTRound(mValue.int64);
1184  break;
1185  case kTypeUInt64:
1186  mValue.uint64 = TTRound(mValue.uint64);
1187  break;
1188  default:
1189  break;
1190  }
1191  }
1192  }
1193 
1194 
1195  void truncate()
1196  {
1197  if (TTDataInfo::getIsNumerical(mType)) {
1198  // TODO: find a way to make this routine faster
1199  switch (mType) {
1200  case kTypeFloat32:
1201  mValue.int32 = (TTInt32)mValue.float32;
1202  mType = kTypeInt32;
1203  break;
1204  case kTypeFloat64:
1205  mValue.int32 = (TTInt32)mValue.float64;
1206  mType = kTypeInt32;
1207  break;
1208  default:
1209  break;
1210  }
1211  }
1212  }
1213 
1214 
1215  void booleanize()
1216  {
1217  if (TTDataInfo::getIsNumerical(mType)) {
1218  // TODO: find a way to make this routine faster
1219  switch (mType) {
1220  case kTypeFloat32:
1221  mValue.boolean = mValue.float32 != 0.;
1222  mType = kTypeBoolean;
1223  break;
1224  case kTypeFloat64:
1225  mValue.boolean = mValue.float64 != 0;
1226  mType = kTypeBoolean;
1227  break;
1228  case kTypeInt8:
1229  mValue.boolean = mValue.int8 != 0;
1230  mType = kTypeBoolean;
1231  break;
1232  case kTypeUInt8:
1233  mValue.boolean = mValue.uint8 != 0;
1234  mType = kTypeBoolean;
1235  break;
1236  case kTypeInt16:
1237  mValue.boolean = mValue.int16 != 0;
1238  mType = kTypeBoolean;
1239  break;
1240  case kTypeUInt16:
1241  mValue.boolean = mValue.uint16 != 0;
1242  mType = kTypeBoolean;
1243  break;
1244  case kTypeInt32:
1245  mValue.boolean = mValue.int32 != 0;
1246  mType = kTypeBoolean;
1247  break;
1248  case kTypeUInt32:
1249  mValue.boolean = mValue.uint32 != 0;
1250  mType = kTypeBoolean;
1251  break;
1252  case kTypeInt64:
1253  mValue.boolean = mValue.int64 != 0;
1254  mType = kTypeBoolean;
1255  break;
1256  case kTypeUInt64:
1257  mValue.boolean = mValue.uint64 != 0;
1258  mType = kTypeBoolean;
1259  break;
1260  default:
1261  break;
1262  }
1263  }
1264  }
1265 
1266 };
1267 
1268 
1269 typedef std::vector<TTElement> TTElementVector;
1270 typedef TTElementVector::iterator TTElementIter;
1271 
1272 
1273 #endif // __TT_ELEMENT_H__
1274 
TTDataType type() const
query an element for its type
Definition: TTElement.h:204
An instance of a TTMatrix object.
Definition: TTBase.h:287
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
void TTFOUNDATION_EXPORT TTFree16(TTPtr ptr)
Free memory allocated using TTMalloc16().
Definition: TTBase.cpp:647
Limiting and Constraining Utilities.
Create Jamoma object instances.
std::uint64_t TTUInt64
64 bit unsigned integer
Definition: TTBase.h:180
bool TTFOUNDATION_EXPORT operator!=(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for inequality.
Definition: TTObject.cpp:173
8-bit unsigned integer, range is 0 through 255.
Definition: TTBase.h:274
Object type.
Definition: TTBase.h:283
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Definition: TTAddress.h:29
Create and use Jamoma object instances.
Definition: TTObject.h:29
64-bit unsigned integer, range is 0 through 18,446,744,073,709,551,615.
Definition: TTBase.h:280
TTPtr TTFOUNDATION_EXPORT TTMalloc16(size_t numBytes)
Allocate memory from the heap aligned to 16-byte boundaries.
Definition: TTBase.cpp:641
TTDataType
TTBlue Data Types Enumeration of data types used through out TTBlue, including the TTValue class and ...
Definition: TTBase.h:269
The TTSymbolBase class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbolBase.h:28
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
16-bit unsigned integer, range is 0 through 65,535.
Definition: TTBase.h:276
An error represented by TTErr.
Definition: TTBase.h:289
A type that represents the key as a C-String and the value as a pointer to the matching TTSymbol obje...
Definition: TTDictionary.h:47
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
std::int64_t TTInt64
64 bit signed integer
Definition: TTBase.h:179
std::int16_t TTInt16
16 bit signed integer
Definition: TTBase.h:175
#define TT_ALIGN_16
Supress warnings about use of deprecated methods.
Definition: TTBase.h:157
16-bit signed integer, range is −32,768 through 32,767.
Definition: TTBase.h:275
64-bit floating point
Definition: TTBase.h:272
Jamoma's lowest-level base class and related infrastructure.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
float TTFloat32
32 bit floating point number
Definition: TTBase.h:187
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
bool TTFOUNDATION_EXPORT operator==(const TTObject &anObject, const TTObject &anotherObject)
Compare two objects for equality.
Definition: TTObject.cpp:167
Individual items found in a TTValue.
Definition: TTElement.h:89
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
Wrap TTMatrixBase instances.
Definition: TTMatrix.h:27
64-bit signed integer, ragne is −9,223,372,036,854,775,808 through 9,223,372,036,854,775,807
Definition: TTBase.h:279
32-bit floating point
Definition: TTBase.h:271
TTMatrix wraps a TTMatrixBase for use.
TTElement(const TTElement &anOtherElement)
Copy constructor.
Definition: TTElement.h:179
32-bit signed integer, range is -2,147,483,648 through 2,147,483,647.
Definition: TTBase.h:277
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
signed char TTInt8
8 bit signed integer (char)
Definition: TTBase.h:173
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
void append(const char *str, size_t length=0)
Append / Concatenate.
Definition: TTString.h:196
Pointer type.
Definition: TTBase.h:284
32-bit unsigned integer, range is 0 through 4,294,967,295.
Definition: TTBase.h:278
8-bit signed integer, range is -128 through 127.
Definition: TTBase.h:273
No Error.
Definition: TTBase.h:343
The TTString class is used to represent a string.
Definition: TTString.h:34
String type.
Definition: TTBase.h:285
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174