1 /**
2 * Copyright 2020 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef MINDSPORE_LITE_INCLUDE_LITE_UTILS_H_
18 #define MINDSPORE_LITE_INCLUDE_LITE_UTILS_H_
19
20 #ifndef NOT_USE_STL
21 #include <vector>
22 #include <string>
23 #include <memory>
24 #include <functional>
25 #else
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stddef.h>
30 #include <stdio.h>
31 #include <float.h>
32 #include <new>
33 #endif // NOT_USE_STL
34
35 #ifndef MS_API
36 #ifdef _WIN32
37 #define MS_API __declspec(dllexport)
38 #else
39 #define MS_API __attribute__((visibility("default")))
40 #endif
41 #endif
42
43 namespace mindspore {
44 namespace schema {
45 struct Tensor;
46 } // namespace schema
47
48 namespace tensor {
49 class MSTensor;
50 } // namespace tensor
51
52 namespace lite {
53 struct DeviceContext;
54 struct LiteQuantParam;
55 } // namespace lite
56
57 #ifdef NOT_USE_STL
58 #define MS_C_EXCEPTION(...) exit(1)
59
60 class String {
61 public:
String()62 String() {
63 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * 1));
64 if (buffer_ == nullptr) {
65 MS_C_EXCEPTION("malloc data failed");
66 }
67 buffer_[0] = '\0';
68 size_ = 0;
69 }
70
String(size_t count,char ch)71 String(size_t count, char ch) {
72 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (count + 1)));
73 if (buffer_ == nullptr) {
74 MS_C_EXCEPTION("malloc data failed");
75 }
76 memset(buffer_, ch, count);
77 buffer_[count] = '\0';
78 size_ = count;
79 }
80
String(const char * s,size_t count)81 String(const char *s, size_t count) {
82 if (s == nullptr) {
83 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * 1));
84 if (buffer_ == nullptr) {
85 MS_C_EXCEPTION("malloc data failed");
86 }
87 buffer_[0] = '\0';
88 size_ = 0;
89 return;
90 }
91 size_t size_s = strlen(s);
92 if (size_s <= count) {
93 size_ = size_s;
94 } else {
95 size_ = count;
96 }
97 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (size_ + 1)));
98 if (buffer_ == nullptr) {
99 MS_C_EXCEPTION("malloc data failed");
100 }
101 strncpy(buffer_, s, size_);
102 buffer_[size_] = '\0';
103 }
104
String(const char * s)105 explicit String(const char *s) {
106 if (s == nullptr) {
107 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * 1));
108 if (buffer_ == nullptr) {
109 MS_C_EXCEPTION("malloc data failed");
110 }
111 buffer_[0] = '\0';
112 size_ = 0;
113 return;
114 }
115 size_ = strlen(s);
116 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (size_ + 1)));
117 if (buffer_ == nullptr) {
118 MS_C_EXCEPTION("malloc data failed");
119 }
120 memcpy(buffer_, s, size_ + 1);
121 }
122
String(const String & other)123 String(const String &other) {
124 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (other.size_ + 1)));
125 if (buffer_ == nullptr) {
126 MS_C_EXCEPTION("malloc data failed");
127 }
128 size_ = other.size_;
129 memcpy(buffer_, other.buffer_, size_ + 1);
130 }
131
132 String(const String &other, size_t pos, size_t count = npos) {
133 if (pos >= other.size_) {
134 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * 1));
135 if (buffer_ == nullptr) {
136 MS_C_EXCEPTION("malloc data failed");
137 }
138 buffer_[0] = '\0';
139 size_ = 0;
140 } else {
141 if (count == npos) {
142 count = other.size_ - pos;
143 }
144 if (pos + count > other.size_) {
145 size_ = other.size_ - pos;
146 } else {
147 size_ = count;
148 }
149 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (size_ + 1)));
150 if (buffer_ == nullptr) {
151 MS_C_EXCEPTION("malloc data failed");
152 }
153 strncpy(buffer_, other.buffer_ + pos, size_);
154 buffer_[size_] = '\0';
155 }
156 }
157
~String()158 ~String() { free(buffer_); }
159
160 String &operator=(const String &str) {
161 if (this == &str) {
162 return *this;
163 }
164 free(buffer_);
165 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (str.size_ + 1)));
166 if (buffer_ == nullptr) {
167 MS_C_EXCEPTION("malloc data failed");
168 }
169 size_ = str.size_;
170 memcpy(buffer_, str.buffer_, size_ + 1);
171 return *this;
172 }
173
174 String &operator=(const char *str) {
175 free(buffer_);
176 if (str == nullptr) {
177 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * 1));
178 if (buffer_ == nullptr) {
179 MS_C_EXCEPTION("malloc data failed");
180 }
181 buffer_[0] = '\0';
182 size_ = 0;
183 return *this;
184 }
185 size_t size_s = strlen(str);
186 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * (size_s + 1)));
187 if (buffer_ == nullptr) {
188 MS_C_EXCEPTION("malloc data failed");
189 }
190 size_ = size_s;
191 memcpy(buffer_, str, size_ + 1);
192 return *this;
193 }
194
at(size_t pos)195 char &at(size_t pos) {
196 if (pos >= size_) {
197 MS_C_EXCEPTION("pos out of range");
198 }
199 return buffer_[pos];
200 }
201
at(size_t pos)202 const char &at(size_t pos) const {
203 if (pos >= size_) {
204 MS_C_EXCEPTION("pos out of range");
205 }
206 return buffer_[pos];
207 }
208
209 inline char &operator[](size_t pos) {
210 if (pos >= size_) {
211 MS_C_EXCEPTION("pos out of range");
212 }
213 return this->at(pos);
214 }
215
216 inline const char &operator[](size_t pos) const {
217 if (pos >= size_) {
218 MS_C_EXCEPTION("pos out of range");
219 }
220 return this->at(pos);
221 }
222
data()223 char *data() noexcept { return buffer_; }
data()224 const char *data() const noexcept { return buffer_; }
c_str()225 const char *c_str() const noexcept { return buffer_; }
226
227 // capacity
empty()228 bool empty() const noexcept { return size_ == 0; }
size()229 size_t size() const noexcept { return size_; }
length()230 size_t length() const noexcept { return size_; }
231
232 // operations
clear()233 void clear() noexcept {
234 free(buffer_);
235 buffer_ = reinterpret_cast<char *>(malloc(sizeof(char) * 1));
236 if (buffer_ == nullptr) {
237 MS_C_EXCEPTION("malloc data failed");
238 }
239 buffer_[0] = '\0';
240 size_ = 0;
241 }
242
append(size_t count,const char ch)243 String &append(size_t count, const char ch) {
244 (*this) += ch;
245 return *this;
246 }
247
append(const String & str)248 String &append(const String &str) {
249 (*this) += str;
250 return *this;
251 }
252
append(const char * str)253 String &append(const char *str) {
254 if (str == nullptr) {
255 return *this;
256 }
257 (*this) += str;
258 return *this;
259 }
260
261 String &operator+(const String &str) {
262 (*this) += str;
263 return *this;
264 }
265
266 String &operator+=(const String &str) {
267 size_t new_size = size_ + str.size_;
268 char *tmp = reinterpret_cast<char *>(malloc(sizeof(char) * (new_size + 1)));
269 if (tmp == nullptr) {
270 MS_C_EXCEPTION("malloc data failed");
271 }
272 memcpy(tmp, this->buffer_, size_ + 1);
273 strncat(tmp, str.buffer_, str.size_);
274 tmp[new_size] = '\0';
275 free(buffer_);
276 buffer_ = tmp;
277 size_ = new_size;
278 return *this;
279 }
280
281 String &operator+=(const char *str) {
282 if (str == nullptr) {
283 return *this;
284 }
285 size_t str_size = strlen(str);
286 size_t new_size = size_ + str_size;
287 char *tmp = reinterpret_cast<char *>(malloc(sizeof(char) * (new_size + 1)));
288 if (tmp == nullptr) {
289 MS_C_EXCEPTION("malloc data failed");
290 }
291 memcpy(tmp, this->buffer_, size_ + 1);
292 strncat(tmp, str, str_size);
293 tmp[new_size] = '\0';
294 free(buffer_);
295 buffer_ = tmp;
296 size_ = new_size;
297 return *this;
298 }
299
300 String &operator+=(const char ch) {
301 char *tmp = reinterpret_cast<char *>(malloc(sizeof(char) * (size_ + 2)));
302 if (tmp == nullptr) {
303 MS_C_EXCEPTION("malloc data failed");
304 }
305 memcpy(tmp, this->buffer_, size_ + 1);
306 tmp[size_] = ch;
307 tmp[size_ + 1] = '\0';
308 free(buffer_);
309 buffer_ = tmp;
310 size_ += 1;
311 return *this;
312 }
313
compare(const String & str)314 int compare(const String &str) const { return strcmp(buffer_, str.buffer_); }
compare(const char * str)315 int compare(const char *str) const { return strcmp(buffer_, str); }
316
317 String substr(size_t pos = 0, size_t count = npos) const { return String(*this, pos, count); }
318
319 static const size_t npos = -1;
320
321 private:
322 size_t size_;
323 char *buffer_;
324 };
325
326 inline String operator+(const String &lhs, const char *rhs) {
327 String str = lhs;
328 str += rhs;
329 return str;
330 }
331
332 inline String operator+(const char *lhs, const String &rhs) {
333 String str = rhs;
334 str += lhs;
335 return str;
336 }
337
338 inline bool operator!=(const String &lhs, const String &rhs) { return lhs.compare(rhs) != 0; }
339 inline bool operator==(const String &lhs, const String &rhs) { return lhs.compare(rhs) == 0; }
340 inline bool operator==(const String &lhs, const char *rhs) { return lhs.compare(rhs) == 0; }
341 inline bool operator==(const char *lhs, const String &rhs) { return rhs.compare(lhs) == 0; }
342
to_String(int32_t value)343 inline String to_String(int32_t value) {
344 char tmp[sizeof(int32_t) * 4];
345 snprintf(tmp, sizeof(int32_t) * 4, "%d", value);
346 return String(tmp, strlen(tmp));
347 }
348
to_String(float value)349 inline String to_String(float value) {
350 char tmp[FLT_MAX_10_EXP + 20];
351 snprintf(tmp, FLT_MAX_10_EXP + 20, "%f", value);
352 return String(tmp, strlen(tmp));
353 }
354
355 #define DEFAULT_CAPACITY 4
356 #define MIN(x, y) ((x < y) ? (x) : (y))
357 template <typename T>
358 class Vector {
359 public:
Vector()360 Vector() {
361 size_ = 0;
362 capacity_ = DEFAULT_CAPACITY;
363 elem_size_ = sizeof(T);
364 data_ = nullptr;
365 }
366
Vector(size_t size)367 explicit Vector(size_t size) {
368 size_ = size;
369 elem_size_ = sizeof(T);
370 capacity_ = (size == 0 ? DEFAULT_CAPACITY : size);
371 data_ = new (std::nothrow) T[capacity_];
372 if (data_ == nullptr) {
373 MS_C_EXCEPTION("malloc data failed");
374 }
375 }
376
Vector(size_t size,const T & value)377 Vector(size_t size, const T &value) {
378 size_ = size;
379 elem_size_ = sizeof(T);
380 capacity_ = (size == 0 ? DEFAULT_CAPACITY : size);
381 data_ = new (std::nothrow) T[capacity_];
382 if (data_ == nullptr) {
383 MS_C_EXCEPTION("malloc data failed");
384 }
385 for (int i = 0; i < static_cast<int>(size_); ++i) {
386 data_[i] = value;
387 }
388 }
389
Vector(const Vector<T> & vec)390 Vector(const Vector<T> &vec) {
391 size_ = vec.size_;
392 elem_size_ = sizeof(T);
393 capacity_ = vec.capacity_;
394 data_ = new (std::nothrow) T[capacity_];
395 if (data_ == nullptr) {
396 MS_C_EXCEPTION("malloc data failed");
397 }
398 for (int i = 0; i < static_cast<int>(size_); ++i) {
399 data_[i] = vec.data_[i];
400 }
401 }
402
~Vector()403 ~Vector() {
404 if (data_ != nullptr) {
405 delete[] data_;
406 }
407 }
408
clear()409 void clear() {
410 size_ = 0;
411 if (data_ != nullptr) {
412 delete[] data_;
413 data_ = nullptr;
414 }
415 }
416
push_back(const T & elem)417 void push_back(const T &elem) {
418 if (data_ == nullptr) {
419 data_ = new (std::nothrow) T[capacity_];
420 if (data_ == nullptr) {
421 MS_C_EXCEPTION("malloc data failed");
422 }
423 } else if (size_ == capacity_) {
424 resize(size_ + 1);
425 --size_;
426 }
427 data_[size_] = elem;
428 ++size_;
429 }
430
push_back(T && elem)431 void push_back(T &&elem) {
432 if (data_ == nullptr) {
433 data_ = new (std::nothrow) T[capacity_];
434 if (data_ == nullptr) {
435 MS_C_EXCEPTION("malloc data failed");
436 }
437 } else if (size_ == capacity_) {
438 resize(size_ + 1);
439 --size_;
440 }
441 data_[size_] = elem;
442 ++size_;
443 }
444
pop_back()445 void pop_back() {
446 if (size_ > 0) {
447 --size_;
448 } else {
449 MS_C_EXCEPTION("Index is out of range!");
450 }
451 }
452
insert(const T & elem,size_t index)453 void insert(const T &elem, size_t index) {
454 if (index <= size_) {
455 ++size_;
456 if (size_ > capacity_) {
457 resize(size_);
458 }
459 if (index == size_ - 1) {
460 push_back(elem);
461 } else {
462 for (int i = static_cast<int>(size_) - 1; i > static_cast<int>(index); --i) {
463 data_[i + 1] = data_[i];
464 }
465 data_[index] = elem;
466 }
467 } else {
468 MS_C_EXCEPTION("Input index is out of range!");
469 }
470 }
471
begin()472 T *begin() { return data_; }
473
begin()474 const T *begin() const { return data_; }
475
end()476 T *end() { return data_ + size_; }
477
end()478 const T *end() const { return data_ + size_; }
479
front()480 T &front() {
481 if (size_ > 0) {
482 return data_[0];
483 }
484 MS_C_EXCEPTION("Index is out of range!");
485 }
486
front()487 const T &front() const {
488 if (size_ > 0) {
489 return data_[0];
490 }
491 MS_C_EXCEPTION("Index is out of range!");
492 }
493
back()494 T &back() {
495 if (size_ > 0) {
496 return data_[size_ - 1];
497 }
498 MS_C_EXCEPTION("Index is out of range!");
499 }
500
back()501 const T &back() const {
502 if (size_ > 0) {
503 return data_[size_ - 1];
504 }
505 MS_C_EXCEPTION("Index is out of range!");
506 }
507
at(size_t index)508 T &at(size_t index) {
509 if (index < size_) {
510 return data_[index];
511 }
512 MS_C_EXCEPTION("Input index is out of range!");
513 }
514
at(size_t index)515 const T &at(size_t index) const {
516 if (index < size_) {
517 return data_[index];
518 }
519 MS_C_EXCEPTION("Input index is out of range!");
520 }
521
522 T &operator[](size_t index) {
523 if (index < size_) {
524 return data_[index];
525 }
526 MS_C_EXCEPTION("Input index is out of range!");
527 }
528
529 const T &operator[](size_t index) const {
530 if (index < size_) {
531 return data_[index];
532 }
533 MS_C_EXCEPTION("Input index is out of range!");
534 }
535
data()536 T *data() { return data_; }
537
data()538 const T *data() const { return data_; }
539
size()540 size_t size() const { return size_; }
541
capacity()542 size_t capacity() const { return capacity_; }
543
empty()544 bool empty() const { return size_ == 0; }
545
erase(size_t index)546 void erase(size_t index) {
547 if (index == size_ - 1) {
548 --size_;
549 } else if (index < size_) {
550 for (int i = index; i < static_cast<int>(size_); ++i) {
551 data_[i] = data_[i + 1];
552 }
553 --size_;
554 } else {
555 MS_C_EXCEPTION("Input index is out of range!");
556 }
557 }
558
resize(size_t size)559 void resize(size_t size) {
560 while (size > capacity_) {
561 capacity_ *= 2;
562 }
563 T *tmp = data_;
564 data_ = new (std::nothrow) T[capacity_];
565 if (data_ == nullptr) {
566 MS_C_EXCEPTION("malloc data failed");
567 }
568 for (int i = 0; i < MIN(static_cast<int>(size), static_cast<int>(size_)); ++i) {
569 data_[i] = tmp[i];
570 }
571 size_ = size;
572 delete[] tmp;
573 }
574
reserve(size_t capacity)575 void reserve(size_t capacity) {
576 if (capacity > capacity_) {
577 capacity_ = capacity;
578 }
579 }
580
581 Vector<T> &operator=(const Vector<T> &vec) {
582 if (this == &vec) {
583 return *this;
584 }
585 size_ = vec.size_;
586 elem_size_ = sizeof(T);
587 capacity_ = vec.capacity_;
588 data_ = new (std::nothrow) T[capacity_];
589 if (data_ == nullptr) {
590 MS_C_EXCEPTION("malloc data failed");
591 }
592 for (int i = 0; i < static_cast<int>(size_); ++i) {
593 data_[i] = vec.data_[i];
594 }
595 return *this;
596 }
597
598 private:
599 size_t size_;
600 size_t elem_size_;
601 size_t capacity_;
602 T *data_;
603 };
604 using TensorPtrVector = Vector<mindspore::schema::Tensor *>;
605 using Uint32Vector = Vector<uint32_t>;
606 class Allocator;
607 using AllocatorPtr = void *;
608 class Delegate;
609 using DelegatePtr = void *;
610 using DeviceContextVector = Vector<lite::DeviceContext>;
611 using KernelCallBack = void (*)(void *, void *);
612 #else
613 /// \brief Allocator defined a memory pool for malloc memory and free memory dynamically.
614 ///
615 /// \note List public class and interface for reference.
616 class Allocator;
617 using AllocatorPtr = std::shared_ptr<Allocator>;
618
619 class Delegate;
620 using DelegatePtr = std::shared_ptr<Delegate>;
621
622 using TensorPtrVector = std::vector<void *>;
623 using Uint32Vector = std::vector<uint32_t>;
624 template <typename T>
625 using Vector = std::vector<T>;
626
627 template <typename T>
to_string(T t)628 inline std::string to_string(T t) {
629 return std::to_string(t);
630 }
631
632 namespace tensor {
633 using String = std::string;
634 } // namespace tensor
635
636 namespace session {
637 using String = std::string;
638 } // namespace session
639
640 /// \brief CallBackParam defined input arguments for callBack function.
641 struct CallBackParam {
642 session::String node_name; /**< node name argument */
643 session::String node_type; /**< node type argument */
644 };
645
646 struct GPUCallBackParam : CallBackParam {
647 double execute_time{-1.f};
648 };
649
650 /// \brief KernelCallBack defined the function pointer for callBack.
651 using KernelCallBack = std::function<bool(Vector<tensor::MSTensor *> inputs, Vector<tensor::MSTensor *> outputs,
652 const CallBackParam &opInfo)>;
653
654 namespace lite {
655 using String = std::string;
656 using DeviceContextVector = std::vector<DeviceContext>;
657
658 /// \brief Set data of MSTensor from string vector.
659 ///
660 /// \param[in] input string vector.
661 /// \param[out] MSTensor.
662 ///
663 /// \return STATUS as an error code of this interface, STATUS is defined in errorcode.h.
664 int MS_API StringsToMSTensor(const Vector<String> &inputs, tensor::MSTensor *tensor);
665
666 /// \brief Get string vector from MSTensor.
667 /// \param[in] MSTensor.
668 /// \return string vector.
669 Vector<String> MS_API MSTensorToStrings(const tensor::MSTensor *tensor);
670 } // namespace lite
671 #endif // NOT_USE_STL
672 } // namespace mindspore
673 #endif // MINDSPORE_LITE_INCLUDE_LITE_UTILS_H_
674