Merge branch 'master' of github.com:gnustep/libs-base into add_nsorderedset_classcluster

This commit is contained in:
Gregory John Casamento 2019-06-07 04:55:25 -04:00
commit b3e457cd1f
16 changed files with 786 additions and 110 deletions

View file

@ -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
}

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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

View file

@ -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];

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)