mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 00:11:26 +00:00
Merge branch 'master' of github.com:gnustep/libs-base into add_nsorderedset_classcluster
This commit is contained in:
commit
b3e457cd1f
16 changed files with 786 additions and 110 deletions
56
ChangeLog
56
ChangeLog
|
@ -1,3 +1,59 @@
|
|||
2019-05-23 Frederik Seiffert <frederik@algoriddim.com>
|
||||
|
||||
* configure:
|
||||
* configure.ac:
|
||||
Link against libandroid on Android.
|
||||
* Headers/Foundation/NSBundle.h:
|
||||
* Source/NSBundle.m:
|
||||
Added methods for passing Android asset manager from Java to GNUstep
|
||||
and for getting AAsset/AAssetDir for given path in main bundle.
|
||||
Skip app bundle suffix check on Android. Extended bundle resource
|
||||
paths backbone to check for known paths directly on Android as we
|
||||
can't enumerate directories.
|
||||
Extended -localizations method to check for known localizations
|
||||
directly (requires setting userLanguages in NSUserDefaults).
|
||||
Extracted path cache cleaning into separate method.
|
||||
* Source/GSFileHandle.h:
|
||||
* Source/GSFileHandle.m:
|
||||
Added file handle support for reading Android assets from main bundle.
|
||||
* Source/NSData.m:
|
||||
Added support for reading Android assets from main bundle in
|
||||
readContentsOfFile(). This is also used by all other
|
||||
-initWithContentsOfFile: and related methods from other classes.
|
||||
* Source/NSFileManager.m:
|
||||
Added support for Android assets from main bundle in
|
||||
fileExistsAtPath:isDirectory:, isReadableFileAtPath:,
|
||||
NSDirectoryEnumerator, and copying from assets. Extended
|
||||
GSAttrDictionary with basic support for Android assets.
|
||||
* Source/NSProcessInfo.m:
|
||||
Added +initialize method to auto-initialize NSProcessInfo on Android
|
||||
using fake executable path "/data/data/<app identifier>/exe" (Android
|
||||
apps don't have a real executable path).
|
||||
|
||||
2019-05-20 Frederik Seiffert <frederik@algoriddim.com>
|
||||
|
||||
* Source/NSLog.m: Have all logs go to syslog on android.
|
||||
* Source/NSThread.m: Spinlock implementation using builtins as
|
||||
implemented by David in libobjc2
|
||||
* Source/NSRunLoop.m
|
||||
* Headers/GNUstepBase/config.h.in:
|
||||
* configure.ac:
|
||||
This updates the libdispatch runloop integration to be compatible with
|
||||
the Swift corelibs libdispatch release at
|
||||
(https://github.com/apple/swift-corelibs-libdispatch).
|
||||
|
||||
In that release, the main queue handle and drain functions have been
|
||||
renamed with a "_4CF" (for CoreFoundation) suffix and have moved to
|
||||
private.h, so we now check for the existance of this header and
|
||||
function names.
|
||||
|
||||
Note that libdispatch must be compiled with
|
||||
INSTALL_PRIVATE_HEADERS=YES.
|
||||
|
||||
Also fixes the checks for the HAVE_LIBDISPATCH_RUNLOOP define (was
|
||||
inverted) and ensures that both the handle and drain functions are
|
||||
available.
|
||||
|
||||
2019-02-16 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSString.m: Removed public functions which could conflict
|
||||
|
|
|
@ -36,6 +36,10 @@ extern "C" {
|
|||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/asset_manager_jni.h>
|
||||
#endif
|
||||
|
||||
@class NSString;
|
||||
@class NSArray;
|
||||
@class NSDictionary;
|
||||
|
@ -540,6 +544,47 @@ GS_EXPORT NSString* const NSLoadedClasses;
|
|||
ofType: (NSString*)extension
|
||||
inDirectory: (NSString*)bundlePath;
|
||||
|
||||
/** Cleans up the path cache for the bundle. */
|
||||
- (void) cleanPathCache;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
/**
|
||||
* Sets the Java Android asset manager.
|
||||
* The developer can call this method to enable asset loading via NSBundle.
|
||||
*/
|
||||
+ (void) setJavaAssetManager: (jobject)jassetManager withJNIEnv: (JNIEnv *)env;
|
||||
|
||||
/**
|
||||
* Returns the native Android asset manager.
|
||||
*/
|
||||
+ (AAssetManager *) assetManager;
|
||||
|
||||
/**
|
||||
* Returns the Android asset for the given path if path is in main bundle
|
||||
* resources and asset exists.
|
||||
* Uses `AASSET_MODE_UNKNOWN` to open the asset if it exists.
|
||||
* The returned object must be released using AAsset_close().
|
||||
*/
|
||||
+ (AAsset *) assetForPath: (NSString *)path;
|
||||
|
||||
/**
|
||||
* Returns the Android asset for the given path if path is in main bundle
|
||||
* resources and asset exists.
|
||||
* Uses the given mode to open the AAsset if it exists.
|
||||
* The returned object must be released using AAsset_close().
|
||||
*/
|
||||
+ (AAsset *) assetForPath: (NSString *)path withMode: (int)mode;
|
||||
|
||||
/**
|
||||
* Returns the Android asset dir for the given path if path is in main bundle
|
||||
* resources and the asset directory exists.
|
||||
* The returned object must be released using AAssetDir_close().
|
||||
*/
|
||||
+ (AAssetDir *) assetDirForPath: (NSString *)path;
|
||||
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* GNUSTEP */
|
||||
|
@ -603,7 +648,7 @@ GS_EXPORT NSString* const NSLoadedClasses;
|
|||
* </p>
|
||||
*/
|
||||
#define NSLocalizedString(key, comment) \
|
||||
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
|
||||
[[NSBundle mainBundle] localizedStringForKey: (key) value: @"" table: nil]
|
||||
|
||||
/**
|
||||
* This function (macro) does the same as
|
||||
|
@ -621,7 +666,7 @@ GS_EXPORT NSString* const NSLoadedClasses;
|
|||
* different table.
|
||||
*/
|
||||
#define NSLocalizedStringFromTable(key, tbl, comment) \
|
||||
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]
|
||||
[[NSBundle mainBundle] localizedStringForKey: (key) value: @"" table: (tbl)]
|
||||
|
||||
/**
|
||||
* This function is the full-blown localization function (it
|
||||
|
@ -637,7 +682,7 @@ GS_EXPORT NSString* const NSLoadedClasses;
|
|||
* use when translating the string.
|
||||
*/
|
||||
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
|
||||
[bundle localizedStringForKey:(key) value:@"" table:(tbl)]
|
||||
[bundle localizedStringForKey: (key) value: @"" table: (tbl)]
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -216,6 +216,9 @@
|
|||
/* Define to 1 if you have the `dispatch_main_queue_drain_np' function. */
|
||||
#undef HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP
|
||||
|
||||
/* Define to 1 if you have the <dispatch/private.h> header file. */
|
||||
#undef HAVE_DISPATCH_PRIVATE_H
|
||||
|
||||
/* Define to 1 if you have the `dladdr' function. */
|
||||
#undef HAVE_DLADDR
|
||||
|
||||
|
@ -767,6 +770,14 @@
|
|||
/* Define to 1 if you have the `_Block_copy' function. */
|
||||
#undef HAVE__BLOCK_COPY
|
||||
|
||||
/* Define to 1 if you have the `_dispatch_get_main_queue_handle_4CF' function.
|
||||
*/
|
||||
#undef HAVE__DISPATCH_GET_MAIN_QUEUE_HANDLE_4CF
|
||||
|
||||
/* Define to 1 if you have the `_dispatch_main_queue_callback_4CF' function.
|
||||
*/
|
||||
#undef HAVE__DISPATCH_MAIN_QUEUE_CALLBACK_4CF
|
||||
|
||||
/* Define to 1 if you have the `__builtin_extract_return_address' function. */
|
||||
#undef HAVE___BUILTIN_EXTRACT_RETURN_ADDRESS
|
||||
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/asset_manager_jni.h>
|
||||
#endif
|
||||
|
||||
struct sockaddr_in;
|
||||
|
||||
/**
|
||||
|
@ -69,6 +73,9 @@ struct sockaddr_in;
|
|||
#if defined(_WIN32)
|
||||
WSAEVENT event;
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
AAsset *asset;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -285,6 +285,13 @@ static GSTcpTune *tune = nil;
|
|||
|
||||
do
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
result = AAsset_read(asset, buf, len);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if USE_ZLIB
|
||||
if (gzDescriptor != 0)
|
||||
{
|
||||
|
@ -379,6 +386,14 @@ static GSTcpTune *tune = nil;
|
|||
[self ignoreReadDescriptor];
|
||||
[self ignoreWriteDescriptor];
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
asset = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (closeOnDealloc == YES && descriptor != -1)
|
||||
{
|
||||
[self closeFile];
|
||||
|
@ -1075,6 +1090,15 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
|
||||
if (d < 0)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
asset = [NSBundle assetForPath:path withMode:AASSET_MODE_RANDOM];
|
||||
if (asset)
|
||||
{
|
||||
readOK = YES;
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
DESTROY(self);
|
||||
return nil;
|
||||
}
|
||||
|
@ -1645,6 +1669,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
{
|
||||
off_t result = -1;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
result = AAsset_seek(asset, 0, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (isStandardFile && descriptor >= 0)
|
||||
{
|
||||
#if USE_ZLIB
|
||||
|
@ -1669,6 +1700,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
{
|
||||
off_t result = -1;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
result = AAsset_seek(asset, 0, SEEK_END);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (isStandardFile && descriptor >= 0)
|
||||
{
|
||||
#if USE_ZLIB
|
||||
|
@ -1693,6 +1731,13 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
{
|
||||
off_t result = -1;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
result = AAsset_seek(asset, (off_t)pos, SEEK_SET);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (isStandardFile && descriptor >= 0)
|
||||
{
|
||||
#if USE_ZLIB
|
||||
|
@ -1726,6 +1771,15 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
|||
[self ignoreWriteDescriptor];
|
||||
|
||||
[self setNonBlocking: NO];
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
asset = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if USE_ZLIB
|
||||
if (gzDescriptor != 0)
|
||||
{
|
||||
|
|
|
@ -627,15 +627,11 @@ descriptorOrComparator: (id)descriptorOrComparator
|
|||
while (stackSize > 1)
|
||||
{
|
||||
NSInteger n = stackSize -2;
|
||||
if ( (n >= 1
|
||||
&& runStack[n-1].length <= (runStack[n].length
|
||||
+ runStack[n+1].length)
|
||||
)
|
||||
|| (n >= 2
|
||||
&& runStack[n-2].length <= (runStack[n].length
|
||||
+ runStack[n-1].length)
|
||||
)
|
||||
)
|
||||
|
||||
if ((n >= 1 && runStack[n-1].length
|
||||
<= (runStack[n].length + runStack[n+1].length))
|
||||
|| (n >= 2 && runStack[n-2].length
|
||||
<= (runStack[n].length + runStack[n-1].length)))
|
||||
{
|
||||
if (runStack[n-1].length < runStack[n+1].length)
|
||||
{
|
||||
|
|
|
@ -241,6 +241,11 @@ static NSString *library_combo =
|
|||
nil;
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static jobject _jassetManager = NULL;
|
||||
static AAssetManager *_assetManager = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Try to find the absolute path of an executable.
|
||||
|
@ -264,17 +269,17 @@ AbsolutePathOfExecutable(NSString *path, BOOL atLaunch)
|
|||
NSString *result = nil;
|
||||
|
||||
env = [[NSProcessInfo processInfo] environment];
|
||||
pathlist = [env objectForKey:@"PATH"];
|
||||
pathlist = [env objectForKey: @"PATH"];
|
||||
|
||||
/* Windows 2000 and perhaps others have "Path" not "PATH" */
|
||||
if (pathlist == nil)
|
||||
{
|
||||
pathlist = [env objectForKey:@"Path"];
|
||||
pathlist = [env objectForKey: @"Path"];
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
patharr = [pathlist componentsSeparatedByString:@";"];
|
||||
patharr = [pathlist componentsSeparatedByString: @";"];
|
||||
#else
|
||||
patharr = [pathlist componentsSeparatedByString:@":"];
|
||||
patharr = [pathlist componentsSeparatedByString: @":"];
|
||||
#endif
|
||||
/* Add . if not already in path */
|
||||
if ([patharr indexOfObject: @"."] == NSNotFound)
|
||||
|
@ -285,7 +290,7 @@ AbsolutePathOfExecutable(NSString *path, BOOL atLaunch)
|
|||
patharr = [patharr objectEnumerator];
|
||||
while (nil != (prefix = [patharr nextObject]))
|
||||
{
|
||||
if ([prefix isEqual:@"."])
|
||||
if ([prefix isEqual: @"."])
|
||||
{
|
||||
if (atLaunch == YES)
|
||||
{
|
||||
|
@ -543,13 +548,14 @@ _find_framework(NSString *name)
|
|||
{
|
||||
NSArray *paths;
|
||||
NSFileManager *file_mgr = manager();
|
||||
NSString *file_name = [name stringByAppendingPathExtension:@"framework"];
|
||||
NSString *file_name;
|
||||
NSString *file_path;
|
||||
NSString *path;
|
||||
NSEnumerator *enumerator;
|
||||
|
||||
NSCParameterAssert(name != nil);
|
||||
|
||||
file_name = [name stringByAppendingPathExtension: @"framework"];
|
||||
paths = NSSearchPathForDirectoriesInDomains(GSFrameworksDirectory,
|
||||
NSAllDomainsMask,YES);
|
||||
|
||||
|
@ -922,9 +928,9 @@ _find_main_bundle_for_tool(NSString *toolName)
|
|||
for (j = 0; j < [l count]; j++)
|
||||
{
|
||||
if ([[l objectAtIndex: j] pointerValue]
|
||||
== [[b objectAtIndex:i] pointerValue])
|
||||
== [[b objectAtIndex: i] pointerValue])
|
||||
{
|
||||
[l removeObjectAtIndex:j];
|
||||
[l removeObjectAtIndex: j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1382,6 +1388,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
isNonInstalledTool = YES;
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__ /* don't check suffix on Android's fake executable path */
|
||||
if (isApplication == YES)
|
||||
{
|
||||
s = [path lastPathComponent];
|
||||
|
@ -1422,6 +1429,7 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif /* !__ANDROID__ */
|
||||
|
||||
if (isApplication == NO)
|
||||
{
|
||||
|
@ -1805,9 +1813,6 @@ IF_NO_GC(
|
|||
{
|
||||
NSString *identifier = [self bundleIdentifier];
|
||||
NSUInteger count;
|
||||
NSUInteger plen = [_path length];
|
||||
NSEnumerator *enumerator;
|
||||
NSString *path;
|
||||
|
||||
[load_lock lock];
|
||||
if (_bundles != nil)
|
||||
|
@ -1835,38 +1840,7 @@ IF_NO_GC(
|
|||
|
||||
/* Clean up path cache for this bundle.
|
||||
*/
|
||||
[pathCacheLock lock];
|
||||
enumerator = [pathCache keyEnumerator];
|
||||
while (nil != (path = [enumerator nextObject]))
|
||||
{
|
||||
if (YES == [path hasPrefix: _path])
|
||||
{
|
||||
if ([path length] == plen)
|
||||
{
|
||||
/* Remove the bundle directory path from the cache.
|
||||
*/
|
||||
[pathCache removeObjectForKey: path];
|
||||
}
|
||||
else
|
||||
{
|
||||
unichar c = [path characterAtIndex: plen];
|
||||
|
||||
/* if the directory is inside the bundle, remove from cache.
|
||||
*/
|
||||
if ('/' == c)
|
||||
{
|
||||
[pathCache removeObjectForKey: path];
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
else if ('\\' == c)
|
||||
{
|
||||
[pathCache removeObjectForKey: path];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
[pathCacheLock unlock];
|
||||
[self cleanPathCache];
|
||||
RELEASE(_path);
|
||||
}
|
||||
TEST_RELEASE(_frameworkVersion);
|
||||
|
@ -2144,6 +2118,59 @@ IF_NO_GC(
|
|||
addBundlePath(array, contents, primary, subPath, language);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* Android: check subdir and localization directly, as AAssetDir and thereby
|
||||
* NSDirectoryEnumerator doesn't list directories
|
||||
*/
|
||||
NSString *originalPrimary = primary;
|
||||
if (subPath)
|
||||
{
|
||||
primary = [originalPrimary stringByAppendingPathComponent: subPath];
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
|
||||
if (localization)
|
||||
{
|
||||
primary = [primary stringByAppendingPathComponent:
|
||||
[localization stringByAppendingPathExtension: @"lproj"]];
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *subPathPrimary = primary;
|
||||
|
||||
enumerate = [languages objectEnumerator];
|
||||
while ((language = [enumerate nextObject]))
|
||||
{
|
||||
primary = [subPathPrimary stringByAppendingPathComponent:
|
||||
[language stringByAppendingPathExtension: @"lproj"]];
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (localization)
|
||||
{
|
||||
primary = [originalPrimary stringByAppendingPathComponent:
|
||||
[localization stringByAppendingPathExtension: @"lproj"]];
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
}
|
||||
else
|
||||
{
|
||||
enumerate = [languages objectEnumerator];
|
||||
while ((language = [enumerate nextObject]))
|
||||
{
|
||||
primary = [originalPrimary stringByAppendingPathComponent:
|
||||
[language stringByAppendingPathExtension: @"lproj"]];
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, nil, nil);
|
||||
}
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
primary = rootPath;
|
||||
contents = bundle_directory_readable(primary);
|
||||
addBundlePath(array, contents, primary, subPath, nil);
|
||||
|
@ -2254,7 +2281,7 @@ IF_NO_GC(
|
|||
|
||||
#if !defined(_WIN32)
|
||||
if (_frameworkVersion)
|
||||
rootPath = [NSString stringWithFormat:@"%@/Versions/%@", [self bundlePath],
|
||||
rootPath = [NSString stringWithFormat: @"%@/Versions/%@", [self bundlePath],
|
||||
_frameworkVersion];
|
||||
else
|
||||
#endif
|
||||
|
@ -2525,6 +2552,27 @@ IF_NO_GC(
|
|||
locale = [[locale lastPathComponent] stringByDeletingPathExtension];
|
||||
[array addObject: locale];
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Android: Check known languages for localizations directly, as AAssetDir
|
||||
// and thereby NSDirectoryEnumerator doesn't list directories and the above
|
||||
// call to list lproj resources will therefore come up empty.
|
||||
NSArray *languages = [[NSUserDefaults standardUserDefaults]
|
||||
stringArrayForKey: @"NSLanguages"];
|
||||
|
||||
for (locale in languages)
|
||||
{
|
||||
NSString *path = [self pathForResource: @"Localizable"
|
||||
ofType: @"strings"
|
||||
inDirectory: nil
|
||||
forLocalization: locale];
|
||||
if (path)
|
||||
{
|
||||
[array addObject: locale];
|
||||
}
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
return GS_IMMUTABLE(array);
|
||||
}
|
||||
|
||||
|
@ -2732,7 +2780,7 @@ IF_NO_GC(
|
|||
withString: @"_1"];
|
||||
|
||||
#if !defined(_WIN32)
|
||||
path = [_path stringByAppendingPathComponent:@"Versions/Current"];
|
||||
path = [_path stringByAppendingPathComponent: @"Versions/Current"];
|
||||
#else
|
||||
path = _path;
|
||||
#endif
|
||||
|
@ -2766,7 +2814,7 @@ IF_NO_GC(
|
|||
{
|
||||
#if !defined(_WIN32)
|
||||
return [_path stringByAppendingPathComponent:
|
||||
[NSString stringWithFormat:@"Versions/%@/%@",
|
||||
[NSString stringWithFormat: @"Versions/%@/%@",
|
||||
version, executableName]];
|
||||
#else
|
||||
return [_path stringByAppendingPathComponent: executableName];
|
||||
|
@ -2795,7 +2843,7 @@ IF_NO_GC(
|
|||
{
|
||||
#if !defined(_WIN32)
|
||||
return [_path stringByAppendingPathComponent:
|
||||
[NSString stringWithFormat:@"Versions/%@/Resources",
|
||||
[NSString stringWithFormat: @"Versions/%@/Resources",
|
||||
version]];
|
||||
#else
|
||||
/* No Versions (that require symlinks) on mswindows */
|
||||
|
@ -2852,7 +2900,7 @@ IF_NO_GC(
|
|||
{
|
||||
#if !defined(_WIN32)
|
||||
return [_path stringByAppendingPathComponent:
|
||||
[NSString stringWithFormat:@"Versions/%@/PlugIns",
|
||||
[NSString stringWithFormat: @"Versions/%@/PlugIns",
|
||||
version]];
|
||||
#else
|
||||
return [_path stringByAppendingPathComponent: @"PlugIns"];
|
||||
|
@ -2880,8 +2928,8 @@ IF_NO_GC(
|
|||
{
|
||||
#if !defined(_WIN32)
|
||||
return [_path stringByAppendingPathComponent:
|
||||
[NSString stringWithFormat:@"Versions/%@/PrivateFrameworks",
|
||||
version]];
|
||||
[NSString stringWithFormat: @"Versions/%@/PrivateFrameworks",
|
||||
version]];
|
||||
#else
|
||||
return [_path stringByAppendingPathComponent: @"PrivateFrameworks"];
|
||||
#endif
|
||||
|
@ -3202,5 +3250,142 @@ IF_NO_GC(
|
|||
return path;
|
||||
}
|
||||
|
||||
- (void)cleanPathCache
|
||||
{
|
||||
NSUInteger plen = [_path length];
|
||||
NSEnumerator *enumerator;
|
||||
NSString *path;
|
||||
|
||||
[pathCacheLock lock];
|
||||
enumerator = [pathCache keyEnumerator];
|
||||
while (nil != (path = [enumerator nextObject]))
|
||||
{
|
||||
if (YES == [path hasPrefix: _path])
|
||||
{
|
||||
if ([path length] == plen)
|
||||
{
|
||||
/* Remove the bundle directory path from the cache.
|
||||
*/
|
||||
[pathCache removeObjectForKey: path];
|
||||
}
|
||||
else
|
||||
{
|
||||
unichar c = [path characterAtIndex: plen];
|
||||
|
||||
/* if the directory is inside the bundle, remove from cache.
|
||||
*/
|
||||
if ('/' == c)
|
||||
{
|
||||
[pathCache removeObjectForKey: path];
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
else if ('\\' == c)
|
||||
{
|
||||
[pathCache removeObjectForKey: path];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
[pathCacheLock unlock];
|
||||
|
||||
/* also destroy cached variables depending on bundle paths */
|
||||
DESTROY(_infoDict);
|
||||
DESTROY(_localizations);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
+ (AAssetManager *)assetManager
|
||||
{
|
||||
return _assetManager;
|
||||
}
|
||||
|
||||
+ (void) setJavaAssetManager: (jobject)jassetManager withJNIEnv: (JNIEnv *)env
|
||||
{
|
||||
/* create global reference to Java asset manager to prevent garbage
|
||||
* collection
|
||||
*/
|
||||
_jassetManager = (*env)->NewGlobalRef(env, jassetManager);
|
||||
|
||||
// get native asset manager (may be shared across multiple threads)
|
||||
_assetManager = AAssetManager_fromJava(env, _jassetManager);
|
||||
|
||||
// clean main bundle path cache in case it was accessed before
|
||||
[_mainBundle cleanPathCache];
|
||||
}
|
||||
|
||||
+ (AAsset *) assetForPath: (NSString *)path
|
||||
{
|
||||
return [self assetForPath: path withMode: AASSET_MODE_UNKNOWN];
|
||||
}
|
||||
|
||||
+ (AAsset *) assetForPath: (NSString *)path withMode: (int)mode
|
||||
{
|
||||
AAsset *asset = NULL;
|
||||
|
||||
if (_assetManager && _mainBundle)
|
||||
{
|
||||
NSString *resourcePath = [_mainBundle resourcePath];
|
||||
|
||||
if ([path hasPrefix: resourcePath]
|
||||
&& [path length] > [resourcePath length])
|
||||
{
|
||||
NSString *assetPath;
|
||||
|
||||
assetPath = [path substringFromIndex: [resourcePath length] + 1];
|
||||
asset = AAssetManager_open(_assetManager,
|
||||
[assetPath fileSystemRepresentation], mode);
|
||||
}
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
+ (AAssetDir *) assetDirForPath: (NSString *)path
|
||||
{
|
||||
AAssetDir *assetDir = NULL;
|
||||
|
||||
if (_assetManager && _mainBundle)
|
||||
{
|
||||
NSString *resourcePath = [_mainBundle resourcePath];
|
||||
|
||||
if ([path hasPrefix: resourcePath])
|
||||
{
|
||||
NSString *assetPath = @"";
|
||||
|
||||
if ([path length] > [resourcePath length])
|
||||
{
|
||||
assetPath = [path substringFromIndex: [resourcePath length] + 1];
|
||||
}
|
||||
|
||||
assetDir = AAssetManager_openDir(_assetManager,
|
||||
[assetPath fileSystemRepresentation]);
|
||||
|
||||
if (assetDir)
|
||||
{
|
||||
/* AAssetManager_openDir() always returns an object,
|
||||
* so we check if the directory exists by ensuring
|
||||
* it contains a file
|
||||
*/
|
||||
BOOL exists = AAssetDir_getNextFileName(assetDir) != NULL;
|
||||
if (exists)
|
||||
{
|
||||
AAssetDir_rewind(assetDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
AAssetDir_close(assetDir);
|
||||
assetDir = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assetDir;
|
||||
}
|
||||
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -242,6 +242,40 @@ readContentsOfFile(NSString *path, void **buf, off_t *len, NSZone *zone)
|
|||
void *tmp = 0;
|
||||
int c;
|
||||
off_t fileLength;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Android: try using asset manager if path is in main bundle resources
|
||||
AAsset *asset = [NSBundle assetForPath: path withMode: AASSET_MODE_BUFFER];
|
||||
if (asset)
|
||||
{
|
||||
fileLength = AAsset_getLength(asset);
|
||||
|
||||
tmp = NSZoneMalloc(zone, fileLength);
|
||||
if (tmp == 0)
|
||||
{
|
||||
NSLog(@"Malloc failed for file (%@) of length %jd - %@", path,
|
||||
(intmax_t)fileLength, [NSError _last]);
|
||||
AAsset_close(asset);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
int result = AAsset_read(asset, tmp, fileLength);
|
||||
AAsset_close(asset);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
NSWarnFLog(@"read of file (%@) contents failed - %@", path,
|
||||
[NSError errorWithDomain: NSPOSIXErrorDomain
|
||||
code: result
|
||||
userInfo: nil]);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
*buf = tmp;
|
||||
*len = fileLength;
|
||||
return YES;
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
#if defined(_WIN32)
|
||||
thePath = (const unichar*)[path fileSystemRepresentation];
|
||||
|
|
|
@ -241,7 +241,7 @@
|
|||
struct _STATB statbuf;
|
||||
_CHAR _path[0];
|
||||
}
|
||||
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
|
||||
+ (NSDictionary*) attributesAt: (NSString *)path
|
||||
traverseLink: (BOOL)traverse;
|
||||
@end
|
||||
|
||||
|
@ -738,7 +738,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
nxtImp = [direnum methodForSelector: @selector(nextObject)];
|
||||
|
||||
urlArray = [NSMutableArray arrayWithCapacity:128];
|
||||
urlArray = [NSMutableArray arrayWithCapacity: 128];
|
||||
while ((tempPath = (*nxtImp)(direnum, @selector(nextObject))) != nil)
|
||||
{
|
||||
NSURL *tempURL;
|
||||
|
@ -749,7 +749,7 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
/* we purge files beginning with . */
|
||||
if (!((mask & NSDirectoryEnumerationSkipsHiddenFiles)
|
||||
&& [lastComponent hasPrefix:@"."]))
|
||||
&& [lastComponent hasPrefix: @"."]))
|
||||
{
|
||||
[urlArray addObject: tempURL];
|
||||
}
|
||||
|
@ -1652,6 +1652,29 @@ static NSStringEncoding defaultEncoding;
|
|||
|
||||
if (_STAT(lpath, &statbuf) != 0)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
/* Android: try using asset manager if path is in
|
||||
* main bundle resources
|
||||
*/
|
||||
AAsset *asset = [NSBundle assetForPath: path];
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
return YES;
|
||||
}
|
||||
|
||||
AAssetDir *assetDir = [NSBundle assetDirForPath: path];
|
||||
if (assetDir)
|
||||
{
|
||||
AAssetDir_close(assetDir);
|
||||
if (isDirectory)
|
||||
{
|
||||
*isDirectory = YES;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
@ -1700,6 +1723,17 @@ static NSStringEncoding defaultEncoding;
|
|||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// Android: try using asset manager if path is in main bundle resources
|
||||
AAsset *asset = [NSBundle assetForPath: path];
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
return YES;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NO;
|
||||
}
|
||||
#endif
|
||||
|
@ -1929,8 +1963,7 @@ static NSStringEncoding defaultEncoding;
|
|||
{
|
||||
NSDictionary *d;
|
||||
|
||||
d = [GSAttrDictionaryClass attributesAt:
|
||||
[self fileSystemRepresentationWithPath: path] traverseLink: flag];
|
||||
d = [GSAttrDictionaryClass attributesAt: path traverseLink: flag];
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -2012,8 +2045,7 @@ static NSStringEncoding defaultEncoding;
|
|||
NSDictionary *d;
|
||||
|
||||
DESTROY(_lastError);
|
||||
d = [GSAttrDictionaryClass attributesAt:
|
||||
[self fileSystemRepresentationWithPath: path] traverseLink: NO];
|
||||
d = [GSAttrDictionaryClass attributesAt: path traverseLink: NO];
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
|
@ -2177,8 +2209,8 @@ static NSStringEncoding defaultEncoding;
|
|||
*/
|
||||
- (NSDictionary*) fileSystemAttributesAtPath: (NSString*)path
|
||||
{
|
||||
return [self attributesOfFileSystemForPath:path
|
||||
error:NULL];
|
||||
return [self attributesOfFileSystemForPath: path
|
||||
error: NULL];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2379,6 +2411,9 @@ static NSStringEncoding defaultEncoding;
|
|||
typedef struct _GSEnumeratedDirectory {
|
||||
NSString *path;
|
||||
_DIR *pointer;
|
||||
#ifdef __ANDROID__
|
||||
AAssetDir *assetDir;
|
||||
#endif
|
||||
} GSEnumeratedDirectory;
|
||||
|
||||
|
||||
|
@ -2386,6 +2421,12 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
{
|
||||
DESTROY(X.path);
|
||||
_CLOSEDIR(X.pointer);
|
||||
#ifdef __ANDROID__
|
||||
if (X.assetDir)
|
||||
{
|
||||
AAssetDir_close(X.assetDir);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define GSI_ARRAY_TYPES 0
|
||||
|
@ -2443,12 +2484,29 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
|
||||
localPath = [_mgr fileSystemRepresentationWithPath: path];
|
||||
dir_pointer = _OPENDIR(localPath);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
AAssetDir *assetDir = NULL;
|
||||
if (!dir_pointer)
|
||||
{
|
||||
/* Android: try using asset manager if path is in
|
||||
* main bundle resources
|
||||
*/
|
||||
assetDir = [NSBundle assetDirForPath: path];
|
||||
}
|
||||
|
||||
if (dir_pointer || assetDir)
|
||||
#else
|
||||
if (dir_pointer)
|
||||
#endif
|
||||
{
|
||||
GSIArrayItem item;
|
||||
|
||||
item.ext.path = @"";
|
||||
item.ext.pointer = dir_pointer;
|
||||
#ifdef __ANDROID__
|
||||
item.ext.assetDir = assetDir;
|
||||
#endif
|
||||
|
||||
GSIArrayAddItem(_stack, item);
|
||||
}
|
||||
|
@ -2535,35 +2593,56 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
while (GSIArrayCount(_stack) > 0)
|
||||
{
|
||||
GSEnumeratedDirectory dir = GSIArrayLastItem(_stack).ext;
|
||||
struct _DIRENT *dirbuf;
|
||||
struct _STATB statbuf;
|
||||
#if defined(_WIN32)
|
||||
const wchar_t *dirname = NULL;
|
||||
#else
|
||||
const char *dirname = NULL;
|
||||
#endif
|
||||
|
||||
dirbuf = _READDIR(dir.pointer);
|
||||
#ifdef __ANDROID__
|
||||
if (dir.assetDir)
|
||||
{
|
||||
/* This will only return files and not directories, which means that
|
||||
* recursion is not supported.
|
||||
* See https://issuetracker.google.com/issues/37002833
|
||||
*/
|
||||
dirname = AAssetDir_getNextFileName(dir.assetDir);
|
||||
}
|
||||
else if (dir.pointer)
|
||||
#endif
|
||||
{
|
||||
struct _DIRENT *dirbuf = _READDIR(dir.pointer);
|
||||
if (dirbuf)
|
||||
{
|
||||
dirname = dirbuf->d_name;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirbuf)
|
||||
if (dirname)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/* Skip "." and ".." directory entries */
|
||||
if (wcscmp(dirbuf->d_name, L".") == 0
|
||||
|| wcscmp(dirbuf->d_name, L"..") == 0)
|
||||
if (wcscmp(dirname, L".") == 0
|
||||
|| wcscmp(dirname, L"..") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Name of file to return */
|
||||
returnFileName = [_mgr
|
||||
stringWithFileSystemRepresentation: dirbuf->d_name
|
||||
length: wcslen(dirbuf->d_name)];
|
||||
stringWithFileSystemRepresentation: dirname
|
||||
length: wcslen(dirname)];
|
||||
#else
|
||||
/* Skip "." and ".." directory entries */
|
||||
if (strcmp(dirbuf->d_name, ".") == 0
|
||||
|| strcmp(dirbuf->d_name, "..") == 0)
|
||||
if (strcmp(dirname, ".") == 0
|
||||
|| strcmp(dirname, "..") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Name of file to return */
|
||||
returnFileName = [_mgr
|
||||
stringWithFileSystemRepresentation: dirbuf->d_name
|
||||
length: strlen(dirbuf->d_name)];
|
||||
stringWithFileSystemRepresentation: dirname
|
||||
length: strlen(dirname)];
|
||||
#endif
|
||||
/* if we have a null FileName something went wrong (charset?) and we skip it */
|
||||
if (returnFileName == nil)
|
||||
|
@ -2841,6 +2920,9 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
int rbytes;
|
||||
int wbytes;
|
||||
char buffer[bufsize];
|
||||
#ifdef __ANDROID__
|
||||
AAsset *asset = NULL;
|
||||
#endif
|
||||
|
||||
attributes = [self fileAttributesAtPath: source traverseLink: NO];
|
||||
if (nil == attributes)
|
||||
|
@ -2859,7 +2941,16 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
/* Open the source file. In case of error call the handler. */
|
||||
sourceFd = open([self fileSystemRepresentationWithPath: source],
|
||||
GSBINIO|O_RDONLY);
|
||||
#ifdef __ANDROID__
|
||||
if (sourceFd < 0)
|
||||
{
|
||||
// Android: try using asset manager if path is in main bundle resources
|
||||
asset = [NSBundle assetForPath: source withMode: AASSET_MODE_STREAMING];
|
||||
}
|
||||
if (sourceFd < 0 && asset == NULL)
|
||||
#else
|
||||
if (sourceFd < 0)
|
||||
#endif
|
||||
{
|
||||
return [self _proceedAccordingToHandler: handler
|
||||
forError: @"cannot open file for reading"
|
||||
|
@ -2873,6 +2964,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
GSBINIO|O_WRONLY|O_CREAT|O_TRUNC, fileMode);
|
||||
if (destFd < 0)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
close (sourceFd);
|
||||
|
||||
return [self _proceedAccordingToHandler: handler
|
||||
|
@ -2886,6 +2984,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
file. In case of errors call the handler and abort the operation. */
|
||||
for (i = 0; i < fileSize; i += rbytes)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
rbytes = AAsset_read(asset, buffer, bufsize);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
rbytes = read (sourceFd, buffer, bufsize);
|
||||
if (rbytes <= 0)
|
||||
{
|
||||
|
@ -2893,6 +2998,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
{
|
||||
break; // End of input file
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
close (sourceFd);
|
||||
close (destFd);
|
||||
|
||||
|
@ -2906,6 +3018,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
wbytes = write (destFd, buffer, rbytes);
|
||||
if (wbytes != rbytes)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
close (sourceFd);
|
||||
close (destFd);
|
||||
|
||||
|
@ -2916,6 +3035,13 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
toPath: destination];
|
||||
}
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
AAsset_close(asset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
close (sourceFd);
|
||||
close (destFd);
|
||||
|
||||
|
@ -3252,12 +3378,16 @@ static inline void gsedRelease(GSEnumeratedDirectory X)
|
|||
|
||||
static NSSet *fileKeys = nil;
|
||||
|
||||
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
|
||||
+ (NSDictionary*) attributesAt: (NSString *)path
|
||||
traverseLink: (BOOL)traverse
|
||||
{
|
||||
GSAttrDictionary *d;
|
||||
unsigned l = 0;
|
||||
unsigned i;
|
||||
const _CHAR *lpath = [defaultManager fileSystemRepresentationWithPath: path];
|
||||
#ifdef __ANDROID__
|
||||
AAsset *asset = NULL;
|
||||
#endif
|
||||
|
||||
if (lpath == 0 || *lpath == 0)
|
||||
{
|
||||
|
@ -3275,6 +3405,13 @@ static NSSet *fileKeys = nil;
|
|||
{
|
||||
if (lstat(lpath, &d->statbuf) != 0)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
/* Android: try using asset manager if path is in
|
||||
* main bundle resources
|
||||
*/
|
||||
asset = [NSBundle assetForPath: path];
|
||||
if (asset == NULL)
|
||||
#endif
|
||||
DESTROY(d);
|
||||
}
|
||||
}
|
||||
|
@ -3282,6 +3419,11 @@ static NSSet *fileKeys = nil;
|
|||
#endif
|
||||
if (_STAT(lpath, &d->statbuf) != 0)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
// Android: try using asset manager if path is in main bundle resources
|
||||
asset = [NSBundle assetForPath: path];
|
||||
if (asset == NULL)
|
||||
#endif
|
||||
DESTROY(d);
|
||||
}
|
||||
if (d != nil)
|
||||
|
@ -3290,6 +3432,16 @@ static NSSet *fileKeys = nil;
|
|||
{
|
||||
d->_path[i] = lpath[i];
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
if (asset)
|
||||
{
|
||||
// set some basic stat values for Android assets
|
||||
memset(&d->statbuf, 0, sizeof(d->statbuf));
|
||||
d->statbuf.st_mode = S_IRUSR;
|
||||
d->statbuf.st_size = AAsset_getLength(asset);
|
||||
AAsset_close(asset);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return AUTORELEASE(d);
|
||||
}
|
||||
|
|
|
@ -181,8 +181,10 @@ _NSLog_standard_printf_handler(NSString* message)
|
|||
#else
|
||||
|
||||
#if defined(HAVE_SYSLOG)
|
||||
#ifndef __ANDROID__ // always use syslog on Android (no stdout/stderr)
|
||||
if (GSPrivateDefaultsFlag(GSLogSyslog) == YES
|
||||
|| write(_NSLogDescriptor, buf, len) != (int)len)
|
||||
#endif
|
||||
{
|
||||
null_terminated_buf = malloc(sizeof (char) * (len + 1));
|
||||
strncpy (null_terminated_buf, buf, len);
|
||||
|
|
|
@ -2580,12 +2580,56 @@ GSPrivateMemorySize(NSObject *self, NSHashTable *exclude)
|
|||
}
|
||||
|
||||
@implementation NSObject (MemoryFootprint)
|
||||
+ (NSUInteger) contentSizeInBytesOf: (NSObject*)instance
|
||||
excluding: (NSHashTable*)exclude
|
||||
{
|
||||
unsigned count;
|
||||
Ivar *vars;
|
||||
NSUInteger size = 0;
|
||||
|
||||
if (0 != (vars = class_copyIvarList(self, &count)))
|
||||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
const char *type = ivar_getTypeEncoding(vars[count]);
|
||||
|
||||
type = GSSkipTypeQualifierAndLayoutInfo(type);
|
||||
if ('@' == *type)
|
||||
{
|
||||
NSObject *obj = object_getIvar(instance, vars[count]);
|
||||
|
||||
if (obj != nil)
|
||||
{
|
||||
size += [obj sizeInBytesExcluding: exclude];
|
||||
}
|
||||
}
|
||||
}
|
||||
free(vars);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
+ (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude
|
||||
{
|
||||
return GSPrivateMemorySize(self, exclude);
|
||||
if (0 == NSHashGet(exclude, self))
|
||||
{
|
||||
Class c = object_getClass(self);
|
||||
NSUInteger size = class_getInstanceSize(c);
|
||||
|
||||
NSHashInsert(exclude, self);
|
||||
if (size > 0)
|
||||
{
|
||||
while (c != Nil)
|
||||
{
|
||||
size += [c contentSizeInBytesOf: self excluding: exclude];
|
||||
}
|
||||
c = class_getSuperclass(c);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -943,6 +943,35 @@ extern char **__libc_argv;
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (nil == procLock) procLock = [NSRecursiveLock new];
|
||||
if (self == [NSProcessInfo class]
|
||||
&& !_gnu_processName && !_gnu_arguments && !_gnu_environment)
|
||||
{
|
||||
FILE *f = fopen("/proc/self/cmdline", "r");
|
||||
|
||||
if (f)
|
||||
{
|
||||
char identifier[BUFSIZ];
|
||||
fgets(identifier, sizeof(identifier), f);
|
||||
fclose(f);
|
||||
|
||||
// construct fake executable path
|
||||
char *arg0;
|
||||
asprintf(&arg0, "/data/data/%s/exe", identifier);
|
||||
|
||||
char *argv[] = { arg0 };
|
||||
_gnu_process_args(sizeof(argv)/sizeof(char *), argv, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Failed to read cmdline\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
+ (void) initialize
|
||||
|
|
|
@ -62,10 +62,12 @@
|
|||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_DISPATCH_GET_MAIN_QUEUE_HANDLE_NP && HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP
|
||||
#if HAVE_LIBDISPATCH_RUNLOOP
|
||||
# define RL_INTEGRATE_DISPATCH 1
|
||||
# ifdef HAVE_DISPATCH_H
|
||||
# include <dispatch.h>
|
||||
# elif HAVE_DISPATCH_PRIVATE_H
|
||||
# include <dispatch/private.h>
|
||||
# elif HAVE_DISPATCH_DISPATCH_H
|
||||
# include <dispatch/dispatch.h>
|
||||
# endif
|
||||
|
@ -398,7 +400,13 @@ static inline BOOL timerInvalidated(NSTimer *t)
|
|||
@implementation GSMainQueueDrainer
|
||||
+ (void*) mainQueueFileDescriptor
|
||||
{
|
||||
#if HAVE_DISPATCH_GET_MAIN_QUEUE_HANDLE_NP
|
||||
return (void*)(uintptr_t)dispatch_get_main_queue_handle_np();
|
||||
#elif HAVE__DISPATCH_GET_MAIN_QUEUE_HANDLE_4CF
|
||||
return (void*)_dispatch_get_main_queue_handle_4CF();
|
||||
#else
|
||||
#error libdispatch missing main queue handle function
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) receivedEvent: (void*)data
|
||||
|
@ -406,7 +414,13 @@ static inline BOOL timerInvalidated(NSTimer *t)
|
|||
extra: (void*)extra
|
||||
forMode: (NSString*)mode
|
||||
{
|
||||
#if HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP
|
||||
dispatch_main_queue_drain_np();
|
||||
#elif HAVE__DISPATCH_MAIN_QUEUE_CALLBACK_4CF
|
||||
_dispatch_main_queue_callback_4CF(NULL)
|
||||
#else
|
||||
#error libdispatch missing main queue callback function
|
||||
#endif
|
||||
}
|
||||
@end
|
||||
#endif
|
||||
|
|
|
@ -38,21 +38,40 @@
|
|||
// Dummy implementatation
|
||||
// cleaner than IFDEF'ing the code everywhere
|
||||
#if !(HAVE_PTHREAD_SPIN_LOCK)
|
||||
#warning no spin_locks, using dummy versions
|
||||
typedef int pthread_spinlock_t;
|
||||
typedef volatile int pthread_spinlock_t;
|
||||
int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
|
||||
{
|
||||
#if DEBUG
|
||||
#if DEBUG && !__has_builtin(__sync_bool_compare_and_swap)
|
||||
fprintf(stderr,"NSThread.m: Warning this platform does not support spin locks - init.\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int pthread_spin_lock(pthread_spinlock_t *lock)
|
||||
{
|
||||
#if __has_builtin(__sync_bool_compare_and_swap)
|
||||
int count = 0;
|
||||
// Set the spin lock value to 1 if it is 0.
|
||||
while(!__sync_bool_compare_and_swap(lock, 0, 1))
|
||||
{
|
||||
count++;
|
||||
if (0 == count % 10)
|
||||
{
|
||||
// If it is already 1, let another thread play with the CPU for a
|
||||
// bit then try again.
|
||||
sleep(0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#warning no spin_locks, using dummy versions
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int pthread_spin_unlock(pthread_spinlock_t *lock)
|
||||
{
|
||||
#if __has_builtin(__sync_bool_compare_and_swap)
|
||||
__sync_synchronize();
|
||||
*lock = 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int pthread_spin_destroy(pthread_spinlock_t *lock)
|
||||
|
|
59
configure
vendored
59
configure
vendored
|
@ -764,7 +764,6 @@ infodir
|
|||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
|
@ -879,7 +878,6 @@ datadir='${datarootdir}'
|
|||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE}'
|
||||
|
@ -1132,15 +1130,6 @@ do
|
|||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
|
@ -1278,7 +1267,7 @@ fi
|
|||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
|
@ -1431,7 +1420,6 @@ Fine tuning of the installation directories:
|
|||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
|
@ -5464,7 +5452,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -5510,7 +5498,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -5534,7 +5522,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -5579,7 +5567,7 @@ else
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -5603,7 +5591,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
|||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
|
@ -6008,6 +5996,9 @@ case "$target_os" in
|
|||
LDFLAGS="$LDFLAGS -L/usr/local/lib";;
|
||||
netbsd*) CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
|
||||
LDFLAGS="$LDFLAGS -Wl,-R/usr/pkg/lib -L/usr/pkg/lib";;
|
||||
linux-android* )
|
||||
# link against libandroid for native application APIs
|
||||
LIBS="$LIBS -landroid";;
|
||||
esac
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -12410,6 +12401,20 @@ else
|
|||
have_dispatch=no
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# check for private header which includes runloop integration functions in
|
||||
# the Swift corelibs libdispatch release
|
||||
for ac_header in dispatch/private.h
|
||||
do :
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "dispatch/private.h" "ac_cv_header_dispatch_private_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_dispatch_private_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DISPATCH_PRIVATE_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
@ -12515,10 +12520,24 @@ _ACEOF
|
|||
fi
|
||||
done
|
||||
|
||||
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "no"; then
|
||||
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "yes" && test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "yes"; then
|
||||
HAVE_LIBDISPATCH_RUNLOOP=1
|
||||
fi
|
||||
if test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "no"; then
|
||||
# Check for "_4CF" variants of runloop integration functions provided by the
|
||||
# Swift corelibs libdispatch release
|
||||
for ac_func in _dispatch_main_queue_callback_4CF _dispatch_get_main_queue_handle_4CF
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
done
|
||||
|
||||
if test "$ac_cv_func__dispatch_main_queue_callback_4CF" = "yes" && test "$ac_cv_func__dispatch_get_main_queue_handle_4CF" = "yes"; then
|
||||
HAVE_LIBDISPATCH_RUNLOOP=1
|
||||
fi
|
||||
fi
|
||||
|
|
13
configure.ac
13
configure.ac
|
@ -1246,6 +1246,9 @@ case "$target_os" in
|
|||
LDFLAGS="$LDFLAGS -L/usr/local/lib";;
|
||||
netbsd*) CPPFLAGS="$CPPFLAGS -I/usr/pkg/include"
|
||||
LDFLAGS="$LDFLAGS -Wl,-R/usr/pkg/lib -L/usr/pkg/lib";;
|
||||
linux-android* )
|
||||
# link against libandroid for native application APIs
|
||||
LIBS="$LIBS -landroid";;
|
||||
esac
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
@ -3357,6 +3360,9 @@ if test $enable_libdispatch = yes; then
|
|||
AC_CHECK_HEADERS(dispatch.h, have_dispatch=yes, have_dispatch=no)
|
||||
if test "$have_dispatch" = "no"; then
|
||||
AC_CHECK_HEADERS(dispatch/dispatch.h, have_dispatch=yes, have_dispatch=no)
|
||||
# check for private header which includes runloop integration functions in
|
||||
# the Swift corelibs libdispatch release
|
||||
AC_CHECK_HEADERS(dispatch/private.h)
|
||||
fi
|
||||
if test "$have_dispatch" = "yes"; then
|
||||
AC_CHECK_LIB(dispatch, dispatch_queue_create, have_dispatch=yes, have_dispatch=no)
|
||||
|
@ -3388,10 +3394,13 @@ if test $HAVE_LIBDISPATCH = 1; then
|
|||
# We check whether we have a variant of libdispatch that allows runloop
|
||||
# integration
|
||||
AC_CHECK_FUNCS(dispatch_main_queue_drain_np dispatch_get_main_queue_handle_np)
|
||||
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "no"; then
|
||||
if test "$ac_cv_func_dispatch_main_queue_drain_np" = "yes" && test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "yes"; then
|
||||
HAVE_LIBDISPATCH_RUNLOOP=1
|
||||
fi
|
||||
if test "$ac_cv_func_dispatch_get_main_queue_handle_np" = "no"; then
|
||||
# Check for "_4CF" variants of runloop integration functions provided by the
|
||||
# Swift corelibs libdispatch release
|
||||
AC_CHECK_FUNCS(_dispatch_main_queue_callback_4CF _dispatch_get_main_queue_handle_4CF)
|
||||
if test "$ac_cv_func__dispatch_main_queue_callback_4CF" = "yes" && test "$ac_cv_func__dispatch_get_main_queue_handle_4CF" = "yes"; then
|
||||
HAVE_LIBDISPATCH_RUNLOOP=1
|
||||
fi
|
||||
fi
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue