v1.0 Release
This commit is contained in:
commit
bbb40b226e
|
@ -0,0 +1,18 @@
|
||||||
|
.DS_Store
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
build/
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
*.xcworkspace
|
||||||
|
!default.xcworkspace
|
||||||
|
xcuserdata
|
||||||
|
profile
|
||||||
|
*.moved-aside
|
||||||
|
DerivedData
|
|
@ -0,0 +1,3 @@
|
||||||
|
## [1.0](https://github.com/milend/hmap/releases/tag/1.0) (2017-08-20)
|
||||||
|
|
||||||
|
- Public release
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"autoPin": true,
|
||||||
|
"pins": [
|
||||||
|
{
|
||||||
|
"package": "Commander",
|
||||||
|
"reason": null,
|
||||||
|
"repositoryURL": "git@github.com:kylef/Commander.git",
|
||||||
|
"version": "0.6.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"package": "Spectre",
|
||||||
|
"reason": null,
|
||||||
|
"repositoryURL": "https://github.com/kylef/Spectre",
|
||||||
|
"version": "0.7.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 1
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
// swift-tools-version:3.1
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "hmap",
|
||||||
|
targets: [
|
||||||
|
Target(
|
||||||
|
name: "hmap",
|
||||||
|
dependencies: [
|
||||||
|
"HeaderMapCore",
|
||||||
|
"HeaderMapFrontend",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
Target(
|
||||||
|
name: "HeaderMapCore"
|
||||||
|
),
|
||||||
|
Target(
|
||||||
|
name: "HeaderMapFrontend",
|
||||||
|
dependencies: [
|
||||||
|
"HeaderMapCore",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
Target(
|
||||||
|
name: "HeaderMapTesting"
|
||||||
|
),
|
||||||
|
Target(
|
||||||
|
name: "HeaderMapCoreTests",
|
||||||
|
dependencies: [
|
||||||
|
"HeaderMapTesting",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
Target(
|
||||||
|
name: "HeaderMapFrontendTests",
|
||||||
|
dependencies: [
|
||||||
|
"HeaderMapTesting",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.Package(
|
||||||
|
url: "git@github.com:kylef/Commander.git",
|
||||||
|
"0.6.0"
|
||||||
|
),
|
||||||
|
],
|
||||||
|
swiftLanguageVersions: [3]
|
||||||
|
)
|
|
@ -0,0 +1,57 @@
|
||||||
|
# What is this?
|
||||||
|
|
||||||
|
`hmap` is a command line tool to work with Clang header maps produced by Xcode.
|
||||||
|
It is written in Swift.
|
||||||
|
|
||||||
|
# How to Get
|
||||||
|
|
||||||
|
- Grab a [release](https://github.com/milend/hmap/releases) from GitHub.
|
||||||
|
- Build from source. See instructions below.
|
||||||
|
|
||||||
|
# How to Use
|
||||||
|
|
||||||
|
To print the contents of a header map:
|
||||||
|
|
||||||
|
hmap print ~/path/to/header_map.hmap
|
||||||
|
|
||||||
|
To convert the contents of a binary header map to JSON:
|
||||||
|
|
||||||
|
hmap convert ~/header_map.hmap ~/header_map.json
|
||||||
|
|
||||||
|
`hmap` deduces file formats by looking at the file extensions of the paths.
|
||||||
|
|
||||||
|
You can also use the `convert` command to create a binary header map from JSON:
|
||||||
|
|
||||||
|
hmap convert ~/header_map.json ~/header_map.hmap
|
||||||
|
|
||||||
|
You can discover all the commands and options by using `hmap --help`.
|
||||||
|
|
||||||
|
# Building from Source
|
||||||
|
|
||||||
|
## Xcode
|
||||||
|
|
||||||
|
The easiest way to build `hmap` is to use the provided Xcode project.
|
||||||
|
|
||||||
|
## Swift Package Manager
|
||||||
|
|
||||||
|
If you would like to build from the command line, run:
|
||||||
|
|
||||||
|
swift build
|
||||||
|
|
||||||
|
To produce a release build suitable for distribution, run:
|
||||||
|
|
||||||
|
swift build -c release -Xswiftc -static-stdlib
|
||||||
|
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
To generate an Xcode project, run:
|
||||||
|
|
||||||
|
swift package generate-xcodeproj
|
||||||
|
|
||||||
|
You must manually add the test files for the test targets as the Swift Package
|
||||||
|
Manager does not yet have such functionality (tracked by
|
||||||
|
[SR-2866](https://bugs.swift.org/browse/SR-2866)).
|
||||||
|
|
||||||
|
If you end up adding new dependencies, remember to run:
|
||||||
|
|
||||||
|
swift package update
|
|
@ -0,0 +1,310 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol Packable {
|
||||||
|
static var packedSize: Int { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This implements v1 of the Clang header map format. For reference, see the
|
||||||
|
following files in the Clang source tree:
|
||||||
|
- HeaderMap.h
|
||||||
|
- HeaderMap.cpp
|
||||||
|
- HeaderMapTypes.h
|
||||||
|
*/
|
||||||
|
struct BinaryHeaderMap {
|
||||||
|
static let StringEncoding: String.Encoding = .utf8
|
||||||
|
|
||||||
|
struct DataHeader: Packable {
|
||||||
|
typealias MagicType = Magic
|
||||||
|
typealias VersionType = Version
|
||||||
|
typealias ReservedType = Reserved
|
||||||
|
typealias StringSectionOffsetType = UInt32
|
||||||
|
typealias StringCountType = UInt32
|
||||||
|
typealias BucketCountType = UInt32
|
||||||
|
typealias MaxValueLengthType = UInt32
|
||||||
|
|
||||||
|
let magic: MagicType
|
||||||
|
let version: VersionType
|
||||||
|
let reserved: ReservedType
|
||||||
|
let stringSectionOffset: StringSectionOffsetType
|
||||||
|
let stringCount: StringCountType
|
||||||
|
let bucketCount: BucketCountType // Must be power of 2
|
||||||
|
let maxValueLength: MaxValueLengthType
|
||||||
|
|
||||||
|
static var packedSize: Int {
|
||||||
|
return
|
||||||
|
MemoryLayout<Magic.RawValue>.size +
|
||||||
|
MemoryLayout<Version.RawValue>.size +
|
||||||
|
MemoryLayout<Reserved.RawValue>.size +
|
||||||
|
MemoryLayout<UInt32>.size +
|
||||||
|
MemoryLayout<UInt32>.size +
|
||||||
|
MemoryLayout<UInt32>.size +
|
||||||
|
MemoryLayout<UInt32>.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Magic: UInt32 {
|
||||||
|
case hmap = 0x68_6D_61_70 // 'hmap'
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Version: UInt16 {
|
||||||
|
case version1 = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Reserved: UInt16 {
|
||||||
|
case none = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bucket: Packable {
|
||||||
|
typealias OffsetType = StringSectionOffset
|
||||||
|
|
||||||
|
let key: OffsetType
|
||||||
|
let prefix: OffsetType
|
||||||
|
let suffix: OffsetType
|
||||||
|
|
||||||
|
// MARK: Packable
|
||||||
|
|
||||||
|
static var packedSize: Int {
|
||||||
|
return OffsetType.packedSize * 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StringSectionOffset: Packable {
|
||||||
|
typealias OffsetType = UInt32
|
||||||
|
|
||||||
|
/** Indicates an invalid offset */
|
||||||
|
static let Reserved = OffsetType(0)
|
||||||
|
|
||||||
|
let offset: OffsetType
|
||||||
|
|
||||||
|
init?(offset: OffsetType) {
|
||||||
|
if offset == StringSectionOffset.Reserved {
|
||||||
|
// The first byte is reserved and means 'empty'.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.offset = offset
|
||||||
|
}
|
||||||
|
|
||||||
|
static var packedSize: Int {
|
||||||
|
return MemoryLayout<OffsetType>.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate let data: Data
|
||||||
|
fileprivate let header: DataHeader
|
||||||
|
fileprivate let byteSwap: Bool
|
||||||
|
|
||||||
|
public init(data: Data) throws {
|
||||||
|
let parseResult = try parseHeaderMap(data: data)
|
||||||
|
self.data = data
|
||||||
|
self.header = parseResult.dataHeader
|
||||||
|
self.byteSwap = parseResult.byteSwap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
enum ProbeAction<T> {
|
||||||
|
case keepProbing
|
||||||
|
case stop(value: T?)
|
||||||
|
}
|
||||||
|
|
||||||
|
func probeHashTable<T>(
|
||||||
|
bucketCount: BinaryHeaderMap.DataHeader.BucketCountType,
|
||||||
|
start: UInt32,
|
||||||
|
_ body: (UInt32) -> ProbeAction<T>) -> T? {
|
||||||
|
var probeAttempts = BinaryHeaderMap.DataHeader.BucketCountType(0)
|
||||||
|
var nextUnboundedBucketIndex = start
|
||||||
|
|
||||||
|
while (probeAttempts < bucketCount) {
|
||||||
|
// Takes advantage of the fact that buckets are a power of 2
|
||||||
|
let nextBucketIndex = nextUnboundedBucketIndex & (bucketCount - 1)
|
||||||
|
|
||||||
|
switch body(nextBucketIndex) {
|
||||||
|
case .keepProbing:
|
||||||
|
break
|
||||||
|
case .stop(let value):
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
nextUnboundedBucketIndex += 1
|
||||||
|
probeAttempts += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
extension BinaryHeaderMap {
|
||||||
|
func getBucket(at index: UInt32) -> Bucket? {
|
||||||
|
let offset =
|
||||||
|
BinaryHeaderMap.DataHeader.packedSize + Int(index) * Bucket.packedSize
|
||||||
|
return withBoundsCheckedBytes(at: offset, count: Bucket.packedSize) {
|
||||||
|
(bytesPointer) in
|
||||||
|
|
||||||
|
return BinaryHeaderMap.Bucket(bytes: bytesPointer, byteSwap: byteSwap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bucketCount: UInt32 {
|
||||||
|
return header.bucketCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func getString(at offset: StringSectionOffset) -> String? {
|
||||||
|
let begin = Int(header.stringSectionOffset + offset.offset)
|
||||||
|
guard begin < data.count else { return nil }
|
||||||
|
|
||||||
|
let nullByteIndex = data.withUnsafeBytes {
|
||||||
|
(bytes: UnsafePointer<UInt8>) -> Int? in
|
||||||
|
|
||||||
|
for i in begin..<data.count {
|
||||||
|
if bytes.advanced(by: i).pointee == 0x0 {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullByteIndex.flatMap { (nullIndex) in
|
||||||
|
let stringData = data.subdata(in: begin..<nullIndex)
|
||||||
|
return String(data: stringData, encoding: BinaryHeaderMap.StringEncoding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func withBoundsCheckedBytes<Result>(
|
||||||
|
at offset: Int,
|
||||||
|
count: Int,
|
||||||
|
_ body: (UnsafePointer<UInt8>) throws -> Result?
|
||||||
|
) rethrows -> Result? {
|
||||||
|
guard offset + count < data.count else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return try data.withUnsafeBytes {
|
||||||
|
return try body($0.advanced(by: offset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Bucket
|
||||||
|
|
||||||
|
extension BinaryHeaderMap.Bucket {
|
||||||
|
init?(bytes: UnsafePointer<UInt8>, byteSwap: Bool) {
|
||||||
|
let decoder = ByteBufferDecoder(bytes: bytes, byteSwap: byteSwap)
|
||||||
|
|
||||||
|
guard
|
||||||
|
let keyOffset = BinaryHeaderMap.StringSectionOffset(
|
||||||
|
offset: decoder.advance()),
|
||||||
|
let prefixOffset = BinaryHeaderMap.StringSectionOffset(
|
||||||
|
offset: decoder.advance()),
|
||||||
|
let suffixOffset = BinaryHeaderMap.StringSectionOffset(
|
||||||
|
offset: decoder.advance())
|
||||||
|
else { return nil }
|
||||||
|
|
||||||
|
|
||||||
|
self.init(
|
||||||
|
key: keyOffset,
|
||||||
|
prefix: prefixOffset,
|
||||||
|
suffix: suffixOffset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Header
|
||||||
|
|
||||||
|
struct DataHeaderParseResult {
|
||||||
|
let dataHeader: BinaryHeaderMap.DataHeader
|
||||||
|
let byteSwap: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHeaderMap(data: Data) throws -> DataHeaderParseResult {
|
||||||
|
if data.count < BinaryHeaderMap.DataHeader.packedSize {
|
||||||
|
throw HeaderMapParseError.missingDataHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
return try data.withUnsafeBytes { (headerBytes: UnsafePointer<UInt8>) in
|
||||||
|
typealias H = BinaryHeaderMap.DataHeader
|
||||||
|
|
||||||
|
let decoder = ByteBufferDecoder(bytes: headerBytes, byteSwap: false)
|
||||||
|
|
||||||
|
let magicValue = decoder.advanceByteSwappable(
|
||||||
|
expect: H.MagicType.hmap.rawValue
|
||||||
|
)
|
||||||
|
let versionValue: H.VersionType.RawValue = decoder.advance()
|
||||||
|
let reseredValue: H.ReservedType.RawValue = decoder.advance()
|
||||||
|
let stringSectionOffset: H.StringSectionOffsetType = decoder.advance()
|
||||||
|
let stringCount: H.StringCountType = decoder.advance()
|
||||||
|
let bucketCount: H.BucketCountType = decoder.advance()
|
||||||
|
let maxValueLength: H.MaxValueLengthType = decoder.advance()
|
||||||
|
|
||||||
|
guard let magic = H.MagicType(rawValue: magicValue) else {
|
||||||
|
throw HeaderMapParseError.unknownFileMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
let expectedVersion = BinaryHeaderMap.Version.version1
|
||||||
|
guard versionValue == expectedVersion.rawValue else {
|
||||||
|
throw HeaderMapParseError.invalidVersion(
|
||||||
|
expected: expectedVersion.rawValue,
|
||||||
|
found: versionValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
let expectedReserved = BinaryHeaderMap.Reserved.none
|
||||||
|
guard reseredValue == expectedReserved.rawValue else {
|
||||||
|
throw HeaderMapParseError.reservedValueMismatch(
|
||||||
|
expected: expectedReserved.rawValue,
|
||||||
|
found: reseredValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard bucketCount.isPowerOf2 else {
|
||||||
|
throw HeaderMapParseError.bucketCountNotPowerOf2(found: bucketCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard Int(stringSectionOffset) < data.count else {
|
||||||
|
throw HeaderMapParseError.outOfBoundsStringSectionOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
let bucketsSectionSize = Int(bucketCount) * BinaryHeaderMap.Bucket.packedSize
|
||||||
|
let headerAndBucketsSectionSize = H.packedSize + bucketsSectionSize
|
||||||
|
guard headerAndBucketsSectionSize < data.count else {
|
||||||
|
throw HeaderMapParseError.bucketsSectionOverflow
|
||||||
|
}
|
||||||
|
|
||||||
|
guard headerAndBucketsSectionSize <= Int(stringSectionOffset) else {
|
||||||
|
throw HeaderMapParseError.invalidStringSectionOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
return DataHeaderParseResult(
|
||||||
|
dataHeader: BinaryHeaderMap.DataHeader(
|
||||||
|
magic: magic,
|
||||||
|
version: expectedVersion,
|
||||||
|
reserved: expectedReserved,
|
||||||
|
stringSectionOffset: stringSectionOffset,
|
||||||
|
stringCount: stringCount,
|
||||||
|
bucketCount: bucketCount,
|
||||||
|
maxValueLength: maxValueLength),
|
||||||
|
byteSwap: decoder.byteSwap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class ByteBufferDecoder {
|
||||||
|
private let bytes: UnsafePointer<UInt8>
|
||||||
|
private var offset: Int
|
||||||
|
|
||||||
|
private(set) var byteSwap: Bool
|
||||||
|
|
||||||
|
init(bytes: UnsafePointer<UInt8>, byteSwap: Bool) {
|
||||||
|
self.bytes = bytes
|
||||||
|
self.offset = 0
|
||||||
|
self.byteSwap = byteSwap
|
||||||
|
}
|
||||||
|
|
||||||
|
func advance<T: ByteSwappable & Equatable>() -> T {
|
||||||
|
return advance {
|
||||||
|
// Needs temporary `result` due to Swift's type inference
|
||||||
|
let result: T = castBytes()
|
||||||
|
return result.byte(swapped: byteSwap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func advanceByteSwappable<T: ByteSwappable & Equatable>(expect expectedValue: T) -> T {
|
||||||
|
return advance {
|
||||||
|
let memoryValue: T = castBytes()
|
||||||
|
|
||||||
|
let swappedValue = expectedValue.byte(swapped: true)
|
||||||
|
if memoryValue == expectedValue || memoryValue == swappedValue {
|
||||||
|
byteSwap = (memoryValue == swappedValue)
|
||||||
|
return expectedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return memoryValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func castBytes<T>() -> T {
|
||||||
|
return bytes.advanced(by: offset).withMemoryRebound(to: T.self, capacity: 1) {
|
||||||
|
return $0.pointee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func advance<T>(_ body: () -> T) -> T {
|
||||||
|
let value = body()
|
||||||
|
offset += MemoryLayout<T>.size
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ByteBufferEncoder {
|
||||||
|
private(set) var bytes = Data()
|
||||||
|
|
||||||
|
func encode<T>(_ value: T) {
|
||||||
|
var mutableValue = value
|
||||||
|
withUnsafeBytes(of: &mutableValue) { (pointer) in
|
||||||
|
let valueBytes = Array(pointer[0..<pointer.count])
|
||||||
|
bytes.append(contentsOf: valueBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func append(_ data: Data) {
|
||||||
|
bytes.append(data)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct HeaderMap {
|
||||||
|
public struct Entry {
|
||||||
|
public let key: String
|
||||||
|
public let prefix: String
|
||||||
|
public let suffix: String
|
||||||
|
|
||||||
|
public init(key: String, prefix: String, suffix: String) {
|
||||||
|
self.key = key
|
||||||
|
self.prefix = prefix
|
||||||
|
self.suffix = suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(data: Data) throws {
|
||||||
|
let binaryHeader = try BinaryHeaderMap(data: data)
|
||||||
|
self.entries = try makeIndexedEntries(from: binaryHeader.makeEntries())
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(entries: [Entry]) throws {
|
||||||
|
self.entries = try makeIndexedEntries(from: entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate typealias EntryIndex = [Data: Entry]
|
||||||
|
fileprivate let entries: EntryIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Private
|
||||||
|
|
||||||
|
fileprivate extension BinaryHeaderMap {
|
||||||
|
func makeEntries() -> [HeaderMap.Entry] {
|
||||||
|
return (0..<bucketCount).flatMap { (index) in
|
||||||
|
return getBucket(at: index).flatMap { (bucket) in
|
||||||
|
return makeEntry(forBucket: bucket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeEntry(forBucket bucket: Bucket) -> HeaderMap.Entry? {
|
||||||
|
guard
|
||||||
|
let key = getString(at: bucket.key),
|
||||||
|
let prefix = getString(at: bucket.prefix),
|
||||||
|
let suffix = getString(at: bucket.suffix)
|
||||||
|
else { return nil }
|
||||||
|
|
||||||
|
return HeaderMap.Entry(
|
||||||
|
key: key,
|
||||||
|
prefix: prefix,
|
||||||
|
suffix: suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func makeIndexedEntries(from entries: [HeaderMap.Entry]) throws -> HeaderMap.EntryIndex {
|
||||||
|
return try sanitize(headerEntries: entries).dictionaryMap { (entry) in
|
||||||
|
let lowercasedBytes = try entry.key.clangLowercasedBytes()
|
||||||
|
return (lowercasedBytes, entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public
|
||||||
|
|
||||||
|
extension HeaderMap {
|
||||||
|
public subscript(key: String) -> HeaderMap.Entry? {
|
||||||
|
guard let lowercasedBytes = try? key.clangLowercasedBytes() else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries[lowercasedBytes]
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeEntryList() -> [HeaderMap.Entry] {
|
||||||
|
return entries.map { (_, entry) in
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HeaderMap {
|
||||||
|
public static func makeBinary(withEntries entries: [Entry]) throws -> Data {
|
||||||
|
return try makeHeaderMapBinaryData(withEntries: entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HeaderMap.Entry: Hashable {
|
||||||
|
public var hashValue: Int {
|
||||||
|
return key.hashValue ^ prefix.hashValue ^ suffix.hashValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: HeaderMap.Entry, rhs: HeaderMap.Entry) -> Bool {
|
||||||
|
return lhs.key == rhs.key &&
|
||||||
|
lhs.prefix == rhs.prefix &&
|
||||||
|
lhs.suffix == rhs.suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum HeaderMapError: LocalizedError {
|
||||||
|
case unencodableString
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HeaderMapParseError: LocalizedError {
|
||||||
|
case missingDataHeader
|
||||||
|
case unknownFileMagic
|
||||||
|
case invalidVersion(expected: UInt16, found: UInt16)
|
||||||
|
case reservedValueMismatch(expected: UInt16, found: UInt16)
|
||||||
|
case outOfBoundsStringSectionOffset
|
||||||
|
case bucketCountNotPowerOf2(found: UInt32)
|
||||||
|
case bucketsSectionOverflow
|
||||||
|
case invalidStringSectionOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum HeaderMapCreateError: LocalizedError {
|
||||||
|
case invalidStringSectionOffset
|
||||||
|
case noEntries
|
||||||
|
case stringWithoutOffsetInTable
|
||||||
|
case hashTableFull
|
||||||
|
case unhashableKey
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HeaderMapError {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .unencodableString:
|
||||||
|
return "String cannot be encoded"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HeaderMapParseError {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .missingDataHeader:
|
||||||
|
return "File is missing a header section"
|
||||||
|
case .unknownFileMagic:
|
||||||
|
return "File magic is unknown"
|
||||||
|
case .invalidVersion(let expected, let found):
|
||||||
|
return "Found invalid version \(found), expected \(expected)"
|
||||||
|
case .reservedValueMismatch(let expected, let found):
|
||||||
|
return "Found invalid reserved value \(found), expected \(expected)"
|
||||||
|
case .outOfBoundsStringSectionOffset:
|
||||||
|
return "String offset is out of bounds"
|
||||||
|
case .bucketCountNotPowerOf2(let buckets):
|
||||||
|
return "Bucket count is not a power of 2, found \(buckets) buckets"
|
||||||
|
case .bucketsSectionOverflow:
|
||||||
|
return "Bucket section overflows"
|
||||||
|
case .invalidStringSectionOffset:
|
||||||
|
return "The string section offset is invalid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension HeaderMapCreateError {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .invalidStringSectionOffset:
|
||||||
|
return "The string section offset is invalid"
|
||||||
|
case .noEntries:
|
||||||
|
return "Header map needs to contain at least one entry"
|
||||||
|
case .stringWithoutOffsetInTable:
|
||||||
|
return "String not present in string section"
|
||||||
|
case .hashTableFull:
|
||||||
|
return "Header map is full"
|
||||||
|
case .unhashableKey:
|
||||||
|
return "Key cannot be hashed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,216 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
func makeHeaderMapBinaryData(
|
||||||
|
withEntries unsafeEntries: [HeaderMap.Entry]) throws -> Data {
|
||||||
|
|
||||||
|
guard unsafeEntries.count > 0 else {
|
||||||
|
throw HeaderMapCreateError.noEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
let safeEntries = sanitize(headerEntries: unsafeEntries)
|
||||||
|
let allStrings = Set(safeEntries.flatMap { [$0.key, $0.prefix, $0.suffix] })
|
||||||
|
let stringSection = try makeStringSection(allStrings: allStrings)
|
||||||
|
let bucketSection = try makeBucketSection(
|
||||||
|
forEntries: safeEntries,
|
||||||
|
stringSection: stringSection)
|
||||||
|
|
||||||
|
let maxValueLength = safeEntries.max(by: { lhs, rhs in
|
||||||
|
return lhs.valueLength < rhs.valueLength
|
||||||
|
}).map { $0.valueLength } ?? 0
|
||||||
|
|
||||||
|
let headerSize = BinaryHeaderMap.DataHeader.packedSize
|
||||||
|
let stringSectionOffset = headerSize + bucketSection.data.count
|
||||||
|
|
||||||
|
let header = BinaryHeaderMap.DataHeader(
|
||||||
|
magic: .hmap,
|
||||||
|
version: .version1,
|
||||||
|
reserved: .none,
|
||||||
|
stringSectionOffset: UInt32(stringSectionOffset),
|
||||||
|
stringCount: UInt32(stringSection.stringCount),
|
||||||
|
bucketCount: UInt32(bucketSection.bucketCount),
|
||||||
|
maxValueLength: UInt32(maxValueLength))
|
||||||
|
|
||||||
|
let encoder = ByteBufferEncoder()
|
||||||
|
encoder.encode(header.magic.rawValue)
|
||||||
|
encoder.encode(header.version.rawValue)
|
||||||
|
encoder.encode(header.reserved.rawValue)
|
||||||
|
encoder.encode(header.stringSectionOffset)
|
||||||
|
encoder.encode(header.stringCount)
|
||||||
|
encoder.encode(header.bucketCount)
|
||||||
|
encoder.encode(header.maxValueLength)
|
||||||
|
encoder.append(bucketSection.data)
|
||||||
|
encoder.append(stringSection.data)
|
||||||
|
|
||||||
|
return encoder.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate struct BucketSection {
|
||||||
|
let data: Data
|
||||||
|
let bucketCount: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate struct StringSection {
|
||||||
|
let data: Data
|
||||||
|
let stringCount: Int
|
||||||
|
let offsets: [String: BinaryHeaderMap.StringSectionOffset]
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func makeStringSection(
|
||||||
|
allStrings: Set<String>) throws -> StringSection {
|
||||||
|
|
||||||
|
var buffer = Data()
|
||||||
|
buffer.append(UInt8(BinaryHeaderMap.StringSectionOffset.Reserved))
|
||||||
|
var offsets = Dictionary<String, BinaryHeaderMap.StringSectionOffset>()
|
||||||
|
|
||||||
|
for string in allStrings {
|
||||||
|
guard let stringBytes = string.data(using: BinaryHeaderMap.StringEncoding) else {
|
||||||
|
throw HeaderMapError.unencodableString
|
||||||
|
}
|
||||||
|
|
||||||
|
let bufferCount = UInt32(buffer.count)
|
||||||
|
guard
|
||||||
|
let offset = BinaryHeaderMap.StringSectionOffset(offset: bufferCount)
|
||||||
|
else {
|
||||||
|
throw HeaderMapCreateError.invalidStringSectionOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
offsets[string] = offset
|
||||||
|
buffer.append(stringBytes)
|
||||||
|
buffer.append(0x0) // NUL character
|
||||||
|
}
|
||||||
|
|
||||||
|
return StringSection(
|
||||||
|
data: buffer,
|
||||||
|
stringCount: allStrings.count,
|
||||||
|
offsets: offsets)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func isBucketSlotEmpty(
|
||||||
|
bytePointer: UnsafeMutablePointer<UInt8>,
|
||||||
|
index: UInt32) -> Bool {
|
||||||
|
|
||||||
|
let slotOffset = Int(index) * BinaryHeaderMap.Bucket.packedSize
|
||||||
|
let slotPointer = bytePointer.advanced(by: slotOffset)
|
||||||
|
return slotPointer.withMemoryRebound(
|
||||||
|
to: BinaryHeaderMap.StringSectionOffset.OffsetType.self,
|
||||||
|
capacity: 1) {
|
||||||
|
return $0.pointee == BinaryHeaderMap.StringSectionOffset.Reserved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func writeTo<T>(bytePointer: UnsafeMutablePointer<UInt8>, value: T) {
|
||||||
|
var mutableValue = value
|
||||||
|
withUnsafeBytes(of: &mutableValue) { (pointer) in
|
||||||
|
let valueBytes = Array(pointer[0..<pointer.count])
|
||||||
|
for (index, byte) in valueBytes.enumerated() {
|
||||||
|
bytePointer.advanced(by: index).pointee = byte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func makeBucketSection(
|
||||||
|
forEntries entries: [HeaderMap.Entry],
|
||||||
|
stringSection: StringSection) throws -> BucketSection {
|
||||||
|
|
||||||
|
assert(entries.count > 0)
|
||||||
|
|
||||||
|
let bucketCount = numberOfBuckets(forEntryCount: entries.count)
|
||||||
|
var bytes = Data(count: bucketCount * BinaryHeaderMap.Bucket.packedSize)
|
||||||
|
try bytes.withUnsafeMutableBytes {
|
||||||
|
(bytePointer: UnsafeMutablePointer<UInt8>) in
|
||||||
|
|
||||||
|
try entries.forEach { (entry) in
|
||||||
|
guard let keyHash = entry.key.headerMapHash else {
|
||||||
|
throw HeaderMapCreateError.unhashableKey
|
||||||
|
}
|
||||||
|
|
||||||
|
guard
|
||||||
|
let keyOffset = stringSection.offsets[entry.key],
|
||||||
|
let prefixOffset = stringSection.offsets[entry.prefix],
|
||||||
|
let suffixOffset = stringSection.offsets[entry.suffix]
|
||||||
|
else {
|
||||||
|
throw HeaderMapCreateError.stringWithoutOffsetInTable
|
||||||
|
}
|
||||||
|
|
||||||
|
let maybeEmptySlotIndex: UInt32? = probeHashTable(
|
||||||
|
bucketCount: UInt32(bucketCount),
|
||||||
|
start: keyHash) { (probeIndex) in
|
||||||
|
if isBucketSlotEmpty(bytePointer: bytePointer, index: probeIndex) {
|
||||||
|
return .stop(value: probeIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
return .keepProbing
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let emptySlotIndex = maybeEmptySlotIndex else {
|
||||||
|
throw HeaderMapCreateError.hashTableFull
|
||||||
|
}
|
||||||
|
|
||||||
|
let slotPointer = bytePointer.advanced(
|
||||||
|
by: Int(emptySlotIndex) * BinaryHeaderMap.Bucket.packedSize)
|
||||||
|
let fieldSize = MemoryLayout<BinaryHeaderMap.Bucket.OffsetType>.size
|
||||||
|
|
||||||
|
writeTo(
|
||||||
|
bytePointer: slotPointer,
|
||||||
|
value: keyOffset.offset)
|
||||||
|
writeTo(
|
||||||
|
bytePointer: slotPointer.advanced(by: fieldSize),
|
||||||
|
value: prefixOffset.offset)
|
||||||
|
writeTo(
|
||||||
|
bytePointer: slotPointer.advanced(by: 2 * fieldSize),
|
||||||
|
value: suffixOffset.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BucketSection(data: bytes, bucketCount: bucketCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func numberOfBuckets(forEntryCount entryCount: Int) -> Int {
|
||||||
|
assert(entryCount > 0)
|
||||||
|
|
||||||
|
let minimumSlots = Int(ceil(Double(entryCount) * (1.0 / 0.7)))
|
||||||
|
var bucketCount = 1
|
||||||
|
while bucketCount < minimumSlots {
|
||||||
|
bucketCount <<= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return bucketCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func sanitize(headerEntries entries: [HeaderMap.Entry]) -> [HeaderMap.Entry] {
|
||||||
|
var allKeys = Set<String>()
|
||||||
|
return entries.flatMap { (entry) in
|
||||||
|
guard !allKeys.contains(entry.key) else { return nil }
|
||||||
|
allKeys.insert(entry.key)
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension HeaderMap.Entry {
|
||||||
|
var valueLength: Int {
|
||||||
|
return prefix.lengthOfBytes(using: BinaryHeaderMap.StringEncoding) +
|
||||||
|
suffix.lengthOfBytes(using: BinaryHeaderMap.StringEncoding)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct JSONHeaderMap {
|
||||||
|
public struct Entry {
|
||||||
|
public let prefix: String
|
||||||
|
public let suffix: String
|
||||||
|
|
||||||
|
public init(prefix: String, suffix: String) {
|
||||||
|
self.prefix = prefix
|
||||||
|
self.suffix = suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public let entries: [String: Entry]
|
||||||
|
|
||||||
|
public init(entries: [String: Entry]) {
|
||||||
|
self.entries = entries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Error
|
||||||
|
|
||||||
|
enum JSONHeaderMapError: LocalizedError {
|
||||||
|
case invalidTopLevelObject
|
||||||
|
case invalidEntryObject
|
||||||
|
case missingPrefix
|
||||||
|
case missingSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSONHeaderMapError {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .invalidTopLevelObject:
|
||||||
|
return "The top level object in the JSON is invalid."
|
||||||
|
case .invalidEntryObject:
|
||||||
|
return "The entry object in the JSON is invalid."
|
||||||
|
case .missingPrefix:
|
||||||
|
return "An entry object does not have a value for the 'prefix' key."
|
||||||
|
case .missingSuffix:
|
||||||
|
return "An entry object does not have a value for the 'suffix' key."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Decode
|
||||||
|
|
||||||
|
extension JSONHeaderMap.Entry {
|
||||||
|
init(json: Any) throws {
|
||||||
|
guard let dict = json as? [String: String] else {
|
||||||
|
throw JSONHeaderMapError.invalidEntryObject
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let prefix = dict[JSONHeaderMapEntryKey.prefix.rawValue] else {
|
||||||
|
throw JSONHeaderMapError.missingPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let suffix = dict[JSONHeaderMapEntryKey.suffix.rawValue] else {
|
||||||
|
throw JSONHeaderMapError.missingSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
self.prefix = prefix
|
||||||
|
self.suffix = suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension JSONHeaderMap {
|
||||||
|
public init(json: Any) throws {
|
||||||
|
guard let dict = json as? [String: Any] else {
|
||||||
|
throw JSONHeaderMapError.invalidTopLevelObject
|
||||||
|
}
|
||||||
|
|
||||||
|
self.entries = try dict.dictionaryMap { (key, jsonValue) in
|
||||||
|
let entry = try Entry(json: jsonValue)
|
||||||
|
return (key, entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(jsonData: Data) throws {
|
||||||
|
let jsonObj = try JSONSerialization.jsonObject(with: jsonData, options: [])
|
||||||
|
try self.init(json: jsonObj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Encode
|
||||||
|
|
||||||
|
extension JSONHeaderMap.Entry {
|
||||||
|
var jsonValue: Any {
|
||||||
|
return [
|
||||||
|
JSONHeaderMapEntryKey.prefix.rawValue: prefix,
|
||||||
|
JSONHeaderMapEntryKey.suffix.rawValue: suffix,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSONHeaderMap {
|
||||||
|
public var jsonValue: Any {
|
||||||
|
return entries.dictionaryMap { (key, entry) in
|
||||||
|
return (key, entry.jsonValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeJSONData(prettyPrinted: Bool = true) throws -> Data {
|
||||||
|
let opts = prettyPrinted ? JSONSerialization.WritingOptions.prettyPrinted : []
|
||||||
|
return try JSONSerialization.data(withJSONObject: jsonValue, options: opts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Keys
|
||||||
|
|
||||||
|
enum JSONHeaderMapEntryKey: String {
|
||||||
|
case prefix = "prefix"
|
||||||
|
case suffix = "suffix"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Conversion
|
||||||
|
|
||||||
|
public extension HeaderMap.Entry {
|
||||||
|
public var jsonEntry: JSONHeaderMap.Entry {
|
||||||
|
return JSONHeaderMap.Entry(
|
||||||
|
prefix: prefix,
|
||||||
|
suffix: suffix
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension JSONHeaderMap.Entry: Hashable {
|
||||||
|
public var hashValue: Int {
|
||||||
|
return prefix.hashValue ^ suffix.hashValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: JSONHeaderMap.Entry, rhs: JSONHeaderMap.Entry) -> Bool {
|
||||||
|
return lhs.prefix == rhs.prefix && lhs.suffix == rhs.suffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension HeaderMap {
|
||||||
|
public func makeJSONHeaderMap() -> JSONHeaderMap {
|
||||||
|
let jsonEntries = makeEntryList().dictionaryMap { (entry) in
|
||||||
|
return (entry.key, entry.jsonEntry)
|
||||||
|
}
|
||||||
|
return JSONHeaderMap(entries: jsonEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func binaryDataFrom(jsonHeaderMap: JSONHeaderMap) throws -> Data {
|
||||||
|
let hmapEntries = jsonHeaderMap.entries.map { (key, jsonEntry) in
|
||||||
|
return HeaderMap.Entry(
|
||||||
|
key: key,
|
||||||
|
prefix: jsonEntry.prefix,
|
||||||
|
suffix: jsonEntry.suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
return try HeaderMap.makeBinary(withEntries: hmapEntries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension JSONHeaderMap {
|
||||||
|
public func makeHeaderMapEntries() -> [HeaderMap.Entry] {
|
||||||
|
return entries.map { (key, value) in
|
||||||
|
return HeaderMap.Entry(key: key, prefix: value.prefix, suffix: value.suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Array {
|
||||||
|
func dictionaryMap<Key: Hashable, Value>(_ mapper: (Element) throws -> (Key, Value)) rethrows -> Dictionary<Key, Value> {
|
||||||
|
var dict = Dictionary<Key, Value>()
|
||||||
|
for element in self {
|
||||||
|
let (key, value) = try mapper(element)
|
||||||
|
dict[key] = value
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Dictionary {
|
||||||
|
func dictionaryMap<NewKey: Hashable, NewValue>(_ mapper: ((Key, Value)) throws -> (NewKey, NewValue)) rethrows -> Dictionary<NewKey, NewValue> {
|
||||||
|
var dict = Dictionary<NewKey, NewValue>()
|
||||||
|
for keyValuePair in self {
|
||||||
|
let (newKey, newValue) = try mapper(keyValuePair)
|
||||||
|
dict[newKey] = newValue
|
||||||
|
}
|
||||||
|
return dict
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol ByteSwappable {
|
||||||
|
func byte(swapped: Bool) -> Self
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt16: ByteSwappable {
|
||||||
|
func byte(swapped: Bool) -> UInt16 {
|
||||||
|
return swapped ? byteSwapped : self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt32: ByteSwappable {
|
||||||
|
func byte(swapped: Bool) -> UInt32 {
|
||||||
|
return swapped ? byteSwapped : self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UInt32 {
|
||||||
|
var isPowerOf2: Bool {
|
||||||
|
return (self != 0) && ((self & (self - 1)) == 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
func clangLowercasedBytes() throws -> Data {
|
||||||
|
guard let charBytes = data(using: BinaryHeaderMap.StringEncoding) else {
|
||||||
|
throw HeaderMapError.unencodableString
|
||||||
|
}
|
||||||
|
|
||||||
|
let lowercasedBytes = charBytes.map { $0.asciiLowercased() }
|
||||||
|
return Data(bytes: lowercasedBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func clangLowercased() throws -> String? {
|
||||||
|
return try String(data: clangLowercasedBytes(), encoding: BinaryHeaderMap.StringEncoding)
|
||||||
|
}
|
||||||
|
|
||||||
|
var headerMapHash: UInt32? {
|
||||||
|
guard
|
||||||
|
let characterBytes = try? clangLowercasedBytes()
|
||||||
|
else { return nil }
|
||||||
|
|
||||||
|
return characterBytes.withUnsafeBytes {
|
||||||
|
(charBlockPointer: UnsafePointer<UInt8>) -> UInt32 in
|
||||||
|
|
||||||
|
var result = UInt32(0)
|
||||||
|
for i in 0 ..< characterBytes.count {
|
||||||
|
let charPointer = charBlockPointer.advanced(by: i)
|
||||||
|
result += UInt32(charPointer.pointee) * 13
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension UInt8 {
|
||||||
|
func asciiLowercased() -> UInt8 {
|
||||||
|
let isUppercase = (65 <= self && self <= 90)
|
||||||
|
return self + (isUppercase ? 32 : 0)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
public protocol ToolCommand {
|
||||||
|
associatedtype InputType
|
||||||
|
associatedtype OutputType
|
||||||
|
|
||||||
|
static func perform(input: InputType) throws -> OutputType
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import HeaderMapCore
|
||||||
|
|
||||||
|
// MARK: - Command Definitions
|
||||||
|
|
||||||
|
public struct MemoryConvertCommand {
|
||||||
|
public struct Input {
|
||||||
|
public let data: Data
|
||||||
|
public let from: HeaderMapFileFormat
|
||||||
|
public let to: HeaderMapFileFormat
|
||||||
|
|
||||||
|
public init(data: Data,
|
||||||
|
from: HeaderMapFileFormat,
|
||||||
|
to: HeaderMapFileFormat) {
|
||||||
|
self.data = data
|
||||||
|
self.from = from
|
||||||
|
self.to = to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Output {
|
||||||
|
public let data: Data
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Error: LocalizedError {
|
||||||
|
case sameFormat(format: HeaderMapFileFormat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FileConvertCommand {
|
||||||
|
public struct Input {
|
||||||
|
public struct TypedFile {
|
||||||
|
public let url: URL
|
||||||
|
public let format: HeaderMapFileFormat
|
||||||
|
|
||||||
|
public init(url: URL) throws {
|
||||||
|
self.url = url
|
||||||
|
self.format = try url.resolveHeaderMapFormat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public let from: TypedFile
|
||||||
|
public let to: TypedFile
|
||||||
|
|
||||||
|
public init(from: TypedFile, to: TypedFile) {
|
||||||
|
self.from = from
|
||||||
|
self.to = to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Error: LocalizedError {
|
||||||
|
case unknownFormat(url: URL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Memory Convert
|
||||||
|
|
||||||
|
extension MemoryConvertCommand: ToolCommand {
|
||||||
|
public typealias InputType = Input
|
||||||
|
public typealias OutputType = Output
|
||||||
|
|
||||||
|
public static func perform(input: Input) throws -> Output {
|
||||||
|
switch (input.from, input.to) {
|
||||||
|
case (.hmap, .json):
|
||||||
|
let hmap = try HeaderMap(data: input.data)
|
||||||
|
let jsonHmap = hmap.makeJSONHeaderMap()
|
||||||
|
let jsonData = try jsonHmap.makeJSONData(prettyPrinted: true)
|
||||||
|
return Output(data: jsonData)
|
||||||
|
|
||||||
|
case (.json, .hmap):
|
||||||
|
let jsonHmap = try JSONHeaderMap(jsonData: input.data)
|
||||||
|
let hmapData = try HeaderMap.binaryDataFrom(jsonHeaderMap: jsonHmap)
|
||||||
|
return Output(data: hmapData)
|
||||||
|
|
||||||
|
case (.json, .json),
|
||||||
|
(.hmap, .hmap):
|
||||||
|
throw MemoryConvertCommand.Error.sameFormat(format: input.from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - File Convert
|
||||||
|
|
||||||
|
extension FileConvertCommand: ToolCommand {
|
||||||
|
public typealias InputType = Input
|
||||||
|
public typealias OutputType = Void
|
||||||
|
|
||||||
|
public static func perform(input: Input) throws -> Void {
|
||||||
|
let fromData = try Data(contentsOf: input.from.url)
|
||||||
|
let outputData = try MemoryConvertCommand.perform(
|
||||||
|
input: MemoryConvertCommand.Input(
|
||||||
|
data: fromData, from: input.from.format, to: input.to.format)
|
||||||
|
)
|
||||||
|
|
||||||
|
try outputData.data.write(to: input.to.url, options: [.atomic])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension URL {
|
||||||
|
func resolveHeaderMapFormat() throws -> HeaderMapFileFormat {
|
||||||
|
switch pathExtension {
|
||||||
|
case "json":
|
||||||
|
return .json
|
||||||
|
case "hmap":
|
||||||
|
return .hmap
|
||||||
|
default:
|
||||||
|
throw FileConvertCommand.Error.unknownFormat(url: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Error Descriptions
|
||||||
|
|
||||||
|
extension MemoryConvertCommand.Error {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .sameFormat(_):
|
||||||
|
return "Must specify different formats for conversion."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FileConvertCommand.Error {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .unknownFormat(let url):
|
||||||
|
return "The format of the file at path \(url.path) could not be determined."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
public enum HeaderMapFileFormat: String {
|
||||||
|
/** Binary format as defined by Clang */
|
||||||
|
case hmap
|
||||||
|
/** JSON format as defined by hmap */
|
||||||
|
case json
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum PrintCommandError: LocalizedError {
|
||||||
|
case cannotOpenFile(path: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PrintCommandError {
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .cannotOpenFile(let path):
|
||||||
|
return "Could not open file at path: \(path)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import HeaderMapCore
|
||||||
|
|
||||||
|
public struct PrintCommandOutput {
|
||||||
|
public let text: String
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct FilePrintCommand: ToolCommand {
|
||||||
|
public typealias InputType = Input
|
||||||
|
public typealias OutputType = PrintCommandOutput
|
||||||
|
|
||||||
|
public struct Input {
|
||||||
|
public let headerMapFile: URL
|
||||||
|
public let argumentPath: String
|
||||||
|
public init(headerMapFile: URL, argumentPath: String) {
|
||||||
|
self.headerMapFile = headerMapFile
|
||||||
|
self.argumentPath = argumentPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func perform(input: Input) throws -> PrintCommandOutput {
|
||||||
|
guard let headerMapData = try? Data(contentsOf: input.headerMapFile) else {
|
||||||
|
throw PrintCommandError.cannotOpenFile(path: input.argumentPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
return try MemoryPrintCommand.perform(
|
||||||
|
input: MemoryPrintCommand.Input(headerMap: headerMapData)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct MemoryPrintCommand: ToolCommand {
|
||||||
|
public typealias InputType = Input
|
||||||
|
public typealias OutputType = PrintCommandOutput
|
||||||
|
|
||||||
|
public struct Input {
|
||||||
|
public let headerMap: Data
|
||||||
|
public init(headerMap: Data) {
|
||||||
|
self.headerMap = headerMap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func perform(input: Input) throws -> PrintCommandOutput {
|
||||||
|
let headerMap = try HeaderMap(data: input.headerMap)
|
||||||
|
let entries = headerMap.makeEntryList().sorted { return $0.key < $1.key }
|
||||||
|
|
||||||
|
let textLines = entries.flatMap { (entry) -> String? in
|
||||||
|
return "\(entry.key) -> \(entry.prefix)\(entry.suffix)"
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = textLines.joined(separator: "\n")
|
||||||
|
return PrintCommandOutput(text: output)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import XCTest
|
||||||
|
|
||||||
|
public enum OptionalError: Error {
|
||||||
|
case unwrappedNil
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Optional {
|
||||||
|
public func unwrap(file: StaticString = #file, line: UInt = #line) throws -> Wrapped {
|
||||||
|
guard let unwrapped = self else {
|
||||||
|
XCTFail("Unwrapped nil: \(file):\(line)")
|
||||||
|
throw OptionalError.unwrappedNil
|
||||||
|
}
|
||||||
|
|
||||||
|
return unwrapped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension XCTestCase {
|
||||||
|
public func loadFile(named name: String, extension ext: String? = nil) throws -> Data? {
|
||||||
|
let url = Bundle(for: type(of: self)).url(forResource: name, withExtension: ext)
|
||||||
|
return try url.map { try Data(contentsOf: $0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Commander
|
||||||
|
import Foundation
|
||||||
|
import HeaderMapFrontend
|
||||||
|
|
||||||
|
func addConvertCommand(to group: Group) {
|
||||||
|
let sourceFileArgument = Argument<String>(
|
||||||
|
"source_file",
|
||||||
|
description: "Path to the file to be converted"
|
||||||
|
)
|
||||||
|
let destFileArgument = Argument<String>(
|
||||||
|
"dest_file",
|
||||||
|
description: "Path to the converted file"
|
||||||
|
)
|
||||||
|
|
||||||
|
group.command("convert", sourceFileArgument, destFileArgument) {
|
||||||
|
(from, to) in
|
||||||
|
|
||||||
|
do {
|
||||||
|
let fromUrl = URL(fileURLWithPath: from)
|
||||||
|
let fromFile = try FileConvertCommand.Input.TypedFile(url: fromUrl)
|
||||||
|
|
||||||
|
let toUrl = URL(fileURLWithPath: to)
|
||||||
|
let toFile = try FileConvertCommand.Input.TypedFile(url: toUrl)
|
||||||
|
|
||||||
|
let input = FileConvertCommand.Input(from: fromFile, to: toFile)
|
||||||
|
try FileConvertCommand.perform(input: input)
|
||||||
|
} catch (let error) {
|
||||||
|
Swift.print(error.localizedDescription)
|
||||||
|
exit(ToolReturnCode.failure.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Commander
|
||||||
|
import Foundation
|
||||||
|
import HeaderMapFrontend
|
||||||
|
|
||||||
|
func addPrintCommand(to group: Group) {
|
||||||
|
let fileArgument = Argument<String>(
|
||||||
|
"file",
|
||||||
|
description: "Path to header map file"
|
||||||
|
)
|
||||||
|
|
||||||
|
group.command("print", fileArgument) { (file) in
|
||||||
|
do {
|
||||||
|
let url = file.expandedFileURL
|
||||||
|
let output = try FilePrintCommand.perform(
|
||||||
|
input: FilePrintCommand.Input(headerMapFile: url, argumentPath: file)
|
||||||
|
)
|
||||||
|
Swift.print(output.text)
|
||||||
|
} catch (let error) {
|
||||||
|
Swift.print(error.localizedDescription)
|
||||||
|
exit(ToolReturnCode.failure.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
enum ToolReturnCode: Int32 {
|
||||||
|
case failure = 1
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
var expandedFileURL: URL {
|
||||||
|
return URL(fileURLWithPath: (self as NSString).expandingTildeInPath)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import Commander
|
||||||
|
import HeaderMapFrontend
|
||||||
|
|
||||||
|
public let version = "1.0.0"
|
||||||
|
|
||||||
|
let commandGroup = Group()
|
||||||
|
addPrintCommand(to: commandGroup)
|
||||||
|
addConvertCommand(to: commandGroup)
|
||||||
|
|
||||||
|
commandGroup.run(version)
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import HeaderMapCore
|
||||||
|
import HeaderMapTesting
|
||||||
|
|
||||||
|
class HeaderMapTests: XCTestCase {
|
||||||
|
func testHeaderMapASCIIKeyMatching() throws {
|
||||||
|
let entries = [
|
||||||
|
HeaderMap.Entry(
|
||||||
|
key: "Foo/Foo.h",
|
||||||
|
prefix: "/Users/Foo/Source",
|
||||||
|
suffix: "Foo.h"),
|
||||||
|
]
|
||||||
|
|
||||||
|
let hmap = try HeaderMap(entries: entries)
|
||||||
|
|
||||||
|
let fooEntryExactCase = hmap["Foo/Foo.h"]
|
||||||
|
XCTAssertNotNil(fooEntryExactCase)
|
||||||
|
XCTAssertEqual(fooEntryExactCase, entries.first)
|
||||||
|
|
||||||
|
let fooEntryLowercase = hmap["foo/foo.h"]
|
||||||
|
XCTAssertNotNil(fooEntryLowercase)
|
||||||
|
XCTAssertEqual(fooEntryLowercase, entries.first)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHeaderMapUnicodeKeyMatching() throws {
|
||||||
|
let lowercaseAUmlaut = "\u{00E4}"
|
||||||
|
let uppercaseAUmlaut = "\u{00C4}"
|
||||||
|
let entries = [
|
||||||
|
HeaderMap.Entry(
|
||||||
|
key: uppercaseAUmlaut,
|
||||||
|
prefix: "/Users/Foo/Source",
|
||||||
|
suffix: uppercaseAUmlaut),
|
||||||
|
]
|
||||||
|
|
||||||
|
let hmap = try HeaderMap(entries: entries)
|
||||||
|
|
||||||
|
let fooEntryExactCase = hmap[uppercaseAUmlaut]
|
||||||
|
XCTAssertNotNil(fooEntryExactCase)
|
||||||
|
XCTAssertEqual(fooEntryExactCase, entries.first)
|
||||||
|
|
||||||
|
// By definition, lowercasing is ASCII-only
|
||||||
|
let fooEntryLowercase = hmap[lowercaseAUmlaut]
|
||||||
|
XCTAssertNil(fooEntryLowercase)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHeaderMap8BitKeyMatching() throws {
|
||||||
|
let eAcute = "\u{E9}"
|
||||||
|
let combinedEAcute = "\u{65}\u{301}"
|
||||||
|
XCTAssertEqual(eAcute, combinedEAcute)
|
||||||
|
|
||||||
|
let entries = [
|
||||||
|
HeaderMap.Entry(key: eAcute, prefix: "", suffix: ""),
|
||||||
|
]
|
||||||
|
|
||||||
|
let hmap = try HeaderMap(entries: entries)
|
||||||
|
|
||||||
|
// By definition, key comparison is not Unicode-aware
|
||||||
|
XCTAssertNotNil(hmap[eAcute])
|
||||||
|
XCTAssertNil(hmap[combinedEAcute])
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRealmHeaderMap() throws {
|
||||||
|
let hmapData = try loadFile(named: "Realm", extension: "hmap").unwrap()
|
||||||
|
let headerMap = try HeaderMap(data: hmapData)
|
||||||
|
|
||||||
|
let jsonData = try loadFile(named: "Realm", extension: "json").unwrap()
|
||||||
|
let jsonHeaderMap = try JSONHeaderMap(jsonData: jsonData)
|
||||||
|
|
||||||
|
let entries = Set<HeaderMap.Entry>(headerMap.makeEntryList())
|
||||||
|
let jsonEntries = Set<HeaderMap.Entry>(jsonHeaderMap.makeHeaderMapEntries())
|
||||||
|
XCTAssertEqual(entries, jsonEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHeaderMapBinaryFormat() throws {
|
||||||
|
let entries = Set<HeaderMap.Entry>([
|
||||||
|
HeaderMap.Entry(key: "A", prefix: "B", suffix: "C"),
|
||||||
|
HeaderMap.Entry(key: "D", prefix: "E", suffix: "F"),
|
||||||
|
HeaderMap.Entry(key: "G", prefix: "H", suffix: "I"),
|
||||||
|
])
|
||||||
|
|
||||||
|
let hmapBinaryData = try HeaderMap.makeBinary(withEntries: Array(entries))
|
||||||
|
let hmap = try HeaderMap(data: hmapBinaryData)
|
||||||
|
let hmapEntries = Set<HeaderMap.Entry>(hmap.makeEntryList())
|
||||||
|
XCTAssertEqual(entries, hmapEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHeaderMapJSONFormat() throws {
|
||||||
|
let entries = [
|
||||||
|
"A": JSONHeaderMap.Entry(prefix: "B", suffix: "C"),
|
||||||
|
"D": JSONHeaderMap.Entry(prefix: "E", suffix: "F"),
|
||||||
|
]
|
||||||
|
|
||||||
|
let jsonData = try JSONHeaderMap(entries: entries).makeJSONData()
|
||||||
|
let decodedEntries = try JSONHeaderMap(jsonData: jsonData).entries
|
||||||
|
XCTAssertEqual(entries, decodedEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHeaderMapFormatConversions() throws {
|
||||||
|
let entries = [
|
||||||
|
"A": JSONHeaderMap.Entry(prefix: "B", suffix: "C"),
|
||||||
|
"D": JSONHeaderMap.Entry(prefix: "E", suffix: "F"),
|
||||||
|
]
|
||||||
|
|
||||||
|
let jsonHeaderMap = JSONHeaderMap(entries: entries)
|
||||||
|
let hmapEntries = jsonHeaderMap.makeHeaderMapEntries()
|
||||||
|
let hmap = try HeaderMap(entries: hmapEntries)
|
||||||
|
let decodedEntries = hmap.makeJSONHeaderMap().entries
|
||||||
|
XCTAssertEqual(entries, decodedEntries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,786 @@
|
||||||
|
{
|
||||||
|
"list_notifier.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "list_notifier.hpp"
|
||||||
|
},
|
||||||
|
"list.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "list.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/NSError+RLMSync.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "NSError+RLMSync.h"
|
||||||
|
},
|
||||||
|
"RLMSyncCredentials.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncCredentials.h"
|
||||||
|
},
|
||||||
|
"RLMCollection_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMCollection_Private.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/Realm.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "Realm.h"
|
||||||
|
},
|
||||||
|
"RLMCollection_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMCollection_Private.h"
|
||||||
|
},
|
||||||
|
"thread_safe_reference.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "thread_safe_reference.hpp"
|
||||||
|
},
|
||||||
|
"RLMObservation.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObservation.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionOffer.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOffer.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSchema.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSchema.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMThreadSafeReference.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMThreadSafeReference.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionResults_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionResults_Private.hpp"
|
||||||
|
},
|
||||||
|
"RLMQueryUtil.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMQueryUtil.hpp"
|
||||||
|
},
|
||||||
|
"RLMListBase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMListBase.h"
|
||||||
|
},
|
||||||
|
"RLMCollection.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMCollection.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionResults.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionResults.h"
|
||||||
|
},
|
||||||
|
"aligned_union.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "aligned_union.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncSession.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncSession.h"
|
||||||
|
},
|
||||||
|
"binding_context.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "binding_context.hpp"
|
||||||
|
},
|
||||||
|
"RLMAccessor.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMAccessor.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObjectBase_Dynamic.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectBase_Dynamic.h"
|
||||||
|
},
|
||||||
|
"RLMAccessor.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMAccessor.h"
|
||||||
|
},
|
||||||
|
"RLMThreadSafeReference.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMThreadSafeReference.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMRealmConfiguration.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration.h"
|
||||||
|
},
|
||||||
|
"atomic_shared_ptr.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "atomic_shared_ptr.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncManager.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncManager.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncConfiguration.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncConfiguration.h"
|
||||||
|
},
|
||||||
|
"sync_session.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/",
|
||||||
|
"suffix" : "sync_session.hpp"
|
||||||
|
},
|
||||||
|
"system_configuration.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/impl\/apple\/",
|
||||||
|
"suffix" : "system_configuration.hpp"
|
||||||
|
},
|
||||||
|
"RLMAssertions.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/Tests\/",
|
||||||
|
"suffix" : "RLMAssertions.h"
|
||||||
|
},
|
||||||
|
"event_loop_signal.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "event_loop_signal.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncSessionRefreshHandle.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncSessionRefreshHandle.hpp"
|
||||||
|
},
|
||||||
|
"sync_file.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/impl\/",
|
||||||
|
"suffix" : "sync_file.hpp"
|
||||||
|
},
|
||||||
|
"RLMProperty_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMProperty_Private.hpp"
|
||||||
|
},
|
||||||
|
"RLMArray_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMArray_Private.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMRealmConfiguration_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration_Private.h"
|
||||||
|
},
|
||||||
|
"results.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "results.hpp"
|
||||||
|
},
|
||||||
|
"RLMObjectSchema.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectSchema.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionValue_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionValue_Private.hpp"
|
||||||
|
},
|
||||||
|
"binding_callback_thread_observer.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "binding_callback_thread_observer.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionOffer_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOffer_Private.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncCredentials.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncCredentials.h"
|
||||||
|
},
|
||||||
|
"RLMTestUtils.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectServerTests\/",
|
||||||
|
"suffix" : "RLMTestUtils.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMProperty.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMProperty.h"
|
||||||
|
},
|
||||||
|
"RLMPredicateUtil.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMPredicateUtil.hpp"
|
||||||
|
},
|
||||||
|
"RLMTestCase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/Tests\/",
|
||||||
|
"suffix" : "RLMTestCase.h"
|
||||||
|
},
|
||||||
|
"RLMRealmConfiguration_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration_Private.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionOfferResponse_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOfferResponse_Private.h"
|
||||||
|
},
|
||||||
|
"RLMObjectStore.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectStore.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMResults_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMResults_Private.h"
|
||||||
|
},
|
||||||
|
"RLMObjectBase_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectBase_Private.h"
|
||||||
|
},
|
||||||
|
"weak_realm_notifier.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "weak_realm_notifier.hpp"
|
||||||
|
},
|
||||||
|
"RLMResults.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMResults.h"
|
||||||
|
},
|
||||||
|
"object_accessor.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "object_accessor.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncUser.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUser.h"
|
||||||
|
},
|
||||||
|
"RLMSyncUser_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUser_Private.hpp"
|
||||||
|
},
|
||||||
|
"RLMRealm_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm_Private.h"
|
||||||
|
},
|
||||||
|
"RLMObjectBase_Dynamic.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectBase_Dynamic.h"
|
||||||
|
},
|
||||||
|
"RLMRealmConfiguration_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration_Private.h"
|
||||||
|
},
|
||||||
|
"RLMNetworkClient.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMNetworkClient.h"
|
||||||
|
},
|
||||||
|
"RLMResults_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMResults_Private.h"
|
||||||
|
},
|
||||||
|
"RLMSwiftBridgingHeader.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSwiftBridgingHeader.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObjectSchema_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectSchema_Private.h"
|
||||||
|
},
|
||||||
|
"sync_metadata.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/impl\/",
|
||||||
|
"suffix" : "sync_metadata.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMArray.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMArray.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMProperty_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMProperty_Private.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSwiftSupport.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSwiftSupport.h"
|
||||||
|
},
|
||||||
|
"results_notifier.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "results_notifier.hpp"
|
||||||
|
},
|
||||||
|
"RLMPrefix.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMPrefix.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMCollection.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMCollection.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMAccessor.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMAccessor.h"
|
||||||
|
},
|
||||||
|
"Swift-Tests-Bridging-Header.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/Tests\/Swift\/",
|
||||||
|
"suffix" : "Swift-Tests-Bridging-Header.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermission.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermission.h"
|
||||||
|
},
|
||||||
|
"RLMSyncUtil_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUtil_Private.hpp"
|
||||||
|
},
|
||||||
|
"RLMOptionalBase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMOptionalBase.h"
|
||||||
|
},
|
||||||
|
"RLMObject_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObject_Private.hpp"
|
||||||
|
},
|
||||||
|
"RealmSwiftTests-BridgingHeader.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/RealmSwift\/Tests\/",
|
||||||
|
"suffix" : "RealmSwiftTests-BridgingHeader.h"
|
||||||
|
},
|
||||||
|
"schema.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "schema.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncUser+ObjectServerTests.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectServerTests\/",
|
||||||
|
"suffix" : "RLMSyncUser+ObjectServerTests.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObject_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObject_Private.h"
|
||||||
|
},
|
||||||
|
"realm_coordinator.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "realm_coordinator.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionOfferResponse.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOfferResponse.h"
|
||||||
|
},
|
||||||
|
"RLMSyncSession.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncSession.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncConfiguration_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncConfiguration_Private.h"
|
||||||
|
},
|
||||||
|
"property.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "property.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionOfferResponse_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOfferResponse_Private.h"
|
||||||
|
},
|
||||||
|
"RLMSchema_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSchema_Private.h"
|
||||||
|
},
|
||||||
|
"RLMArray.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMArray.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionValue.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionValue.h"
|
||||||
|
},
|
||||||
|
"RLMSyncManager_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncManager_Private.h"
|
||||||
|
},
|
||||||
|
"object_accessor_impl.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "object_accessor_impl.hpp"
|
||||||
|
},
|
||||||
|
"network_reachability.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/impl\/",
|
||||||
|
"suffix" : "network_reachability.hpp"
|
||||||
|
},
|
||||||
|
"object_store.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "object_store.hpp"
|
||||||
|
},
|
||||||
|
"NSError+RLMSync.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "NSError+RLMSync.h"
|
||||||
|
},
|
||||||
|
"TestUtils.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/Tests\/",
|
||||||
|
"suffix" : "TestUtils.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermission.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermission.h"
|
||||||
|
},
|
||||||
|
"RLMMigration.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMMigration.h"
|
||||||
|
},
|
||||||
|
"RLMRealm_Dynamic.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm_Dynamic.h"
|
||||||
|
},
|
||||||
|
"RLMRealm_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm_Private.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMResults.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMResults.h"
|
||||||
|
},
|
||||||
|
"RLMSchema_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSchema_Private.hpp"
|
||||||
|
},
|
||||||
|
"keychain_helper.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/apple\/",
|
||||||
|
"suffix" : "keychain_helper.hpp"
|
||||||
|
},
|
||||||
|
"RLMUtil.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMUtil.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionChange.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionChange.h"
|
||||||
|
},
|
||||||
|
"network_reachability_observer.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/impl\/apple\/",
|
||||||
|
"suffix" : "network_reachability_observer.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncConfiguration_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncConfiguration_Private.hpp"
|
||||||
|
},
|
||||||
|
"RLMMigration_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMMigration_Private.h"
|
||||||
|
},
|
||||||
|
"collection_notifier.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "collection_notifier.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionOffer.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOffer.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermission_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermission_Private.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObject.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObject.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMMigration.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMMigration.h"
|
||||||
|
},
|
||||||
|
"RLMUpdateChecker.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMUpdateChecker.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncSession_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncSession_Private.hpp"
|
||||||
|
},
|
||||||
|
"object_notifier.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "object_notifier.hpp"
|
||||||
|
},
|
||||||
|
"feature_checks.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "feature_checks.hpp"
|
||||||
|
},
|
||||||
|
"RLMMultiProcessTestCase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/Tests\/",
|
||||||
|
"suffix" : "RLMMultiProcessTestCase.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionResults.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionResults.h"
|
||||||
|
},
|
||||||
|
"sync_config.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/",
|
||||||
|
"suffix" : "sync_config.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncSessionRefreshHandle.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncSessionRefreshHandle.h"
|
||||||
|
},
|
||||||
|
"RLMObject_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObject_Private.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncManager.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncManager.h"
|
||||||
|
},
|
||||||
|
"RLMObjectSchema_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectSchema_Private.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionChange_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionChange_Private.h"
|
||||||
|
},
|
||||||
|
"execution_context_id.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "execution_context_id.hpp"
|
||||||
|
},
|
||||||
|
"format.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "format.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncPermission_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermission_Private.h"
|
||||||
|
},
|
||||||
|
"tagged_bool.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "tagged_bool.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionChange_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionChange_Private.h"
|
||||||
|
},
|
||||||
|
"RLMRealm.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm.h"
|
||||||
|
},
|
||||||
|
"collection_notifications.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "collection_notifications.hpp"
|
||||||
|
},
|
||||||
|
"RLMSwiftSupport.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSwiftSupport.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionChange.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionChange.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncUtil_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUtil_Private.h"
|
||||||
|
},
|
||||||
|
"RLMSyncSessionRefreshHandle+ObjectServerTests.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectServerTests\/",
|
||||||
|
"suffix" : "RLMSyncSessionRefreshHandle+ObjectServerTests.h"
|
||||||
|
},
|
||||||
|
"RLMProperty.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMProperty.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObjectBase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectBase.h"
|
||||||
|
},
|
||||||
|
"compiler.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "compiler.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMConstants.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMConstants.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMListBase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMListBase.h"
|
||||||
|
},
|
||||||
|
"descriptor_ordering.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "descriptor_ordering.hpp"
|
||||||
|
},
|
||||||
|
"RLMSchema.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSchema.h"
|
||||||
|
},
|
||||||
|
"sync_permission.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/",
|
||||||
|
"suffix" : "sync_permission.hpp"
|
||||||
|
},
|
||||||
|
"Realm.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "Realm.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSchema_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSchema_Private.h"
|
||||||
|
},
|
||||||
|
"RLMRealmUtil.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmUtil.hpp"
|
||||||
|
},
|
||||||
|
"RLMTestObjects.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/Tests\/",
|
||||||
|
"suffix" : "RLMTestObjects.h"
|
||||||
|
},
|
||||||
|
"index_set.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "index_set.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncConfiguration.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncConfiguration.h"
|
||||||
|
},
|
||||||
|
"RLMProperty_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMProperty_Private.h"
|
||||||
|
},
|
||||||
|
"RLMJSONModels.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMJSONModels.h"
|
||||||
|
},
|
||||||
|
"RLMObjectBase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectBase.h"
|
||||||
|
},
|
||||||
|
"RLMSyncManager+ObjectServerTests.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectServerTests\/",
|
||||||
|
"suffix" : "RLMSyncManager+ObjectServerTests.h"
|
||||||
|
},
|
||||||
|
"RLMSyncUser.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUser.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObjectStore.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectStore.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMRealmConfiguration+Sync.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration+Sync.h"
|
||||||
|
},
|
||||||
|
"RLMObject.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObject.h"
|
||||||
|
},
|
||||||
|
"external_commit_helper.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "external_commit_helper.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMArray_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMArray_Private.h"
|
||||||
|
},
|
||||||
|
"sync_manager.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/",
|
||||||
|
"suffix" : "sync_manager.hpp"
|
||||||
|
},
|
||||||
|
"RLMArray_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMArray_Private.h"
|
||||||
|
},
|
||||||
|
"object.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "object.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMRealm.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm.h"
|
||||||
|
},
|
||||||
|
"RLMRealmConfiguration+Sync.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration+Sync.h"
|
||||||
|
},
|
||||||
|
"RLMSyncConfiguration_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncConfiguration_Private.h"
|
||||||
|
},
|
||||||
|
"RLMRealmConfiguration.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealmConfiguration.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionValue.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionValue.h"
|
||||||
|
},
|
||||||
|
"sync_client.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/impl\/",
|
||||||
|
"suffix" : "sync_client.hpp"
|
||||||
|
},
|
||||||
|
"object_schema.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "object_schema.hpp"
|
||||||
|
},
|
||||||
|
"RLMObjectSchema_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectSchema_Private.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMRealm_Dynamic.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm_Dynamic.h"
|
||||||
|
},
|
||||||
|
"RLMSyncTestCase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectServerTests\/",
|
||||||
|
"suffix" : "RLMSyncTestCase.h"
|
||||||
|
},
|
||||||
|
"any.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "any.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObjectBase_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectBase_Private.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncUtil.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUtil.h"
|
||||||
|
},
|
||||||
|
"Object-Server-Tests-Bridging-Header.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectServerTests\/",
|
||||||
|
"suffix" : "Object-Server-Tests-Bridging-Header.h"
|
||||||
|
},
|
||||||
|
"collection_change_builder.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "collection_change_builder.hpp"
|
||||||
|
},
|
||||||
|
"uuid.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "uuid.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMOptionalBase.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMOptionalBase.h"
|
||||||
|
},
|
||||||
|
"RLMThreadSafeReference_Private.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMThreadSafeReference_Private.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMSyncPermissionOfferResponse.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOfferResponse.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMCollection_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMCollection_Private.h"
|
||||||
|
},
|
||||||
|
"RLMSyncPermissionOffer_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncPermissionOffer_Private.h"
|
||||||
|
},
|
||||||
|
"transact_log_handler.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/impl\/",
|
||||||
|
"suffix" : "transact_log_handler.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMObjectSchema.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMObjectSchema.h"
|
||||||
|
},
|
||||||
|
"shared_realm.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/",
|
||||||
|
"suffix" : "shared_realm.hpp"
|
||||||
|
},
|
||||||
|
"RLMSyncUtil_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUtil_Private.h"
|
||||||
|
},
|
||||||
|
"RLMSyncUtil.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMSyncUtil.h"
|
||||||
|
},
|
||||||
|
"Realm\/RLMMigration_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMMigration_Private.h"
|
||||||
|
},
|
||||||
|
"RLMAnalytics.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMAnalytics.hpp"
|
||||||
|
},
|
||||||
|
"RLMConstants.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMConstants.h"
|
||||||
|
},
|
||||||
|
"sync_user.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/sync\/",
|
||||||
|
"suffix" : "sync_user.hpp"
|
||||||
|
},
|
||||||
|
"RLMClassInfo.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMClassInfo.hpp"
|
||||||
|
},
|
||||||
|
"time.hpp" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/ObjectStore\/src\/util\/",
|
||||||
|
"suffix" : "time.hpp"
|
||||||
|
},
|
||||||
|
"Realm\/RLMRealm_Private.h" : {
|
||||||
|
"prefix" : "\/Users\/milen\/Downloads\/realm-cocoa\/Realm\/",
|
||||||
|
"suffix" : "RLMRealm_Private.h"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 Milen Dzhumerov
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import HeaderMapCore
|
||||||
|
import HeaderMapFrontend
|
||||||
|
import HeaderMapTesting
|
||||||
|
|
||||||
|
class CommandTests: XCTestCase {
|
||||||
|
func testReadCommand() throws {
|
||||||
|
let hmapData = try loadFile(named: "map", extension: "hmap").unwrap()
|
||||||
|
let input = MemoryPrintCommand.Input(headerMap: hmapData)
|
||||||
|
let output = try MemoryPrintCommand.perform(input: input)
|
||||||
|
|
||||||
|
let printoutData = try loadFile(named: "map", extension: "txt").unwrap()
|
||||||
|
let printoutText = try String(data: printoutData, encoding: .utf8).unwrap()
|
||||||
|
XCTAssertEqual(output.text, printoutText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testConvertCommand() throws {
|
||||||
|
let hmapData = try loadFile(named: "map", extension: "hmap").unwrap()
|
||||||
|
let input = MemoryConvertCommand.Input(
|
||||||
|
data: hmapData,
|
||||||
|
from: .hmap,
|
||||||
|
to: .json)
|
||||||
|
|
||||||
|
let output = try MemoryConvertCommand.perform(input: input)
|
||||||
|
let jsonFileData = try loadFile(named: "map", extension: "json").unwrap()
|
||||||
|
|
||||||
|
let jsonHeaderFromFile = try JSONHeaderMap(jsonData: jsonFileData)
|
||||||
|
let jsonHeaderFromCommand = try JSONHeaderMap(jsonData: output.data)
|
||||||
|
|
||||||
|
XCTAssertEqual(jsonHeaderFromFile.entries, jsonHeaderFromCommand.entries)
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"A": {
|
||||||
|
"prefix": "A1",
|
||||||
|
"suffix": "A2"
|
||||||
|
},
|
||||||
|
"B": {
|
||||||
|
"prefix": "B1",
|
||||||
|
"suffix": "B2"
|
||||||
|
},
|
||||||
|
"C": {
|
||||||
|
"prefix": "C1",
|
||||||
|
"suffix": "C2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
A -> A1A2
|
||||||
|
B -> B1B2
|
||||||
|
C -> C1C2
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>BNDL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string></string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,163 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "9999"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_68"
|
||||||
|
BuildableName = "Spectre.framework"
|
||||||
|
BlueprintName = "Spectre"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_82"
|
||||||
|
BuildableName = "Commander.framework"
|
||||||
|
BlueprintName = "Commander"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_99"
|
||||||
|
BuildableName = "hmap"
|
||||||
|
BlueprintName = "hmap"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_117"
|
||||||
|
BuildableName = "HeaderMapCore.framework"
|
||||||
|
BlueprintName = "HeaderMapCore"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_139"
|
||||||
|
BuildableName = "HeaderMapTesting.framework"
|
||||||
|
BlueprintName = "HeaderMapTesting"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_119"
|
||||||
|
BuildableName = "HeaderMapFrontend.framework"
|
||||||
|
BlueprintName = "HeaderMapFrontend"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_166"
|
||||||
|
BuildableName = "HeaderMapCoreTests.xctest"
|
||||||
|
BlueprintName = "HeaderMapCoreTests"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_179"
|
||||||
|
BuildableName = "HeaderMapFrontendTests.xctest"
|
||||||
|
BlueprintName = "HeaderMapFrontendTests"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
language = ""
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "OBJ_68"
|
||||||
|
BuildableName = "Spectre.framework"
|
||||||
|
BlueprintName = "Spectre"
|
||||||
|
ReferencedContainer = "container:hmap.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<AdditionalOptions>
|
||||||
|
</AdditionalOptions>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>SchemeUserState</key>
|
||||||
|
<dict>
|
||||||
|
<key>hmap.xcscheme</key>
|
||||||
|
<dict></dict>
|
||||||
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict></dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Loading…
Reference in New Issue