001    package railo.runtime.type;
002    
003    import java.io.Serializable;
004    import java.util.ArrayList;
005    
006    import railo.commons.lang.SizeOf;
007    import railo.runtime.exp.ExpressionException;
008    
009    
010    
011    /**
012     * cold fusion array object
013     */
014    public final class ArrayInt implements Sizeable,Serializable {
015            
016            private static final int NULL = 0;
017            private int[] arr;
018            private final int cap=32;
019            private int size=0;
020            private int offset=0;
021            private int offCount=0;
022            
023            /**
024             * constructor with default dimesnion (1)
025             */
026            public ArrayInt() {
027                    arr=new int[offset+cap];
028            }
029            
030            /**
031             * constructor with to data to fill
032             * @param objects Objects array data to fill
033             */
034            public ArrayInt(int[] objects) {
035                    arr=objects;
036                    size=arr.length;
037                    offset=0;
038            }
039            
040            public int get(int key, int defaultValue) {
041                    if(key>size || key<1) {
042                            return defaultValue;
043                    }
044                    int o=arr[(offset+key)-1];
045                    if(o==NULL) return defaultValue;
046                    return o;
047            }
048            
049            public int get(int key) throws ExpressionException {
050                    if(key<1 || key>size) {
051                            throw invalidPosition(key);
052                    }
053                    
054                    int o=arr[(offset+key)-1];
055                    
056                    if(o==NULL) {
057                            throw invalidPosition(key);
058                    }
059                    return o;
060            }
061            
062            /**
063             * Exception method if key doesn't exist at given position
064             * @param pos
065             * @return exception
066             */
067            private ExpressionException invalidPosition(int pos) {
068                    return new ExpressionException("Element at position ["+pos+"] doesn't exist in array");
069            }
070            
071            public int set(int key, int value) {
072                    if(offset+key>arr.length)enlargeCapacity(key);
073                    if(key>size)size=key;
074                    return arr[(offset+key)-1]=value;
075            }       
076            
077            /**
078         * !!! all methods that use this method must be sync
079             * enlarge the inner array to given size
080             * @param key min size of the array
081             */
082            private synchronized void enlargeCapacity(int key) {
083                    int diff=offCount-offset;
084                    
085                    int newSize=arr.length;
086                    if(newSize<1) newSize=1;
087                    while(newSize<key+offset+diff) {
088                            newSize*=2;
089                    }
090                    if(newSize>arr.length) {
091                            int[] na=new int[newSize];
092                            for(int i=offset;i<offset+size;i++) {
093                                    na[i+diff]=arr[i];
094                            }
095                            arr=na;
096                            offset+=diff;
097                    }
098            }
099            
100            /* *
101             * !!! all methods that use this method must be sync
102         * enlarge the offset if 0
103             * /
104            private void enlargeOffset() {
105                    if(offset==0) {
106                            offCount=offCount==0?1:offCount*2;
107                            offset=offCount;
108                            int[] narr=new int[arr.length+offset];
109                            for(int i=0;i<size;i++) {
110                                    narr[offset+i]=arr[i];
111                            }
112                            arr=narr;
113                    }
114            }*/
115            
116            public int size() {
117                    return size;
118            }
119            
120            public int[] keys() {
121                    ArrayList lst=new ArrayList();          
122                    int count=0;
123                    for(int i=offset;i<offset+size;i++) {
124                            int o=arr[i];
125                            count++;
126                            if(o!=NULL) lst.add(Integer.valueOf(count));
127                    }
128    
129                    int[] ints=new int[lst.size()];
130                    
131                    for(int i=0;i<ints.length;i++){
132                            ints[i]=((Integer)lst.get(i)).intValue();
133                    }
134                    return ints;
135            }
136            
137            public int remove(int key) throws ExpressionException {
138                    if(key>size || key<1) throw invalidPosition(key);
139                    int obj=get(key,NULL);
140                    for(int i=(offset+key)-1;i<(offset+size)-1;i++) {
141                            arr[i]=arr[i+1];
142                    }
143                    size--;
144                    return obj;
145            }
146            
147            public int removeEL(int key) {
148                if(key>size || key<1) return NULL;
149                    int obj=get(key,NULL);
150                
151                    for(int i=(offset+key)-1;i<(offset+size)-1;i++) {
152                            arr[i]=arr[i+1];
153                    }
154                    size--;
155                    return obj;
156            }
157            
158            public void clear() {
159                if(size()>0) {
160                            arr=new int[cap];
161                            size=0;
162                            offCount=1;
163                            offset=0;
164                }
165            }
166            
167        public int add(int o) {
168            if(offset+size+1>arr.length)enlargeCapacity(size+1);
169            arr[offset+size]=o;
170            size++;
171            return o;
172        }
173            
174            public int[] toArray() {
175                    int[] rtn=new int[size];
176                    int count=0;
177                    for(int i=offset;i<offset+size;i++) {
178                            rtn[count++]=arr[i];
179                    }
180                    return rtn;
181            }
182    
183        public boolean contains(int key) {
184            return get(key,NULL)!=NULL;
185        }
186    
187            /**
188             * @see railo.runtime.engine.Sizeable#sizeOf()
189             */
190            public long sizeOf() {
191                    return SizeOf.size(arr)
192                    +SizeOf.size(cap)
193                    +SizeOf.size(size)
194                    +SizeOf.size(offset)
195                    +SizeOf.size(offCount)
196                    +SizeOf.REF_SIZE;
197            }
198    
199    }