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