|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: NXUniquedString.m
26: Copyright 1991, NeXT, Inc.
27: Responsibility:
28: */
29:
30: #ifndef KERNEL
31: #ifdef SHLIB
32: #import "shlib.h"
33: #endif SHLIB
34:
35: #import <mach/cthreads.h>
36: #import "NXStringPrivate.h"
37: #import "HashTable.h"
38:
39: /* Mutex for mucking around with global stuff */
40: static struct mutex stringLock;
41:
42: /* For storing unique strings... Maps objects to objects. */
43: static HashTable *uniquedStringHashTable = nil;
44:
45: #if SEPARATE_UNIQUED_ZONE
46: static NXZone *uniquedStringZone = NULL; /* Zone for uniqued strings */
47: #else
48: #define uniquedStringZone stringZone
49: #endif
50:
51:
52: @implementation NXUniquedString
53:
54: + initialize
55: {
56: if ([self class] == [NXUniquedString class]) {
57: mutex_init(&stringLock);
58: #if SEPARATE_UNIQUED_ZONE
59: uniquedStringZone = NXCreateZone(vm_page_size, vm_page_size, YES);
60: #endif
61: uniquedStringHashTable = [[HashTable allocFromZone:uniquedStringZone] init];
62: }
63: return self;
64: }
65:
66: + newFromString:(NXString *)string
67: {
68: NXUniquedString *result;
69: if ([string isKindOf:self]) {
70: result = (NXUniquedString *)string;
71: } else {
72: mutex_lock(&stringLock);
73: if (!(result = [uniquedStringHashTable valueForKey:string])) {
74: unsigned newLength = [string length];
75: result = [self allocFromZone:uniquedStringZone];
76: result->characters = [result allocateCharacterBuffer:newLength];
77: result->_length = newLength;
78: [string getCharacters:result->characters];
79: [uniquedStringHashTable insertKey:result value:result];
80: }
81: mutex_unlock(&stringLock);
82: }
83: return result;
84: }
85:
86: + newFromCharacters:(const unichar *)chars length:(unsigned)length
87: {
88: NXReadOnlyString *string = [[NXReadOnlyString alloc] initFromCharactersNoCopy:(unichar *)chars length:length freeWhenDone:NO];
89: NXUniquedString *result = [self newFromString:string];
90: [string free];
91: return result;
92: }
93:
94: - initFromCharactersNoCopy:(unichar *)chars length:(unsigned)len
95: {
96: NXUniquedString *result;
97: NXReadOnlyString *string = [[NXReadOnlyString alloc] initFromCharactersNoCopy:chars length:len freeWhenDone:NO];
98: mutex_lock(&stringLock);
99: if ((result = [uniquedStringHashTable valueForKey:string])) {
100: // Already in the hash table
101: [self free];
102: } else {
103: // Not in the table; create a new string
104: [super initFromCharactersNoCopy:chars length:len];
105: [uniquedStringHashTable insertKey:self value:self];
106: result = self;
107: }
108: mutex_unlock(&stringLock);
109: [string free];
110: return result;
111: }
112:
113: + allocFromZone:(NXZone *)zone
114: {
115: return [super allocFromZone:uniquedStringZone];
116: }
117:
118: + alloc
119: {
120: return [super allocFromZone:uniquedStringZone];
121: }
122:
123: - free
124: {
125: return nil;
126: }
127:
128: - copyFromZone:(NXZone *)zone
129: {
130: return self;
131: }
132:
133: - (BOOL)isEqual:string
134: {
135: static id uniquedStringClass = nil; // Cache to avoid hash lookup...
136: if (!uniquedStringClass) { // No mutex necessary
137: uniquedStringClass = [NXUniquedString class];
138: }
139: if ([string isKindOf:uniquedStringClass]) {
140: return (self == string) ? YES : NO;
141: } else {
142: return [super isEqual:string];
143: }
144: }
145:
146: /*
147: finishUnarchiving not only has to look the string up in the hash table, it also has to make sure the object itself was allocated in the appropriate zone.
148: */
149:
150: - finishUnarchiving
151: {
152: id actual;
153: mutex_lock(&stringLock);
154: if (!(actual = [uniquedStringHashTable valueForKey:self])) {
155: // If not in this zone, reallocate...
156: actual = ([self zone] == uniquedStringZone) ? self : object_copyFromZone (self, 0, uniquedStringZone);
157: [uniquedStringHashTable insertKey:actual value:actual];
158: } else {
159: free (characters); // Already in the hash table, so we free this guy
160: }
161: mutex_unlock(&stringLock);
162: if (actual != self) {
163: object_dispose(self);
164: return actual;
165: } else {
166: return nil;
167: }
168: }
169:
170: @end
171: #endif /* KERNEL */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.