Imported Upstream version 2.3.1
[platform/upstream/harfbuzz.git] / src / hb-vector.hh
1 /*
2  * Copyright © 2017,2018  Google, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Google Author(s): Behdad Esfahbod
25  */
26
27 #ifndef HB_VECTOR_HH
28 #define HB_VECTOR_HH
29
30 #include "hb.hh"
31 #include "hb-array.hh"
32 #include "hb-null.hh"
33
34
35 template <typename Type>
36 struct hb_vector_t
37 {
38   typedef Type item_t;
39   static constexpr unsigned item_size = hb_static_size (Type);
40
41   HB_NO_COPY_ASSIGN_TEMPLATE (hb_vector_t, Type);
42   hb_vector_t ()  { init (); }
43   ~hb_vector_t () { fini (); }
44
45   unsigned int length;
46   private:
47   int allocated; /* == -1 means allocation failed. */
48   Type *arrayZ_;
49   public:
50
51   void init ()
52   {
53     allocated = length = 0;
54     arrayZ_ = nullptr;
55   }
56
57   void fini ()
58   {
59     if (arrayZ_)
60       free (arrayZ_);
61     init ();
62   }
63   void fini_deep ()
64   {
65     Type *array = arrayZ();
66     unsigned int count = length;
67     for (unsigned int i = 0; i < count; i++)
68       array[i].fini ();
69     fini ();
70   }
71
72   const Type * arrayZ () const { return arrayZ_; }
73         Type * arrayZ ()       { return arrayZ_; }
74
75   Type& operator [] (int i_)
76   {
77     unsigned int i = (unsigned int) i_;
78     if (unlikely (i >= length))
79       return Crap (Type);
80     return arrayZ()[i];
81   }
82   const Type& operator [] (int i_) const
83   {
84     unsigned int i = (unsigned int) i_;
85     if (unlikely (i >= length))
86       return Null(Type);
87     return arrayZ()[i];
88   }
89
90   explicit_operator bool () const { return length; }
91
92   hb_array_t<Type> as_array ()
93   { return hb_array (arrayZ(), length); }
94   hb_array_t<const Type> as_array () const
95   { return hb_array (arrayZ(), length); }
96
97   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
98   { return as_array ().sub_array (start_offset, count);}
99   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
100   { return as_array ().sub_array (start_offset, count);}
101   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
102   { return as_array ().sub_array (start_offset, count);}
103   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
104   { return as_array ().sub_array (start_offset, count);}
105
106   hb_sorted_array_t<Type> as_sorted_array ()
107   { return hb_sorted_array (arrayZ(), length); }
108   hb_sorted_array_t<const Type> as_sorted_array () const
109   { return hb_sorted_array (arrayZ(), length); }
110
111   hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int count) const
112   { return as_sorted_array ().sorted_sub_array (start_offset, count);}
113   hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
114   { return as_sorted_array ().sorted_sub_array (start_offset, count);}
115   hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int count)
116   { return as_sorted_array ().sorted_sub_array (start_offset, count);}
117   hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
118   { return as_sorted_array ().sorted_sub_array (start_offset, count);}
119
120   template <typename T> explicit_operator T * () { return arrayZ(); }
121   template <typename T> explicit_operator const T * () const { return arrayZ(); }
122   operator hb_array_t<Type> ()             { return as_array (); }
123   operator hb_array_t<const Type> () const { return as_array (); }
124
125   Type * operator  + (unsigned int i) { return arrayZ() + i; }
126   const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
127
128   Type *push ()
129   {
130     if (unlikely (!resize (length + 1)))
131       return &Crap(Type);
132     return &arrayZ()[length - 1];
133   }
134   Type *push (const Type& v)
135   {
136     Type *p = push ();
137     *p = v;
138     return p;
139   }
140
141   bool in_error () const { return allocated < 0; }
142
143   /* Allocate for size but don't adjust length. */
144   bool alloc (unsigned int size)
145   {
146     if (unlikely (allocated < 0))
147       return false;
148
149     if (likely (size <= (unsigned) allocated))
150       return true;
151
152     /* Reallocate */
153
154     unsigned int new_allocated = allocated;
155     while (size >= new_allocated)
156       new_allocated += (new_allocated >> 1) + 8;
157
158     Type *new_array = nullptr;
159     bool overflows =
160       (int) new_allocated < 0 ||
161       (new_allocated < (unsigned) allocated) ||
162       hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
163     if (likely (!overflows))
164       new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));
165
166     if (unlikely (!new_array))
167     {
168       allocated = -1;
169       return false;
170     }
171
172     arrayZ_ = new_array;
173     allocated = new_allocated;
174
175     return true;
176   }
177
178   bool resize (int size_)
179   {
180     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
181     if (!alloc (size))
182       return false;
183
184     if (size > length)
185       memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));
186
187     length = size;
188     return true;
189   }
190
191   void pop ()
192   {
193     if (!length) return;
194     length--;
195   }
196
197   void remove (unsigned int i)
198   {
199     if (unlikely (i >= length))
200       return;
201     Type *array = arrayZ();
202     memmove (static_cast<void *> (&array[i]),
203              static_cast<void *> (&array[i + 1]),
204              (length - i - 1) * sizeof (Type));
205     length--;
206   }
207
208   void shrink (int size_)
209   {
210     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
211      if (size < length)
212        length = size;
213   }
214
215   template <typename T>
216   Type *find (T v)
217   {
218     Type *array = arrayZ();
219     for (unsigned int i = 0; i < length; i++)
220       if (array[i] == v)
221         return &array[i];
222     return nullptr;
223   }
224   template <typename T>
225   const Type *find (T v) const
226   {
227     const Type *array = arrayZ();
228     for (unsigned int i = 0; i < length; i++)
229       if (array[i] == v)
230         return &array[i];
231     return nullptr;
232   }
233
234   void qsort (int (*cmp)(const void*, const void*))
235   { as_array ().qsort (cmp); }
236   void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
237   { as_array ().qsort (start, end); }
238
239   template <typename T>
240   Type *lsearch (const T &x, Type *not_found = nullptr)
241   { return as_array ().lsearch (x, not_found); }
242   template <typename T>
243   const Type *lsearch (const T &x, const Type *not_found = nullptr) const
244   { return as_array ().lsearch (x, not_found); }
245
246   template <typename T>
247   Type *bsearch (const T &x, Type *not_found = nullptr)
248   { return as_sorted_array ().bsearch (x, not_found); }
249   template <typename T>
250   const Type *bsearch (const T &x, const Type *not_found = nullptr) const
251   { return as_sorted_array ().bsearch (x, not_found); }
252   template <typename T>
253   bool bfind (const T &x, unsigned int *i = nullptr,
254                      hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
255                      unsigned int to_store = (unsigned int) -1) const
256   { return as_sorted_array ().bfind (x, i, not_found, to_store); }
257 };
258
259
260 #endif /* HB_VECTOR_HH */