1 /** 2 Dynamic bindings to the Foundation framework. 3 4 Copyright: Guillaume Piolat 2016. 5 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 6 */ 7 module bindbc.cocoa.foundation; 8 9 import std.string; 10 import std.utf; 11 12 import dplug.core.nogc; 13 14 import bindbc.cocoa.runtime; 15 16 // NSZone 17 18 extern (C) nothrow @nogc 19 { 20 alias void* function(NSUInteger bytes) pfNSAllocateMemoryPages; 21 alias void function (void* ptr, NSUInteger bytes) pfNSDeallocateMemoryPages; 22 alias void function(id format, ...) pfNSLog; 23 24 alias Class function(id aClassName) pfNSClassFromString; 25 alias SEL function(id aString) pfNSSelectorFromString; 26 alias id function(Class aClass) pfNSStringFromClass; 27 alias id function(SEL aSelector) pfNSStringFromSelector; 28 alias id function(Protocol* aProtocol) pfNSStringFromProtocol; 29 alias Protocol* function(id aString) pfNSProtocolFromString; 30 } 31 32 __gshared 33 { 34 pfNSDeallocateMemoryPages NSDeallocateMemoryPages; 35 pfNSAllocateMemoryPages NSAllocateMemoryPages; 36 pfNSLog NSLog; 37 38 pfNSClassFromString NSClassFromString; 39 pfNSSelectorFromString NSSelectorFromString; 40 pfNSStringFromClass NSStringFromClass; 41 pfNSStringFromSelector NSStringFromSelector; 42 pfNSStringFromProtocol NSStringFromProtocol; 43 pfNSProtocolFromString NSProtocolFromString; 44 } 45 46 __gshared 47 { 48 //NSString NSDefaultRunLoopMode; 49 NSString NSRunLoopCommonModes; 50 } 51 52 alias NSTimeInterval = double; 53 54 55 // Mixin'd by all Cocoa objects 56 mixin template NSObjectTemplate(T, string className) 57 { 58 nothrow @nogc: 59 60 // create from an id 61 this (id id_) 62 { 63 this._id = id_; 64 } 65 66 /// Allocates, but do not init 67 static T alloc() 68 { 69 alias fun_t = extern(C) id function (id obj, SEL sel) nothrow @nogc; 70 return T( (cast(fun_t)objc_msgSend)(getClassID(), sel!"alloc") ); 71 } 72 73 static Class getClass() 74 { 75 return cast(Class)( lazyClass!className() ); 76 } 77 78 static id getClassID() 79 { 80 return lazyClass!className(); 81 } 82 } 83 84 struct NSObject 85 { 86 nothrow @nogc: 87 88 // The only field available in all NSObject hierarchy 89 // That makes all these destructs idempotent with an id, 90 // and the size of a pointer. 91 id _id = null; 92 93 // Subtype id 94 bool opCast() 95 { 96 return _id != null; 97 } 98 99 mixin NSObjectTemplate!(NSObject, "NSObject"); 100 101 ~this() 102 { 103 } 104 105 NSObject init_() 106 { 107 alias fun_t = extern(C) id function (id, const(SEL)) nothrow @nogc; 108 id result = (cast(fun_t)objc_msgSend)(_id, sel!"init"); 109 return NSObject(result); 110 } 111 112 void retain() 113 { 114 alias fun_t = extern(C) void function (id, const(SEL)) nothrow @nogc; 115 (cast(fun_t)objc_msgSend)(_id, sel!"retain"); 116 } 117 118 void release() 119 { 120 alias fun_t = extern(C) void function (id, const(SEL)) nothrow @nogc; 121 (cast(fun_t)objc_msgSend)(_id, sel!"release"); 122 } 123 } 124 125 struct NSData 126 { 127 nothrow @nogc: 128 129 NSObject parent; 130 alias parent this; 131 132 mixin NSObjectTemplate!(NSData, "NSData"); 133 134 static NSData data() 135 { 136 alias fun_t = extern(C) id function (id obj, const(SEL) sel) nothrow @nogc; 137 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"data"); 138 return NSData(result); 139 } 140 141 static NSData dataWithBytesNoCopy(void* bytes, NSUInteger length, bool freeWhenDone) 142 { 143 alias fun_t = extern(C) id function(id, const(SEL), void*, NSUInteger, BOOL) nothrow @nogc; 144 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"dataWithBytesNoCopy:length:freeWhenDone:", 145 bytes, length, freeWhenDone ? YES : NO); 146 return NSData(result); 147 } 148 } 149 150 struct NSString 151 { 152 nothrow @nogc: 153 154 NSObject parent; 155 alias parent this; 156 157 mixin NSObjectTemplate!(NSString, "NSString"); 158 159 static NSString stringWith (wstring str) nothrow @nogc 160 { 161 alias fun_t = extern(C) id function(id, SEL, const(wchar)*, NSUInteger) nothrow @nogc; 162 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"stringWithCharacters:length:", 163 CString16(str).storage, cast(NSUInteger)(str.length)); 164 return NSString(result); 165 } 166 167 size_t length () 168 { 169 alias fun_t = extern(C) NSUInteger function(id, SEL) nothrow @nogc; 170 return cast(size_t)( (cast(fun_t)objc_msgSend)(_id, sel!"length") ); 171 } 172 173 char* UTF8String () 174 { 175 alias fun_t = extern(C) char* function(id, SEL) nothrow @nogc; 176 return (cast(fun_t)objc_msgSend)(_id, sel!"UTF8String"); 177 } 178 179 void getCharacters (wchar* buffer, NSRange range) 180 { 181 alias fun_t = extern(C) void function(id, SEL, wchar*, NSRange) nothrow @nogc; 182 (cast(fun_t)objc_msgSend)(_id, sel!"getCharacters:range:", buffer, range); 183 } 184 185 NSString stringWithCharacters (wchar* chars, size_t length) 186 { 187 alias fun_t = extern(C) id function(id, SEL, wchar*, NSUInteger) nothrow @nogc; 188 id result = (cast(fun_t)objc_msgSend)(_id, sel!"stringWithCharacters:length:", chars, cast(NSUInteger)length); 189 return NSString(result); 190 } 191 192 NSRange rangeOfString (NSString aString) 193 { 194 alias fun_t = extern(C) NSRange function(id, SEL, id) nothrow @nogc; 195 return (cast(fun_t)objc_msgSend)(_id, sel!"rangeOfString", aString._id); 196 } 197 198 NSString stringByAppendingString (NSString aString) 199 { 200 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 201 id result = (cast(fun_t)objc_msgSend)(_id, sel!"stringByAppendingString:", aString._id); 202 return NSString(result); 203 } 204 205 /// Returns: The character at a given UTF-16 code unit index. 206 wchar characterAtIndex(int index) 207 { 208 alias fun_t = extern(C) wchar function(id, SEL, NSUInteger) nothrow @nogc; 209 return (cast(fun_t)objc_msgSend)(_id, sel!"characterAtIndex:", cast(NSUInteger)index); 210 } 211 } 212 213 struct NSURL 214 { 215 nothrow @nogc: 216 NSObject parent; 217 alias parent this; 218 219 mixin NSObjectTemplate!(NSURL, "NSURL"); 220 221 static NSURL URLWithString(NSString str) 222 { 223 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 224 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"URLWithString:", str._id); 225 return NSURL(result); 226 } 227 228 } 229 230 struct NSEnumerator 231 { 232 nothrow @nogc: 233 NSObject parent; 234 alias parent this; 235 236 mixin NSObjectTemplate!(NSEnumerator, "NSEnumerator"); 237 238 id nextObject () 239 { 240 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 241 return (cast(fun_t)objc_msgSend)(_id, sel!"nextObject"); 242 } 243 } 244 245 struct NSArray 246 { 247 nothrow @nogc: 248 249 NSObject parent; 250 alias parent this; 251 252 mixin NSObjectTemplate!(NSArray, "NSArray"); 253 254 NSEnumerator objectEnumerator () 255 { 256 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 257 id result = (cast(fun_t)objc_msgSend)(_id, sel!"objectEnumerator"); 258 return NSEnumerator(result); 259 } 260 } 261 262 263 struct NSProcessInfo 264 { 265 nothrow @nogc: 266 267 NSObject parent; 268 alias parent this; 269 270 mixin NSObjectTemplate!(NSProcessInfo, "NSProcessInfo"); 271 272 static NSProcessInfo processInfo () 273 { 274 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 275 id result = (cast(fun_t)objc_msgSend)(lazyClass!"NSProcessInfo", sel!"processInfo"); 276 return NSProcessInfo(result); 277 } 278 279 NSString processName () 280 { 281 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 282 id result = (cast(fun_t)objc_msgSend)(_id, sel!"processName"); 283 return NSString(result); 284 } 285 } 286 287 struct NSNotification 288 { 289 nothrow @nogc: 290 NSObject parent; 291 alias parent this; 292 293 mixin NSObjectTemplate!(NSNotification, "NSNotification"); 294 } 295 296 struct NSDictionary 297 { 298 nothrow @nogc: 299 NSObject parent; 300 alias parent this; 301 302 mixin NSObjectTemplate!(NSDictionary, "NSDictionary"); 303 304 static NSDictionary dictionaryWithObjectsAndKeys(Args...)(id firstObject, Args args) 305 { 306 alias fun_t = extern(C) id function(id, SEL, id, ...) nothrow @nogc; 307 auto result = (cast(fun_t) objc_msgSend)(getClassID(), sel!"dictionaryWithObjectsAndKeys:", firstObject, args); 308 309 return NSDictionary(result); 310 } 311 312 id objectForKey(id key) 313 { 314 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 315 id result = (cast(fun_t)objc_msgSend)(_id, sel!"objectForKey:", key); 316 return result; 317 } 318 } 319 320 struct NSAutoreleasePool 321 { 322 nothrow @nogc: 323 NSObject parent; 324 alias parent this; 325 326 mixin NSObjectTemplate!(NSAutoreleasePool, "NSAutoreleasePool"); 327 } 328 329 enum : int 330 { 331 NSFileErrorMaximum = 1023, 332 NSFileErrorMinimum = 0, 333 NSFileLockingError = 255, 334 NSFileNoSuchFileError = 4, 335 NSFileReadCorruptFileError = 259, 336 NSFileReadInapplicableStringEncodingError = 261, 337 NSFileReadInvalidFileNameError = 258, 338 NSFileReadNoPermissionError = 257, 339 NSFileReadNoSuchFileError = 260, 340 NSFileReadUnknownError = 256, 341 NSFileReadUnsupportedSchemeError = 262, 342 NSFileWriteInapplicableStringEncodingError = 517, 343 NSFileWriteInvalidFileNameError = 514, 344 NSFileWriteNoPermissionError = 513, 345 NSFileWriteOutOfSpaceError = 640, 346 NSFileWriteUnknownError = 512, 347 NSFileWriteUnsupportedSchemeError = 518, 348 NSFormattingError = 2048, 349 NSFormattingErrorMaximum = 2559, 350 NSFormattingErrorMinimum = 2048, 351 NSKeyValueValidationError = 1024, 352 NSUserCancelledError = 3072, 353 NSValidationErrorMaximum = 2047, 354 NSValidationErrorMinimum = 1024, 355 356 NSExecutableArchitectureMismatchError = 3585, 357 NSExecutableErrorMaximum = 3839, 358 NSExecutableErrorMinimum = 3584, 359 NSExecutableLinkError = 3588, 360 NSExecutableLoadError = 3587, 361 NSExecutableNotLoadableError = 3584, 362 NSExecutableRuntimeMismatchError = 3586, 363 NSFileReadTooLargeError = 263, 364 NSFileReadUnknownStringEncodingError = 264, 365 366 GSFoundationPlaceHolderError = 9999 367 } 368 369 struct NSError 370 { 371 nothrow @nogc: 372 NSObject parent; 373 alias parent this; 374 375 mixin NSObjectTemplate!(NSError, "NSError"); 376 377 NSString localizedDescription() 378 { 379 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 380 id res = (cast(fun_t)objc_msgSend)(_id, sel!"localizedDescription"); 381 return NSString(res); 382 } 383 } 384 385 struct NSBundle 386 { 387 nothrow @nogc: 388 NSObject parent; 389 alias parent this; 390 391 mixin NSObjectTemplate!(NSBundle, "NSBundle"); 392 393 void initWithPath(NSString path) 394 { 395 alias fun_t = extern(C) void function(id, SEL, id) nothrow @nogc; 396 (cast(fun_t)objc_msgSend)(_id, sel!"initWithPath:", path._id); 397 } 398 399 bool load() 400 { 401 alias fun_t = extern(C) BOOL function(id, SEL) nothrow @nogc; 402 return (cast(fun_t)objc_msgSend)(_id, sel!"load") != NO; 403 } 404 405 bool unload() 406 { 407 alias fun_t = extern(C) BOOL function(id, SEL) nothrow @nogc; 408 return (cast(fun_t)objc_msgSend)(_id, sel!"unload") != NO; 409 } 410 411 bool loadAndReturnError(NSError error) 412 { 413 alias fun_t = extern(C) BOOL function(id, SEL, id) nothrow @nogc; 414 return (cast(fun_t)objc_msgSend)(_id, sel!"loadAndReturnError:", error._id) != NO; 415 } 416 } 417 418 struct NSTimer 419 { 420 nothrow @nogc: 421 NSObject parent; 422 alias parent this; 423 424 mixin NSObjectTemplate!(NSTimer, "NSTimer"); 425 426 static NSTimer timerWithTimeInterval(double seconds, NSObject target, SEL selector, void* userInfo, bool repeats) 427 { 428 alias fun_t = extern(C) id function(id, SEL, double, id, SEL, id, BOOL) nothrow @nogc; 429 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"timerWithTimeInterval:target:selector:userInfo:repeats:", 430 seconds, target._id, selector, cast(id)userInfo, repeats ? YES : NO); 431 return NSTimer(result); 432 } 433 434 void invalidate() 435 { 436 alias fun_t = extern(C) void function(id, SEL) nothrow @nogc; 437 (cast(fun_t)objc_msgSend)(_id, sel!"invalidate"); 438 } 439 } 440 441 struct NSRunLoop 442 { 443 nothrow @nogc: 444 NSObject parent; 445 alias parent this; 446 447 mixin NSObjectTemplate!(NSRunLoop, "NSRunLoop"); 448 449 static NSRunLoop currentRunLoop() 450 { 451 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 452 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"currentRunLoop"); 453 return NSRunLoop(result); 454 } 455 456 static NSRunLoop mainRunLoop() 457 { 458 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 459 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"mainRunLoop"); 460 return NSRunLoop(result); 461 } 462 463 void runUntilDate(NSDate limitDate) 464 { 465 alias fun_t = extern(C) void function(id, SEL, id) nothrow @nogc; 466 (cast(fun_t)objc_msgSend)(_id, sel!"runUntilDate:", limitDate._id); 467 } 468 469 void addTimer(NSTimer aTimer, NSString forMode) 470 { 471 alias fun_t = extern(C) void function(id, SEL, id, id) nothrow @nogc; 472 (cast(fun_t)objc_msgSend)(_id, sel!"addTimer:forMode:", aTimer._id, forMode._id); 473 } 474 } 475 476 struct NSDate 477 { 478 nothrow @nogc: 479 NSObject parent; 480 alias parent this; 481 482 mixin NSObjectTemplate!(NSDate, "NSDate"); 483 484 static NSDate date() 485 { 486 return NSDate(objc_msgSend(getClassID(), sel!"date")); 487 } 488 489 static NSTimeInterval timeIntervalSinceReferenceDate() 490 { 491 alias fun_t = extern(C) NSTimeInterval function(id, SEL) nothrow @nogc; 492 493 version(X86) 494 return (cast(fun_t)objc_msgSend_fpret)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 495 else version(X86_64) 496 return (cast(fun_t)objc_msgSend)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 497 else 498 return (cast(fun_t)objc_msgSend)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 499 } 500 501 static NSDate dateWithTimeIntervalSinceNow(double secs) 502 { 503 alias fun_t = extern(C) id function(id, SEL, double) nothrow @nogc; 504 id res = (cast(fun_t)objc_msgSend)(getClassID(), sel!"dateWithTimeIntervalSinceNow:", secs); 505 506 return NSDate(res); 507 } 508 509 NSString description() 510 { 511 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 512 id result = (cast(fun_t)objc_msgSend)(_id, sel!"description"); 513 514 return NSString(result); 515 } 516 517 NSString descriptionWithLocale() 518 { 519 alias fun_t = extern(C) id function(id, SEL, void*) nothrow @nogc; 520 id result = (cast(fun_t)objc_msgSend)(_id, sel!"descriptionWithLocale:", null); 521 return NSString(result); 522 } 523 } 524 525 struct NSNumber 526 { 527 nothrow @nogc: 528 NSObject parent; 529 alias parent this; 530 531 mixin NSObjectTemplate!(NSNumber, "NSNumber"); 532 533 static NSNumber numberWithUnsignedInt(uint value) 534 { 535 alias fun_t = extern(C) id function(id, SEL, uint) nothrow @nogc; 536 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"numberWithUnsignedInt:", value); 537 538 return NSNumber(result); 539 } 540 }