2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
6 SOPE 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 SOPE 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 SOPE; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 #include "WOElementID.h"
25 // TODO: do not keep the array in the ivars, but use malloc
27 //#define PROF_ELEMID 1
29 @implementation WOElementID
31 - (id)initWithString:(NSString *)_rid {
35 reid = [_rid componentsSeparatedByString:@"."];
36 if ((self->elementIdCount = [reid count]) == 0) {
40 if (self->elementIdCount > NGObjWeb_MAX_ELEMENT_ID_COUNT) {
41 [self errorWithFormat:@"request element ID is too long (%i parts)",
42 self->elementIdCount];
46 for (i = 0; i < self->elementIdCount; i++)
47 self->elementId[i].string = [[reid objectAtIndex:i] copy];
55 for (i = 0; i < self->elementIdCount; i++) {
56 [self->elementId[i].string release];
57 [self->elementId[i].fqn release];
65 static int prioCacheHit = 0;
66 static int prioStrCacheHit = 0;
67 static int prioConstruct = 0;
68 static int callCount = 0;
71 - (NSString *)elementID {
73 TODO: increase performance (~24% of -componentActionURL [was 50%])
74 Prof: 1.9% -appendString
75 18% -stringByAppendingString
78 static NSString *nums[30] = {
79 @".0", @".1", @".2", @".3", @".4", @".5", @".6", @".7", @".8", @".9",
80 @".10", @".11", @".12", @".13", @".14",
81 @".15", @".16", @".17", @".18", @".19",
82 @".20", @".21", @".22", @".23", @".24",
83 @".25", @".26", @".27", @".28", @".29",
88 if (callCount % 10 == 0) {
89 printf("ElementIDProfing: #calls=%i "
90 "#priohits=%i(string=%i), #prioconstructs=%i\n",
91 callCount, prioCacheHit, prioStrCacheHit, prioConstruct);
96 if (self->elementIdCount == 0) {
99 else if (self->elementIdCount == 1) {
100 /* a single part in element id (the ctx-id) ... (rare case ...) */
101 if ((e = self->elementId[0].string))
104 return [NSString stringWithFormat:@"%d", self->elementId[0].number];
106 else if ((e = self->elementId[(self->elementIdCount - 2)].fqn)) {
107 /* the prior part has a cached fqn */
108 /* TODO cache prior string as C-string ! */
114 if ((o = self->elementId[self->elementIdCount - 1].string)) {
115 NSMutableString *eid;
119 eid = [e mutableCopy];
120 [eid appendString:@"."];
121 [eid appendString:o];
122 return [eid autorelease];
125 i = self->elementId[self->elementIdCount - 1].number;
126 if (i >= 0 && i < 30)
127 return [e stringByAppendingString:nums[i]];
128 return [e stringByAppendingFormat:@".%i", i];
131 if (self->cs == nil) {
132 self->cs = [[NSMutableString alloc] initWithCapacity:64];
133 self->addStr = [self->cs methodForSelector:@selector(appendString:)];
136 [self->cs setString:@""];
138 for (i = 0; i < self->elementIdCount; i++) {
141 if (i == (self->elementIdCount - 1)) {
142 /* the last iteration, cache the fqn of the *prior* element ! */
143 self->elementId[i - 1].fqn = [self->cs copy];
149 if ((o = self->elementId[i].string)) {
150 /* some identity comparison for faster NSNumber->NSString conversion */
151 if (i != 0) addStr(self->cs, @selector(appendString:), @".");
152 addStr(self->cs, @selector(appendString:), o);
157 n = self->elementId[i].number;
158 if (n >= 0 && n < 30) {
160 addStr(self->cs, @selector(appendString:), nums[n]);
162 /* very rare, the first id is almost always a string (ctx-id!) */
163 [self->cs appendFormat:@"%i", n];
166 [self->cs appendFormat:(i != 0 ? @".%i" : @"%i"), n];
170 return [[self->cs copy] autorelease];
173 - (void)appendElementIDComponent:(NSString *)_eid {
174 self->elementId[(int)self->elementIdCount].string = [_eid copy];
175 self->elementIdCount++;
176 NSAssert(self->elementIdCount < NGObjWeb_MAX_ELEMENT_ID_COUNT,
177 @"element id size exceeded !");
179 - (void)appendIntElementIDComponent:(int)_eid {
180 self->elementId[(int)self->elementIdCount].number = _eid;
181 self->elementIdCount++;
182 NSAssert(self->elementIdCount < NGObjWeb_MAX_ELEMENT_ID_COUNT,
183 @"element id size exceeded !");
186 - (void)appendZeroElementIDComponent {
187 self->elementId[(int)self->elementIdCount].number = 0;
188 self->elementIdCount++;
189 NSAssert(self->elementIdCount < NGObjWeb_MAX_ELEMENT_ID_COUNT,
190 @"element id size exceeded !");
193 - (void)deleteAllElementIDComponents {
195 for (i = 0; i < self->elementIdCount; i++) {
196 [self->elementId[i].string release];
197 self->elementId[i].string = nil;
198 [self->elementId[i].fqn release];
199 self->elementId[i].fqn = nil;
201 self->elementIdCount = 0;
204 - (void)deleteLastElementIDComponent {
205 if (self->elementIdCount == 0)
208 self->elementIdCount--;
209 [self->elementId[(int)self->elementIdCount].string release];
210 self->elementId[(int)(self->elementIdCount)].string = nil;
211 [self->elementId[(int)self->elementIdCount].fqn release];
212 self->elementId[(int)(self->elementIdCount)].fqn = nil;
215 - (void)incrementLastElementIDComponent {
216 register WOElementIDPart *p;
219 if (self->elementIdCount < 1) {
220 [self warnWithFormat:@"tried to increment a non-existing element-id"];
223 else if (self->elementIdCount >= NGObjWeb_MAX_ELEMENT_ID_COUNT) {
224 [self errorWithFormat:@"exceeded element-id restriction (max=%i)",
225 NGObjWeb_MAX_ELEMENT_ID_COUNT];
229 // TODO: range check ?
230 p = &(self->elementId[(int)(self->elementIdCount - 1)]);
232 [p->fqn release]; p->fqn = nil;
233 if ((v = p->string)) {
234 p->number = [v intValue] + 1;
235 [p->string release]; p->string = nil;
241 /* request ID processing */
243 - (id)currentElementID {
244 return (self->idPos >= self->elementIdCount)
246 : (id)self->elementId[(int)self->idPos].string;
248 - (id)consumeElementID {
250 return [self currentElementID];
253 @end /* WOElementID */