mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-04 10:30:47 +00:00
get base to compile again, and improve readability/consistency
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34184 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
2f646c72ad
commit
fc8d1c8260
3 changed files with 204 additions and 80 deletions
25
ChangeLog
25
ChangeLog
|
@ -1,16 +1,29 @@
|
||||||
|
2011-11-17 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/GSString.m: Fix to compile again (use ifdef to consistently
|
||||||
|
have/not-have tiny strings), and tidy use of whitespace for readability
|
||||||
|
and coding standards.
|
||||||
|
I like the experimental tiny strings idea... will definitely save
|
||||||
|
space, but will need a lot of optimisation (like that of literal
|
||||||
|
strings) to stop it being slow.
|
||||||
|
Until it's about as fast as literal strings, we should probably only
|
||||||
|
enable it on platforms where memory footprint is an issue.
|
||||||
|
Not sure how to do that though.
|
||||||
|
|
||||||
2011-11-16 20:48 theraven
|
2011-11-16 20:48 theraven
|
||||||
|
|
||||||
* libs/base/trunk/Source/GSString.m: Store tiny strings (up to 8
|
* Source/GSString.m: Store tiny strings (up to 8
|
||||||
ASCII characters) inside the pointer. Strings of this length are fairly
|
ASCII characters) inside the pointer. Strings of this length are
|
||||||
common, and this makes them very cheap to store / copy / compare
|
fairly common, and this makes them very cheap to store/copy/compare
|
||||||
(pointer comparisons test for equality). 8 characters seems to be enough
|
(pointer comparisons test for equality). 8 characters seems to be
|
||||||
for quite a lot of common uses, such as path components and tokens.
|
enough for quite a lot of common uses, such as path components and
|
||||||
|
tokens.
|
||||||
There are possibly still some things constructing tiny strings and not
|
There are possibly still some things constructing tiny strings and not
|
||||||
using these.
|
using these.
|
||||||
|
|
||||||
2011-11-16 17:29 theraven
|
2011-11-16 17:29 theraven
|
||||||
|
|
||||||
* libs/base/trunk/Source/NSNumber.m: Implement the double boxing
|
* Source/NSNumber.m: Implement the double boxing
|
||||||
techniques used by Smalltalk/X and Cincom Smalltalk. Now we can
|
techniques used by Smalltalk/X and Cincom Smalltalk. Now we can
|
||||||
conceal most doubles inside a pointer. This is most useful for
|
conceal most doubles inside a pointer. This is most useful for
|
||||||
LanguageKit, but should save some memory / malloc overhead / heap
|
LanguageKit, but should save some memory / malloc overhead / heap
|
||||||
|
|
|
@ -695,7 +695,7 @@ static void getCString_u(GSStr self, char *buffer, unsigned int maxLength,
|
||||||
|
|
||||||
#if defined(OBJC_SMALL_OBJECT_SHIFT) && (OBJC_SMALL_OBJECT_SHIFT == 3)
|
#if defined(OBJC_SMALL_OBJECT_SHIFT) && (OBJC_SMALL_OBJECT_SHIFT == 3)
|
||||||
#define TINY_STRING_MASK 4
|
#define TINY_STRING_MASK 4
|
||||||
BOOL useTinyStrings;
|
static BOOL useTinyStrings;
|
||||||
/**
|
/**
|
||||||
* A GSTinyString is used on 64-bit platforms to store up to 8 ASCII (7-bit)
|
* A GSTinyString is used on 64-bit platforms to store up to 8 ASCII (7-bit)
|
||||||
* characters inside a pointer. Note that a mutable version of this class is
|
* characters inside a pointer. Note that a mutable version of this class is
|
||||||
|
@ -718,17 +718,21 @@ BOOL useTinyStrings;
|
||||||
#define TINY_STRING_CHAR(s, x) ((s & (0xFE00000000000000 >> (x*7))) >> (57-(x*7)))
|
#define TINY_STRING_CHAR(s, x) ((s & (0xFE00000000000000 >> (x*7))) >> (57-(x*7)))
|
||||||
#define TINY_STRING_LENGTH_MASK 0x1f
|
#define TINY_STRING_LENGTH_MASK 0x1f
|
||||||
#define TINY_STRING_LENGTH_SHIFT OBJC_SMALL_OBJECT_SHIFT
|
#define TINY_STRING_LENGTH_SHIFT OBJC_SMALL_OBJECT_SHIFT
|
||||||
@interface GSTinyString : NSString @end
|
@interface GSTinyString : NSString
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation GSTinyString
|
@implementation GSTinyString
|
||||||
- (NSUInteger)length
|
- (NSUInteger) length
|
||||||
{
|
{
|
||||||
uintptr_t s = (uintptr_t)self;
|
uintptr_t s = (uintptr_t)self;
|
||||||
return (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
|
return (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
|
||||||
}
|
}
|
||||||
- (unichar)characterAtIndex: (NSUInteger)anIndex
|
|
||||||
|
- (unichar) characterAtIndex: (NSUInteger)anIndex
|
||||||
{
|
{
|
||||||
uintptr_t s = (uintptr_t)self;
|
uintptr_t s = (uintptr_t)self;
|
||||||
NSUInteger length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
|
NSUInteger length = (s >> TINY_STRING_LENGTH_SHIFT) & TINY_STRING_LENGTH_MASK;
|
||||||
|
|
||||||
if (anIndex >= length)
|
if (anIndex >= length)
|
||||||
{
|
{
|
||||||
[NSException raise: NSInvalidArgumentException
|
[NSException raise: NSInvalidArgumentException
|
||||||
|
@ -741,41 +745,74 @@ BOOL useTinyStrings;
|
||||||
}
|
}
|
||||||
return TINY_STRING_CHAR(s, anIndex);
|
return TINY_STRING_CHAR(s, anIndex);
|
||||||
}
|
}
|
||||||
+ (void)load
|
|
||||||
|
+ (void) load
|
||||||
{
|
{
|
||||||
useTinyStrings = objc_registerSmallObjectClass_np(self, TINY_STRING_MASK);
|
useTinyStrings = objc_registerSmallObjectClass_np(self, TINY_STRING_MASK);
|
||||||
}
|
}
|
||||||
+ (id)alloc
|
|
||||||
|
+ (id) alloc
|
||||||
{
|
{
|
||||||
return (id)TINY_STRING_MASK;
|
return (id)TINY_STRING_MASK;
|
||||||
}
|
}
|
||||||
+ (id)allocWithZone: (NSZone*)aZone
|
|
||||||
|
+ (id) allocWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return (id)TINY_STRING_MASK;
|
return (id)TINY_STRING_MASK;
|
||||||
}
|
}
|
||||||
- (id)copy
|
|
||||||
|
- (id) copy
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)copyWithZone: (NSZone*)aZone
|
|
||||||
|
- (id) copyWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)retain { return self; }
|
|
||||||
- (id)autorelease { return self; }
|
- (id) retain
|
||||||
- (oneway void)release { }
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) autorelease
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (oneway void) release
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a tiny string.
|
* Constructs a tiny string.
|
||||||
*/
|
*/
|
||||||
static id createTinyString(const char *str, int length)
|
static id
|
||||||
|
createTinyString(const char *str, int length)
|
||||||
{
|
{
|
||||||
// No tiny string support detected at run time, give up
|
/* No tiny string support detected at run time, give up
|
||||||
if (!useTinyStrings) { return nil; }
|
*/
|
||||||
// String too long to fit in a pointer, give up
|
if (!useTinyStrings)
|
||||||
if (length > 9) { return nil; }
|
{
|
||||||
// String would fit if the last byte was an implicit 0, but it isn't.
|
return nil;
|
||||||
if ((length == 9) && str[8] != '\0') { return nil; }
|
}
|
||||||
|
|
||||||
|
/* String too long to fit in a pointer, give up
|
||||||
|
*/
|
||||||
|
if (length > 9)
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* String would fit if the last byte was an implicit 0, but it isn't.
|
||||||
|
*/
|
||||||
|
if ((length == 9) && str[8] != '\0')
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
uintptr_t s = TINY_STRING_MASK;
|
uintptr_t s = TINY_STRING_MASK;
|
||||||
s |= length << TINY_STRING_LENGTH_SHIFT;
|
s |= length << TINY_STRING_LENGTH_SHIFT;
|
||||||
for (unsigned int i = 0 ; i<length ; i++)
|
for (unsigned int i = 0 ; i<length ; i++)
|
||||||
|
@ -784,11 +821,6 @@ static id createTinyString(const char *str, int length)
|
||||||
}
|
}
|
||||||
return (id)s;
|
return (id)s;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
static id createTinyString(const char *str, int length)
|
|
||||||
{
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* The GSPlaceholderString class is used by the abstract cluster root
|
* The GSPlaceholderString class is used by the abstract cluster root
|
||||||
|
@ -945,11 +977,13 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned,
|
||||||
{
|
{
|
||||||
const void *original = bytes;
|
const void *original = bytes;
|
||||||
|
|
||||||
|
#if defined(OBJC_SMALL_OBJECT_SHIFT) && (OBJC_SMALL_OBJECT_SHIFT == 3)
|
||||||
if (useTinyStrings)
|
if (useTinyStrings)
|
||||||
{
|
{
|
||||||
if (NSASCIIStringEncoding == encoding)
|
if (NSASCIIStringEncoding == encoding)
|
||||||
{
|
{
|
||||||
id tinyString = createTinyString(bytes, length);
|
id tinyString = createTinyString(bytes, length);
|
||||||
|
|
||||||
if (tinyString)
|
if (tinyString)
|
||||||
{
|
{
|
||||||
return tinyString;
|
return tinyString;
|
||||||
|
@ -958,7 +992,8 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned,
|
||||||
if (NSUTF8StringEncoding == encoding && (length < 9))
|
if (NSUTF8StringEncoding == encoding && (length < 9))
|
||||||
{
|
{
|
||||||
NSUInteger i;
|
NSUInteger i;
|
||||||
for (i=0 ; i<length ; i++)
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
if (((const char*)bytes)[i] & 0x80)
|
if (((const char*)bytes)[i] & 0x80)
|
||||||
{
|
{
|
||||||
|
@ -968,6 +1003,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned,
|
||||||
if (i == length)
|
if (i == length)
|
||||||
{
|
{
|
||||||
id tinyString = createTinyString(bytes, length);
|
id tinyString = createTinyString(bytes, length);
|
||||||
|
|
||||||
if (tinyString)
|
if (tinyString)
|
||||||
{
|
{
|
||||||
return tinyString;
|
return tinyString;
|
||||||
|
@ -975,6 +1011,7 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fixBOM((unsigned char**)&bytes, &length, &flag, encoding);
|
fixBOM((unsigned char**)&bytes, &length, &flag, encoding);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -357,46 +357,71 @@ static BOOL useSmallRepeatingDouble;
|
||||||
#define SMALL_REPEATING_DOUBLE_MASK 3
|
#define SMALL_REPEATING_DOUBLE_MASK 3
|
||||||
|
|
||||||
|
|
||||||
@interface NSSmallInt : NSSignedIntegerNumber @end
|
@interface NSSmallInt : NSSignedIntegerNumber
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation NSSmallInt
|
@implementation NSSmallInt
|
||||||
#undef VALUE
|
#undef VALUE
|
||||||
#define VALUE (((intptr_t)self) >> OBJC_SMALL_OBJECT_SHIFT)
|
#define VALUE (((intptr_t)self) >> OBJC_SMALL_OBJECT_SHIFT)
|
||||||
#define FORMAT @"%d"
|
#define FORMAT @"%d"
|
||||||
#include "NSNumberMethods.h"
|
#include "NSNumberMethods.h"
|
||||||
+ (void)load
|
|
||||||
|
+ (void) load
|
||||||
{
|
{
|
||||||
useSmallInt = objc_registerSmallObjectClass_np(self, SMALL_INT_MASK);
|
useSmallInt = objc_registerSmallObjectClass_np(self, SMALL_INT_MASK);
|
||||||
}
|
}
|
||||||
+ (id)alloc
|
|
||||||
|
+ (id) alloc
|
||||||
{
|
{
|
||||||
return (id)1;
|
return (id)1;
|
||||||
}
|
}
|
||||||
+ (id)allocWithZone: (NSZone*)aZone
|
|
||||||
|
+ (id) allocWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return (id)1;
|
return (id)1;
|
||||||
}
|
}
|
||||||
- (id)copy
|
|
||||||
|
- (id) copy
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)copyWithZone: (NSZone*)aZone
|
|
||||||
|
- (id) copyWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)retain { return self; }
|
|
||||||
- (id)autorelease { return self; }
|
- (id) retain
|
||||||
- (oneway void)release { }
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) autorelease
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (oneway void) release
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#if OBJC_SMALL_OBJECT_SHIFT == 3
|
#if OBJC_SMALL_OBJECT_SHIFT == 3
|
||||||
|
|
||||||
union BoxedDouble
|
union BoxedDouble
|
||||||
{
|
{
|
||||||
id obj;
|
id obj;
|
||||||
uintptr_t bits;
|
uintptr_t bits;
|
||||||
double d;
|
double d;
|
||||||
} ;
|
};
|
||||||
@interface NSSmallExtendedDouble : NSFloatingPointNumber @end
|
|
||||||
|
@interface NSSmallExtendedDouble : NSFloatingPointNumber
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation NSSmallExtendedDouble
|
@implementation NSSmallExtendedDouble
|
||||||
static double unboxSmallExtendedDouble(uintptr_t boxed)
|
static double
|
||||||
|
unboxSmallExtendedDouble(uintptr_t boxed)
|
||||||
{
|
{
|
||||||
// The low bit of the mantissa
|
// The low bit of the mantissa
|
||||||
uintptr_t mask = boxed & 8;
|
uintptr_t mask = boxed & 8;
|
||||||
|
@ -406,12 +431,16 @@ static double unboxSmallExtendedDouble(uintptr_t boxed)
|
||||||
ret.bits = boxed | (mask >> 1) | (mask >> 2) | (mask >> 3);
|
ret.bits = boxed | (mask >> 1) | (mask >> 2) | (mask >> 3);
|
||||||
return ret.d;
|
return ret.d;
|
||||||
}
|
}
|
||||||
static BOOL isSmallExtendedDouble(double d)
|
|
||||||
|
static BOOL
|
||||||
|
isSmallExtendedDouble(double d)
|
||||||
{
|
{
|
||||||
union BoxedDouble b = {.d=d};
|
union BoxedDouble b = {.d=d};
|
||||||
return unboxSmallExtendedDouble(b.bits) == d;
|
return unboxSmallExtendedDouble(b.bits) == d;
|
||||||
}
|
}
|
||||||
static double unboxSmallRepeatingDouble(uintptr_t boxed)
|
|
||||||
|
static double
|
||||||
|
unboxSmallRepeatingDouble(uintptr_t boxed)
|
||||||
{
|
{
|
||||||
// The low bit of the mantissa
|
// The low bit of the mantissa
|
||||||
uintptr_t mask = boxed & 56;
|
uintptr_t mask = boxed & 56;
|
||||||
|
@ -421,75 +450,120 @@ static double unboxSmallRepeatingDouble(uintptr_t boxed)
|
||||||
ret.bits = boxed | (mask >> 3);
|
ret.bits = boxed | (mask >> 3);
|
||||||
return ret.d;
|
return ret.d;
|
||||||
}
|
}
|
||||||
static BOOL isSmallRepeatingDouble(double d)
|
|
||||||
|
static BOOL
|
||||||
|
isSmallRepeatingDouble(double d)
|
||||||
{
|
{
|
||||||
union BoxedDouble b = {.d=d};
|
union BoxedDouble b = {.d=d};
|
||||||
return unboxSmallRepeatingDouble(b.bits) == d;
|
return unboxSmallRepeatingDouble(b.bits) == d;
|
||||||
}
|
}
|
||||||
static id boxDouble(double d, uintptr_t mask)
|
|
||||||
|
static id
|
||||||
|
boxDouble(double d, uintptr_t mask)
|
||||||
{
|
{
|
||||||
union BoxedDouble b = {.d=d};
|
union BoxedDouble b = {.d=d};
|
||||||
b.bits &= ~OBJC_SMALL_OBJECT_MASK;
|
b.bits &= ~OBJC_SMALL_OBJECT_MASK;
|
||||||
b.bits |= mask;
|
b.bits |= mask;
|
||||||
return b.obj;
|
return b.obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef VALUE
|
#undef VALUE
|
||||||
#define VALUE (unboxSmallExtendedDouble((uintptr_t)self))
|
#define VALUE (unboxSmallExtendedDouble((uintptr_t)self))
|
||||||
#define FORMAT @"%0.16g"
|
#define FORMAT @"%0.16g"
|
||||||
#include "NSNumberMethods.h"
|
#include "NSNumberMethods.h"
|
||||||
+ (void)load
|
|
||||||
|
+ (void)
|
||||||
|
load
|
||||||
{
|
{
|
||||||
useSmallExtendedDouble = objc_registerSmallObjectClass_np(self, SMALL_EXTENDED_DOUBLE_MASK);
|
useSmallExtendedDouble = objc_registerSmallObjectClass_np
|
||||||
|
(self, SMALL_EXTENDED_DOUBLE_MASK);
|
||||||
}
|
}
|
||||||
+ (id)alloc
|
|
||||||
|
+ (id) alloc
|
||||||
{
|
{
|
||||||
return (id)SMALL_EXTENDED_DOUBLE_MASK;
|
return (id)SMALL_EXTENDED_DOUBLE_MASK;
|
||||||
}
|
}
|
||||||
+ (id)allocWithZone: (NSZone*)aZone
|
|
||||||
|
+ (id) allocWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return (id)SMALL_EXTENDED_DOUBLE_MASK;
|
return (id)SMALL_EXTENDED_DOUBLE_MASK;
|
||||||
}
|
}
|
||||||
- (id)copy
|
|
||||||
|
- (id) copy
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)copyWithZone: (NSZone*)aZone
|
|
||||||
|
- (id) copyWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)retain { return self; }
|
|
||||||
- (id)autorelease { return self; }
|
- (id) retain
|
||||||
- (oneway void)release { }
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) autorelease
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (oneway void) release
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
@interface NSSmallRepeatingDouble : NSFloatingPointNumber @end
|
|
||||||
|
@interface NSSmallRepeatingDouble : NSFloatingPointNumber
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation NSSmallRepeatingDouble
|
@implementation NSSmallRepeatingDouble
|
||||||
#undef VALUE
|
#undef VALUE
|
||||||
#define VALUE (unboxSmallRepeatingDouble((uintptr_t)self))
|
#define VALUE (unboxSmallRepeatingDouble((uintptr_t)self))
|
||||||
#define FORMAT @"%0.16g"
|
#define FORMAT @"%0.16g"
|
||||||
#include "NSNumberMethods.h"
|
#include "NSNumberMethods.h"
|
||||||
+ (void)load
|
|
||||||
|
+ (void) load
|
||||||
{
|
{
|
||||||
useSmallRepeatingDouble = objc_registerSmallObjectClass_np(self, SMALL_REPEATING_DOUBLE_MASK);
|
useSmallRepeatingDouble = objc_registerSmallObjectClass_np
|
||||||
|
(self, SMALL_REPEATING_DOUBLE_MASK);
|
||||||
}
|
}
|
||||||
+ (id)alloc
|
|
||||||
|
+ (id) alloc
|
||||||
{
|
{
|
||||||
return (id)SMALL_REPEATING_DOUBLE_MASK;
|
return (id)SMALL_REPEATING_DOUBLE_MASK;
|
||||||
}
|
}
|
||||||
+ (id)allocWithZone: (NSZone*)aZone
|
|
||||||
|
+ (id) allocWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return (id)SMALL_REPEATING_DOUBLE_MASK;
|
return (id)SMALL_REPEATING_DOUBLE_MASK;
|
||||||
}
|
}
|
||||||
- (id)copy
|
|
||||||
|
- (id) copy
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)copyWithZone: (NSZone*)aZone
|
|
||||||
|
- (id) copyWithZone: (NSZone*)aZone
|
||||||
{
|
{
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
- (id)retain { return self; }
|
|
||||||
- (id)autorelease { return self; }
|
- (id) retain
|
||||||
- (oneway void)release { }
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) autorelease
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (oneway void) release
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue