Skip to content

Commit

Permalink
Add initial Swift wrapper classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Alejandro Isaza committed Oct 2, 2015
1 parent 1ea99f4 commit 5dcf63a
Show file tree
Hide file tree
Showing 9 changed files with 510 additions and 216 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Xcode per-user config
*.mode1
*.mode1v3
*.mode2v3
*.pbxuser
xcuserdata/
*.xccheckout

# Object files
*.o
*.lo
.deps/
.libs/
365 changes: 185 additions & 180 deletions HDF5.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions HDF5/Dataset.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright © 2015 Venture Media Labs. All rights reserved.

import Foundation

public class Dataset {
var id: Int32 = -1

public init(file: File, name: String, datatype: Datatype, dataspace: Dataspace) {
name.withCString{ name in
id = H5Dcreate2(file.id, name, datatype.id, dataspace.id, 0, 0, 0)
}
guard id >= 0 else {
fatalError("Failed to create Dataset")
}
}

/// The address in the file of the dataset or `nil` if the offset is undefined. That address is expressed as the offset in bytes from the beginning of the file.
public var offset: UInt64? {
let offset = H5Dget_offset(id)
guard offset != unsafeBitCast(-1, UInt64.self) else {
return nil
}
return offset
}

public var space: Dataspace {
return Dataspace(id: H5Dget_space(id))
}

public func read(inout data: [Double]) -> Bool {
let status = H5Dread(id, H5T_NATIVE_DOUBLE_g, 0, 0, 0, &data)
return status >= 0
}

public func write(data: [Double]) -> Bool {
let status = H5Dwrite(id, H5T_NATIVE_DOUBLE_g, 0, 0, 0, data);
return status >= 0
}
}
39 changes: 39 additions & 0 deletions HDF5/Dataspace.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright © 2015 Venture Media Labs. All rights reserved.

import Foundation

public class Dataspace {
var id: Int32

init(id: Int32) {
self.id = id
guard id >= 0 else {
fatalError("Failed to create Dataspace")
}
}

public init(dims: [UInt64]) {
id = H5Screate_simple(Int32(dims.count), dims, nil)
guard id >= 0 else {
fatalError("Failed to create Dataspace")
}
}

deinit {
let status = H5Sclose(id)
assert(status >= 0, "Failed to close Dataspace")
}

public var size: Int64 {
return H5Sget_simple_extent_npoints(id)
}

public var dims: [UInt64] {
let rank = Int(H5Sget_simple_extent_ndims(id))
var dims = [UInt64](count: rank, repeatedValue: UInt64(0))
guard H5Sget_simple_extent_dims(id, &dims, nil) >= 0 else {
fatalError("Coulnd't get the dimensons of the Dataspace")
}
return dims
}
}
118 changes: 118 additions & 0 deletions HDF5/Datatype.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright © 2015 Venture Media Labs. All rights reserved.

import Foundation

public class Datatype {
public enum DataClass: Int32 {
case NoClass = -1 // error
case Integer = 0 // integer types
case Float = 1 // floating-point types
case Time = 2 // date and time types
case String = 3 // character string types
case BitField = 4 // bit field types
case Opaque = 5 // opaque types
case Compound = 6 // compound types
case Reference = 7 // reference types
case Enum = 8 // enumeration types
case VarLength = 9 // Variable-Length types
case Array = 10 // Array types
}

public enum NativeType {
case Byte
case UByte
case Short
case UShort
case Int
case UInt
case Long
case ULong
case LongLong
case ULongLong
case Float
case Double
case LongDouble
case Int8
case UInt8
case Int16
case UInt16
case Int32
case UInt32
case Int64
case UInt64
case Opaque

public var rawValue: Swift.Int32 {
switch self {
case Byte: return H5T_NATIVE_SCHAR_g
case UByte: return H5T_NATIVE_UCHAR_g
case Short: return H5T_NATIVE_SHORT_g
case UShort: return H5T_NATIVE_USHORT_g
case Int: return H5T_NATIVE_INT_g
case UInt: return H5T_NATIVE_UINT_g
case Long: return H5T_NATIVE_LONG_g
case ULong: return H5T_NATIVE_ULONG_g
case LongLong: return H5T_NATIVE_LLONG_g
case ULongLong: return H5T_NATIVE_ULLONG_g
case Float: return H5T_NATIVE_FLOAT_g
case Double: return H5T_NATIVE_DOUBLE_g
case LongDouble: return H5T_NATIVE_LDOUBLE_g
case Int8: return H5T_NATIVE_INT8_g
case UInt8: return H5T_NATIVE_UINT8_g
case Int16: return H5T_NATIVE_INT16_g
case UInt16: return H5T_NATIVE_UINT16_g
case Int32: return H5T_NATIVE_INT32_g
case UInt32: return H5T_NATIVE_UINT32_g
case Int64: return H5T_NATIVE_INT64_g
case UInt64: return H5T_NATIVE_UINT64_g
case Opaque: return H5T_NATIVE_OPAQUE_g
}
}
}

/// Create a Datatype from a class and a size
public init(dataClass: DataClass, size: Int) {
id = H5Tcreate(H5T_class_t(dataClass.rawValue), size)
guard id >= 0 else {
fatalError("Failed to create Datatype")
}
}

/// Copies an existing Datatype from a native type
public class func copy(type: NativeType) -> Datatype {
let id = H5Tcopy(type.rawValue)
return Datatype(id: id)
}
var id: Int32

init(id: Int32) {
self.id = id
guard id >= 0 else {
fatalError("Failed to create Datatype")
}
}

deinit {
let status = H5Tclose(id)
assert(status >= 0, "Failed to close Datatype")
}

public enum Order: Int32 {
case Error = -1
case LittleEndian = 0
case BigEndian = 1
case Vax = 2
case Mixed = 3
case Nonde = 4
}

/// The byte order of the Datatype
public var order: Order {
get {
return Order(rawValue: H5Tget_order(id).rawValue)!
}
set {
H5Tset_order(id, H5T_order_t(newValue.rawValue))
}
}
}
55 changes: 55 additions & 0 deletions HDF5/File.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright © 2015 Venture Media Labs. All rights reserved.

import Foundation

public class File {
public enum CreateMode: UInt32 {
case Truncate = 0x02 // Overwrite existing files
case Exclusive = 0x04 // Fail if file already exists
}

public class func create(filePath: String, mode: CreateMode) -> File? {
var id: Int32 = -1
filePath.withCString { filePath in
id = H5Fcreate(filePath, mode.rawValue, 0, 0)
}
guard id >= 0 else {
return nil
}
return File(id: id)
}

public enum OpenMode: UInt32 {
case ReadOnly = 0x00
case ReadWrite = 0x01
}

public class func open(filePath: String, mode: OpenMode) -> File? {
var id: Int32 = -1
filePath.withCString { filePath in
id = H5Fopen(filePath, mode.rawValue, 0)
}
guard id >= 0 else {
return nil
}
return File(id: id)
}

var id: Int32 = -1

init(id: Int32) {
self.id = id
guard id >= 0 else {
fatalError("Failed to create Dataspace")
}
}

deinit {
let status = H5Fclose(id)
assert(status >= 0, "Failed to close HDF5 file")
}

public func flush() {
H5Fflush(id, H5F_SCOPE_LOCAL)
}
}
30 changes: 20 additions & 10 deletions HDF5/HDF5.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
//
// HDF5.h
// HDF5
//
// Created by Alejandro Isaza on 2015-10-01.
// Copyright © 2015 Venture Media Labs. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>

//! Project version number for HDF5.
FOUNDATION_EXPORT double HDF5VersionNumber;

//! Project version string for HDF5.
FOUNDATION_EXPORT const unsigned char HDF5VersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <HDF5/PublicHeader.h>


#import <HDF5/H5Apublic.h>
#import <HDF5/H5ACpublic.h>
#import <HDF5/H5Bpublic.h>
#import <HDF5/H5B2public.h>
#import <HDF5/H5Dpublic.h>
#import <HDF5/H5Epublic.h>
#import <HDF5/H5Fpublic.h>
#import <HDF5/H5FDpublic.h>
#import <HDF5/H5FSpublic.h>
#import <HDF5/H5Gpublic.h>
#import <HDF5/H5HFpublic.h>
#import <HDF5/H5HGpublic.h>
#import <HDF5/H5HLpublic.h>
#import <HDF5/H5MMpublic.h>
#import <HDF5/H5Ppublic.h>
#import <HDF5/H5PLpublic.h>
#import <HDF5/H5Rpublic.h>
#import <HDF5/H5Spublic.h>
#import <HDF5/H5Zpublic.h>
2 changes: 1 addition & 1 deletion HDF5/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>0.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
65 changes: 40 additions & 25 deletions HDF5Tests/HDF5Tests.swift
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
//
// HDF5Tests.swift
// HDF5Tests
//
// Created by Alejandro Isaza on 2015-10-01.
// Copyright © 2015 Venture Media Labs. All rights reserved.
//

import XCTest
@testable import HDF5

class HDF5Tests: XCTestCase {

override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()

var filePath: String {
let fileName = NSProcessInfo.processInfo().globallyUniqueString + ".hdf"
return NSTemporaryDirectory() + "/" + fileName
}

func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.

func testCreateDataset() {
guard let file = File.create(filePath, mode: .Truncate) else {
XCTFail("Failed to create file")
return
}

let dims: [UInt64] = [100, 100]
let dataspace = Dataspace(dims: dims)
XCTAssertEqual(dataspace.size, 100*100)
XCTAssertEqual(dataspace.dims, dims)

let datatype = Datatype.copy(.Double)
datatype.order = .LittleEndian
let dataset = Dataset(file: file, name: "MyData", datatype: datatype, dataspace: dataspace)
XCTAssertNil(dataset.offset)
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock {
// Put the code you want to measure the time of here.

func testWriteRead() {
guard let file = File.create(filePath, mode: .Truncate) else {
XCTFail("Failed to create file")
return
}

let dims: [UInt64] = [10, 10]
let dataspace = Dataspace(dims: dims)

let datatype = Datatype.copy(.Double)
datatype.order = .LittleEndian

let writtenData = (0..<10*10).map{ _ in return Double(arc4random()) / Double(UINT32_MAX) }
let dataset = Dataset(file: file, name: "MyData", datatype: datatype, dataspace: dataspace)
XCTAssert(dataset.write(writtenData))

var readData = [Double](count: 10*10, repeatedValue: 0.0)
XCTAssert(dataset.read(&readData))

XCTAssertEqual(writtenData, readData)
}

}

0 comments on commit 5dcf63a

Please sign in to comment.