1 #define LLOG(x)   // DLOG(x)
2 
3 int64 NewInVectorSerial();
4 
5 template <class T>
Init()6 void InVector<T>::Init()
7 {
8 	serial = NewInVectorSerial();
9 	slave = 0;
10 	Reset();
11 }
12 
13 template <class T>
InVector()14 InVector<T>::InVector()
15 {
16 	Init();
17 }
18 
19 template <class T>
Reset()20 void InVector<T>::Reset()
21 {
22 	hcount = count = 0;
23 	SetBlkPar();
24 }
25 
26 template <class T>
Clear()27 void InVector<T>::Clear()
28 {
29 	if(slave)
30 		Slave()->Clear();
31 	data.Clear();
32 	index.Clear();
33 	Reset();
34 	ClearCache();
35 }
36 
37 void SetInvectorCache__(int64 serial, int blki, int offset, int end);
38 void ClearInvectorCache__();
39 int  FindInvectorCache__(int64 serial, int& pos, int& off);
40 
41 template <class T>
SetCache(int blki,int offset) const42 force_inline void InVector<T>::SetCache(int blki, int offset) const
43 {
44 #ifdef flagIVTEST
45 	Check(0, 0);
46 #endif
47 	SetInvectorCache__(serial, blki, offset, offset + data[blki].GetCount());
48 }
49 
50 template <class T>
ClearCache() const51 force_inline void InVector<T>::ClearCache() const
52 {
53 	ClearInvectorCache__();
54 }
55 
56 template <class T>
FindBlock(int & pos,int & off) const57 force_inline int InVector<T>::FindBlock(int& pos, int& off) const
58 {
59 	int i = FindInvectorCache__(serial, pos, off);
60 	return i >= 0 ? i : FindBlock0(pos, off);
61 }
62 
63 template <class T>
FindBlock0(int & pos,int & off) const64 int InVector<T>::FindBlock0(int& pos, int& off) const
65 {
66 	LLOG("FindBlock " << pos);
67 	ASSERT(pos >= 0 && pos <= count);
68 	if(pos == count) {
69 		LLOG("Found last");
70 		pos = data.Top().GetCount();
71 		off = count - pos;
72 		return data.GetCount() - 1;
73 	}
74 	int blki = 0;
75 	int offset = 0;
76 	for(int i = index.GetCount(); --i >= 0;) {
77 		int n = index[i][blki];
78 		if(pos >= n) {
79 			blki++;
80 			pos -= n;
81 			offset += n;
82 		}
83 		blki += blki;
84 	}
85 	int n = data[blki].GetCount();
86 	if(pos >= n) {
87 		blki++;
88 		pos -= n;
89 		offset += n;
90 	}
91 
92 	SetCache(blki, offset);
93 
94 	off = offset;
95 	return blki;
96 }
97 
98 template <class T>
FindBlock(int & pos) const99 force_inline int InVector<T>::FindBlock(int& pos) const
100 {
101 	int h;
102 	return FindBlock(pos, h);
103 }
104 
105 template <class T>
operator [](int i) const106 const T& InVector<T>::operator[](int i) const
107 {
108 	LLOG("operator[] " << i);
109 	ASSERT(i >= 0 && i < count);
110 	int blki = FindBlock(i);
111 	return data[blki][i];
112 }
113 
114 template <class T>
operator [](int i)115 T& InVector<T>::operator[](int i)
116 {
117 	LLOG("operator[] " << i);
118 	ASSERT(i >= 0 && i < count);
119 	int blki = FindBlock(i);
120 	return data[blki][i];
121 }
122 
123 template <class T>
Reindex()124 void InVector<T>::Reindex()
125 {
126 	LLOG("--- Reindexing");
127 	ClearCache();
128 	SetBlkPar();
129 	index.Clear();
130 	if(slave)
131 		Slave()->Reindex();
132 	hcount = 0;
133 	Vector<T> *ds = data.Begin();
134 	Vector<T> *dend = data.End();
135 	int n = data.GetCount();
136 	if(n <= 2)
137 		return;
138 	Vector<int>& w = index.Add();
139 	hcount = 2;
140 	w.SetCount((n + 1) >> 1);
141 	int *t = w.Begin();
142 	while(ds != dend) {
143 		*t = (ds++)->GetCount();
144 		if(ds == dend)
145 			break;
146 		*t++ += (ds++)->GetCount();
147 	}
148 	int *s = w.Begin();
149 	int *end = w.End();
150 	n = w.GetCount();
151 	while(n > 2) {
152 		Vector<int>& w = index.Add();
153 		hcount += hcount;
154 		w.SetCount((n + 1) >> 1);
155 		t = w.Begin();
156 		while(s != end) {
157 			*t = *s++;
158 			if(s == end)
159 				break;
160 			*t++ += *s++;
161 		}
162 		s = w.Begin();
163 		end = w.End();
164 		n = w.GetCount();
165 	}
166 #ifdef flagIVTEST
167 	Check(0, 0);
168 #endif
169 }
170 
171 template <class T>
SetBlkPar()172 void InVector<T>::SetBlkPar()
173 {
174 #if defined(_DEBUG) && defined(flagIVTEST)
175 	blk_high = 11;
176 	blk_low = 5;
177 #else
178 	int n = 2500 + data.GetCount() / 4;
179 	blk_high = minmax(n / (int)sizeof(T), 16, 65000);
180 	blk_low = minmax(n / 3 / (int)sizeof(T), 16, 65000);
181 #endif
182 }
183 
184 template <class T>
Index(int q,int n)185 void InVector<T>::Index(int q, int n)
186 {
187 	for(int i = 0; i < index.GetCount(); i++)
188 		index[i].At(q >>= 1, 0) += n;
189 }
190 
191 template <class T>
Insert0(int ii,int blki,int pos,int off,const T * val)192 T *InVector<T>::Insert0(int ii, int blki, int pos, int off, const T *val)
193 {
194 	if(data[blki].GetCount() > blk_high) {
195 		if(slave)
196 			Slave()->Split(blki, data[blki].GetCount() / 2);
197 		Vector<T>& x = data.Insert(blki + 1);
198 		x.InsertSplit(0, data[blki], data[blki].GetCount() / 2);
199 		data[blki].Shrink();
200 		Reindex();
201 		pos = ii;
202 		blki = FindBlock(pos, off);
203 	}
204 	LLOG("blki: " << blki << ", pos: " << pos);
205 	count++;
206 	if(slave) {
207 		Slave()->Count(1);
208 		Slave()->Index(blki, 1);
209 		Slave()->Insert(blki, pos);
210 	}
211 	Index(blki, 1);
212 	if(val)
213 		data[blki].Insert(pos, *val);
214 	else
215 		data[blki].Insert(pos);
216 	SetCache(blki, off);
217 	return &data[blki][pos];
218 }
219 
220 template <class T>
Insert0(int ii,const T * val)221 T *InVector<T>::Insert0(int ii, const T *val)
222 {
223 	ASSERT(ii >= 0 && ii <= GetCount());
224 	if(data.GetCount() == 0) {
225 		count++;
226 		ClearCache();
227 		if(slave) {
228 			Slave()->Count(1);
229 			Slave()->AddFirst();
230 		}
231 		if(val) {
232 			data.Add().Add(*val);
233 			return &data[0][0];
234 		}
235 		return &data.Add().Add();
236 	}
237 	int pos = ii;
238 	int off;
239 	int blki = FindBlock(pos, off);
240 	return Insert0(ii, blki, pos, off, val);
241 }
242 
243 template <class T>
244 template <class Range>
Insert_(int ii,const Range & r,bool def)245 void InVector<T>::Insert_(int ii, const Range& r, bool def)
246 {
247 	int n = r.GetCount();
248 
249 	ASSERT(ii >= 0 && ii <= GetCount() && n >= 0 && !slave);
250 
251 	if(n <= 0)
252 		return;
253 
254 	auto s = r.begin();
255 
256 	if(data.GetCount() == 0) {
257 		int m = (blk_high + blk_low) / 2;
258 		count = n;
259 		while(n > 0) {
260 			int n1 = min(m, n);
261 			if(def)
262 				data.Add().SetCount(n1);
263 			else
264 				data.Add().AppendRange(SubRange(s, n1));
265 			s += n1;
266 			n -= n1;
267 		}
268 		Reindex();
269 		return;
270 	}
271 
272 	int pos = ii;
273 	int off;
274 	int blki = FindBlock(pos, off);
275 	int bc = data[blki].GetCount();
276 
277 	count += n;
278 
279 	if(bc + n < blk_high) { // block will not be bigger than threshold after insert
280 		if(def)
281 			data[blki].InsertN(pos, n);
282 		else
283 			data[blki].InsertRange(pos, SubRange(s, n));
284 		Index(blki, n);
285 		SetCache(blki, off);
286 	}
287 	else
288 	if(bc - pos + n < blk_high) { // splitting into 2 blocks is enough
289 		Vector<T>& t = data.Insert(blki + 1);
290 		if(def)
291 			t.InsertN(0, n);
292 		else
293 			t.InsertRange(0, SubRange(s, n));
294 		t.InsertSplit(n, data[blki], pos);
295 		data[blki].Shrink();
296 		Reindex();
297 	}
298 	else { // need to insert several blocks
299 		int m = (blk_high + blk_low) / 2;
300 		int bn = (n + m - 1) / m;
301 		int ti;
302 		if(pos) { // need to split first block
303 			ti = blki + 1; // TODO should add some of data to splitted blocks
304 			data.InsertN(ti, bn + 1);
305 			data[ti + bn].InsertSplit(0, data[blki], pos);
306 			data[blki].Shrink();
307 		}
308 		else {
309 			ti = blki;
310 			data.InsertN(ti, bn);
311 		}
312 		for(int i = 0; i < bn; i++) {
313 			int q = min(m, n);
314 			if(def)
315 				data[ti + i].SetCount(q);
316 			else
317 				data[ti + i].AppendRange(SubRange(s, q));
318 			s += q;
319 			n -= q;
320 		}
321 		ASSERT(n == 0);
322 		Reindex();
323 	}
324 #ifdef flagIVTEST
325 	Check(0, 0);
326 #endif
327 }
328 
329 template <class T>
Join(int blki)330 void InVector<T>::Join(int blki)
331 {
332 	data[blki].AppendPick(pick(data[blki + 1]));
333 	data.Remove(blki + 1);
334 }
335 
336 template <class T>
JoinSmall(int blki)337 force_inline bool InVector<T>::JoinSmall(int blki)
338 {
339 	if(blki < data.GetCount()) {
340 		int n = data[blki].GetCount();
341 		if(n == 0) {
342 			if(slave)
343 				Slave()->RemoveBlk(blki, 1);
344 			data.Remove(blki);
345 			return true;
346 		}
347 		if(n < blk_low) {
348 			if(blki > 0 && data[blki - 1].GetCount() + n <= blk_high) {
349 				if(slave)
350 					Slave()->Join(blki - 1);
351 				Join(blki - 1);
352 				return true;
353 			}
354 			if(blki + 1 < data.GetCount() && n + data[blki + 1].GetCount() <= blk_high) {
355 				if(slave)
356 					Slave()->Join(blki);
357 				Join(blki);
358 				return true;
359 			}
360 		}
361 	}
362 	return false;
363 }
364 
365 template <class T>
Remove(int pos,int n)366 void InVector<T>::Remove(int pos, int n)
367 {
368 	ASSERT(pos >= 0 && pos + n <= GetCount());
369 	if(n == 0)
370 		return;
371 	int off;
372 	int blki = FindBlock(pos, off);
373 	count -= n;
374 	if(slave)
375 		Slave()->Count(-n);
376 	if(pos + n < data[blki].GetCount()) {
377 		if(slave)
378 			Slave()->Remove(blki, pos, n);
379 		data[blki].Remove(pos, n);
380 		if(JoinSmall(blki))
381 			Reindex();
382 		else {
383 			if(slave)
384 				Slave()->Index(blki, -n);
385 			Index(blki, -n);
386 			SetCache(blki, off);
387 		}
388 	}
389 	else {
390 		int b1 = blki;
391 		int nn = min(n, data[b1].GetCount() - pos);
392 		if(slave)
393 			Slave()->Remove(b1, pos, nn);
394 		data[b1++].Remove(pos, nn);
395 		n -= nn;
396 		int b2 = b1;
397 		while(b2 < data.GetCount() && n >= data[b2].GetCount()) {
398 			n -= min(n, data[b2].GetCount());
399 			b2++;
400 		}
401 		if(slave)
402 			Slave()->RemoveBlk(b1, b2 - b1);
403 		data.Remove(b1, b2 - b1);
404 		if(b1 < data.GetCount()) {
405 			if(slave)
406 				Slave()->Remove(b1, 0, n);
407 			data[b1].Remove(0, n);
408 		}
409 		JoinSmall(blki + 1);
410 		JoinSmall(blki);
411 		Reindex();
412 	}
413 #ifdef flagIVTEST
414 	Check(0, 0);
415 #endif
416 }
417 
418 template <class T>
SetCount(int n)419 void InVector<T>::SetCount(int n)
420 {
421 	if(n < GetCount())
422 		Trim(n);
423 	else
424 		InsertN(GetCount(), n - GetCount());
425 }
426 
427 template <class T>
Shrink()428 void InVector<T>::Shrink()
429 {
430 	for(int i = 0; i < data.GetCount(); i++)
431 		data[i].Shrink();
432 	data.Shrink();
433 	for(int i = 0; i < index.GetCount(); i++)
434 		index[i].Shrink();
435 	index.Shrink();
436 }
437 
438 template <class T>
Set(int i,const T & x,int count)439 void InVector<T>::Set(int i, const T& x, int count)
440 {
441 	Iterator it = GetIter(i);
442 	while(count-- > 0)
443 		*it++ = x;
444 }
445 
446 template <class T>
InVector(const InVector<T> & v,int)447 InVector<T>::InVector(const InVector<T>& v, int)
448 {
449 	data <<= v.data;
450 	index <<= v.index;
451 	count = v.count;
452 	hcount = v.hcount;
453 	blk_high = v.blk_high;
454 	blk_low = v.blk_low;
455 	serial = NewInVectorSerial();
456 	slave = v.slave;
457 }
458 
459 template <class T>
Pick(InVector && v)460 void InVector<T>::Pick(InVector&& v)
461 {
462 	data = pick(v.data);
463 	index = pick(v.index);
464 	count = v.count;
465 	hcount = v.hcount;
466 	blk_high = v.blk_high;
467 	blk_low = v.blk_low;
468 	serial = v.serial;
469 	slave = v.slave;
470 
471 	v.Init();
472 }
473 
474 
475 template <class T>
476 template <class L>
FindUpperBound(const T & val,const L & less,int & off,int & pos) const477 int InVector<T>::FindUpperBound(const T& val, const L& less, int& off, int& pos) const
478 {
479 	if(data.GetCount() == 0) {
480 		pos = off = 0;
481 		return 0;
482 	}
483 	int blki = 0;
484 	int ii = 0;
485 	int offset = 0;
486 	int half = hcount;
487 	for(int i = index.GetCount(); --i >= 0;) {
488 		int m = blki + half;
489 		if(m - 1 < data.GetCount() && !less(val, data[m - 1].Top())) {
490 			blki = m;
491 			offset += index[i][ii];
492 			ii++;
493 		}
494 		ii += ii;
495 		half >>= 1;
496 	}
497 #ifdef flagIVTEST
498 	Check(blki, offset);
499 #endif
500 	if(blki < data.GetCount()) {
501 		if(!less(val, data[blki].Top()))
502 			offset += data[blki++].GetCount();
503 		if(blki < data.GetCount()) {
504 			pos = Upp::FindUpperBound(data[blki], val, less);
505 			off = offset;
506 			SetCache(blki, offset);
507 			return blki;
508 		}
509 	}
510 	pos = data.Top().GetCount();
511 	off = count - pos;
512 	blki--;
513 	SetCache(blki, off);
514 	return blki;
515 }
516 
517 template <class T>
518 template <class L>
FindLowerBound(const T & val,const L & less,int & off,int & pos) const519 int InVector<T>::FindLowerBound(const T& val, const L& less, int& off, int& pos) const
520 {
521 	if(data.GetCount() == 0) {
522 		pos = off = 0;
523 		return 0;
524 	}
525 	int blki = 0;
526 	int ii = 0;
527 	int offset = 0;
528 	int half = hcount;
529 	for(int i = index.GetCount(); --i >= 0;) {
530 		int m = blki + half;
531 		if(m < data.GetCount() && less(data[m][0], val)) {
532 			blki = m;
533 			offset += index[i][ii];
534 			ii++;
535 		}
536 		ii += ii;
537 		half >>= 1;
538 	}
539 #ifdef flagIVTEST
540 	Check(blki, offset);
541 #endif
542 	if(blki < data.GetCount()) {
543 		if(blki + 1 < data.GetCount() && less(data[blki + 1][0], val))
544 			offset += data[blki++].GetCount();
545 		if(blki < data.GetCount()) {
546 			pos = Upp::FindLowerBound(data[blki], val, less);
547 			off = offset;
548 			SetCache(blki, offset);
549 			return blki;
550 		}
551 	}
552 	pos = data.Top().GetCount();
553 	off = count - pos;
554 	blki--;
555 	SetCache(blki, off);
556 	return blki;
557 }
558 
559 template <class T>
560 template <class L>
InsertUpperBound(const T & val,const L & less)561 int InVector<T>::InsertUpperBound(const T& val, const L& less)
562 {
563 	if(data.GetCount() == 0) {
564 		count++;
565 		ClearCache();
566 		if(slave) {
567 			Slave()->Count(1);
568 			Slave()->AddFirst();
569 		}
570 		data.Add().Insert(0) = val;
571 		return 0;
572 	}
573 	int off;
574 	int pos;
575 	int blki = FindUpperBound(val, less, off, pos);
576 	Insert0(off + pos, blki, pos, off, &val);
577 	return off + pos;
578 }
579 
580 template <class T>
581 template <class L>
Find(const T & val,const L & less) const582 int InVector<T>::Find(const T& val, const L& less) const
583 {
584 	int i = FindLowerBound(val, less);
585 	return i < GetCount() && !less(val, (*this)[i]) ? i : -1;
586 }
587 
588 
589 template <class T>
SetIter(ConstIterator & it,int ii) const590 void InVector<T>::SetIter(ConstIterator& it, int ii) const
591 {
592 	if(count) {
593 		it.v = this;
594 		it.blki = FindBlock(ii, it.offset);
595 		it.begin = data[it.blki].Begin();
596 		it.end = data[it.blki].End();
597 		it.ptr = it.begin + ii;
598 	}
599 	else
600 		SetEnd(it);
601 }
602 
603 template <class T>
SetBegin(ConstIterator & it) const604 void InVector<T>::SetBegin(ConstIterator& it) const
605 {
606 	if(count) {
607 		it.v = this;
608 		it.blki = 0;
609 		it.ptr = it.begin = data[0].Begin();
610 		it.end = data[0].End();
611 		it.offset = 0;
612 	}
613 	else
614 		SetEnd(it);
615 }
616 
617 template <class T>
SetEnd(ConstIterator & it) const618 void InVector<T>::SetEnd(ConstIterator& it) const
619 {
620 	if(count) {
621 		it.v = this;
622 		it.blki = data.GetCount() - 1;
623 		it.begin = data.Top().Begin();
624 		it.ptr = it.end = data.Top().End();
625 		it.offset = count - data.Top().GetCount();
626 	}
627 	else {
628 		it.v = this;
629 		it.blki = 0;
630 		it.ptr = it.begin = it.end = NULL;
631 		it.offset = 0;
632 	}
633 }
634 
635 template <typename T>
operator +=(int d)636 force_inline typename InVector<T>::ConstIterator& InVector<T>::ConstIterator::operator+=(int d)
637 {
638 	if(d >= 0 ? d < end - ptr : -d < ptr - begin)
639 		ptr += d;
640 	else
641 		v->SetIter(*this, GetIndex() + d);
642 	ASSERT(end - begin == v->data[blki].GetCount());
643 	return *this;
644 }
645 
646 template <typename T>
NextBlk()647 void InVector<T>::ConstIterator::NextBlk()
648 {
649 	ASSERT(end - begin == v->data[blki].GetCount());
650 	if(blki + 1 < v->data.GetCount()) {
651 		offset += v->data[blki].GetCount();
652 		++blki;
653 		ptr = begin = v->data[blki].Begin();
654 		end = v->data[blki].End();
655 	}
656 }
657 
658 template <typename T>
PrevBlk()659 void InVector<T>::ConstIterator::PrevBlk()
660 {
661 	--blki;
662 	begin = v->data[blki].Begin();
663 	ptr = end = v->data[blki].End();
664 	offset -= v->data[blki].GetCount();
665 }
666 
667 template <typename T>
Swap(InVector & b)668 void InVector<T>::Swap(InVector& b)
669 {
670 	Upp::Swap(data, b.data);
671 	Upp::Swap(index, b.index);
672 	Upp::Swap(count, b.count);
673 	Upp::Swap(hcount, b.hcount);
674 	Upp::Swap(serial, b.serial);
675 	Upp::Swap(blk_high, b.blk_high);
676 	Upp::Swap(blk_low, b.blk_low);
677 	Upp::Swap(slave, b.slave);
678 }
679 
680 template <class T>
Xmlize(XmlIO & xio,const char * itemtag)681 void InVector<T>::Xmlize(XmlIO& xio, const char *itemtag)
682 {
683 	XmlizeContainer(xio, itemtag, *this);
684 }
685 
686 template <class T>
Jsonize(JsonIO & jio)687 void InVector<T>::Jsonize(JsonIO& jio)
688 {
689 	JsonizeArray<InVector<T>>(jio, *this);
690 }
691 
692 template <class T>
ToString() const693 String InVector<T>::ToString() const
694 {
695 	return AsStringArray(*this);
696 }
697 
698 template <class T>
DumpIndex() const699 void InVector<T>::DumpIndex() const
700 {
701 	String h;
702 	RLOG("------- InVector dump, count: " << GetCount() << ", index depth: " << index.GetCount());
703 	int64 alloc = 0;
704 	for(int i = 0; i < data.GetCount(); i++) {
705 		if(i)
706 			h << ", ";
707 		h << data[i].GetCount() << " (" << data[i].GetAlloc() << ")";
708 		alloc += data[i].GetAlloc();
709 	}
710 	RLOG("Data blocks: " << data.GetCount() << ", sizeof: " << data.GetCount() * sizeof(Vector<T>));
711 	RLOG("Total alloc: " << alloc);
712 	RLOG(h);
713 	for(int j = 0; j < index.GetCount(); j++) {
714 		h.Clear();
715 		h << index[j].GetCount() << ": ";
716 		for(int k = 0; k < index[j].GetCount(); k++) {
717 			if(k)
718 				h << ", ";
719 			h << index[j][k];
720 		}
721 		RLOG(h);
722 	}
723 	RLOG(".");
724 }
725 
726 #ifdef flagIVTEST
727 template <class T>
Check(int blki,int offset) const728 void InVector<T>::Check(int blki, int offset) const
729 {
730 	int off = 0;
731 	int all = 0;
732 	for(int i = 0; i < data.GetCount(); i++) {
733 		if(i < blki)
734 			off += data[i].GetCount();
735 		all += data[i].GetCount();
736 	}
737 	ASSERT(off == offset);
738 	ASSERT(all == count);
739 }
740 #endif
741 
742 template <class T>
Delete(IVIter it,int count)743 void InArray<T>::Delete(IVIter it, int count)
744 {
745 	ASSERT(count >= 0);
746 	while(count--)
747 		delete (T *)*it++;
748 }
749 
750 template <class T>
Delete(int i,int count)751 void InArray<T>::Delete(int i, int count)
752 {
753 	Delete(iv.GetIter(i), count);
754 }
755 
756 template <class T>
Init(int i,int count)757 void InArray<T>::Init(int i, int count)
758 {
759 	ASSERT(count >= 0);
760 	IVIter it = iv.GetIter(i);
761 	while(count--)
762 		*it++ = new T;
763 }
764 
765 template <class T>
InsertN(int i,int count)766 void InArray<T>::InsertN(int i, int count)
767 {
768 	iv.InsertN(i, count);
769 	Init(i, count);
770 }
771 
772 template <class T>
773 template <class Range>
InsertRange(int i,const Range & r)774 void InArray<T>::InsertRange(int i, const Range& r)
775 {
776 	int count = r.GetCount();
777 	iv.InsertN(i, count);
778 	IVIter it = iv.begin() + i;
779 	auto s = r.begin();
780 	while(count--)
781 		*it++ = new T(*s++);
782 }
783 
784 template <class T>
Remove(int i,int count)785 void InArray<T>::Remove(int i, int count)
786 {
787 	Delete(i, count);
788 	iv.Remove(i, count);
789 }
790 
791 template <class T>
SetCount(int n)792 void InArray<T>::SetCount(int n)
793 {
794 	if(n < GetCount())
795 		Trim(n);
796 	else
797 		InsertN(GetCount(), n - GetCount());
798 }
799 
800 template <class T>
Clear()801 void InArray<T>::Clear()
802 {
803 	Free();
804 	iv.Clear();
805 }
806 
807 template <class T>
Set(int i,const T & x,int count)808 void InArray<T>::Set(int i, const T& x, int count)
809 {
810 	Iterator it = GetIter(i);
811 	while(count-- > 0)
812 		*it++ = x;
813 }
814 
815 template <class T>
SetIter(ConstIterator & it,int ii) const816 void InArray<T>::SetIter(ConstIterator& it, int ii) const
817 {
818 	it.it = iv.GetIter(ii);
819 }
820 
821 template <class T>
SetBegin(ConstIterator & it) const822 void InArray<T>::SetBegin(ConstIterator& it) const
823 {
824 	it.it = iv.Begin();
825 }
826 
827 template <class T>
SetEnd(ConstIterator & it) const828 void InArray<T>::SetEnd(ConstIterator& it) const
829 {
830 	it.it = iv.End();
831 }
832 
833 template <class T>
InArray(const InArray & v,int)834 InArray<T>::InArray(const InArray& v, int)
835 {
836 	int n = v.GetCount();
837 	iv.SetCount(v.GetCount());
838 	ConstIterator s = v.Begin();
839 	IVIter it = iv.Begin();
840 	while(n--)
841 		*it++ = new T(clone(*s++));
842 }
843 
844 #ifdef UPP
845 template <class T>
Xmlize(XmlIO & xio,const char * itemtag)846 void InArray<T>::Xmlize(XmlIO& xio, const char *itemtag)
847 {
848 	XmlizeContainer(xio, itemtag, *this);
849 }
850 
851 template <class T>
Jsonize(JsonIO & jio)852 void InArray<T>::Jsonize(JsonIO& jio)
853 {
854 	JsonizeArray<InArray<T>>(jio, *this);
855 }
856 
857 template <class T>
ToString() const858 String InArray<T>::ToString() const
859 {
860 	return AsStringArray(*this);
861 }
862 
863 #endif
864 
865 #ifdef LLOG
866 #undef  LLOG
867 #endif