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:
richard 2000-04-18 09:02:38 +00:00
parent 2fe1953386
commit 15d28621f9
14 changed files with 770 additions and 353 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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>
&#60;?xml version="1.0"?>
&#60;!DOCTYPE gsdoc PUBLIC "-//GNUstep//DTD gsdoc 0.6.5//EN" "http://www.gnustep.org/gsdoc-0_6_5.xml">
&#60;gsdoc base="MyDoc" prev="First.html" next="Last.html" up="Overview.html">
&#60;head>
... your document head here
&#60;/head>
&#60;body>
... your document body here
&#60;/body>
&#60;/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>
&#60;head>
&#60;title>GNUstep Documentation XML markup language (GSDoc)&#60;/title>
&#60;author name="Richard Frith-Macdonald">
&#60;email address="rfm@gnu.org"/>
&#60;url url="http://www.gnustep.org/developers/whoiswho.html"/>
&#60;desc>
A person who has devotes far too much time to GNUstep development.
&#60;/desc>
&#60;/author>
&#60;version>0.1&#60;/version>
&#60;date>4 march, 2000&#60;/date>
&#60;abstract>
This documents the GNUstep Documentation markup language and tools
&#60;/abstract>
&#60;copy>Free Software Foundation, Inc.&#60;/copy>
&#60;/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>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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