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