2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
6 OGo is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 #include "WOElementID.h"
26 // TODO: do not keep the array in the ivars, but use malloc
28 //#define PROF_ELEMID 1
30 @implementation WOElementID
32 - (id)initWithString:(NSString *)_rid {
36 reid = [_rid componentsSeparatedByString:@"."];
37 if ((self->elementIdCount = [reid count]) == 0) {
41 if (self->elementIdCount > NGObjWeb_MAX_ELEMENT_ID_COUNT) {
42 [self logWithFormat:@"ERROR: request element ID is too long (%i parts)",
43 self->elementIdCount];
47 for (i = 0; i < self->elementIdCount; i++)
48 self->elementId[i].string = [[reid objectAtIndex:i] copy];
56 for (i = 0; i < self->elementIdCount; i++) {
57 [self->elementId[i].string release];
58 [self->elementId[i].fqn release];
66 static int prioCacheHit = 0;
67 static int prioStrCacheHit = 0;
68 static int prioConstruct = 0;
69 static int callCount = 0;
72 - (NSString *)elementID {
74 TODO: increase performance (~24% of -componentActionURL [was 50%])
75 Prof: 1.9% -appendString
76 18% -stringByAppendingString
79 static NSString *nums[30] = {
80 @".0", @".1", @".2", @".3", @".4", @".5", @".6", @".7", @".8", @".9",
81 @".10", @".11", @".12", @".13", @".14",
82 @".15", @".16", @".17", @".18", @".19",
83 @".20", @".21", @".22", @".23", @".24",
84 @".25", @".26", @".27", @".28", @".29",
89 if (callCount % 10 == 0) {
90 printf("ElementIDProfing: #calls=%i "
91 "#priohits=%i(string=%i), #prioconstructs=%i\n",
92 callCount, prioCacheHit, prioStrCacheHit, prioConstruct);
97 if (self->elementIdCount == 0) {
100 else if (self->elementIdCount == 1) {
101 /* a single part in element id (the ctx-id) ... (rare case ...) */
102 if ((e = self->elementId[0].string))
105 return [NSString stringWithFormat:@"%d", self->elementId[0].number];
107 else if ((e = self->elementId[(self->elementIdCount - 2)].fqn)) {
108 /* the prior part has a cached fqn */
109 /* TODO cache prior string as C-string ! */
115 if ((o = self->elementId[self->elementIdCount - 1].string)) {
116 NSMutableString *eid;
120 eid = [e mutableCopy];
121 [eid appendString:@"."];
122 [eid appendString:o];
123 return [eid autorelease];
126 i = self->elementId[self->elementIdCount - 1].number;
127 if (i >= 0 && i < 30)
128 return [e stringByAppendingString:nums[i]];
129 return [e stringByAppendingFormat:@".%i", i];
132 if (self->cs == nil) {
133 self->cs = [[NSMutableString alloc] initWithCapacity:64];
134 self->addStr = [self->cs methodForSelector:@selector(appendString:)];
137 [self->cs setString:@""];
139 for (i = 0; i < self->elementIdCount; i++) {
142 if (i == (self->elementIdCount - 1)) {
143 /* the last iteration, cache the fqn of the *prior* element ! */
144 self->elementId[i - 1].fqn = [self->cs copy];
150 if ((o = self->elementId[i].string)) {
151 /* some identity comparison for faster NSNumber->NSString conversion */
152 if (i != 0) addStr(self->cs, @selector(appendString:), @".");
153 addStr(self->cs, @selector(appendString:), o);
158 n = self->elementId[i].number;
159 if (n >= 0 && n < 30) {
161 addStr(self->cs, @selector(appendString:), nums[n]);
163 /* very rare, the first id is almost always a string (ctx-id!) */
164 [self->cs appendFormat:@"%i", n];
167 [self->cs appendFormat:(i != 0 ? @".%i" : @"%i"), n];
171 return [[self->cs copy] autorelease];
174 - (void)appendElementIDComponent:(NSString *)_eid {
175 self->elementId[(int)self->elementIdCount].string = [_eid copy];
176 self->elementIdCount++;
177 NSAssert(self->elementIdCount < NGObjWeb_MAX_ELEMENT_ID_COUNT,
178 @"element id size exceeded !");
180 - (void)appendIntElementIDComponent:(int)_eid {
181 self->elementId[(int)self->elementIdCount].number = _eid;
182 self->elementIdCount++;
183 NSAssert(self->elementIdCount < NGObjWeb_MAX_ELEMENT_ID_COUNT,
184 @"element id size exceeded !");
187 - (void)appendZeroElementIDComponent {
188 self->elementId[(int)self->elementIdCount].number = 0;
189 self->elementIdCount++;
190 NSAssert(self->elementIdCount < NGObjWeb_MAX_ELEMENT_ID_COUNT,
191 @"element id size exceeded !");
194 - (void)deleteAllElementIDComponents {
196 for (i = 0; i < self->elementIdCount; i++) {
197 [self->elementId[i].string release];
198 self->elementId[i].string = nil;
199 [self->elementId[i].fqn release];
200 self->elementId[i].fqn = nil;
202 self->elementIdCount = 0;
205 - (void)deleteLastElementIDComponent {
206 if (self->elementIdCount == 0)
209 self->elementIdCount--;
210 [self->elementId[(int)self->elementIdCount].string release];
211 self->elementId[(int)(self->elementIdCount)].string = nil;
212 [self->elementId[(int)self->elementIdCount].fqn release];
213 self->elementId[(int)(self->elementIdCount)].fqn = nil;
216 - (void)incrementLastElementIDComponent {
217 register WOElementIDPart *p;
220 if (self->elementIdCount < 1) {
222 @"WARNING: tried to increment a non-existing element-id"];
225 else if (self->elementIdCount >= NGObjWeb_MAX_ELEMENT_ID_COUNT) {
227 @"ERROR: exceeded element-id restriction (max=%i)",
228 NGObjWeb_MAX_ELEMENT_ID_COUNT];
232 // TODO: range check ?
233 p = &(self->elementId[(int)(self->elementIdCount - 1)]);
235 [p->fqn release]; p->fqn = nil;
236 if ((v = p->string)) {
237 p->number = [v intValue] + 1;
238 [p->string release]; p->string = nil;
244 /* request ID processing */
246 - (id)currentElementID {
247 return (self->idPos >= self->elementIdCount)
249 : self->elementId[(int)self->idPos].string;
251 - (id)consumeElementID {
253 return [self currentElementID];
256 @end /* WOElementID */