OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/uri.h" |
| 6 |
| 7 #include "src/char-predicates-inl.h" |
| 8 #include "src/handles.h" |
| 9 #include "src/isolate-inl.h" |
| 10 #include "src/list.h" |
| 11 |
| 12 namespace v8 { |
| 13 namespace internal { |
| 14 |
| 15 namespace { // anonymous namespace for EncodeURI helper functions |
| 16 bool IsUnescapePredicateInUriComponent(uc16 c) { |
| 17 if (IsAlphaNumeric(c)) { |
| 18 return true; |
| 19 } |
| 20 |
| 21 switch (c) { |
| 22 case '!': |
| 23 case '\'': |
| 24 case '(': |
| 25 case ')': |
| 26 case '*': |
| 27 case '-': |
| 28 case '.': |
| 29 case '_': |
| 30 case '~': |
| 31 return true; |
| 32 default: |
| 33 return false; |
| 34 } |
| 35 } |
| 36 |
| 37 bool IsUriSeparator(uc16 c) { |
| 38 switch (c) { |
| 39 case '#': |
| 40 case ':': |
| 41 case ';': |
| 42 case '/': |
| 43 case '?': |
| 44 case '$': |
| 45 case '&': |
| 46 case '+': |
| 47 case ',': |
| 48 case '@': |
| 49 case '=': |
| 50 return true; |
| 51 default: |
| 52 return false; |
| 53 } |
| 54 } |
| 55 |
| 56 void AddHexEncodedToBuffer(uint8_t octet, List<uint8_t>* buffer) { |
| 57 buffer->Add('%'); |
| 58 buffer->Add(HexCharOfValue(octet >> 4)); |
| 59 buffer->Add(HexCharOfValue(octet & 0x0F)); |
| 60 } |
| 61 |
| 62 void EncodeSingle(uc16 c, List<uint8_t>* buffer) { |
| 63 uint8_t x = (c >> 12) & 0xF; |
| 64 uint8_t y = (c >> 6) & 63; |
| 65 uint8_t z = c & 63; |
| 66 if (c <= 0x007F) { |
| 67 AddHexEncodedToBuffer(c, buffer); |
| 68 } else if (c <= 0x07FF) { |
| 69 AddHexEncodedToBuffer(y + 192, buffer); |
| 70 AddHexEncodedToBuffer(z + 128, buffer); |
| 71 } else { |
| 72 AddHexEncodedToBuffer(x + 224, buffer); |
| 73 AddHexEncodedToBuffer(y + 128, buffer); |
| 74 AddHexEncodedToBuffer(z + 128, buffer); |
| 75 } |
| 76 } |
| 77 |
| 78 void EncodePair(uc16 cc1, uc16 cc2, List<uint8_t>* buffer) { |
| 79 uint8_t u = ((cc1 >> 6) & 0xF) + 1; |
| 80 uint8_t w = (cc1 >> 2) & 0xF; |
| 81 uint8_t x = cc1 & 3; |
| 82 uint8_t y = (cc2 >> 6) & 0xF; |
| 83 uint8_t z = cc2 & 63; |
| 84 AddHexEncodedToBuffer((u >> 2) + 240, buffer); |
| 85 AddHexEncodedToBuffer((((u & 3) << 4) | w) + 128, buffer); |
| 86 AddHexEncodedToBuffer(((x << 4) | y) + 128, buffer); |
| 87 AddHexEncodedToBuffer(z + 128, buffer); |
| 88 } |
| 89 |
| 90 } // anonymous namespace |
| 91 |
| 92 Object* Uri::Encode(Isolate* isolate, Handle<String> uri, bool is_uri) { |
| 93 uri = String::Flatten(uri); |
| 94 int uri_length = uri->length(); |
| 95 List<uint8_t> buffer(uri_length); |
| 96 |
| 97 { |
| 98 DisallowHeapAllocation no_gc; |
| 99 String::FlatContent uri_content = uri->GetFlatContent(); |
| 100 |
| 101 for (int k = 0; k < uri_length; k++) { |
| 102 uc16 cc1 = uri_content.Get(k); |
| 103 if (unibrow::Utf16::IsLeadSurrogate(cc1)) { |
| 104 k++; |
| 105 if (k < uri_length) { |
| 106 uc16 cc2 = uri->Get(k); |
| 107 if (unibrow::Utf16::IsTrailSurrogate(cc2)) { |
| 108 EncodePair(cc1, cc2, &buffer); |
| 109 continue; |
| 110 } |
| 111 } |
| 112 } else if (!unibrow::Utf16::IsTrailSurrogate(cc1)) { |
| 113 if (IsUnescapePredicateInUriComponent(cc1) || |
| 114 (is_uri && IsUriSeparator(cc1))) { |
| 115 buffer.Add(cc1); |
| 116 } else { |
| 117 EncodeSingle(cc1, &buffer); |
| 118 } |
| 119 continue; |
| 120 } |
| 121 |
| 122 AllowHeapAllocation allocate_error_and_return; |
| 123 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewURIError()); |
| 124 } |
| 125 } |
| 126 |
| 127 Handle<String> result; |
| 128 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 129 isolate, result, |
| 130 isolate->factory()->NewStringFromOneByte(buffer.ToConstVector())); |
| 131 return *result; |
| 132 } |
| 133 |
| 134 } // namespace internal |
| 135 } // namespace v8 |
OLD | NEW |