StringUtils.h (3862B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* String utility functions used by the module loader. */ 8 9 #ifndef shell_StringUtils_h 10 #define shell_StringUtils_h 11 12 #include "js/StableStringChars.h" 13 #include "js/String.h" 14 15 namespace js { 16 namespace shell { 17 18 inline char16_t CharAt(JSLinearString* str, size_t index) { 19 return str->latin1OrTwoByteChar(index); 20 } 21 22 inline JSLinearString* SubString(JSContext* cx, JSLinearString* str, 23 size_t start, size_t end) { 24 MOZ_ASSERT(start <= str->length()); 25 MOZ_ASSERT(end >= start && end <= str->length()); 26 return NewDependentString(cx, str, start, end - start); 27 } 28 29 inline JSLinearString* SubString(JSContext* cx, JSLinearString* str, 30 size_t start) { 31 return SubString(cx, str, start, str->length()); 32 } 33 34 template <size_t NullTerminatedLength> 35 bool StringStartsWith(JSLinearString* str, 36 const char16_t (&chars)[NullTerminatedLength]) { 37 MOZ_ASSERT(NullTerminatedLength > 0); 38 const size_t length = NullTerminatedLength - 1; 39 MOZ_ASSERT(chars[length] == '\0'); 40 41 if (str->length() < length) { 42 return false; 43 } 44 45 for (size_t i = 0; i < length; i++) { 46 if (CharAt(str, i) != chars[i]) { 47 return false; 48 } 49 } 50 51 return true; 52 } 53 54 template <size_t NullTerminatedLength> 55 bool StringEquals(JSLinearString* str, 56 const char16_t (&chars)[NullTerminatedLength]) { 57 MOZ_ASSERT(NullTerminatedLength > 0); 58 const size_t length = NullTerminatedLength - 1; 59 MOZ_ASSERT(chars[length] == '\0'); 60 61 return str->length() == length && StringStartsWith(str, chars); 62 } 63 64 inline int32_t IndexOf(Handle<JSLinearString*> str, char16_t target, 65 size_t start = 0) { 66 int32_t length = str->length(); 67 for (int32_t i = start; i < length; i++) { 68 if (CharAt(str, i) == target) { 69 return i; 70 } 71 } 72 73 return -1; 74 } 75 76 inline int32_t LastIndexOf(Handle<JSLinearString*> str, char16_t target) { 77 int32_t length = str->length(); 78 for (int32_t i = length - 1; i >= 0; i--) { 79 if (CharAt(str, i) == target) { 80 return i; 81 } 82 } 83 84 return -1; 85 } 86 87 inline JSLinearString* ReplaceCharGlobally(JSContext* cx, 88 Handle<JSLinearString*> str, 89 char16_t target, 90 char16_t replacement) { 91 int32_t i = IndexOf(str, target); 92 if (i == -1) { 93 return str; 94 } 95 96 JS::AutoStableStringChars chars(cx); 97 if (!chars.initTwoByte(cx, str)) { 98 return nullptr; 99 } 100 101 Vector<char16_t> buf(cx); 102 if (!buf.append(chars.twoByteChars(), str->length())) { 103 return nullptr; 104 } 105 106 for (; i < int32_t(buf.length()); i++) { 107 if (buf[i] == target) { 108 buf[i] = replacement; 109 } 110 } 111 112 RootedString result(cx, JS_NewUCStringCopyN(cx, buf.begin(), buf.length())); 113 if (!result) { 114 return nullptr; 115 } 116 117 return JS_EnsureLinearString(cx, result); 118 } 119 120 inline JSString* JoinStrings(JSContext* cx, 121 Handle<GCVector<JSLinearString*>> strings, 122 Handle<JSLinearString*> separator) { 123 RootedString result(cx, JS_GetEmptyString(cx)); 124 125 for (size_t i = 0; i < strings.length(); i++) { 126 HandleString str = strings[i]; 127 if (i != 0) { 128 result = JS_ConcatStrings(cx, result, separator); 129 if (!result) { 130 return nullptr; 131 } 132 } 133 134 result = JS_ConcatStrings(cx, result, str); 135 if (!result) { 136 return nullptr; 137 } 138 } 139 140 return result; 141 } 142 143 } // namespace shell 144 } // namespace js 145 146 #endif // shell_StringUtils_h