Modify escaping string (#22)
This commit is contained in:
parent
3e41826e3e
commit
ba5cd8decf
|
@ -15,24 +15,41 @@
|
|||
*/
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
* `EscapeString` escapes string.
|
||||
*/
|
||||
extension String {
|
||||
/// Escapes string.
|
||||
private enum JsonEscape {
|
||||
static let tempPlaceHolder = UUID().uuidString
|
||||
static let backSlash = "\\"
|
||||
static let escapedBackSlash = "\\\\"
|
||||
|
||||
/// Escaping based on JS-SDK
|
||||
static let escapeSequences = [
|
||||
(original: "\\", escaped: "\\\\"),
|
||||
(original: JsonEscape.backSlash, escaped: JsonEscape.escapedBackSlash),
|
||||
(original: "\"", escaped: "\\\""),
|
||||
(original: "'", escaped: "\\'"),
|
||||
(original: "\n", escaped: "\\n"),
|
||||
(original: "\r", escaped: "\\r"),
|
||||
(original: "\t", escaped: "\\t"),
|
||||
(original: "\u{2028}", escaped: "\\u{2028}"),
|
||||
(original: "\u{2029}", escaped: "\\u{2029}")
|
||||
(original: "\u{0008}", escaped: "\\b"),
|
||||
(original: "\u{000C}", escaped: "\\f"),
|
||||
(original: "\u{2028}", escaped: "\\u2028"),
|
||||
(original: "\u{2029}", escaped: "\\u2029")
|
||||
]
|
||||
}
|
||||
|
||||
extension String {
|
||||
func escaped() -> String {
|
||||
return String.escapeSequences.reduce(self) { string, seq in
|
||||
return JsonEscape.escapeSequences.reduce(self) { string, seq in
|
||||
string.replacingOccurrences(of: seq.original, with: seq.escaped)
|
||||
}
|
||||
}
|
||||
|
||||
func unescaped() -> String {
|
||||
let target = self.replacingOccurrences(of: JsonEscape.escapedBackSlash, with: JsonEscape.tempPlaceHolder)
|
||||
|
||||
let temp = JsonEscape.escapeSequences.reduce(target) { string, seq in
|
||||
string.replacingOccurrences(of: seq.escaped, with: seq.original)
|
||||
}
|
||||
|
||||
return temp.replacingOccurrences(of: JsonEscape.tempPlaceHolder, with: JsonEscape.backSlash)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2022 The Yorkie Authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import XCTest
|
||||
@testable import Yorkie
|
||||
|
||||
class StringEscapingTests: XCTestCase {
|
||||
func test_can_escape_string() {
|
||||
let target = "1\\2\"3'4\n5\r6\t7\u{0008}8\u{000C}9\u{2028}0\u{2029}"
|
||||
let escaped = "1\\\\2\\\"3\\'4\\n5\\r6\\t7\\b8\\f9\\u20280\\u2029"
|
||||
|
||||
XCTAssertEqual(target.escaped(), escaped)
|
||||
XCTAssertEqual(escaped.unescaped(), target)
|
||||
}
|
||||
|
||||
func test_can_escape_string_2() {
|
||||
let target = "\\n"
|
||||
let escaped = "\\\\n"
|
||||
|
||||
XCTAssertEqual(target.escaped(), escaped)
|
||||
XCTAssertEqual(escaped.unescaped(), target)
|
||||
}
|
||||
|
||||
func test_can_escape_string_3() {
|
||||
let target = "\\\\\\t"
|
||||
let escaped = "\\\\\\\\\\\\t"
|
||||
|
||||
XCTAssertEqual(target.escaped(), escaped)
|
||||
XCTAssertEqual(escaped.unescaped(), target)
|
||||
}
|
||||
|
||||
func test_can_escape_string_4() {
|
||||
let target = "\\\\\\\t"
|
||||
let escaped = "\\\\\\\\\\\\\\t"
|
||||
|
||||
XCTAssertEqual(target.escaped(), escaped)
|
||||
XCTAssertEqual(escaped.unescaped(), target)
|
||||
}
|
||||
|
||||
func test_can_escape_string_5() {
|
||||
let target = "\\u{000C}"
|
||||
let escaped = "\\\\u{000C}"
|
||||
|
||||
XCTAssertEqual(target.escaped(), escaped)
|
||||
XCTAssertEqual(escaped.unescaped(), target)
|
||||
}
|
||||
|
||||
func test_can_escape_string_6() {
|
||||
let target = "\u{000C}"
|
||||
let escaped = "\\f"
|
||||
|
||||
XCTAssertEqual(target.escaped(), escaped)
|
||||
XCTAssertEqual(escaped.unescaped(), target)
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@
|
|||
CE8C230528C9F1BD00432DE5 /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8C230428C9F1BD00432DE5 /* Client.swift */; };
|
||||
CE8C230728D1514900432DE5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8C230628D1514900432DE5 /* Logger.swift */; };
|
||||
CE8C230B28D15FF200432DE5 /* ClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8C230928D15F5A00432DE5 /* ClientTests.swift */; };
|
||||
CEC631DE28F4F36100915A85 /* StringEscapingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC631DC28F4F15900915A85 /* StringEscapingTests.swift */; };
|
||||
CE8ED31628F55BF7009A5419 /* SetOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8ED31528F55BF7009A5419 /* SetOperation.swift */; };
|
||||
CE8ED31A28F55F42009A5419 /* SetOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8ED31828F55F3E009A5419 /* SetOperationTests.swift */; };
|
||||
CE8ED31C28F56506009A5419 /* RemoveOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8ED31B28F56506009A5419 /* RemoveOperation.swift */; };
|
||||
|
@ -112,6 +113,7 @@
|
|||
CE8C230428C9F1BD00432DE5 /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
|
||||
CE8C230628D1514900432DE5 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Logger.swift; path = Sources/Core/Logger.swift; sourceTree = SOURCE_ROOT; };
|
||||
CE8C230928D15F5A00432DE5 /* ClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientTests.swift; sourceTree = "<group>"; };
|
||||
CEC631DC28F4F15900915A85 /* StringEscapingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringEscapingTests.swift; sourceTree = "<group>"; };
|
||||
CE8ED31528F55BF7009A5419 /* SetOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetOperation.swift; sourceTree = "<group>"; };
|
||||
CE8ED31828F55F3E009A5419 /* SetOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetOperationTests.swift; sourceTree = "<group>"; };
|
||||
CE8ED31B28F56506009A5419 /* RemoveOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveOperation.swift; sourceTree = "<group>"; };
|
||||
|
@ -244,6 +246,7 @@
|
|||
children = (
|
||||
CE3EC96F28D40415009471BC /* CRDT */,
|
||||
CE8ED31728F55F25009A5419 /* Operation */,
|
||||
CEC631DB28F4F14100915A85 /* Json */,
|
||||
CE3EC96B28D3FFDB009471BC /* Time */,
|
||||
);
|
||||
path = Document;
|
||||
|
@ -378,6 +381,14 @@
|
|||
path = Operation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CEC631DB28F4F14100915A85 /* Json */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CEC631DC28F4F15900915A85 /* StringEscapingTests.swift */,
|
||||
);
|
||||
path = Json;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CECCCB8028C96BB500544204 /* V1 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -627,6 +638,7 @@
|
|||
CEA2DA4328F672AD00431B61 /* MoveOperationTests.swift in Sources */,
|
||||
96DA809128C5B7B400E2C1DA /* GRPCTests.swift in Sources */,
|
||||
CE3EC94D28D189EF009471BC /* HeapTests.swift in Sources */,
|
||||
CEC631DE28F4F36100915A85 /* StringEscapingTests.swift in Sources */,
|
||||
CE3EC95228D195E4009471BC /* RedBlackTreeTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
Loading…
Reference in New Issue