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; 046import org.bridj.JNI; 047 048import static org.bridj.Pointer.*; 049import org.bridj.ann.Array; 050import org.bridj.ann.Library; 051import org.bridj.ann.Ptr; 052 053/** 054 * Binding for <a href="http://www.sgi.com/tech/stl/Vector.html">STL's 055 * std::vector</a> class. 056 * 057 * @author ochafik 058 * @param <T> 059 */ 060@Template({Type.class}) 061@Struct(customizer = STL.class) 062public class list<T> extends CPPObject { 063 064 @Library("c") 065 protected static native @Ptr 066 long malloc(@Ptr long size); 067 068 @Library("c") 069 protected static native void free(@Ptr long address); 070 071 @Template({Type.class}) 072 public static class list_node<T> extends CPPObject { 073 074 @Deprecated 075 @Field(0) 076 public Pointer<list_node<T>> next() { 077 return io.getPointerField(this, 0); 078 } 079 080 @Deprecated 081 @Field(0) 082 public void next(Pointer<list_node<T>> value) { 083 io.setPointerField(this, 0, value); 084 } 085 086 @Deprecated 087 @Field(1) 088 public Pointer<list_node<T>> prev() { 089 return io.getPointerField(this, 1); 090 } 091 092 @Field(1) 093 public void prev(Pointer<list_node<T>> value) { 094 io.setPointerField(this, 1, value); 095 } 096 097 @Deprecated 098 @Field(2) 099 @Array(1) 100 public Pointer<T> data() { 101 return io.getPointerField(this, 2); 102 } 103 104 public list_node(Type t) { 105 super((Void) null, CPPRuntime.SKIP_CONSTRUCTOR, t); 106 } 107 108 public list_node(Pointer<? extends list_node> peer, Type t) { 109 super(peer, t); 110 if (!isValid()) { 111 throw new RuntimeException("Invalid list internal data ! Are you trying to use an unsupported version of the STL ?"); 112 } 113 } 114 115 protected boolean isValid() { 116 long next = getPeer(next()); 117 long prev = getPeer(prev()); 118 if (next == 0 && prev == 0) { 119 return false; 120 } 121 return true; // TODO other checks? 122 } 123 124 public T get() { 125 return data().get(); 126 } 127 128 public void set(T value) { 129 data().set(value); 130 } 131 } 132 protected volatile Type _T; 133 134 protected Type T() { 135 if (_T == null) { 136 _T = (Type) CPPRuntime.getInstance().getTemplateParameters(this, list.class)[0]; 137 } 138 return _T; 139 } 140 141 protected list_node<T> createNode() { 142 Type T = T(); 143 long size = BridJ.sizeOf(T); 144 return new list_node<T>((Pointer) pointerToAddress(malloc(size)), T); 145 } 146 147 protected void deleteNode(list_node<T> node) { 148 free(Pointer.getAddress(node, list_node.class)); 149 } 150 151 @Deprecated 152 @Field(0) 153 public Pointer<list_node<T>> next() { 154 return io.getPointerField(this, 0); 155 } 156 157 @Deprecated 158 @Field(0) 159 public void next(Pointer<list_node<T>> value) { 160 io.setPointerField(this, 0, value); 161 } 162 163 @Deprecated 164 @Field(1) 165 public Pointer<list_node<T>> prev() { 166 return io.getPointerField(this, 1); 167 } 168 169 @Deprecated 170 @Field(1) 171 public void prev(Pointer<list_node<T>> value) { 172 io.setPointerField(this, 1, value); 173 } 174 //@Constructor(-1) 175 public list(Type t) { 176 super((Void)null, CPPRuntime.SKIP_CONSTRUCTOR, t); 177 } 178 public list(Pointer<? extends list<T>> peer, Type t) { 179 super(peer, t); 180 } 181 private void checkNotEmpty() { 182 if (isRoot(next()) && isRoot(prev())) 183 throw new NoSuchElementException(); 184 } 185 public boolean empty() { 186 return next() != null; 187 } 188 public T front() { 189 checkNotEmpty(); 190 return next().get().get(); 191 } 192 public T back() { 193 checkNotEmpty(); 194 Pointer<list_node<T>> prev = prev(), next = next(); 195 Pointer<list_node<T>> nextPrev = next == null ? null : next.get().prev(); 196 Pointer<list_node<T>> prevNext = prev == null ? null : prev.get().next(); 197 int[] nextValues = next == null ? null : next.getInts(20); 198 int[] prevValues = prev == null ? null : prev.getInts(20); 199 200 list_node<T> n = prev.get(); 201 int[] values = pointerTo(n).getInts(20); 202 return n.get(); 203// return prev().get().get(); 204 } 205 206 private boolean same(Pointer a, Pointer b) { 207 return getPeer(a) == getPeer(b); 208 } 209 210 private boolean isRoot(Pointer a) { 211 return same(a, getPointer(this)); 212 } 213 214 protected void hook(Pointer<list_node<T>> prev, Pointer<list_node<T>> next, T value) { 215 list_node<T> tmp = createNode(); 216 Pointer<list_node<T>> pTmp = getPointer(tmp); 217 tmp.set(value); 218 tmp.next(next); 219 tmp.prev(prev); 220 if (!isRoot(next)) { 221 next.get().prev(pTmp); 222 } 223 if (!isRoot(prev)) { 224 prev.get().next(pTmp); 225 } 226 } 227 228 public void push_back(T value) { 229 hook(prev(), null, value); 230 } 231 232 public void push_front(T value) { 233 hook(null, next(), value); 234 } 235}