mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
Removed obsolete files to Old subdirectory
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@7190 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
c31c32a186
commit
f048297123
45 changed files with 124 additions and 9920 deletions
124
ChangeLog
124
ChangeLog
|
@ -1,3 +1,127 @@
|
|||
2000-08-08 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/gnustep/base/all.h: Moved to Old as obsolete file.
|
||||
* Headers/gnustep/base/Arch: dittoiver.m
|
||||
* Headers/gnustep/base/Archiver.h: ditto
|
||||
* Headers/gnustep/base/Array.h: ditto
|
||||
* Headers/gnustep/base/ArrayPrivate.h: ditto
|
||||
* Headers/gnustep/base/Bag.h: ditto
|
||||
* Headers/gnustep/base/BinaryCStream.h: ditto
|
||||
* Headers/gnustep/base/BinaryTree.h: ditto
|
||||
* Headers/gnustep/base/BinaryTreeNode.h: ditto
|
||||
* Headers/gnustep/base/CircularArray.h: ditto
|
||||
* Headers/gnustep/base/CircularArrayPrivate.h: ditto
|
||||
* Headers/gnustep/base/Coder.h: ditto
|
||||
* Headers/gnustep/base/CoderPrivate.h: ditto
|
||||
* Headers/gnustep/base/Coding.h: ditto
|
||||
* Headers/gnustep/base/Collecting.h: ditto
|
||||
* Headers/gnustep/base/Collection.h: ditto
|
||||
* Headers/gnustep/base/CollectionPrivate.h: ditto
|
||||
* Headers/gnustep/base/CStream.h: ditto
|
||||
* Headers/gnustep/base/CStreaming.h: ditto
|
||||
* Headers/gnustep/base/DelegatePool.h: ditto
|
||||
* Headers/gnustep/base/Dictionary.h: ditto
|
||||
* Headers/gnustep/base/Enumerating.h: ditto
|
||||
* Headers/gnustep/base/GapArray.h: ditto
|
||||
* Headers/gnustep/base/GapArrayPrivate.h: ditto
|
||||
* Headers/gnustep/base/Heap.h: ditto
|
||||
* Headers/gnustep/base/IndexedCollecting.h: ditto
|
||||
* Headers/gnustep/base/IndexedCollection.h: ditto
|
||||
* Headers/gnustep/base/IndexedCollectionPrivate.h: ditto
|
||||
* Headers/gnustep/base/InvalidationListening.h: ditto
|
||||
* Headers/gnustep/base/Invocation.h: ditto
|
||||
* Headers/gnustep/base/Invoking.h: ditto
|
||||
* Headers/gnustep/base/KeyedCollecting.h: ditto
|
||||
* Headers/gnustep/base/KeyedCollection.h: ditto
|
||||
* Headers/gnustep/base/LinkedList.h: ditto
|
||||
* Headers/gnustep/base/LinkedListNode.h: ditto
|
||||
* Headers/gnustep/base/Locking.h: ditto
|
||||
* Headers/gnustep/base/Mach: dittoPort.m
|
||||
* Headers/gnustep/base/MachPort.h: ditto
|
||||
* Headers/gnustep/base/Magnitude.h: ditto
|
||||
* Headers/gnustep/base/MappedCollector.h: ditto
|
||||
* Headers/gnustep/base/MemoryStream.h: ditto
|
||||
* Headers/gnustep/base/NotificationDispatch: dittoer.m
|
||||
* Headers/gnustep/base/NotificationDispatcher.h: ditto
|
||||
* Headers/gnustep/base/OldNSConnection.h: ditto
|
||||
* Headers/gnustep/base/OldNSPortCoder.h: ditto
|
||||
* Headers/gnustep/base/OrderedCollecting.h: ditto
|
||||
* Headers/gnustep/base/OrderedCollection.h: ditto
|
||||
* Headers/gnustep/base/Ordering.h: ditto
|
||||
* Headers/gnustep/base/Port.h: ditto
|
||||
* Headers/gnustep/base/Queue.h: ditto
|
||||
* Headers/gnustep/base/RandomGenerating.h: ditto
|
||||
* Headers/gnustep/base/Random.h: ditto
|
||||
* Headers/gnustep/base/RawCStream.h: ditto
|
||||
* Headers/gnustep/base/RBTree.h: ditto
|
||||
* Headers/gnustep/base/RBTreeNode.h: ditto
|
||||
* Headers/gnustep/base/Retaining.h: ditto
|
||||
* Headers/gnustep/base/RNGAdditiveCongruential.h: ditto
|
||||
* Headers/gnustep/base/RNGBerkeley.h: ditto
|
||||
* Headers/gnustep/base/RunLoop.h: ditto
|
||||
* Headers/gnustep/base/Set.h: ditto
|
||||
* Headers/gnustep/base/SplayTree.h: ditto
|
||||
* Headers/gnustep/base/Stack.h: ditto
|
||||
* Headers/gnustep/base/StdioStream.h: ditto
|
||||
* Headers/gnustep/base/Stream.h: ditto
|
||||
* Headers/gnustep/base/Streaming.h: ditto
|
||||
* Headers/gnustep/base/TcpPort.h: ditto
|
||||
* Headers/gnustep/base/TextCStream.h: ditto
|
||||
* Headers/gnustep/base/Time.h: ditto
|
||||
* Headers/gnustep/base/UdpPort.h: ditto
|
||||
* Headers/gnustep/base/ValueHolding.h: ditto
|
||||
* Source/Array.m: ditto
|
||||
* Source/Bag.m: ditto
|
||||
* Source/BinaryCStream.m: ditto
|
||||
* Source/BinaryTree.m: ditto
|
||||
* Source/BinaryTreeNode.m: ditto
|
||||
* Source/CircularArray.m: ditto
|
||||
* Source/Coder.m: ditto
|
||||
* Source/Collection.m: ditto
|
||||
* Source/CStream.m: ditto
|
||||
* Source/Decoder.m: ditto
|
||||
* Source/DelegatePool.m: ditto
|
||||
* Source/Dictionary.m: ditto
|
||||
* Source/Encoder.m: ditto
|
||||
* Source/GapArray.m: ditto
|
||||
* Source/Heap.m: ditto
|
||||
* Source/IndexedCollection.m: ditto
|
||||
* Source/Invocation.m: ditto
|
||||
* Source/KeyedCollection.m: ditto
|
||||
* Source/LinkedList.m: ditto
|
||||
* Source/LinkedListNode.m: ditto
|
||||
* Source/Magnitude.m: ditto
|
||||
* Source/MappedCollector.m: ditto
|
||||
* Source/MemoryStream.m: ditto
|
||||
* Source/OldNSConnection.m: ditto
|
||||
* Source/OldNSPortCoder.m: ditto
|
||||
* Source/OrderedCollection.m: ditto
|
||||
* Source/Port.m: ditto
|
||||
* Source/Queue.m: ditto
|
||||
* Source/Random.m: ditto
|
||||
* Source/RawCStream.m: ditto
|
||||
* Source/RBTree.m: ditto
|
||||
* Source/RBTreeNode.m: ditto
|
||||
* Source/RNGAdditiveCongruential.m: ditto
|
||||
* Source/RNGBerkeley.m: ditto
|
||||
* Source/Set.m: ditto
|
||||
* Source/SplayTree.m: ditto
|
||||
* Source/Stack.m: ditto
|
||||
* Source/StdioStream.m: ditto
|
||||
* Source/Stream.m: ditto
|
||||
* Source/TcpPort.m: ditto
|
||||
* Source/TextCStream.m: ditto
|
||||
* Source/UdpPort.m: ditto
|
||||
* Testing/cstream.m: ditto
|
||||
* Testing/invocation_char.m: ditto
|
||||
* Testing/invocation_int.m: ditto
|
||||
* Testing/invocation_long.m: ditto
|
||||
* Testing/invocation.m: ditto
|
||||
* Testing/invocation_short.m: ditto
|
||||
* Testing/ostream.h: ditto
|
||||
* Testing/ostream.m: ditto
|
||||
* Testing/pipes.m: ditto
|
||||
|
||||
2000-08-07 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Merge 0.6.6 branch into main.
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/* Interface for GNU Objective-C binary stream object for use serializing
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __BinaryCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __BinaryCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStream.h>
|
||||
|
||||
@interface BinaryCStream : CStream
|
||||
{
|
||||
unsigned char _sizeof_long;
|
||||
unsigned char _sizeof_int;
|
||||
unsigned char _sizeof_short;
|
||||
unsigned char _sizeof_char;
|
||||
}
|
||||
|
||||
+ setDebugging: (BOOL)f;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __BinaryCStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,62 +0,0 @@
|
|||
/* Interface for GNU Objective-C stream object for use in archiving
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __CStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStreaming.h>
|
||||
|
||||
@interface CStream : Stream <CStreaming>
|
||||
{
|
||||
Stream *stream;
|
||||
int format_version;
|
||||
int indentation;
|
||||
}
|
||||
|
||||
/* These are the standard ways to create a new CStream from a Stream
|
||||
that is open for reading.
|
||||
It reads the CStream signature at the beginning of the file, and
|
||||
automatically creates the appropriate subclass of CStream with
|
||||
the correct format version. */
|
||||
+ cStreamReadingFromFile: (NSString*) filename;
|
||||
+ cStreamReadingFromStream: (id <Streaming>) stream;
|
||||
|
||||
/* These are standard ways to create a new CStream with a Stream
|
||||
that is open for writing. */
|
||||
- initForWritingToFile: (NSString*) filename;
|
||||
- initForWritingToStream: (id <Streaming>) stream;
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version;
|
||||
|
||||
+ cStreamWritingToStream: (id <Streaming>) stream;
|
||||
+ cStreamWritingToFile: (NSString*) filename;
|
||||
|
||||
/* This is the designated initializer for reading. Don't call it yourself. */
|
||||
- _initForReadingFromPostSignatureStream: (id <Streaming>)s
|
||||
withFormatVersion: (int)version;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __CStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,59 +0,0 @@
|
|||
/* Protocol for GNU Objective C byte streams that can code C types and indentn
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: April 1995
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __CStreaming_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __CStreaming_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Streaming.h>
|
||||
|
||||
@protocol CStreaming <Streaming>
|
||||
|
||||
- (void) encodeValueOfCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name;
|
||||
- (void) decodeValueOfCType: (const char*) type
|
||||
at: (void*) d
|
||||
withName: (NSString* *) namePtr;
|
||||
|
||||
- (void) encodeWithName: (NSString*) name
|
||||
valuesOfCTypes: (const char *) types, ...;
|
||||
- (void) decodeWithName: (NSString* *)name
|
||||
valuesOfCTypes: (const char *)types, ...;
|
||||
|
||||
- (void) encodeName: (NSString*) name;
|
||||
- (void) decodeName: (NSString* *) name;
|
||||
|
||||
- (void) encodeIndent;
|
||||
- (void) decodeIndent;
|
||||
|
||||
- (void) encodeUnindent;
|
||||
- (void) decodeUnindent;
|
||||
|
||||
- (id <Streaming>) stream;
|
||||
|
||||
+ (int) defaultFormatVersion;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __CStreaming_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
/* Interface for GNU Objective-C coder object for use serializing
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Coder_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Coder_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coding.h>
|
||||
#include <base/Streaming.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
@class CStream;
|
||||
|
||||
|
||||
/* The root abstract class for archiving */
|
||||
|
||||
@interface Coder : NSObject
|
||||
{
|
||||
@public
|
||||
int format_version;
|
||||
CStream *cstream;
|
||||
NSMapTable *classname_2_classname; /* for changing class names on r/w */
|
||||
int interconnect_stack_height; /* number of nested root objects */
|
||||
}
|
||||
|
||||
+ setDebugging: (BOOL)f;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* An abstract class for writing an archive */
|
||||
|
||||
@interface Encoder : Coder
|
||||
{
|
||||
@public
|
||||
/* xxx in_progress_table should actually be an NSHashTable,
|
||||
but we are working around a bug right now. */
|
||||
NSMapTable *in_progress_table; /* objects begun writing, but !finished */
|
||||
NSMapTable *object_2_xref; /* objects already written */
|
||||
NSMapTable *object_2_fref; /* table of forward references */
|
||||
NSMapTable *const_ptr_2_xref; /* const pointers already written */
|
||||
unsigned fref_counter; /* Keep track of unused fref numbers */
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename;
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withCStreamClass: (Class) cStreamClass;
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class)scc
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion;
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s;
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withCStreamClass: (Class) cStreamClass;
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class) cStreamClass
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion;
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toFile: (NSString*) filename;
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toStream: (id <Streaming>)stream;
|
||||
|
||||
/* Defaults */
|
||||
+ (void) setDefaultStreamClass: sc;
|
||||
+ defaultStreamClass;
|
||||
+ (void) setDefaultCStreamClass: sc;
|
||||
+ defaultCStreamClass;
|
||||
+ (void) setDefaultFormatVersion: (int)fv;
|
||||
+ (int) defaultFormatVersion;
|
||||
|
||||
@end
|
||||
|
||||
@interface Encoder (Encoding) <Encoding>
|
||||
@end
|
||||
|
||||
|
||||
|
||||
/* An abstract class for reading an archive. */
|
||||
|
||||
@interface Decoder : Coder
|
||||
{
|
||||
NSZone *zone; /* zone in which to create objects */
|
||||
id xref_2_object; /* objects already read */
|
||||
id xref_2_object_root; /* objs read since last -startDecodoingI.. */
|
||||
NSMapTable *xref_2_const_ptr; /* const pointers already written */
|
||||
NSMapTable *fref_2_object; /* table of forward references */
|
||||
NSMapTable *address_2_fref; /* table of forward references */
|
||||
}
|
||||
|
||||
/* These are class methods (and not instance methods) because the
|
||||
header of the file or stream determines which subclass of Decoder
|
||||
is created. */
|
||||
|
||||
+ newReadingFromFile: (NSString*) filename;
|
||||
+ newReadingFromStream: (id <Streaming>)stream;
|
||||
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromFile: (NSString*) filename;
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromStream: (id <Streaming>)stream;
|
||||
|
||||
@end
|
||||
|
||||
@interface Decoder (Decoding) <Decoding>
|
||||
@end
|
||||
|
||||
|
||||
/* Extensions to NSObject for encoding and decoding. */
|
||||
|
||||
@interface NSObject (OptionalNewWithCoder)
|
||||
+ newWithCoder: (Coder*)aDecoder;
|
||||
@end
|
||||
|
||||
GS_EXPORT id CoderSignatureMalformedException;
|
||||
|
||||
#endif /* __Coder_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,66 +0,0 @@
|
|||
/* Private interface for GNU Objective-C coder object for use serializing
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __CoderPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __CoderPrivate_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coder.h>
|
||||
#include <base/CStreaming.h>
|
||||
|
||||
enum {
|
||||
CODER_OBJECT_NIL = 0,
|
||||
CODER_OBJECT,
|
||||
CODER_OBJECT_ROOT,
|
||||
CODER_OBJECT_REPEATED,
|
||||
CODER_OBJECT_FORWARD_REFERENCE,
|
||||
CODER_OBJECT_CLASS,
|
||||
CODER_CLASS_NIL,
|
||||
CODER_CLASS,
|
||||
CODER_CLASS_REPEATED,
|
||||
CODER_CONST_PTR_NULL,
|
||||
CODER_CONST_PTR,
|
||||
CODER_CONST_PTR_REPEATED
|
||||
};
|
||||
|
||||
#define DOING_ROOT_OBJECT (interconnect_stack_height != 0)
|
||||
|
||||
@interface Coder (Private)
|
||||
- _initWithCStream: (id <CStreaming>) cs formatVersion: (int) version;
|
||||
- (unsigned) _coderReferenceForObject: anObject;
|
||||
@end
|
||||
|
||||
#define SIGNATURE_FORMAT_STRING \
|
||||
@"GNU Objective C (%s %d.%d.%d) [%s %d]\n"
|
||||
|
||||
#define WRITE_SIGNATURE_FORMAT_ARGS \
|
||||
STRINGIFY(GNUSTEP_BASE_PACKAGE_NAME), \
|
||||
GNUSTEP_BASE_MAJOR_VERSION, \
|
||||
GNUSTEP_BASE_MINOR_VERSION, \
|
||||
GNUSTEP_BASE_SUBMINOR_VERSION, \
|
||||
[self defaultDecoderClassname], \
|
||||
format_version
|
||||
|
||||
|
||||
#define NO_SEL_TYPES "none"
|
||||
|
||||
#endif /* __CoderPrivate_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,165 +0,0 @@
|
|||
/* Protocol for GNU Objective-C objects that can write/read to a coder
|
||||
Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Coding_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Coding_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
/* #include <base/String.h>
|
||||
xxx Think about trying to get <String> back in types,
|
||||
but now there is a circular dependancy in the include files. */
|
||||
|
||||
@protocol CommonCoding
|
||||
- (BOOL) isDecoding;
|
||||
- (void) close;
|
||||
- (BOOL) isClosed;
|
||||
+ (int) defaultFormatVersion;
|
||||
- cStream;
|
||||
@end
|
||||
|
||||
@protocol Encoding <CommonCoding>
|
||||
|
||||
- (void) encodeValueOfObjCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeWithName: (id /*<String>*/)name
|
||||
valuesOfObjCTypes: (const char *)types, ...;
|
||||
|
||||
- (void) encodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (const void *)d
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) encodeBycopyObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) encodeByrefObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeRootObject: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) encodeObjectReference: anObj
|
||||
withName: (id /*<String>*/)name;
|
||||
- (void) startEncodingInterconnectedObjects;
|
||||
- (void) finishEncodingInterconnectedObjects;
|
||||
|
||||
- (void) encodeAtomicString: (const char*)sp
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
- (void) encodeClass: aClass;
|
||||
|
||||
/* For inserting a name into a TextCoder stream */
|
||||
- (void) encodeName: (id /*<String>*/) n;
|
||||
|
||||
/* For classes that want to keep track of recursion */
|
||||
- (void) encodeIndent;
|
||||
- (void) encodeUnindent;
|
||||
|
||||
- (void) encodeBytes: (const void *)b
|
||||
count: (unsigned)c
|
||||
withName: (id /*<String>*/)name;
|
||||
|
||||
@end
|
||||
|
||||
@protocol Decoding <CommonCoding>
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (id /*<String>*/ *) namePtr;
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (id /*<String>*/ *) namePtr;
|
||||
|
||||
- (void) decodeWithName: (id /*<String>*/*)name
|
||||
valuesOfObjCTypes: (const char *) types, ...;
|
||||
|
||||
- (void) decodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (void *)d
|
||||
withName: (id /*<String>*/*)name;
|
||||
|
||||
- (void) decodeObjectAt: (id*)anObjPtr
|
||||
withName: (id /*<String>*/*)name;
|
||||
|
||||
- (void) startDecodingInterconnectedObjects;
|
||||
- (void) finishDecodingInterconnectedObjects;
|
||||
|
||||
- (const char *) decodeAtomicStringWithName: (id /*<String>*/*) name;
|
||||
|
||||
- decodeClass;
|
||||
|
||||
/* For inserting a name into a TextCoder stream */
|
||||
- (void) decodeName: (id /*<String>*/ *)n;
|
||||
|
||||
/* For classes that want to keep track of recursion */
|
||||
- (void) decodeIndent;
|
||||
- (void) decodeUnindent;
|
||||
|
||||
- (void) decodeBytes: (void *)b
|
||||
count: (unsigned)c
|
||||
withName: (id /*<String>*/ *) name;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSObject (SelfCoding)
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)anEncoder;
|
||||
- (id) initWithCoder: (id <Decoding>)aDecoder;
|
||||
+ (id) newWithCoder: (id <Decoding>)aDecoder;
|
||||
|
||||
/* NOTE:
|
||||
|
||||
If the class responds to +newWithCoder Coder will send it for
|
||||
decoding, otherwise Coder will allocate the object itself and send
|
||||
initWithCoder instead.
|
||||
|
||||
+newWithCoder is useful because many classes keep track of their
|
||||
instances and only allow one instance of each configuration. For
|
||||
example, see the designated initializers of SocketPort, Connection,
|
||||
and Proxy.
|
||||
|
||||
Using +new.. instead of -init.. prevents us from having to waste
|
||||
the effort of allocating space for an object to be decoded, then
|
||||
immediately deallocating that space because we're just returning a
|
||||
pre-existing object.
|
||||
|
||||
The newWithCoder and initWithCoder methods must return the decoded
|
||||
object.
|
||||
|
||||
This is not a Protocol, because objects are not required to
|
||||
implement newWithCoder or initWithCoder. They probably want to
|
||||
implement one of them, though.
|
||||
|
||||
-mccallum */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Coding_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,36 +0,0 @@
|
|||
/* Protocol for GNU Objective C invocations
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: February 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Enumerating_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __Enumerating_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
@protocol Enumerating <NSObject>
|
||||
|
||||
- initWithCollection: aCollection;
|
||||
- nextObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Enumerating_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/* Protocol for GNU Objective-C mutex locks
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Locking_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Locking_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <objc/Protocol.h>
|
||||
|
||||
@protocol Locking
|
||||
- (void) lock;
|
||||
- (void) unlock;
|
||||
@end
|
||||
|
||||
#endif /* __Locking_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,39 +0,0 @@
|
|||
/* Interface for Mach-port based object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __MachPort_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __MachPort_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#if __mach__
|
||||
|
||||
#include <base/Port.h>
|
||||
|
||||
@interface MachInPort : InPort
|
||||
@end
|
||||
|
||||
@interface MachOutPort : OutPort
|
||||
@end
|
||||
|
||||
#endif /* __mach__ */
|
||||
|
||||
#endif /* __MachPort_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,90 +0,0 @@
|
|||
/* Interface for GNU Objective C memory stream
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
||||
Date: September 1997
|
||||
|
||||
Modifications to use NSData and NSMutable data objects to hold data.
|
||||
*/
|
||||
|
||||
#ifndef __MemoryStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __MemoryStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/Streaming.h>
|
||||
|
||||
/* This protocol is preliminary and may change.
|
||||
This also may get pulled out into a separate .h file. */
|
||||
|
||||
@protocol MemoryStreaming <Streaming>
|
||||
|
||||
- initWithCapacity: (unsigned)capacity;
|
||||
|
||||
- (void) setStreamBufferCapacity: (unsigned)s;
|
||||
|
||||
- (char*) streamBuffer;
|
||||
- (unsigned) streamBufferCapacity;
|
||||
- (unsigned) streamEofPosition;
|
||||
|
||||
@end
|
||||
|
||||
@interface MemoryStream : Stream <MemoryStreaming>
|
||||
{
|
||||
id data;
|
||||
int prefix;
|
||||
int position;
|
||||
int eof_position;
|
||||
BOOL isMutable;
|
||||
}
|
||||
|
||||
+ (MemoryStream*)streamWithData: (id)anObject;
|
||||
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
prefix: (unsigned)prefix;
|
||||
- initWithData: (id)anObject;
|
||||
|
||||
#if 0
|
||||
- initWithSize: (unsigned)s; /* For backwards compatibility, depricated */
|
||||
#endif
|
||||
|
||||
- (id) data;
|
||||
- (id) mutableData;
|
||||
- (unsigned) streamBufferPrefix;
|
||||
- (unsigned) streamBufferLength; /* prefix + eofPosition */
|
||||
|
||||
/* xxx This interface will change */
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* reset for this position */
|
||||
position: (unsigned)i; /* current position for reading/writing */
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
freeWhenDone: (BOOL)f
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* reset for this position */
|
||||
position: (unsigned)i; /* current position for reading/writing */
|
||||
@end
|
||||
|
||||
#endif /* __MemoryStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,47 +0,0 @@
|
|||
/* Protocol for Objective-C objects that can be ordered.
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Ordering_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Ordering_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <objc/objc.h>
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol Ordering
|
||||
|
||||
- (int) compare: anObject;
|
||||
|
||||
- (BOOL) greaterThan: anObject;
|
||||
- (BOOL) greaterThanOrEqual: anObject;
|
||||
|
||||
- (BOOL) lessThan: anObject;
|
||||
- (BOOL) lessThanOrEqual: anObject;
|
||||
|
||||
- (BOOL) between: firstObject and: secondObject;
|
||||
|
||||
- maximum: anObject;
|
||||
- minimum: anObject;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Ordering_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,119 +0,0 @@
|
|||
/* Interface for abstract superclass port for use with Connection
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Port_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Port_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Coding.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <Foundation/NSPort.h>
|
||||
#include <Foundation/NSDate.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
/* xxx Use something like this? */
|
||||
@protocol PacketSending
|
||||
@end
|
||||
|
||||
@interface Port : NSPort
|
||||
{
|
||||
}
|
||||
- (void) close;
|
||||
|
||||
+ (Class) outPacketClass;
|
||||
- (Class) outPacketClass;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface InPort : Port
|
||||
{
|
||||
id _packet_invocation;
|
||||
}
|
||||
|
||||
+ newForReceiving;
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name;
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name fromPort: (int)port;
|
||||
|
||||
/* Register/Unregister this port for input handling through RunLoop
|
||||
RUN_LOOP in mode MODE. */
|
||||
- (void) addToRunLoop: run_loop forMode: (NSString*)mode;
|
||||
- (void) removeFromRunLoop: run_loop forMode: (NSString*)mode;
|
||||
|
||||
/* When a RunLoop is handling this InPort, and a new incoming
|
||||
packet arrives, INVOCATION will be invoked with the new packet
|
||||
as an argument. The INVOCATION is responsible for releasing
|
||||
the packet. */
|
||||
- (void) setReceivedPacketInvocation: (id)invocation;
|
||||
|
||||
/* An alternative to the above way for receiving packets from this port.
|
||||
Get a packet from the net and return it. If no packet is received
|
||||
within MILLISECONDS, then return nil. The caller is responsible
|
||||
for releasing the packet. */
|
||||
- receivePacketWithTimeout: (int)milliseconds;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OutPort : Port
|
||||
|
||||
+ newForSendingToRegisteredName: (NSString*)name
|
||||
onHost: (NSString*)hostname;
|
||||
- (BOOL) sendPacket: packet timeout: (NSTimeInterval)t;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* Objects for holding incoming/outgoing data to/from ports. */
|
||||
|
||||
@interface InPacket : MemoryStream
|
||||
{
|
||||
id _receiving_in_port;
|
||||
id _reply_out_port;
|
||||
}
|
||||
|
||||
- replyOutPort;
|
||||
- receivingInPort;
|
||||
|
||||
/* Do not call this method yourself; it is to be called by subclassers.
|
||||
InPackets are created for you by the InPort object, and are
|
||||
made available as the argument to the received packet invocation. */
|
||||
- initForReceivingWithCapacity: (unsigned)s
|
||||
receivingInPort: ip
|
||||
replyOutPort: op;
|
||||
|
||||
@end
|
||||
|
||||
@interface OutPacket : MemoryStream
|
||||
{
|
||||
id _reply_in_port;
|
||||
}
|
||||
|
||||
- initForSendingWithCapacity: (unsigned)c
|
||||
replyInPort: p;
|
||||
- replyInPort;
|
||||
|
||||
+ (unsigned) prefixSize;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Port_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,36 +0,0 @@
|
|||
/* Interface for GNU Objective-C raw stream object for archiving
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __RawCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __RawCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStream.h>
|
||||
|
||||
@interface RawCStream : CStream
|
||||
|
||||
+ setDebugging: (BOOL)f;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __RawCStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,100 +0,0 @@
|
|||
/* Protocol for GNU Objective-C objects that can keep a retain count.
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Retaining_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __Retaining_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol Retaining
|
||||
|
||||
- retain;
|
||||
|
||||
/* Use this message when the sender did not allocate the receiving
|
||||
object, but the sender wants to keep a reference to the receiving
|
||||
object. It increments a reference count for the object. The
|
||||
object will not be deallocated until after a matching release
|
||||
message is sent to this object.
|
||||
|
||||
IMPORTANT PROGRAMMING CONVENTION: There is no need to send this
|
||||
message to objects that the sender allocated---allocating an object
|
||||
already implies that the object will not be deallocated until the
|
||||
sender releases it. Just as "retain" and "release" messages cancel
|
||||
each other, one "release" message is needed to cancel the original
|
||||
allocation. */
|
||||
|
||||
|
||||
- (oneway void) release;
|
||||
|
||||
/* Use this message when the sender is done with the receiving object.
|
||||
If the sender had the last reference to the object, the object will
|
||||
be deallocated by sending "dealloc" to it.
|
||||
|
||||
IMPORTANT PROGRAMMING CONVENTION: The sender should only send this
|
||||
to objects that it has allocated or has retain'ed. */
|
||||
|
||||
|
||||
- (void) dealloc;
|
||||
|
||||
/* This method deallocates the memory for this object. You should not
|
||||
send this message yourself; it is sent for you by the release
|
||||
method, which properly manages retain counts. Do, however,
|
||||
override this method to deallocate any memory allocated by this
|
||||
object during initialization; the overriding method should call
|
||||
[super dealloc] at the end. */
|
||||
|
||||
|
||||
- (unsigned) retainCount;
|
||||
|
||||
/* This method returns the retain count to this object. It does
|
||||
not, however, include the decrements due to stackRelease's. Note
|
||||
that the returned number is not quite a "reference count" in the
|
||||
traditional sense; it is less by one in that it is actually a count
|
||||
of the number of unreleased retain messages sent. A retainCount of
|
||||
zero implies that there is still one more release necessary to
|
||||
deallocate the receiver. For example, after an object is created,
|
||||
its retainCount is zero, but another "release" message is still
|
||||
required before the object will be deallocated. */
|
||||
|
||||
|
||||
- autorelease;
|
||||
|
||||
/* Use this message when the sender is done with this object, but the
|
||||
sender doesn't want the object to be deallocated immediately
|
||||
because the function that sends this message will use this object
|
||||
as its return value. The object will be queued to receive the
|
||||
actual "release" message later.
|
||||
|
||||
Due to this delayed release, the function that receives the object
|
||||
as a return value will have the opportunity to retain the object
|
||||
before the "release" instigated by the "autorelease" actually
|
||||
takes place.
|
||||
|
||||
For the object to be autoreleased, you must have previously created
|
||||
a AutoreleasePool or an AutoreleaseStack. If you don't, however,
|
||||
your program won't crash, the release corresponding to the
|
||||
autorelease will just never happen. */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Retaining_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,55 +0,0 @@
|
|||
/* Interface for GNU Objective C stdio stream
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __StdioStream_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __StdioStream_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@interface StdioStream : Stream
|
||||
{
|
||||
int mode;
|
||||
FILE *fp;
|
||||
}
|
||||
|
||||
+ standardIn;
|
||||
+ standardOut;
|
||||
+ standardError;
|
||||
|
||||
+ streamWithFilename: (NSString*)name fmode: (const char *)m;
|
||||
/* xxx Add the others too. */
|
||||
|
||||
- initWithFilePointer: (FILE*)afp fmode: (const char *)m;
|
||||
- initWithFilename: (NSString*)name fmode: (const char *)m;
|
||||
- initWithFileDescriptor: (int)fd fmode: (const char *)m;
|
||||
|
||||
- initWithPipeTo: (NSString*)systemCommand;
|
||||
- initWithPipeFrom: (NSString*)systemCommand;
|
||||
|
||||
- (void) rewindStream;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __StdioStream_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* Interface for GNU Objective C byte stream
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Stream_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __Stream_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Streaming.h>
|
||||
|
||||
GS_EXPORT NSString* StreamException;
|
||||
|
||||
@interface Stream : NSObject <Streaming>
|
||||
|
||||
- init;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __Stream_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* Protocol for GNU Objective C byte streams
|
||||
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: April 1995
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __Streaming_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __Streaming_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@protocol Streaming <NSObject>
|
||||
|
||||
- (int) writeByte: (unsigned char)b;
|
||||
- (int) readByte: (unsigned char*)b;
|
||||
|
||||
- (int) writeBytes: (const void*)b length: (int)l;
|
||||
- (int) readBytes: (void*)b length: (int)l;
|
||||
|
||||
- (int) writeFormat: (NSString*)format, ...;
|
||||
- (int) readFormat: (NSString*)format, ...;
|
||||
- (int) writeFormat: (NSString*)format arguments: (va_list)arg;
|
||||
- (int) readFormat: (NSString*)format arguments: (va_list)arg;
|
||||
|
||||
- (void) writeLine: (NSString*)l;
|
||||
- (NSString*) readLine;
|
||||
|
||||
- (unsigned) streamPosition;
|
||||
- (BOOL) isAtEof;
|
||||
- (void) flushStream;
|
||||
|
||||
/* We must separate the idea of "closing" a stream and "deallocating" a
|
||||
stream because of delays in deallocation due to -autorelease. */
|
||||
- (void) close;
|
||||
- (BOOL) isClosed;
|
||||
|
||||
- (BOOL) isWritable;
|
||||
|
||||
@end
|
||||
|
||||
typedef enum _seek_mode_t
|
||||
{
|
||||
STREAM_SEEK_FROM_START,
|
||||
STREAM_SEEK_FROM_CURRENT,
|
||||
STREAM_SEEK_FROM_END
|
||||
} seek_mode_t;
|
||||
|
||||
@protocol SeekableStreaming
|
||||
|
||||
- (void) rewindStream;
|
||||
- (void) setStreamPosition: (unsigned)i;
|
||||
- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)mode;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif /* __Streaming_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
/* Interface for stream based on TCP sockets
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TcpPort_h__GNUSTEP_BASE_INCLUDE
|
||||
#define __TcpPort_h__GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Port.h>
|
||||
#include <Foundation/NSRunLoop.h>
|
||||
#ifdef __MINGW32__
|
||||
# include <winsock.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#include <Foundation/NSMapTable.h>
|
||||
|
||||
/* A concrete implementation of a Port object implemented on top of
|
||||
SOCK_STREAM connections. */
|
||||
|
||||
@interface TcpInPort : InPort
|
||||
{
|
||||
int _port_socket;
|
||||
struct sockaddr_in _listening_address;
|
||||
NSMapTable *_client_sock_2_out_port;
|
||||
NSMapTable *_client_sock_2_packet;
|
||||
}
|
||||
|
||||
+ newForReceivingFromPortNumber: (unsigned short)n;
|
||||
|
||||
- (int) portNumber;
|
||||
- (id) connectedOutPorts;
|
||||
- (unsigned) numberOfConnectedOutPorts;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface TcpOutPort : OutPort
|
||||
{
|
||||
int _port_socket;
|
||||
/* This is actually the address of the listen()'ing socket of the remote
|
||||
TcpInPort we are connected to, not the address of the _port_socket ivar. */
|
||||
struct sockaddr_in _remote_in_port_address;
|
||||
/* This is the address of our remote peer socket. */
|
||||
struct sockaddr_in _peer_address;
|
||||
/* The TcpInPort that is polling our _port_socket with select(). */
|
||||
id _polling_in_port;
|
||||
}
|
||||
|
||||
+ newForSendingToPortNumber: (unsigned short)n
|
||||
onHost: (NSString*)hostname;
|
||||
- (int) portNumber;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* Holders of sent and received data. */
|
||||
|
||||
@interface TcpInPacket : InPacket
|
||||
@end
|
||||
@interface TcpOutPacket : OutPacket
|
||||
@end
|
||||
|
||||
|
||||
/* Notification Strings. */
|
||||
GS_EXPORT NSString *InPortClientBecameInvalidNotification;
|
||||
GS_EXPORT NSString *InPortAcceptedClientNotification;
|
||||
|
||||
#endif /* __TcpPort_h__GNUSTEP_BASE_INCLUDE */
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/* Interface for GNU Objective-C text stream object for use serializing
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TextCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __TextCStream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStream.h>
|
||||
|
||||
@interface TextCStream : CStream
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __TextCStream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,62 +0,0 @@
|
|||
/* Interface for socket-based port object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __UdpPort_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __UdpPort_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <base/Port.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef __MINGW32__
|
||||
# include <winsock.h>
|
||||
#else
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
@interface UdpInPort : InPort
|
||||
{
|
||||
int _port_socket;
|
||||
struct sockaddr_in _address;
|
||||
}
|
||||
|
||||
- (int) portNumber;
|
||||
- (int) socket;
|
||||
|
||||
@end
|
||||
|
||||
@interface UdpOutPort : OutPort
|
||||
{
|
||||
struct sockaddr_in _address;
|
||||
}
|
||||
|
||||
- (int) portNumber;
|
||||
- (NSString*) hostname;
|
||||
|
||||
@end
|
||||
|
||||
@interface UdpInPacket : InPacket
|
||||
@end
|
||||
@interface UdpOutPacket : OutPacket
|
||||
@end
|
||||
|
||||
#endif /* __UdpPort_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,50 +0,0 @@
|
|||
/* Protocol for Objective-C objects that hold numerical and/or string values.
|
||||
Copyright (C) 1993,1994 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: May 1993
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __ValueHolding_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __ValueHolding_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
/* protocol String; */
|
||||
|
||||
@protocol ValueGetting
|
||||
- (int) intValue;
|
||||
- (float) floatValue;
|
||||
- (double) doubleValue;
|
||||
- (const char *) cStringValue;
|
||||
- /* (NSString*) */ stringValue;
|
||||
@end
|
||||
|
||||
@protocol ValueSetting
|
||||
- (void) setIntValue: (int)anInt;
|
||||
- (void) setFloatValue: (float)aFloat;
|
||||
- (void) setDoubleValue: (double)aDouble;
|
||||
- (void) setCStringValue: (const char *)aCString;
|
||||
- (void) setStringValue: /* (NSString*) */ aString;
|
||||
@end
|
||||
|
||||
@protocol ValueHolding <ValueGetting, ValueSetting>
|
||||
@end
|
||||
|
||||
#endif /* __ValueHolding_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,84 +0,0 @@
|
|||
/* ostream.h - C-function interface to GNUstep Objective-C streams
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Adam Fedor <fedor@boulder.colorado.edu>
|
||||
Date: Jun 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef __objc_stream_h_GNUSTEP_BASE_INCLUDE
|
||||
#define __objc_stream_h_GNUSTEP_BASE_INCLUDE
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <objc/typedstream.h>
|
||||
#include <Foundation/NSObjCRuntime.h>
|
||||
|
||||
typedef struct _ostream
|
||||
{
|
||||
void* stream_obj;
|
||||
int flags;
|
||||
} ostream;
|
||||
|
||||
/* Access modes */
|
||||
#define OSTREAM_READONLY 1 /* read on stream only */
|
||||
#define OSTREAM_WRITEONLY 2 /* write on stream only */
|
||||
#define OSTREAM_READWRITE 4 /* do read & write */
|
||||
#define OSTREAM_APPEND 8 /* append (write at end of file) */
|
||||
|
||||
/* Seek modes */
|
||||
#define OSTREAM_SEEK_FROM_START 0
|
||||
#define OSTREAM_SEEK_FROM_CURRENT 1
|
||||
#define OSTREAM_SEEK_FROM_END 2
|
||||
|
||||
/* Private flags */
|
||||
#define OSTREAM_READFLAG 1 /* stream is for reading */
|
||||
#define OSTREAM_WRITEFLAG (1 << 1) /* stream is for writing */
|
||||
#define OSTREAM_ISBUFFER (1 << 2)
|
||||
#define OSTREAM_USER_OWNS_BUF (1 << 3)
|
||||
#define OSTREAM_CANSEEK (1 << 4)
|
||||
|
||||
GS_EXPORT int ostream_getc (ostream* s);
|
||||
GS_EXPORT void ostream_ungetc (ostream* s);
|
||||
GS_EXPORT int ostream_putc (ostream* s, int c);
|
||||
GS_EXPORT BOOL ostream_at_eos (ostream* s);
|
||||
GS_EXPORT char* ostream_gets (ostream* s, char* buf, int count);
|
||||
|
||||
GS_EXPORT int ostream_flush (ostream *s);
|
||||
GS_EXPORT void ostream_seek (ostream *s, long offset, int mode);
|
||||
GS_EXPORT long ostream_tell (ostream *s);
|
||||
GS_EXPORT int ostream_read (ostream* s, void* buf, int count);
|
||||
GS_EXPORT int ostream_write (ostream* s, const void* buf, int count);
|
||||
GS_EXPORT void ostream_printf (ostream *s, const char *format, ...);
|
||||
GS_EXPORT void ostream_vprintf (ostream *s, const char *format, va_list argList);
|
||||
GS_EXPORT int ostream_scanf (ostream *s, const char *format, ...);
|
||||
GS_EXPORT int ostream_vscanf (ostream *s, const char *format, va_list argList);
|
||||
|
||||
GS_EXPORT ostream *ostream_open_descriptor (int fd, int mode);
|
||||
GS_EXPORT ostream *ostream_open_memory (const char *addr, int size, int mode);
|
||||
GS_EXPORT ostream *ostream_map_file (const char *name, int mode);
|
||||
GS_EXPORT int ostream_save_to_file (ostream *s, const char *name);
|
||||
GS_EXPORT void ostream_get_memory_buffer (ostream *s, char **addr,
|
||||
int *len, int *maxlen);
|
||||
GS_EXPORT void ostream_close_memory (ostream *s, int option);
|
||||
GS_EXPORT void ostream_close (ostream *s);
|
||||
|
||||
#define OSTREAM_FREEBUFFER 0
|
||||
#define OSTREAM_TRUNCATEBUFFER 1
|
||||
#define OSTREAM_SAVEBUFFER 2
|
||||
|
||||
#endif /* __objc_stream_h_GNUSTEP_BASE_INCLUDE */
|
|
@ -1,646 +0,0 @@
|
|||
/* Implementation of GNU Objective-C binary stream object for use serializing
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/BinaryCStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSByteOrder.h>
|
||||
#include <math.h>
|
||||
#if HAVE_VALUES_H
|
||||
#include <values.h> // This gets BITSPERBYTE on Solaris
|
||||
#endif
|
||||
|
||||
#define PRE_SIZEOF_PREFIX_FORMAT_VERSION 0
|
||||
#define CURRENT_FORMAT_VERSION ((((GNUSTEP_BASE_MAJOR_VERSION * 100) + \
|
||||
GNUSTEP_BASE_MINOR_VERSION) * 100) + GNUSTEP_BASE_SUBMINOR_VERSION)
|
||||
#define DEFAULT_FORMAT_VERSION CURRENT_FORMAT_VERSION
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
/* The number of bytes used to encode the length of a _C_CHARPTR
|
||||
string that is encoded. */
|
||||
#define NUM_BYTES_STRING_LENGTH 4
|
||||
|
||||
/* The value by which we multiply a float or double in order to bring
|
||||
mantissa digits to the left-hand-side of the decimal point, so that
|
||||
we can extract them by assigning the float or double to an int. */
|
||||
#if !defined(BITSPERBYTE) && defined(NeXT)
|
||||
#include <mach/vm_param.h>
|
||||
#define BITSPERBYTE BYTE_SIZE
|
||||
#elif !defined(BITSPERBYTE)
|
||||
#define BITSPERBYTE 8 /* a safe guess? */
|
||||
#endif
|
||||
#define FLOAT_FACTOR ((double)(1 << ((sizeof(int)*BITSPERBYTE)-2)))
|
||||
|
||||
@implementation BinaryCStream
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [BinaryCStream class])
|
||||
/* Make sure that we don't overrun memory when reading _C_CHARPTR. */
|
||||
NSAssert (sizeof(unsigned) >= NUM_BYTES_STRING_LENGTH,
|
||||
@"_C_CHARPTR overruns memory");
|
||||
}
|
||||
|
||||
|
||||
/* For debugging */
|
||||
|
||||
static int debug_binary_coder = 0;
|
||||
|
||||
+ setDebugging: (BOOL)f
|
||||
{
|
||||
debug_binary_coder = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ debugStderrCoder
|
||||
{
|
||||
static id c = nil;
|
||||
|
||||
if (!c)
|
||||
c = [[TextCStream alloc]
|
||||
initForWritingToStream: [StdioStream standardError]];
|
||||
return c;
|
||||
}
|
||||
|
||||
/* This is the designated initializer for reading. */
|
||||
- _initForReadingFromPostSignatureStream: (id <Streaming>)s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[super _initForReadingFromPostSignatureStream: s
|
||||
withFormatVersion: version];
|
||||
if (version > PRE_SIZEOF_PREFIX_FORMAT_VERSION)
|
||||
{
|
||||
/* Read the C-type sizes to expect. */
|
||||
[s readByte: &_sizeof_long];
|
||||
[s readByte: &_sizeof_int];
|
||||
[s readByte: &_sizeof_short];
|
||||
[s readByte: &_sizeof_char];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This is a designated initializer for writing. */
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[super initForWritingToStream: s
|
||||
withFormatVersion: version];
|
||||
if (version > PRE_SIZEOF_PREFIX_FORMAT_VERSION)
|
||||
{
|
||||
[s writeByte: sizeof (long)];
|
||||
[s writeByte: sizeof (int)];
|
||||
[s writeByte: sizeof (short)];
|
||||
[s writeByte: sizeof (char)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (NSString*) name
|
||||
{
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
/* Make sure we're not being asked to encode an "ObjC" type. */
|
||||
NSAssert(*type != '@', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to encode an \"ObjC\" type");
|
||||
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType: type
|
||||
at: d
|
||||
withName: name];
|
||||
}
|
||||
|
||||
[stream writeByte: *type];
|
||||
|
||||
#define WRITE_SIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
_TYPE tmp; \
|
||||
char buffer[1+sizeof(_TYPE)]; \
|
||||
buffer[0] = sizeof (_TYPE); \
|
||||
if (*(_TYPE*)_PTR < 0) \
|
||||
{ \
|
||||
buffer[0] |= 0x80; \
|
||||
tmp = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
||||
memcpy (buffer+1, &tmp, sizeof(_TYPE)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tmp = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
memcpy (buffer+1, &tmp, sizeof(_TYPE)); \
|
||||
} \
|
||||
[stream writeBytes: buffer length: 1+sizeof(_TYPE)]; \
|
||||
}
|
||||
|
||||
#define WRITE_SIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
_TYPE tmp; \
|
||||
char buffer[sizeof(_TYPE)]; \
|
||||
if (*(_TYPE*)_PTR < 0) \
|
||||
{ \
|
||||
tmp = _CONV_FUNC (- *(_TYPE*)_PTR); \
|
||||
memcpy (buffer, &tmp, sizeof(_TYPE)); \
|
||||
NSAssert(!(buffer[0] & 0x80), @"high bit set"); \
|
||||
buffer[0] |= 0x80; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tmp = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
memcpy (buffer, &tmp, sizeof(_TYPE)); \
|
||||
} \
|
||||
[stream writeBytes: buffer length: sizeof(_TYPE)]; \
|
||||
}
|
||||
|
||||
#define WRITE_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
WRITE_SIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
WRITE_SIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
#define READ_SIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
char sign, size; \
|
||||
[stream readByte: &size]; \
|
||||
sign = size & 0x80; \
|
||||
size &= ~0x80; \
|
||||
{ \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size");\
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
if (sign) \
|
||||
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_SIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
int size = _sizeof_ ## _TYPE; \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
int sign; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
/* xxx Remove this next requirement eventually */ \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size"); \
|
||||
sign = buffer[0] & 0x80; \
|
||||
buffer[0] &= ~0x80; \
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
if (sign) \
|
||||
*(_TYPE*)_PTR = - *(_TYPE*)_PTR; \
|
||||
}
|
||||
|
||||
#define READ_SIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
READ_SIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
READ_SIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
/* Reading and writing unsigned scalar types. */
|
||||
|
||||
#define WRITE_UNSIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
_TYPE tmp; \
|
||||
char buffer[1+sizeof(_TYPE)]; \
|
||||
buffer[0] = sizeof (_TYPE); \
|
||||
tmp = _CONV_FUNC (*(_TYPE*)_PTR); \
|
||||
memcpy (buffer+1, &tmp, sizeof(_TYPE)); \
|
||||
[stream writeBytes: buffer length: (1+sizeof(_TYPE))]; \
|
||||
}
|
||||
|
||||
#define WRITE_UNSIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
unsigned _TYPE tmp; \
|
||||
char buffer[sizeof(unsigned _TYPE)]; \
|
||||
tmp = _CONV_FUNC (*(unsigned _TYPE*)_PTR); \
|
||||
memcpy (buffer, &tmp, sizeof(unsigned _TYPE)); \
|
||||
[stream writeBytes: buffer length: (sizeof(unsigned _TYPE))]; \
|
||||
}
|
||||
|
||||
#define WRITE_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
WRITE_UNSIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
WRITE_UNSIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE0(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
char size; \
|
||||
[stream readByte: &size]; \
|
||||
{ \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size");\
|
||||
*(_TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(_TYPE*)buffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE1(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
int size = _sizeof_ ## _TYPE; \
|
||||
char buffer[size]; \
|
||||
int read_size; \
|
||||
read_size = [stream readBytes: buffer length: size]; \
|
||||
NSAssert (read_size == size, @"expected more input"); \
|
||||
/* xxx Remove this next requirement eventually */ \
|
||||
NSAssert (size == sizeof(_TYPE), @"inconsistent size"); \
|
||||
*(unsigned _TYPE*)_PTR = \
|
||||
_CONV_FUNC (*(unsigned _TYPE*)buffer); \
|
||||
}
|
||||
|
||||
#define READ_UNSIGNED_TYPE(_PTR, _TYPE, _CONV_FUNC) \
|
||||
{ \
|
||||
if (format_version == PRE_SIZEOF_PREFIX_FORMAT_VERSION) \
|
||||
READ_UNSIGNED_TYPE0 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
else \
|
||||
READ_UNSIGNED_TYPE1 (_PTR, _TYPE, _CONV_FUNC) \
|
||||
}
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
unsigned length = strlen (*(char**)d);
|
||||
unsigned nlength;
|
||||
nlength = NSSwapHostIntToBig (length);
|
||||
[stream writeBytes: &nlength
|
||||
length: NUM_BYTES_STRING_LENGTH];
|
||||
[stream writeBytes: *(char**)d
|
||||
length: length];
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream writeByte: *(unsigned char*)d];
|
||||
break;
|
||||
|
||||
/* Reading and writing signed scalar types. */
|
||||
|
||||
case _C_SHT:
|
||||
WRITE_SIGNED_TYPE (d, short, NSSwapHostShortToBig);
|
||||
break;
|
||||
case _C_USHT:
|
||||
WRITE_UNSIGNED_TYPE (d, short, NSSwapHostShortToBig);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
WRITE_SIGNED_TYPE (d, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
case _C_UINT:
|
||||
WRITE_UNSIGNED_TYPE (d, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
WRITE_SIGNED_TYPE (d, long, NSSwapHostLongToBig);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
WRITE_UNSIGNED_TYPE (d, long, NSSwapHostLongToBig);
|
||||
break;
|
||||
|
||||
/* xxx The handling of floats and doubles could be improved.
|
||||
e.g. I should account for varying sizeof(int) vs sizeof(double). */
|
||||
|
||||
case _C_FLT:
|
||||
{
|
||||
float fvalue;
|
||||
double value;
|
||||
int exponent, mantissa;
|
||||
short exponent_encoded;
|
||||
|
||||
memcpy (&fvalue, d, sizeof (float));
|
||||
value = fvalue;
|
||||
/* Get the exponent */
|
||||
value = frexp (value, &exponent);
|
||||
exponent_encoded = exponent;
|
||||
NSParameterAssert (exponent_encoded == exponent);
|
||||
/* Get the mantissa. */
|
||||
value *= FLOAT_FACTOR;
|
||||
mantissa = value;
|
||||
NSAssert (value - mantissa == 0,
|
||||
@"mantissa and value should be the same");
|
||||
/* Encode the value as its two integer components. */
|
||||
WRITE_SIGNED_TYPE (&exponent_encoded, short, NSSwapHostShortToBig);
|
||||
WRITE_SIGNED_TYPE (&mantissa, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_DBL:
|
||||
{
|
||||
double value;
|
||||
int exponent, mantissa1, mantissa2;
|
||||
short exponent_encoded;
|
||||
|
||||
memcpy (&value, d, sizeof (double));
|
||||
/* Get the exponent */
|
||||
value = frexp (value, &exponent);
|
||||
exponent_encoded = exponent;
|
||||
NSParameterAssert (exponent_encoded == exponent);
|
||||
/* Get the first part of the mantissa. */
|
||||
value *= FLOAT_FACTOR;
|
||||
mantissa1 = value;
|
||||
value -= mantissa1;
|
||||
value *= FLOAT_FACTOR;
|
||||
mantissa2 = value;
|
||||
NSAssert (value - mantissa2 == 0,
|
||||
@"mantissa2 and value should be the same");
|
||||
/* Encode the value as its three integer components. */
|
||||
WRITE_SIGNED_TYPE (&exponent_encoded, short, NSSwapHostShortToBig);
|
||||
WRITE_SIGNED_TYPE (&mantissa1, int, NSSwapHostIntToBig);
|
||||
WRITE_SIGNED_TYPE (&mantissa2, int, NSSwapHostIntToBig);
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi (type+1); /* xxx why +1 ? */
|
||||
int offset;
|
||||
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
while (len-- > 0)
|
||||
{
|
||||
/* Change this so we don't re-write type info every time. */
|
||||
/* xxx We should be able to encode arrays "ObjC" types also! */
|
||||
[self encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"array component"];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
[self encodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
/* xxx We should be able to encode structs "ObjC" types also! */
|
||||
[self encodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:@"structure component"];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
[self encodeUnindent];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Unrecognized type %s", type];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
char encoded_type;
|
||||
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to decode an \"ObjC\" type");
|
||||
|
||||
[stream readByte: &encoded_type];
|
||||
if (encoded_type != *type
|
||||
&& !((encoded_type=='c' || encoded_type=='C')
|
||||
&& (*type=='c' || *type=='C')))
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Expected type \"%c\", got type \"%c\"",
|
||||
*type, encoded_type];
|
||||
|
||||
switch (encoded_type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
unsigned length;
|
||||
unsigned read_count;
|
||||
read_count = [stream readBytes: &length
|
||||
length: NUM_BYTES_STRING_LENGTH];
|
||||
NSAssert2 (read_count == NUM_BYTES_STRING_LENGTH,
|
||||
@"expected %d bytes of input, got %d",
|
||||
NUM_BYTES_STRING_LENGTH,read_count);
|
||||
length = NSSwapBigIntToHost (length);
|
||||
OBJC_MALLOC (*(char**)d, char, length+1);
|
||||
read_count = [stream readBytes: *(char**)d
|
||||
length: length];
|
||||
NSAssert2 (read_count == length,
|
||||
@"expected %d bytes of input, got %d",length,read_count);
|
||||
(*(char**)d)[length] = '\0';
|
||||
/* Autorelease the newly malloc'ed pointer? Grep for (*objc_free)
|
||||
to see the places the may have to be changed
|
||||
[NSData dataWithBytesNoCopy: *(void**)d length: length+1]; */
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream readByte: (unsigned char*)d];
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
READ_SIGNED_TYPE (d, short, NSSwapBigShortToHost);
|
||||
break;
|
||||
case _C_USHT:
|
||||
READ_UNSIGNED_TYPE (d, short, NSSwapBigShortToHost);
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
READ_SIGNED_TYPE (d, int, NSSwapBigIntToHost);
|
||||
break;
|
||||
case _C_UINT:
|
||||
READ_UNSIGNED_TYPE (d, int, NSSwapBigIntToHost);
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
READ_SIGNED_TYPE (d, long, NSSwapBigLongToHost);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
READ_UNSIGNED_TYPE (d, long, NSSwapBigLongToHost);
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
{
|
||||
short exponent;
|
||||
int mantissa;
|
||||
double value;
|
||||
float fvalue;
|
||||
|
||||
/* Decode the exponent and mantissa. */
|
||||
READ_SIGNED_TYPE (&exponent, short, NSSwapBigShortToHost);
|
||||
READ_SIGNED_TYPE (&mantissa, int, NSSwapBigIntToHost);
|
||||
/* Assemble them into a double */
|
||||
value = mantissa / FLOAT_FACTOR;
|
||||
value = ldexp (value, exponent);
|
||||
/* Put the double into the requested memory location as a float */
|
||||
fvalue = value;
|
||||
memcpy (d, &fvalue, sizeof (float));
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_DBL:
|
||||
{
|
||||
short exponent;
|
||||
int mantissa1, mantissa2;
|
||||
double value;
|
||||
|
||||
/* Decode the exponent and the two pieces of the mantissa. */
|
||||
READ_SIGNED_TYPE (&exponent, short, NSSwapBigShortToHost);
|
||||
READ_SIGNED_TYPE (&mantissa1, int, NSSwapBigIntToHost);
|
||||
READ_SIGNED_TYPE (&mantissa2, int, NSSwapBigIntToHost);
|
||||
/* Assemble them into a double */
|
||||
value = ((mantissa2 / FLOAT_FACTOR) + mantissa1) / FLOAT_FACTOR;
|
||||
value = ldexp (value, exponent);
|
||||
/* Put the double into the requested memory location. */
|
||||
memcpy (d, &value, sizeof (double));
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||
int len = atoi(type+1);
|
||||
int offset;
|
||||
[self decodeName:namePtr];
|
||||
[self decodeIndent];
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
[self decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
[self decodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space just like char* ? No. */
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
const char *save_type = type;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
[self decodeName:namePtr];
|
||||
[self decodeIndent]; /* xxx insert [self decodeName:] */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self decodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:namePtr];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
type = save_type;
|
||||
[self decodeUnindent];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Unrecognized Type %s", type];
|
||||
}
|
||||
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"decoding unnamed"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
|
||||
|
||||
/* Encoding and decoding names. */
|
||||
|
||||
- (void) encodeName: (NSString*) name
|
||||
{
|
||||
if (debug_binary_coder)
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeName:name];
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *)n
|
||||
{
|
||||
#if 1
|
||||
if (n)
|
||||
*n = nil;
|
||||
#else
|
||||
if (n)
|
||||
*n = [[[NSString alloc] init] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
287
Source/CStream.m
287
Source/CStream.m
|
@ -1,287 +0,0 @@
|
|||
/* Implementation of GNU Objective-C class for streaming C types and indentatn
|
||||
Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/CStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/CoderPrivate.h> /* for SIGNATURE_FORMAT_STRING */
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
id CStreamSignatureMalformedException = @"CStreamSignatureMalformedException";
|
||||
id CStreamSignatureMismatchException = @"CStreamSignatureMismatchException";
|
||||
|
||||
@implementation CStream
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name;
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) decodeValueOfCType: (const char*) type
|
||||
at: (void*) d
|
||||
withName: (NSString* *) namePtr;
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
|
||||
/* Signature methods. */
|
||||
|
||||
- (void) writeSignature
|
||||
{
|
||||
/* Careful: the string should not contain newlines. */
|
||||
[stream writeFormat: SIGNATURE_FORMAT_STRING,
|
||||
STRINGIFY(GNUSTEP_BASE_PACKAGE_NAME),
|
||||
GNUSTEP_BASE_MAJOR_VERSION,
|
||||
GNUSTEP_BASE_MINOR_VERSION,
|
||||
GNUSTEP_BASE_SUBMINOR_VERSION,
|
||||
object_get_class_name(self),
|
||||
format_version];
|
||||
}
|
||||
|
||||
+ (void) readSignatureFromStream: s
|
||||
getClassname: (char *) name
|
||||
formatVersion: (int*) version
|
||||
{
|
||||
int got;
|
||||
char package_name[64];
|
||||
int major_version;
|
||||
int minor_version;
|
||||
int subminor_version;
|
||||
|
||||
got = [s readFormat: SIGNATURE_FORMAT_STRING,
|
||||
&(package_name[0]),
|
||||
&major_version,
|
||||
&minor_version,
|
||||
&subminor_version,
|
||||
name,
|
||||
version];
|
||||
if (got != 6)
|
||||
[NSException raise:CStreamSignatureMalformedException
|
||||
format: @"CStream found a malformed signature"];
|
||||
}
|
||||
|
||||
|
||||
/* Initialization methods */
|
||||
|
||||
/* This is the hidden designated initializer. Do not call it yourself. */
|
||||
- _initWithStream: (id <Streaming>) s
|
||||
formatVersion: (int)version
|
||||
{
|
||||
[super init];
|
||||
[s retain];
|
||||
stream = s;
|
||||
format_version = version;
|
||||
indentation = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This is the designated initializer for reading. */
|
||||
- _initForReadingFromPostSignatureStream: (id <Streaming>)s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[self _initWithStream: s
|
||||
formatVersion: version];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initForReadingFromStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
/* xxx Why this condition? -mccallum */
|
||||
if ([stream streamPosition] != 0)
|
||||
{
|
||||
char name[128]; /* max class name length. */
|
||||
int version;
|
||||
[[self class] readSignatureFromStream: stream
|
||||
getClassname: name
|
||||
formatVersion: &version];
|
||||
if (!strcmp(name, object_get_class_name(self))
|
||||
|| version != format_version)
|
||||
{
|
||||
[NSException raise: CStreamSignatureMismatchException
|
||||
format: @"CStream found a mismatched signature"];
|
||||
}
|
||||
[self _initForReadingFromPostSignatureStream: s
|
||||
withFormatVersion: version];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ cStreamReadingFromStream: (id <Streaming>) s
|
||||
{
|
||||
char name[128]; /* Maximum class name length. */
|
||||
int version;
|
||||
id new_cstream;
|
||||
|
||||
[self readSignatureFromStream: s
|
||||
getClassname: name
|
||||
formatVersion: &version];
|
||||
new_cstream = [[objc_lookup_class(name) alloc]
|
||||
_initForReadingFromPostSignatureStream: s
|
||||
withFormatVersion: version];
|
||||
return [new_cstream autorelease];
|
||||
}
|
||||
|
||||
+ cStreamReadingFromFile: (NSString*) filename
|
||||
{
|
||||
return [self cStreamReadingFromStream:
|
||||
[StdioStream streamWithFilename: filename fmode: "r"]];
|
||||
}
|
||||
|
||||
/* This is a designated initializer for writing. */
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int)version
|
||||
{
|
||||
[self _initWithStream: s
|
||||
formatVersion: version];
|
||||
[self writeSignature];
|
||||
return self;
|
||||
}
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withFormatVersion: [[self class] defaultFormatVersion]];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) file
|
||||
{
|
||||
return [self initForWritingToStream:
|
||||
[StdioStream streamWithFilename: file fmode: "w"]];
|
||||
}
|
||||
|
||||
+ cStreamWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [[[self alloc] initForWritingToStream: s]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
+ cStreamWritingToFile: (NSString*) filename;
|
||||
{
|
||||
return [[[self alloc] initForWritingToFile: filename]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
|
||||
/* Encoding/decoding indentation */
|
||||
|
||||
- (void) encodeWithName: (NSString*) name
|
||||
valuesOfCTypes: (const char *) types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self encodeName: name];
|
||||
va_start (ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self encodeValueOfCType: types
|
||||
at: va_arg(ap, void*)
|
||||
withName: NULL];
|
||||
types = objc_skip_typespec (types);
|
||||
}
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
- (void) decodeWithName: (NSString* *)name
|
||||
valuesOfCTypes: (const char *)types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self decodeName: name];
|
||||
va_start (ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self decodeValueOfCType: types
|
||||
at: va_arg (ap, void*)
|
||||
withName: NULL];
|
||||
types = objc_skip_typespec (types);
|
||||
}
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
- (void) encodeIndent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) encodeUnindent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) decodeIndent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) decodeUnindent
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*) n
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *) name
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
|
||||
/* Access to the underlying stream. */
|
||||
|
||||
- (id <Streaming>) stream
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
/* Deallocation. */
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[stream release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
310
Source/Coder.m
310
Source/Coder.m
|
@ -1,310 +0,0 @@
|
|||
/* Implementation of GNU Objective-C coder object for use serializing
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/behavior.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/CoderPrivate.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/Coding.h>
|
||||
#include <base/Streaming.h>
|
||||
#include <base/Stream.h>
|
||||
#include <base/CStreaming.h>
|
||||
#include <base/CStream.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <base/BinaryCStream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSGeometry.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSArchiver.h>
|
||||
#include <Foundation/NSMapTable.h>
|
||||
#include <Foundation/NSHashTable.h>
|
||||
#include <Foundation/NSCoder.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
|
||||
|
||||
/* Exception strings */
|
||||
id CoderSignatureMalformedException = @"CoderSignatureMalformedException";
|
||||
|
||||
#define DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
#define DOING_ROOT_OBJECT (interconnect_stack_height != 0)
|
||||
|
||||
static BOOL debug_coder = NO;
|
||||
|
||||
|
||||
@implementation Coder
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Coder class])
|
||||
behavior_class_add_class (self, [NSCoderNonCore class]);
|
||||
}
|
||||
|
||||
+ setDebugging: (BOOL)f
|
||||
{
|
||||
debug_coder = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
/* Initialization. */
|
||||
|
||||
/* This is the designated initializer. But, don't call it yourself;
|
||||
override it and call [super...] in subclasses. */
|
||||
- _initWithCStream: (id <CStreaming>) cs
|
||||
formatVersion: (int) version
|
||||
{
|
||||
format_version = version;
|
||||
cstream = [cs retain];
|
||||
classname_2_classname = NULL;
|
||||
interconnect_stack_height = 0;
|
||||
return self;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
if ([self class] == [Coder class])
|
||||
{
|
||||
[self shouldNotImplement:_cmd];
|
||||
return nil;
|
||||
}
|
||||
else
|
||||
return [super init];
|
||||
}
|
||||
|
||||
/* We must separate the idea of "closing" a coder and "deallocating"
|
||||
a coder because of delays in deallocation due to -autorelease. */
|
||||
- (void) close
|
||||
{
|
||||
[[cstream stream] close];
|
||||
}
|
||||
|
||||
- (BOOL) isClosed
|
||||
{
|
||||
return [[cstream stream] isClosed];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
/* xxx No. [self _finishDecodeRootObject]; */
|
||||
[cstream release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
/* Access to instance variables. */
|
||||
|
||||
- cStream
|
||||
{
|
||||
return cstream;
|
||||
}
|
||||
|
||||
- (int) formatVersion
|
||||
{
|
||||
return format_version;
|
||||
}
|
||||
|
||||
- (void) resetCoder
|
||||
{
|
||||
/* xxx Finish this */
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/* To fool ourselves into thinking we can call all these
|
||||
Encoding and Decoding methods. */
|
||||
@interface Coder (Coding) <Encoding, Decoding>
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation Coder (NSCoderCompatibility)
|
||||
|
||||
|
||||
/* The core methods */
|
||||
|
||||
- (void) encodeValueOfObjCType: (const char*)type
|
||||
at: (const void*)address;
|
||||
{
|
||||
[self encodeValueOfObjCType: type at: address withName: NULL];
|
||||
}
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)address
|
||||
{
|
||||
[self decodeValueOfObjCType: type at: address withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeDataObject: (NSData*)data
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- (NSData*) decodeDataObject
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (unsigned int) versionForClassName: (NSString*)className
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Override some methods in NSCoderNonCore */
|
||||
|
||||
- (void) encodeObject: (id)anObject
|
||||
{
|
||||
[self encodeObject: anObject withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeBycopyObject: (id)anObject
|
||||
{
|
||||
[self encodeBycopyObject: anObject withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeByrefObject: (id)anObject
|
||||
{
|
||||
[self encodeByrefObject: anObject withName: NULL];
|
||||
}
|
||||
|
||||
- (void) encodeConditionalObject: (id)anObject
|
||||
{
|
||||
/* NeXT's implementation handles *forward* references by running
|
||||
through the entire encoding process twice! GNU Coding can handle
|
||||
forward references with only one pass. Therefore, however, GNU
|
||||
Coding cannot return a *forward* reference from -decodeObject, so
|
||||
here, assuming this call to -encodeConditionalObject: is mirrored
|
||||
by a -decodeObject, we don't try to encode *forward*
|
||||
references.
|
||||
|
||||
Note that this means objects that use -encodeConditionalObject:
|
||||
that are encoded in the GNU style might decode a nil where
|
||||
NeXT-style encoded would not. I don't see this a huge problem;
|
||||
at least not as bad as NeXT coding mechanism that actually causes
|
||||
crashes in situations where GNU's does fine. Still, if we wanted
|
||||
to fix this, we might be able to build a kludgy fix based on
|
||||
detecting when this would happen, rewinding the stream to the
|
||||
"conditional" point, and encoding again. Yuck. */
|
||||
|
||||
if ([self _coderReferenceForObject: anObject])
|
||||
[self encodeObject: anObject];
|
||||
else
|
||||
[self encodeObject: nil];
|
||||
}
|
||||
|
||||
- (void) encodeRootObject: (id)rootObject
|
||||
{
|
||||
[self encodeRootObject: rootObject withName: NULL];
|
||||
}
|
||||
|
||||
- (id) decodeObject
|
||||
{
|
||||
/* This won't work for decoding GNU-style forward references because
|
||||
once the GNU decoder finds the object later in the decoding, it
|
||||
will back-patch by storing the id in &o... &o will point to some
|
||||
weird location on the stack! This is why we make the GNU
|
||||
implementation of -encodeConditionalObject: not encode forward
|
||||
references. */
|
||||
id o;
|
||||
[self decodeObjectAt: &o withName: NULL];
|
||||
return [o autorelease];
|
||||
}
|
||||
|
||||
- (unsigned int) systemVersion
|
||||
{
|
||||
return format_version; /* xxx Is this right? */
|
||||
}
|
||||
|
||||
@end /* of (NSCoderCompatibility) */
|
||||
|
||||
|
||||
@implementation Coder (NSArchiverCompatibility)
|
||||
|
||||
|
||||
/* Initializing an archiver */
|
||||
|
||||
- (id) initForWritingWithMutableData: (NSMutableData*)mdata
|
||||
{
|
||||
[(id)self initForWritingToStream: [MemoryStream streamWithData: mdata]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initForReadingWithData: (NSData*)data
|
||||
{
|
||||
id ret = [[self class] newReadingFromStream:
|
||||
[MemoryStream streamWithData:data]];
|
||||
[self release];
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Archiving Data */
|
||||
|
||||
+ (NSData*) archivedDataWithRootObject: (id)rootObject
|
||||
{
|
||||
id d = [[NSMutableData alloc] init];
|
||||
id a = [[NSArchiver alloc] initForWritingWithMutableData:d];
|
||||
[a encodeRootObject:rootObject];
|
||||
return [d autorelease];
|
||||
}
|
||||
|
||||
+ (BOOL) archiveRootObject: (id)rootObject toFile: (NSString*)path
|
||||
{
|
||||
/* xxx fix this return value */
|
||||
id d = [self archivedDataWithRootObject:rootObject];
|
||||
[d writeToFile:path atomically:NO];
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* Getting data from the archiver */
|
||||
|
||||
+ unarchiveObjectWithData: (NSData*) data
|
||||
{
|
||||
return [self decodeObjectWithName: NULL
|
||||
fromStream: [MemoryStream streamWithData:data]];
|
||||
}
|
||||
|
||||
+ unarchiveObjectWithFile: (NSString*) path
|
||||
{
|
||||
return [self decodeObjectWithName: NULL fromFile: path];
|
||||
}
|
||||
|
||||
- (NSMutableData*) archiverData
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
878
Source/Decoder.m
878
Source/Decoder.m
|
@ -1,878 +0,0 @@
|
|||
/* Abstract class for reading objects from a stream
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996, with core from Coder, created 1994.
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/CoderPrivate.h>
|
||||
#include <base/CStream.h>
|
||||
#include <base/Stream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
extern BOOL sel_types_match(const char* t1, const char* t2);
|
||||
|
||||
static int debug_coder = 0;
|
||||
|
||||
@implementation Decoder
|
||||
|
||||
static id dummyObject;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
BOOL beenHere = NO;
|
||||
|
||||
if (beenHere == NO)
|
||||
{
|
||||
beenHere = YES;
|
||||
dummyObject = [NSObject new];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Signature Handling. */
|
||||
|
||||
+ (void) readSignatureFromCStream: (id <CStreaming>) cs
|
||||
getClassname: (char *) name
|
||||
formatVersion: (int*) version
|
||||
{
|
||||
int got;
|
||||
char package_name[64];
|
||||
int major_version;
|
||||
int minor_version;
|
||||
int subminor_version;
|
||||
|
||||
/* SIGNATURE_FORMAT_STRING is defined in gnustep/base/CoderPrivate.h */
|
||||
got = [[cs stream] readFormat: SIGNATURE_FORMAT_STRING,
|
||||
&package_name,
|
||||
&major_version,
|
||||
&minor_version,
|
||||
&subminor_version,
|
||||
name, version];
|
||||
if (got != 6)
|
||||
[NSException raise: CoderSignatureMalformedException
|
||||
format: @"Decoder found a malformed signature"];
|
||||
}
|
||||
|
||||
/* This is the designated initializer. */
|
||||
+ newReadingFromStream: (id <Streaming>) stream
|
||||
{
|
||||
id cs = [CStream cStreamReadingFromStream: stream];
|
||||
char name[128]; /* Max classname length. */
|
||||
int version;
|
||||
Decoder *new_coder;
|
||||
|
||||
[self readSignatureFromCStream: cs
|
||||
getClassname: name
|
||||
formatVersion: &version];
|
||||
|
||||
new_coder = [[objc_lookup_class(name) alloc]
|
||||
_initWithCStream: cs
|
||||
formatVersion: version];
|
||||
new_coder->xref_2_object = NULL;
|
||||
new_coder->xref_2_object_root = NULL;
|
||||
new_coder->fref_2_object = NULL;
|
||||
new_coder->address_2_fref = NULL;
|
||||
new_coder->zone = NSDefaultMallocZone();
|
||||
return new_coder;
|
||||
}
|
||||
|
||||
+ newReadingFromFile: (NSString*) filename
|
||||
{
|
||||
return [self newReadingFromStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "r"]];
|
||||
}
|
||||
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromStream: (id <Streaming>)stream;
|
||||
{
|
||||
id c, o;
|
||||
c = [self newReadingFromStream:stream];
|
||||
[c decodeObjectAt: &o withName: name];
|
||||
[c release];
|
||||
return [o autorelease];
|
||||
}
|
||||
|
||||
+ decodeObjectWithName: (NSString* *) name
|
||||
fromFile: (NSString*) filename;
|
||||
{
|
||||
return [self decodeObjectWithName: name
|
||||
fromStream:
|
||||
[StdioStream streamWithFilename:filename fmode: "r"]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Functions and methods for keeping cross-references
|
||||
so objects that were already read can be referred to again. */
|
||||
|
||||
/* These _coder... methods may be overriden by subclasses so that
|
||||
cross-references can be kept differently. */
|
||||
|
||||
- (unsigned) _coderCreateReferenceForObject: anObj
|
||||
{
|
||||
if (!xref_2_object)
|
||||
{
|
||||
xref_2_object = [NSMutableArray new];
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
[xref_2_object addObject: dummyObject];
|
||||
}
|
||||
if (debug_coder)
|
||||
fprintf (stderr, "Decoder registering object xref %u\n",
|
||||
[xref_2_object count] - 1);
|
||||
[xref_2_object addObject: anObj]; // xxx but this will retain anObj. NO.
|
||||
/* This return value should be the same as the index of anObj
|
||||
in xref_2_object. */
|
||||
return ([xref_2_object count] - 1);
|
||||
}
|
||||
|
||||
- (void) _coderSubstituteObject: anObj atReference: (unsigned)xref
|
||||
{
|
||||
[xref_2_object replaceObjectAtIndex: xref withObject: anObj];
|
||||
}
|
||||
|
||||
- _coderObjectAtReference: (unsigned)xref
|
||||
{
|
||||
NSParameterAssert (xref_2_object);
|
||||
return [xref_2_object objectAtIndex: xref];
|
||||
}
|
||||
|
||||
|
||||
/* The methods for the root object table. The *root* object table
|
||||
(XREF_2_OBJECT_ROOT) isn't really used for much right now, but it
|
||||
may be in the future. For now, most of the work is don't by
|
||||
XREF_2_OBJECT. */
|
||||
|
||||
- (void) _coderPushRootObjectTable
|
||||
{
|
||||
if (!xref_2_object_root)
|
||||
xref_2_object_root = [NSMutableArray new];
|
||||
}
|
||||
|
||||
- (void) _coderPopRootObjectTable
|
||||
{
|
||||
NSParameterAssert (xref_2_object_root);
|
||||
if (!interconnect_stack_height)
|
||||
{
|
||||
[xref_2_object_root release];
|
||||
xref_2_object_root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) _coderCreateReferenceForInterconnectedObject: anObj
|
||||
{
|
||||
if (!xref_2_object_root)
|
||||
{
|
||||
xref_2_object_root = [NSMutableArray new];
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
[xref_2_object_root addObject: dummyObject];
|
||||
}
|
||||
[xref_2_object_root addObject: anObj];
|
||||
/* This return value should be the same as the index of anObj
|
||||
in xref_2_object_root. */
|
||||
return ([xref_2_object_root count] - 1);
|
||||
}
|
||||
|
||||
- _coderTopRootObjectTable
|
||||
{
|
||||
NSParameterAssert (xref_2_object_root);
|
||||
return xref_2_object_root;
|
||||
}
|
||||
|
||||
|
||||
/* Using the next three methods, subclasses can change the way that
|
||||
const pointers (like SEL, Class, Atomic strings, etc) are
|
||||
archived. */
|
||||
|
||||
- (unsigned) _coderCreateReferenceForConstPtr: (const void*)ptr
|
||||
{
|
||||
unsigned xref;
|
||||
|
||||
if (!xref_2_const_ptr)
|
||||
{
|
||||
xref_2_const_ptr = NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks,
|
||||
0);
|
||||
/* Append an object so our xref numbers are in sync with the
|
||||
Encoders, which start at 1. */
|
||||
NSMapInsert (xref_2_const_ptr, (void*)0, (void*)1);
|
||||
}
|
||||
xref = NSCountMapTable (xref_2_const_ptr);
|
||||
NSMapInsert (xref_2_const_ptr, (void*)xref, ptr);
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (const void*) _coderConstPtrAtReference: (unsigned)xref;
|
||||
{
|
||||
NSParameterAssert (xref_2_const_ptr);
|
||||
return NSMapGet (xref_2_const_ptr, (void*)xref);
|
||||
}
|
||||
|
||||
|
||||
/* Here are the methods for forward object references. */
|
||||
|
||||
- (void) _coderPushForwardObjectTable
|
||||
{
|
||||
#if 0
|
||||
if (!fref_stack)
|
||||
fref_stack = o_list_of_void_p ();
|
||||
o_list_append_element (fref_stack, NSCreateMap (...));
|
||||
#endif
|
||||
if (!address_2_fref)
|
||||
address_2_fref = NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
|
||||
}
|
||||
|
||||
- (void) _coderPopForwardObjectTable
|
||||
{
|
||||
NSParameterAssert (address_2_fref);
|
||||
if (!interconnect_stack_height)
|
||||
{
|
||||
NSFreeMapTable (address_2_fref);
|
||||
address_2_fref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) _coderSatisfyForwardReference: (unsigned)fref withObject: anObj
|
||||
{
|
||||
NSParameterAssert (address_2_fref);
|
||||
if (!fref_2_object)
|
||||
/* xxx Or should this be NSObjectMapValueCallBacks, so we make
|
||||
sure the object doesn't get released before we can resolve
|
||||
references with it? */
|
||||
fref_2_object = NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
/* There should only be one object for each fref. */
|
||||
NSAssert (!NSMapGet (fref_2_object, (void*)fref),
|
||||
@"Should have only been one object for each fref");
|
||||
NSMapInsert (fref_2_object, (void*)fref, anObj);
|
||||
}
|
||||
|
||||
- (void) _coderAssociateForwardReference: (unsigned)fref
|
||||
withObjectAddress: (void*)addr
|
||||
{
|
||||
/* Register ADDR as associated with FREF; later we will put id
|
||||
associated with FREF at ADDR. */
|
||||
NSParameterAssert (address_2_fref);
|
||||
/* There should not be duplicate addresses */
|
||||
NSAssert (!NSMapGet (address_2_fref, addr), @"Duplicate addresses");
|
||||
NSMapInsert (address_2_fref, addr, (void*)fref);
|
||||
}
|
||||
|
||||
- (void) _coderResolveTopForwardReferences
|
||||
{
|
||||
/* Enumerate the forward references and put them at the proper addresses. */
|
||||
NSMapEnumerator me;
|
||||
void *fref;
|
||||
void *addr;
|
||||
|
||||
if (!address_2_fref)
|
||||
return;
|
||||
|
||||
/* Go through all the addresses that are needing to be filled
|
||||
in with forward references, and put the correct object there.
|
||||
If fref_2_object does not contain an object for fref, (i.e. there
|
||||
was no satisfier for the forward reference), put nil there. */
|
||||
me = NSEnumerateMapTable (address_2_fref);
|
||||
while (NSNextMapEnumeratorPair (&me, &addr, &fref))
|
||||
*(id*)addr = (id) NSMapGet (fref_2_object, fref);
|
||||
}
|
||||
|
||||
|
||||
/* This is the Coder's interface to the over-ridable
|
||||
"_coderCreateReferenceForObject" method. Do not override it. It
|
||||
handles the xref_2_object_root. */
|
||||
|
||||
- (unsigned) _coderInternalCreateReferenceForObject: anObj
|
||||
{
|
||||
unsigned xref = [self _coderCreateReferenceForObject: anObj];
|
||||
if (DOING_ROOT_OBJECT)
|
||||
[self _coderCreateReferenceForInterconnectedObject: anObj];
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (void) _coderInternalSubstituteObject: anObj atReference: (unsigned)xref
|
||||
{
|
||||
[self _coderSubstituteObject: anObj atReference: xref];
|
||||
/* xxx If we ever use the root object table, do something with it also. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Method for decoding things. */
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
[cstream decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
}
|
||||
|
||||
- (void) decodeBytes: (void *)b
|
||||
count: (unsigned)c
|
||||
withName: (NSString* *) name
|
||||
{
|
||||
int actual_count;
|
||||
/* xxx Is this what we want?
|
||||
It won't be cleanly readable in TextCStream's. */
|
||||
[cstream decodeName: name];
|
||||
actual_count = [[cstream stream] readBytes: b length: c];
|
||||
NSAssert2 (actual_count == c,
|
||||
@"expected to read %d bytes, read %d bytes",c,actual_count);
|
||||
}
|
||||
|
||||
- (unsigned char) decodeTag
|
||||
{
|
||||
if ([cstream respondsToSelector: @selector(decodeTag)])
|
||||
return [(id)cstream decodeTag];
|
||||
{
|
||||
unsigned char t;
|
||||
[self decodeValueOfCType:@encode(unsigned char)
|
||||
at:&t
|
||||
withName:NULL];
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
- decodeClass
|
||||
{
|
||||
unsigned char tag;
|
||||
char *class_name;
|
||||
int class_version;
|
||||
id ret = Nil;
|
||||
|
||||
[self decodeIndent];
|
||||
tag = [self decodeTag];
|
||||
switch (tag)
|
||||
{
|
||||
case CODER_CLASS_NIL:
|
||||
break;
|
||||
case CODER_CLASS_REPEATED:
|
||||
{
|
||||
unsigned xref;
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: NULL];
|
||||
ret = (id) [self _coderConstPtrAtReference: xref];
|
||||
if (!ret)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"repeated class cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
case CODER_CLASS:
|
||||
{
|
||||
[self decodeValueOfCType: @encode(char*)
|
||||
at: &class_name
|
||||
withName: NULL];
|
||||
[self decodeValueOfCType: @encode(int)
|
||||
at: &class_version
|
||||
withName: NULL];
|
||||
|
||||
/* xxx should do classname substitution,
|
||||
ala decodeClassName:intoClassName: here. */
|
||||
|
||||
ret = objc_lookup_class (class_name);
|
||||
/* Ensure that the [+initialize] method has been called for the
|
||||
class by calling one of it's methods */
|
||||
if (ret != Nil)
|
||||
ret = [ret class];
|
||||
if (ret == Nil)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Couldn't find class `%s'", class_name];
|
||||
if (class_get_version(ret) != class_version)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"Class version mismatch, executable %d != encoded %d",
|
||||
class_get_version(ret), class_version];
|
||||
|
||||
{
|
||||
unsigned xref;
|
||||
xref = [self _coderCreateReferenceForConstPtr: ret];
|
||||
if (debug_coder)
|
||||
fprintf(stderr,
|
||||
"Decoder decoding registered class xref %u\n", xref);
|
||||
}
|
||||
objc_free (class_name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"unrecognized class tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (const char *) decodeAtomicStringWithName: (NSString* *) name
|
||||
{
|
||||
char *s;
|
||||
/* xxx Add repeat-string-ptr checking here */
|
||||
[self notImplemented:_cmd];
|
||||
[self decodeValueOfCType:@encode(char*) at:&s withName:name];
|
||||
return s;
|
||||
}
|
||||
|
||||
- (SEL) decodeSelectorWithName: (NSString* *) name
|
||||
{
|
||||
char tag;
|
||||
SEL ret = NULL;
|
||||
|
||||
[self decodeName:name];
|
||||
[self decodeIndent];
|
||||
tag = [self decodeTag];
|
||||
switch (tag)
|
||||
{
|
||||
case CODER_CONST_PTR_NULL:
|
||||
break;
|
||||
case CODER_CONST_PTR_REPEATED:
|
||||
{
|
||||
unsigned xref;
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: NULL];
|
||||
ret = (SEL) [self _coderConstPtrAtReference: xref];
|
||||
if (!ret)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"repeated selector cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
case CODER_CONST_PTR:
|
||||
{
|
||||
char *sel_name;
|
||||
char *sel_types;
|
||||
|
||||
[self decodeValueOfCType:@encode(char *)
|
||||
at:&sel_name
|
||||
withName:NULL];
|
||||
[self decodeValueOfCType:@encode(char *)
|
||||
at:&sel_types
|
||||
withName:NULL];
|
||||
#if NeXT_runtime
|
||||
ret = sel_getUid(sel_name);
|
||||
#else
|
||||
if (!strcmp(sel_types, NO_SEL_TYPES))
|
||||
ret = sel_get_any_uid(sel_name);
|
||||
else
|
||||
ret = sel_get_typed_uid(sel_name, sel_types);
|
||||
#endif
|
||||
if (!ret)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Could not find selector (%s) with types [%s]",
|
||||
sel_name, sel_types];
|
||||
#if ! NeXT_runtime
|
||||
if (strcmp(sel_types, NO_SEL_TYPES)
|
||||
&& !(sel_types_match(sel_types, ret->sel_types)))
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"ObjC runtime didn't provide SEL with matching type"];
|
||||
#endif
|
||||
{
|
||||
unsigned xref;
|
||||
xref = [self _coderCreateReferenceForConstPtr: ret];
|
||||
if (debug_coder)
|
||||
fprintf(stderr,
|
||||
"Decoder decoding registered sel xref %u\n", xref);
|
||||
}
|
||||
objc_free(sel_name);
|
||||
objc_free(sel_types);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"unrecognized selector tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
- (void) startDecodingInterconnectedObjects
|
||||
{
|
||||
interconnect_stack_height++;
|
||||
[self _coderPushRootObjectTable];
|
||||
[self _coderPushForwardObjectTable];
|
||||
}
|
||||
|
||||
- (void) finishDecodingInterconnectedObjects
|
||||
{
|
||||
NSParameterAssert (interconnect_stack_height);
|
||||
|
||||
/* xxx This might not be the right thing to do; perhaps we should do
|
||||
this finishing up work at the end of each nested call, not just
|
||||
at the end of all nested calls.
|
||||
However, then we might miss some forward references that we could
|
||||
have resolved otherwise. */
|
||||
if (--interconnect_stack_height)
|
||||
return;
|
||||
|
||||
/* xxx fix the use of _coderPopForwardObjectTable and
|
||||
_coderPopRootObjectTable. */
|
||||
|
||||
#if 0 /* Actually, we do this below in -decodeObjectAt:withName: */
|
||||
/* Send "-awakeAfterUsingCoder:" to all the objects that were read */
|
||||
{
|
||||
SEL awake_sel = sel_get_any_uid("awakeAfterUsingCoder:");
|
||||
if (awake_sel)
|
||||
{
|
||||
int i;
|
||||
id table = [self _coderTopRootObjectTable];
|
||||
|
||||
/* Loop through all objects that we decoded by this Decoder */
|
||||
for (i = [table count]-1; i >= 0; i--)
|
||||
{
|
||||
id o = [table objectAtIndex: i];
|
||||
if (__objc_responds_to(o, awake_sel))
|
||||
{
|
||||
replacement_obj =
|
||||
(*objc_msg_lookup(e.id_u,awake_sel))(o, awake_sel, self);
|
||||
/* xxx Make the replacement in the decoder's object tables. */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* resolve object forward references */
|
||||
[self _coderResolveTopForwardReferences];
|
||||
[self _coderPopForwardObjectTable];
|
||||
|
||||
[self _coderPopRootObjectTable];
|
||||
}
|
||||
|
||||
- (void) _decodeRootObjectAt: (id*)ret withName: (NSString* *) name
|
||||
{
|
||||
[self startDecodingInterconnectedObjects];
|
||||
[self decodeObjectAt:ret withName:name];
|
||||
[self finishDecodingInterconnectedObjects];
|
||||
}
|
||||
|
||||
|
||||
- (void) decodeValueOfObjCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CLASS:
|
||||
{
|
||||
[self decodeName:namePtr];
|
||||
*(id*)d = [self decodeClass];
|
||||
break;
|
||||
}
|
||||
case _C_ATOM:
|
||||
*(const char**)d = [self decodeAtomicStringWithName:namePtr];
|
||||
break;
|
||||
case _C_SEL:
|
||||
*(SEL*)d = [self decodeSelectorWithName:namePtr];
|
||||
break;
|
||||
case _C_ID:
|
||||
[self decodeObjectAt:d withName:namePtr];
|
||||
break;
|
||||
default:
|
||||
[self decodeValueOfCType:type at:d withName:namePtr];
|
||||
}
|
||||
/* xxx We need to catch unions and make a sensible error message */
|
||||
}
|
||||
|
||||
- (BOOL) _createReferenceBeforeInit
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* This is the designated (and one-and-only) object decoder */
|
||||
- (void) decodeObjectAt: (id*) anObjPtr withName: (NSString* *) name
|
||||
{
|
||||
unsigned char tag;
|
||||
unsigned fref = 0;
|
||||
id dummy_object;
|
||||
|
||||
/* Sometimes the user wants to decode an object, but doesn't care to
|
||||
have a pointer to it, (LinkedList elements, for example). In
|
||||
this case, the user can pass in NULL for anObjPtr, and all will
|
||||
be safe. */
|
||||
if (!anObjPtr)
|
||||
anObjPtr = &dummy_object;
|
||||
|
||||
[self decodeName:name];
|
||||
[self decodeIndent];
|
||||
tag = [self decodeTag];
|
||||
switch (tag)
|
||||
{
|
||||
case CODER_OBJECT_NIL:
|
||||
*anObjPtr = nil;
|
||||
break;
|
||||
case CODER_OBJECT_CLASS:
|
||||
*anObjPtr = [self decodeClass];
|
||||
break;
|
||||
case CODER_OBJECT_FORWARD_REFERENCE:
|
||||
{
|
||||
if (!DOING_ROOT_OBJECT)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"can't decode forward reference when not decoding "
|
||||
@"a root object"];
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: NULL];
|
||||
/* The user doesn't need the object pointer anyway, don't record
|
||||
it in the table. */
|
||||
if (anObjPtr == &dummy_object)
|
||||
break;
|
||||
[self _coderAssociateForwardReference: fref
|
||||
withObjectAddress: anObjPtr];
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT:
|
||||
{
|
||||
Class object_class;
|
||||
SEL new_sel = sel_get_any_uid ("newWithCoder:");
|
||||
Method* new_method;
|
||||
BOOL create_ref_before_init = [self _createReferenceBeforeInit];
|
||||
/* Initialize this to <0 so we can tell below if it's been set */
|
||||
int xref = -1;
|
||||
|
||||
[self decodeIndent];
|
||||
object_class = [self decodeClass];
|
||||
/* xxx Should change the runtime.
|
||||
class_get_class_method should take the class as its first
|
||||
argument, not the metaclass! */
|
||||
new_method = class_get_class_method(class_get_meta_class(object_class),
|
||||
new_sel);
|
||||
if (new_method && !create_ref_before_init)
|
||||
*anObjPtr = (*(new_method->method_imp))(object_class, new_sel, self);
|
||||
else
|
||||
{
|
||||
SEL init_sel = sel_get_any_uid ("initWithCoder:");
|
||||
Method *init_method =
|
||||
class_get_instance_method (object_class, init_sel);
|
||||
/* xxx Or should I send +alloc? */
|
||||
*anObjPtr = (id) NSAllocateObject (object_class, 0, zone);
|
||||
if (create_ref_before_init)
|
||||
xref = [self _coderInternalCreateReferenceForObject: *anObjPtr];
|
||||
if (init_method)
|
||||
*anObjPtr =
|
||||
(*(init_method->method_imp))(*anObjPtr, init_sel, self);
|
||||
/* xxx else what, error? */
|
||||
}
|
||||
|
||||
/* Send -awakeAfterUsingCoder: */
|
||||
/* xxx Unknown whether -awakeAfterUsingCoder: should be sent here, or
|
||||
when Decoder is deallocated, or after a root object is finished
|
||||
decoding. */
|
||||
/* NOTE: Use of this with the NeXT archiving methods is
|
||||
tricky, because if [*anObj initWithCoder:] creates any
|
||||
objects that references *anObj, and if [*anObj
|
||||
awakeAfterUsingCoder:] replaces itself, then the
|
||||
subobject's references will not be to the replacement.
|
||||
There is no way to magically fix this circular dependancy;
|
||||
users must be aware. We should just make sure we require
|
||||
the same cautions as NeXT's implementation. Note that, with
|
||||
the GNU archiving methods, this problem doesn't occur because
|
||||
we don't register the object until after it has been fully
|
||||
initialized and awakened. */
|
||||
{
|
||||
SEL awake_sel = sel_get_any_uid ("awakeAfterUsingCoder:");
|
||||
IMP awake_imp = objc_msg_lookup (*anObjPtr, awake_sel);
|
||||
id replacement;
|
||||
|
||||
if (awake_imp)
|
||||
{
|
||||
replacement = (*awake_imp) (*anObjPtr, awake_sel, self);
|
||||
if (replacement != *anObjPtr)
|
||||
{
|
||||
if (xref > 0)
|
||||
[self _coderInternalSubstituteObject: replacement
|
||||
atReference: xref];
|
||||
*anObjPtr = replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self decodeUnindent];
|
||||
|
||||
/* If this was a CODER_OBJECT_FORWARD_SATISFIER, then remember it. */
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: NULL];
|
||||
if (fref)
|
||||
{
|
||||
NSAssert (!create_ref_before_init,
|
||||
@"You are trying to decode an object with the non-GNU\n"
|
||||
@"OpenStep-style forward references, but the object's\n"
|
||||
@"decoding mechanism wants to use GNU features.");
|
||||
[self _coderSatisfyForwardReference: fref withObject: *anObjPtr];
|
||||
}
|
||||
|
||||
/* Would get error here with Connection-wide object references
|
||||
because addProxy gets called in +newRemote:connection: */
|
||||
if (!create_ref_before_init)
|
||||
{
|
||||
unsigned xref =
|
||||
[self _coderInternalCreateReferenceForObject: *anObjPtr];
|
||||
if (debug_coder)
|
||||
fprintf(stderr,
|
||||
"Decoder decoding registered class xref %u\n", xref);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT_ROOT:
|
||||
{
|
||||
[self _decodeRootObjectAt: anObjPtr withName: name];
|
||||
break;
|
||||
}
|
||||
case CODER_OBJECT_REPEATED:
|
||||
{
|
||||
unsigned xref;
|
||||
|
||||
[self decodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: NULL];
|
||||
*anObjPtr = [[self _coderObjectAtReference: xref] retain];
|
||||
if (!*anObjPtr)
|
||||
[NSException
|
||||
raise: NSGenericException
|
||||
format: @"repeated object cross-reference number %u not found",
|
||||
xref];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"unrecognized object tag = %d", (int)tag];
|
||||
}
|
||||
[self decodeUnindent];
|
||||
}
|
||||
|
||||
|
||||
- (void) decodeWithName: (NSString* *)name
|
||||
valuesOfObjCTypes: (const char *)types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self decodeName:name];
|
||||
va_start(ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self decodeValueOfObjCType:types
|
||||
at:va_arg(ap, void*)
|
||||
withName:NULL];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
- (void) decodeValueOfObjCTypes: (const char *)types
|
||||
at: (void *)d
|
||||
withName: (NSString* *)name
|
||||
{
|
||||
[self decodeName:name];
|
||||
while (*types)
|
||||
{
|
||||
[self decodeValueOfObjCType:types
|
||||
at:d
|
||||
withName:NULL];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (void *)d
|
||||
withName: (NSString* *) name
|
||||
{
|
||||
int i;
|
||||
int offset = objc_sizeof_type(type);
|
||||
char *where = d;
|
||||
|
||||
[self decodeName:name];
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
[self decodeValueOfObjCType:type
|
||||
at:where
|
||||
withName:NULL];
|
||||
where += offset;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeIndent
|
||||
{
|
||||
[cstream decodeIndent];
|
||||
}
|
||||
|
||||
- (void) decodeUnindent
|
||||
{
|
||||
[cstream decodeUnindent];
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *)n
|
||||
{
|
||||
[cstream decodeName: n];
|
||||
}
|
||||
|
||||
|
||||
+ (NSString*) classNameDecodedForArchiveClassName: (NSString*) inArchiveName
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void) decodeClassName: (NSString*) inArchiveName
|
||||
asClassName:(NSString *)trueName
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
|
||||
/* Managing Zones */
|
||||
|
||||
- (NSZone*) objectZone
|
||||
{
|
||||
return zone;
|
||||
}
|
||||
|
||||
- (void) setObjectZone: (NSZone*)z
|
||||
{
|
||||
zone = z;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (xref_2_object) [xref_2_object release];
|
||||
if (xref_2_object_root) [xref_2_object_root release];
|
||||
if (xref_2_const_ptr) NSFreeMapTable (xref_2_const_ptr);
|
||||
if (fref_2_object) NSFreeMapTable (fref_2_object);
|
||||
if (address_2_fref) NSFreeMapTable (address_2_fref);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
883
Source/Encoder.m
883
Source/Encoder.m
|
@ -1,883 +0,0 @@
|
|||
/* Abstract class for writing objects to a stream
|
||||
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: February 1996, with core from Coder, created 1994.
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/CoderPrivate.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/BinaryCStream.h>
|
||||
#include <Foundation/NSArchiver.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
static int default_format_version;
|
||||
static id default_stream_class;
|
||||
static id default_cstream_class;
|
||||
#define DEFAULT_DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
static int debug_coder = 0;
|
||||
|
||||
|
||||
/* xxx For experimentation. The function in objc-api.h doesn't always
|
||||
work for objects; it sometimes returns YES for an instance. */
|
||||
/* But, metaclasses return YES too? */
|
||||
static BOOL
|
||||
my_object_is_class(id object)
|
||||
{
|
||||
if (object != nil
|
||||
#if NeXT_runtime
|
||||
&& CLS_ISMETA(((Class)object)->isa)
|
||||
&& ((Class)object)->isa != ((Class)object)->isa)
|
||||
#else
|
||||
&& CLS_ISMETA(((Class)object)->class_pointer)
|
||||
&& ((Class)object)->class_pointer != ((Class)object)->class_pointer)
|
||||
#endif
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@implementation Encoder
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [Encoder class])
|
||||
{
|
||||
/* This code has not yet been ported to machines for which
|
||||
a pointer is not the same size as an int. */
|
||||
NSAssert(sizeof(void*) == sizeof(unsigned),
|
||||
@"Pointer and int are different sizes");
|
||||
|
||||
/* Initialize some defaults. */
|
||||
default_stream_class = [MemoryStream class];
|
||||
default_cstream_class = [BinaryCStream class];
|
||||
default_format_version = DEFAULT_DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Default format version, Stream and CStream class handling. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return default_format_version;
|
||||
}
|
||||
|
||||
+ (void) setDefaultFormatVersion: (int)f
|
||||
{
|
||||
default_format_version = f;
|
||||
}
|
||||
|
||||
+ (void) setDefaultCStreamClass: sc
|
||||
{
|
||||
default_cstream_class = sc;
|
||||
}
|
||||
|
||||
+ defaultCStreamClass
|
||||
{
|
||||
return default_cstream_class;
|
||||
}
|
||||
|
||||
+ (void) setDefaultStreamClass: sc
|
||||
{
|
||||
default_stream_class = sc;
|
||||
}
|
||||
|
||||
+ defaultStreamClass
|
||||
{
|
||||
return default_stream_class;
|
||||
}
|
||||
|
||||
/* xxx This method interface may change in the future. */
|
||||
- (const char *) defaultDecoderClassname
|
||||
{
|
||||
return "Unarchiver";
|
||||
}
|
||||
|
||||
|
||||
/* Signature Handling. */
|
||||
|
||||
- (void) writeSignature
|
||||
{
|
||||
/* Careful: the string should not contain newlines. */
|
||||
[[cstream stream] writeFormat: SIGNATURE_FORMAT_STRING,
|
||||
WRITE_SIGNATURE_FORMAT_ARGS];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This is the designated initializer for this class. */
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class) cStreamClass
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion
|
||||
{
|
||||
[super _initWithCStream: [[cStreamClass alloc]
|
||||
initForWritingToStream: s
|
||||
withFormatVersion: cStreamFormatVersion]
|
||||
formatVersion: version];
|
||||
[cstream release];
|
||||
in_progress_table = NULL;
|
||||
object_2_xref = NULL;
|
||||
object_2_fref = NULL;
|
||||
const_ptr_2_xref = NULL;
|
||||
fref_counter = 0;
|
||||
[self writeSignature];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* ..Writing... methods */
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
withCStreamClass: (Class) cStreamClass
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withFormatVersion: DEFAULT_DEFAULT_FORMAT_VERSION
|
||||
cStreamClass: cStreamClass
|
||||
cStreamFormatVersion: [cStreamClass defaultFormatVersion]];
|
||||
}
|
||||
|
||||
- initForWritingToStream: (id <Streaming>) s
|
||||
{
|
||||
return [self initForWritingToStream: s
|
||||
withCStreamClass: [[self class] defaultCStreamClass]];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withFormatVersion: (int) version
|
||||
cStreamClass: (Class) cStreamClass
|
||||
cStreamFormatVersion: (int) cStreamFormatVersion
|
||||
{
|
||||
return [self initForWritingToStream: [StdioStream
|
||||
streamWithFilename: filename
|
||||
fmode: "w"]
|
||||
withFormatVersion: version
|
||||
cStreamClass: cStreamClass
|
||||
cStreamFormatVersion: cStreamFormatVersion];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
withCStreamClass: (Class) cStreamClass
|
||||
{
|
||||
return [self initForWritingToStream: [StdioStream
|
||||
streamWithFilename: filename
|
||||
fmode: "w"]
|
||||
withCStreamClass: cStreamClass];
|
||||
}
|
||||
|
||||
- initForWritingToFile: (NSString*) filename
|
||||
{
|
||||
return [self initForWritingToStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
+ newWritingToStream: (id <Streaming>)s
|
||||
{
|
||||
return [[self alloc] initForWritingToStream: s];
|
||||
}
|
||||
|
||||
+ newWritingToFile: (NSString*)filename
|
||||
{
|
||||
return [self newWritingToStream:
|
||||
[StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toStream: (id <Streaming>)stream
|
||||
{
|
||||
id c = [[self alloc] initForWritingToStream: stream];
|
||||
[c encodeRootObject: anObject withName: name];
|
||||
[c close];
|
||||
[c release];
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL) encodeRootObject: anObject
|
||||
withName: (NSString*) name
|
||||
toFile: (NSString*) filename
|
||||
{
|
||||
return [self encodeRootObject: anObject
|
||||
withName: name
|
||||
toStream: [StdioStream streamWithFilename: filename
|
||||
fmode: "w"]];
|
||||
}
|
||||
|
||||
|
||||
/* Functions and methods for keeping cross-references
|
||||
so objects aren't written/read twice. */
|
||||
|
||||
/* These _coder... methods may be overriden by subclasses so that
|
||||
cross-references can be kept differently.
|
||||
over again.
|
||||
*/
|
||||
- (unsigned) _coderCreateReferenceForObject: anObj
|
||||
{
|
||||
unsigned xref;
|
||||
if (!object_2_xref)
|
||||
{
|
||||
object_2_xref =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
}
|
||||
xref = NSCountMapTable (object_2_xref) + 1;
|
||||
NSMapInsert (object_2_xref, anObj, (void*)xref);
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (unsigned) _coderReferenceForObject: anObject
|
||||
{
|
||||
if (object_2_xref)
|
||||
return (unsigned) NSMapGet (object_2_xref, anObject);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Methods for handling constant pointers */
|
||||
/* By overriding the next three methods, subclasses can change the way
|
||||
that const pointers (like SEL, Class, Atomic strings, etc) are
|
||||
archived. */
|
||||
|
||||
- (unsigned) _coderCreateReferenceForConstPtr: (const void*)ptr
|
||||
{
|
||||
unsigned xref;
|
||||
if (!const_ptr_2_xref)
|
||||
const_ptr_2_xref =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
|
||||
xref = NSCountMapTable (const_ptr_2_xref) + 1;
|
||||
NSAssert (! NSMapGet (const_ptr_2_xref, (void*)xref), @"xref already in Map");
|
||||
NSMapInsert (const_ptr_2_xref, ptr, (void*)xref);
|
||||
return xref;
|
||||
}
|
||||
|
||||
- (unsigned) _coderReferenceForConstPtr: (const void*)ptr
|
||||
{
|
||||
if (const_ptr_2_xref)
|
||||
return (unsigned) NSMapGet (const_ptr_2_xref, ptr);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Methods for forward references */
|
||||
|
||||
- (unsigned) _coderCreateForwardReferenceForObject: anObject
|
||||
{
|
||||
unsigned fref;
|
||||
if (!object_2_fref)
|
||||
object_2_fref =
|
||||
NSCreateMapTable (NSNonOwnedPointerOrNullMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
fref = ++fref_counter;
|
||||
NSAssert ( ! NSMapGet (object_2_fref, anObject), @"anObject already in Map");
|
||||
NSMapInsert (object_2_fref, anObject, (void*)fref);
|
||||
return fref;
|
||||
}
|
||||
|
||||
- (unsigned) _coderForwardReferenceForObject: anObject
|
||||
{
|
||||
/* This method must return 0 if it's not there. */
|
||||
if (!object_2_fref)
|
||||
return 0;
|
||||
return (unsigned) NSMapGet (object_2_fref, anObject);
|
||||
}
|
||||
|
||||
- (void) _coderRemoveForwardReferenceForObject: anObject
|
||||
{
|
||||
NSMapRemove (object_2_fref, anObject);
|
||||
}
|
||||
|
||||
|
||||
/* This is the Coder's interface to the over-ridable
|
||||
"_coderPutObject:atReference" method. Do not override it. It
|
||||
handles the root_object_table. */
|
||||
|
||||
- (void) _coderInternalCreateReferenceForObject: anObj
|
||||
{
|
||||
[self _coderCreateReferenceForObject: anObj];
|
||||
}
|
||||
|
||||
|
||||
/* Handling the in_progress_table. These are called before and after
|
||||
the actual object (not a forward or backward reference) is encoded.
|
||||
|
||||
One of these objects should also call
|
||||
-_coderInternalCreateReferenceForObject:. GNU archiving calls it
|
||||
in the first, in order to force forward references to objects that
|
||||
are in progress; this allows for -initWithCoder: methods that
|
||||
deallocate self, and return another object. OpenStep-style coding
|
||||
calls it in the second, meaning that we never create forward
|
||||
references to objects that are in progress; we encode a backward
|
||||
reference to the in progress object, and assume that it will not
|
||||
change location. */
|
||||
|
||||
- (void) _objectWillBeInProgress: anObj
|
||||
{
|
||||
if (!in_progress_table)
|
||||
in_progress_table =
|
||||
/* This is "NonOwnedPointer", and not "Object", because
|
||||
with "Object" we would get an infinite loop with distributed
|
||||
objects when we try to put a Proxy in in the table, and
|
||||
send the proxy the -hash method. */
|
||||
NSCreateMapTable (NSNonOwnedPointerMapKeyCallBacks,
|
||||
NSIntMapValueCallBacks, 0);
|
||||
NSMapInsert (in_progress_table, anObj, (void*)1);
|
||||
}
|
||||
|
||||
- (void) _objectNoLongerInProgress: anObj
|
||||
{
|
||||
NSMapRemove (in_progress_table, anObj);
|
||||
/* Register that we have encoded it so that future encoding can
|
||||
do backward references properly. */
|
||||
[self _coderInternalCreateReferenceForObject: anObj];
|
||||
}
|
||||
|
||||
|
||||
/* Method for encoding things. */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[cstream encodeValueOfCType:type
|
||||
at:d
|
||||
withName:name];
|
||||
}
|
||||
|
||||
- (void) encodeBytes: (const void *)b
|
||||
count: (unsigned)c
|
||||
withName: (NSString*)name
|
||||
{
|
||||
/* xxx Is this what we want?
|
||||
It won't be cleanly readable in TextCStream's. */
|
||||
[cstream encodeName: name];
|
||||
[[cstream stream] writeBytes: b length: c];
|
||||
}
|
||||
|
||||
|
||||
- (void) encodeTag: (unsigned char)t
|
||||
{
|
||||
if ([cstream respondsToSelector: @selector(encodeTag:)])
|
||||
[(id)cstream encodeTag:t];
|
||||
else
|
||||
[self encodeValueOfCType:@encode(unsigned char)
|
||||
at:&t
|
||||
withName:@"Coder tag"];
|
||||
}
|
||||
|
||||
- (void) encodeClass: aClass
|
||||
{
|
||||
[self encodeIndent];
|
||||
if (aClass == Nil)
|
||||
{
|
||||
[self encodeTag: CODER_CLASS_NIL];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* xxx Perhaps I should do classname substitution here. */
|
||||
const char *class_name = class_get_class_name (aClass);
|
||||
unsigned xref;
|
||||
|
||||
/* Do classname substitution, ala encodeClassName:intoClassName */
|
||||
if (classname_2_classname)
|
||||
{
|
||||
char *subst_class_name = NSMapGet (classname_2_classname,
|
||||
class_name);
|
||||
if (subst_class_name)
|
||||
{
|
||||
class_name = subst_class_name;
|
||||
aClass = objc_lookup_class (class_name);
|
||||
}
|
||||
}
|
||||
|
||||
xref = [self _coderReferenceForConstPtr: aClass];
|
||||
if (xref)
|
||||
{
|
||||
/* It's already been encoded, so just encode the x-reference */
|
||||
[self encodeTag: CODER_CLASS_REPEATED];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: @"Class cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It hasn't been encoded before; encode it. */
|
||||
int class_version = class_get_version (aClass);
|
||||
|
||||
NSAssert (class_name, @"Class doesn't have a name");
|
||||
NSAssert (*class_name, @"Class name is empty");
|
||||
|
||||
[self encodeTag: CODER_CLASS];
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &class_name
|
||||
withName: @"Class name"];
|
||||
[self encodeValueOfCType: @encode(int)
|
||||
at: &class_version
|
||||
withName: @"Class version"];
|
||||
[self _coderCreateReferenceForConstPtr: aClass];
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
return;
|
||||
}
|
||||
|
||||
- (void) encodeAtomicString: (const char*) sp
|
||||
withName: (NSString*) name
|
||||
{
|
||||
/* xxx Add repeat-string-ptr checking here. */
|
||||
[self notImplemented:_cmd];
|
||||
[self encodeValueOfCType:@encode(char*) at:&sp withName:name];
|
||||
}
|
||||
|
||||
- (void) encodeSelector: (SEL)sel withName: (NSString*) name
|
||||
{
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
if (sel == 0)
|
||||
{
|
||||
[self encodeTag: CODER_CONST_PTR_NULL];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned xref = [self _coderReferenceForConstPtr: sel];
|
||||
if (xref)
|
||||
{
|
||||
/* It's already been encoded, so just encode the x-reference */
|
||||
[self encodeTag: CODER_CONST_PTR_REPEATED];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: @"SEL cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *sel_name;
|
||||
const char *sel_types;
|
||||
|
||||
[self encodeTag: CODER_CONST_PTR];
|
||||
|
||||
/* Get the selector name and type. */
|
||||
sel_name = sel_get_name(sel);
|
||||
#if NeXT_runtime
|
||||
sel_types = NO_SEL_TYPES;
|
||||
#else
|
||||
sel_types = sel_get_type(sel);
|
||||
#endif
|
||||
#if 1 /* xxx Yipes,... careful... */
|
||||
/* xxx Think about something like this. */
|
||||
if (!sel_types)
|
||||
sel_types =
|
||||
sel_get_type (sel_get_any_typed_uid (sel_get_name (sel)));
|
||||
#endif
|
||||
if (!sel_name || !*sel_name)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"ObjC runtime didn't provide SEL name"];
|
||||
if (!sel_types || !*sel_types)
|
||||
sel_types = NO_SEL_TYPES;
|
||||
|
||||
[self _coderCreateReferenceForConstPtr: sel];
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &sel_name
|
||||
withName: @"SEL name"];
|
||||
[self encodeValueOfCType: @encode(char*)
|
||||
at: &sel_types
|
||||
withName: @"SEL types"];
|
||||
if (debug_coder)
|
||||
fprintf(stderr, "Coder encoding registered sel xref %u\n", xref);
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
return;
|
||||
}
|
||||
|
||||
- (void) encodeValueOfObjCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name
|
||||
{
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CLASS:
|
||||
[self encodeName: name];
|
||||
[self encodeClass: *(id*)d];
|
||||
break;
|
||||
case _C_ATOM:
|
||||
[self encodeAtomicString: *(char**)d withName: name];
|
||||
break;
|
||||
case _C_SEL:
|
||||
{
|
||||
[self encodeSelector: *(SEL*)d withName: name];
|
||||
break;
|
||||
}
|
||||
case _C_ID:
|
||||
[self encodeObject: *(id*)d withName: name];
|
||||
break;
|
||||
default:
|
||||
[self encodeValueOfCType:type at:d withName:name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Methods for handling interconnected objects */
|
||||
|
||||
- (void) startEncodingInterconnectedObjects
|
||||
{
|
||||
interconnect_stack_height++;
|
||||
}
|
||||
|
||||
- (void) finishEncodingInterconnectedObjects
|
||||
{
|
||||
/* xxx Perhaps we should look at the forward references and
|
||||
encode here any forward-referenced objects that haven't been
|
||||
encoded yet. No---the current behavior implements NeXT's
|
||||
-encodeConditionalObject: */
|
||||
NSParameterAssert (interconnect_stack_height);
|
||||
interconnect_stack_height--;
|
||||
}
|
||||
|
||||
/* NOTE: Unlike NeXT's, this *can* be called recursively */
|
||||
- (void) encodeRootObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self encodeName: @"Root Object"];
|
||||
[self encodeIndent];
|
||||
[self encodeTag: CODER_OBJECT_ROOT];
|
||||
[self startEncodingInterconnectedObjects];
|
||||
[self encodeObject: anObj withName: name];
|
||||
[self finishEncodingInterconnectedObjects];
|
||||
[self encodeUnindent];
|
||||
}
|
||||
|
||||
|
||||
/* These next three methods are the designated coder methods called when
|
||||
we've determined that the object has not already been
|
||||
encoded---we're not simply going to encode a cross-reference number
|
||||
to the object, we're actually going to encode an object (either a
|
||||
proxy to the object or the object itself).
|
||||
|
||||
NSPortCoder overrides _doEncodeObject: in order to implement
|
||||
the encoding of proxies. */
|
||||
|
||||
- (void) _doEncodeBycopyObject: anObj
|
||||
{
|
||||
id encoded_object, encoded_class;
|
||||
|
||||
/* Give the user the opportunity to substitute the class and object */
|
||||
/* xxx Is this the right place for this substitution? */
|
||||
if ([[self class] isKindOf: [NSCoder class]]
|
||||
&& ! [[self class] isKindOf: [NSArchiver class]])
|
||||
/* Make sure we don't do this for the Coder class, because
|
||||
by default Coder should behave like NSArchiver. */
|
||||
{
|
||||
encoded_object = [anObj replacementObjectForCoder: (NSCoder*)self];
|
||||
encoded_class = [encoded_object classForCoder];
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded_object = [anObj replacementObjectForArchiver: (NSArchiver*)self];
|
||||
encoded_class = [encoded_object classForArchiver];
|
||||
}
|
||||
[self encodeClass: encoded_class];
|
||||
/* xxx We should make sure it responds to this selector! */
|
||||
[encoded_object encodeWithCoder: (id)self];
|
||||
}
|
||||
|
||||
/* This method overridden by NSPortCoder */
|
||||
- (void) _doEncodeObject: anObj
|
||||
{
|
||||
[self _doEncodeBycopyObject:anObj];
|
||||
}
|
||||
|
||||
/* This method overridden by NSPortCoder */
|
||||
- (void) _doEncodeByrefObject: anObj
|
||||
{
|
||||
[self _doEncodeObject: anObj];
|
||||
}
|
||||
|
||||
|
||||
/* This is the designated object encoder */
|
||||
- (void) _encodeObject: anObj
|
||||
withName: (NSString*) name
|
||||
isBycopy: (BOOL) bycopy_flag
|
||||
isByref: (BOOL) byref_flag
|
||||
isForwardReference: (BOOL) forward_ref_flag
|
||||
{
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
if (!anObj)
|
||||
{
|
||||
[self encodeTag:CODER_OBJECT_NIL];
|
||||
}
|
||||
else if (my_object_is_class(anObj))
|
||||
{
|
||||
[self encodeTag: CODER_OBJECT_CLASS];
|
||||
[self encodeClass:anObj];
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned xref = [self _coderReferenceForObject: anObj];
|
||||
if (xref)
|
||||
{
|
||||
/* It's already been encoded, so just encode the x-reference */
|
||||
[self encodeTag: CODER_OBJECT_REPEATED];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &xref
|
||||
withName: @"Object cross-reference number"];
|
||||
}
|
||||
else if (forward_ref_flag
|
||||
|| (in_progress_table
|
||||
&& NSMapGet (in_progress_table, anObj)))
|
||||
{
|
||||
unsigned fref;
|
||||
|
||||
/* We are going to encode a forward reference, either because
|
||||
(1) our caller asked for it, or (2) we are in the middle
|
||||
of encoding this object, and haven't finished encoding it yet. */
|
||||
/* Find out if it already has a forward reference number. */
|
||||
fref = [self _coderForwardReferenceForObject: anObj];
|
||||
if (!fref)
|
||||
/* It doesn't, so create one. */
|
||||
fref = [self _coderCreateForwardReferenceForObject: anObj];
|
||||
[self encodeTag: CODER_OBJECT_FORWARD_REFERENCE];
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No backward or forward references, we are going to encode
|
||||
the object. */
|
||||
unsigned fref;
|
||||
|
||||
/* Register the object as being in progress of encoding. In
|
||||
OpenStep-style archiving, this method also calls
|
||||
-_coderInternalCreateReferenceForObject:. */
|
||||
[self _objectWillBeInProgress: anObj];
|
||||
|
||||
/* Encode the object. */
|
||||
[self encodeTag: CODER_OBJECT];
|
||||
[self encodeIndent];
|
||||
if (bycopy_flag)
|
||||
[self _doEncodeBycopyObject:anObj];
|
||||
else if (byref_flag)
|
||||
[self _doEncodeByrefObject:anObj];
|
||||
else
|
||||
[self _doEncodeObject:anObj];
|
||||
[self encodeUnindent];
|
||||
|
||||
/* Find out if this object satisfies any forward references,
|
||||
and encode either the forward reference number, or a
|
||||
zero. NOTE: This test is here, and not before the
|
||||
_doEncode.., because the encoding of this object may,
|
||||
itself, generate a "forward reference" to this object,
|
||||
(ala the in_progress_table). That is, we cannot know
|
||||
whether this object satisfies a forward reference until
|
||||
after it has been encoded. */
|
||||
fref = [self _coderForwardReferenceForObject: anObj];
|
||||
if (fref)
|
||||
{
|
||||
/* It does satisfy a forward reference; write the forward
|
||||
reference number, so the decoder can know. */
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
/* Remove it from the forward reference table, since we'll never
|
||||
have another forward reference for this object. */
|
||||
[self _coderRemoveForwardReferenceForObject: anObj];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It does not satisfy any forward references. Let the
|
||||
decoder know this by encoding NULL. Note: in future
|
||||
encoding we may have backward references to this
|
||||
object, but we will never need forward references to
|
||||
this object. */
|
||||
unsigned null_fref = 0;
|
||||
[self encodeValueOfCType: @encode(unsigned)
|
||||
at: &null_fref
|
||||
withName: @"Object forward cross-reference number"];
|
||||
}
|
||||
|
||||
/* We're done encoding the object, it's no longer in progress.
|
||||
In GNU-style archiving, this method also calls
|
||||
-_coderInternalCreateReferenceForObject:. */
|
||||
[self _objectNoLongerInProgress: anObj];
|
||||
}
|
||||
}
|
||||
[self encodeUnindent];
|
||||
}
|
||||
|
||||
- (void) encodeObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:NO
|
||||
isByref:NO
|
||||
isForwardReference:NO];
|
||||
}
|
||||
|
||||
|
||||
- (void) encodeBycopyObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:YES
|
||||
isByref:NO
|
||||
isForwardReference:NO];
|
||||
}
|
||||
|
||||
- (void) encodeByrefObject: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:NO
|
||||
isByref:YES
|
||||
isForwardReference:NO];
|
||||
}
|
||||
|
||||
- (void) encodeObjectReference: anObj
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self _encodeObject:anObj
|
||||
withName:name
|
||||
isBycopy:NO
|
||||
isByref:NO
|
||||
isForwardReference:YES];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void) encodeWithName: (NSString*)name
|
||||
valuesOfObjCTypes: (const char *)types, ...
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
[self encodeName:name];
|
||||
va_start(ap, types);
|
||||
while (*types)
|
||||
{
|
||||
[self encodeValueOfObjCType:types
|
||||
at:va_arg(ap, void*)
|
||||
withName:@"Encoded Types Component"];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
- (void) encodeValueOfObjCTypes: (const char *)types
|
||||
at: (const void *)d
|
||||
withName: (NSString*)name
|
||||
{
|
||||
[self encodeName:name];
|
||||
while (*types)
|
||||
{
|
||||
[self encodeValueOfObjCType:types
|
||||
at:d
|
||||
withName:@"Encoded Types Component"];
|
||||
types = objc_skip_typespec(types);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) encodeArrayOfObjCType: (const char *)type
|
||||
count: (unsigned)c
|
||||
at: (const void *)d
|
||||
withName: (NSString*)name
|
||||
{
|
||||
int i;
|
||||
int offset = objc_sizeof_type(type);
|
||||
const char *where = d;
|
||||
|
||||
[self encodeName:name];
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
[self encodeValueOfObjCType:type
|
||||
at:where
|
||||
withName:@"Encoded Array Component"];
|
||||
where += offset;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) encodeIndent
|
||||
{
|
||||
[cstream encodeIndent];
|
||||
}
|
||||
|
||||
- (void) encodeUnindent
|
||||
{
|
||||
[cstream encodeUnindent];
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*)n
|
||||
{
|
||||
[cstream encodeName: n];
|
||||
}
|
||||
|
||||
|
||||
/* Substituting Classes */
|
||||
|
||||
- (NSString*) classNameEncodedForTrueClassName: (NSString*) trueName
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
|
||||
#if 0
|
||||
if (classname_2_classname)
|
||||
return NSMapGet (classname_2_classname, [trueName cString]);
|
||||
return trueName;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) encodeClassName: (NSString*) trueName
|
||||
intoClassName: (NSString*) inArchiveName
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
|
||||
#if 0
|
||||
/* The table should hold char*'s, not id's. */
|
||||
if (!classname_2_classname)
|
||||
classname_2_classname =
|
||||
NSCreateMapTable (NSObjectsMapKeyCallBacks,
|
||||
NSObjectsMapValueCallBacks, 0);
|
||||
NSMapInsert (classname_2_classname, trueName, inArchiveName);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (in_progress_table) NSFreeMapTable (in_progress_table);
|
||||
if (object_2_xref) NSFreeMapTable (object_2_xref);
|
||||
if (object_2_fref) NSFreeMapTable (object_2_fref);
|
||||
if (const_ptr_2_xref) NSFreeMapTable (const_ptr_2_xref);
|
||||
if (classname_2_classname) NSFreeMapTable (classname_2_classname);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,196 +0,0 @@
|
|||
/* Implementation of Machport-based port object for use with Connection
|
||||
Copyright (C) 1994, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: September 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/* This old code really needs work; it does not currently compile. */
|
||||
|
||||
#if __mach__
|
||||
|
||||
#include <config.h>
|
||||
#include <base/MachPort.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <base/Set.h>
|
||||
|
||||
#include <mach/cthreads.h>
|
||||
#include <mach/notify.h>
|
||||
|
||||
static Dictionary *portDictionary;
|
||||
static NSLock *portDictionaryGate;
|
||||
|
||||
@implementation MachPort
|
||||
|
||||
+ initialize
|
||||
{
|
||||
portDictionaryGate = [NSLock new];
|
||||
NSAssert(sizeof(int) == sizeof(port_t), NSInternalInconsistencyException);
|
||||
portDictionary = [[Dictionary alloc]
|
||||
initWithType:@encode(id)
|
||||
keyType:@encode(int)];
|
||||
return self;
|
||||
}
|
||||
|
||||
/* This not tested */
|
||||
static int
|
||||
listen_for_invalidation (any_t arg)
|
||||
{
|
||||
kern_return_t r;
|
||||
notification_t m;
|
||||
m.notify_header.msg_size = sizeof(notification_t);
|
||||
m.notify_header.msg_local_port = task_notify();
|
||||
for (;;)
|
||||
{
|
||||
r = msg_receive((msg_header_t*)&m, MSG_OPTION_NONE, 0);
|
||||
switch (r)
|
||||
{
|
||||
case RCV_SUCCESS:
|
||||
fprintf(stderr, "notification id %d\n", (int)m.notify_header.msg_id);
|
||||
break;
|
||||
case RCV_TIMED_OUT:
|
||||
fprintf(stderr, "notification msg_receive timed out\n");
|
||||
exit(-1);
|
||||
default:
|
||||
mach_error("notification", r);
|
||||
exit(-1);
|
||||
}
|
||||
switch (m.notify_header.msg_id)
|
||||
{
|
||||
case NOTIFY_PORT_DELETED:
|
||||
[[MachPort newFromMachPort:m.notify_port] invalidate];
|
||||
break;
|
||||
case NOTIFY_MSG_ACCEPTED:
|
||||
break;
|
||||
case NOTIFY_PORT_DESTROYED:
|
||||
[[MachPort newFromMachPort:m.notify_port] invalidate];
|
||||
break;
|
||||
default:
|
||||
mach_error("notification", r);
|
||||
exit(-1);
|
||||
}
|
||||
/* Where do we free the object? */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This not tested */
|
||||
+ listenForPortInvalidation
|
||||
{
|
||||
MachPort *listenPort = [MachPort new];
|
||||
task_set_special_port(task_self(), TASK_NOTIFY_PORT, [listenPort mach_port]);
|
||||
cthread_detach(cthread_fork((any_t)listen_for_invalidation, (any_t)0));
|
||||
return self;
|
||||
}
|
||||
|
||||
/* designated initializer */
|
||||
+ newFromMachPort: (port_t)p dealloc: (BOOL)f
|
||||
{
|
||||
MachPort *aPort;
|
||||
[portDictionaryGate lock];
|
||||
if ((aPort = [portDictionary elementAtKey:(int)p]))
|
||||
{
|
||||
[portDictionaryGate unlock];
|
||||
[aPort addReference];
|
||||
return aPort;
|
||||
}
|
||||
aPort = [[self alloc] init];
|
||||
aPort->mach_port = p;
|
||||
aPort->deallocate = f;
|
||||
[portDictionary addElement:aPort atKey:(int)p];
|
||||
[portDictionaryGate unlock];
|
||||
return aPort;
|
||||
}
|
||||
|
||||
+ newFromMachPort: (port_t)p
|
||||
{
|
||||
return [self newFromMachPort:p dealloc:NO];
|
||||
}
|
||||
|
||||
+ new
|
||||
{
|
||||
kern_return_t error;
|
||||
port_t p;
|
||||
|
||||
if ((error=port_allocate(task_self(), &p)) != KERN_SUCCESS) {
|
||||
mach_error("port_allocate failed", error);
|
||||
exit(1);
|
||||
}
|
||||
return [self newFromMachPort:p];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[aCoder encodeValueOfCType: @encode(BOOL)
|
||||
at: &deallocate
|
||||
withName: @""];
|
||||
[aCoder encodeMachPort: mach_port];
|
||||
}
|
||||
|
||||
+ newWithCoder: aCoder
|
||||
{
|
||||
BOOL f;
|
||||
port_t mp;
|
||||
MachPort *p;
|
||||
|
||||
[aCoder decodeValueOfCType: @encode(BOOL)
|
||||
at: &f
|
||||
withName: NULL];
|
||||
[aCoder decodeMachPort: &mp];
|
||||
|
||||
p = [MachPort newFromMachPort:mp dealloc:f];
|
||||
return p;
|
||||
}
|
||||
|
||||
- (unsigned) hash
|
||||
{
|
||||
/* What should this be? */
|
||||
return (unsigned)self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (refcount-1 == 0)
|
||||
{
|
||||
[portDictionaryGate lock];
|
||||
[portDictionaryGate removeElementAtKey:(int)machPort];
|
||||
[portDictionaryGate unlock];
|
||||
if (deallocate)
|
||||
{
|
||||
kern_return_t error;
|
||||
error = port_deallocate(task_self(), machPort);
|
||||
if (error != KERN_SUCCESS) {
|
||||
mach_error("port_deallocate failed", error);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
[super dealloc];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (mach_port_t) machPort
|
||||
{
|
||||
return mach_port;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __mach__ */
|
|
@ -1,435 +0,0 @@
|
|||
/* Implementation of GNU Objective C memory stream
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/Coder.h>
|
||||
#include <Foundation/NSData.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Deal with memchr: */
|
||||
#if STDC_HEADERS || HAVE_STRING_H
|
||||
#include <string.h>
|
||||
/* An ANSI string.h and pre-ANSI memory.h might conflict. */
|
||||
#if !STDC_HEADERS && HAVE_MEMORY_H
|
||||
#include <memory.h>
|
||||
#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
|
||||
#define rindex strrchr
|
||||
#define bcopy(s, d, n) memcpy ((d), (s), (n))
|
||||
#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
|
||||
#define bzero(s, n) memset ((s), 0, (n))
|
||||
#else /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
#include <strings.h>
|
||||
/* memory.h and strings.h conflict on some systems. */
|
||||
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
|
||||
#define DEFAULT_MEMORY_STREAM_SIZE 64
|
||||
|
||||
extern int
|
||||
o_vscanf (void *stream,
|
||||
int (*inchar_func)(void*),
|
||||
void (*unchar_func)(void*,int),
|
||||
const char *format, va_list argptr);
|
||||
|
||||
static BOOL debug_memory_stream = NO;
|
||||
|
||||
/* A pretty stupid implementation based on realloc(), but it works for now. */
|
||||
|
||||
@implementation MemoryStream
|
||||
|
||||
+ (MemoryStream*)streamWithData: (id)anObject
|
||||
{
|
||||
return [[[MemoryStream alloc] initWithData:anObject] autorelease];
|
||||
}
|
||||
|
||||
- (id) data
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/* xxx This interface will change */
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
freeWhenDone: (BOOL)f
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* never read/write before this position */
|
||||
position: (unsigned)i /* current position for reading/writing */
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
if (b)
|
||||
if (f)
|
||||
data = [[NSMutableData alloc] initWithBytesNoCopy: b length: s];
|
||||
else
|
||||
data = [[NSMutableData alloc] initWithBytes: b length: s];
|
||||
else
|
||||
{
|
||||
data = [[NSMutableData alloc] initWithCapacity: s];
|
||||
if (data)
|
||||
[data setLength: s];
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
prefix = p;
|
||||
position = i;
|
||||
eof_position = l;
|
||||
isMutable = YES;
|
||||
if ([data length] < prefix + MAX(position, eof_position))
|
||||
[data setLength: prefix + MAX(position, eof_position)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self release];
|
||||
self = nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- _initOnMallocBuffer: (char*)b
|
||||
size: (unsigned)s /* size of malloc'ed buffer */
|
||||
eofPosition: (unsigned)l /* length of buffer with data for reading */
|
||||
prefix: (unsigned)p /* never read/write before this position */
|
||||
position: (unsigned)i /* current position for reading/writing */
|
||||
{
|
||||
return [self _initOnMallocBuffer: b
|
||||
freeWhenDone: YES
|
||||
size: s
|
||||
eofPosition: l
|
||||
prefix: p
|
||||
position: i];
|
||||
}
|
||||
|
||||
/* xxx This method will disappear. */
|
||||
#if 0
|
||||
- initWithSize: (unsigned)s
|
||||
prefix: (unsigned)p
|
||||
position: (unsigned)i
|
||||
{
|
||||
return [self _initOnMallocBuffer: 0
|
||||
freeWhenDone: YES
|
||||
size: s
|
||||
eofPosition: i
|
||||
prefix: p
|
||||
position: i];
|
||||
}
|
||||
#endif
|
||||
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
prefix: (unsigned)p
|
||||
{
|
||||
return [self _initOnMallocBuffer: 0
|
||||
freeWhenDone: YES
|
||||
size: capacity
|
||||
eofPosition: 0
|
||||
prefix: p
|
||||
position: 0];
|
||||
}
|
||||
|
||||
- initWithCapacity: (unsigned)capacity
|
||||
{
|
||||
return [self _initOnMallocBuffer: 0
|
||||
freeWhenDone: YES
|
||||
size: capacity
|
||||
eofPosition: 0
|
||||
prefix: 0
|
||||
position: 0];
|
||||
}
|
||||
|
||||
- initWithData: (id)anObject
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
if (anObject && [anObject isKindOfClass:[NSData class]])
|
||||
{
|
||||
data = [anObject retain];
|
||||
if ([data isKindOfClass:[NSMutableData class]])
|
||||
isMutable = YES;
|
||||
eof_position = [data length];
|
||||
position = 0;
|
||||
prefix = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self dealloc];
|
||||
self = nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#if 0
|
||||
- initWithSize: (unsigned)s
|
||||
{
|
||||
return [self initWithCapacity:s];
|
||||
}
|
||||
#endif
|
||||
|
||||
- init
|
||||
{
|
||||
return [self initWithCapacity: DEFAULT_MEMORY_STREAM_SIZE];
|
||||
}
|
||||
|
||||
- (BOOL) isWritable
|
||||
{
|
||||
return isMutable;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
+ newWithCoder: aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) mutableData
|
||||
{
|
||||
if (isMutable)
|
||||
return data;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (int) writeBytes: (const void*)b length: (int)l
|
||||
{
|
||||
unsigned size;
|
||||
|
||||
if (isMutable)
|
||||
{
|
||||
size = [data capacity];
|
||||
if (prefix+position+l > size)
|
||||
{
|
||||
size = MAX(prefix+position+l, size*2);
|
||||
[data setCapacity: size];
|
||||
}
|
||||
if (position+prefix+l > [data length])
|
||||
[data setLength: position+prefix+l];
|
||||
memcpy([data mutableBytes]+prefix+position, b, l);
|
||||
position += l;
|
||||
if (position > eof_position)
|
||||
eof_position = position;
|
||||
return l;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int) readBytes: (void*)b length: (int)l
|
||||
{
|
||||
if (position+l > eof_position)
|
||||
l = eof_position-position;
|
||||
memcpy(b, [data bytes]+prefix+position, l);
|
||||
position += l;
|
||||
return l;
|
||||
}
|
||||
|
||||
- (NSString*) readLine
|
||||
{
|
||||
char *nl = memchr([data bytes]+prefix+position, '\n', eof_position-position);
|
||||
char *ret = NULL;
|
||||
if (nl)
|
||||
{
|
||||
int len = nl-((char*)[data bytes])-prefix-position;
|
||||
ret = objc_malloc (len+1);
|
||||
strncpy(ret, ((char*)[data bytes])+prefix+position, len);
|
||||
ret[len] = '\0';
|
||||
position += len+1;
|
||||
}
|
||||
return [[[NSString alloc] initWithCStringNoCopy: ret
|
||||
length: strlen (ret)
|
||||
freeWhenDone: YES]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
/* Making these nested functions (which is what I'd like to do) is
|
||||
crashing the va_arg stuff in vscanf(). Why? */
|
||||
#define MS ((MemoryStream*)s)
|
||||
|
||||
int outchar_func(void *s, int c)
|
||||
{
|
||||
if (MS->isMutable)
|
||||
{
|
||||
if (MS->prefix + MS->position >= [MS->data capacity])
|
||||
return EOF;
|
||||
((char*)[MS->data mutableBytes])[MS->prefix + MS->position++] = (char)c;
|
||||
return 1;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int inchar_func(void *s)
|
||||
{
|
||||
if (MS->prefix + MS->position >= [MS->data length])
|
||||
return EOF;
|
||||
return (int) ((char*)[MS->data bytes])[MS->prefix + MS->position++];
|
||||
}
|
||||
|
||||
void unchar_func(void *s, int c)
|
||||
{
|
||||
if (MS->position > 0)
|
||||
MS->position--;
|
||||
if (MS->isMutable)
|
||||
((char*)[MS->data mutableBytes])[MS->prefix + MS->position] = (char)c;
|
||||
}
|
||||
|
||||
#if HAVE_VSPRINTF
|
||||
- (int) writeFormat: (NSString*)format
|
||||
arguments: (va_list)arg
|
||||
{
|
||||
unsigned size;
|
||||
int ret;
|
||||
|
||||
if (!isMutable)
|
||||
return 0;
|
||||
/* xxx Using this ugliness we at least let ourselves safely print
|
||||
formatted strings up to 128 bytes long.
|
||||
It's digusting, though, and we need to fix it.
|
||||
Using GNU stdio streams would do the trick.
|
||||
*/
|
||||
size = [data capacity];
|
||||
if (size - (prefix + position) < 128)
|
||||
size = MAX(size+128, size*2);
|
||||
[data setLength: size];
|
||||
|
||||
ret = VSPRINTF_LENGTH (vsprintf([data mutableBytes]+prefix+position,
|
||||
[format cString], arg));
|
||||
position += ret;
|
||||
/* xxx Make sure we didn't overrun our buffer.
|
||||
As per above kludge, this would happen if we happen to have more than
|
||||
128 bytes left in the buffer and we try to write a string longer than
|
||||
the num bytes left in the buffer. */
|
||||
NSAssert(prefix + position <= [data capacity], @"buffer overrun");
|
||||
if (position > eof_position)
|
||||
eof_position = position;
|
||||
[data setLength:eof_position + prefix];
|
||||
if (debug_memory_stream)
|
||||
{
|
||||
*(char*)([data mutableBytes]+prefix+position) = '\0';
|
||||
fprintf(stderr, "%s\n", (char*)[data mutableBytes]+prefix);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (int) readFormat: (NSString*)format, ...
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = o_vscanf(self, inchar_func, unchar_func,
|
||||
[format cString], ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)mode
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case STREAM_SEEK_FROM_START:
|
||||
position = i;
|
||||
break;
|
||||
case STREAM_SEEK_FROM_CURRENT:
|
||||
position += i;
|
||||
break;
|
||||
case STREAM_SEEK_FROM_END:
|
||||
position = eof_position + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (unsigned) streamPosition
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
[self flushStream];
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[data release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL) streamEof
|
||||
{
|
||||
if (position == eof_position)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (unsigned) streamBufferCapacity
|
||||
{
|
||||
if (isMutable)
|
||||
return [data capacity];
|
||||
return [data length];
|
||||
}
|
||||
|
||||
- (char*) streamBuffer
|
||||
{
|
||||
if (isMutable)
|
||||
return (char*)[data mutableBytes];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void) setStreamBufferCapacity: (unsigned)s
|
||||
{
|
||||
if (isMutable)
|
||||
if (s > prefix + eof_position)
|
||||
[data setCapacity:s];
|
||||
}
|
||||
|
||||
- (unsigned) streamEofPosition
|
||||
{
|
||||
return eof_position;
|
||||
}
|
||||
|
||||
- (void) setStreamEofPosition: (unsigned)i
|
||||
{
|
||||
if (i < [data length] - prefix)
|
||||
eof_position = i;
|
||||
}
|
||||
|
||||
- (unsigned) streamBufferPrefix
|
||||
{
|
||||
return prefix;
|
||||
}
|
||||
|
||||
- (unsigned) streamBufferLength
|
||||
{
|
||||
return prefix + eof_position;
|
||||
}
|
||||
|
||||
@end
|
210
Source/Port.m
210
Source/Port.m
|
@ -1,210 +0,0 @@
|
|||
/* Implementation of abstract superclass port for use with Connection
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/Port.h>
|
||||
#include <base/Coder.h> /* for Coding protocol in Object category */
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
@implementation Port
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_is_valid = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
+ (Class) outPacketClass
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) outPacketClass
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) classForPortCoder
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy,
|
||||
i.e. as our own class, not a Proxy class. */
|
||||
return [self class];
|
||||
}
|
||||
- replacementObjectForPortCoder: aRmc
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (id <Encoding>)anEncoder
|
||||
{
|
||||
[super encodeWithCoder: anEncoder];
|
||||
/* xxx What else? */
|
||||
}
|
||||
|
||||
- initWithCoder: (id <Decoding>)coder
|
||||
{
|
||||
self = [super initWithCoder: coder];
|
||||
/* xxx What else? */
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation InPort
|
||||
|
||||
- init
|
||||
{
|
||||
[super init];
|
||||
_packet_invocation = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name fromPort: (int)port
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ newForReceiving
|
||||
{
|
||||
return [self newForReceivingFromRegisteredName: nil];
|
||||
}
|
||||
|
||||
- receivePacketWithTimeout: (int)milliseconds
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) setReceivedPacketInvocation: (id)invocation
|
||||
{
|
||||
NSAssert(!_packet_invocation, NSInternalInconsistencyException);
|
||||
_packet_invocation = invocation;
|
||||
}
|
||||
|
||||
- (void) addToRunLoop: run_loop forMode: (NSString*)mode
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) removeFromRunLoop: run_loop forMode: (NSString*)mode
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OutPort
|
||||
|
||||
+ newForSendingToRegisteredName: (NSString*)name
|
||||
onHost: (NSString*)hostname
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL) sendPacket: packet timeout: (NSTimeInterval)t
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation InPacket
|
||||
|
||||
/* The designated initializer. */
|
||||
- initForReceivingWithCapacity: (unsigned)c
|
||||
receivingInPort: ip
|
||||
replyOutPort: op
|
||||
{
|
||||
self = [super initWithCapacity: c prefix: 0];
|
||||
if (self)
|
||||
{
|
||||
NSAssert([op isValid], NSInternalInconsistencyException);
|
||||
NSAssert(!ip || [ip isValid], NSInternalInconsistencyException);
|
||||
_reply_out_port = op;
|
||||
_receiving_in_port = ip;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- replyOutPort
|
||||
{
|
||||
return _reply_out_port;
|
||||
}
|
||||
|
||||
- receivingInPort
|
||||
{
|
||||
return _receiving_in_port;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation OutPacket
|
||||
|
||||
/* The designated initializer. */
|
||||
- initForSendingWithCapacity: (unsigned)c
|
||||
replyInPort: ip
|
||||
{
|
||||
self = [super initWithCapacity: c prefix: [[self class] prefixSize]];
|
||||
if (self)
|
||||
{
|
||||
NSAssert([ip isValid], NSInternalInconsistencyException);
|
||||
_reply_in_port = ip;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (unsigned) prefixSize
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- replyInPort
|
||||
{
|
||||
return _reply_in_port;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
/* Implementation of GNU Objective-C raw-binary stream for archiving
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/* Use this CStream subclass when you are encoding/decoding on the
|
||||
same architecture, and you care about time and space.
|
||||
WARNING: This encoding is *not* machine-independent. */
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/RawCStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <base/NSException.h>
|
||||
|
||||
#define DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
@implementation RawCStream
|
||||
|
||||
|
||||
/* For debugging */
|
||||
|
||||
static BOOL debug_binary_coder;
|
||||
|
||||
+ setDebugging: (BOOL)f
|
||||
{
|
||||
debug_binary_coder = f;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ debugStderrCoder
|
||||
{
|
||||
static id c = nil;
|
||||
|
||||
if (!c)
|
||||
c = [[TextCStream alloc]
|
||||
initForWritingToStream: [StdioStream standardError]];
|
||||
return c;
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*) name
|
||||
{
|
||||
if (debug_binary_coder)
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeName:name];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
- (void) encodeValueOfCType: (const char*)type
|
||||
at: (const void*)d
|
||||
withName: (NSString*) name
|
||||
{
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType:type
|
||||
at:d
|
||||
withName:name];
|
||||
}
|
||||
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to encode an \"ObjC\" type");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
int length = strlen(*(char**)d);
|
||||
[self encodeValueOfCType:@encode(int)
|
||||
at:&length withName:@"BinaryCStream char* length"];
|
||||
[stream writeBytes:*(char**)d length:length];
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream writeByte:*(unsigned char*)d];
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
case _C_USHT:
|
||||
[stream writeBytes:d length:sizeof(short)];
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
case _C_UINT:
|
||||
[stream writeBytes:d length:sizeof(int)];
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
case _C_ULNG:
|
||||
[stream writeBytes:d length:sizeof(long)];
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
[stream writeBytes:d length:sizeof(float)];
|
||||
break;
|
||||
|
||||
case _C_DBL:
|
||||
[stream writeBytes:d length:sizeof(double)];
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi (type+1); /* xxx why +1 ? */
|
||||
int offset;
|
||||
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
/* Change this so we don't re-write type info every time. */
|
||||
[self encodeValueOfCType: type
|
||||
at: d
|
||||
withName: NULL];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self encodeValueOfCType: type
|
||||
at: ((char*)d)+acc_size
|
||||
withName: NULL];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"Unrecognized Type %s", type];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) decodeValueOfCType: (const char*)type
|
||||
at: (void*)d
|
||||
withName: (NSString* *)namePtr
|
||||
{
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to decode an \"ObjC\" type");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_CHARPTR:
|
||||
{
|
||||
int length;
|
||||
[self decodeValueOfCType:@encode(int)
|
||||
at:&length withName:NULL];
|
||||
OBJC_MALLOC(*(char**)d, char, length+1);
|
||||
[stream readBytes:*(char**)d length:length];
|
||||
(*(char**)d)[length] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
case _C_CHR:
|
||||
case _C_UCHR:
|
||||
[stream readByte:d];
|
||||
break;
|
||||
|
||||
case _C_SHT:
|
||||
case _C_USHT:
|
||||
[stream readBytes:d length:sizeof(short)];
|
||||
break;
|
||||
|
||||
case _C_INT:
|
||||
case _C_UINT:
|
||||
[stream readBytes:d length:sizeof(int)];
|
||||
break;
|
||||
|
||||
case _C_LNG:
|
||||
case _C_ULNG:
|
||||
[stream readBytes:d length:sizeof(long)];
|
||||
break;
|
||||
|
||||
case _C_FLT:
|
||||
[stream readBytes:d length:sizeof(float)];
|
||||
break;
|
||||
|
||||
case _C_DBL:
|
||||
[stream readBytes:d length:sizeof(double)];
|
||||
break;
|
||||
|
||||
case _C_ARY_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||
int len = atoi(type+1);
|
||||
int offset;
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
[self decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space just like char* ? No. */
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
const char *save_type = type;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self decodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:namePtr];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
type = save_type;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
[self error:"Unrecognized Type %s", type];
|
||||
}
|
||||
|
||||
if (debug_binary_coder)
|
||||
{
|
||||
[[[self class] debugStderrCoder]
|
||||
encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"decoding unnamed"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *)n
|
||||
{
|
||||
#if 1
|
||||
if (n)
|
||||
*n = nil;
|
||||
#else
|
||||
if (n)
|
||||
*n = [[[NSString alloc] init] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,309 +0,0 @@
|
|||
/* Implementation of GNU Objective C stdio stream
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Date: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#ifndef _REENTRANT
|
||||
#define _REENTRANT
|
||||
#endif
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <base/Coder.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSDebug.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> /* SEEK_* on SunOS 4 */
|
||||
|
||||
enum {
|
||||
STREAM_READONLY = 0,
|
||||
STREAM_READWRITE,
|
||||
STREAM_WRITEONLY
|
||||
};
|
||||
|
||||
extern int
|
||||
o_vscanf (void *stream,
|
||||
int (*inchar_func)(void*),
|
||||
void (*unchar_func)(void*,int),
|
||||
const char *format, va_list argptr);
|
||||
|
||||
@implementation StdioStream
|
||||
|
||||
+ standardIn
|
||||
{
|
||||
static id stdinStream = nil;
|
||||
|
||||
if (!stdinStream)
|
||||
stdinStream = [[self alloc] initWithFilePointer:stdin fmode:"r"];
|
||||
return stdinStream;
|
||||
}
|
||||
|
||||
+ standardOut
|
||||
{
|
||||
static id stdoutStream = nil;
|
||||
|
||||
if (!stdoutStream)
|
||||
stdoutStream = [[self alloc] initWithFilePointer:stdout fmode:"w"];
|
||||
return stdoutStream;
|
||||
}
|
||||
|
||||
+ standardError
|
||||
{
|
||||
static id stderrStream = nil;
|
||||
|
||||
if (!stderrStream)
|
||||
stderrStream = [[self alloc] initWithFilePointer:stderr fmode:"w"];
|
||||
return stderrStream;
|
||||
}
|
||||
|
||||
+ streamWithFilename: (NSString*)name fmode: (const char *)m
|
||||
{
|
||||
return [[[self alloc]
|
||||
initWithFilename: name fmode: m]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- initWithFilePointer: (FILE*)afp fmode: (const char *)mo
|
||||
{
|
||||
#if 0
|
||||
/* xxx Is this portable? I don't think so.
|
||||
How do I find out if a FILE* is open for reading/writing?
|
||||
I want to get rid of the "mode" instance variable. */
|
||||
if (afp->_flag & _IOREAD)
|
||||
mode = STREAM_READONLY;
|
||||
else if (afp->_flag & _IOWRT)
|
||||
mode = STREAM_WRITEONLY;
|
||||
else
|
||||
mode = STREAM_READWRITE;
|
||||
#else
|
||||
if (!strcmp(mo, "rw"))
|
||||
mode = STREAM_READWRITE;
|
||||
else if (*mo == 'r')
|
||||
mode = STREAM_READONLY;
|
||||
else if (*mo == 'w')
|
||||
mode = STREAM_WRITEONLY;
|
||||
#endif
|
||||
[super init];
|
||||
fp = afp;
|
||||
return self;
|
||||
}
|
||||
|
||||
- initWithFilename: (NSString*)name fmode: (const char *)m
|
||||
{
|
||||
FILE *afp = fopen([name cString], (char*)m);
|
||||
if (!afp)
|
||||
{
|
||||
id message;
|
||||
|
||||
message = [[NSString alloc] initWithFormat: @"Stream: %s",
|
||||
strerror(errno)];
|
||||
NSLog(message);
|
||||
[message release];
|
||||
[super dealloc];
|
||||
return nil;
|
||||
}
|
||||
return [self initWithFilePointer:afp fmode:m];
|
||||
}
|
||||
|
||||
- initWithFileDescriptor: (int)fd fmode: (const char *)m
|
||||
{
|
||||
FILE *afp = fdopen(fd, (char*)m);
|
||||
if (!afp)
|
||||
{
|
||||
id message;
|
||||
|
||||
message = [[NSString alloc] initWithFormat: @"Stream: %s",
|
||||
strerror(errno)];
|
||||
NSLog(message);
|
||||
[message release];
|
||||
[super dealloc];
|
||||
return nil;
|
||||
}
|
||||
return [self initWithFilePointer:afp fmode:m];
|
||||
}
|
||||
|
||||
- initWithPipeTo: (NSString*) systemCommand
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
return nil;
|
||||
#else
|
||||
return [self initWithFilePointer:
|
||||
popen([systemCommand cString], "w")
|
||||
fmode:"w"];
|
||||
#endif
|
||||
}
|
||||
|
||||
- initWithPipeFrom: (NSString*) systemCommand
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
return nil;
|
||||
#else
|
||||
return [self initWithFilePointer:
|
||||
popen([systemCommand cString], "r")
|
||||
fmode:"r"];
|
||||
#endif
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
return [self initWithFilePointer:stdout fmode:"w"];
|
||||
}
|
||||
|
||||
- (int) writeBytes: (const void*)b length: (int)len
|
||||
{
|
||||
int ret = fwrite (b, 1, len, fp);
|
||||
if (ferror(fp))
|
||||
{
|
||||
[NSException raise: StreamException
|
||||
format: @"%s", strerror(errno)];
|
||||
}
|
||||
else if (ret != len)
|
||||
{
|
||||
[NSException raise: StreamException
|
||||
format: @"Write bytes differ"];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (int) readBytes: (void*)b length: (int)len
|
||||
{
|
||||
int ret = fread (b, 1, len, fp);
|
||||
if (ferror(fp))
|
||||
{
|
||||
[NSException raise: StreamException
|
||||
format: @"%s", strerror(errno)];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (int) writeFormat: (NSString*)format
|
||||
arguments: (va_list)arg
|
||||
{
|
||||
return vfprintf(fp, [format cString], arg);
|
||||
}
|
||||
|
||||
static int
|
||||
stdio_inchar_func(void *s)
|
||||
{
|
||||
return getc((FILE*)s);
|
||||
}
|
||||
static void
|
||||
stdio_unchar_func(void *s, int c)
|
||||
{
|
||||
ungetc(c, (FILE*)s);
|
||||
}
|
||||
|
||||
- (int) readFormat: (NSString*)format, ...
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
/* Wow. Why does putting in these nested functions crash the
|
||||
va_arg stuff in vscanf? */
|
||||
#if 0
|
||||
int inchar_func()
|
||||
{
|
||||
return getc(fp);
|
||||
}
|
||||
void unchar_func(int c)
|
||||
{
|
||||
ungetc(c, fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
va_start(ap, format);
|
||||
ret = o_vscanf(fp, stdio_inchar_func, stdio_unchar_func,
|
||||
[format cString], ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (void) flushStream
|
||||
{
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
fclose(fp);
|
||||
fp = 0;
|
||||
}
|
||||
|
||||
- (BOOL) isClosed
|
||||
{
|
||||
/* xxx How should this be implemented? */
|
||||
[self notImplemented:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
/* xxx Add "- (BOOL) isOpen" method? */
|
||||
|
||||
- (void) rewindStream
|
||||
{
|
||||
rewind(fp);
|
||||
}
|
||||
|
||||
- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)m
|
||||
{
|
||||
fseek(fp, i, m + SEEK_SET - STREAM_SEEK_FROM_START);
|
||||
}
|
||||
|
||||
- (unsigned) streamPosition
|
||||
{
|
||||
return ftell(fp);
|
||||
}
|
||||
|
||||
- (BOOL) isAtEof
|
||||
{
|
||||
if (feof(fp))
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) isWritable
|
||||
{
|
||||
if (mode)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (fp != 0)
|
||||
fclose(fp);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: (Coder*)anEncoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: (Coder*)aDecoder
|
||||
{
|
||||
[self notImplemented:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
168
Source/Stream.m
168
Source/Stream.m
|
@ -1,168 +0,0 @@
|
|||
/* Implementation of GNU Objective C byte stream
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/Stream.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/Coder.h>
|
||||
#include <base/NSString.h>
|
||||
|
||||
@implementation Stream
|
||||
|
||||
/* This is the designated initializer. */
|
||||
- init
|
||||
{
|
||||
return [super init];
|
||||
}
|
||||
|
||||
- (int) writeByte: (unsigned char)b
|
||||
{
|
||||
return [self writeBytes:&b length:1];
|
||||
}
|
||||
|
||||
- (int) readByte: (unsigned char*)b
|
||||
{
|
||||
return [self readBytes:b length:1];
|
||||
}
|
||||
|
||||
- (int) writeBytes: (const void*)b length: (int)l
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int) readBytes: (void*)b length: (int)l
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int) writeFormat: (NSString*)format
|
||||
arguments: (va_list)arg
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int) writeFormat: (NSString*)format, ...
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = [self writeFormat: format arguments: ap];
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (int) readFormat: (NSString*)format
|
||||
arguments: (va_list)arg
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int) readFormat: (NSString*)format, ...
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void) writeLine: (NSString*)l
|
||||
{
|
||||
const char *s = [l cString];
|
||||
[self writeBytes:s length:strlen(s)];
|
||||
[self writeBytes:"\n" length:1];
|
||||
}
|
||||
|
||||
- (NSString*) readLine
|
||||
{
|
||||
char *l;
|
||||
[self readFormat: @"%a[^\n]\n", &l];
|
||||
return [[[NSString alloc] initWithCStringNoCopy: l
|
||||
length: strlen (l)
|
||||
freeWhenDone: YES]
|
||||
autorelease];
|
||||
}
|
||||
|
||||
- (void) flushStream
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
- (void) close
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
- (BOOL) isClosed
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) setStreamPosition: (unsigned)i seekMode: (seek_mode_t)mode
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- (void) setStreamPosition: (unsigned)i
|
||||
{
|
||||
[self setStreamPosition: i seekMode: STREAM_SEEK_FROM_START];
|
||||
}
|
||||
|
||||
- (void) rewindStream
|
||||
{
|
||||
[self setStreamPosition:0];
|
||||
}
|
||||
|
||||
- (unsigned) streamPosition
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL) isAtEof
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) isWritable
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: anEncoder
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
}
|
||||
|
||||
- initWithCoder: aDecoder
|
||||
{
|
||||
[self subclassResponsibility:_cmd];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
1609
Source/TcpPort.m
1609
Source/TcpPort.m
File diff suppressed because it is too large
Load diff
|
@ -1,421 +0,0 @@
|
|||
/* Implementation of GNU Objective-C text stream object for use serializing
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Written: Jan 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <base/NSString.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
#define DEFAULT_FORMAT_VERSION 0
|
||||
|
||||
static BOOL debug_textcoder = NO;
|
||||
|
||||
@implementation TextCStream
|
||||
|
||||
|
||||
/* Encoding/decoding C values */
|
||||
|
||||
#define XSTR(s) STR(s)
|
||||
#define STR(s) #s
|
||||
|
||||
#define ATXSTR(s) ATSTR(s)
|
||||
#define ATSTR(s) @#s
|
||||
|
||||
#define ROUND(V, A) \
|
||||
({ typeof(V) __v=(V); typeof(A) __a=(A); \
|
||||
__a*((__v+__a-1)/__a); })
|
||||
|
||||
#define ENCODER_FORMAT(TYPE, CONVERSION) \
|
||||
@"%*s<%s> (" ATXSTR(TYPE) @") = %" ATXSTR(CONVERSION) @"\n"
|
||||
|
||||
- (void) encodeValueOfCType: (const char*) type
|
||||
at: (const void*) d
|
||||
withName: (NSString*) name;
|
||||
{
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to encode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to encode an \"ObjC\" type");
|
||||
|
||||
if (!name || [name length] == 0)
|
||||
name = @"Anonymous";
|
||||
switch (*type)
|
||||
{
|
||||
case _C_LNG:
|
||||
[stream writeFormat:@"%*s<%s> (long) = %ld\n",
|
||||
indentation, "", [name cString], *(long*)d];
|
||||
break;
|
||||
case _C_ULNG:
|
||||
[stream writeFormat:@"%*s<%s> (unsigned long) = %lu\n",
|
||||
indentation, "", [name cString], *(unsigned long*)d];
|
||||
break;
|
||||
case _C_INT:
|
||||
[stream writeFormat:@"%*s<%s> (int) = %d\n",
|
||||
indentation, "", [name cString], *(int*)d];
|
||||
break;
|
||||
case _C_UINT:
|
||||
[stream writeFormat:@"%*s<%s> (unsigned int) = %u\n",
|
||||
indentation, "", [name cString], *(unsigned int*)d];
|
||||
break;
|
||||
case _C_SHT:
|
||||
[stream writeFormat:@"%*s<%s> (short) = %d\n",
|
||||
indentation, "", [name cString], (int)*(short*)d];
|
||||
break;
|
||||
case _C_USHT:
|
||||
[stream writeFormat:@"%*s<%s> (unsigned short) = %u\n",
|
||||
indentation, "", [name cString],
|
||||
(unsigned)*(unsigned short*)d];
|
||||
break;
|
||||
case _C_CHR:
|
||||
[stream writeFormat:@"%*s<%s> (char) = %c (0x%x)\n",
|
||||
indentation, "", [name cString],
|
||||
*(char*)d, (unsigned)*(char*)d];
|
||||
break;
|
||||
case _C_UCHR:
|
||||
[stream writeFormat:@"%*s<%s> (unsigned char) = 0x%x\n",
|
||||
indentation, "", [name cString],
|
||||
(unsigned)*(unsigned char*)d];
|
||||
break;
|
||||
case _C_FLT:
|
||||
[stream writeFormat:@"%*s<%s> (float) = %g\n",
|
||||
indentation, "", [name cString], *(float*)d];
|
||||
break;
|
||||
case _C_DBL:
|
||||
[stream writeFormat:@"%*s<%s> (double) = %g\n",
|
||||
indentation, "", [name cString], *(double*)d];
|
||||
break;
|
||||
case _C_CHARPTR:
|
||||
[stream writeFormat:@"%*s<%s> (char*) = \"%s\"\n",
|
||||
indentation, "", [name cString], *(char**)d];
|
||||
break;
|
||||
case _C_ARY_B:
|
||||
{
|
||||
int len = atoi (type+1); /* xxx why +1 ? */
|
||||
int offset;
|
||||
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
while (len-- > 0)
|
||||
{
|
||||
/* Change this so we don't re-write type info every time. */
|
||||
[self encodeValueOfCType:type
|
||||
at:d
|
||||
withName:@"array component"];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
[self encodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
[self encodeName:name];
|
||||
[self encodeIndent];
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self encodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:@"structure component"];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
[self encodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_PTR:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Cannot encode pointers"];
|
||||
break;
|
||||
#if 0 /* No, don't know how far to recurse */
|
||||
[self encodeValueOfObjCType:type+1 at:*(char**)d withName:name];
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"type %s not implemented", type];
|
||||
}
|
||||
}
|
||||
|
||||
#define DECODER_FORMAT(TYPE, CONVERSION) \
|
||||
@" <%a[^>]> (" ATXSTR(TYPE) @") = %" ATXSTR(CONVERSION) @" \n"
|
||||
|
||||
#define DECODE_ERROR(TYPE) \
|
||||
{ \
|
||||
id line = [stream readLine]; \
|
||||
[NSException raise: NSGenericException \
|
||||
format: @"bad format decoding " ATXSTR(TYPE) @".\n" \
|
||||
@"Looking at %s\n.", \
|
||||
[line cString]]; \
|
||||
}
|
||||
|
||||
|
||||
#define DECODE_DEBUG(TYPE, CONVERSION) \
|
||||
if (debug_textcoder) \
|
||||
[[StdioStream standardError] writeFormat: \
|
||||
@"got <%s> (%s) %" ATXSTR(CONVERSION) @"\n", \
|
||||
tmpname, \
|
||||
XSTR(TYPE), *(TYPE*)d];
|
||||
|
||||
- (void) decodeValueOfCType: (const char*) type
|
||||
at: (void*) d
|
||||
withName: (NSString* *) namePtr;
|
||||
{
|
||||
char *tmpname;
|
||||
|
||||
if (!type)
|
||||
[NSException raise:NSInvalidArgumentException format:@"type is NULL"];
|
||||
if (!d)
|
||||
[NSException raise:NSInvalidArgumentException format:@"d is NULL"];
|
||||
|
||||
NSAssert(*type != '@', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != '^', @"tried to decode an \"ObjC\" type");
|
||||
NSAssert(*type != ':', @"tried to decode an \"ObjC\" type");
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_LNG:
|
||||
if ([stream readFormat: DECODER_FORMAT(long,l),
|
||||
&tmpname, (long*)d] != 2)
|
||||
DECODE_ERROR(long);
|
||||
DECODE_DEBUG(long, l);
|
||||
break;
|
||||
case _C_ULNG:
|
||||
if ([stream readFormat:DECODER_FORMAT(unsigned long, lu),
|
||||
&tmpname, (unsigned long*)d] != 2)
|
||||
DECODE_ERROR(unsigned long);
|
||||
DECODE_DEBUG(unsigned long, lu);
|
||||
break;
|
||||
case _C_INT:
|
||||
if ([stream readFormat:DECODER_FORMAT(int, d),
|
||||
&tmpname, (int*)d] != 2)
|
||||
DECODE_ERROR(int);
|
||||
DECODE_DEBUG(int, d);
|
||||
break;
|
||||
case _C_UINT:
|
||||
if ([stream readFormat:DECODER_FORMAT(unsigned int,u),
|
||||
&tmpname, (unsigned int*)d] != 2)
|
||||
DECODE_ERROR(unsigned int);
|
||||
DECODE_DEBUG(unsigned int, u);
|
||||
break;
|
||||
case _C_SHT:
|
||||
if ([stream readFormat:DECODER_FORMAT(short,hd),
|
||||
&tmpname, (short*)d] != 2)
|
||||
DECODE_ERROR(short);
|
||||
DECODE_DEBUG(short, d);
|
||||
break;
|
||||
case _C_USHT:
|
||||
if ([stream readFormat:DECODER_FORMAT(unsigned short,hu),
|
||||
&tmpname, (unsigned short*)d] != 2)
|
||||
DECODE_ERROR(unsigned short);
|
||||
DECODE_DEBUG(unsigned short, u);
|
||||
break;
|
||||
case _C_CHR:
|
||||
{
|
||||
unsigned tmp;
|
||||
if ([stream readFormat:@" <%a[^>]> (char) = %*c (%x) \n",
|
||||
&tmpname, &tmp] != 2)
|
||||
DECODE_ERROR(char);
|
||||
*(char*)d = (char)tmp;
|
||||
DECODE_DEBUG(char, c);
|
||||
break;
|
||||
}
|
||||
case _C_UCHR:
|
||||
{
|
||||
unsigned tmp;
|
||||
if ([stream readFormat:DECODER_FORMAT(unsigned char,x),
|
||||
&tmpname, &tmp] != 2)
|
||||
DECODE_ERROR(unsigned char);
|
||||
*(unsigned char*)d = (unsigned char)tmp;
|
||||
DECODE_DEBUG(unsigned char, c);
|
||||
break;
|
||||
}
|
||||
case _C_FLT:
|
||||
if ([stream readFormat:DECODER_FORMAT(float,f),
|
||||
&tmpname, (float*)d] != 2)
|
||||
DECODE_ERROR(float);
|
||||
DECODE_DEBUG(float, f);
|
||||
break;
|
||||
case _C_DBL:
|
||||
if ([stream readFormat:DECODER_FORMAT(double,lf),
|
||||
&tmpname, (double*)d] != 2)
|
||||
DECODE_ERROR(double);
|
||||
DECODE_DEBUG(double, f);
|
||||
break;
|
||||
case _C_CHARPTR:
|
||||
if ([stream readFormat:@" <%a[^>]> (char*) = \"%a[^\"]\" \n",
|
||||
&tmpname, (char**)d] != 2)
|
||||
DECODE_ERROR(char*);
|
||||
DECODE_DEBUG(char*, s);
|
||||
break;
|
||||
case _C_ARY_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space, just like _C_CHARPTR ? */
|
||||
int len = atoi(type+1);
|
||||
int offset;
|
||||
[self decodeName:namePtr];
|
||||
[self decodeIndent];
|
||||
while (isdigit(*++type));
|
||||
offset = objc_sizeof_type(type);
|
||||
while (len-- > 0)
|
||||
{
|
||||
[self decodeValueOfCType:type
|
||||
at:d
|
||||
withName:namePtr];
|
||||
((char*)d) += offset;
|
||||
}
|
||||
[self decodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_STRUCT_B:
|
||||
{
|
||||
/* xxx Do we need to allocate space just like char* ? No. */
|
||||
int acc_size = 0;
|
||||
int align;
|
||||
while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
|
||||
[self decodeName:namePtr];
|
||||
[self decodeIndent]; /* xxx insert [self decodeName:] */
|
||||
while (*type != _C_STRUCT_E)
|
||||
{
|
||||
align = objc_alignof_type (type); /* pad to alignment */
|
||||
acc_size = ROUND (acc_size, align);
|
||||
[self decodeValueOfCType:type
|
||||
at:((char*)d)+acc_size
|
||||
withName:namePtr];
|
||||
acc_size += objc_sizeof_type (type); /* add component size */
|
||||
type = objc_skip_typespec (type); /* skip component */
|
||||
}
|
||||
[self decodeUnindent];
|
||||
break;
|
||||
}
|
||||
case _C_PTR:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"Cannot decode pointers"];
|
||||
break;
|
||||
#if 0 /* No, don't know how far to recurse */
|
||||
OBJC_MALLOC(*(void**)d, void*, 1);
|
||||
[self decodeValueOfObjCType:type+1 at:*(char**)d withName:namePtr];
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
[NSException raise: NSGenericException
|
||||
format: @"type %s not yet implemented", type];
|
||||
}
|
||||
if (namePtr)
|
||||
*namePtr = [[[NSString alloc] initWithCStringNoCopy: tmpname
|
||||
length: strlen (tmpname)
|
||||
freeWhenDone: YES]
|
||||
autorelease];
|
||||
else
|
||||
objc_free (tmpname);
|
||||
}
|
||||
|
||||
|
||||
/* Encoding/decoding indentation */
|
||||
|
||||
- (void) encodeIndent
|
||||
{
|
||||
[stream writeFormat: @"%*s {\n", indentation, ""];
|
||||
indentation += 2;
|
||||
}
|
||||
|
||||
- (void) encodeUnindent
|
||||
{
|
||||
indentation -= 2;
|
||||
[stream writeFormat: @"%*s }\n", indentation, ""];
|
||||
}
|
||||
|
||||
- (void) decodeIndent
|
||||
{
|
||||
id line;
|
||||
const char *lp;
|
||||
|
||||
line = [stream readLine];
|
||||
lp = [line cString];
|
||||
while (*lp == ' ') lp++;
|
||||
if (*lp != '{')
|
||||
[NSException raise: NSGenericException
|
||||
format: @"bad indent format, got \"%s\"", line];
|
||||
}
|
||||
|
||||
- (void) decodeUnindent
|
||||
{
|
||||
id line;
|
||||
const char *lp;
|
||||
|
||||
line = [stream readLine];
|
||||
lp = [line cString];
|
||||
while (*lp == ' ') lp++;
|
||||
if (*lp != '}')
|
||||
[NSException raise: NSGenericException
|
||||
format: @"bad unindent format, got \"%s\"", line];
|
||||
}
|
||||
|
||||
- (void) encodeName: (NSString*) n
|
||||
{
|
||||
if (n)
|
||||
[stream writeFormat:@"%*s<%s>\n", indentation, "", [n cString]];
|
||||
else
|
||||
[stream writeFormat:@"%*s<NULL>\n", indentation, ""];
|
||||
}
|
||||
|
||||
- (void) decodeName: (NSString* *) name
|
||||
{
|
||||
char *n;
|
||||
if (name)
|
||||
{
|
||||
if ([stream readFormat: @" <%a[^>]> \n", &n] != 1)
|
||||
[NSException raise: NSGenericException
|
||||
format: @"bad format"];
|
||||
*name = [[[NSString alloc] initWithCStringNoCopy: n
|
||||
length: strlen (n)
|
||||
freeWhenDone: YES]
|
||||
autorelease];
|
||||
if (debug_textcoder)
|
||||
fprintf(stderr, "got name <%s>\n", n);
|
||||
}
|
||||
else
|
||||
{
|
||||
[stream readFormat: @" <%*[^>]> \n"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returning default format version. */
|
||||
|
||||
+ (int) defaultFormatVersion
|
||||
{
|
||||
return DEFAULT_FORMAT_VERSION;
|
||||
}
|
||||
|
||||
@end
|
479
Source/UdpPort.m
479
Source/UdpPort.m
|
@ -1,479 +0,0 @@
|
|||
/* Implementation of UDP port object for use with Connection
|
||||
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
|
||||
Created: July 1994
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
/* xxx I should also look into SOCK_RDM and SOCK_SEQPACKET. */
|
||||
|
||||
#include <config.h>
|
||||
#include <base/UdpPort.h>
|
||||
#include <base/Coder.h>
|
||||
#include <Foundation/NSPortCoder.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSHost.h>
|
||||
#include <Foundation/NSByteOrder.h>
|
||||
|
||||
#if _AIX
|
||||
#include <sys/select.h>
|
||||
#endif /* _AIX */
|
||||
|
||||
#ifdef __MINGW__
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#endif /* !__MINGW__ */
|
||||
|
||||
/* For IRIX machines, which don't define this */
|
||||
#ifndef IPPORT_USERRESERVED
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
#endif /* IPPORT_USERRESERVED */
|
||||
|
||||
@interface UdpInPort (Private)
|
||||
@end
|
||||
@interface UdpOutPort (Private)
|
||||
+ newForSendingToSockaddr: (struct sockaddr_in*)addr;
|
||||
@end
|
||||
@interface UdpInPacket (Private)
|
||||
- (void) _setReplyPort: p;
|
||||
@end
|
||||
|
||||
/* The maximum size of packet UdpPort's will send or recieve. */
|
||||
/* xxx What is the UDP maximum? */
|
||||
#define MAX_PACKET_SIZE 2048
|
||||
|
||||
/* Make this a hashtable? */
|
||||
static NSLock* udp_port_gate = nil;
|
||||
|
||||
static BOOL udp_port_debug = NO;
|
||||
|
||||
|
||||
/* Our current, sad excuse for a name server. */
|
||||
|
||||
static unsigned short
|
||||
name_2_port_number (const char *name)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
unsigned int ctr = 0;
|
||||
|
||||
while (*name)
|
||||
{
|
||||
ret ^= *name++ << ctr;
|
||||
ctr = (ctr + 1) % sizeof (void *);
|
||||
}
|
||||
return (ret % (65535 - IPPORT_USERRESERVED - 1)) + IPPORT_USERRESERVED;
|
||||
/* return strlen (name) + IPPORT_USERRESERVED; */
|
||||
}
|
||||
|
||||
@implementation UdpInPort
|
||||
|
||||
static NSMapTable *port_number_2_in_port = NULL;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [UdpInPort class])
|
||||
{
|
||||
port_number_2_in_port =
|
||||
NSCreateMapTable (NSIntMapKeyCallBacks,
|
||||
NSNonOwnedPointerMapValueCallBacks, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the designated initializer.
|
||||
If N is zero, it will choose a port number for you. */
|
||||
|
||||
+ newForReceivingFromPortNumber: (unsigned short)n
|
||||
{
|
||||
UdpInPort* p;
|
||||
|
||||
NSAssert(n > IPPORT_USERRESERVED, NSInvalidArgumentException);
|
||||
|
||||
[udp_port_gate lock];
|
||||
|
||||
/* See if there is already one created */
|
||||
if ((p = NSMapGet (port_number_2_in_port, (void*)(int)n)))
|
||||
return p;
|
||||
|
||||
/* No, create a new port object */
|
||||
p = [[self alloc] init];
|
||||
|
||||
/* Make a new socket for the port object */
|
||||
if ((p->_port_socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
perror("[UdpInPort +newForReceivingFromPortNumber:] socket()");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Give the socket a name using bind */
|
||||
{
|
||||
struct hostent *hp;
|
||||
|
||||
hp = gethostbyname ([[[NSHost currentHost] name] cString]);
|
||||
if (!hp)
|
||||
/* xxx This won't work with port connections on a network, though.
|
||||
Fix this. Perhaps there is a better way of getting the address
|
||||
of the local host. */
|
||||
hp = gethostbyname ("localhost");
|
||||
NSAssert(hp, NSInternalInconsistencyException);
|
||||
/* Use host's address, and not INADDR_ANY, so that went we
|
||||
encode our _address for a D.O. operation, they get
|
||||
our unique host address that can identify us across the network. */
|
||||
memcpy (&(p->_address.sin_addr), hp->h_addr, hp->h_length);
|
||||
p->_address.sin_family = AF_INET;
|
||||
p->_address.sin_port = NSSwapHostShortToBig (n);
|
||||
/* N may be zero, in which case bind() will choose a port number
|
||||
for us. */
|
||||
if (bind (p->_port_socket,
|
||||
(struct sockaddr*) &(p->_address),
|
||||
sizeof (p->_address))
|
||||
< 0)
|
||||
{
|
||||
perror ("[UdpInPort +newForReceivingFromPortNumber] bind()");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* If the caller didn't specify a port number, it was chosen for us.
|
||||
Here, find out what number was chosen. */
|
||||
if (!n)
|
||||
/* xxx Perhaps I should do this unconditionally? */
|
||||
{
|
||||
int size = sizeof (p->_address);
|
||||
if (getsockname (p->_port_socket,
|
||||
(struct sockaddr*)&(p->_address),
|
||||
&size)
|
||||
< 0)
|
||||
{
|
||||
perror ("[UdpInPort +newForReceivingFromPortNumber] getsockname()");
|
||||
abort ();
|
||||
}
|
||||
NSAssert(p->_address.sin_port, NSInternalInconsistencyException);
|
||||
}
|
||||
|
||||
/* Record it in UdpInPort's map table. */
|
||||
NSMapInsert (port_number_2_in_port, (void*)(int)n, p);
|
||||
[udp_port_gate unlock];
|
||||
|
||||
if (udp_port_debug)
|
||||
fprintf(stderr, "created new UdpInPort 0x%x, fd=%d port_number=%d\n",
|
||||
(unsigned)p, p->_port_socket, NSSwapHostShortToBig(p->_address.sin_port));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
+ newForReceivingFromRegisteredName: (NSString*)name
|
||||
{
|
||||
int n;
|
||||
|
||||
n = name_2_port_number ([name cString]);
|
||||
return [self newForReceivingFromPortNumber: n];
|
||||
}
|
||||
|
||||
/* Returns nil on timeout.
|
||||
Pass -1 for milliseconds to ignore timeout parameter and block indefinitely.
|
||||
*/
|
||||
|
||||
- receivePacketWithTimeout: (int)milliseconds
|
||||
{
|
||||
int r;
|
||||
struct sockaddr_in remote_addr;
|
||||
int remote_len;
|
||||
UdpInPacket *packet;
|
||||
|
||||
if (udp_port_debug)
|
||||
fprintf(stderr, "receiving from %d\n", [self portNumber]);
|
||||
|
||||
if (milliseconds >= 0)
|
||||
{
|
||||
/* A timeout was requested; use select to ask if something is ready. */
|
||||
struct timeval timeout;
|
||||
fd_set ready;
|
||||
|
||||
timeout.tv_sec = milliseconds / 1000;
|
||||
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||
memset(&ready, '\0', sizeof(ready));
|
||||
FD_SET(_port_socket, &ready);
|
||||
if ((r = select(_port_socket + 1, &ready, 0, 0, &timeout)) < 0)
|
||||
{
|
||||
perror("select");
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (r == 0) /* timeout */
|
||||
return nil;
|
||||
if (!FD_ISSET(_port_socket, &ready))
|
||||
[self error:"select lied"];
|
||||
}
|
||||
|
||||
/* There is a packet on the socket ready for us to receive. */
|
||||
|
||||
/* Create a packet. */
|
||||
packet = [[UdpInPacket alloc] initWithCapacity: MAX_PACKET_SIZE];
|
||||
|
||||
/* Fill it with the UDP packet data. */
|
||||
remote_len = sizeof(remote_addr);
|
||||
if (recvfrom (_port_socket, [packet streamBuffer], MAX_PACKET_SIZE, 0,
|
||||
(struct sockaddr*)&remote_addr, &remote_len)
|
||||
< 0)
|
||||
{
|
||||
perror("recvfrom");
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Set the packet's reply_port. */
|
||||
if (remote_len != sizeof(struct sockaddr_in))
|
||||
[self error:"remote address size mismatch"];
|
||||
[packet _setReplyPort: [[self class] newForSendingToSockaddr: &remote_addr]];
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
- (void) invalidate
|
||||
{
|
||||
if (_is_valid)
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
closesocket (_port_socket);
|
||||
#else
|
||||
close (_port_socket);
|
||||
#endif /* __MINGW__ */
|
||||
[super invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self invalidate];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (int) socket
|
||||
{
|
||||
return _port_socket;
|
||||
}
|
||||
|
||||
- (int) portNumber
|
||||
{
|
||||
return (int) NSSwapBigShortToHost (_address.sin_port);
|
||||
}
|
||||
|
||||
- (Class) packetClass
|
||||
{
|
||||
return [UdpInPacket class];
|
||||
}
|
||||
|
||||
- (Class) classForPortCoder
|
||||
{
|
||||
/* Make sure that Connection's always send us bycopy, not a Proxy class.
|
||||
Also, don't encode a "receive right" (ala Mach), encode a "send right". */
|
||||
return [UdpOutPort class];
|
||||
}
|
||||
- replacementObjectForPortCoder: aRmc
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
/* We are actually encoding a "send right" (ala Mach),
|
||||
not a receive right.
|
||||
These values must match those expected by [TcpOutPort +newWithCoder] */
|
||||
[super encodeWithCoder: aCoder];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_port))
|
||||
at: &_address.sin_port
|
||||
withName: @"socket number"];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_addr.s_addr))
|
||||
at: &_address.sin_addr.s_addr
|
||||
withName: @"inet address"];
|
||||
}
|
||||
|
||||
+ newWithCoder: aCoder
|
||||
{
|
||||
/* An InPort cannot be created by decoding, only OutPort's. */
|
||||
[self shouldNotImplement: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void) setDebug: (BOOL)f
|
||||
{
|
||||
udp_port_debug = f;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UdpOutPort
|
||||
|
||||
static NSMutableArray *udp_out_port_array;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [UdpOutPort class])
|
||||
{
|
||||
udp_out_port_array = [NSMutableArray new];
|
||||
}
|
||||
}
|
||||
|
||||
#define SOCKADDR_EQUAL(s1,s2) ((s1)->sin_port == (s2)->sin_port && (s1)->sin_addr.s_addr == (s2)->sin_addr.s_addr)
|
||||
/* xxx Change to make INADDR_ANY and the localhost address be equal. */
|
||||
/* Assume that sin_family is equal */
|
||||
/* (!memcmp(s1, s2, sizeof(struct sockaddr_in)))
|
||||
didn't work because sin_zero's differ. Does this matter? */
|
||||
|
||||
|
||||
/* This is the designated initializer. */
|
||||
|
||||
+ newForSendingToSockaddr: (struct sockaddr_in*)sockaddr
|
||||
{
|
||||
UdpOutPort *p;
|
||||
unsigned i;
|
||||
unsigned c = [udp_out_port_array count];
|
||||
|
||||
/* See if there already exists a port for this sockaddr;
|
||||
if so, just return it. */
|
||||
for (i = 0; i < c; i++)
|
||||
{
|
||||
p = [udp_out_port_array objectAtIndex: i];
|
||||
/* xxx Come up with a way to do this with a hashtable, not a list. */
|
||||
if (SOCKADDR_EQUAL (sockaddr, &(p->_address)))
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Create a new port. */
|
||||
p = [[self alloc] init];
|
||||
|
||||
/* Set the address. */
|
||||
memcpy (&(p->_address), sockaddr, sizeof(p->_address));
|
||||
|
||||
/* Remember it in the array. */
|
||||
/* xxx This will retain it; how will it ever get dealloc'ed? */
|
||||
[udp_out_port_array addObject: p];
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
+ newForSendingToPortNumber: (unsigned short)n
|
||||
onHost: (NSString*)hostname
|
||||
{
|
||||
struct hostent *hp;
|
||||
const char *host_cstring;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
/* Look up the hostname. */
|
||||
if (!hostname || ![hostname length])
|
||||
host_cstring = "localhost";
|
||||
else
|
||||
host_cstring = [hostname cString];
|
||||
hp = gethostbyname ((char*)host_cstring);
|
||||
if (hp == 0)
|
||||
[self error: "unknown host: \"%s\"", host_cstring];
|
||||
|
||||
/* Get the sockaddr_in address. */
|
||||
memcpy (&addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = NSSwapHostShortToBig (n);
|
||||
|
||||
return [self newForSendingToSockaddr: &addr];
|
||||
}
|
||||
|
||||
|
||||
/* This currently ignores the timeout parameter */
|
||||
|
||||
- (BOOL) sendPacket: packet timeout: (NSTimeInterval)seconds
|
||||
{
|
||||
id reply_port = [packet replyPort];
|
||||
int len = [packet streamEofPosition];
|
||||
|
||||
NSAssert(len < MAX_PACKET_SIZE, NSInternalInconsistencyException);
|
||||
|
||||
if ( ! [reply_port isKindOfClass: [UdpInPort class]])
|
||||
[self error:"Trying to send to a port that is not a UdpInPort"];
|
||||
if (udp_port_debug)
|
||||
fprintf (stderr, "sending to %d\n", (int) NSSwapBigShortToHost (_address.sin_port));
|
||||
if (sendto ([reply_port socket],
|
||||
[packet streamBuffer], len, 0,
|
||||
(struct sockaddr*)&_address, sizeof (_address))
|
||||
< 0)
|
||||
{
|
||||
perror ("sendto");
|
||||
abort ();
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int) portNumber
|
||||
{
|
||||
return (int) NSSwapBigShortToHost (_address.sin_port);
|
||||
}
|
||||
|
||||
- (NSString*) hostname
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (Class) packetClass
|
||||
{
|
||||
return [UdpInPacket class];
|
||||
}
|
||||
|
||||
- (void) encodeWithCoder: aCoder
|
||||
{
|
||||
[super encodeWithCoder: aCoder];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_port))
|
||||
at: &_address.sin_port
|
||||
withName: @"socket number"];
|
||||
[aCoder encodeValueOfCType: @encode(typeof(_address.sin_addr.s_addr))
|
||||
at: &_address.sin_addr.s_addr
|
||||
withName: @"inet address"];
|
||||
}
|
||||
|
||||
+ newWithCoder: aCoder
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
[aCoder decodeValueOfCType: @encode(typeof(addr.sin_port))
|
||||
at: &addr.sin_port
|
||||
withName: NULL];
|
||||
[aCoder decodeValueOfCType: @encode(typeof(addr.sin_addr.s_addr))
|
||||
at: &addr.sin_addr.s_addr
|
||||
withName: NULL];
|
||||
return [UdpOutPort newForSendingToSockaddr: &addr];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation UdpInPacket
|
||||
|
||||
- (void) _setReplyPort: p
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
}
|
||||
|
||||
@end
|
366
Source/ostream.m
366
Source/ostream.m
|
@ -1,366 +0,0 @@
|
|||
/* objc_streams - C-function interface to Objective-C streams
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Adam Fedor <fedor@boulder.colorado.edu>
|
||||
Date: Aug 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <base/preface.h>
|
||||
#include <base/ostream.h>
|
||||
#include <base/MemoryStream.h>
|
||||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSException.h>
|
||||
|
||||
#define OSTREAM_EOF EOF
|
||||
|
||||
/* Handle a stream error - FIXME: not sure if this should throw an exception
|
||||
or what... */
|
||||
static void
|
||||
_ostream_error (const char* message)
|
||||
{
|
||||
fprintf (stderr, "ostream error: %s\n", message);
|
||||
}
|
||||
|
||||
int
|
||||
ostream_getc (ostream* s)
|
||||
{
|
||||
char r, c;
|
||||
r = c = 0;
|
||||
if (s->flags & OSTREAM_READFLAG)
|
||||
r = [(id <Streaming>)s->stream_obj readByte: &c];
|
||||
if (r == 0)
|
||||
c = OSTREAM_EOF;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
ostream_ungetc (ostream* s)
|
||||
{
|
||||
if ((s->flags & OSTREAM_READFLAG) && (s->flags & OSTREAM_CANSEEK))
|
||||
{
|
||||
long pos = [(id <SeekableStreaming>)s->stream_obj streamPosition];
|
||||
[(id <SeekableStreaming>)s->stream_obj setStreamPosition: pos-1];
|
||||
}
|
||||
else
|
||||
_ostream_error("Tried to unget on non-readable/non-seekable stream");
|
||||
}
|
||||
|
||||
int
|
||||
ostream_putc (ostream* s, int c)
|
||||
{
|
||||
if (s->flags & OSTREAM_WRITEFLAG)
|
||||
return [(id <Streaming>)s->stream_obj writeByte: c];
|
||||
else
|
||||
return OSTREAM_EOF;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ostream_at_eos (ostream* s)
|
||||
{
|
||||
return [(id <Streaming>)s->stream_obj isAtEof];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ostream_flush (ostream *s)
|
||||
{
|
||||
int pos;
|
||||
pos = [(id <Streaming>)s->stream_obj streamPosition];
|
||||
[(id <Streaming>)s->stream_obj flushStream];
|
||||
return [(id <Streaming>)s->stream_obj streamPosition] - pos;
|
||||
}
|
||||
|
||||
void
|
||||
ostream_seek (ostream *s, long offset, int mode)
|
||||
{
|
||||
if (!(s->flags & OSTREAM_CANSEEK))
|
||||
return;
|
||||
|
||||
[(id <SeekableStreaming>)s->stream_obj setStreamPosition: offset
|
||||
seekMode: (mode - OSTREAM_SEEK_FROM_START + STREAM_SEEK_FROM_START)];
|
||||
}
|
||||
|
||||
long
|
||||
ostream_tell (ostream *s)
|
||||
{
|
||||
return [(id <Streaming>)s->stream_obj streamPosition];
|
||||
}
|
||||
|
||||
int
|
||||
ostream_read (ostream* s, void* buf, int count)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (!buf)
|
||||
[NSException raise:NSInvalidArgumentException format:@"buf is NULL"];
|
||||
|
||||
if (s->flags & OSTREAM_READFLAG)
|
||||
r = [(id <Streaming>)s->stream_obj readBytes: buf length: count];
|
||||
if (r == 0)
|
||||
r = OSTREAM_EOF;
|
||||
return r;
|
||||
}
|
||||
|
||||
char* ostream_gets (ostream* s, char* buf, int count)
|
||||
{
|
||||
char r, c;
|
||||
int i = 0;
|
||||
|
||||
if (!buf)
|
||||
[NSException raise:NSInvalidArgumentException format:@"buf is NULL"];
|
||||
|
||||
if (!(s->flags & OSTREAM_READFLAG))
|
||||
return NULL;
|
||||
while (i < count-1) {
|
||||
r = [(id <Streaming>)s->stream_obj readByte: &c];
|
||||
if (r <= 0)
|
||||
break;
|
||||
buf[i++] = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
buf[i++] = 0;
|
||||
|
||||
return i > 1 ? buf : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
ostream_write (ostream* s, const void* buf, int count)
|
||||
{
|
||||
if (!buf)
|
||||
[NSException raise:NSInvalidArgumentException format:@"buf is NULL"];
|
||||
|
||||
if (s->flags & OSTREAM_WRITEFLAG)
|
||||
return [(id <Streaming>)s->stream_obj writeBytes: buf length: count];
|
||||
return OSTREAM_EOF;
|
||||
}
|
||||
|
||||
void
|
||||
ostream_printf (ostream *s, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ostream_vprintf(s, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
ostream_vprintf (ostream *s, const char *format, va_list argList)
|
||||
{
|
||||
id str = [[NSString alloc] initWithCString: format];
|
||||
if (s->flags & OSTREAM_WRITEFLAG)
|
||||
[(id <Streaming>)s->stream_obj writeFormat: str arguments: argList];
|
||||
else
|
||||
_ostream_error("Tried to write to non-writable stream");
|
||||
[str release];
|
||||
}
|
||||
|
||||
int
|
||||
ostream_scanf (ostream *s, const char *format, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ret = ostream_vscanf(s, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ostream_vscanf (ostream *s, const char *format, va_list argList)
|
||||
{
|
||||
id str = [[NSString alloc] stringWithCString: format];
|
||||
if (s->flags & OSTREAM_READFLAG)
|
||||
{
|
||||
int r = 0;
|
||||
r = [(id <Streaming>)s->stream_obj readFormat: str
|
||||
arguments: argList];
|
||||
if (r == 0)
|
||||
r = OSTREAM_EOF;
|
||||
return r;
|
||||
}
|
||||
_ostream_error("Tried to read from non-readable stream");
|
||||
[str release];
|
||||
return OSTREAM_EOF;
|
||||
}
|
||||
|
||||
static ostream *
|
||||
_ostream_new_stream_struct (int mode, char** cmode)
|
||||
{
|
||||
char* fmode;
|
||||
ostream* stream;
|
||||
OBJC_MALLOC(stream, ostream, 1);
|
||||
stream->flags = 0;
|
||||
switch (mode)
|
||||
{
|
||||
case OSTREAM_READONLY:
|
||||
fmode = "r";
|
||||
stream->flags |= OSTREAM_READFLAG;
|
||||
break;
|
||||
case OSTREAM_WRITEONLY:
|
||||
fmode = "w";
|
||||
stream->flags |= OSTREAM_WRITEFLAG;
|
||||
break;
|
||||
case OSTREAM_READWRITE:
|
||||
fmode = "r+";
|
||||
stream->flags |= OSTREAM_READFLAG;
|
||||
stream->flags |= OSTREAM_WRITEFLAG;
|
||||
break;
|
||||
case OSTREAM_APPEND:
|
||||
fmode = "r+";
|
||||
stream->flags |= OSTREAM_WRITEFLAG;
|
||||
break;
|
||||
default:
|
||||
fmode = "r";
|
||||
break;
|
||||
}
|
||||
if (cmode)
|
||||
*cmode = fmode;
|
||||
return stream;
|
||||
}
|
||||
|
||||
ostream *
|
||||
ostream_open_descriptor (int fd, int mode)
|
||||
{
|
||||
char* fmode;
|
||||
ostream* stream = _ostream_new_stream_struct(mode, &fmode);
|
||||
stream->stream_obj = [[StdioStream alloc] initWithFileDescriptor: fd
|
||||
fmode: fmode];
|
||||
/* FIXME: Just assuming we can seek FILE streams */
|
||||
stream->flags |= OSTREAM_CANSEEK;
|
||||
return stream;
|
||||
}
|
||||
|
||||
ostream *
|
||||
ostream_open_memory (const char *addr, int size, int mode)
|
||||
{
|
||||
char* fmode;
|
||||
ostream* stream = _ostream_new_stream_struct(mode, &fmode);
|
||||
if (addr)
|
||||
{
|
||||
stream->stream_obj = [[MemoryStream alloc]
|
||||
_initOnMallocBuffer: (char*)addr
|
||||
freeWhenDone: NO
|
||||
size: size
|
||||
eofPosition: size
|
||||
prefix: 0
|
||||
position: 0];
|
||||
if (!stream->stream_obj)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream->stream_obj = [[MemoryStream alloc] initWithCapacity: size
|
||||
prefix: 0];
|
||||
}
|
||||
if (mode == OSTREAM_APPEND)
|
||||
ostream_seek(stream, 0, OSTREAM_SEEK_FROM_END);
|
||||
stream->flags |= OSTREAM_CANSEEK;
|
||||
stream->flags |= OSTREAM_ISBUFFER;
|
||||
return stream;
|
||||
}
|
||||
|
||||
ostream *
|
||||
ostream_map_file (const char *name, int mode)
|
||||
{
|
||||
char* fmode;
|
||||
NSString* str = [NSString stringWithCString: name];
|
||||
ostream* stream = _ostream_new_stream_struct(mode, &fmode);
|
||||
stream->stream_obj = [[StdioStream alloc] initWithFilename: str
|
||||
fmode: fmode];
|
||||
if (!stream->stream_obj)
|
||||
return NULL;
|
||||
|
||||
/* xxxFIXME: Just assuming that we can seek: */
|
||||
stream->flags |= OSTREAM_CANSEEK;
|
||||
if (mode == OSTREAM_APPEND)
|
||||
ostream_seek(stream, 0, OSTREAM_SEEK_FROM_END);
|
||||
return stream;
|
||||
}
|
||||
|
||||
/* Would like to use NSData for this, but it's to hard to pass the buffer
|
||||
and tell NSData not to free it */
|
||||
int
|
||||
ostream_save_to_file (ostream *s, const char *name)
|
||||
{
|
||||
StdioStream* output;
|
||||
if (!(s->flags & OSTREAM_ISBUFFER))
|
||||
{
|
||||
_ostream_error("Tried to save non-memory stream");
|
||||
return -1;
|
||||
}
|
||||
|
||||
output = [[StdioStream alloc]
|
||||
initWithFilename: [NSString stringWithCString: name]
|
||||
fmode: "w"];
|
||||
if (!output)
|
||||
{
|
||||
_ostream_error("Unable to open save file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
[output writeBytes: [(id <MemoryStreaming>)s->stream_obj streamBuffer]
|
||||
length: [(id <MemoryStreaming>)s->stream_obj streamEofPosition]];
|
||||
[output release];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ostream_get_memory_buffer (ostream *s, char **addr, int *len, int *maxlen)
|
||||
{
|
||||
if (!(s->flags & OSTREAM_ISBUFFER))
|
||||
{
|
||||
if (addr)
|
||||
*addr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
*addr = [(id <MemoryStreaming>)s->stream_obj streamBuffer];
|
||||
if (len)
|
||||
*len = [(id <MemoryStreaming>)s->stream_obj streamEofPosition];
|
||||
if (maxlen)
|
||||
*maxlen = [(id <MemoryStreaming>)s->stream_obj streamBufferCapacity];
|
||||
}
|
||||
|
||||
void
|
||||
ostream_close_memory (ostream *s, int option)
|
||||
{
|
||||
if (s->flags & OSTREAM_ISBUFFER)
|
||||
{
|
||||
/* Dumb way to save buffer, but what else? */
|
||||
if (option == OSTREAM_SAVEBUFFER)
|
||||
[(MemoryStream*)s->stream_obj retain];
|
||||
}
|
||||
ostream_close(s);
|
||||
}
|
||||
|
||||
void
|
||||
ostream_close (ostream *s)
|
||||
{
|
||||
[(id <Streaming>)s->stream_obj close];
|
||||
[(id)s->stream_obj release];
|
||||
s->stream_obj = 0;
|
||||
OBJC_FREE(s);
|
||||
}
|
||||
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/* A demonstration of writing and reading GNU Objective C objects to a file. */
|
||||
|
||||
#include <base/BinaryCStream.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/Dictionary.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
id arp;
|
||||
long l = 0x6543;
|
||||
int i = 0x1234;
|
||||
unsigned u = 2;
|
||||
short s = 0x987;
|
||||
char c = 0x12;
|
||||
char *string = "Testing";
|
||||
float f = 0.1234F;
|
||||
double d = 0.987654321;
|
||||
id cstream;
|
||||
Class cstream_class;
|
||||
|
||||
if (argc > 1)
|
||||
cstream_class = objc_get_class (argv[1]);
|
||||
else
|
||||
cstream_class = [BinaryCStream class];
|
||||
|
||||
[NSObject enableDoubleReleaseCheck: YES];
|
||||
arp = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
cstream = [[cstream_class alloc]
|
||||
initForWritingToFile: @"cstream.dat"];
|
||||
|
||||
/* Write an integer to a file */
|
||||
[cstream encodeWithName: @"some values"
|
||||
valuesOfCTypes: "liIsc*fd",
|
||||
&l, &i, &u, &s, &c, &string, &f, &d];
|
||||
printf ("Wrote %d %d %u %d %d %s %g %.15g\n",
|
||||
(int)l, i, u, (int)s, (int)c, string, f, d);
|
||||
[[cstream stream] close];
|
||||
|
||||
f = d = 0;
|
||||
|
||||
cstream = [cstream_class cStreamReadingFromFile: @"cstream.dat"];
|
||||
[cstream decodeWithName: NULL
|
||||
valuesOfCTypes: "liIsc*fd",
|
||||
&l, &i, &u, &s, &c, &string, &f, &d];
|
||||
printf ("Read %d %d %u %d %d %s %g %.15g\n",
|
||||
(int)l, i, u, (int)s, (int)c, string, f, d);
|
||||
[[cstream stream] close];
|
||||
|
||||
/* Do the autorelease. */
|
||||
[arp release];
|
||||
|
||||
exit(0);
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
/* A demonstration of writing and reading with NSArchiver */
|
||||
|
||||
#include <base/Invocation.h>
|
||||
#include <base/Array.h>
|
||||
#include <base/Archiver.h>
|
||||
#include <Foundation/NSValue.h>
|
||||
#include <base/TextCStream.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
|
||||
@interface NSNumber (printing)
|
||||
- (void) print;
|
||||
- printAddNumber: n;
|
||||
@end
|
||||
|
||||
@implementation NSNumber (printing)
|
||||
- (void) print
|
||||
{
|
||||
printf("%d\n", [self intValue]);
|
||||
}
|
||||
- printAddNumber: n
|
||||
{
|
||||
printf("%d\n", [self intValue] + [n intValue]);
|
||||
return self;
|
||||
}
|
||||
@end
|
||||
|
||||
int main()
|
||||
{
|
||||
id obj;
|
||||
id inv;
|
||||
id array;
|
||||
int i;
|
||||
BOOL b;
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
|
||||
/* Create a simple invocation, and get it's return value. */
|
||||
obj = [NSObject new];
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: obj selector: @selector(isInstance)];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &b];
|
||||
printf ("object is instance %d\n", (int)b);
|
||||
[inv release];
|
||||
|
||||
/* Do a simple invocation on all the contents of a collection. */
|
||||
array = [Array new];
|
||||
for (i = 0; i < 5; i++)
|
||||
[array addObject: [NSNumber numberWithInt: i]];
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithSelector: @selector(print)];
|
||||
printf ("The numbers\n");
|
||||
[array withObjectsInvoke: inv];
|
||||
[inv release];
|
||||
|
||||
/* Do an invocation on all the contents of the array, but the
|
||||
array contents become the first object argument of the invocation,
|
||||
not the target for the invocation. */
|
||||
inv = [[ObjectMethodInvocation alloc]
|
||||
initWithTarget: [NSNumber numberWithInt: 2]
|
||||
selector: @selector(printAddNumber:), nil];
|
||||
printf ("The numbers adding 2\n");
|
||||
[array withObjectsInvoke: inv];
|
||||
|
||||
/* Get an int return value in a way that is simpler than -getReturnValue: */
|
||||
printf ("The target number was %d\n", [inv intReturnValue]);
|
||||
[inv release];
|
||||
|
||||
/* Use a function instead of a selector for the invocation.
|
||||
Also show the use of filtered enumerating over a collection. */
|
||||
{
|
||||
id inv2;
|
||||
id test_func (id o)
|
||||
{
|
||||
printf ("test_func got %d\n", [o intValue]);
|
||||
return [NSNumber numberWithInt: [o intValue] + 3];
|
||||
}
|
||||
inv = [[ObjectFunctionInvocation alloc]
|
||||
initWithObjectFunction: test_func];
|
||||
inv2 = [[MethodInvocation alloc] initWithSelector: @selector(print)];
|
||||
[array withObjectsTransformedByInvoking: inv
|
||||
invoke: inv2];
|
||||
[inv release];
|
||||
[inv2 release];
|
||||
}
|
||||
|
||||
/* Archive the some invocations, read them back and invoke. */
|
||||
{
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: array
|
||||
selector: @selector(withObjectsInvoke:),
|
||||
[[[MethodInvocation alloc] initWithSelector: @selector(print)]
|
||||
autorelease]];
|
||||
printf ("Before archiving\n");
|
||||
[inv invoke];
|
||||
[Archiver setDefaultCStreamClass: [TextCStream class]];
|
||||
[Archiver encodeRootObject: inv withName: NULL toFile: @"invocation.txt"];
|
||||
[inv release];
|
||||
printf ("After archiving\n");
|
||||
inv = [Unarchiver decodeObjectWithName: NULL
|
||||
fromFile: @"invocation.txt"];
|
||||
[inv invoke];
|
||||
}
|
||||
|
||||
[arp release];
|
||||
exit(0);
|
||||
}
|
||||
|
|
@ -1,181 +0,0 @@
|
|||
#include <Foundation/NSMethodSignature.h>
|
||||
#include <Foundation/NSInvocation.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <base/Invocation.h>
|
||||
|
||||
#define TYPE char
|
||||
|
||||
struct pair {
|
||||
TYPE i;
|
||||
TYPE j;
|
||||
};
|
||||
|
||||
@interface Pair: NSObject
|
||||
- (TYPE)member:(Class)c;
|
||||
- (TYPE)plus: (struct pair) pair;
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr;
|
||||
@end
|
||||
|
||||
@implementation Pair
|
||||
- (TYPE)member:(Class)c
|
||||
{
|
||||
if ([self class] == c)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
- (TYPE)plus: (struct pair) pair
|
||||
{
|
||||
return (pair.i + pair.j);
|
||||
}
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr
|
||||
{
|
||||
return (pair_ptr->i + pair_ptr->j);
|
||||
}
|
||||
@end
|
||||
/* Invocation.m
|
||||
- initWithTarget: target selector: (SEL)s, ...
|
||||
[1] Adding CASE_TYPE(_C_CLASS, Class);
|
||||
[2] Adding default: block
|
||||
|
||||
NSInvocation.h
|
||||
[3] Adding NS_INVOCATION
|
||||
[4, 5] Adding NS_MESSAGE
|
||||
|
||||
NSMethodSignature.m
|
||||
[6] Modifiying -(NSArgumentInfo)argumentInfoAtIndex:(unsigned)index */
|
||||
|
||||
void test1();
|
||||
void test2();
|
||||
void test3();
|
||||
void test4();
|
||||
void test5();
|
||||
void test6();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
id pool = [NSAutoreleasePool new];
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
test1()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(member:);
|
||||
Class c = [Pair class];
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, c];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test1 YES == %s\n", result? "YES": "NO");
|
||||
}
|
||||
|
||||
void
|
||||
test2()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(plus:);
|
||||
SEL sel_ptr = @selector(plus_ptr:);
|
||||
struct pair pair0;
|
||||
struct pair * pair0_ptr;
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
|
||||
pair0.i = 3;
|
||||
pair0.j = 4;
|
||||
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-1 %d == 7\n", result);
|
||||
|
||||
pair0_ptr = &pair0;
|
||||
pair0_ptr->i = 2;
|
||||
pair0_ptr->j = 3;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel_ptr, &pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-2 %d == 5\n", result);
|
||||
}
|
||||
|
||||
void
|
||||
test3()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 1;
|
||||
pair0.j = 2;
|
||||
inv = NS_INVOCATION(Pair ,
|
||||
plus:,
|
||||
pair0);
|
||||
[inv setTarget: ipair];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test3 3 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test4()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 3;
|
||||
pair0.j = 8;
|
||||
inv = NS_MESSAGE(ipair ,
|
||||
plus_ptr:,
|
||||
&pair0); // Method with args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test4 11 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test5()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
NSInvocation * inv;
|
||||
int x;
|
||||
|
||||
inv = NS_MESSAGE(ipair,
|
||||
hash); // Method with NO args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test5 hash value of an object == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test6()
|
||||
{
|
||||
NSObject * foo = [NSObject new];
|
||||
NSArgumentInfo info;
|
||||
SEL sel = @selector(isKindOfClass:);
|
||||
NSMethodSignature * ms = [foo methodSignatureForSelector: sel];
|
||||
info = [ms argumentInfoAtIndex: 0];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 1];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 2];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
}
|
||||
|
||||
#undef TYPE
|
|
@ -1,181 +0,0 @@
|
|||
#include <Foundation/NSMethodSignature.h>
|
||||
#include <Foundation/NSInvocation.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <base/Invocation.h>
|
||||
|
||||
#define TYPE int
|
||||
|
||||
struct pair {
|
||||
TYPE i;
|
||||
TYPE j;
|
||||
};
|
||||
|
||||
@interface Pair: NSObject
|
||||
- (TYPE)member:(Class)c;
|
||||
- (TYPE)plus: (struct pair) pair;
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr;
|
||||
@end
|
||||
|
||||
@implementation Pair
|
||||
- (TYPE)member:(Class)c
|
||||
{
|
||||
if ([self class] == c)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
- (TYPE)plus: (struct pair) pair
|
||||
{
|
||||
return (pair.i + pair.j);
|
||||
}
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr
|
||||
{
|
||||
return (pair_ptr->i + pair_ptr->j);
|
||||
}
|
||||
@end
|
||||
/* Invocation.m
|
||||
- initWithTarget: target selector: (SEL)s, ...
|
||||
[1] Adding CASE_TYPE(_C_CLASS, Class);
|
||||
[2] Adding default: block
|
||||
|
||||
NSInvocation.h
|
||||
[3] Adding NS_INVOCATION
|
||||
[4, 5] Adding NS_MESSAGE
|
||||
|
||||
NSMethodSignature.m
|
||||
[6] Modifiying -(NSArgumentInfo)argumentInfoAtIndex:(unsigned)index */
|
||||
|
||||
void test1();
|
||||
void test2();
|
||||
void test3();
|
||||
void test4();
|
||||
void test5();
|
||||
void test6();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
id pool = [NSAutoreleasePool new];
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
test1()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(member:);
|
||||
Class c = [Pair class];
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, c];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test1 YES == %s\n", result? "YES": "NO");
|
||||
}
|
||||
|
||||
void
|
||||
test2()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(plus:);
|
||||
SEL sel_ptr = @selector(plus_ptr:);
|
||||
struct pair pair0;
|
||||
struct pair * pair0_ptr;
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
|
||||
pair0.i = 3;
|
||||
pair0.j = 4;
|
||||
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-1 %d == 7\n", result);
|
||||
|
||||
pair0_ptr = &pair0;
|
||||
pair0_ptr->i = 2;
|
||||
pair0_ptr->j = 3;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel_ptr, &pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-2 %d == 5\n", result);
|
||||
}
|
||||
|
||||
void
|
||||
test3()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 1;
|
||||
pair0.j = 2;
|
||||
inv = NS_INVOCATION(Pair ,
|
||||
plus:,
|
||||
pair0);
|
||||
[inv setTarget: ipair];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test3 3 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test4()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 3;
|
||||
pair0.j = 8;
|
||||
inv = NS_MESSAGE(ipair ,
|
||||
plus_ptr:,
|
||||
&pair0); // Method with args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test4 11 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test5()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
NSInvocation * inv;
|
||||
int x;
|
||||
|
||||
inv = NS_MESSAGE(ipair,
|
||||
hash); // Method with NO args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test5 hash value of an object == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test6()
|
||||
{
|
||||
NSObject * foo = [NSObject new];
|
||||
NSArgumentInfo info;
|
||||
SEL sel = @selector(isKindOfClass:);
|
||||
NSMethodSignature * ms = [foo methodSignatureForSelector: sel];
|
||||
info = [ms argumentInfoAtIndex: 0];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 1];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 2];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
}
|
||||
|
||||
#undef TYPE
|
|
@ -1,181 +0,0 @@
|
|||
#include <Foundation/NSMethodSignature.h>
|
||||
#include <Foundation/NSInvocation.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <base/Invocation.h>
|
||||
|
||||
#define TYPE long
|
||||
|
||||
struct pair {
|
||||
TYPE i;
|
||||
TYPE j;
|
||||
};
|
||||
|
||||
@interface Pair: NSObject
|
||||
- (TYPE)member:(Class)c;
|
||||
- (TYPE)plus: (struct pair) pair;
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr;
|
||||
@end
|
||||
|
||||
@implementation Pair
|
||||
- (TYPE)member:(Class)c
|
||||
{
|
||||
if ([self class] == c)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
- (TYPE)plus: (struct pair) pair
|
||||
{
|
||||
return (pair.i + pair.j);
|
||||
}
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr
|
||||
{
|
||||
return (pair_ptr->i + pair_ptr->j);
|
||||
}
|
||||
@end
|
||||
/* Invocation.m
|
||||
- initWithTarget: target selector: (SEL)s, ...
|
||||
[1] Adding CASE_TYPE(_C_CLASS, Class);
|
||||
[2] Adding default: block
|
||||
|
||||
NSInvocation.h
|
||||
[3] Adding NS_INVOCATION
|
||||
[4, 5] Adding NS_MESSAGE
|
||||
|
||||
NSMethodSignature.m
|
||||
[6] Modifiying -(NSArgumentInfo)argumentInfoAtIndex:(unsigned)index */
|
||||
|
||||
void test1();
|
||||
void test2();
|
||||
void test3();
|
||||
void test4();
|
||||
void test5();
|
||||
void test6();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
id pool = [NSAutoreleasePool new];
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
[pool release];
|
||||
}
|
||||
|
||||
void
|
||||
test1()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(member:);
|
||||
Class c = [Pair class];
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, c];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test1 YES == %s\n", result? "YES": "NO");
|
||||
}
|
||||
|
||||
void
|
||||
test2()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(plus:);
|
||||
SEL sel_ptr = @selector(plus_ptr:);
|
||||
struct pair pair0;
|
||||
struct pair * pair0_ptr;
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
|
||||
pair0.i = 3;
|
||||
pair0.j = 4;
|
||||
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-1 %d == 7\n", result);
|
||||
|
||||
pair0_ptr = &pair0;
|
||||
pair0_ptr->i = 2;
|
||||
pair0_ptr->j = 3;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel_ptr, &pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-2 %d == 5\n", result);
|
||||
}
|
||||
|
||||
void
|
||||
test3()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 1;
|
||||
pair0.j = 2;
|
||||
inv = NS_INVOCATION(Pair ,
|
||||
plus:,
|
||||
pair0);
|
||||
[inv setTarget: ipair];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test3 3 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test4()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 3;
|
||||
pair0.j = 8;
|
||||
inv = NS_MESSAGE(ipair ,
|
||||
plus_ptr:,
|
||||
&pair0); // Method with args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test4 11 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test5()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
NSInvocation * inv;
|
||||
int x;
|
||||
|
||||
inv = NS_MESSAGE(ipair,
|
||||
hash); // Method with NO args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test5 hash value of an object == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test6()
|
||||
{
|
||||
NSObject * foo = [NSObject new];
|
||||
NSArgumentInfo info;
|
||||
SEL sel = @selector(isKindOfClass:);
|
||||
NSMethodSignature * ms = [foo methodSignatureForSelector: sel];
|
||||
info = [ms argumentInfoAtIndex: 0];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 1];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 2];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
}
|
||||
|
||||
#undef TYPE
|
|
@ -1,179 +0,0 @@
|
|||
#include <Foundation/NSMethodSignature.h>
|
||||
#include <Foundation/NSInvocation.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <base/Invocation.h>
|
||||
|
||||
#define TYPE short
|
||||
|
||||
struct pair {
|
||||
TYPE i;
|
||||
TYPE j;
|
||||
};
|
||||
|
||||
@interface Pair: NSObject
|
||||
- (TYPE)member:(Class)c;
|
||||
- (TYPE)plus: (struct pair) pair;
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr;
|
||||
@end
|
||||
|
||||
@implementation Pair
|
||||
- (TYPE)member:(Class)c
|
||||
{
|
||||
if ([self class] == c)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
- (TYPE)plus: (struct pair) pair
|
||||
{
|
||||
return (pair.i + pair.j);
|
||||
}
|
||||
- (TYPE)plus_ptr: (struct pair*) pair_ptr
|
||||
{
|
||||
return (pair_ptr->i + pair_ptr->j);
|
||||
}
|
||||
@end
|
||||
/* Invocation.m
|
||||
- initWithTarget: target selector: (SEL)s, ...
|
||||
[1] Adding CASE_TYPE(_C_CLASS, Class);
|
||||
[2] Adding default: block
|
||||
|
||||
NSInvocation.h
|
||||
[3] Adding NS_INVOCATION
|
||||
[4, 5] Adding NS_MESSAGE
|
||||
|
||||
NSMethodSignature.m
|
||||
[6] Modifiying -(NSArgumentInfo)argumentInfoAtIndex:(unsigned)index */
|
||||
|
||||
void test1();
|
||||
void test2();
|
||||
void test3();
|
||||
void test4();
|
||||
void test5();
|
||||
void test6();
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test6();
|
||||
}
|
||||
|
||||
void
|
||||
test1()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(member:);
|
||||
Class c = [Pair class];
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, c];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test1 YES == %s\n", result? "YES": "NO");
|
||||
}
|
||||
|
||||
void
|
||||
test2()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
SEL sel = @selector(plus:);
|
||||
SEL sel_ptr = @selector(plus_ptr:);
|
||||
struct pair pair0;
|
||||
struct pair * pair0_ptr;
|
||||
Invocation * inv;
|
||||
TYPE result;
|
||||
|
||||
pair0.i = 3;
|
||||
pair0.j = 4;
|
||||
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel, pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-1 %d == 7\n", result);
|
||||
|
||||
pair0_ptr = &pair0;
|
||||
pair0_ptr->i = 2;
|
||||
pair0_ptr->j = 3;
|
||||
inv = [[MethodInvocation alloc]
|
||||
initWithTarget: ipair
|
||||
selector: sel_ptr, &pair0];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &result];
|
||||
fprintf(stderr, "test2-2 %d == 5\n", result);
|
||||
}
|
||||
|
||||
void
|
||||
test3()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 1;
|
||||
pair0.j = 2;
|
||||
inv = NS_INVOCATION(Pair ,
|
||||
plus:,
|
||||
pair0);
|
||||
[inv setTarget: ipair];
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test3 3 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test4()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
struct pair pair0;
|
||||
NSInvocation * inv;
|
||||
TYPE x;
|
||||
pair0.i = 3;
|
||||
pair0.j = 8;
|
||||
inv = NS_MESSAGE(ipair ,
|
||||
plus_ptr:,
|
||||
&pair0); // Method with args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test4 11 == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test5()
|
||||
{
|
||||
Pair * ipair = [Pair new];
|
||||
NSInvocation * inv;
|
||||
int x;
|
||||
|
||||
inv = NS_MESSAGE(ipair,
|
||||
hash); // Method with NO args
|
||||
[inv invoke];
|
||||
[inv getReturnValue: &x];
|
||||
fprintf(stderr, "test5 hash value of an object == %d\n", x);
|
||||
}
|
||||
|
||||
void
|
||||
test6()
|
||||
{
|
||||
NSObject * foo = [NSObject new];
|
||||
NSArgumentInfo info;
|
||||
SEL sel = @selector(isKindOfClass:);
|
||||
NSMethodSignature * ms = [foo methodSignatureForSelector: sel];
|
||||
info = [ms argumentInfoAtIndex: 0];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 1];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
info = [ms argumentInfoAtIndex: 2];
|
||||
fprintf(stderr, "test6 (%d, %d, %s)\n", info.offset, info.size, info.type);
|
||||
}
|
||||
|
||||
#undef TYPE
|
|
@ -1,17 +0,0 @@
|
|||
#include <base/StdioStream.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char b[100];
|
||||
int len;
|
||||
id s = [[StdioStream alloc] initWithPipeFrom: @"cat /etc/group | sort"];
|
||||
|
||||
while ((len = [s readBytes:b length:99]) > 0)
|
||||
{
|
||||
b[len] = '\0';
|
||||
printf("[%d]: %s\n", len, b);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
Loading…
Reference in a new issue