~ubuntu-branches/ubuntu/oneiric/tomcat6/oneiric

« back to all changes in this revision

Viewing changes to java/org/apache/tomcat/util/buf/CharChunk.java

  • Committer: Bazaar Package Importer
  • Author(s): Thierry Carrez
  • Date: 2010-07-20 14:36:48 UTC
  • mfrom: (2.2.17 sid)
  • Revision ID: james.westby@ubuntu.com-20100720143648-23y81x6cq1kv1z00
Tags: 6.0.28-2
* Add debconf questions for user, group and Java options.
* Use ucf to install /etc/default/tomcat6 from a template
* Drop CATALINA_BASE and CATALINA_HOME from /etc/default/tomcat6 since we
  shouldn't encourage users to change those anyway

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
     *  grow the buffer ( up to the limit ) or send it to a channel.
49
49
     */
50
50
    public static interface CharOutputChannel {
51
 
        /** Send the bytes ( usually the internal conversion buffer ).
52
 
         *  Expect 8k output if the buffer is full.
53
 
         */
 
51
        /** Send the bytes ( usually the internal conversion buffer ).
 
52
         *  Expect 8k output if the buffer is full.
 
53
         */
54
54
        public void realWriteChars(char cbuf[], int off, int len)
55
55
            throws IOException;
56
56
    }
64
64
 
65
65
    private boolean isSet=false;  // XXX 
66
66
 
67
 
    private boolean isOutput=false;
68
 
 
69
67
    // -1: grow undefinitely
70
68
    // maximum amount to be cached
71
69
    private int limit=-1;
82
80
    }
83
81
 
84
82
    public CharChunk(int size) {
85
 
        allocate( size, -1 );
 
83
        allocate( size, -1 );
86
84
    }
87
85
 
88
86
    // --------------------
89
87
    
90
88
    public CharChunk getClone() {
91
 
        try {
92
 
            return (CharChunk)this.clone();
93
 
        } catch( Exception ex) {
94
 
            return null;
95
 
        }
 
89
        try {
 
90
            return (CharChunk)this.clone();
 
91
        } catch( Exception ex) {
 
92
            return null;
 
93
        }
96
94
    }
97
95
 
98
96
    public boolean isNull() {
99
 
        if( end > 0 ) return false;
100
 
        return !isSet; //XXX 
 
97
        if( end > 0 ) return false;
 
98
        return !isSet; //XXX 
101
99
    }
102
100
    
103
101
    /**
104
102
     * Resets the message bytes to an uninitialized state.
105
103
     */
106
104
    public void recycle() {
107
 
        //      buff=null;
108
 
        isSet=false; // XXX
109
 
        start=0;
110
 
        end=0;
 
105
        //        buff=null;
 
106
        isSet=false; // XXX
 
107
        start=0;
 
108
        end=0;
111
109
    }
112
110
 
113
111
    public void reset() {
114
 
        buff=null;
 
112
        buff=null;
115
113
    }
116
114
 
117
115
    // -------------------- Setup --------------------
118
116
 
119
117
    public void allocate( int initial, int limit  ) {
120
 
        isOutput=true;
121
 
        if( buff==null || buff.length < initial ) {
122
 
            buff=new char[initial];
123
 
        }
124
 
        this.limit=limit;
125
 
        start=0;
126
 
        end=0;
127
 
        isOutput=true;
128
 
        isSet=true;
 
118
        if( buff==null || buff.length < initial ) {
 
119
            buff=new char[initial];
 
120
        }
 
121
        this.limit=limit;
 
122
        start=0;
 
123
        end=0;
 
124
        isSet=true;
129
125
    }
130
126
 
131
127
 
148
144
     *  or throw exception.
149
145
     */
150
146
    public void setLimit(int limit) {
151
 
        this.limit=limit;
 
147
        this.limit=limit;
152
148
    }
153
149
    
154
150
    public int getLimit() {
155
 
        return limit;
 
151
        return limit;
156
152
    }
157
153
 
158
154
    /**
163
159
    }
164
160
 
165
161
    /** When the buffer is full, write the data to the output channel.
166
 
     *  Also used when large amount of data is appended.
 
162
     *         Also used when large amount of data is appended.
167
163
     *
168
164
     *  If not set, the buffer will grow to the limit.
169
165
     */
