acme
Foundational cross-platform layer of the ca2 framework
Loading...
Searching...
No Matches
array_base.h
1#pragma once
2
3
4#include "acme/prototype/collection/base_array.h"
5#include "acme/prototype/collection/copy_elements.h"
6
7
8
9template < class TYPE, class ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
10class array_base :
11 public base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >
12{
13public:
14
15
16 //using is_array_base = true_type;
17 using BASE_ARRAY = base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >;
18 using RAW_BASE_ARRAY = typename BASE_ARRAY::RAW_BASE_ARRAY;
19
20 using THIS_ARRAY = array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >;
21
22
23
24 using BASE_TYPE = TYPE;
25 using BASE_ARG_TYPE = ARG_TYPE;
26
27
28 using BASE_RAW_RANGE = typename BASE_ARRAY::BASE_RAW_RANGE;
29
30
31 using iterator = typename BASE_ARRAY::iterator;
32 using const_iterator = typename BASE_ARRAY::const_iterator;
33
34 using this_iterator = typename BASE_ARRAY::this_iterator;
35
36 using ITERATOR_RANGE = typename BASE_ARRAY::ARRAY_RANGE;
37
38 using CONST_RANGE = typename BASE_ARRAY::CONST_RANGE;
39 using CONST_RAW_RANGE = typename BASE_ARRAY::CONST_RAW_RANGE;
40
41 using BASE_ARRAY::BASE_ARRAY;
42 using BASE_ARRAY::operator =;
43 using BASE_ARRAY::operator +=;
44
45 array_base(const RAW_BASE_ARRAY & a) : BASE_ARRAY(a) { }
46
47 //using ::base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::base_array;
48
49 // array_base();
50 // array_base(nullptr_t) : array_base() {}
51 // array_base(std::initializer_list < TYPE > initializer_list) : BASE_ARRAY(initializer_list) {}
52 // //array_base(const_iterator begin, const_iterator end) : BASE_ARRAY(begin, end) {}
53 // array_base(const array_base & a);
54 // array_base(enum_create_new, ::collection::count n);
55 // array_base(::collection::count n);
56 // array_base(::collection::count n, ARG_TYPE t);
57 // array_base(::range < const_iterator > constrange) : BASE_ARRAY(constrange) {}
58 // template < prototype_integral INTEGRAL >
59 // array_base(const_iterator begin, INTEGRAL count) : BASE_ARRAY(begin, count) {}
60 // array_base(const_iterator begin, const_iterator end) : BASE_ARRAY(begin, end) {}
61 // array_base(array_base && a) noexcept : base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >(::transfer(a)) { }
62 // ~array_base() override;
63
64
65 // array_base & operator = (const array_base & array_base) { BASE_ARRAY::operator=(array_base); return *this; }
66 // array_base & operator = (array_base && array_base) { BASE_ARRAY::operator=(::transfer(array_base)); return *this; }
67 // array_base & operator = (std::initializer_list < TYPE > initializer_list)
68 // {
69 // this->clear();
70 // for (auto & item : initializer_list) this->add(item);
71 // return *this;
72 // }
73
74
75 inline const TYPE & get_at(::collection::index nIndex) const;
76 inline TYPE & get_at(::collection::index nIndex);
77 inline void set_at(::collection::index nIndex, ARG_TYPE newElement);
78
79
80 //inline const TYPE * data() const { return this->m_begin; }
81 //inline TYPE * data() { return this->m_begin; }
82
83 // must not be overloaded!!
84 inline ::collection::index add_item(ARG_TYPE newElement);
85
86
87 inline ::collection::index add(ARG_TYPE newElement);
88 inline ::collection::index add_copies(ARG_TYPE newElement, ::collection::count cCopies)
89 {
90 ::collection::index iLastInsertIndex = -1;
91 while (cCopies > 0)
92 {
93
94 iLastInsertIndex =add_item(newElement);
95
96 cCopies--;
97
98 }
99
100 return iLastInsertIndex;
101 }
103
104
105 //template < prototype_container CONTAINER >
106 //inline ::collection::count append(const CONTAINER & container)
107 //{
108
109 // return BASE_ARRAY::append(container);
110
111 //}*/
112
113
114 template < typename CONTAINER >
115 inline array_base appended_container(const CONTAINER & container)
116 {
117
118 auto array_base = *this;
119
120 array_base.append_container(container);
121
122 return ::transfer(array_base);
123
124 }
125
126
127
128
129
130 inline void copy(const array_base & src);
131
132 inline TYPE & add_new(::collection::count c = 1);
133
134
135 inline TYPE & add_new_at(::collection::index iIndex, ::collection::count count = 1);
136
137
138 inline array_base & operator << (ARG_TYPE newElement) { add(newElement); return *this; }
139
140
141 //that transfer elements around
142 //inline ::collection::index insert_at(::collection::index nIndex, ARG_TYPE newElement, ::collection::count nCount = 1);
143 //void _001RemoveIndexes(index_array & ia);
144 //void erase_indexes(const index_array & ia); // erase indexes from ::collection::index array_base upper bound to ::collection::index array_base lower bound
145 //void erase_descending_indexes(const index_array & ia); // erase indexes from ::collection::index array_base lower bound to ::collection::index array_base upper bound
146 //::collection::index insert_at(::collection::index nStartIndex, array_base* pNewArray);
147
148 //using base_array < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::operator=;
149 //inline array_base & operator = (const array_base & src);
150 //inline array_base & operator = (array_base && a);
151
152
153
154 //inline ::collection::index find_first(ARG_TYPE t, ::collection::index (* pfnCompare)(ARG_TYPE, ARG_TYPE), ::collection::index start = 0, ::collection::index last = -1) const;
155
156 //::collection::index raw_find_first(TYPE * point, ::collection::index first = 0, ::collection::index last = -1) const;
157
158 //template < class DERIVED >
159 //inline ::collection::index find_first(DERIVED * point, ::collection::index first = 0, ::collection::index last = -1)
160 //{
161 // return raw_find_first(dynamic_cast < TYPE * > (point), first, last);
162 //}
163
164 template < class ARRAY >
165 inline ::collection::count slice(ARRAY & a, ::collection::index iStart = 0, ::collection::count nCount = -1)
166 {
167
168 ::collection::count ca = 0;
169
170 ::collection::index iEnd;
171
172 if (nCount < 0)
173 iEnd = this->get_upper_bound(nCount);
174 else
175 iEnd = iStart + nCount - 1;
176
177 for (::collection::index i = iStart; i <= iEnd; i++)
178 {
179
180 a.add(this->element_at(i));
181 ca++;
182
183 }
184
185 return ca;
186
187 }
188
189 template < typename ARRAY >
190 inline ARRAY slice(::collection::index iStart = 0, ::collection::count nCount = -1)
191 {
192
193 ARRAY a;
194
195 slice(a, iStart, nCount);
196
197 return a;
198
199 }
200
201 //operator TYPE *() {return this->m_begin;}
202 //operator const TYPE *() const {return this->m_begin;}
203
204 // template < prototype_container CONTAINER >
205 // inline array_base & operator += (const CONTAINER & container);
206
207 template < typename... T >
208 void fadd(T... a)
209 {
210
211 add(TYPE(a...));
212
213 }
214
215 template < typename PREDICATE >
216 ::collection::index predicate_index_index(::collection::index iPredicateIndex, PREDICATE predicate)
217 {
218
219 if (iPredicateIndex < 0)
220 {
221
222 return -1;
223
224 }
225
226 for (::collection::index iIndex = 0; iIndex < this->get_size(); iIndex++)
227 {
228
229 auto & element = this->element_at(iIndex);
230
231 if (predicate(element))
232 {
233
234 if (iPredicateIndex <= 0)
235 {
236
237 return iIndex;
238
239 }
240
241 iPredicateIndex--;
242
243 }
244
245 }
246
247 return -1;
248
249 }
250
251 template < typename PREDICATE >
252 ::collection::index index_predicate_index(::collection::index iIndex, PREDICATE predicate)
253 {
254
255 ::collection::index iPredicateIndex = -1;
256
257 ::collection::index i = 0;
258
259 for (; i <= iIndex && i < this->get_size(); i++)
260 {
261
262 auto & element = this->element_at(i);
263
264 if (predicate(element))
265 {
266
267 iPredicateIndex++;
268
269 }
270
271 }
272
273 if (i <= iIndex)
274 {
275
276 return -1;
277
278 }
279
280 return iPredicateIndex;
281
282 }
283
284 template < typename PRED >
285 bool predicate_add_unique(TYPE t, PRED pred)
286 {
287
288 if (this->predicate_contains(pred))
289 {
290
291 return false;
292
293 }
294
295 this->add(t);
296
297 return true;
298
299 }
300
301
302
303 template < typename ITERABLE >
304 base_array< TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & copy_iter(const ITERABLE & iterable)
305 {
306
307 this->set_size(0, maximum(__iterable_count(iterable), 17));
308
309 for (auto & item : iterable)
310 {
311
312 add_item(item);
313
314 }
315
316 return *this;
317
318 }
319
320};
321
322
323template < typename CONTAINER, typename T >
324auto container_predicate_get(const CONTAINER & source, const ::function < bool(const T & t) >& predicate)
325{
326
327 CONTAINER result;
328
329 for (auto& item : source)
330 {
331
332 if (predicate(item))
333 {
334
335 result.add(item);
336
337 }
338
339 }
340
341 return ::transfer(result);
342
343}
344
345
346template < class TYPE, class ARG_TYPE = const TYPE & >
347class nodefctr_array :
348 public array_base < TYPE, ARG_TYPE, ::constructor::nodef < TYPE > >
349{
350public:
351
352
353 nodefctr_array(::collection::count nGrowBy = 32) : array_base < TYPE, ARG_TYPE, ::constructor::nodef < TYPE > >(nGrowBy) {}
354 nodefctr_array(const array_base <TYPE, ARG_TYPE> & a) : array_base < TYPE, ARG_TYPE, ::constructor::nodef < TYPE > >(a) {}
355 //nodefctr_array(::collection::count n) : array_base < TYPE, ARG_TYPE, ::constructor::nodef < TYPE > > (n) {}
356 ~nodefctr_array() {}
357
358};
359
360// template < class TYPE, class ARG_TYPE, class TYPED, class MEMORY, ::enum_type t_etypeContainer >
361// class array_base :
362// virtual public ::particle,
363// public array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >
364// {
365// public:
366//
367//
368// using BASE_ARRAY = array_base< TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >;
369//
370//
371// using BASE_ARRAY::BASE_ARRAY;
372// using BASE_ARRAY::operator =;
373//
374// //array_base() : array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >() {}
375// //template < typename ...Args >
376// //array_base(Args&&... args) :
377// // array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >(::std::forward < Args >(args)...)
378// //{
379// //}
380// // array_base() {}
381// // array_base(nullptr_t) : BASE_ARRAY() {}
382// // array_base(std::initializer_list < TYPE > initializer_list) : BASE_ARRAY(initializer_list) {}
383// // //array_base(const_iterator begin, const_iterator end) : BASE_ARRAY(begin, end) {}
384// // array_base(const BASE_ARRAY & a) : BASE_ARRAY(a) {}
385// // array_base(BASE_ARRAY && a) noexcept : BASE_ARRAY(::transfer(a)) { }
386// // array_base(enum_create_new, ::collection::count n) : BASE_ARRAY(e_create_new, n) {}
387// // array_base(pre_allocate_t, ::collection::count n) : BASE_ARRAY() { this->m_countAddUp = n; }
388// // array_base(zeroe_on_allocation_t, ::collection::count n) : BASE_ARRAY(zeroe_on_allocation_t{}, n) { }
389// // array_base(::collection::count n) : BASE_ARRAY(n) {}
390// // array_base(::collection::count n, ARG_TYPE t) : BASE_ARRAY(n, t) {}
391// // array_base(::range < typename BASE_ARRAY::const_iterator > constrange) : BASE_ARRAY(constrange) {}
392// // template < prototype_integral INTEGRAL >
393// // array_base(typename BASE_ARRAY::const_iterator begin, INTEGRAL count) : BASE_ARRAY(begin, count) {}
394// // array_base(typename BASE_ARRAY::const_iterator begin, typename BASE_ARRAY::const_iterator end) : BASE_ARRAY(begin, end) {}
395//
396//
397//
398// void destroy() override
399// {
400//
401// ::particle::destroy();
402// BASE_ARRAY::destroy();
403//
404// }
405//
406// };
407
408
409
410template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
411inline TYPE & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::get_at(::collection::index nIndex)
412{
413
414 ASSERT(nIndex >= 0 && nIndex < this->size());
415
416 return this->m_begin[nIndex];
417
418}
419
420
421template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
422inline const TYPE & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::get_at(::collection::index nIndex) const
423{
424
425 ASSERT(nIndex >= 0 && nIndex < this->size());
426
427 return this->m_begin[nIndex];
428
429}
430
431
432template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
433inline void array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::set_at(::collection::index nIndex, ARG_TYPE newElement)
434{
435
436 ASSERT(nIndex >= 0 && nIndex < this->size());
437
438 this->m_begin[nIndex] = newElement;
439
440}
441
442
443
444template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
445inline ::collection::index array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::add_item(ARG_TYPE newElement)
446{
447
448 auto nIndex = this->size();
449
450 this->allocate(nIndex + 1, false, false, newElement);
451
452 //this->last() = newElement;
453
454 return nIndex;
455
456}
457
458
459template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
460inline ::collection::index array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::add(ARG_TYPE newElement)
461{
462
463 return add_item(newElement);
464
465}
466
467
468//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
469//template < container_type CONTAINER >
470//inline ::collection::index array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::add(const CONTAINER & container)
471//{
472//
473// ::collection::index i = -1;
474//
475// for(auto & item : container)
476// {
477//
478// i = add_item(item);
479//
480// }
481//
482// return i;
483//
484//}
485
486//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
487//inline ::collection::index array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::append(ARG_TYPE newElement)
488//{
489// return add(newElement);
490//}
491
492
493
494//
495//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
496//inline array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::operator = (const array_base & src)
497//{
498//
499// if(&src != this)
500// {
501//
502// copy(src);
503//
504// }
505//
506// return *this;
507//
508//}
509
510//
511// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
512// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::array_base() :
513// BASE_ARRAY::base_array()
514// {
515//
516//
517// }
518//
519//
520// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
521// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::array_base(const array_base & a) :
522// BASE_ARRAY::base_array(a)
523// {
524//
525// }
526//
527
528//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
529//inline array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::array_base(::std::initializer_list < TYPE > l)
530//{
531//
532// for(auto & item : l)
533// {
534//
535// add((ARG_TYPE) item);
536//
537// }
538//
539//}
540
541//
542// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
543// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::array_base(enum_create_new, ::collection::count n)
544// {
545//
546// this->set_size(n);
547//
548// }
549//
550//
551// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
552// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::array_base(::collection::count n) :
553// array_base()
554// {
555//
556// this->set_size(n);
557//
558// }
559//
560//
561// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
562// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::array_base(::collection::count n, ARG_TYPE t) :
563// array_base()
564// {
565//
566// while (n > 0)
567// {
568//
569// add(t);
570//
571// n--;
572//
573// }
574//
575// }
576//
577//
578// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
579// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::~array_base()
580// {
581//
582// this->erase_all(); // on_destruct_element is virtual and won't be available for base_array
583//
584// }
585//
586
587//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
588//inline ::collection::index array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::append(const array_base & src)
589//{
590//
591// auto countOld = this->size();
592//
593// this->allocate(countOld + src.size(), false, true);
594//
595// TYPED::copy_construct_count(this->m_begin + countOld, src.size(), src.m_begin);
596//
597// return countOld;
598//
599//}
600
601
602template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
603inline void array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::copy(const array_base & src)
604{
605
606 ASSERT(this != &src);
607
608 if (this != &src)
609 {
610
611 this->erase_all();
612
613 this->append_container(src);
614
615 // auto nSrcSize = src.size();
616 //
617 // this->allocate(nSrcSize);
618 //
619 // CopyElements<TYPE>(this->m_begin,src.m_begin, nSrcSize);
620
621 }
622
623}
624
625
626
627
628// template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
629// template < prototype_container CONTAINER >
630// inline array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::operator += (const CONTAINER & container)
631// {
632//
633// if (&container == this)
634// {
635//
636// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > aCopy(container);
637//
638// this->append_container(aCopy);
639//
640// }
641// else
642// {
643//
644// this->append_container(container);
645//
646// }
647//
648// return *this;
649//
650// }
651
652
653//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
654//template < container CONTAINER >
655//inline array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::operator + (const CONTAINER & container) const
656//{
657//
658// array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > aNew(*this);
659//
660// aNew.add(container);
661//
662// return aNew;
663//
664//}
665//
666
667template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
668inline TYPE & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::add_new(::collection::count c)
669{
670
671 if (c <= 0)
672 {
673
674 throw_exception(error_bad_argument);
675
676 }
677
678 auto end = this->size();
679
680 this->set_size(end + c);
681
682 return this->element_at(end);
683
684}
685
686//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
687//inline TYPE & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::add_new_at(::i32 iIndex)
688//{
689//
690// this->make_room_at(iIndex);
691//
692// return this->element_at(iIndex);
693//
694//}
695
696
697template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
698inline TYPE & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > ::add_new_at(::collection::index i, ::collection::count c)
699{
700
701 this->raw_allocate_at(i, c);
702
703 TYPED::construct_count(this->m_begin + i, c);
704
705 return this->element_at(i);
706
707}
708
709
710
711//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
712//inline array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::transfer(array_base && a)
713//{
714//
715// if(&a != this)
716// {
717//
718// this->destroy();
719//
720// this->m_nGrowBy = a.m_nGrowBy;
721// this->m_begin = a.m_begin;
722// this->m_end = a.m_end;
723// this->m_nMaxSize = a.m_nMaxSize;
724//
725// a.m_begin = nullptr;
726// a.m_end = nullptr;
727// a.m_nMaxSize = 0;
728//
729// }
730//
731// return *this;
732//
733//}
734
735
736//template < typename TYPE, typename ARG_TYPE, typename TYPED, typename MEMORY, ::enum_type t_etypeContainer >
737//inline array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer > & array_base < TYPE, ARG_TYPE, TYPED, MEMORY, t_etypeContainer >::operator = (array_base && a)
738//{
739//
740// transfer(::transfer(a));
741//
742// return *this;
743//
744//}
745
746
747
748
Definition array_base.h:12
array_base appended_container(const CONTAINER &container)
inline collection::count append(const array_base & src);
Definition array_base.h:115
Definition item.h:93
source is originator of subjects
Definition source.h:11