xsens_imu
xsens_list.hpp
Go to the documentation of this file.
1 
23 #ifndef _XSENS_LIST_HPP_2006_06_08
24 #define _XSENS_LIST_HPP_2006_06_08
25 
26 #ifndef _XSENS_LIST_H_2006_06_08
27 # include "xsens_list.h"
28 #endif
29 
30 #ifdef _XSENS_LIST_IO
31 # include <iostream>
32 #endif
33 #include <stdlib.h>
34 #include <malloc.h>
35 
36 namespace xsens {
37 
38 #define CMT_LIST_LINEAR_SEARCH_TRESHOLD 10
39 
40 template <typename T>
42 {
43  m_max = 16;
44  m_count = 0;
45  m_data = (T*) malloc(m_max * sizeof(T));
46 // _ASSERT((void*) m_data != (void*) 0x00392E90);
47  m_jcf = NULL;
48  m_manage = true;
49 }
50 
51 template <typename T>
52 List<T>::List(uint32_t size)
53 {
54  m_max = size;
55  if (m_max == 0)
56  m_max = 1;
57  m_count = 0;
58  m_data = (T*) malloc(m_max * sizeof(T));
59  m_jcf = NULL;
60  m_manage = true;
61 }
62 
63 template <typename T>
64 List<T>::List(const List<T>& src)
65 {
66  m_max = src.m_max;
67  if (m_max == 0)
68  m_max = 1;
69  m_count = src.m_count;
70  m_data = (T*) malloc(m_max * sizeof(T));
71  m_jcf = NULL;
72  if (m_count > 0)
73  memcpy(m_data,src.m_data,m_count*sizeof(T));
74  m_manage = true;
75 }
76 
77 template <typename T>
78 List<T>::List(const uint32_t size, const T* src)
79 {
80  m_max = size;
81  if (m_max == 0)
82  m_max = 1;
83  m_count = size;
84  m_data = (T*) malloc(m_max * sizeof(T));
85  m_jcf = NULL;
86  if (m_count > 0)
87  memcpy(m_data,src,m_count * sizeof(T));
88  m_manage = true;
89 }
90 
91 template <typename T>
92 List<T>::List(const uint32_t size, T* src, bool manage)
93 {
94  m_max = size;
95  m_count = size;
96  m_data = src;
97  m_jcf = NULL;
98  m_manage = manage;
99 }
100 
101 template <typename T>
103 {
104  if (m_jcf != NULL)
105  delete m_jcf;
106  if (m_manage && m_data != NULL)
107  free(m_data);
108  m_jcf = NULL;
109  m_data = NULL;
110 }
111 
112 template <typename T>
113 void List<T>::deleteAndClear(void)
114 {
115  for (unsigned i=0;i<m_count;++i)
116  delete m_data[i];
117  m_count = 0;
118 }
119 
120 template <typename T>
121 void List<T>::freeAndClear(void)
122 {
123  for (unsigned i=0;i<m_count;++i)
124  free(m_data[i]);
125  m_count = 0;
126 }
127 
128 template <typename T>
129 void List<T>::clear(void)
130 {
131  m_count = 0;
132 }
133 
134 template <typename T>
135 void List<T>::resize(uint32_t newSize)
136 {
137  if (m_manage)
138  {
139  if (newSize == m_max)
140  return;
141  if (m_count > newSize)
142  m_max = m_count;
143  else
144  m_max = newSize;
145  if (m_max == 0)
146  m_max = 1; // size 0 is not allowed
147 
148  m_data = (T*) realloc(m_data,m_max * sizeof(T));
149  }
150 }
151 
152 template <typename T>
153 void List<T>::append(const T& item)
154 {
155  if (m_count == m_max)
156  resize(m_max + 1 + m_max/2);
157  m_data[m_count++] = item;
158 }
159 
160 template <typename T>
161 void List<T>::appendList(uint32_t count, const T* lst)
162 {
163  if (m_count+count > m_max)
164  resize(m_max + count + m_max/2);
165  for (unsigned i = 0; i < count; ++i)
166  m_data[m_count++] = lst[i];
167 }
168 
169 template <typename T>
170 void List<T>::appendDeepCopy(const List<T>& source)
171 {
172  if (m_max < source.m_count + m_count)
173  resize(source.m_count + m_count);
174 
175  for (uint32_t i = 0;i<source.m_count;++i)
176  m_data[m_count++] = new T(*source.m_data[i]);
177 }
178 
179 template <typename T>
180 void List<T>::appendShallowCopy(const List<T>& source)
181 {
182  if (m_max < source.m_count + m_count)
183  resize(source.m_count + m_count);
184 
185  for (uint32_t i = 0;i<source.m_count;++i)
186  m_data[m_count++] = source.m_data[i];
187 }
188 
189 template <typename T>
190 template <typename TB>
191 void List<T>::appendCopy(const TB& item)
192 {
193  if (m_count == m_max)
194  resize(m_max + 1 + m_max/2);
195  m_data[m_count++] = new TB(item);
196 }
197 
198 template <typename T>
199 template <typename TR>
200 void List<T>::appendRelated(const TR& item)
201 {
202  if (m_count == m_max)
203  resize(m_max + 1 + m_max/2);
204  m_data[m_count++] = item;
205 }
206 
207 template <typename T>
208 T& List<T>::last(void) const XSENS_LIST_THROW
209 {
210  #ifdef _XSENS_LIST_RANGE_CHECKS
211  if (m_count == 0)
212  throw "List.last: empty list";
213  #endif
214  return m_data[m_count-1];
215 }
216 
217 template <typename T>
218 T& List<T>::get(const uint32_t index) const XSENS_LIST_THROW
219 {
220  #ifdef _XSENS_LIST_RANGE_CHECKS
221  if (index >= m_count)
222  throw "List.get: index out of bounds";
223  #endif
224  if (index >= m_count)
225  return m_data[m_count-1];
226  return m_data[index];
227 }
228 
229 template <typename T>
230 void List<T>::insert(const T& item, const uint32_t index)
231 {
232  if (m_count == m_max)
233  resize(1 + m_max + (m_max >> 1));
234  for (unsigned i=m_count;i>index;--i)
235  m_data[i] = m_data[i-1];
236  if (index <= m_count)
237  m_data[index] = item;
238  else
239  m_data[m_count] = item;
240  m_count++;
241 }
242 
243 template <typename T>
244 template <typename TB>
245 void List<T>::insertCopy(const TB& item, const uint32_t index)
246 {
247  if (m_count == m_max)
248  resize(1 + m_max + (m_max >> 1));
249  for (unsigned i=m_count;i>index;--i)
250  m_data[i] = m_data[i-1];
251  if (index <= m_count)
252  m_data[index] = new TB(item);
253  else
254  m_data[m_count] = new TB(item);
255  m_count++;
256 }
257 
258 template <typename T>
259 T& List<T>::operator [] (const uint32_t index) const XSENS_LIST_THROW
260 {
261  #ifdef _XSENS_LIST_RANGE_CHECKS
262  if (index >= m_count)
263  throw "List[]: index out of bounds";
264  #endif
265  return m_data[index];
266 }
267 
268 #if defined(_XSENS_LIST_WITH_MATH) && defined(_XSENS_LIST_IO)
269 
270 template <typename T>
271 std::ostream& operator << (std::ostream& os, List<T>& t)
272 {
273  os << '[' << t.length() << "]{ ";
274  for (unsigned i=0 ; i<t.length() ; ++i)
275  os << t[i] << " ";
276  os << '}';
277  return os;
278 }
279 
280 #ifndef _CMTMATLABHEADERS
281 #define _CMTMATLABHEADERS
282  struct MatlabFileHeader {
283  char description[116];
284  int32_t data_offset1;
285  int32_t data_offset2;
286  int16_t version;
287  int16_t endian;
288  };
289 
290  struct MatlabDataHeader {
291  int32_t data_type;
292  int32_t n_bytes;
293  };
294 
295  struct MatlabMatrixHeader {
296  int32_t flags_data_type;
297  int32_t flags_data_size;
298  int32_t flags0,flags1;
299 
300  int32_t dimensions_data_type;
301  int32_t dimensions_data_size;
302  int32_t dimensions_m, dimensions_n;
303 
304  int32_t name_type;
305  int32_t name_length;
306  };
307 #endif
308 
310 template <typename T>
311 void List<T>::saveAsMatlab(const char* filename, const char *varname) const
312 {
313  // new header
314 
315  size_t i, j;
316  MatlabFileHeader file_header;
317  MatlabMatrixHeader matrix_header;
318  int32_t name_pad;
319  MatlabDataHeader inner_header;
320  MatlabDataHeader outer_header;
321 
322  FILE* fp = fopen(filename,"wb");
323  if (fp == NULL)
324  return;
325 
326  strcpy(file_header.description,"cmtMath/Xsens");
327  for (i = strlen(file_header.description); i <116; ++i)
328  file_header.description[i] = ' ';
329  file_header.data_offset1 = 0;
330  file_header.data_offset2 = 0;
331  file_header.version = 0x0100;
332  file_header.endian = (int16_t) 'M' << 8 | 'I';
333 
334  //matlab mat;
335 
336  matrix_header.flags_data_type = 6;
337  matrix_header.flags_data_size = 8;
338  matrix_header.flags0 = 6; // mxDOUBLE_CLASS (double precision array)
339  matrix_header.flags1 = 0;
340  matrix_header.dimensions_data_type = 5;
341  matrix_header.dimensions_data_size = 8;
342  matrix_header.dimensions_m = m_count;
343  matrix_header.dimensions_n = m_data[0]->size();
344  matrix_header.name_type = 1;
345 
346  if ( varname == (char *)NULL )
347  matrix_header.name_length = 0;
348  else
349  matrix_header.name_length = (int32_t) strlen(varname);
350 
351  name_pad = matrix_header.name_length & 7;
352 
353  inner_header.data_type = 9; // double
354  inner_header.n_bytes = sizeof(double) * m_count * matrix_header.dimensions_n;
355 
356  outer_header.data_type = 14;
357  outer_header.n_bytes = sizeof(matrix_header) + matrix_header.name_length + name_pad
358  + sizeof(MatlabDataHeader) + inner_header.n_bytes;
359 
360  fwrite((char*) &file_header,sizeof(MatlabFileHeader),1,fp);
361  fwrite((char*) &outer_header,sizeof(MatlabDataHeader),1,fp);
362  fwrite((char*) &matrix_header,sizeof(MatlabMatrixHeader),1,fp);
363  fwrite(varname,sizeof(char),matrix_header.name_length,fp);
364 
365  if (name_pad != 0)
366  fwrite("\0\0\0\0\0\0\0",sizeof(char),8-name_pad,fp);
367 
368  fwrite((char*) &inner_header,sizeof(MatlabDataHeader),1,fp);
369 
370  // write actual data
371  // column major order: ORDER == COL_ORDER
372  double tmp;
373  for ( j = 0; j < (size_t) matrix_header.dimensions_n; j++ )
374  for ( i = 0; i < m_count; i++ )
375  {
376  tmp = (*m_data[i])[(unsigned)j];
377  fwrite(&tmp,sizeof(double),1,fp);
378  }
379 
380  fclose(fp);
381 }
382 #endif // _XSENS_LIST_WITH_MATH && _XSENS_LIST_IO
383 
384 template <typename T>
385 void List<T>::qSort(uint32_t left, uint32_t right)
386 {
387  uint32_t l_hold, r_hold;
388  T pivot;
389 
390  l_hold = left;
391  r_hold = right;
392  pivot = m_data[left];
393  while (left < right)
394  {
395  while (!(m_data[right] < pivot) && (left < right))
396  right--;
397  if (left != right)
398  {
399  m_data[left] = m_data[right];
400  left++;
401  }
402  while (!(pivot < m_data[left]) && (left < right))
403  left++;
404  if (!(left == right))
405  {
406  m_data[right] = m_data[left];
407  right--;
408  }
409  }
410  m_data[left] = pivot;
411  if (l_hold < left)
412  qSort(l_hold, left-1);
413  if (r_hold > left)
414  qSort(left+1, r_hold);
415 }
416 
417 template <typename T>
418 void List<T>::qSortDeref(uint32_t left, uint32_t right)
419 {
420  uint32_t l_hold, r_hold;
421  T pivot;
422 
423  l_hold = left;
424  r_hold = right;
425  pivot = m_data[left];
426  while (left < right)
427  {
428  while (!(*m_data[right] < *pivot) && (left < right))
429  right--;
430  if (left != right)
431  {
432  m_data[left] = m_data[right];
433  left++;
434  }
435  while (!(*pivot < *m_data[left]) && (left < right))
436  left++;
437  if (!(left == right))
438  {
439  m_data[right] = m_data[left];
440  right--;
441  }
442  }
443  m_data[left] = pivot;
444  if (l_hold < left)
445  qSortDeref(l_hold, left-1);
446  if (r_hold > left)
447  qSortDeref(left+1, r_hold);
448 }
449 
450 //#define XSENS_LIST_QSORT
451 //#define XSENS_LIST_COMBSORT
452 #define XSENS_LIST_JOBSORT
453 // when nothing is defined, bubble sort is used
454 
455 template <typename T>
456 void List<T>::sortAscending(void)
457 {
458  if (m_count <= 1)
459  return;
460 #if defined(XSENS_LIST_QSORT)
461  qSort(0,m_count-1);
462 #elif defined(XSENS_LIST_COMBSORT)
463 
464  uint32_t gap = m_count;
465  double dgap;
466  uint32_t swaps = 0;
467  T temp;
468 
469  while (gap > 1 || swaps > 0)
470  {
471  if (gap > 1)
472  {
473  dgap = floor(((double) gap) / 1.247330950103979);
474  gap = (uint32_t) dgap;
475  if (gap == 10 || gap == 9)
476  gap = 11;
477  }
478 
479  uint32_t gappedCount = m_count-gap;
480  swaps = 0;
481  for (uint32_t i = 0; i < gappedCount; ++i)
482  {
483  if (m_data[i] > m_data[i+gap])
484  {
485  temp = m_data[i];
486  m_data[i] = m_data[i+gap];
487  m_data[i+gap] = temp;
488  ++swaps;
489  }
490  }
491  }
492 #elif defined(XSENS_LIST_JOBSORT)
493  struct Linker {
494  Linker *prev, *next;
495  uint32_t index;
496 
497  T item;
498  };
499 
500  Linker* list = (Linker*) malloc(m_count*sizeof(Linker));
501 
502  list[0].prev = NULL;
503  list[0].next = NULL;
504  list[0].index = 0;
505  list[0].item = m_data[0];
506 
507  Linker* curr = list;
508 
509  for (uint32_t i = 1; i < m_count; ++i)
510  {
511  list[i].index = i;
512  list[i].item = m_data[i];
513  if (m_data[i] < m_data[curr->index])
514  {
515  while (curr->prev != NULL)
516  {
517  curr = curr->prev;
518  if (!(m_data[i] < m_data[curr->index]))
519  {
520  // insert after this
521  list[i].next = curr->next;
522  list[i].prev = curr;
523  curr->next->prev = &list[i];
524  curr->next = &list[i];
525  curr = &list[i];
526  break;
527  }
528  }
529  if (curr != &list[i])
530  {
531  list[i].prev = NULL;
532  list[i].next = curr;
533  curr->prev = &list[i];
534  curr = &list[i];
535  }
536  }
537  else
538  {
539  while (curr->next != NULL)
540  {
541  curr = curr->next;
542  if (m_data[i] < m_data[curr->index])
543  {
544  // insert before this
545  list[i].next = curr;
546  list[i].prev = curr->prev;
547  curr->prev->next = &list[i];
548  curr->prev = &list[i];
549  curr = &list[i];
550  break;
551  }
552  }
553  if (curr != &list[i])
554  {
555  list[i].prev = curr;
556  list[i].next = NULL;
557  curr->next = &list[i];
558  curr = &list[i];
559  }
560  }
561  }
562 
563  // go to start of list
564  while (curr->prev != NULL) curr = curr->prev;
565 
566  // copy sorted list back
567  for (uint32_t i = 0; i < m_count; ++i)
568  {
569  m_data[i] = curr->item;
570  curr = curr->next;
571  }
572 
573  free(list);
574 #else
575  uint32_t swaps;
576  T temp;
577 
578  for (uint32_t i = 1; i < m_count; ++i)
579  {
580  swaps = 0;
581  for (uint32_t j = end-1; j >= i; --j)
582  {
583  if (m_data[j] < m_data[j-1])
584  {
585  temp = m_data[j];
586  m_data[j] = m_data[j-1];
587  m_data[j-1] = temp;
588  ++swaps;
589  }
590  }
591  if (swaps == 0)
592  break;
593  }
594 #endif
595 }
596 
597 template <typename T>
599 {
600  if (m_count <= 1)
601  return;
602 #if defined(XSENS_LIST_QSORT)
603  qSortDeref(0,m_count-1);
604 #elif defined(XSENS_LIST_COMBSORT)
605 
606  uint32_t gap = m_count;
607  double dgap;
608  uint32_t swaps = 0;
609  T temp;
610 
611  while (gap > 1 || swaps > 0)
612  {
613  if (gap > 1)
614  {
615  dgap = floor(((double) gap) / 1.247330950103979);
616  gap = (uint32_t) dgap;
617  if (gap == 10 || gap == 9)
618  gap = 11;
619  }
620 
621  uint32_t gappedCount = m_count-gap;
622  swaps = 0;
623  for (uint32_t i = 0; i < gappedCount; ++i)
624  {
625  if (*m_data[i+gap] < *m_data[i])
626  {
627  temp = m_data[i];
628  m_data[i] = m_data[i+gap];
629  m_data[i+gap] = temp;
630  ++swaps;
631  }
632  }
633  }
634 #elif defined(XSENS_LIST_JOBSORT)
635  struct Linker {
636  Linker *prev, *next;
637  uint32_t index;
638 
639  T item;
640  };
641 
642  Linker* list = (Linker*) malloc(m_count*sizeof(Linker));
643 
644  list[0].prev = NULL;
645  list[0].next = NULL;
646  list[0].index = 0;
647  list[0].item = m_data[0];
648 
649  Linker* curr = list;
650 
651  for (uint32_t i = 1; i < m_count; ++i)
652  {
653  list[i].index = i;
654  list[i].item = m_data[i];
655  if (*m_data[i] < *m_data[curr->index])
656  {
657  while (curr->prev != NULL)
658  {
659  curr = curr->prev;
660  if (!(*m_data[i] < *m_data[curr->index]))
661  {
662  // insert after this
663  list[i].next = curr->next;
664  list[i].prev = curr;
665  curr->next->prev = &list[i];
666  curr->next = &list[i];
667  curr = &list[i];
668  break;
669  }
670  }
671  if (curr != &list[i])
672  {
673  list[i].prev = NULL;
674  list[i].next = curr;
675  curr->prev = &list[i];
676  curr = &list[i];
677  }
678  }
679  else
680  {
681  while (curr->next != NULL)
682  {
683  curr = curr->next;
684  if (*m_data[i] < *m_data[curr->index])
685  {
686  // insert before this
687  list[i].next = curr;
688  list[i].prev = curr->prev;
689  curr->prev->next = &list[i];
690  curr->prev = &list[i];
691  curr = &list[i];
692  break;
693  }
694  }
695  if (curr != &list[i])
696  {
697  list[i].prev = curr;
698  list[i].next = NULL;
699  curr->next = &list[i];
700  curr = &list[i];
701  }
702  }
703  }
704 
705  // go to start of list
706  while (curr->prev != NULL) curr = curr->prev;
707 
708  // copy sorted list back
709  for (uint32_t i = 0; i < m_count; ++i)
710  {
711  m_data[i] = curr->item;
712  curr = curr->next;
713  }
714 
715  free(list);
716 #else
717  uint32_t swaps;
718  T temp;
719 
720  for (uint32_t i = 1; i < m_count; ++i)
721  {
722  swaps = 0;
723  for (uint32_t j = end-1; j >= i; --j)
724  {
725  if (*(m_data[j]) < *(m_data[j-1]))
726  {
727  temp = m_data[j];
728  m_data[j] = m_data[j-1];
729  m_data[j-1] = temp;
730  ++swaps;
731  }
732  }
733  if (swaps == 0)
734  break;
735  }
736 #endif
737 }
738 
739 template <typename T>
740 template <typename T2>
741 void List<T>::twinSortAscending(List<T2>& twin)
742 {
743  if (m_count <= 1)
744  return;
745 
746  #ifdef _XSENS_LIST_RANGE_CHECKS
747  if (m_count != twin.m_count)
748  throw "List.twinSortAscending: sizes do not match";
749  #endif
750  uint32_t iteration = 0;
751  uint32_t mini;
752  T tmp;
753  T2 tmp2;
754  if (m_count > 1)
755  while (iteration < m_count-1)
756  {
757  mini = iteration;
758  for (uint32_t i=iteration+1;i<m_count;++i)
759  {
760  if (m_data[i] < m_data[mini])
761  mini = i;
762  }
763  if (mini != iteration)
764  {
765  tmp = m_data[mini];
766  m_data[mini] = m_data[iteration];
767  m_data[iteration] = tmp;
768 
769  tmp2 = twin.m_data[mini];
770  twin.m_data[mini] = twin.m_data[iteration];
771  twin.m_data[iteration] = tmp2;
772  }
773  ++iteration;
774  }
775 }
776 
777 template <typename T>
778 void List<T>::remove(const uint32_t index) XSENS_LIST_THROW
779 {
780  #ifdef _XSENS_LIST_RANGE_CHECKS
781  if (index >= m_count)
782  throw "List.remove: index out of bounds";
783  #endif
784  if (index == m_count-1)
785  {
786  --m_count;
787  return;
788  }
789  --m_count;
790  for (unsigned i = index;i < m_count;++i)
791  m_data[i] = m_data[i+1];
792 }
793 
794 template <typename T>
795 void List<T>::removeTail(const uint32_t count) XSENS_LIST_THROW
796 {
797  #ifdef _XSENS_LIST_RANGE_CHECKS
798  if (count > m_count)
799  throw "List.removeTail: list size less than remove count";
800  #endif
801  if (m_count > count)
802  {
803  m_count -= count;
804  return;
805  }
806  m_count = 0;
807 }
808 
809 template <typename T>
810 void List<T>::deleteAndRemoveTail(const uint32_t count) XSENS_LIST_THROW
811 {
812  #ifdef _XSENS_LIST_RANGE_CHECKS
813  if (count > m_count)
814  throw "List.deleteAndRemoveTail: list size less than remove count";
815  #endif
816  if (m_count > count)
817  {
818  for (unsigned i = 0;i < count;++i)
819  delete m_data[--m_count];
820  return;
821  }
822  deleteAndClear();
823 }
824 
825 template <typename T>
826 void List<T>::freeAndRemoveTail(const uint32_t count) XSENS_LIST_THROW
827 {
828  #ifdef _XSENS_LIST_RANGE_CHECKS
829  if (count > m_count)
830  throw "List.freeAndRemoveTail: list size less than remove count";
831  #endif
832  if (m_count > count)
833  {
834  for (unsigned i = 0;i < count;++i)
835  free(m_data[--m_count]);
836  return;
837  }
838  freeAndClear();
839 }
840 
841 template <typename T>
842 uint32_t List<T>::removeDuplicateEntries(void)
843 {
844  uint32_t removed = 0;
845  for (uint32_t i=0;i < m_count; ++i)
846  {
847  for (uint32_t j=i+1;j < m_count; ++j)
848  {
849  if (m_data[i] == m_data[j])
850  {
851  remove(j);
852  ++removed;
853  --j;
854  }
855  }
856  }
857  return removed;
858 }
859 
860 template <typename T>
862 {
863  uint32_t removed = 0;
864  for (uint32_t i=0;i < m_count; ++i)
865  {
866  for (uint32_t j=i+1;j < m_count; ++j)
867  {
868  if (*(m_data[i]) == *(m_data[j]))
869  {
870  remove(j);
871  ++removed;
872  --j;
873  }
874  }
875  }
876  return removed;
877 }
878 
879 template <typename T>
880 void List<T>::deleteAndRemove(const uint32_t index) XSENS_LIST_THROW
881 {
882  #ifdef _XSENS_LIST_RANGE_CHECKS
883  if (index >= m_count)
884  throw "List.deleteAndRemove: index out of bounds";
885  #endif
886  delete m_data[index];
887  if (index == m_count-1)
888  {
889  --m_count;
890  return;
891  }
892  --m_count;
893  for (unsigned i = index;i < m_count;++i)
894  m_data[i] = m_data[i+1];
895 }
896 
897 template <typename T>
898 void List<T>::freeAndRemove(const uint32_t index) XSENS_LIST_THROW
899 {
900  #ifdef _XSENS_LIST_RANGE_CHECKS
901  if (index >= m_count)
902  throw "List.freeAndRemove: index out of bounds";
903  #endif
904  free(m_data[index]);
905  if (index == m_count-1)
906  {
907  --m_count;
908  return;
909  }
910  --m_count;
911  for (unsigned i = index;i < m_count;++i)
912  m_data[i] = m_data[i+1];
913 }
914 
915 template <typename T>
916 template <typename TB>
917 uint32_t List<T>::find(const TB& item) const
918 {
919  for (uint32_t i=0;i<m_count;++i)
920  if (((const T*)m_data)[i] == item)
921  return i;
922  return XSENS_LIST_NOTFOUND;
923 }
924 
925 template <typename T>
926 uint32_t List<T>::find(const T item, InequalityFunction fnc) const
927 {
928  for (uint32_t i=0;i<m_count;++i)
929  if (!fnc(m_data[i],item))
930  return i;
931  return XSENS_LIST_NOTFOUND;
932 }
933 
934 template <typename T>
935 template <typename TB>
936 uint32_t List<T>::findDeref(const TB& item) const
937 {
938  for (uint32_t i=0;i<m_count;++i)
939  if (*(m_data[i]) == item)
940  return i;
941  return XSENS_LIST_NOTFOUND;
942 }
943 
944 template <typename T>
945 template <typename TB>
946 uint32_t List<T>::findSorted(const TB& item) const
947 {
948  if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) // for small lists, it is faster to simply walk the list
949  return find(item);
950 
951  uint32_t x = m_count;
952  uint32_t n = 1;
953  uint32_t i;
954 
955  while(x >= n)
956  {
957  i = (x + n) >> 1;
958 
959  if (m_data[i-1] == item)
960  return i-1;
961  if (m_data[i-1] < item)
962  n = i+1;
963  else
964  x = i-1;
965  }
966  return XSENS_LIST_NOTFOUND;
967 }
968 
969 template <typename T>
970 template <typename TB>
971 uint32_t List<T>::findSortedDeref(const TB& item) const
972 {
973  if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD) // for small lists, it is faster to simply walk the list
974  return findDeref(item);
975 
976  uint32_t x = m_count;
977  uint32_t n = 1;
978  uint32_t i;
979 
980  while(x >= n)
981  {
982  i = (x + n) >> 1;
983 
984  if (*(m_data[i-1]) == item)
985  return i-1;
986  if (*(m_data[i-1]) < item)
987  n = i+1;
988  else
989  x = i-1;
990  }
991  return XSENS_LIST_NOTFOUND;
992 }
993 
994 template <typename T>
995 uint32_t List<T>::insertSorted(const T& item)
996 {
997  uint32_t i;
998  if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD)
999  {
1000  for (i=0;i<m_count;++i)
1001  if (item < m_data[i])
1002  {
1003  insert(item,i);
1004  return i;
1005  }
1006  append(item);
1007  return m_count-1;
1008  }
1009  else
1010  {
1011  uint32_t x = m_count;
1012  uint32_t n = 1;
1013 
1014  while(x >= n)
1015  {
1016  i = (x + n) >> 1;
1017 
1018  if (m_data[i-1] == item)
1019  {
1020  insert(item,i-1);
1021  return i-1;
1022  }
1023  if (m_data[i-1] < item)
1024  n = i+1;
1025  else
1026  x = i-1;
1027  }
1028  insert(item,n-1);
1029  return n-1;
1030  }
1031 }
1032 
1033 template <typename T>
1034 uint32_t List<T>::insertSortedDeref(const T& item)
1035 {
1036  uint32_t i;
1037  if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD)
1038  {
1039  for (i=0;i<m_count;++i)
1040  if (*item < *m_data[i])
1041  {
1042  insert(item,i);
1043  return i;
1044  }
1045  append(item);
1046  return m_count-1;
1047  }
1048  else
1049  {
1050  uint32_t x = m_count;
1051  uint32_t n = 1;
1052 
1053  while(x >= n)
1054  {
1055  i = (x + n) >> 1;
1056 
1057  if (*(m_data[i-1]) == *item)
1058  {
1059  insert(item,i-1);
1060  return i-1;
1061  }
1062  if (*(m_data[i-1]) < *item)
1063  n = i+1;
1064  else
1065  x = i-1;
1066  }
1067  insert(item,n-1);
1068  return n-1;
1069  }
1070 }
1071 
1072 template <typename T>
1073 template <typename TB>
1074 uint32_t List<T>::insertSortedCopy(const TB& item)
1075 {
1076  uint32_t i;
1077  if (m_count < CMT_LIST_LINEAR_SEARCH_TRESHOLD)
1078  {
1079  for (i=0;i<m_count;++i)
1080  if (item < m_data[i])
1081  {
1082  insertCopy<TB>(item,i);
1083  return i;
1084  }
1085  append(item);
1086  return m_count-1;
1087  }
1088  else
1089  {
1090  uint32_t x = m_count;
1091  uint32_t n = 1;
1092 
1093  while(x >= n)
1094  {
1095  i = (x + n) >> 1;
1096 
1097  if (m_data[i-1] == item)
1098  {
1099  insertCopy<TB>(item,i-1);
1100  return i-1;
1101  }
1102  if (m_data[i-1] < item)
1103  n = i+1;
1104  else
1105  x = i-1;
1106  }
1107  insertCopy<TB>(item,n-1);
1108  return n-1;
1109  }
1110 }
1111 
1112 template <typename T>
1114 {
1115  if (m_jcf != NULL)
1116  {
1117  m_jcf->disable();
1118  delete m_jcf;
1119  }
1120  m_jcf = new JanitorClassFunc<List<T>, void>(*this,&List<T>::deleteAndClear);
1121 }
1122 
1123 template <typename T>
1124 void List<T>::freeItemsOnDestroy(void)
1125 {
1126  if (m_jcf != NULL)
1127  {
1128  m_jcf->disable();
1129  delete m_jcf;
1130  }
1131  m_jcf = new JanitorClassFunc<List<T>, void>(*this,&List<T>::freeAndClear);
1132 }
1133 
1134 template <typename T>
1135 template <typename TB>
1136 void List<T>::isDeepCopyOf(const List<T>& source)
1137 {
1138  m_count = 0;
1139  if (m_max < source.m_count)
1140  resize(source.m_count);
1141  m_count = source.m_count;
1142  for (uint32_t i = 0;i<m_count;++i)
1143  m_data[i] = new TB(*source.m_data[i]);
1144 }
1145 
1146 template <typename T>
1147 void List<T>::isShallowCopyOf(const List<T>& x)
1148 {
1149  m_count = 0;
1150  if (m_max < x.m_count)
1151  resize(x.m_count);
1152  m_count = x.m_count;
1153  for (uint32_t i = 0;i<m_count;++i)
1154  m_data[i] = x.m_data[i];
1155 }
1156 
1157 template <typename T>
1158 void List<T>::swap(const uint32_t i, const uint32_t j) XSENS_LIST_THROW
1159 {
1160  #ifdef _XSENS_LIST_RANGE_CHECKS
1161  if (i >= m_count || j >= m_count)
1162  throw "List.swap: index out of bounds";
1163  #endif
1164  T tmp = m_data[i];
1165  m_data[i] = m_data[j];
1166  m_data[j] = tmp;
1167 }
1168 
1169 template <typename T>
1170 void List<T>::reverse(void)
1171 {
1172  uint32_t half = m_count / 2;
1173  for (uint32_t i = 0, end=m_count-1; i < half; ++i,--end)
1174  {
1175  T tmp = m_data[i];
1176  m_data[i] = m_data[end];
1177  m_data[end] = tmp;
1178  }
1179 }
1180 
1181 } // end of xsens namespace
1182 
1183 #endif // _XSENS_LIST_HPP_2006_06_08
1184 
void remove(const uint32_t index) XSENS_LIST_THROW
Removes an item at the given index in the list.
Definition: xsens_list.h:787
void deleteItemsOnDestroy(void)
Definition: xsens_list.h:1130
void swap(const uint32_t i, const uint32_t j) XSENS_LIST_THROW
Swaps two items in the list.
Definition: xsens_list.h:1175
void freeAndRemoveTail(const uint32_t count) XSENS_LIST_THROW
Definition: xsens_list.h:835
T & get(const uint32_t index) const XSENS_LIST_THROW
Retrieves the item at the given index. An index beyond the end returns the first item.
Definition: xsens_list.h:450
void freeAndClear(void)
Calls free for all items in the list and then clears the list.
Definition: xsens_list.h:325
void deleteAndClear(void)
Calls delete for all items in the list and then clears the list.
Definition: xsens_list.h:317
void deleteAndRemove(const uint32_t index) XSENS_LIST_THROW
Removes an item at the given index in the list.
Definition: xsens_list.h:889
void reverse(void)
Reverse the order of the list, useful for sorted lists that are read/created in the reverse order...
Definition: xsens_list.h:1187
List()
Standard constructor, creates an empty list with some room for items.
Definition: xsens_list.h:238
void sortAscendingDeref(void)
Sorts the list in an ascending order, using the T::< operator on dereferenced list items...
Definition: xsens_list.h:658
uint32_t findDeref(const TB &item) const
Finds an item in an unsorted list (walk over all items) using the T::== operator on dereferenced list...
Definition: xsens_list.h:945
void clear(void)
Clears the list without explicitly deleting anything.
Definition: xsens_list.h:333
void insert(const T &item, const uint32_t index)
Inserts an item at the given index, shifting any items below it down one spot.
Definition: xsens_list.h:462
uint32_t insertSorted(const T &item)
Assumes the list is sorted and inserts the item at the appropriate spot.
Definition: xsens_list.h:1090
List class interface for use in CMT.
~List()
Destroy the list. This does NOT automatically delete items IN the list.
Definition: xsens_list.h:306
void appendDeepCopy(const List< T > &source)
Adds the contents of the source list to the end of the list.
Definition: xsens_list.h:374
uint32_t find(const TB &item) const
Finds an item in an unsorted list (walk over all items) using the T::== operator. ...
Definition: xsens_list.h:926
#define XSENS_LIST_THROW
Definition: xsens_list.h:58
void appendCopy(const TB &item)
Adds a copy of a referenced item to the end of the list using newItem = new TB(item).
Definition: xsens_list.h:395
#define XSENS_LIST_NOTFOUND
Definition: xsens_list.h:49
void deleteAndRemoveTail(const uint32_t count) XSENS_LIST_THROW
Definition: xsens_list.h:819
uint32_t removeDuplicateEntriesDeref(void)
Removes any duplicate entries and returns the number of items removed. Items are compared after deref...
Definition: xsens_list.h:870
void appendList(uint32_t count, const T *lst)
Adds a number of items to the end of the list.
Definition: xsens_list.h:365
uint32_t insertSortedCopy(const TB &item)
Assumes the list is sorted and inserts a copy of the referenced item at the appropriate spot...
Definition: xsens_list.h:1117
void freeAndRemove(const uint32_t index) XSENS_LIST_THROW
Removes an item at the given index in the list.
Definition: xsens_list.h:907
void resize(uint32_t newSize)
Resizes the list to at least the given size.
Definition: xsens_list.h:339
T & last(void) const XSENS_LIST_THROW
Retrieves the last item.
Definition: xsens_list.h:412
void appendShallowCopy(const List< T > &source)
Adds the contents of the source list to the end of the list.
Definition: xsens_list.h:384
uint32_t findSortedDeref(const TB &item) const
Finds an item in a sorted list (binary search) using the T::== and T::< operators on dereferenced lis...
Definition: xsens_list.h:1002
void isShallowCopyOf(const List< T > &source)
Overwrites the current list with a direct copy (a=b) of another list.
Definition: xsens_list.h:1164
#define CMT_LIST_LINEAR_SEARCH_TRESHOLD
Definition: xsens_list.hpp:38
uint32_t removeDuplicateEntries(void)
Removes any duplicate entries and returns the number of items removed. Items are compared directly...
Definition: xsens_list.h:851
void sortAscending(void)
Sorts the list in an ascending order, using the T::< operator.
Definition: xsens_list.h:568
void removeTail(const uint32_t count) XSENS_LIST_THROW
Removes items from the end of the list.
Definition: xsens_list.h:804
uint32_t insertSortedDeref(const T &item)
Assumes the list is sorted by dereferenced values and inserts the item at the appropriate spot...
Definition: xsens_list.h:1103
void freeItemsOnDestroy(void)
Definition: xsens_list.h:1141
void append(const T &item)
Adds an item to the end of the list.
Definition: xsens_list.h:357
T & operator[](const uint32_t index) const XSENS_LIST_THROW
Retrieves the item at the given index. An index beyond the end probably causes an exception...
Definition: xsens_list.h:491
void twinSortAscending(List< T2 > &twin)
Sorts the first list in an ascending order, using the T::< operator, the second list will be updated ...
Definition: xsens_list.h:750
void appendRelated(const TR &item)
Adds a related item to the end of the list, using the T = TR operator.
Definition: xsens_list.h:404
void insertCopy(const TB &item, const uint32_t index)
Inserts a copy of the referenced item at the given index, shifting any items below it down one spot...
Definition: xsens_list.h:477
uint32_t findSorted(const TB &item) const
Finds an item in a sorted list (binary search) using the T::== and T::< operators.
Definition: xsens_list.h:977
void isDeepCopyOf(const List< T > &source)
Make a copy of the list, duplicating list items i with: copy[i] = new TB(*source[i]) ...
Definition: xsens_list.h:1153