001/*
002 * BridJ - Dynamic and blazing-fast native interop for Java.
003 * http://bridj.googlecode.com/
004 *
005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/)
006 * All rights reserved.
007 *
008 * Redistribution and use in source and binary forms, with or without
009 * modification, are permitted provided that the following conditions are met:
010 * 
011 *     * Redistributions of source code must retain the above copyright
012 *       notice, this list of conditions and the following disclaimer.
013 *     * Redistributions in binary form must reproduce the above copyright
014 *       notice, this list of conditions and the following disclaimer in the
015 *       documentation and/or other materials provided with the distribution.
016 *     * Neither the name of Olivier Chafik nor the
017 *       names of its contributors may be used to endorse or promote products
018 *       derived from this software without specific prior written permission.
019 * 
020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY
021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030 */
031package org.bridj.cpp.std;
032
033import org.bridj.ann.Template;
034import org.bridj.cpp.CPPObject;
035
036
037import org.bridj.BridJ;
038import org.bridj.Pointer;
039import org.bridj.ann.Field;
040import org.bridj.ann.Struct;
041import org.bridj.cpp.CPPRuntime;
042
043import java.lang.reflect.Type;
044import java.util.NoSuchElementException;
045import org.bridj.BridJRuntime;
046
047import static org.bridj.Pointer.*;
048
049/**
050 * Binding for <a href="http://www.sgi.com/tech/stl/Vector.html">STL's
051 * std::vector</a> class.
052 *
053 * @author ochafik
054 * @param <T>
055 */
056@Template({Type.class})
057@Struct(customizer = STL.class)
058public class vector<T> extends CPPObject {
059
060    @Deprecated
061    @Field(0)
062    public Pointer<T> _M_start() {
063        return io.getPointerField(this, 0);
064    }
065
066    @Deprecated
067    @Field(1)
068    public Pointer<T> _M_finish() {
069        return io.getPointerField(this, 1);
070    }
071
072    @Deprecated
073    @Field(2)
074    public Pointer<T> _M_end_of_storage() {
075        return io.getPointerField(this, 2);
076    }
077    //@Constructor(-1)
078
079    public vector(Type t) {
080        super((Void) null, CPPRuntime.SKIP_CONSTRUCTOR, t);
081    }
082
083    public vector(Pointer<? extends vector<T>> peer, Type t) {
084        super(peer, t);
085        if (!isValid()) {
086            throw new RuntimeException("Invalid vector internal data ! Are you trying to use an unsupported version of the STL ?");
087        }
088    }
089
090    protected boolean isValid() {
091        long start = getPeer(_M_start());
092        long finish = getPeer(_M_finish());
093        long eos = getPeer(_M_end_of_storage());
094        if (start == 0 || finish == 0 || eos == 0) {
095            return false;
096        }
097        return start <= finish && finish <= eos;
098    }
099
100    private void checkNotEmpty() {
101        checkIndex(0);
102    }
103
104    private void checkIndex(long i) {
105        long size = size();
106        if (i < 0 || i >= size) {
107            throw new NoSuchElementException("index " + i + " (size = " + size + ")");
108        }
109    }
110
111    public boolean empty() {
112        return size() == 0;
113    }
114
115    public T get(long index) {
116        // TODO make this unnecessary
117        checkIndex(index);
118        Pointer<T> p = _M_start().as(T());
119        return p.get(index);
120    }
121
122    public T get(int index) {
123        return get((long) index);
124    }
125
126    public T front() {
127        return get(0);
128    }
129
130    public T back() {
131        return get(size() - 1);
132    }
133
134    public void push_back(T value) {
135        throw new UnsupportedOperationException();
136    }
137
138    protected Type T() {
139        return (Type) CPPRuntime.getInstance().getTemplateParameters(this, vector.class)[0];
140    }
141
142    protected long byteSize() {
143        return _M_finish().getPeer() - _M_start().getPeer();
144    }
145
146    public long size() {
147        long byteSize = byteSize();
148        long elementSize = BridJ.sizeOf(T());
149
150        return byteSize / elementSize;
151    }
152}