001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: IntegerArray.java 1225434 2011-12-29 05:07:42Z mrglavas $
020     */
021    
022    package org.apache.xalan.xsltc.util;
023    
024    /**
025     * @author Jacek Ambroziak
026     */
027    public final class IntegerArray implements Cloneable {
028        private static final int InitialSize = 32;
029        
030        private int[] _array;
031        private int   _size;
032        private int   _free = 0;
033      
034        public IntegerArray() {
035            this(InitialSize);
036        }
037      
038        public IntegerArray(int size) {
039            _array = new int[_size = size];
040        }
041    
042        public IntegerArray(int[] array) {
043            this(array.length);
044            System.arraycopy(array, 0, _array, 0, _free = _size);
045        }
046    
047        public void clear() {
048            _free = 0;
049        }
050    
051        public Object clone() {
052            final IntegerArray clone = new IntegerArray(_free > 0 ? _free : 1);
053            System.arraycopy(_array, 0, clone._array, 0, _free);
054            clone._free = _free;
055            return clone;
056        }
057    
058        public int[] toIntArray() {
059            final int[] result = new int[cardinality()];
060            System.arraycopy(_array, 0, result, 0, cardinality());
061            return result;
062        }
063    
064        public final int at(int index) {
065            return _array[index];
066        }
067    
068        public final void set(int index, int value) {
069            _array[index] = value;
070        }
071    
072        public int indexOf(int n) {
073            for (int i = 0; i < _free; i++) {
074                if (n == _array[i]) return i;
075            }
076            return -1;
077        }
078    
079        public final void add(int value) {
080            if (_free == _size) {
081                growArray(_size * 2);
082            }
083            _array[_free++] = value;
084        }
085      
086        /** 
087         * Adds new int at the end if not already present.
088         */
089        public void addNew(int value) {
090            for (int i = 0; i < _free; i++) {
091                if (_array[i] == value) return;  // already in array
092            }
093            add(value);
094        }
095    
096        public void reverse() {
097            int left = 0; 
098            int right = _free - 1;
099    
100            while (left < right) {
101                int temp = _array[left];
102                _array[left++] = _array[right];
103                _array[right--] = temp;
104            }
105        }
106    
107        /**
108         * Merge two sorted arrays and eliminate duplicates.
109         * Elements of the other IntegerArray must not be changed. 
110         */
111        public void merge(final IntegerArray other) {
112            final int newSize = _free + other._free;
113    // System.out.println("IntegerArray.merge() begin newSize = " + newSize);
114            int[] newArray = new int[newSize];
115    
116            // Merge the two arrays
117            int i = 0, j = 0, k;
118            for (k = 0; i < _free && j < other._free; k++) {
119                int x = _array[i];
120                int y = other._array[j];
121    
122                if (x < y) {
123                    newArray[k] = x;
124                    i++;
125                }
126                else if (x > y) {
127                    newArray[k] = y;
128                    j++;
129                }
130                else {
131                    newArray[k] = x;
132                    i++; j++;
133                }
134            }
135    
136            // Copy the rest if of different lengths
137            if (i >= _free) {
138                while (j < other._free) {
139                    newArray[k++] = other._array[j++];
140                }
141            }
142            else {
143                while (i < _free) {
144                    newArray[k++] = _array[i++];
145                }
146            }
147    
148            // Update reference to this array
149            _array = newArray;
150            _free = _size = newSize;
151    // System.out.println("IntegerArray.merge() end");
152        }
153    
154        public void sort() {
155            quicksort(_array, 0, _free - 1);
156        }
157    
158        private static void quicksort(int[] array, int p, int r) {
159            if (p < r) {
160                final int q = partition(array, p, r);
161                quicksort(array, p, q);
162                quicksort(array, q + 1, r);
163            }
164        }
165        
166        private static int partition(int[] array, int p, int r) {
167            final int x = array[(p + r) >>> 1];
168            int i = p - 1; int j = r + 1;
169    
170            while (true) {
171                while (x < array[--j]);
172                while (x > array[++i]);
173                if (i < j) {
174                    int temp = array[i];
175                    array[i] = array[j];
176                    array[j] = temp;
177                }
178                else {
179                    return j;
180                }
181            }
182        }
183    
184        private void growArray(int size) {
185            final int[] newArray = new int[_size = size];
186            System.arraycopy(_array, 0, newArray, 0, _free);
187            _array = newArray;
188        }
189    
190        public int popLast() {
191            return _array[--_free];
192        }
193    
194        public int last() {
195            return _array[_free - 1];
196        }
197    
198        public void setLast(int n) {
199            _array[_free - 1] = n;
200        }
201    
202        public void pop() {
203            _free--;
204        }
205    
206        public void pop(int n) {
207            _free -= n;
208        }
209      
210        public final int cardinality() {
211            return _free;
212        }
213    
214        public void print(java.io.PrintStream out) {
215            if (_free > 0) {
216                for (int i = 0; i < _free - 1; i++) {
217                    out.print(_array[i]);
218                    out.print(' ');
219                }
220                out.println(_array[_free - 1]);
221            }
222            else {
223                out.println("IntegerArray: empty");
224            }
225        }
226    }