tvm
string.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
24 #ifndef TVM_RUNTIME_CONTAINER_STRING_H_
25 #define TVM_RUNTIME_CONTAINER_STRING_H_
26 
27 #include <dmlc/logging.h>
29 #include <tvm/runtime/logging.h>
30 #include <tvm/runtime/memory.h>
31 #include <tvm/runtime/object.h>
32 
33 #include <algorithm>
34 #include <cstddef>
35 #include <cstring>
36 #include <initializer_list>
37 #include <memory>
38 #include <string>
39 #include <unordered_map>
40 #include <utility>
41 // We use c++14 std::experimental::string_view for optimizing hash computation
42 // only right now, its usage is limited in this file. Any broader usage of
43 // std::experiment in our core codebase is discouraged and needs community
44 // discussion for each use case. Reference for feature test macros of
45 // string_view:
46 // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
47 // https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
48 #if defined(__cpp_lib_experimental_string_view) && __cpp_lib_experimental_string_view >= 201411
49 #define TVM_USE_CXX14_STRING_VIEW_HASH 1
50 #else
51 #define TVM_USE_CXX14_STRING_VIEW_HASH 0
52 #endif
53 
54 // Tested with clang version 9.0.1 and c++17. It will detect string_view support
55 // correctly.
56 #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606
57 #define TVM_USE_CXX17_STRING_VIEW_HASH 1
58 #else
59 #define TVM_USE_CXX17_STRING_VIEW_HASH 0
60 #endif
61 
62 #if TVM_USE_CXX17_STRING_VIEW_HASH
63 #include <string_view>
64 #elif TVM_USE_CXX14_STRING_VIEW_HASH
65 #include <experimental/string_view>
66 #endif
67 
68 #include <type_traits>
69 #include <utility>
70 #include <vector>
71 
72 namespace llvm {
73 // String to llvm object compatibility.
74 class StringRef;
75 } // namespace llvm
76 
77 namespace tvm {
78 namespace runtime {
79 
80 // Forward declare TVMArgValue
81 class TVMArgValue;
82 
84 class StringObj : public Object {
85  public:
87  const char* data;
88 
90  uint64_t size;
91 
92  static constexpr const uint32_t _type_index = TypeIndex::kRuntimeString;
93  static constexpr const char* _type_key = "runtime.String";
95 
96  private:
98  class FromStd;
99 
100  friend class String;
101 };
102 
129 class String : public ObjectRef {
130  public:
134  String() : String(std::string()) {}
143  String(std::string other); // NOLINT(*)
144 
150  String(const char* other) // NOLINT(*)
151  : String(std::string(other)) {}
152 
156  String(std::nullptr_t) // NOLINT(*)
157  : ObjectRef(nullptr) {}
158 
165  inline String& operator=(std::string other);
166 
172  inline String& operator=(const char* other);
173 
182  int compare(const String& other) const {
183  return memncmp(data(), other.data(), size(), other.size());
184  }
185 
194  int compare(const std::string& other) const {
195  return memncmp(data(), other.data(), size(), other.size());
196  }
197 
206  int compare(const char* other) const {
207  return memncmp(data(), other, size(), std::strlen(other));
208  }
209 
215  const char* c_str() const { return get()->data; }
216 
222  size_t size() const {
223  const auto* ptr = get();
224  return ptr->size;
225  }
226 
232  size_t length() const { return size(); }
233 
239  bool empty() const { return size() == 0; }
240 
247  char at(size_t pos) const {
248  if (pos < size()) {
249  return data()[pos];
250  } else {
251  throw std::out_of_range("tvm::String index out of bounds");
252  }
253  }
254 
260  const char* data() const { return get()->data; }
261 
267  operator std::string() const { return std::string{get()->data, size()}; }
268 
269  // LLVM compatibility function, implemented in src/target/llvm/llvm_common.h
275  inline operator llvm::StringRef() const;
276 
282  inline static bool CanConvertFrom(const TVMArgValue& val);
283 
290  static size_t HashBytes(const char* data, size_t size) {
291  // This function falls back to string copy with c++11 compiler and is
292  // recommended to be compiled with c++14
293 #if TVM_USE_CXX17_STRING_VIEW_HASH
294  return std::hash<std::string_view>()(std::string_view(data, size));
295 #elif TVM_USE_CXX14_STRING_VIEW_HASH
296  return std::hash<std::experimental::string_view>()(std::experimental::string_view(data, size));
297 #else
298  return std::hash<std::string>()(std::string(data, size));
299 #endif
300  }
301 
303 
304  private:
315  static int memncmp(const char* lhs, const char* rhs, size_t lhs_count, size_t rhs_count);
316 
327  static String Concat(const char* lhs, size_t lhs_size, const char* rhs, size_t rhs_size) {
328  std::string ret(lhs, lhs_size);
329  ret.append(rhs, rhs_size);
330  return String(ret);
331  }
332 
333  // Overload + operator
334  friend String operator+(const String& lhs, const String& rhs);
335  friend String operator+(const String& lhs, const std::string& rhs);
336  friend String operator+(const std::string& lhs, const String& rhs);
337  friend String operator+(const String& lhs, const char* rhs);
338  friend String operator+(const char* lhs, const String& rhs);
339 
341 };
342 
345  public:
354  explicit FromStd(std::string other) : data_container{other} {}
355 
356  private:
358  std::string data_container;
359 
360  friend class String;
361 };
362 
363 inline String::String(std::string other) {
364  auto ptr = make_object<StringObj::FromStd>(std::move(other));
365  ptr->size = ptr->data_container.size();
366  ptr->data = ptr->data_container.data();
367  data_ = std::move(ptr);
368 }
369 
370 inline String& String::operator=(std::string other) {
371  String replace{std::move(other)};
372  data_.swap(replace.data_);
373  return *this;
374 }
375 
376 inline String& String::operator=(const char* other) { return operator=(std::string(other)); }
377 
378 inline String operator+(const String& lhs, const String& rhs) {
379  size_t lhs_size = lhs.size();
380  size_t rhs_size = rhs.size();
381  return String::Concat(lhs.data(), lhs_size, rhs.data(), rhs_size);
382 }
383 
384 inline String operator+(const String& lhs, const std::string& rhs) {
385  size_t lhs_size = lhs.size();
386  size_t rhs_size = rhs.size();
387  return String::Concat(lhs.data(), lhs_size, rhs.data(), rhs_size);
388 }
389 
390 inline String operator+(const std::string& lhs, const String& rhs) {
391  size_t lhs_size = lhs.size();
392  size_t rhs_size = rhs.size();
393  return String::Concat(lhs.data(), lhs_size, rhs.data(), rhs_size);
394 }
395 
396 inline String operator+(const char* lhs, const String& rhs) {
397  size_t lhs_size = std::strlen(lhs);
398  size_t rhs_size = rhs.size();
399  return String::Concat(lhs, lhs_size, rhs.data(), rhs_size);
400 }
401 
402 inline String operator+(const String& lhs, const char* rhs) {
403  size_t lhs_size = lhs.size();
404  size_t rhs_size = std::strlen(rhs);
405  return String::Concat(lhs.data(), lhs_size, rhs, rhs_size);
406 }
407 
408 // Overload < operator
409 inline bool operator<(const String& lhs, const std::string& rhs) { return lhs.compare(rhs) < 0; }
410 
411 inline bool operator<(const std::string& lhs, const String& rhs) { return rhs.compare(lhs) > 0; }
412 
413 inline bool operator<(const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
414 
415 inline bool operator<(const String& lhs, const char* rhs) { return lhs.compare(rhs) < 0; }
416 
417 inline bool operator<(const char* lhs, const String& rhs) { return rhs.compare(lhs) > 0; }
418 
419 // Overload > operator
420 inline bool operator>(const String& lhs, const std::string& rhs) { return lhs.compare(rhs) > 0; }
421 
422 inline bool operator>(const std::string& lhs, const String& rhs) { return rhs.compare(lhs) < 0; }
423 
424 inline bool operator>(const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
425 
426 inline bool operator>(const String& lhs, const char* rhs) { return lhs.compare(rhs) > 0; }
427 
428 inline bool operator>(const char* lhs, const String& rhs) { return rhs.compare(lhs) < 0; }
429 
430 // Overload <= operator
431 inline bool operator<=(const String& lhs, const std::string& rhs) { return lhs.compare(rhs) <= 0; }
432 
433 inline bool operator<=(const std::string& lhs, const String& rhs) { return rhs.compare(lhs) >= 0; }
434 
435 inline bool operator<=(const String& lhs, const String& rhs) { return lhs.compare(rhs) <= 0; }
436 
437 inline bool operator<=(const String& lhs, const char* rhs) { return lhs.compare(rhs) <= 0; }
438 
439 inline bool operator<=(const char* lhs, const String& rhs) { return rhs.compare(lhs) >= 0; }
440 
441 // Overload >= operator
442 inline bool operator>=(const String& lhs, const std::string& rhs) { return lhs.compare(rhs) >= 0; }
443 
444 inline bool operator>=(const std::string& lhs, const String& rhs) { return rhs.compare(lhs) <= 0; }
445 
446 inline bool operator>=(const String& lhs, const String& rhs) { return lhs.compare(rhs) >= 0; }
447 
448 inline bool operator>=(const String& lhs, const char* rhs) { return lhs.compare(rhs) >= 0; }
449 
450 inline bool operator>=(const char* lhs, const String& rhs) { return rhs.compare(rhs) <= 0; }
451 
452 // Overload == operator
453 inline bool operator==(const String& lhs, const std::string& rhs) { return lhs.compare(rhs) == 0; }
454 
455 inline bool operator==(const std::string& lhs, const String& rhs) { return rhs.compare(lhs) == 0; }
456 
457 inline bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
458 
459 inline bool operator==(const String& lhs, const char* rhs) { return lhs.compare(rhs) == 0; }
460 
461 inline bool operator==(const char* lhs, const String& rhs) { return rhs.compare(lhs) == 0; }
462 
463 // Overload != operator
464 inline bool operator!=(const String& lhs, const std::string& rhs) { return lhs.compare(rhs) != 0; }
465 
466 inline bool operator!=(const std::string& lhs, const String& rhs) { return rhs.compare(lhs) != 0; }
467 
468 inline bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
469 
470 inline bool operator!=(const String& lhs, const char* rhs) { return lhs.compare(rhs) != 0; }
471 
472 inline bool operator!=(const char* lhs, const String& rhs) { return rhs.compare(lhs) != 0; }
473 
474 inline std::ostream& operator<<(std::ostream& out, const String& input) {
475  out.write(input.data(), input.size());
476  return out;
477 }
478 
479 inline int String::memncmp(const char* lhs, const char* rhs, size_t lhs_count, size_t rhs_count) {
480  if (lhs == rhs && lhs_count == rhs_count) return 0;
481 
482  for (size_t i = 0; i < lhs_count && i < rhs_count; ++i) {
483  if (lhs[i] < rhs[i]) return -1;
484  if (lhs[i] > rhs[i]) return 1;
485  }
486  if (lhs_count < rhs_count) {
487  return -1;
488  } else if (lhs_count > rhs_count) {
489  return 1;
490  } else {
491  return 0;
492  }
493 }
494 
495 inline size_t ObjectHash::operator()(const ObjectRef& a) const {
496  if (const auto* str = a.as<StringObj>()) {
497  return String::HashBytes(str->data, str->size);
498  }
499  return ObjectPtrHash()(a);
500 }
501 
502 inline bool ObjectEqual::operator()(const ObjectRef& a, const ObjectRef& b) const {
503  if (a.same_as(b)) {
504  return true;
505  }
506  if (const auto* str_a = a.as<StringObj>()) {
507  if (const auto* str_b = b.as<StringObj>()) {
508  return String::memncmp(str_a->data, str_b->data, str_a->size, str_b->size) == 0;
509  }
510  }
511  return false;
512 }
513 } // namespace runtime
514 
515 // expose the functions to the root namespace.
516 using runtime::String;
517 using runtime::StringObj;
518 } // namespace tvm
519 
520 namespace std {
521 
522 template <>
523 struct hash<::tvm::runtime::String> {
524  std::size_t operator()(const ::tvm::runtime::String& str) const {
525  return ::tvm::runtime::String::HashBytes(str.data(), str.size());
526  }
527 };
528 } // namespace std
529 
530 #endif // TVM_RUNTIME_CONTAINER_STRING_H_
bool operator>(const char *lhs, const String &rhs)
Definition: string.h:428
uint64_t size
The length of the string object.
Definition: string.h:90
String-aware ObjectRef hash functor.
Definition: base.h:50
int compare(const char *other) const
Compares this to other.
Definition: string.h:206
String(std::nullptr_t)
Construct a new null object.
Definition: string.h:156
char at(size_t pos) const
Read an element.
Definition: string.h:247
const char * data() const
Return the data pointer.
Definition: string.h:260
Definition: string.h:72
bool operator!=(const char *lhs, const String &rhs)
Definition: string.h:472
bool operator<(const char *lhs, const String &rhs)
Definition: string.h:417
An object representing string moved from std::string.
Definition: string.h:344
Performance counters for profiling via the PAPI library.
Definition: analyzer.h:36
bool operator>=(const char *lhs, const String &rhs)
Definition: string.h:450
String()
Construct an empty string.
Definition: string.h:134
Runtime memory management.
Definition: loop_state.h:456
static size_t HashBytes(const char *data, size_t size)
Hash the binary bytes.
Definition: string.h:290
Base utilities for common POD(plain old data) container types.
std::ostream & operator<<(std::ostream &out, const String &input)
Definition: string.h:474
base class of all object containers.
Definition: object.h:165
size_t length() const
Return the length of the string.
Definition: string.h:232
const char * c_str() const
Returns a pointer to the char array in the string.
Definition: string.h:215
const char * data
The pointer to string data.
Definition: string.h:87
String operator+(const String &lhs, const char *rhs)
Definition: string.h:402
FromStd(std::string other)
Construct a new FromStd object.
Definition: string.h:354
ObjectRef hash functor.
Definition: object.h:617
bool operator<=(const char *lhs, const String &rhs)
Definition: string.h:439
size_t size() const
Return the length of the string.
Definition: string.h:222
Reference to string objects.
Definition: string.h:129
bool same_as(const ObjectRef &other) const
Comparator.
Definition: object.h:515
Base class of all object reference.
Definition: object.h:504
A managed object in the TVM runtime.
#define TVM_DECLARE_FINAL_OBJECT_INFO(TypeName, ParentType)
helper macro to declare type information in a final class.
Definition: object.h:664
bool operator==(const char *lhs, const String &rhs)
Definition: string.h:461
An object representing string. It&#39;s POD type.
Definition: string.h:84
String(const char *other)
Construct a new String object.
Definition: string.h:150
A single argument value to PackedFunc. Containing both type_code and TVMValue.
Definition: packed_func.h:583
bool empty() const
Retun if the string is empty.
Definition: string.h:239
const ObjectType * as() const
Try to downcast the internal Object to a raw pointer of a corresponding type.
Definition: object.h:858
int compare(const String &other) const
Compares this String object to other.
Definition: string.h:182
const Op & ret()
Return value.
#define TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(TypeName, ParentType, ObjectName)
Definition: object.h:721
Array< T > Concat(Array< T > lhs, const Array< T > &rhs)
Concat two Arrays.
Definition: array.h:719
int compare(const std::string &other) const
Compares this String object to other.
Definition: string.h:194