mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-25 01:31:08 +00:00
Various changes for improved uniquing
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@6478 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
2fe1953386
commit
15d28621f9
14 changed files with 770 additions and 353 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2000-04-18 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Documentation/gsdoc/NSCountedSet.gsdoc: Method descriptions fleshed
|
||||
out, including GNUstep additional methods and related functions.
|
||||
* Documentation/gsdoc/NSDeserializer.gsdoc: GNUstep specific extension
|
||||
method documented.
|
||||
* GSDoc/gnustep.gsdoc: Fixed use of 'standards' element.
|
||||
* Headers/NSSerialization.h: Removed some extensions.
|
||||
* Headers/NSSet.h: Added some extensions for uniquing.
|
||||
* Source/NSCountedSet.m: Added uniquing methods and functions.
|
||||
* Source/NSGCountedSet.m: Added optimised uniquing methods.
|
||||
* Source/NSSerializer.m: Simplified uniquing code using stuff from
|
||||
NSCountedSet.
|
||||
* Testing/benchmark.m: included uniquing serialization/deserialization.
|
||||
|
||||
2000-04-14 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/mframe.m: Update to handle '-' in stack position information
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
<email address="rfm@gnu.org"/>
|
||||
<url url="http://www.gnustep.org/developers/whoiswho.html"/>
|
||||
</author>
|
||||
<version>0.1</version>
|
||||
<date>28 February, 2000</date>
|
||||
<version>1.0</version>
|
||||
<date>18 April, 2000</date>
|
||||
</head>
|
||||
<body>
|
||||
<chapter>
|
||||
|
@ -17,59 +17,165 @@
|
|||
<declared>Foundation/NSSet.h</declared>
|
||||
<conform>NSCoding</conform>
|
||||
<desc>
|
||||
<p>
|
||||
The NSCountedSet class is used to maintain a set of objects where
|
||||
the number of times each object has been added (wiithout a
|
||||
corresponding removal) is kept track of.
|
||||
</p>
|
||||
<p>
|
||||
In GNUstep, extra methods are provided to make use of a counted
|
||||
set for <em>uniquing</em> objects easier.
|
||||
</p>
|
||||
</desc>
|
||||
<method type="void">
|
||||
<sel>addObject:</sel>
|
||||
<arg type="id">anObject</arg>
|
||||
<desc>
|
||||
Adds an object to the set. If the set already contains an object
|
||||
equal to the specified object (as determined by the [-isEqual:]
|
||||
method) then the count for that object is incremented rather
|
||||
than the new object being added.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="NSArray*">
|
||||
<sel>allObjects</sel>
|
||||
<desc>
|
||||
Returns an array containing all the objects stored in the set.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="unsigned int">
|
||||
<sel>count</sel>
|
||||
<desc>
|
||||
Returns the number of objects stored in the set.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="unsigned int">
|
||||
<sel>countForObject:</sel>
|
||||
<arg type="id">anObject</arg>
|
||||
<desc>
|
||||
Returns the number of times that an object that is equal to the
|
||||
specified object (as determined byt the [-isEqual:] method) has
|
||||
been added to the set and not removed from it.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="id">
|
||||
<sel>initWithArray:</sel>
|
||||
<arg type="NSArray*">anArray</arg>
|
||||
<desc>
|
||||
Initialises a newly allocated set by adding all the objects
|
||||
in the supplied array to the set. Each object is added to
|
||||
the set as many times as it occurs in the array.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="id">
|
||||
<sel>initWithCapacity:</sel>
|
||||
<arg type="unsigned int">numItems</arg>
|
||||
<desc>
|
||||
Initialises a newly allocated set to contain no objects but
|
||||
to have space available to hold the specified number of items.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="id">
|
||||
<sel>initWithSet:</sel>
|
||||
<arg type="NSSet*">aSet</arg>
|
||||
<desc>
|
||||
Initialises a newly allocated set by adding all the objects
|
||||
in the supplied set.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="NSEnumerator*">
|
||||
<sel>objectEnumerator</sel>
|
||||
<desc>
|
||||
Returns an NSEnumerator object able to step through all the
|
||||
objects in the set.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="void">
|
||||
<sel>purge:</sel>
|
||||
<arg type="int">count</arg>
|
||||
<desc>
|
||||
<p>
|
||||
This method removes from the set all objects whose count is
|
||||
less than or equal to the specified value.
|
||||
</p>
|
||||
<p>
|
||||
This is useful where a counted set is used for uniquing objects.
|
||||
The set can be periodically purged of objects that have only
|
||||
been added once - and are therefore simply wasting space.
|
||||
</p>
|
||||
</desc>
|
||||
<standards><NotOpenStep/><NotMacOS-X/></standards>
|
||||
</method>
|
||||
<method type="void">
|
||||
<sel>removeObject:</sel>
|
||||
<arg type="id">anObject</arg>
|
||||
<desc>
|
||||
Decrements the count of the number of times that the specified
|
||||
object (or an object qequal to it as determined by the
|
||||
[-isEqual:] method) has been added to the set. If the count
|
||||
becomes zero, the object is removed from the set.
|
||||
</desc>
|
||||
</method>
|
||||
<method type="id">
|
||||
<sel>unique:</sel>
|
||||
<arg type="id">anObject</arg>
|
||||
<desc>
|
||||
<p>
|
||||
If the supplied object (or one equal to it as determined by
|
||||
the [-isEqual:] method) is already present in the set, the
|
||||
count for that object is incremented, the supplied object
|
||||
is released, and the object in the set is retained and returned.
|
||||
Otherwise, the supplied object is added to the set and returned.
|
||||
</p>
|
||||
<p>
|
||||
This method is useful for uniquing objects - the init method of
|
||||
a class need simply end with -
|
||||
<code>
|
||||
return [myUniquingSet unique: self];
|
||||
</code>
|
||||
</p>
|
||||
</desc>
|
||||
<standards><NotOpenStep/><NotMacOS-X/></standards>
|
||||
</method>
|
||||
</class>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<heading>NSCountedSet related functions</heading>
|
||||
<p>
|
||||
GNUstep provides some functions that may be using to maintain a
|
||||
global NSCountedSet object for usin in uniquing objects. In a
|
||||
multi-threaded application, accesses to this global set are
|
||||
automatically protected by locks.
|
||||
</p>
|
||||
<function name="GSUniquing" type="void">
|
||||
<arg type="BOOL">flag</arg>
|
||||
<desc>
|
||||
This function sets the state of a flag that determines the
|
||||
behavior of the GSUnique() function. If the flag is on,
|
||||
uniquing is performed, if it is off the function has no effect.
|
||||
The default is for uniquing to be turned off.
|
||||
</desc>
|
||||
<standards><GNUstep/><NotOpenStep/><NotMacOS-X/></standards>
|
||||
</function>
|
||||
<function name="GSUnique" type="id">
|
||||
<arg type="id">anObject</arg>
|
||||
<desc>
|
||||
This function <em>uniques</em> the supplied argument, returning
|
||||
the result. It works by using the [-unique:] method of a global
|
||||
NSCountedSet object. It handles locking as necessary.
|
||||
If uniquing is turned off, it simply returns its argument.
|
||||
</desc>
|
||||
<standards><GNUstep/><NotOpenStep/><NotMacOS-X/></standards>
|
||||
</function>
|
||||
<function name="GSUPurge" type="void">
|
||||
<arg type="int">count</arg>
|
||||
<desc>
|
||||
This function purges the global NSCountedSet object used for
|
||||
uniquing. It handles locking as necessary. It can be used to
|
||||
purge the set even when uniquing is turned off.
|
||||
</desc>
|
||||
<standards><GNUstep/><NotOpenStep/><NotMacOS-X/></standards>
|
||||
</function>
|
||||
</chapter>
|
||||
</body>
|
||||
</gsdoc>
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
<dt><a href="http://www.gnustep.org/developers/whoiswho.html">Richard Frith-Macdonald</a>
|
||||
<dd>
|
||||
</dl>
|
||||
<p>Version: 0.1</p>
|
||||
<p>Date: 28 February, 2000</p>
|
||||
<p>Version: 1.0</p>
|
||||
<p>Date: 18 April, 2000</p>
|
||||
<h2><a name="cont-0">NSCountedSet</a></h2>
|
||||
<h2><a name="NSCountedSet">NSCountedSet</a></h2>
|
||||
<p><b>Declared in:</b> Foundation/NSSet.h</p>
|
||||
|
@ -21,6 +21,19 @@
|
|||
</p>
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
|
||||
The NSCountedSet class is used to maintain a set of objects where
|
||||
the number of times each object has been added (wiithout a
|
||||
corresponding removal) is kept track of.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
In GNUstep, extra methods are provided to make use of a counted
|
||||
set for <em>uniquing</em> objects easier.
|
||||
</p>
|
||||
|
||||
|
||||
<ul>
|
||||
<li><a href="NSCountedSet.html#method-0">-addObject:</a>
|
||||
|
@ -31,53 +44,154 @@
|
|||
<li><a href="NSCountedSet.html#method-5">-initWithCapacity:</a>
|
||||
<li><a href="NSCountedSet.html#method-6">-initWithSet:</a>
|
||||
<li><a href="NSCountedSet.html#method-7">-objectEnumerator</a>
|
||||
<li><a href="NSCountedSet.html#method-8">-removeObject:</a>
|
||||
<li><a href="NSCountedSet.html#method-8">-purge:</a>
|
||||
<li><a href="NSCountedSet.html#method-9">-removeObject:</a>
|
||||
<li><a href="NSCountedSet.html#method-10">-unique:</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2><a name="method-0">addObject:</a></h2>
|
||||
- (void) <b>addObject:</b> (id)anObject<br>
|
||||
|
||||
Adds an object to the set. If the set already contains an object
|
||||
equal to the specified object (as determined by the [-isEqual:]
|
||||
method) then the count for that object is incremented rather
|
||||
than the new object being added.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-1">allObjects</a></h2>
|
||||
- (NSArray*) <b>allObjects</b><br>
|
||||
|
||||
Returns an array containing all the objects stored in the set.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-2">count</a></h2>
|
||||
- (unsigned int) <b>count</b><br>
|
||||
|
||||
Returns the number of objects stored in the set.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-3">countForObject:</a></h2>
|
||||
- (unsigned int) <b>countForObject:</b> (id)anObject<br>
|
||||
|
||||
Returns the number of times that an object that is equal to the
|
||||
specified object (as determined byt the [-isEqual:] method) has
|
||||
been added to the set and not removed from it.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-4">initWithArray:</a></h2>
|
||||
- (id) <b>initWithArray:</b> (NSArray*)anArray<br>
|
||||
|
||||
Initialises a newly allocated set by adding all the objects
|
||||
in the supplied array to the set. Each object is added to
|
||||
the set as many times as it occurs in the array.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-5">initWithCapacity:</a></h2>
|
||||
- (id) <b>initWithCapacity:</b> (unsigned int)numItems<br>
|
||||
|
||||
Initialises a newly allocated set to contain no objects but
|
||||
to have space available to hold the specified number of items.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-6">initWithSet:</a></h2>
|
||||
- (id) <b>initWithSet:</b> (NSSet*)aSet<br>
|
||||
|
||||
Initialises a newly allocated set by adding all the objects
|
||||
in the supplied set.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-7">objectEnumerator</a></h2>
|
||||
- (NSEnumerator*) <b>objectEnumerator</b><br>
|
||||
|
||||
Returns an NSEnumerator object able to step through all the
|
||||
objects in the set.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-8">removeObject:</a></h2>
|
||||
- (void) <b>removeObject:</b> (id)anObject<br>
|
||||
<h2><a name="method-8">purge:</a></h2>
|
||||
- (void) <b>purge:</b> (int)count<br>
|
||||
Standards: NotOpenStep NotMacOS-X<br>
|
||||
|
||||
<p>
|
||||
|
||||
This method removes from the set all objects whose count is
|
||||
less than or equal to the specified value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
This is useful where a counted set is used for uniquing objects.
|
||||
The set can be periodically purged of objects that have only
|
||||
been added once - and are therefore simply wasting space.
|
||||
</p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-9">removeObject:</a></h2>
|
||||
- (void) <b>removeObject:</b> (id)anObject<br>
|
||||
|
||||
Decrements the count of the number of times that the specified
|
||||
object (or an object qequal to it as determined by the
|
||||
[-isEqual:] method) has been added to the set. If the count
|
||||
becomes zero, the object is removed from the set.
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-10">unique:</a></h2>
|
||||
- (id) <b>unique:</b> (id)anObject<br>
|
||||
Standards: NotOpenStep NotMacOS-X<br>
|
||||
|
||||
<p>
|
||||
|
||||
If the supplied object (or one equal to it as determined by
|
||||
the [-isEqual:] method) is already present in the set, the
|
||||
count for that object is incremented, the supplied object
|
||||
is released, and the object in the set is retained and returned.
|
||||
Otherwise, the supplied object is added to the set and returned.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
This method is useful for uniquing objects - the init method of
|
||||
a class need simply end with -
|
||||
<code>
|
||||
return [myUniquingSet unique: self];
|
||||
</code>
|
||||
</p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="cont-1">NSCountedSet related functions</a></h2>
|
||||
<p>
|
||||
|
||||
GNUstep provides some functions that may be using to maintain a
|
||||
global NSCountedSet object for usin in uniquing objects. In a
|
||||
multi-threaded application, accesses to this global set are
|
||||
automatically protected by locks.
|
||||
</p>
|
||||
<h2><a name="function-11">GSUniquing</a></h2>
|
||||
<b>Prototype:</b> void GSUniquing(BOOL flag)<br>
|
||||
|
||||
This function sets the state of a flag that determines the
|
||||
behavior of the GSUnique() function. If the flag is on,
|
||||
uniquing is performed, if it is off the function has no effect.
|
||||
The default is for uniquing to be turned off.
|
||||
|
||||
<hr>
|
||||
<h2><a name="function-12">GSUnique</a></h2>
|
||||
<b>Prototype:</b> id GSUnique(id anObject)<br>
|
||||
|
||||
This function <em>uniques</em> the supplied argument, returning
|
||||
the result. It works by using the [-unique:] method of a global
|
||||
NSCountedSet object. It handles locking as necessary.
|
||||
If uniquing is turned off, it simply returns its argument.
|
||||
|
||||
<hr>
|
||||
<h2><a name="function-13">GSUPurge</a></h2>
|
||||
<b>Prototype:</b> void GSUPurge(int count)<br>
|
||||
|
||||
This function purges the global NSCountedSet object used for
|
||||
uniquing. It handles locking as necessary. It can be used to
|
||||
purge the set even when uniquing is turned off.
|
||||
|
||||
<hr>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
<email address="rfm@gnu.org"/>
|
||||
<url url="http://www.gnustep.org/developers/whoiswho.html"/>
|
||||
</author>
|
||||
<version>0.1</version>
|
||||
<date>28 February, 2000</date>
|
||||
<version>0.2</version>
|
||||
<date>18 April, 2000</date>
|
||||
</head>
|
||||
<body>
|
||||
<chapter>
|
||||
|
@ -48,6 +48,17 @@
|
|||
<desc>
|
||||
</desc>
|
||||
</method>
|
||||
<method type="void" factory="yes">
|
||||
<sel>uniquing:</sel>
|
||||
<arg type="BOOL">flag</arg>
|
||||
<desc>
|
||||
This method turns on/off uniquing of strings as they are
|
||||
deserialized from data objects. The uniquing mechanism
|
||||
employs the GNUstep-specific functions documented with
|
||||
the NSCountedSet class.
|
||||
</desc>
|
||||
<standards><GNUstep/><NotOpenStep/><NotMacOS-X/></standards>
|
||||
</method>
|
||||
</class>
|
||||
</chapter>
|
||||
</body>
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
<dt><a href="http://www.gnustep.org/developers/whoiswho.html">Richard Frith-Macdonald</a>
|
||||
<dd>
|
||||
</dl>
|
||||
<p>Version: 0.1</p>
|
||||
<p>Date: 28 February, 2000</p>
|
||||
<p>Version: 0.2</p>
|
||||
<p>Date: 18 April, 2000</p>
|
||||
<h2><a name="cont-0">NSDeserializer</a></h2>
|
||||
<h2><a name="NSDeserializer">NSDeserializer</a></h2>
|
||||
<p><b>Declared in:</b> Foundation/NSSerialization.h</p>
|
||||
|
@ -26,6 +26,7 @@
|
|||
<li><a href="NSDeserializer.html#method-0">+deserializePropertyListFromData:atCursor:mutableContainers:</a>
|
||||
<li><a href="NSDeserializer.html#method-1">+deserializePropertyListFromData:mutableContainers:</a>
|
||||
<li><a href="NSDeserializer.html#method-2">+deserializePropertyListLazilyFromData:atCursor:length:mutableContainers:</a>
|
||||
<li><a href="NSDeserializer.html#method-3">+uniquing:</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2><a name="method-0">deserializePropertyListFromData:atCursor:mutableContainers:</a></h2>
|
||||
|
@ -42,6 +43,16 @@
|
|||
+ (id) <b>deserializePropertyListLazilyFromData:</b> (NSData*)data <b>atCursor:</b> (unsigned int*)cursor <b>length:</b> (unsigned int)length <b>mutableContainers:</b> (BOOL)mutable<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-3">uniquing:</a></h2>
|
||||
+ (void) <b>uniquing:</b> (BOOL)flag<br>
|
||||
Standards: GNUstep NotOpenStep NotMacOS-X<br>
|
||||
|
||||
This method turns on/off uniquing of strings as they are
|
||||
deserialized from data objects. The uniquing mechanism
|
||||
employs the GNUstep-specific functions documented with
|
||||
the NSCountedSet class.
|
||||
|
||||
<hr>
|
||||
</body>
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@
|
|||
</desc>
|
||||
</method>
|
||||
|
||||
<standard>OpenStep GNU</standard>
|
||||
<standards><OpenStep/><GNUstep/></standards>
|
||||
|
||||
</class>
|
||||
|
||||
|
@ -279,7 +279,7 @@
|
|||
</desc>
|
||||
</method>
|
||||
|
||||
<standard>OpenStep GNU</standard>
|
||||
<standards><OpenStep/><GNUstep></standards>
|
||||
</class>
|
||||
</chapter>
|
||||
<back>
|
||||
|
@ -370,7 +370,7 @@ function (void *ptr)
|
|||
<desc>
|
||||
Return the larger between <var>a</var> and <var>b</var>.
|
||||
</desc>
|
||||
<standard>GNU</standard>
|
||||
<standards><GNUstep/></standards>
|
||||
</macro>
|
||||
|
||||
<macro name="NS_DURING">
|
||||
|
@ -399,7 +399,7 @@ function (void *ptr)
|
|||
Allocate <var>size</var> bytes from the dynamic memory
|
||||
allocation zone <var>zone</var>.
|
||||
</desc>
|
||||
<standard>OpenStep GNU</standard>
|
||||
<standards><OpenStep/><GNUstep/></standards>
|
||||
</function>
|
||||
</chapter>
|
||||
<index type="class"/>
|
||||
|
|
482
GSDoc/gsdoc.html
482
GSDoc/gsdoc.html
|
@ -1,260 +1,288 @@
|
|||
<html><head>
|
||||
<title>NSObject</title>
|
||||
<title>GNUstep Documentation XML markup language (GSDoc)</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>NSObject</h1>
|
||||
<h1>GNUstep Documentation XML markup language (GSDoc)</h1>
|
||||
<h3>Authors</h3>
|
||||
<dl>
|
||||
<dt><a href="http://www.gnustep.org/developers/whoiswho.html">Richard Frith-Macdonald</a>
|
||||
<dd>
|
||||
</dl>
|
||||
|
||||
A person who has devotes far too much time to GNUstep development.
|
||||
</dl>
|
||||
<p>Version: 0.1</p>
|
||||
<p>Date: 28 February, 2000</p>
|
||||
<h2><a name="cont-0">NSObject</a></h2>
|
||||
<h2><a name="NSObject">NSObject</a></h2>
|
||||
<p><b>Declared in:</b> Foundation/NSObject.h</p>
|
||||
<p><b>Conforms to:</b> NSObject
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
|
||||
<p>Date: 4 march, 2000</p>
|
||||
<blockquote>
|
||||
This documents the GNUstep Documentation markup language and tools
|
||||
</blockquote>
|
||||
<p>Copyright: Free Software Foundation, Inc.</p>
|
||||
<h1>Contents</h1>
|
||||
<ul>
|
||||
<li><a href="gsdoc.html#method-0">+alloc</a>
|
||||
<li><a href="gsdoc.html#method-1">+allocWithZone:</a>
|
||||
<li><a href="gsdoc.html#method-2">+cancelPreviousPerformRequestsWithTarget:selector:</a>
|
||||
<li><a href="gsdoc.html#method-3">+class</a>
|
||||
<li><a href="gsdoc.html#method-4">+conformsToProtocol:</a>
|
||||
<li><a href="gsdoc.html#method-5">+copyWithZone:</a>
|
||||
<li><a href="gsdoc.html#method-6">+description</a>
|
||||
<li><a href="gsdoc.html#method-7">+initialize</a>
|
||||
<li><a href="gsdoc.html#method-8">+instanceMethodForSelector:</a>
|
||||
<li><a href="gsdoc.html#method-9">+instanceMethodSignatureForSelector:</a>
|
||||
<li><a href="gsdoc.html#method-10">+instancesRespondToSelector:</a>
|
||||
<li><a href="gsdoc.html#method-11">+load</a>
|
||||
<li><a href="gsdoc.html#method-12">+mutableCopyWithZone:</a>
|
||||
<li><a href="gsdoc.html#method-13">+new</a>
|
||||
<li><a href="gsdoc.html#method-14">+poseAsClass:</a>
|
||||
<li><a href="gsdoc.html#method-15">+setVersion:</a>
|
||||
<li><a href="gsdoc.html#method-16">+superclass</a>
|
||||
<li><a href="gsdoc.html#method-17">+version</a>
|
||||
<li><a href="gsdoc.html#method-18">-awakeAfterUsingCoder:</a>
|
||||
<li><a href="gsdoc.html#method-19">-classForArchiver</a>
|
||||
<li><a href="gsdoc.html#method-20">-classForCoder</a>
|
||||
<li><a href="gsdoc.html#method-21">-classForPortCoder</a>
|
||||
<li><a href="gsdoc.html#method-22">-connection:handleRequest:</a>
|
||||
<li><a href="gsdoc.html#method-23">-copy</a>
|
||||
<li><a href="gsdoc.html#method-24">-dealloc</a>
|
||||
<li><a href="gsdoc.html#method-25">-description</a>
|
||||
<li><a href="gsdoc.html#method-26">-doesNotRecognizeSelector:</a>
|
||||
<li><a href="gsdoc.html#method-27">-forwardInvocation:</a>
|
||||
<li><a href="gsdoc.html#method-28">-hash</a>
|
||||
<li><a href="gsdoc.html#method-29">-init</a>
|
||||
<li><a href="gsdoc.html#method-30">-isEqual:</a>
|
||||
<li><a href="gsdoc.html#method-31">-methodForSelector:</a>
|
||||
<li><a href="gsdoc.html#method-32">-methodSignatureForSelector:</a>
|
||||
<li><a href="gsdoc.html#method-33">-mutableCopy</a>
|
||||
<li><a href="gsdoc.html#method-34">-performSelector:withObject:</a>
|
||||
<li><a href="gsdoc.html#method-35">-performSelector:withObject:afterDelay:inModes:</a>
|
||||
<li><a href="gsdoc.html#method-36">-replacementObjectForArchiver:</a>
|
||||
<li><a href="gsdoc.html#method-37">-replacementObjectForCoder:</a>
|
||||
<li><a href="gsdoc.html#method-38">-replacementObjectForPortCoder:</a>
|
||||
<li><a href="#cont-0">Introduction</a>
|
||||
<ul>
|
||||
<li><a href="#cont-1">Why another documentation language?</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2><a name="method-0">alloc</a></h2>
|
||||
+ (id) <b>alloc</b><br>
|
||||
<li><a href="#cont-2">The gsdoc DTD and what it means</a>
|
||||
<ul>
|
||||
<li><a href="#gsdoc">Overall document structure</a>
|
||||
<li><a href="#head">The document head</a>
|
||||
<li><a href="#body">The document body</a>
|
||||
</ul>
|
||||
<li><a href="#cont-3">The gsdoc conversion tool</a>
|
||||
</ul>
|
||||
<h2><a name="cont-0">Introduction</a></h2>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-1">allocWithZone:</a></h2>
|
||||
+ (id) <b>allocWithZone:</b> (NSZone*)zone<br>
|
||||
The GSDoc markup language is an XML language designed specifically
|
||||
for writing documentation for the
|
||||
<a href="http://www.gnustep.org">GNUstep project</a>.
|
||||
In practice, that means that it is designed for writing about
|
||||
software, and in particular, for writing about Objective-C classes.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-2">cancelPreviousPerformRequestsWithTarget:selector:</a></h2>
|
||||
+ (void) <b>cancelPreviousPerformRequestsWithTarget:</b> (id)aTarget <b>selector:</b> (SEL)aSelector<br>
|
||||
This is also an example, as well as a test case, of the new
|
||||
GNUstep documentation markup language (GSDoc).
|
||||
</p>
|
||||
<h3><a name="cont-1">Why another documentation language?</a></h3>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-3">class</a></h2>
|
||||
+ (Class) <b>class</b><br>
|
||||
There are several reasons for producing the new markup
|
||||
language -
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
There were no existing markup languages that dealt well with
|
||||
documenting software written in the Objective-C language,
|
||||
except the GDML language - which has no easy to use support
|
||||
software.
|
||||
|
||||
<li>
|
||||
While the DocBook system works nicely for general software
|
||||
documentation, it requires a relatively large amount of
|
||||
support software and comes with a lot of baggage that's
|
||||
not directly useful for GNUstep.
|
||||
|
||||
<li>
|
||||
The GNU info system comes with easy to use, lightweight
|
||||
conversion tools, but is particularly ill suited to
|
||||
Objective-C documentation because the colon character
|
||||
using in Objective-C method names is used in info markup.
|
||||
|
||||
<li>
|
||||
LinuxDoc, while being a nice basic system, seems to be
|
||||
in the process of being replaced by DocBook.
|
||||
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-4">conformsToProtocol:</a></h2>
|
||||
+ (BOOL) <b>conformsToProtocol:</b> (Protocol*)aProtocol<br>
|
||||
So, with only one markup language available that supported
|
||||
Objective-C, and with XML software becoming available, the
|
||||
decision was to take GDML and update it to be an XML
|
||||
language, in the hope that this would -
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Provide optimal support for GNUstep documentation.
|
||||
|
||||
<li>
|
||||
Minimize the amount of work needed for development of
|
||||
software tools.
|
||||
|
||||
<li>
|
||||
Provide future-proofing in that documentation written in one
|
||||
XML language should be quite easy to convert to another if
|
||||
necessary.
|
||||
|
||||
</ul>
|
||||
<h2><a name="cont-2">The gsdoc DTD and what it means</a></h2>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-5">copyWithZone:</a></h2>
|
||||
+ (id) <b>copyWithZone:</b> (NSZone*)zone<br>
|
||||
The GSDoc markup language is defined by an SGML DTD, that specifies
|
||||
the tags that may be used in marking up a GSDoc document, and how
|
||||
and where those tags may be placed. Please see the DTD for a
|
||||
precise specification.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-6">description</a></h2>
|
||||
+ (NSString*) <b>description</b><br>
|
||||
The gsdoc DTD defines an XML language - that is, a markup language
|
||||
that conforms to a specific subset of SGML features defined as XML.
|
||||
The advantage of XML is that it provides most of the useful features
|
||||
of SGML while being much more light-weight (easy to use) because
|
||||
you can forget about the rest of SGML.
|
||||
As XML looks set to become increasingly popular, we can hope that
|
||||
documentation written with an XML language will be easily imported
|
||||
into XML software tools as they become available, so we will not
|
||||
(in the GNUstep project) need to devote a lot of time and effort
|
||||
to maintaining documentation tools.
|
||||
</p>
|
||||
<h3><a name="gsdoc">Overall document structure</a></h3>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-7">initialize</a></h2>
|
||||
+ (void) <b>initialize</b><br>
|
||||
A GSDoc document consists of a <a href="#head">head</a> and a
|
||||
<a href="#body">body</a> wrapped inside the overall document
|
||||
framework that looks like this -
|
||||
</p>
|
||||
<a name="label-0">example</a>
|
||||
<pre>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-8">instanceMethodForSelector:</a></h2>
|
||||
+ (IMP) <b>instanceMethodForSelector:</b> (SEL)aSelector<br>
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE gsdoc PUBLIC "-//GNUstep//DTD gsdoc 0.6.5//EN" "http://www.gnustep.org/gsdoc-0_6_5.xml">
|
||||
<gsdoc base="MyDoc" prev="First.html" next="Last.html" up="Overview.html">
|
||||
<head>
|
||||
... your document head here
|
||||
</head>
|
||||
<body>
|
||||
... your document body here
|
||||
</body>
|
||||
</gsdoc>
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-9">instanceMethodSignatureForSelector:</a></h2>
|
||||
+ (NSMethodSignature*) <b>instanceMethodSignatureForSelector:</b> (SEL)aSelector<br>
|
||||
The above example shows a GSDoc document framework.
|
||||
The first line specifies the XML version that the document
|
||||
conforms to.
|
||||
The second line specifies the version of GSDoc that the
|
||||
document conforms to.
|
||||
The third and final lines frame the main part of the document
|
||||
and supply all the (optional) attributes of the <em>gsdoc</em>
|
||||
element -
|
||||
</p>
|
||||
<dl>
|
||||
<dt>base
|
||||
<dd>
|
||||
This is optional, but recommended - it specifies the base name
|
||||
for the document. When the document is translated to another
|
||||
format, the output file name should be based on this - eg.
|
||||
if the base name of a document is <em>foo</em> then an html
|
||||
output for this file would be <em>foo.html</em>.
|
||||
|
||||
<dt>prev
|
||||
<dd>
|
||||
This optional attribute may be used as the name of a document
|
||||
that precedes this one in logical reading order. If the
|
||||
converted output format of the document supports some sort of
|
||||
link between documents, the converter software may insert
|
||||
a link between the two documents.
|
||||
|
||||
<dt>next
|
||||
<dd>
|
||||
This optional attribute may be used as the name of a document
|
||||
that follows this one in logical reading order. If the
|
||||
converted output format of the document supports some sort of
|
||||
link between documents, the converter software may insert
|
||||
a link between the two documents.
|
||||
|
||||
<dt>up
|
||||
<dd>
|
||||
This optional attribute may be used as the name of a document
|
||||
that is above this document in some sort of hierarchical
|
||||
structure (a contents list perhaps).
|
||||
If the converted output format of the document supports some sort
|
||||
of link between documents, the converter software may insert
|
||||
a link between the two documents.
|
||||
|
||||
</dl>
|
||||
<h3><a name="head">The document head</a></h3>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-10">instancesRespondToSelector:</a></h2>
|
||||
+ (BOOL) <b>instancesRespondToSelector:</b> (SEL)aSelector<br>
|
||||
The document head contains information about the document as
|
||||
a whole: its title, authors, version, modification date,
|
||||
copyright, and perhaps an abstract of its contents.
|
||||
The title and at least one author are the only parts of the
|
||||
document head that must be present.
|
||||
</p>
|
||||
<a name="label-1">example</a>
|
||||
<pre>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-11">load</a></h2>
|
||||
+ (void) <b>load</b><br>
|
||||
<head>
|
||||
<title>GNUstep Documentation XML markup language (GSDoc)</title>
|
||||
<author name="Richard Frith-Macdonald">
|
||||
<email address="rfm@gnu.org"/>
|
||||
<url url="http://www.gnustep.org/developers/whoiswho.html"/>
|
||||
<desc>
|
||||
A person who has devotes far too much time to GNUstep development.
|
||||
</desc>
|
||||
</author>
|
||||
<version>0.1</version>
|
||||
<date>4 march, 2000</date>
|
||||
<abstract>
|
||||
This documents the GNUstep Documentation markup language and tools
|
||||
</abstract>
|
||||
<copy>Free Software Foundation, Inc.</copy>
|
||||
</head>
|
||||
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-12">mutableCopyWithZone:</a></h2>
|
||||
+ (id) <b>mutableCopyWithZone:</b> (NSZone*)zone<br>
|
||||
The above example shows all the elements possible in a document head -
|
||||
</p>
|
||||
<dl>
|
||||
<dt><a name="title">title</a>
|
||||
<dd>
|
||||
The title of the document.
|
||||
|
||||
<dt><a name="author">author</a>
|
||||
<dd>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-13">new</a></h2>
|
||||
+ (id) <b>new</b><br>
|
||||
The author of the document, also specifying an email address at
|
||||
which the author may be reached, a URL for a web page giving
|
||||
some information about the author, and an additional description
|
||||
of the author.
|
||||
</p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-14">poseAsClass:</a></h2>
|
||||
+ (void) <b>poseAsClass:</b> (Class)aClass<br>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-15">setVersion:</a></h2>
|
||||
+ (void) <b>setVersion:</b> (int)aVersion<br>
|
||||
Of course, a document may have more than one author, in which
|
||||
case you simply write multiple author elements.
|
||||
</p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-16">superclass</a></h2>
|
||||
+ (Class) <b>superclass</b><br>
|
||||
|
||||
<dt><a name="version">version</a>
|
||||
<dd>
|
||||
The version number of the document.
|
||||
|
||||
<dt><a name="date">date</a>
|
||||
<dd>
|
||||
The date at which the document was last modified.
|
||||
|
||||
<dt><a name="abstract">abstract</a>
|
||||
<dd>
|
||||
A <em>short</em> description of the document contents.
|
||||
|
||||
<dt><a name="copy">copy</a>
|
||||
<dd>
|
||||
The copyright owner of the document.
|
||||
|
||||
</dl>
|
||||
<h3><a name="body">The document body</a></h3>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-17">version</a></h2>
|
||||
+ (int) <b>version</b><br>
|
||||
The document body contains the main part of the document, it
|
||||
consists of an optional front part (for contents pages, overview
|
||||
etc), a sequence of any number of chapters, and an optional back
|
||||
part (for indexes, appendices etc). Normally, each of these three
|
||||
parts of the document would be expected to have their own separate
|
||||
page numbering schemes.
|
||||
</p>
|
||||
<h2><a name="cont-3">The gsdoc conversion tool</a></h2>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-18">awakeAfterUsingCoder:</a></h2>
|
||||
- (id) <b>awakeAfterUsingCoder:</b> (NSCoder*)aDecoder<br>
|
||||
The gsdoc tool is written in Objective-C and uses the GNUstep base
|
||||
library and the Gnome XML parser library.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-19">classForArchiver</a></h2>
|
||||
- (Class) <b>classForArchiver</b><br>
|
||||
This tool is intended to convert GSDoc documents to other formats
|
||||
though, at present, only HTML output is supported.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-20">classForCoder</a></h2>
|
||||
- (Class) <b>classForCoder</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-21">classForPortCoder</a></h2>
|
||||
- (Class) <b>classForPortCoder</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-22">connection:handleRequest:</a></h2>
|
||||
- (BOOL) <b>connection:</b> (NSConnection*)connection <b>handleRequest:</b> (NSDistantObjectRequest*)doreq<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-23">copy</a></h2>
|
||||
- (id) <b>copy</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-24">dealloc</a></h2>
|
||||
- (void) <b>dealloc</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-25">description</a></h2>
|
||||
- (NSString*) <b>description</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-26">doesNotRecognizeSelector:</a></h2>
|
||||
- (void) <b>doesNotRecognizeSelector:</b> (SEL)aSelector<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-27">forwardInvocation:</a></h2>
|
||||
- (void) <b>forwardInvocation:</b> (NSInvocation*)anInvocation<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-28">hash</a></h2>
|
||||
- (unsigned int) <b>hash</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-29">init</a></h2>
|
||||
- (id) <b>init</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-30">isEqual:</a></h2>
|
||||
- (BOOL) <b>isEqual:</b> (id)anObject<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-31">methodForSelector:</a></h2>
|
||||
- (IMP) <b>methodForSelector:</b> (SEL)aSelector<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-32">methodSignatureForSelector:</a></h2>
|
||||
- (NSMethodSignature*) <b>methodSignatureForSelector:</b> (SEL)aSelector<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-33">mutableCopy</a></h2>
|
||||
- (id) <b>mutableCopy</b><br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-34">performSelector:withObject:</a></h2>
|
||||
- (void) <b>performSelector:</b> (SEL)aSelector <b>withObject:</b> (id)anArgument<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-35">performSelector:withObject:afterDelay:inModes:</a></h2>
|
||||
- (void) <b>performSelector:</b> (SEL)aSelector <b>withObject:</b> (id)anArgument <b>afterDelay:</b> (NSTimeInterval)delay <b>inModes:</b> (NSArray*)modes<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-36">replacementObjectForArchiver:</a></h2>
|
||||
- (id) <b>replacementObjectForArchiver:</b> (NSArchiver*)anArchiver<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-37">replacementObjectForCoder:</a></h2>
|
||||
- (id) <b>replacementObjectForCoder:</b> (NSCoder*)aCoder<br>
|
||||
|
||||
|
||||
<hr>
|
||||
<h2><a name="method-38">replacementObjectForPortCoder:</a></h2>
|
||||
- (id) <b>replacementObjectForPortCoder:</b> (NSPortCoder*)aCoder<br>
|
||||
|
||||
|
||||
<hr>
|
||||
Use of the tool is trivial - just provide it with a list of gsdoc
|
||||
file names, and it will produce a load of html output files.
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
@interface NSDictionary (NonCore)
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone;
|
||||
+ (id) dictionary;
|
||||
+ (id) dictionaryWithContentsOfFile: (NSString*)path;
|
||||
+ (id) dictionaryWithDictionary: (NSDictionary*)aDict;
|
||||
|
@ -85,7 +84,6 @@
|
|||
|
||||
@interface NSMutableDictionary (NonCore)
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone;
|
||||
+ (id) dictionaryWithCapacity: (unsigned)numItems;
|
||||
|
||||
- (void) removeAllObjects;
|
||||
|
|
|
@ -90,17 +90,13 @@
|
|||
* efficient equality testing of uniqued strings).
|
||||
* The default is NOT to deserialize uniqued strings.
|
||||
*
|
||||
* The [+uniquing:] method turns uniquing on/off. Turning off uniquing
|
||||
* destroys the NSMutableSet used for uniquing.
|
||||
* The [+uniqueSet] method gives you direct access to the uniquing set.
|
||||
* The [+unique:] method lets you find the 'uniqued' version os a string.
|
||||
* The [+uniquing:] method turns uniquing on/off.
|
||||
* Uniquing is done using a global NSCountedSet - see NSCountedSet for
|
||||
* details.
|
||||
*/
|
||||
@class NSMutableSet;
|
||||
@interface NSDeserializer (GNUstep)
|
||||
+ (void) _becomeThreaded: (id)notification; /* private */
|
||||
+ (NSString*) unique: (NSString*)original;
|
||||
+ (void) uniquing: (BOOL)flag;
|
||||
+ (NSMutableSet*) uniqueSet;
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,8 +94,35 @@
|
|||
|
||||
#ifndef NO_GNUSTEP
|
||||
|
||||
/*
|
||||
* Utility methods for using a counted set to handle uniquing of objects.
|
||||
*/
|
||||
@interface NSCountedSet (GNU_Uniquing)
|
||||
- (void) purge: (int)level;
|
||||
- (id) unique: (id)anObject;
|
||||
@end
|
||||
|
||||
/*
|
||||
* Functions for managing a global uniquing set.
|
||||
*
|
||||
* GSUniquing() turns on/off the action of the GSUnique() function.
|
||||
* if uniquing is turned off, GSUnique() simply returns its argument.
|
||||
*
|
||||
* GSUnique() returns an object that is equal to the one passed to it.
|
||||
* If the returned object is not the same object as the object passed in,
|
||||
* the original object is released and the returned object is retained.
|
||||
* Thus, an -init metod that wants to implement uniquing simply needs
|
||||
* to end with 'return GSUnique(self);'
|
||||
*/
|
||||
void GSUniquing(BOOL flag);
|
||||
id GSUnique(id anObject);
|
||||
|
||||
/*
|
||||
* Management functions -
|
||||
*/
|
||||
void GSUPurge(int count); /* Purge infrequently referenced objs */
|
||||
|
||||
#include <base/KeyedCollecting.h>
|
||||
#include <Foundation/NSSet.h>
|
||||
|
||||
/* Eventually we'll make a Constant version of this protocol. */
|
||||
@interface NSSet (GNU) <Collecting>
|
||||
|
|
|
@ -28,10 +28,27 @@
|
|||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSUtilities.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSNotification.h>
|
||||
#include <Foundation/NSThread.h>
|
||||
|
||||
@class NSSetNonCore;
|
||||
@class NSMutableSetNonCore;
|
||||
|
||||
/*
|
||||
* Class variables for uniquing objects;
|
||||
*/
|
||||
static NSRecursiveLock *uniqueLock = nil;
|
||||
static NSCountedSet *uniqueSet = nil;
|
||||
static IMP uniqueImp = 0;
|
||||
static IMP lockImp = 0;
|
||||
static IMP unlockImp = 0;
|
||||
static BOOL uniquing = NO;
|
||||
|
||||
@interface NSCountedSet (GSThreading)
|
||||
+ (void) _becomeThreaded: (id)notification;
|
||||
@end
|
||||
|
||||
@implementation NSCountedSet
|
||||
|
||||
static Class NSCountedSet_abstract_class;
|
||||
|
@ -45,6 +62,18 @@ static Class NSCountedSet_concrete_class;
|
|||
NSCountedSet_concrete_class = [NSGCountedSet class];
|
||||
behavior_class_add_class(self, [NSMutableSetNonCore class]);
|
||||
behavior_class_add_class(self, [NSSetNonCore class]);
|
||||
if ([NSThread isMultiThreaded])
|
||||
{
|
||||
[self _becomeThreaded: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(_becomeThreaded:)
|
||||
name: NSWillBecomeMultiThreadedNotification
|
||||
object: nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +94,7 @@ static Class NSCountedSet_concrete_class;
|
|||
return [super allocWithZone: z];
|
||||
}
|
||||
|
||||
- (unsigned int) countForObject: anObject
|
||||
- (unsigned int) countForObject: (id)anObject
|
||||
{
|
||||
[self subclassResponsibility: _cmd];
|
||||
return 0;
|
||||
|
@ -129,4 +158,110 @@ static Class NSCountedSet_concrete_class;
|
|||
return self;
|
||||
}
|
||||
|
||||
- (void) purge: (int)level
|
||||
{
|
||||
if (level > 0)
|
||||
{
|
||||
NSEnumerator *enumerator = [self objectEnumerator];
|
||||
|
||||
if (enumerator != nil)
|
||||
{
|
||||
id obj;
|
||||
id (*nImp)(NSEnumerator*, SEL);
|
||||
unsigned (*cImp)(NSCountedSet*, SEL, id);
|
||||
void (*rImp)(NSCountedSet*, SEL, id);
|
||||
|
||||
nImp = (id (*)(NSEnumerator*, SEL))
|
||||
[enumerator methodForSelector: @selector(nextObject)];
|
||||
cImp = (unsigned (*)(NSCountedSet*, SEL, id))
|
||||
[self methodForSelector: @selector(countForObject:)];
|
||||
rImp = (void (*)(NSCountedSet*, SEL, id))
|
||||
[self methodForSelector: @selector(removeObject:)];
|
||||
while ((obj = (*nImp)(enumerator, @selector(nextObject))) != nil)
|
||||
{
|
||||
unsigned c = (*cImp)(self, @selector(countForObject:), obj);
|
||||
|
||||
if (c <= level)
|
||||
{
|
||||
while (c-- > 0)
|
||||
{
|
||||
(*rImp)(self, @selector(removeObject:), obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (id) unique: (id)anObject
|
||||
{
|
||||
id o = [self member: anObject];
|
||||
|
||||
[self addObject: anObject];
|
||||
#if !GS_WITH_GC
|
||||
if (o != anObject)
|
||||
{
|
||||
[anObject release];
|
||||
[o retain];
|
||||
}
|
||||
#endif
|
||||
return o;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSCountedSet (GSThreading)
|
||||
/*
|
||||
* If we are multi-threaded, we must guard access to the uniquing set.
|
||||
*/
|
||||
+ (void) _becomeThreaded: (id)notification
|
||||
{
|
||||
uniqueLock = [NSLock new];
|
||||
lockImp = [uniqueLock methodForSelector: @selector(lock)];
|
||||
unlockImp = [uniqueLock methodForSelector: @selector(unlock)];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
void
|
||||
GSUPurge(int level)
|
||||
{
|
||||
if (uniqueLock != nil)
|
||||
{
|
||||
(*lockImp)(uniqueLock, @selector(lock));
|
||||
}
|
||||
[uniqueSet purge: level];
|
||||
if (uniqueLock != nil)
|
||||
{
|
||||
(*unlockImp)(uniqueLock, @selector(unlock));
|
||||
}
|
||||
}
|
||||
|
||||
id
|
||||
GSUnique(id obj)
|
||||
{
|
||||
if (uniquing == YES)
|
||||
{
|
||||
if (uniqueLock != nil)
|
||||
{
|
||||
(*lockImp)(uniqueLock, @selector(lock));
|
||||
}
|
||||
obj = (*uniqueImp)(uniqueSet, @selector(unique:), obj);
|
||||
if (uniqueLock != nil)
|
||||
{
|
||||
(*unlockImp)(uniqueLock, @selector(unlock));
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
GSUniquing(BOOL flag)
|
||||
{
|
||||
if (uniqueSet == nil)
|
||||
{
|
||||
uniqueSet = [NSCountedSet new];
|
||||
uniqueImp = [uniqueSet methodForSelector: @selector(unique:)];
|
||||
}
|
||||
uniquing = flag;
|
||||
}
|
||||
|
||||
|
|
|
@ -253,6 +253,29 @@
|
|||
NSDefaultMallocZone()] initWithSet: self]);
|
||||
}
|
||||
|
||||
- (void) purge: (int)level
|
||||
{
|
||||
if (level > 0)
|
||||
{
|
||||
GSIMapNode node = map.firstNode;
|
||||
|
||||
while (node != 0)
|
||||
{
|
||||
GSIMapNode tmp = node->nextInMap;
|
||||
|
||||
if (node->value.uint <= level)
|
||||
{
|
||||
GSIMapBucket bucket;
|
||||
|
||||
bucket = GSIMapBucketForKey(&map, node->key);
|
||||
GSIMapRemoveNodeFromMap(&map, bucket, node);
|
||||
GSIMapFreeNode(&map, node);
|
||||
}
|
||||
node = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeObject: (NSObject*)anObject
|
||||
{
|
||||
GSIMapBucket bucket;
|
||||
|
@ -284,4 +307,35 @@
|
|||
GSIMapCleanMap(&map);
|
||||
}
|
||||
|
||||
- (id) unique: (id)anObject
|
||||
{
|
||||
GSIMapNode node;
|
||||
id result;
|
||||
|
||||
if (anObject == nil)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Tried to unique nil value in counted set"];
|
||||
}
|
||||
|
||||
node = GSIMapNodeForKey(&map, (GSIMapKey)anObject);
|
||||
if (node == 0)
|
||||
{
|
||||
result = anObject;
|
||||
GSIMapAddPairNoRetain(&map,(GSIMapKey)anObject,(GSIMapVal)(unsigned)1);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = node->key.obj;
|
||||
node->value.uint++;
|
||||
#if !GS_WITH_GC
|
||||
if (result != anObject)
|
||||
{
|
||||
[anObject release];
|
||||
[result retain];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -112,7 +112,7 @@ typedef struct {
|
|||
void (*serImp)(); // Serialize integer.
|
||||
void (*setImp)(); // Set length of data.
|
||||
unsigned count; // String counter.
|
||||
GSIMapTable_t map; // For uniquing.
|
||||
GSIMapTable_t map; // For uniquing.
|
||||
BOOL shouldUnique; // Do we do uniquing?
|
||||
} _NSSerializerInfo;
|
||||
|
||||
|
@ -347,15 +347,10 @@ static BOOL shouldBeCompact = NO;
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* Class variables for uniquing incoming strings.
|
||||
*/
|
||||
static NSRecursiveLock *uniqueLock = nil;
|
||||
static NSMutableSet *uniqueSet = nil;
|
||||
|
||||
/*
|
||||
* Variables to cache class information.
|
||||
*/
|
||||
static BOOL uniquing = NO; /* Make incoming strings unique */
|
||||
static Class IACls = 0; /* Immutable Array */
|
||||
static Class MACls = 0; /* Mutable Array */
|
||||
static Class DCls = 0; /* Data */
|
||||
|
@ -439,22 +434,8 @@ deserializeFromInfo(_NSDeserializerInfo* info)
|
|||
/*
|
||||
* If we are supposed to be doing uniquing of strings, handle it.
|
||||
*/
|
||||
if (uniqueSet != nil)
|
||||
{
|
||||
id uniqued;
|
||||
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock lock];
|
||||
[uniqueSet addObject: s];
|
||||
uniqued = [uniqueSet member: s];
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock unlock];
|
||||
if (uniqued != s)
|
||||
{
|
||||
RELEASE(s);
|
||||
s = RETAIN(uniqued);
|
||||
}
|
||||
}
|
||||
if (uniquing == YES)
|
||||
s = GSUnique(s);
|
||||
|
||||
/*
|
||||
* If uniquing was done on serialisation, store the string for
|
||||
|
@ -477,22 +458,8 @@ deserializeFromInfo(_NSDeserializerInfo* info)
|
|||
/*
|
||||
* If we are supposed to be doing uniquing of strings, handle it.
|
||||
*/
|
||||
if (uniqueSet != nil)
|
||||
{
|
||||
id uniqued;
|
||||
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock lock];
|
||||
[uniqueSet addObject: s];
|
||||
uniqued = [uniqueSet member: s];
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock unlock];
|
||||
if (uniqued != s)
|
||||
{
|
||||
RELEASE(s);
|
||||
s = RETAIN(uniqued);
|
||||
}
|
||||
}
|
||||
if (uniquing == YES)
|
||||
s = GSUnique(s);
|
||||
|
||||
/*
|
||||
* If uniquing was done on serialisation, store the string for
|
||||
|
@ -701,18 +668,6 @@ deserializeFromInfo(_NSDeserializerInfo* info)
|
|||
maInitImp = [MACls instanceMethodForSelector: maInitSel];
|
||||
idInitImp = [IDCls instanceMethodForSelector: idInitSel];
|
||||
mdInitImp = [MDCls instanceMethodForSelector: mdInitSel];
|
||||
if ([NSThread isMultiThreaded])
|
||||
{
|
||||
[self _becomeThreaded: nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(_becomeThreaded:)
|
||||
name: NSWillBecomeMultiThreadedNotification
|
||||
object: nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,57 +735,12 @@ deserializeFromInfo(_NSDeserializerInfo* info)
|
|||
}
|
||||
@end
|
||||
|
||||
@implementation NSDeserializer (GNUstep)
|
||||
/*
|
||||
* If we are multi-threaded, we must guard access to the uniquing set.
|
||||
*/
|
||||
+ (void) _becomeThreaded: (id)notification
|
||||
{
|
||||
uniqueLock = [NSRecursiveLock new];
|
||||
}
|
||||
|
||||
+ (NSMutableSet*) uniqueSet
|
||||
{
|
||||
return uniqueSet;
|
||||
}
|
||||
|
||||
+ (NSString*) unique: (NSString*)str
|
||||
{
|
||||
if (uniqueSet)
|
||||
{
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock lock];
|
||||
[uniqueSet addObject: str];
|
||||
str = [uniqueSet member: str];
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock unlock];
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn uniquing of deserialized strings on/off
|
||||
*/
|
||||
@implementation NSDeserializer (GNUstep)
|
||||
+ (void) uniquing: (BOOL)flag
|
||||
{
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock lock];
|
||||
if (flag)
|
||||
{
|
||||
if (uniqueSet == nil)
|
||||
{
|
||||
uniqueSet = [NSMutableSet new];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uniqueSet != nil)
|
||||
{
|
||||
DESTROY(uniqueSet);
|
||||
}
|
||||
}
|
||||
if (uniqueLock != nil)
|
||||
[uniqueLock unlock];
|
||||
if (flag == YES)
|
||||
GSUniquing(YES);
|
||||
uniquing = flag;
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
|
@ -358,6 +358,18 @@ bench_str()
|
|||
END_TIMER;
|
||||
PRINT_TIMER("NSString (ser/des)");
|
||||
|
||||
[NSDeserializer uniquing: YES];
|
||||
START_TIMER;
|
||||
for (i = 0; i < MAX_COUNT/100; i++)
|
||||
{
|
||||
NSData *d = [ser serializePropertyList: plist];
|
||||
id p = [des deserializePropertyListFromData: d
|
||||
mutableContainers: NO];
|
||||
}
|
||||
END_TIMER;
|
||||
PRINT_TIMER("NSString (ser/des - uniquing)");
|
||||
[NSDeserializer uniquing: NO];
|
||||
|
||||
START_TIMER;
|
||||
for (i = 0; i < MAX_COUNT/100; i++)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue