OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/strings/safe_sprintf.h" | 5 #include "base/strings/safe_sprintf.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <string.h> | 8 #include <string.h> |
9 | 9 |
10 #include <limits> | 10 #include <limits> |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 namespace { | 65 namespace { |
66 const size_t kSSizeMaxConst = ((size_t)(ssize_t)-1) >> 1; | 66 const size_t kSSizeMaxConst = ((size_t)(ssize_t)-1) >> 1; |
67 | 67 |
68 const char kUpCaseHexDigits[] = "0123456789ABCDEF"; | 68 const char kUpCaseHexDigits[] = "0123456789ABCDEF"; |
69 const char kDownCaseHexDigits[] = "0123456789abcdef"; | 69 const char kDownCaseHexDigits[] = "0123456789abcdef"; |
70 } | 70 } |
71 | 71 |
72 #if defined(NDEBUG) | 72 #if defined(NDEBUG) |
73 // We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(), | 73 // We would like to define kSSizeMax as std::numeric_limits<ssize_t>::max(), |
74 // but C++ doesn't allow us to do that for constants. Instead, we have to | 74 // but C++ doesn't allow us to do that for constants. Instead, we have to |
75 // use careful casting and shifting. We later use a COMPILE_ASSERT to | 75 // use careful casting and shifting. We later use a static_assert to |
76 // verify that this worked correctly. | 76 // verify that this worked correctly. |
77 namespace { | 77 namespace { |
78 const size_t kSSizeMax = kSSizeMaxConst; | 78 const size_t kSSizeMax = kSSizeMaxConst; |
79 } | 79 } |
80 #else // defined(NDEBUG) | 80 #else // defined(NDEBUG) |
81 // For efficiency, we really need kSSizeMax to be a constant. But for unit | 81 // For efficiency, we really need kSSizeMax to be a constant. But for unit |
82 // tests, it should be adjustable. This allows us to verify edge cases without | 82 // tests, it should be adjustable. This allows us to verify edge cases without |
83 // having to fill the entire available address space. As a compromise, we make | 83 // having to fill the entire available address space. As a compromise, we make |
84 // kSSizeMax adjustable in debug builds, and then only compile that particular | 84 // kSSizeMax adjustable in debug builds, and then only compile that particular |
85 // part of the unit test in debug builds. | 85 // part of the unit test in debug builds. |
(...skipping 17 matching lines...) Expand all Loading... |
103 public: | 103 public: |
104 // |buffer| is caller-allocated storage that SafeSPrintf() writes to. It | 104 // |buffer| is caller-allocated storage that SafeSPrintf() writes to. It |
105 // has |size| bytes of writable storage. It is the caller's responsibility | 105 // has |size| bytes of writable storage. It is the caller's responsibility |
106 // to ensure that the buffer is at least one byte in size, so that it fits | 106 // to ensure that the buffer is at least one byte in size, so that it fits |
107 // the trailing NUL that will be added by the destructor. The buffer also | 107 // the trailing NUL that will be added by the destructor. The buffer also |
108 // must be smaller or equal to kSSizeMax in size. | 108 // must be smaller or equal to kSSizeMax in size. |
109 Buffer(char* buffer, size_t size) | 109 Buffer(char* buffer, size_t size) |
110 : buffer_(buffer), | 110 : buffer_(buffer), |
111 size_(size - 1), // Account for trailing NUL byte | 111 size_(size - 1), // Account for trailing NUL byte |
112 count_(0) { | 112 count_(0) { |
113 // The following assertion does not build on Mac and Android. This is because | 113 // MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe |
114 // static_assert only works with compile-time constants, but mac uses | 114 // supports static_cast but doesn't really implement constexpr yet so it doesn't |
115 // libstdc++4.2 and android uses stlport, which both don't mark | 115 // complain, but clang does. |
116 // numeric_limits::max() as constexp. Likewise, MSVS2013's standard library | 116 #if __cplusplus >= 201103 && !(defined(__clang__) && defined(OS_WIN)) |
117 // also doesn't mark max() as constexpr yet. cl.exe supports static_cast but | 117 static_assert(kSSizeMaxConst == |
118 // doesn't really implement constexpr yet so it doesn't complain, but clang | 118 static_cast<size_t>(std::numeric_limits<ssize_t>::max()), |
119 // does. | 119 "kSSizeMaxConst should be the max value of an ssize_t"); |
120 #if __cplusplus >= 201103 && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \ | |
121 !defined(OS_IOS) && !(defined(__clang__) && defined(OS_WIN)) | |
122 COMPILE_ASSERT(kSSizeMaxConst == \ | |
123 static_cast<size_t>(std::numeric_limits<ssize_t>::max()), | |
124 kSSizeMax_is_the_max_value_of_an_ssize_t); | |
125 #endif | 120 #endif |
126 DEBUG_CHECK(size > 0); | 121 DEBUG_CHECK(size > 0); |
127 DEBUG_CHECK(size <= kSSizeMax); | 122 DEBUG_CHECK(size <= kSSizeMax); |
128 } | 123 } |
129 | 124 |
130 ~Buffer() { | 125 ~Buffer() { |
131 // The code calling the constructor guaranteed that there was enough space | 126 // The code calling the constructor guaranteed that there was enough space |
132 // to store a trailing NUL -- and in debug builds, we are actually | 127 // to store a trailing NUL -- and in debug builds, we are actually |
133 // verifying this with DEBUG_CHECK()s in the constructor. So, we can | 128 // verifying this with DEBUG_CHECK()s in the constructor. So, we can |
134 // always unconditionally write the NUL byte in the destructor. We do not | 129 // always unconditionally write the NUL byte in the destructor. We do not |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 DEBUG_CHECK(src[0] != '%' || src[1] == '%'); | 674 DEBUG_CHECK(src[0] != '%' || src[1] == '%'); |
680 if (src[0] == '%' && src[1] == '%') { | 675 if (src[0] == '%' && src[1] == '%') { |
681 ++src; | 676 ++src; |
682 } | 677 } |
683 } | 678 } |
684 return buffer.GetCount(); | 679 return buffer.GetCount(); |
685 } | 680 } |
686 | 681 |
687 } // namespace strings | 682 } // namespace strings |
688 } // namespace base | 683 } // namespace base |
OLD | NEW |