1 /* 2 * Copyright (c) 2004-2015 Derelict Developers 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the names 'Derelict', 'DerelictSDL', nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 module derelict.cocoa.foundation; 33 34 import std.string; 35 import std.utf; 36 37 import dplug.core.nogc; 38 39 import derelict.cocoa.runtime; 40 41 42 // NSZone 43 44 extern (C) nothrow @nogc 45 { 46 alias void* function(NSUInteger bytes) pfNSAllocateMemoryPages; 47 alias void function (void* ptr, NSUInteger bytes) pfNSDeallocateMemoryPages; 48 alias void function(id format, ...) pfNSLog; 49 } 50 51 __gshared 52 { 53 pfNSDeallocateMemoryPages NSDeallocateMemoryPages; 54 pfNSAllocateMemoryPages NSAllocateMemoryPages; 55 pfNSLog NSLog; 56 } 57 58 __gshared 59 { 60 //NSString NSDefaultRunLoopMode; 61 NSString NSRunLoopCommonModes; 62 } 63 64 alias NSTimeInterval = double; 65 66 67 // Mixin'd by all Cocoa objects 68 mixin template NSObjectTemplate(T, string className) 69 { 70 nothrow @nogc: 71 72 // create from an id 73 this (id id_) 74 { 75 this._id = id_; 76 } 77 78 /// Allocates, but do not init 79 static T alloc() 80 { 81 alias fun_t = extern(C) id function (id obj, SEL sel) nothrow @nogc; 82 return T( (cast(fun_t)objc_msgSend)(getClassID(), sel!"alloc") ); 83 } 84 85 static Class getClass() 86 { 87 return cast(Class)( lazyClass!className() ); 88 } 89 90 static id getClassID() 91 { 92 return lazyClass!className(); 93 } 94 } 95 96 struct NSObject 97 { 98 nothrow @nogc: 99 100 // The only field available in all NSObject hierarchy 101 // That makes all these destructs idempotent with an id, 102 // and the size of a pointer. 103 id _id = null; 104 105 // Subtype id 106 bool opCast() 107 { 108 return _id != null; 109 } 110 111 mixin NSObjectTemplate!(NSObject, "NSObject"); 112 113 ~this() 114 { 115 } 116 117 NSObject init_() 118 { 119 alias fun_t = extern(C) id function (id, const(SEL)) nothrow @nogc; 120 id result = (cast(fun_t)objc_msgSend)(_id, sel!"init"); 121 return NSObject(result); 122 } 123 124 void retain() 125 { 126 alias fun_t = extern(C) void function (id, const(SEL)) nothrow @nogc; 127 (cast(fun_t)objc_msgSend)(_id, sel!"retain"); 128 } 129 130 void release() 131 { 132 alias fun_t = extern(C) void function (id, const(SEL)) nothrow @nogc; 133 (cast(fun_t)objc_msgSend)(_id, sel!"release"); 134 } 135 } 136 137 struct NSData 138 { 139 nothrow @nogc: 140 141 NSObject parent; 142 alias parent this; 143 144 mixin NSObjectTemplate!(NSData, "NSData"); 145 146 static NSData data() 147 { 148 alias fun_t = extern(C) id function (id obj, const(SEL) sel) nothrow @nogc; 149 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"data"); 150 return NSData(result); 151 } 152 153 static NSData dataWithBytesNoCopy(void* bytes, NSUInteger length, bool freeWhenDone) 154 { 155 alias fun_t = extern(C) id function(id, const(SEL), void*, NSUInteger, BOOL) nothrow @nogc; 156 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"dataWithBytesNoCopy:length:freeWhenDone:", 157 bytes, length, freeWhenDone ? YES : NO); 158 return NSData(result); 159 } 160 } 161 162 struct NSString 163 { 164 nothrow @nogc: 165 166 NSObject parent; 167 alias parent this; 168 169 mixin NSObjectTemplate!(NSString, "NSString"); 170 171 static NSString stringWith (wstring str) nothrow @nogc 172 { 173 alias fun_t = extern(C) id function(id, SEL, const(wchar)*, NSUInteger) nothrow @nogc; 174 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"stringWithCharacters:length:", 175 CString16(str).storage, cast(NSUInteger)(str.length)); 176 return NSString(result); 177 } 178 179 size_t length () 180 { 181 alias fun_t = extern(C) NSUInteger function(id, SEL) nothrow @nogc; 182 return cast(size_t)( (cast(fun_t)objc_msgSend)(_id, sel!"length") ); 183 } 184 185 char* UTF8String () 186 { 187 alias fun_t = extern(C) char* function(id, SEL) nothrow @nogc; 188 return (cast(fun_t)objc_msgSend)(_id, sel!"UTF8String"); 189 } 190 191 void getCharacters (wchar* buffer, NSRange range) 192 { 193 alias fun_t = extern(C) void function(id, SEL, wchar*, NSRange) nothrow @nogc; 194 (cast(fun_t)objc_msgSend)(_id, sel!"getCharacters:range:", buffer, range); 195 } 196 197 NSString stringWithCharacters (wchar* chars, size_t length) 198 { 199 alias fun_t = extern(C) id function(id, SEL, wchar*, NSUInteger) nothrow @nogc; 200 id result = (cast(fun_t)objc_msgSend)(_id, sel!"stringWithCharacters:length:", chars, cast(NSUInteger)length); 201 return NSString(result); 202 } 203 204 NSRange rangeOfString (NSString aString) 205 { 206 alias fun_t = extern(C) NSRange function(id, SEL, id) nothrow @nogc; 207 return (cast(fun_t)objc_msgSend)(_id, sel!"rangeOfString", aString._id); 208 } 209 210 NSString stringByAppendingString (NSString aString) 211 { 212 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 213 id result = (cast(fun_t)objc_msgSend)(_id, sel!"stringByAppendingString:", aString._id); 214 return NSString(result); 215 } 216 } 217 218 struct NSURL 219 { 220 nothrow @nogc: 221 NSObject parent; 222 alias parent this; 223 224 mixin NSObjectTemplate!(NSURL, "NSURL"); 225 226 static NSURL URLWithString(NSString str) 227 { 228 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 229 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"URLWithString:", str._id); 230 return NSURL(result); 231 } 232 233 } 234 235 struct NSEnumerator 236 { 237 nothrow @nogc: 238 NSObject parent; 239 alias parent this; 240 241 mixin NSObjectTemplate!(NSEnumerator, "NSEnumerator"); 242 243 id nextObject () 244 { 245 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 246 return (cast(fun_t)objc_msgSend)(_id, sel!"nextObject"); 247 } 248 } 249 250 struct NSArray 251 { 252 nothrow @nogc: 253 254 NSObject parent; 255 alias parent this; 256 257 mixin NSObjectTemplate!(NSArray, "NSArray"); 258 259 NSEnumerator objectEnumerator () 260 { 261 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 262 id result = (cast(fun_t)objc_msgSend)(_id, sel!"objectEnumerator"); 263 return NSEnumerator(result); 264 } 265 } 266 267 268 struct NSProcessInfo 269 { 270 nothrow @nogc: 271 272 NSObject parent; 273 alias parent this; 274 275 mixin NSObjectTemplate!(NSProcessInfo, "NSProcessInfo"); 276 277 static NSProcessInfo processInfo () 278 { 279 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 280 id result = (cast(fun_t)objc_msgSend)(lazyClass!"NSProcessInfo", sel!"processInfo"); 281 return NSProcessInfo(result); 282 } 283 284 NSString processName () 285 { 286 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 287 id result = (cast(fun_t)objc_msgSend)(_id, sel!"processName"); 288 return NSString(result); 289 } 290 } 291 292 struct NSNotification 293 { 294 nothrow @nogc: 295 NSObject parent; 296 alias parent this; 297 298 mixin NSObjectTemplate!(NSNotification, "NSNotification"); 299 } 300 301 struct NSDictionary 302 { 303 nothrow @nogc: 304 NSObject parent; 305 alias parent this; 306 307 mixin NSObjectTemplate!(NSDictionary, "NSDictionary"); 308 309 id objectForKey(id key) 310 { 311 alias fun_t = extern(C) id function(id, SEL, id) nothrow @nogc; 312 id result = (cast(fun_t)objc_msgSend)(_id, sel!"objectForKey:", key); 313 return result; 314 } 315 } 316 317 struct NSAutoreleasePool 318 { 319 nothrow @nogc: 320 NSObject parent; 321 alias parent this; 322 323 mixin NSObjectTemplate!(NSAutoreleasePool, "NSAutoreleasePool"); 324 } 325 326 enum : int 327 { 328 NSFileErrorMaximum = 1023, 329 NSFileErrorMinimum = 0, 330 NSFileLockingError = 255, 331 NSFileNoSuchFileError = 4, 332 NSFileReadCorruptFileError = 259, 333 NSFileReadInapplicableStringEncodingError = 261, 334 NSFileReadInvalidFileNameError = 258, 335 NSFileReadNoPermissionError = 257, 336 NSFileReadNoSuchFileError = 260, 337 NSFileReadUnknownError = 256, 338 NSFileReadUnsupportedSchemeError = 262, 339 NSFileWriteInapplicableStringEncodingError = 517, 340 NSFileWriteInvalidFileNameError = 514, 341 NSFileWriteNoPermissionError = 513, 342 NSFileWriteOutOfSpaceError = 640, 343 NSFileWriteUnknownError = 512, 344 NSFileWriteUnsupportedSchemeError = 518, 345 NSFormattingError = 2048, 346 NSFormattingErrorMaximum = 2559, 347 NSFormattingErrorMinimum = 2048, 348 NSKeyValueValidationError = 1024, 349 NSUserCancelledError = 3072, 350 NSValidationErrorMaximum = 2047, 351 NSValidationErrorMinimum = 1024, 352 353 NSExecutableArchitectureMismatchError = 3585, 354 NSExecutableErrorMaximum = 3839, 355 NSExecutableErrorMinimum = 3584, 356 NSExecutableLinkError = 3588, 357 NSExecutableLoadError = 3587, 358 NSExecutableNotLoadableError = 3584, 359 NSExecutableRuntimeMismatchError = 3586, 360 NSFileReadTooLargeError = 263, 361 NSFileReadUnknownStringEncodingError = 264, 362 363 GSFoundationPlaceHolderError = 9999 364 } 365 366 struct NSError 367 { 368 nothrow @nogc: 369 NSObject parent; 370 alias parent this; 371 372 mixin NSObjectTemplate!(NSError, "NSError"); 373 374 NSString localizedDescription() 375 { 376 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 377 id res = (cast(fun_t)objc_msgSend)(_id, sel!"localizedDescription"); 378 return NSString(res); 379 } 380 } 381 382 struct NSBundle 383 { 384 nothrow @nogc: 385 NSObject parent; 386 alias parent this; 387 388 mixin NSObjectTemplate!(NSBundle, "NSBundle"); 389 390 void initWithPath(NSString path) 391 { 392 alias fun_t = extern(C) void function(id, SEL, id) nothrow @nogc; 393 (cast(fun_t)objc_msgSend)(_id, sel!"initWithPath:", path._id); 394 } 395 396 bool load() 397 { 398 alias fun_t = extern(C) BOOL function(id, SEL) nothrow @nogc; 399 return (cast(fun_t)objc_msgSend)(_id, sel!"load") != NO; 400 } 401 402 bool unload() 403 { 404 alias fun_t = extern(C) BOOL function(id, SEL) nothrow @nogc; 405 return (cast(fun_t)objc_msgSend)(_id, sel!"unload") != NO; 406 } 407 408 bool loadAndReturnError(NSError error) 409 { 410 alias fun_t = extern(C) BOOL function(id, SEL, id) nothrow @nogc; 411 return (cast(fun_t)objc_msgSend)(_id, sel!"loadAndReturnError:", error._id) != NO; 412 } 413 } 414 415 struct NSTimer 416 { 417 nothrow @nogc: 418 NSObject parent; 419 alias parent this; 420 421 mixin NSObjectTemplate!(NSTimer, "NSTimer"); 422 423 static NSTimer timerWithTimeInterval(double seconds, NSObject target, SEL selector, void* userInfo, bool repeats) 424 { 425 alias fun_t = extern(C) id function(id, SEL, double, id, SEL, id, BOOL) nothrow @nogc; 426 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"timerWithTimeInterval:target:selector:userInfo:repeats:", 427 seconds, target._id, selector, cast(id)userInfo, repeats ? YES : NO); 428 return NSTimer(result); 429 } 430 431 void invalidate() 432 { 433 alias fun_t = extern(C) void function(id, SEL) nothrow @nogc; 434 (cast(fun_t)objc_msgSend)(_id, sel!"invalidate"); 435 } 436 } 437 438 struct NSRunLoop 439 { 440 nothrow @nogc: 441 NSObject parent; 442 alias parent this; 443 444 mixin NSObjectTemplate!(NSRunLoop, "NSRunLoop"); 445 446 static NSRunLoop currentRunLoop() 447 { 448 alias fun_t = extern(C) id function(id, SEL) nothrow @nogc; 449 id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"currentRunLoop"); 450 return NSRunLoop(result); 451 } 452 453 void addTimer(NSTimer aTimer, NSString forMode) 454 { 455 alias fun_t = extern(C) void function(id, SEL, id, id) nothrow @nogc; 456 (cast(fun_t)objc_msgSend)(_id, sel!"addTimer:forMode:", aTimer._id, forMode._id); 457 } 458 } 459 460 struct NSDate 461 { 462 nothrow @nogc: 463 NSObject parent; 464 alias parent this; 465 466 mixin NSObjectTemplate!(NSDate, "NSDate"); 467 468 static NSDate date() 469 { 470 return NSDate(objc_msgSend(getClassID(), sel!"date")); 471 } 472 473 static NSTimeInterval timeIntervalSinceReferenceDate() 474 { 475 alias fun_t = extern(C) NSTimeInterval function(id, SEL) nothrow @nogc; 476 477 version(X86) 478 return (cast(fun_t)objc_msgSend_fpret)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 479 else version(X86_64) 480 return (cast(fun_t)objc_msgSend)(getClassID(), sel!"timeIntervalSinceReferenceDate"); 481 else 482 static assert(false); 483 } 484 } 485 486 487