mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Attempt to sort out versioning of archives/DO to be more tolerant/flexible.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35118 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
6ebcdc0883
commit
f224e6286b
6 changed files with 189 additions and 48 deletions
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,22 @@
|
|||
2012-02-28 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSArchiver.m:
|
||||
* Source/NSUnarchiver.m:
|
||||
* Source/NSPortCoder.m:
|
||||
* Source/Coder.m:
|
||||
Updates to cope with the fact that some BSD ports of gnustep-base
|
||||
used incorrect versioning, and that people have released Gorm
|
||||
files with versioning incompatible with current releases.
|
||||
1. dissociate coder -systemVersion from the actual system version,
|
||||
so that if people mess with the gnustep-base version, their
|
||||
non-standard releases will still interoperate with normal code.
|
||||
2. Implement new array encoding/decoding compatible with earlier
|
||||
versions (except if the array contains exactly 0xffffffff items).
|
||||
3. Raise exception if decoding archives with an unsupported version.
|
||||
4. Add GSCoderSystemVersion user default to override the system
|
||||
version used for encoding ... for testing and tweaking to generate
|
||||
archives in, or communicate with DO servers using an earlier version.
|
||||
|
||||
2012-04-23 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Tests/base/NSAutoreleasePool/autorelease_eh.m:
|
||||
|
@ -6,11 +25,11 @@
|
|||
2012-04-23 12:47 theraven
|
||||
|
||||
* libs/base/trunk/Source/NSAutoreleasePool.m,
|
||||
libs/base/trunk/Tests/base/NSAutoreleasePool/autorelease_eh.m:
|
||||
Fix a bug in the new autorelease pool implementation when pools
|
||||
are destroyed in the wrong order.
|
||||
libs/base/trunk/Tests/base/NSAutoreleasePool/autorelease_eh.m:
|
||||
Fix a bug in the new autorelease pool implementation when pools
|
||||
are destroyed in the wrong order.
|
||||
|
||||
Test cast by Chris Armstrong!
|
||||
Test cast by Chris Armstrong!
|
||||
|
||||
2012-04-22 Riccardo Mottola <rm@gnu.org>
|
||||
|
||||
|
|
|
@ -254,20 +254,17 @@ static Class NSMutableDataMallocClass;
|
|||
count: (NSUInteger)count
|
||||
at: (const void*)buf
|
||||
{
|
||||
unsigned c = count;
|
||||
uint32_t c;
|
||||
uint8_t bytes[20];
|
||||
uint8_t *bytePtr = 0;
|
||||
uint8_t byteCount = 0;
|
||||
NSUInteger i;
|
||||
NSUInteger offset = 0;
|
||||
unsigned size = objc_sizeof_type(type);
|
||||
uint32_t size = objc_sizeof_type(type);
|
||||
uint32_t version = [self systemVersion];
|
||||
uchar info;
|
||||
|
||||
/* The array count is encoded as a sequence of bytes containing 7bits of
|
||||
* data and using the eighth (top) bit to indicate that there are more
|
||||
* bytes in the sequence.
|
||||
*/
|
||||
if ([self systemVersion] > 12401)
|
||||
if (12402 == version)
|
||||
{
|
||||
NSUInteger tmp = count;
|
||||
|
||||
|
@ -280,6 +277,21 @@ static Class NSMutableDataMallocClass;
|
|||
}
|
||||
bytePtr = &bytes[sizeof(bytes) - byteCount];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We normally store the count as a 32bit integer ... but if it's
|
||||
* very big, we store 0xffffffff and then an additional 64bit value
|
||||
* containing the actual count.
|
||||
*/
|
||||
if (count >= 0xffffffff)
|
||||
{
|
||||
c = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = count;
|
||||
}
|
||||
}
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
|
@ -308,17 +320,21 @@ static Class NSMutableDataMallocClass;
|
|||
if (_initialPass == NO)
|
||||
{
|
||||
(*_tagImp)(_dst, tagSel, _GSC_ARY_B);
|
||||
if (0 == byteCount)
|
||||
{
|
||||
(*_serImp)(_dst, serSel, &c, @encode(unsigned), nil);
|
||||
}
|
||||
else
|
||||
if (12402 == version)
|
||||
{
|
||||
for (i = 0; i < byteCount; i++)
|
||||
{
|
||||
(*_serImp)(_dst, serSel, bytePtr + i, @encode(uint8_t), nil);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_serImp)(_dst, serSel, &c, @encode(uint32_t), nil);
|
||||
if (0xffffffff == c)
|
||||
{
|
||||
(*_serImp)(_dst, serSel, &count, @encode(NSUInteger), nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < c; i++)
|
||||
|
@ -330,17 +346,21 @@ static Class NSMutableDataMallocClass;
|
|||
else if (_initialPass == NO)
|
||||
{
|
||||
(*_tagImp)(_dst, tagSel, _GSC_ARY_B);
|
||||
if (0 == byteCount)
|
||||
{
|
||||
(*_serImp)(_dst, serSel, &c, @encode(unsigned), nil);
|
||||
}
|
||||
else
|
||||
if (12402 == version)
|
||||
{
|
||||
for (i = 0; i < byteCount; i++)
|
||||
{
|
||||
(*_serImp)(_dst, serSel, bytePtr + i, @encode(uint8_t), nil);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_serImp)(_dst, serSel, &c, @encode(uint32_t), nil);
|
||||
if (0xffffffff == c)
|
||||
{
|
||||
(*_serImp)(_dst, serSel, &count, @encode(NSUInteger), nil);
|
||||
}
|
||||
}
|
||||
|
||||
(*_tagImp)(_dst, tagSel, info);
|
||||
for (i = 0; i < count; i++)
|
||||
|
|
|
@ -36,14 +36,42 @@
|
|||
#import "Foundation/NSData.h"
|
||||
#import "Foundation/NSCoder.h"
|
||||
#import "Foundation/NSSerialization.h"
|
||||
#import "Foundation/NSUserDefaults.h"
|
||||
#import "GNUstepBase/NSObject+GNUstepBase.h"
|
||||
|
||||
@implementation NSCoder
|
||||
|
||||
/* We used to use a system version which actually reflected the version
|
||||
* of GNUstep-base ... but people screwed that up by releasing versions
|
||||
* of base with unofficial version numbers conflicting with the scheme.
|
||||
* So ... we are now starting from a basepoint of 1 million ... on the
|
||||
* basis that the old numbering scheme derived from the gnustep-base
|
||||
* major.minor.subminor versioning (in which each can range from 0 to 99)
|
||||
* should not have allowed anyone to create an archive with a version
|
||||
* greater than 999999.
|
||||
* In future, the system version will change if (and only if) the format
|
||||
* of the encoded data changes.
|
||||
*/
|
||||
#define MAX_SUPPORTED_SYSTEM_VERSION 1000000
|
||||
|
||||
static unsigned systemVersion = MAX_SUPPORTED_SYSTEM_VERSION;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSCoder class])
|
||||
{
|
||||
unsigned sv;
|
||||
|
||||
/* The GSCoderSystemVersion user default is provided for testing
|
||||
* and to allow new code to communicate (via Distributed Objects)
|
||||
* with systems running older versions.
|
||||
*/
|
||||
sv = [[NSUserDefaults standardUserDefaults]
|
||||
integerForKey: @"GSCoderSystemVersion"];
|
||||
if (sv > 0 && sv <= MAX_SUPPORTED_SYSTEM_VERSION)
|
||||
{
|
||||
systemVersion = sv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,8 +326,7 @@
|
|||
|
||||
- (unsigned) systemVersion
|
||||
{
|
||||
return (((GNUSTEP_BASE_MAJOR_VERSION * 100)
|
||||
+ GNUSTEP_BASE_MINOR_VERSION) * 100) + GNUSTEP_BASE_SUBMINOR_VERSION;
|
||||
return systemVersion;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -351,10 +351,16 @@ static IMP _eSerImp; /* Method to serialize with. */
|
|||
static IMP _eTagImp; /* Serialize a type tag. */
|
||||
static IMP _xRefImp; /* Serialize a crossref. */
|
||||
|
||||
static unsigned encodingVersion;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSPortCoder class])
|
||||
{
|
||||
NSCoder *coder = [NSCoder new];
|
||||
|
||||
encodingVersion = [coder systemVersion];
|
||||
[coder release];
|
||||
#if GS_WITH_GC
|
||||
/* We create a typed memory descriptor for map nodes.
|
||||
*/
|
||||
|
@ -435,12 +441,12 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
{
|
||||
NSUInteger i;
|
||||
NSUInteger offset = 0;
|
||||
unsigned size = objc_sizeof_type(type);
|
||||
uint32_t size = objc_sizeof_type(type);
|
||||
unsigned char info;
|
||||
NSUInteger count;
|
||||
|
||||
(*_dTagImp)(_src, dTagSel, &info, 0, &_cursor);
|
||||
if (_version > 12401)
|
||||
if (12402 == _version)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
|
@ -469,10 +475,15 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned c;
|
||||
uint32_t c;
|
||||
|
||||
(*_dDesImp)(_src, dDesSel, &c, @encode(unsigned), &_cursor, nil);
|
||||
(*_dDesImp)(_src, dDesSel, &c, @encode(uint32_t), &_cursor, nil);
|
||||
count = c;
|
||||
if (0xffffffff == c)
|
||||
{
|
||||
(*_dDesImp)(_src, dDesSel,
|
||||
&count, @encode(NSUInteger), &_cursor, nil);
|
||||
}
|
||||
}
|
||||
if (info != _GSC_ARY_B)
|
||||
{
|
||||
|
@ -1135,19 +1146,16 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
at: (const void*)buf
|
||||
{
|
||||
NSUInteger i;
|
||||
unsigned c = count;
|
||||
uint32_t c = count;
|
||||
uint8_t bytes[20];
|
||||
uint8_t *bytePtr = 0;
|
||||
uint8_t byteCount = 0;
|
||||
NSUInteger offset = 0;
|
||||
unsigned size = objc_sizeof_type(type);
|
||||
uint32_t size = objc_sizeof_type(type);
|
||||
uint32_t version = [self systemVersion];
|
||||
uchar info;
|
||||
|
||||
/* The array count is encoded as a sequence of bytes containing 7bits of
|
||||
* data and using the eighth (top) bit to indicate that there are more
|
||||
* bytes in the sequence.
|
||||
*/
|
||||
if ([self systemVersion] > 12401)
|
||||
if (12402 == version)
|
||||
{
|
||||
NSUInteger tmp = count;
|
||||
|
||||
|
@ -1160,6 +1168,21 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
}
|
||||
bytePtr = &bytes[sizeof(bytes) - byteCount];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We normally store the count as a 32bit integer ... but if it's
|
||||
* very big, we store 0xffffffff and then an additional 64bit value
|
||||
* containing the actual count.
|
||||
*/
|
||||
if (count >= 0xffffffff)
|
||||
{
|
||||
c = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = count;
|
||||
}
|
||||
}
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
|
@ -1188,11 +1211,7 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
if (_initialPass == NO)
|
||||
{
|
||||
(*_eTagImp)(_dst, eTagSel, _GSC_ARY_B);
|
||||
if (0 == byteCount)
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil);
|
||||
}
|
||||
else
|
||||
if (12402 == version)
|
||||
{
|
||||
for (i = 0; i < byteCount; i++)
|
||||
{
|
||||
|
@ -1200,6 +1219,14 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
(_dst, eSerSel, bytePtr + i, @encode(uint8_t), nil);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, &c, @encode(uint32_t), nil);
|
||||
if (0xffffffff == c)
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, &count, @encode(NSUInteger), nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -1210,17 +1237,21 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
else if (_initialPass == NO)
|
||||
{
|
||||
(*_eTagImp)(_dst, eTagSel, _GSC_ARY_B);
|
||||
if (0 == byteCount)
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil);
|
||||
}
|
||||
else
|
||||
if (12402 == version)
|
||||
{
|
||||
for (i = 0; i < byteCount; i++)
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, bytePtr + i, @encode(uint8_t), nil);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil);
|
||||
if (0xffffffff == c)
|
||||
{
|
||||
(*_eSerImp)(_dst, eSerSel, &count, @encode(NSUInteger), nil);
|
||||
}
|
||||
}
|
||||
|
||||
(*_eTagImp)(_dst, eTagSel, info);
|
||||
for (i = 0; i < count; i++)
|
||||
|
@ -1920,6 +1951,12 @@ static IMP _xRefImp; /* Serialize a crossref. */
|
|||
objects: &sizeO
|
||||
pointers: &sizeP];
|
||||
|
||||
if (_version > encodingVersion)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Message systemVersion (%u) not recognised", _version];
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialise arrays to build crossref maps in.
|
||||
*/
|
||||
|
|
|
@ -398,16 +398,22 @@ mapClassName(NSUnarchiverObjectInfo *info)
|
|||
@implementation NSUnarchiver
|
||||
|
||||
static Class NSDataMallocClass;
|
||||
static unsigned encodingVersion;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if ([self class] == [NSUnarchiver class])
|
||||
{
|
||||
NSArchiver *archiver = [NSArchiver new];
|
||||
|
||||
encodingVersion = [archiver systemVersion];
|
||||
[archiver release];
|
||||
desSel = @selector(deserializeDataAt:ofObjCType:atCursor:context:);
|
||||
tagSel = @selector(deserializeTypeTag:andCrossRef:atCursor:);
|
||||
dValSel = @selector(decodeValueOfObjCType:at:);
|
||||
clsDict = [[NSMutableDictionary alloc] initWithCapacity: 200];
|
||||
NSDataMallocClass = [NSDataMalloc class];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,7 +542,7 @@ static Class NSDataMallocClass;
|
|||
NSUInteger count;
|
||||
|
||||
(*tagImp)(src, tagSel, &info, 0, &cursor);
|
||||
if ([self systemVersion] > 12401)
|
||||
if ([self systemVersion] == 12402)
|
||||
{
|
||||
uint8_t c;
|
||||
|
||||
|
@ -565,10 +571,14 @@ static Class NSDataMallocClass;
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned c;
|
||||
uint32_t c;
|
||||
|
||||
(*desImp)(src, desSel, &c, @encode(unsigned), &cursor, nil);
|
||||
(*desImp)(src, desSel, &c, @encode(uint32_t), &cursor, nil);
|
||||
count = c;
|
||||
if (0xffffffff == c)
|
||||
{
|
||||
(*desImp)(src, desSel, &count, @encode(NSUInteger), &cursor, nil);
|
||||
}
|
||||
}
|
||||
if (info != _GSC_ARY_B)
|
||||
{
|
||||
|
@ -1524,6 +1534,11 @@ static Class NSDataMallocClass;
|
|||
classes: &sizeC
|
||||
objects: &sizeO
|
||||
pointers: &sizeP];
|
||||
if (version > encodingVersion)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Archive systemVersion (%u) not recognised", version];
|
||||
}
|
||||
|
||||
if (clsMap == 0)
|
||||
{
|
||||
|
|
|
@ -4,13 +4,36 @@
|
|||
* might be from an earlier build.
|
||||
*/
|
||||
|
||||
// disable extensions ... we want to use standard code
|
||||
/* disable extensions ... we want to use standard code
|
||||
*/
|
||||
#ifdef _GNU_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
/* Ensure we have _XOPEN_SOURCE turned on at the appropriate
|
||||
* level for the facilities we need.
|
||||
*
|
||||
* Minimum of 600 for string.h so we get the POSIX strerror_r() behavior
|
||||
*/
|
||||
#if defined(_XOPEN_SOURCE)
|
||||
#if _XOPEN_SOURCE < 600
|
||||
#undef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
#else
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
|
||||
#import "config.h"
|
||||
|
||||
#if defined(HAVE_STRING_H)
|
||||
/* For POSIX strerror_r()
|
||||
*/
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/* If this is included in a file in the Additions subdirectory, and we are
|
||||
* building for use with the NeXT/Apple Foundation, then we need to import
|
||||
* the native headers in preference to any of our own.
|
||||
|
|
Loading…
Reference in a new issue