170
166
    public void setCharOutputChannel(CharOutputChannel out) {
171
 
        this.out=out;
 
167
        this.out=out;
172
168
    }
173
169
 
174
170
    // compat 
175
171
    public char[] getChars()
176
172
    {
177
 
        return getBuffer();
 
173
        return getBuffer();
178
174
    }
179
175
    
180
176
    public char[] getBuffer()
181
177
    {
182
 
        return buff;
 
178
        return buff;
183
179
    }
184
180
    
185
181
    /**
187
183
     * For output this is the end of the buffer.
188
184
     */
189
185
    public int getStart() {
190
 
        return start;
 
186
        return start;
191
187
    }
192
188
    
193
189
    public int getOffset() {
194
 
        return start;
 
190
        return start;
195
191
    }
196
192
 
197
193
    /**
198
194
     * Returns the start offset of the bytes.
199
195
     */
200
196
    public void setOffset(int off) {
201
 
        start=off;
 
197
        start=off;
202
198
    }
203
199
 
204
200
    /**
205
201
     * Returns the length of the bytes.
206
202
     */
207
203
    public int getLength() {
208
 
        return end-start;
 
204
        return end-start;
209
205
    }
210
206
 
211
207
 
212
208
    public int getEnd() {
213
 
        return end;
 
209
        return end;
214
210
    }
215
211
 
216
212
    public void setEnd( int i ) {
217
 
        end=i;
 
213
        end=i;
218
214
    }
219
215
 
220
216
    // -------------------- Adding data --------------------
221
217
    
222
218
    public void append( char b )
223
 
        throws IOException
 
219
        throws IOException
224
220
    {
225
 
        makeSpace( 1 );
 
221
        makeSpace( 1 );
226
222
 
227
 
        // couldn't make space
228
 
        if( limit >0 && end >= limit ) {
229
 
            flushBuffer();
230
 
        }
231
 
        buff[end++]=b;
 
223
        // couldn't make space
 
224
        if( limit >0 && end >= limit ) {
 
225
            flushBuffer();
 
226
        }
 
227
        buff[end++]=b;
232
228
    }
233
229
    
234
230
    public void append( CharChunk src )
235
 
        throws IOException
 
231
        throws IOException
236
232
    {
237
 
        append( src.getBuffer(), src.getOffset(), src.getLength());
 
233
        append( src.getBuffer(), src.getOffset(), src.getLength());
238
234
    }
239
235
 
240
236
    /** Add data to the buffer
241
237
     */
242
238
    public void append( char src[], int off, int len )
243
 
        throws IOException
 
239
        throws IOException
244
240
    {
245
 
        // will grow, up to limit
246
 
        makeSpace( len );
 
241
        // will grow, up to limit
 
242
        makeSpace( len );
247
243
 
248
 
        // if we don't have limit: makeSpace can grow as it wants
249
 
        if( limit < 0 ) {
250
 
            // assert: makeSpace made enough space
251
 
            System.arraycopy( src, off, buff, end, len );
252
 
            end+=len;
253
 
            return;
254
 
        }
 
244
        // if we don't have limit: makeSpace can grow as it wants
 
245
        if( limit < 0 ) {
 
246
            // assert: makeSpace made enough space
 
247
            System.arraycopy( src, off, buff, end, len );
 
248
            end+=len;
 
249
            return;
 
250
        }
255
251
 
256
252
        // Optimize on a common case.
257
253
        // If the source is going to fill up all the space in buffer, may
260
256
            out.realWriteChars( src, off, len );
261
257
            return;
262
258
        }
263
 
        
264
 
        // if we have limit and we're below
265
 
        if( len <= limit - end ) {
266
 
            // makeSpace will grow the buffer to the limit,
267
 
            // so we have space
268
 
            System.arraycopy( src, off, buff, end, len );
269
 
            
270
 
            end+=len;
271
 
            return;
272
 
        }
273
 
 
274
 
        // need more space than we can afford, need to flush
275
 
        // buffer
