find_cstr.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. // Date: Tue Jun 23 15:03:24 CST 2015
  18. #ifndef BUTIL_FIND_CSTR_H
  19. #define BUTIL_FIND_CSTR_H
  20. #include <string>
  21. #include <map>
  22. #include <algorithm>
  23. #include "butil/thread_local.h"
  24. // Find c-string in maps with std::string as keys without memory allocations.
  25. // Example:
  26. // std::map<std::string, int> string_map;
  27. //
  28. // string_map.find("hello"); // constructed a temporary std::string
  29. // // which needs memory allocation.
  30. //
  31. // find_cstr(string_map, "hello"); // no allocation.
  32. //
  33. // You can specialize find_cstr for other maps.
  34. // Possible prototypes are:
  35. // const_iterator find_cstr(const Map& map, const char* key);
  36. // iterator find_cstr(Map& map, const char* key);
  37. // const_iterator find_cstr(const Map& map, const char* key, size_t length);
  38. // iterator find_cstr(Map& map, const char* key, size_t length);
  39. namespace butil {
  40. struct StringMapThreadLocalTemp {
  41. bool initialized;
  42. char buf[sizeof(std::string)];
  43. static void delete_tls(void* buf) {
  44. StringMapThreadLocalTemp* temp = (StringMapThreadLocalTemp*)buf;
  45. if (temp->initialized) {
  46. temp->initialized = false;
  47. std::string* temp_string = (std::string*)temp->buf;
  48. temp_string->~basic_string();
  49. }
  50. }
  51. inline std::string* get_string(const char* key) {
  52. if (!initialized) {
  53. initialized = true;
  54. std::string* tmp = new (buf) std::string(key);
  55. thread_atexit(delete_tls, this);
  56. return tmp;
  57. } else {
  58. std::string* tmp = (std::string*)buf;
  59. tmp->assign(key);
  60. return tmp;
  61. }
  62. }
  63. inline std::string* get_string(const char* key, size_t length) {
  64. if (!initialized) {
  65. initialized = true;
  66. std::string* tmp = new (buf) std::string(key, length);
  67. thread_atexit(delete_tls, this);
  68. return tmp;
  69. } else {
  70. std::string* tmp = (std::string*)buf;
  71. tmp->assign(key, length);
  72. return tmp;
  73. }
  74. }
  75. inline std::string* get_lowered_string(const char* key) {
  76. std::string* tmp = get_string(key);
  77. std::transform(tmp->begin(), tmp->end(), tmp->begin(), ::tolower);
  78. return tmp;
  79. }
  80. inline std::string* get_lowered_string(const char* key, size_t length) {
  81. std::string* tmp = get_string(key, length);
  82. std::transform(tmp->begin(), tmp->end(), tmp->begin(), ::tolower);
  83. return tmp;
  84. }
  85. };
  86. extern thread_local StringMapThreadLocalTemp tls_stringmap_temp;
  87. template <typename T, typename C, typename A>
  88. typename std::map<std::string, T, C, A>::const_iterator
  89. find_cstr(const std::map<std::string, T, C, A>& m, const char* key) {
  90. return m.find(*tls_stringmap_temp.get_string(key));
  91. }
  92. template <typename T, typename C, typename A>
  93. typename std::map<std::string, T, C, A>::iterator
  94. find_cstr(std::map<std::string, T, C, A>& m, const char* key) {
  95. return m.find(*tls_stringmap_temp.get_string(key));
  96. }
  97. template <typename T, typename C, typename A>
  98. typename std::map<std::string, T, C, A>::const_iterator
  99. find_cstr(const std::map<std::string, T, C, A>& m,
  100. const char* key, size_t length) {
  101. return m.find(*tls_stringmap_temp.get_string(key, length));
  102. }
  103. template <typename T, typename C, typename A>
  104. typename std::map<std::string, T, C, A>::iterator
  105. find_cstr(std::map<std::string, T, C, A>& m,
  106. const char* key, size_t length) {
  107. return m.find(*tls_stringmap_temp.get_string(key, length));
  108. }
  109. template <typename T, typename C, typename A>
  110. typename std::map<std::string, T, C, A>::const_iterator
  111. find_lowered_cstr(const std::map<std::string, T, C, A>& m, const char* key) {
  112. return m.find(*tls_stringmap_temp.get_lowered_string(key));
  113. }
  114. template <typename T, typename C, typename A>
  115. typename std::map<std::string, T, C, A>::iterator
  116. find_lowered_cstr(std::map<std::string, T, C, A>& m, const char* key) {
  117. return m.find(*tls_stringmap_temp.get_lowered_string(key));
  118. }
  119. template <typename T, typename C, typename A>
  120. typename std::map<std::string, T, C, A>::const_iterator
  121. find_lowered_cstr(const std::map<std::string, T, C, A>& m,
  122. const char* key, size_t length) {
  123. return m.find(*tls_stringmap_temp.get_lowered_string(key, length));
  124. }
  125. template <typename T, typename C, typename A>
  126. typename std::map<std::string, T, C, A>::iterator
  127. find_lowered_cstr(std::map<std::string, T, C, A>& m,
  128. const char* key, size_t length) {
  129. return m.find(*tls_stringmap_temp.get_lowered_string(key, length));
  130. }
  131. } // namespace butil
  132. #endif // BUTIL_FIND_CSTR_H