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