276
 
 
277
 
        // the buffer is already at ( or bigger than ) limit
278
 
        
279
 
        // Optimization:
280
 
        // If len-avail < length ( i.e. after we fill the buffer with
281
 
        // what we can, the remaining will fit in the buffer ) we'll just
282
 
        // copy the first part, flush, then copy the second part - 1 write
283
 
        // and still have some space for more. We'll still have 2 writes, but
284
 
        // we write more on the first.
285
 
 
286
 
        if( len + end < 2 * limit ) {
287
 
            /* If the request length exceeds the size of the output buffer,
288
 
               flush the output buffer and then write the data directly.
289
 
               We can't avoid 2 writes, but we can write more on the second
290
 
            */
291
 
            int avail=limit-end;
292
 
            System.arraycopy(src, off, buff, end, avail);
293
 
            end += avail;
294
 
            
295
 
            flushBuffer();
296
 
            
297
 
            System.arraycopy(src, off+avail, buff, end, len - avail);
298
 
            end+= len - avail;
299
 
            
300
 
        } else {        // len > buf.length + avail
301
 
            // long write - flush the buffer and write the rest
302
 
            // directly from source
303
 
            flushBuffer();
304
 
            
305
 
            out.realWriteChars( src, off, len );
306
 
        }
 
259
        
 
260
        // if we have limit and we're below
 
261
        if( len <= limit - end ) {
 
262
            // makeSpace will grow the buffer to the limit,
 
263
            // so we have space
 
264
            System.arraycopy( src, off, buff, end, len );
 
265
            
 
266
            end+=len;
 
267
            return;
 
268
        }
 
269
 
 
270
        // need more space than we can afford, need to flush
 
271
        // buffer
 
272
 
 
273
        // the buffer is already at ( or bigger than ) limit
 
274
        
 
275
        // Optimization:
 
276
        // If len-avail < length ( i.e. after we fill the buffer with
 
277
        // what we can, the remaining will fit in the buffer ) we'll just
 
278
        // copy the first part, flush, then copy the second part - 1 write
 
279
        // and still have some space for more. We'll still have 2 writes, but
 
280
        // we write more on the first.
 
281
 
 
282
        if( len + end < 2 * limit ) {
 
283
            /* If the request length exceeds the size of the output buffer,
 
284
               flush the output buffer and then write the data directly.
 
285
               We can't avoid 2 writes, but we can write more on the second
 
286
            */
 
287
            int avail=limit-end;
 
288
            System.arraycopy(src, off, buff, end, avail);
 
289
            end += avail;
 
290
            
 
291
            flushBuffer();
 
292
            
 
293
            System.arraycopy(src, off+avail, buff, end, len - avail);
 
294
            end+= len - avail;
 
295
            
 
296
        } else {        // len > buf.length + avail
 
297
            // long write - flush the buffer and write the rest
 
298
            // directly from source
 
299
            flushBuffer();
 
300
            
 
301
            out.realWriteChars( src, off, len );
 
302
        }
307
303
    }
308
304
 
309
305
 
310
306
    /** Add data to the buffer
311
307
     */
312
308
    public void append( StringBuffer sb )
313
 
        throws IOException
 
309
        throws IOException
314
310
    {
315
 
        int len=sb.length();
316
 
 
317
 
        // will grow, up to limit
318
 
        makeSpace( len );
319
 
 
320
 
        // if we don't have limit: makeSpace can grow as it wants
321
 
        if( limit < 0 ) {
322
 
            // assert: makeSpace made enough space
323
 
            sb.getChars(0, len, buff, end );
324
 
            end+=len;
325
 
            return;
326
 
        }
327
 
 
328
 
        int off=0;
329
 
        int sbOff = off;
330
 
        int sbEnd = off + len;
331
 
        while (sbOff < sbEnd) {
332
 
            int d = min(limit - end, sbEnd - sbOff);
333
 
            sb.getChars( sbOff, sbOff+d, buff, end);
334
 
            sbOff += d;
335
 
            end += d;
336
 
            if (end >= limit)
337
 
                flushBuffer();
338
 
        }
 
311
        int len=sb.length();
 
312
 
 
313
        // will grow, up to limit
 
314
        makeSpace( len );
 
315
 
 
316
        // if we don't have limit: makeSpace can grow as it wants
 
317
        if( limit < 0 ) {
 
318
            // assert: makeSpace made enough space
 
319
            sb.getChars(0, len, buff, end );
 
320
            end+=len;
 
321
            return;
 
322
        }
 
323
 
 
324
        int off=0;
 
325
        int sbOff = off;
 
326
        int sbEnd = off + len;
 
327
        while (sbOff < sbEnd) {
 
328
            int d = min(limit - end, sbEnd - sbOff);
 
329
            sb.getChars( sbOff, sbOff+d, buff, end);
 
330
            sbOff += d;
 
331
            end += d;
 
332
            if (end >= limit)
 
333
                flushBuffer();
 
334
        }
339
335
    }
