1// Iterators -*- C++ -*-
2
3// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License along
17// with this library; see the file COPYING.  If not, write to the Free
18// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19// USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction.  Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License.  This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30/*
31 *
32 * Copyright (c) 1994
33 * Hewlett-Packard Company
34 *
35 * Permission to use, copy, modify, distribute and sell this software
36 * and its documentation for any purpose is hereby granted without fee,
37 * provided that the above copyright notice appear in all copies and
38 * that both that copyright notice and this permission notice appear
39 * in supporting documentation.  Hewlett-Packard Company makes no
40 * representations about the suitability of this software for any
41 * purpose.  It is provided "as is" without express or implied warranty.
42 *
43 *
44 * Copyright (c) 1996-1998
45 * Silicon Graphics Computer Systems, Inc.
46 *
47 * Permission to use, copy, modify, distribute and sell this software
48 * and its documentation for any purpose is hereby granted without fee,
49 * provided that the above copyright notice appear in all copies and
50 * that both that copyright notice and this permission notice appear
51 * in supporting documentation.  Silicon Graphics makes no
52 * representations about the suitability of this software for any
53 * purpose.  It is provided "as is" without express or implied warranty.
54 */
55
56/** @file stl_iterator.h
57 *  This is an internal header file, included by other library headers.
58 *  You should not attempt to use it directly.
59 *
60 *  This file implements reverse_iterator, back_insert_iterator,
61 *  front_insert_iterator, insert_iterator, __normal_iterator, and their
62 *  supporting functions and overloaded operators.
63 */
64
65#ifndef __GLIBCPP_INTERNAL_ITERATOR_H
66#define __GLIBCPP_INTERNAL_ITERATOR_H
67
68namespace std
69{
70  // 24.4.1 Reverse iterators
71  /**
72   *  "Bidirectional and random access iterators have corresponding reverse
73   *  %iterator adaptors that iterate through the data structure in the
74   *  opposite direction.  They have the same signatures as the corresponding
75   *  iterators.  The fundamental relation between a reverse %iterator and its
76   *  corresponding %iterator @c i is established by the identity:
77   *  @code
78   *      &*(reverse_iterator(i)) == &*(i - 1)
79   *  @endcode
80   *
81   *  This mapping is dictated by the fact that while there is always a
82   *  pointer past the end of an array, there might not be a valid pointer
83   *  before the beginning of an array." [24.4.1]/1,2
84   *
85   *  Reverse iterators can be tricky and surprising at first.  Their
86   *  semantics make sense, however, and the trickiness is a side effect of
87   *  the requirement that the iterators must be safe.
88  */
89  template<typename _Iterator>
90    class reverse_iterator
91    : public iterator<typename iterator_traits<_Iterator>::iterator_category,
92		      typename iterator_traits<_Iterator>::value_type,
93		      typename iterator_traits<_Iterator>::difference_type,
94		      typename iterator_traits<_Iterator>::pointer,
95                      typename iterator_traits<_Iterator>::reference>
96    {
97    protected:
98      _Iterator current;
99
100    public:
101      typedef _Iterator 				       iterator_type;
102      typedef typename iterator_traits<_Iterator>::difference_type
103      							       difference_type;
104      typedef typename iterator_traits<_Iterator>::reference   reference;
105      typedef typename iterator_traits<_Iterator>::pointer     pointer;
106
107    public:
108      /**
109       *  The default constructor default-initializes member @p current.
110       *  If it is a pointer, that means it is zero-initialized.
111      */
112      // _GLIBCPP_RESOLVE_LIB_DEFECTS
113      // 235 No specification of default ctor for reverse_iterator
114      reverse_iterator() : current() { }
115
116      /**
117       *  This %iterator will move in the opposite direction that @p x does.
118      */
119      explicit
120      reverse_iterator(iterator_type __x) : current(__x) { }
121
122      /**
123       *  The copy constructor is normal.
124      */
125      reverse_iterator(const reverse_iterator& __x)
126      : current(__x.current) { }
127
128      /**
129       *  A reverse_iterator across other types can be copied in the normal
130       *  fashion.
131      */
132      template<typename _Iter>
133        reverse_iterator(const reverse_iterator<_Iter>& __x)
134	: current(__x.base()) { }
135
136      /**
137       *  @return  @c current, the %iterator used for underlying work.
138      */
139      iterator_type
140      base() const { return current; }
141
142      /**
143       *  @return  TODO
144       *
145       *  @doctodo
146      */
147      reference
148      operator*() const
149      {
150	_Iterator __tmp = current;
151	return *--__tmp;
152      }
153
154      /**
155       *  @return  TODO
156       *
157       *  @doctodo
158      */
159      pointer
160      operator->() const { return &(operator*()); }
161
162      /**
163       *  @return  TODO
164       *
165       *  @doctodo
166      */
167      reverse_iterator&
168      operator++()
169      {
170	--current;
171	return *this;
172      }
173
174      /**
175       *  @return  TODO
176       *
177       *  @doctodo
178      */
179      reverse_iterator
180      operator++(int)
181      {
182	reverse_iterator __tmp = *this;
183	--current;
184	return __tmp;
185      }
186
187      /**
188       *  @return  TODO
189       *
190       *  @doctodo
191      */
192      reverse_iterator&
193      operator--()
194      {
195	++current;
196	return *this;
197      }
198
199      /**
200       *  @return  TODO
201       *
202       *  @doctodo
203      */
204      reverse_iterator operator--(int)
205      {
206	reverse_iterator __tmp = *this;
207	++current;
208	return __tmp;
209      }
210
211      /**
212       *  @return  TODO
213       *
214       *  @doctodo
215      */
216      reverse_iterator
217      operator+(difference_type __n) const
218      { return reverse_iterator(current - __n); }
219
220      /**
221       *  @return  TODO
222       *
223       *  @doctodo
224      */
225      reverse_iterator&
226      operator+=(difference_type __n)
227      {
228	current -= __n;
229	return *this;
230      }
231
232      /**
233       *  @return  TODO
234       *
235       *  @doctodo
236      */
237      reverse_iterator
238      operator-(difference_type __n) const
239      { return reverse_iterator(current + __n); }
240
241      /**
242       *  @return  TODO
243       *
244       *  @doctodo
245      */
246      reverse_iterator&
247      operator-=(difference_type __n)
248      {
249	current += __n;
250	return *this;
251      }
252
253      /**
254       *  @return  TODO
255       *
256       *  @doctodo
257      */
258      reference
259      operator[](difference_type __n) const { return *(*this + __n); }
260    };
261
262  //@{
263  /**
264   *  @param  x  A %reverse_iterator.
265   *  @param  y  A %reverse_iterator.
266   *  @return  A simple bool.
267   *
268   *  Reverse iterators forward many operations to their underlying base()
269   *  iterators.  Others are implemented in terms of one another.
270   *
271  */
272  template<typename _Iterator>
273    inline bool
274    operator==(const reverse_iterator<_Iterator>& __x,
275	       const reverse_iterator<_Iterator>& __y)
276    { return __x.base() == __y.base(); }
277
278  template<typename _Iterator>
279    inline bool
280    operator<(const reverse_iterator<_Iterator>& __x,
281	      const reverse_iterator<_Iterator>& __y)
282    { return __y.base() < __x.base(); }
283
284  template<typename _Iterator>
285    inline bool
286    operator!=(const reverse_iterator<_Iterator>& __x,
287	       const reverse_iterator<_Iterator>& __y)
288    { return !(__x == __y); }
289
290  template<typename _Iterator>
291    inline bool
292    operator>(const reverse_iterator<_Iterator>& __x,
293	      const reverse_iterator<_Iterator>& __y)
294    { return __y < __x; }
295
296  template<typename _Iterator>
297    inline bool
298    operator<=(const reverse_iterator<_Iterator>& __x,
299		const reverse_iterator<_Iterator>& __y)
300    { return !(__y < __x); }
301
302  template<typename _Iterator>
303    inline bool
304    operator>=(const reverse_iterator<_Iterator>& __x,
305	       const reverse_iterator<_Iterator>& __y)
306    { return !(__x < __y); }
307
308  template<typename _Iterator>
309    inline typename reverse_iterator<_Iterator>::difference_type
310    operator-(const reverse_iterator<_Iterator>& __x,
311	      const reverse_iterator<_Iterator>& __y)
312    { return __y.base() - __x.base(); }
313
314  template<typename _Iterator>
315    inline reverse_iterator<_Iterator>
316    operator+(typename reverse_iterator<_Iterator>::difference_type __n,
317	      const reverse_iterator<_Iterator>& __x)
318    { return reverse_iterator<_Iterator>(__x.base() - __n); }
319  //@}
320
321  // 24.4.2.2.1 back_insert_iterator
322  /**
323   *  @brief  Turns assignment into insertion.
324   *
325   *  These are output iterators, constructed from a container-of-T.
326   *  Assigning a T to the iterator appends it to the container using
327   *  push_back.
328   *
329   *  Tip:  Using the back_inserter function to create these iterators can
330   *  save typing.
331  */
332  template<typename _Container>
333    class back_insert_iterator
334    : public iterator<output_iterator_tag, void, void, void, void>
335    {
336    protected:
337      _Container* container;
338
339    public:
340      /// A nested typedef for the type of whatever container you used.
341      typedef _Container          container_type;
342
343      /// The only way to create this %iterator is with a container.
344      explicit
345      back_insert_iterator(_Container& __x) : container(&__x) { }
346
347      /**
348       *  @param  value  An instance of whatever type
349       *                 container_type::const_reference is; presumably a
350       *                 reference-to-const T for container<T>.
351       *  @return  This %iterator, for chained operations.
352       *
353       *  This kind of %iterator doesn't really have a "position" in the
354       *  container (you can think of the position as being permanently at
355       *  the end, if you like).  Assigning a value to the %iterator will
356       *  always append the value to the end of the container.
357      */
358      back_insert_iterator&
359      operator=(typename _Container::const_reference __value)
360      {
361	container->push_back(__value);
362	return *this;
363      }
364
365      /// Simply returns *this.
366      back_insert_iterator&
367      operator*() { return *this; }
368
369      /// Simply returns *this.  (This %iterator does not "move".)
370      back_insert_iterator&
371      operator++() { return *this; }
372
373      /// Simply returns *this.  (This %iterator does not "move".)
374      back_insert_iterator
375      operator++(int) { return *this; }
376    };
377
378  /**
379   *  @param  x  A container of arbitrary type.
380   *  @return  An instance of back_insert_iterator working on @p x.
381   *
382   *  This wrapper function helps in creating back_insert_iterator instances.
383   *  Typing the name of the %iterator requires knowing the precise full
384   *  type of the container, which can be tedious and impedes generic
385   *  programming.  Using this function lets you take advantage of automatic
386   *  template parameter deduction, making the compiler match the correct
387   *  types for you.
388  */
389  template<typename _Container>
390    inline back_insert_iterator<_Container>
391    back_inserter(_Container& __x)
392    { return back_insert_iterator<_Container>(__x); }
393
394  /**
395   *  @brief  Turns assignment into insertion.
396   *
397   *  These are output iterators, constructed from a container-of-T.
398   *  Assigning a T to the iterator prepends it to the container using
399   *  push_front.
400   *
401   *  Tip:  Using the front_inserter function to create these iterators can
402   *  save typing.
403  */
404  template<typename _Container>
405    class front_insert_iterator
406    : public iterator<output_iterator_tag, void, void, void, void>
407    {
408    protected:
409      _Container* container;
410
411    public:
412      /// A nested typedef for the type of whatever container you used.
413      typedef _Container          container_type;
414
415      /// The only way to create this %iterator is with a container.
416      explicit front_insert_iterator(_Container& __x) : container(&__x) { }
417
418      /**
419       *  @param  value  An instance of whatever type
420       *                 container_type::const_reference is; presumably a
421       *                 reference-to-const T for container<T>.
422       *  @return  This %iterator, for chained operations.
423       *
424       *  This kind of %iterator doesn't really have a "position" in the
425       *  container (you can think of the position as being permanently at
426       *  the front, if you like).  Assigning a value to the %iterator will
427       *  always prepend the value to the front of the container.
428      */
429      front_insert_iterator&
430      operator=(typename _Container::const_reference __value)
431      {
432	container->push_front(__value);
433	return *this;
434      }
435
436      /// Simply returns *this.
437      front_insert_iterator&
438      operator*() { return *this; }
439
440      /// Simply returns *this.  (This %iterator does not "move".)
441      front_insert_iterator&
442      operator++() { return *this; }
443
444      /// Simply returns *this.  (This %iterator does not "move".)
445      front_insert_iterator
446      operator++(int) { return *this; }
447    };
448
449  /**
450   *  @param  x  A container of arbitrary type.
451   *  @return  An instance of front_insert_iterator working on @p x.
452   *
453   *  This wrapper function helps in creating front_insert_iterator instances.
454   *  Typing the name of the %iterator requires knowing the precise full
455   *  type of the container, which can be tedious and impedes generic
456   *  programming.  Using this function lets you take advantage of automatic
457   *  template parameter deduction, making the compiler match the correct
458   *  types for you.
459  */
460  template<typename _Container>
461    inline front_insert_iterator<_Container>
462    front_inserter(_Container& __x)
463    { return front_insert_iterator<_Container>(__x); }
464
465  /**
466   *  @brief  Turns assignment into insertion.
467   *
468   *  These are output iterators, constructed from a container-of-T.
469   *  Assigning a T to the iterator inserts it in the container at the
470   *  %iterator's position, rather than overwriting the value at that
471   *  position.
472   *
473   *  (Sequences will actually insert a @e copy of the value before the
474   *  %iterator's position.)
475   *
476   *  Tip:  Using the inserter function to create these iterators can
477   *  save typing.
478  */
479  template<typename _Container>
480    class insert_iterator
481    : public iterator<output_iterator_tag, void, void, void, void>
482    {
483    protected:
484      _Container* container;
485      typename _Container::iterator iter;
486
487    public:
488      /// A nested typedef for the type of whatever container you used.
489      typedef _Container          container_type;
490
491      /**
492       *  The only way to create this %iterator is with a container and an
493       *  initial position (a normal %iterator into the container).
494      */
495      insert_iterator(_Container& __x, typename _Container::iterator __i)
496      : container(&__x), iter(__i) {}
497
498      /**
499       *  @param  value  An instance of whatever type
500       *                 container_type::const_reference is; presumably a
501       *                 reference-to-const T for container<T>.
502       *  @return  This %iterator, for chained operations.
503       *
504       *  This kind of %iterator maintains its own position in the
505       *  container.  Assigning a value to the %iterator will insert the
506       *  value into the container at the place before the %iterator.
507       *
508       *  The position is maintained such that subsequent assignments will
509       *  insert values immediately after one another.  For example,
510       *  @code
511       *     // vector v contains A and Z
512       *
513       *     insert_iterator i (v, ++v.begin());
514       *     i = 1;
515       *     i = 2;
516       *     i = 3;
517       *
518       *     // vector v contains A, 1, 2, 3, and Z
519       *  @endcode
520      */
521      insert_iterator&
522      operator=(const typename _Container::const_reference __value)
523      {
524	iter = container->insert(iter, __value);
525	++iter;
526	return *this;
527      }
528
529      /// Simply returns *this.
530      insert_iterator&
531      operator*() { return *this; }
532
533      /// Simply returns *this.  (This %iterator does not "move".)
534      insert_iterator&
535      operator++() { return *this; }
536
537      /// Simply returns *this.  (This %iterator does not "move".)
538      insert_iterator&
539      operator++(int) { return *this; }
540    };
541
542  /**
543   *  @param  x  A container of arbitrary type.
544   *  @return  An instance of insert_iterator working on @p x.
545   *
546   *  This wrapper function helps in creating insert_iterator instances.
547   *  Typing the name of the %iterator requires knowing the precise full
548   *  type of the container, which can be tedious and impedes generic
549   *  programming.  Using this function lets you take advantage of automatic
550   *  template parameter deduction, making the compiler match the correct
551   *  types for you.
552  */
553  template<typename _Container, typename _Iterator>
554    inline insert_iterator<_Container>
555    inserter(_Container& __x, _Iterator __i)
556    {
557      return insert_iterator<_Container>(__x,
558					 typename _Container::iterator(__i));
559    }
560} // namespace std
561
562namespace __gnu_cxx
563{
564  // This iterator adapter is 'normal' in the sense that it does not
565  // change the semantics of any of the operators of its iterator
566  // parameter.  Its primary purpose is to convert an iterator that is
567  // not a class, e.g. a pointer, into an iterator that is a class.
568  // The _Container parameter exists solely so that different containers
569  // using this template can instantiate different types, even if the
570  // _Iterator parameter is the same.
571  using std::iterator_traits;
572  using std::iterator;
573  template<typename _Iterator, typename _Container>
574    class __normal_iterator
575      : public iterator<typename iterator_traits<_Iterator>::iterator_category,
576                        typename iterator_traits<_Iterator>::value_type,
577                        typename iterator_traits<_Iterator>::difference_type,
578                        typename iterator_traits<_Iterator>::pointer,
579                        typename iterator_traits<_Iterator>::reference>
580    {
581    protected:
582      _Iterator _M_current;
583
584    public:
585      typedef typename iterator_traits<_Iterator>::difference_type
586      							       difference_type;
587      typedef typename iterator_traits<_Iterator>::reference   reference;
588      typedef typename iterator_traits<_Iterator>::pointer     pointer;
589
590      __normal_iterator() : _M_current(_Iterator()) { }
591
592      explicit
593      __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
594
595      // Allow iterator to const_iterator conversion
596      template<typename _Iter>
597      inline __normal_iterator(const __normal_iterator<_Iter, _Container>& __i)
598	: _M_current(__i.base()) { }
599
600      // Forward iterator requirements
601      reference
602      operator*() const { return *_M_current; }
603
604      pointer
605      operator->() const { return _M_current; }
606
607      __normal_iterator&
608      operator++() { ++_M_current; return *this; }
609
610      __normal_iterator
611      operator++(int) { return __normal_iterator(_M_current++); }
612
613      // Bidirectional iterator requirements
614      __normal_iterator&
615      operator--() { --_M_current; return *this; }
616
617      __normal_iterator
618      operator--(int) { return __normal_iterator(_M_current--); }
619
620      // Random access iterator requirements
621      reference
622      operator[](const difference_type& __n) const
623      { return _M_current[__n]; }
624
625      __normal_iterator&
626      operator+=(const difference_type& __n)
627      { _M_current += __n; return *this; }
628
629      __normal_iterator
630      operator+(const difference_type& __n) const
631      { return __normal_iterator(_M_current + __n); }
632
633      __normal_iterator&
634      operator-=(const difference_type& __n)
635      { _M_current -= __n; return *this; }
636
637      __normal_iterator
638      operator-(const difference_type& __n) const
639      { return __normal_iterator(_M_current - __n); }
640
641      const _Iterator&
642      base() const { return _M_current; }
643    };
644
645  // Note: In what follows, the left- and right-hand-side iterators are
646  // allowed to vary in types (conceptually in cv-qualification) so that
647  // comparaison between cv-qualified and non-cv-qualified iterators be
648  // valid.  However, the greedy and unfriendly operators in std::rel_ops
649  // will make overload resolution ambiguous (when in scope) if we don't
650  // provide overloads whose operands are of the same type.  Can someone
651  // remind me what generic programming is about? -- Gaby
652
653  // Forward iterator requirements
654  template<typename _IteratorL, typename _IteratorR, typename _Container>
655  inline bool
656  operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
657	     const __normal_iterator<_IteratorR, _Container>& __rhs)
658  { return __lhs.base() == __rhs.base(); }
659
660  template<typename _Iterator, typename _Container>
661  inline bool
662  operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
663             const __normal_iterator<_Iterator, _Container>& __rhs)
664  { return __lhs.base() == __rhs.base(); }
665
666  template<typename _IteratorL, typename _IteratorR, typename _Container>
667  inline bool
668  operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
669	     const __normal_iterator<_IteratorR, _Container>& __rhs)
670  { return __lhs.base() != __rhs.base(); }
671
672  template<typename _Iterator, typename _Container>
673  inline bool
674  operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
675             const __normal_iterator<_Iterator, _Container>& __rhs)
676  { return __lhs.base() != __rhs.base(); }
677
678  // Random access iterator requirements
679  template<typename _IteratorL, typename _IteratorR, typename _Container>
680  inline bool
681  operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
682	    const __normal_iterator<_IteratorR, _Container>& __rhs)
683  { return __lhs.base() < __rhs.base(); }
684
685  template<typename _Iterator, typename _Container>
686  inline bool
687  operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
688             const __normal_iterator<_Iterator, _Container>& __rhs)
689  { return __lhs.base() < __rhs.base(); }
690
691  template<typename _IteratorL, typename _IteratorR, typename _Container>
692  inline bool
693  operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
694	    const __normal_iterator<_IteratorR, _Container>& __rhs)
695  { return __lhs.base() > __rhs.base(); }
696
697  template<typename _Iterator, typename _Container>
698  inline bool
699  operator>(const __normal_iterator<_Iterator, _Container>& __lhs,
700	    const __normal_iterator<_Iterator, _Container>& __rhs)
701  { return __lhs.base() > __rhs.base(); }
702
703  template<typename _IteratorL, typename _IteratorR, typename _Container>
704  inline bool
705  operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
706	     const __normal_iterator<_IteratorR, _Container>& __rhs)
707  { return __lhs.base() <= __rhs.base(); }
708
709  template<typename _Iterator, typename _Container>
710  inline bool
711  operator<=(const __normal_iterator<_Iterator, _Container>& __lhs,
712	     const __normal_iterator<_Iterator, _Container>& __rhs)
713  { return __lhs.base() <= __rhs.base(); }
714
715  template<typename _IteratorL, typename _IteratorR, typename _Container>
716  inline bool
717  operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
718	     const __normal_iterator<_IteratorR, _Container>& __rhs)
719  { return __lhs.base() >= __rhs.base(); }
720
721  template<typename _Iterator, typename _Container>
722  inline bool
723  operator>=(const __normal_iterator<_Iterator, _Container>& __lhs,
724	     const __normal_iterator<_Iterator, _Container>& __rhs)
725  { return __lhs.base() >= __rhs.base(); }
726
727  // _GLIBCPP_RESOLVE_LIB_DEFECTS
728  // According to the resolution of DR179 not only the various comparison
729  // operators but also operator- must accept mixed iterator/const_iterator
730  // parameters.
731  template<typename _IteratorL, typename _IteratorR, typename _Container>
732  inline typename __normal_iterator<_IteratorL, _Container>::difference_type
733  operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
734	     const __normal_iterator<_IteratorR, _Container>& __rhs)
735  { return __lhs.base() - __rhs.base(); }
736
737  template<typename _Iterator, typename _Container>
738  inline __normal_iterator<_Iterator, _Container>
739  operator+(typename __normal_iterator<_Iterator, _Container>::difference_type __n,
740	    const __normal_iterator<_Iterator, _Container>& __i)
741  { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); }
742} // namespace __gnu_cxx
743
744#endif
745
746// Local Variables:
747// mode:C++
748// End:
749