340
336
 
341
337
    /** Append a string to the buffer
347
343
    /** Append a string to the buffer
348
344
     */
349
345
    public void append(String s, int off, int len) throws IOException {
350
 
        if (s==null) return;
351
 
        
352
 
        // will grow, up to limit
353
 
        makeSpace( len );
354
 
 
355
 
        // if we don't have limit: makeSpace can grow as it wants
356
 
        if( limit < 0 ) {
357
 
            // assert: makeSpace made enough space
358
 
            s.getChars(off, off+len, buff, end );
359
 
            end+=len;
360
 
            return;
361
 
        }
362
 
 
363
 
        int sOff = off;
364
 
        int sEnd = off + len;
365
 
        while (sOff < sEnd) {
366
 
            int d = min(limit - end, sEnd - sOff);
367
 
            s.getChars( sOff, sOff+d, buff, end);
368
 
            sOff += d;
369
 
            end += d;
370
 
            if (end >= limit)
371
 
                flushBuffer();
372
 
        }
 
346
        if (s==null) return;
 
347
        
 
348
        // will grow, up to limit
 
349
        makeSpace( len );
 
350
 
 
351
        // if we don't have limit: makeSpace can grow as it wants
 
352
        if( limit < 0 ) {
 
353
            // assert: makeSpace made enough space
 
354
            s.getChars(off, off+len, buff, end );
 
355
            end+=len;
 
356
            return;
 
357
        }
 
358
 
 
359
        int sOff = off;
 
360
        int sEnd = off + len;
 
361
        while (sOff < sEnd) {
 
362
            int d = min(limit - end, sEnd - sOff);
 
363
            s.getChars( sOff, sOff+d, buff, end);
 
364
            sOff += d;
 
365
            end += d;
 
366
            if (end >= limit)
 
367
                flushBuffer();
 
368
        }
373
369
    }
374
370
    
375
371
    // -------------------- Removing data from the buffer --------------------
430
426
 
431
427
 
432
428
    public void flushBuffer()
433
 
        throws IOException
 
429
        throws IOException
434
430
    {
435
 
        //assert out!=null
436
 
        if( out==null ) {
437
 
            throw new IOException( "Buffer overflow, no sink " + limit + " " +
438
 
                                   buff.length  );
439
 
        }
440
 
        out.realWriteChars( buff, start, end - start );
441
 
        end=start;
 
431
        //assert out!=null
 
432
        if( out==null ) {
 
433
            throw new IOException( "Buffer overflow, no sink " + limit + " " +
 
434
                                   buff.length  );
 
435
        }
 
436
        out.realWriteChars( buff, start, end - start );
 
437
        end=start;
442
438
    }
443
439
 
444
440
    /** Make space for len chars. If len is small, allocate
445
 
     *  a reserve space too. Never grow bigger than limit.
 
441
     *        a reserve space too. Never grow bigger than limit.
446
442
     */
447
443
    private void makeSpace(int count)
448
444
    {
449
 
        char[] tmp = null;
450
 
 
451
 
        int newSize;
452
 
        int desiredSize=end + count;
453
 
 
454
 
        // Can't grow above the limit
455
 
        if( limit > 0 &&
456
 
            desiredSize > limit) {
457
 
            desiredSize=limit;
458
 
        }
459
 
 
460
 
        if( buff==null ) {
461
 
            if( desiredSize < 256 ) desiredSize=256; // take a minimum
462
 
            buff=new char[desiredSize];
463
 
        }
464
 
 
465
 
        // limit < buf.length ( the buffer is already big )
466
 
        // or we already have space XXX
467
 
        if( desiredSize <= buff.length) {
468
 
            return;
469
 
        }
470
 
        // grow in larger chunks
471
 
        if( desiredSize < 2 * buff.length ) {
472
 
            newSize= buff.length * 2;
473
 
            if( limit >0 &&
474
 
                newSize > limit ) newSize=limit;
475
 
            tmp=new char[newSize];
476
 
        } else {
477
 
            newSize= buff.length * 2 + count ;
478
 
            if( limit > 0 &&
479
 
                newSize > limit ) newSize=limit;
480
 
            tmp=new char[newSize];
481
 
        }
482
 
        
483
 
        System.arraycopy(buff, 0, tmp, 0, end);
484
 
        buff = tmp;
485
 
        tmp = null;
 
445
        char[] tmp = null;
 
446
 
 
447
        int newSize;
 
448
        int desiredSize=end + count;
 
449
 
 
450
        // Can't grow above the limit
 
451
        if( limit > 0 &&
 
452
            desiredSize > limit) {
 
453
            desiredSize=limit;
 
454
        }
 
455
 
 
456
        if( buff==null ) {
 
457
            if( desiredSize < 256 ) desiredSize=256; // take a minimum
 
458
            buff=new char[desiredSize];
 
459
        }
 
460
 
 
461
        // limit < buf.length ( the buffer is already big )
 
462
        // or we already have space XXX
 
463
        if( desiredSize <= buff.length) {
 
464
            return;
 
465
        }
 
466
        // grow in larger chunks
 
467
        if( desiredSize < 2 * buff.length ) {
 
468
            newSize= buff.length * 2;
 
469
            if( limit >0 &&
 
470
                newSize > limit ) newSize=limit;
 
471
            tmp=new char[newSize];
 
472
        } else {
 
473
            newSize= buff.length * 2 + count ;
 
474
            if( limit > 0 &&
 
475
                newSize > limit ) newSize=limit;
 
476
            tmp=new char[newSize];
 
477
        }
 
478
        
 
479
        System.arraycopy(buff, 0, tmp, 0, end);
 
480
        buff = tmp;
 
481
        tmp = null;
486
482
    }
487
483
    
488
484
    // -------------------- Conversion and getters --------------------
502
498
 
503
499
    public int getInt()
504
500
    {
505
 
        return Ascii.parseInt(buff, start,
506
 
                                end-start);
 
501
        return Ascii.parseInt(buff, start,
 
502
                                end-start);
507
503
    }
508
504
    
509
505
    // -------------------- equals --------------------
514
510
     * @return true if the comparison succeeded, false otherwise
515
511
     */
516
512
    public boolean equals(String s) {
517
 
        char[] c = buff;
518
 
        int len = end-start;
519
 
        if (c == null || len != s.length()) {
520
 
            return false;
521
 
        }
522
 
        int off = start;
523
 
        for (int i = 0; i < len; i++) {
524
 
            if (c[off++] != s.charAt(i)) {
525
 
                return false;
526
 
            }
527
 
        }
528
 
        return true;
 
513
        char[] c = buff;
 
514
        int len = end-start;
 
515
        if (c == null || len != s.length()) {
 
516
            return false;
 
517
        }
 
518
        int off = start;
 
519
        for (int i = 0; i < len; i++) {
 
520
            if (c[off++] != s.charAt(i)) {
 
521
                return false;
 
522
            }
 
523
        }
 
524
        return true;
529
525
    }
530
526
 
531
527
    /**
534
530
     * @return true if the comparison succeeded, false otherwise
535
531
     */
536
532
    public boolean equalsIgnoreCase(String s) {
537
 
        char[] c = buff;
538
 
        int len = end-start;
539
 
        if (c == null || len != s.length()) {
540
 
            return false;
541
 
        }
542
 
        int off = start;
543
 
        for (int i = 0; i < len; i++) {
544
 
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
545
 
                return false;
546
 
            }
547
 
        }
548
 
        return true;
 
533
        char[] c = buff;
 
534
        int len = end-start;
 
535
        if (c == null || len != s.length()) {
 
536
            return false;
 
537
        }
 
538
        int off = start;
 
539
        for (int i = 0; i < len; i++) {
 
540
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
 
541
                return false;
 
542
            }
 
543
        }
 
544
        return true;
549
545
    }
550
546
 
551
547
    public boolean equals(CharChunk cc) {
552
 
        return equals( cc.getChars(), cc.getOffset(), cc.getLength());
 
548
        return equals( cc.getChars(), cc.getOffset(), cc.getLength());
553
549
    }
554
550
 
555
551
    public boolean equals(char b2[], int off2, int len2) {
556
 
        char b1[]=buff;
557
 
        if( b1==null && b2==null ) return true;
558
 
        
559
 
        if (b1== null || b2==null || end-start != len2) {
560
 
            return false;
561
 
        }
562
 
        int off1 = start;
563
 
        int len=end-start;
564
 
        while ( len-- > 0) {
565
 
            if (b1[off1++] != b2[off2++]) {
566
 
                return false;
567
 
            }
568
 
        }
569
 
        return true;
 
552
        char b1[]=buff;
 
553
        if( b1==null && b2==null ) return true;
 
554
        
 
555
        if (b1== null || b2==null || end-start != len2) {
 
556
            return false;
 
557
        }
 
558
        int off1 = start;
 
559
        int len=end-start;
 
560
        while ( len-- > 0) {
 
561
            if (b1[off1++] != b2[off2++]) {
 
562
                return false;
 
563
            }
 
564
        }
 
565
        return true;
570
566
    }
571
567
 
572
568
    public boolean equals(byte b2[], int off2, int len2) {
573
 
        char b1[]=buff;
574
 
        if( b2==null && b1==null ) return true;
 
569
        char b1[]=buff;
 
570
        if( b2==null && b1==null ) return true;
575
571
 
576
 
        if (b1== null || b2==null || end-start != len2) {
577
 
            return false;
578
 
        }
579
 
        int off1 = start;
580
 
        int len=end-start;
581
 
        
582
 
        while ( len-- > 0) {
583
 
            if ( b1[off1++] != (char)b2[off2++]) {
584
 
                return false;
585
 
            }
586
 
        }
587
 
        return true;
 
572
        if (b1== null || b2==null || end-start != len2) {
 
573
            return false;
 
574
        }
 
575
        int off1 = start;
 
576
        int len=end-start;
 
577
        
 
578
        while ( len-- > 0) {
 
579
            if ( b1[off1++] != (char)b2[off2++]) {
 
580
                return false;
 
581
            }
 
582
        }
 
583
        return true;
588
584
    }
589
585
    
590
586
    /**
592
588
     * @param s the string
593
589
     */
594
590
    public boolean startsWith(String s) {
595
 
        char[] c = buff;
596
 
        int len = s.length();
597
 
        if (c == null || len > end-start) {
598
 
            return false;
599
 
        }
600
 
        int off = start;
601
 
        for (int i = 0; i < len; i++) {
602
 
            if (c[off++] != s.charAt(i)) {
603
 
                return false;
604
 
            }
605
 
        }
606
 
        return true;
 
591
        char[] c = buff;
 
592
        int len = s.length();
 
593
        if (c == null || len > end-start) {
 
594
            return false;
 
595
        }
 
596
        int off = start;
 
597
        for (int i = 0; i < len; i++) {
 
598
            if (c[off++] != s.charAt(i)) {
 
599
                return false;
 
600
            }
 
601
        }
 
602
        return true;
607
603
    }
608
604
    
609
605
    /**
611
607
     * @param s the string
612
608
     */
613
609
    public boolean startsWithIgnoreCase(String s, int pos) {
614
 
        char[] c = buff;
615
 
        int len = s.length();
616
 
        if (c == null || len+pos > end-start) {
617
 
            return false;
618
 
        }
619
 
        int off = start+pos;
620
 
        for (int i = 0; i < len; i++) {
621
 
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
622
 
                return false;
623
 
            }
624
 
        }
625
 
        return true;
 
610
        char[] c = buff;
 
611
        int len = s.length();
 
612
        if (c == null || len+pos > end-start) {
 
613
            return false;
 
614
        }
 
615
        int off = start+pos;
 
616
        for (int i = 0; i < len; i++) {
 
617
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
 
618
                return false;
 
619
            }
 
620
        }
 
621
        return true;
626
622
    }
627
623
    
628
624
 
630
626
 
631
627
    // normal hash. 
632
628
    public int hash() {
633
 
        int code=0;
634
 
        for (int i = start; i < start + end-start; i++) {
635
 
            code = code * 37 + buff[i];
636
 
        }
637
 
        return code;
 
629
        int code=0;
 
630
        for (int i = start; i < start + end-start; i++) {
 
631
            code = code * 37 + buff[i];
 
632
        }
 
633
        return code;
638
634
    }
639
635
 
640
636
    // hash ignoring case
641
637
    public int hashIgnoreCase() {
642
 
        int code=0;
643
 
        for (int i = start; i < end; i++) {
644
 
            code = code * 37 + Ascii.toLower(buff[i]);
645
 
        }
646
 
        return code;
 
638
        int code=0;
 
639
        for (int i = start; i < end; i++) {
 
640
            code = code * 37 + Ascii.toLower(buff[i]);
 
641
        }
 
642
        return code;
647
643
    }
648
644
 
649
645
    public int indexOf(char c) {
650
 
        return indexOf( c, start);
 
646
        return indexOf( c, start);
651
647
    }
652
648
    
653
649
    /**
655
651
     * @param c the character
656
652
     */
657
653
    public int indexOf(char c, int starting) {
658
 
        int ret = indexOf( buff, start+starting, end, c );
659
 
        return (ret >= start) ? ret - start : -1;
 
654
        int ret = indexOf( buff, start+starting, end, c );
 
655
        return (ret >= start) ? ret - start : -1;
660
656
    }
661
657
 
662
658
    public static int indexOf( char chars[], int off, int cend, char qq )
663
659
    {
664
 
        while( off < cend ) {
665
 
            char b=chars[off];
666
 
            if( b==qq )
667
 
                return off;
668
 
            off++;
669
 
        }
670
 
        return -1;
 
660
        while( off < cend ) {
 
661
            char b=chars[off];
 
662
            if( b==qq )
 
663
                return off;
 
664
            off++;
 
665
        }
 
666
        return -1;
671
667
    }
672
668
    
673
669
 
674
670
    public int indexOf( String src, int srcOff, int srcLen, int myOff ) {
675
 
        char first=src.charAt( srcOff );
 
671
        char first=src.charAt( srcOff );
676
672
 
677
 
        // Look for first char 
678
 
        int srcEnd = srcOff + srcLen;
 
673
        // Look for first char 
 
674
        int srcEnd = srcOff + srcLen;
679
675
        
680
 
        for( int i=myOff+start; i <= (end - srcLen); i++ ) {
681
 
            if( buff[i] != first ) continue;
682
 
            // found first char, now look for a match
 
676
        for( int i=myOff+start; i <= (end - srcLen); i++ ) {
 
677
            if( buff[i] != first ) continue;
 
678
            // found first char, now look for a match
683
679
            int myPos=i+1;
684
 
            for( int srcPos=srcOff + 1; srcPos< srcEnd; ) {
 
680
            for( int srcPos=srcOff + 1; srcPos< srcEnd; ) {
685
681
                if( buff[myPos++] != src.charAt( srcPos++ ))
686
 
                    break;
 
682
                    break;
687
683
                if( srcPos==srcEnd ) return i-start; // found it
688
 
            }
689
 
        }
690
 
        return -1;
 
684
            }
 
685
        }
 
686
        return -1;
691
687
    }
692
688
 
693
689
    // -------------------- utils
694
690
    private int min(int a, int b) {
695
 
        if (a < b) return a;
696
 
        return b;
 
691
        if (a < b) return a;
 
692
        return b;
697
693
    }
698
694
 
699
695
    // Char sequence impl