1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 package org.rocksdb;
7 
8 /**
9  * Slices are used by RocksDB to provide
10  * efficient access to keys and values.
11  *
12  * This class is package private, implementers
13  * should extend either of the public abstract classes:
14  *   @see org.rocksdb.Slice
15  *   @see org.rocksdb.DirectSlice
16  *
17  * Regards the lifecycle of Java Slices in RocksDB:
18  *   At present when you configure a Comparator from Java, it creates an
19  *   instance of a C++ BaseComparatorJniCallback subclass and
20  *   passes that to RocksDB as the comparator. That subclass of
21  *   BaseComparatorJniCallback creates the Java
22  *   @see org.rocksdb.AbstractSlice subclass Objects. When you dispose
23  *   the Java @see org.rocksdb.AbstractComparator subclass, it disposes the
24  *   C++ BaseComparatorJniCallback subclass, which in turn destroys the
25  *   Java @see org.rocksdb.AbstractSlice subclass Objects.
26  */
27 public abstract class AbstractSlice<T> extends RocksMutableObject {
28 
AbstractSlice()29   protected AbstractSlice() {
30     super();
31   }
32 
AbstractSlice(final long nativeHandle)33   protected AbstractSlice(final long nativeHandle) {
34     super(nativeHandle);
35   }
36 
37   /**
38    * Returns the data of the slice.
39    *
40    * @return The slice data. Note, the type of access is
41    *   determined by the subclass
42    *   @see org.rocksdb.AbstractSlice#data0(long)
43    */
data()44   public T data() {
45     return data0(getNativeHandle());
46   }
47 
48   /**
49    * Access to the data is provided by the
50    * subtype as it needs to handle the
51    * generic typing.
52    *
53    * @param handle The address of the underlying
54    *   native object.
55    *
56    * @return Java typed access to the data.
57    */
data0(long handle)58   protected abstract T data0(long handle);
59 
60   /**
61    * Drops the specified {@code n}
62    * number of bytes from the start
63    * of the backing slice
64    *
65    * @param n The number of bytes to drop
66    */
removePrefix(final int n)67   public abstract void removePrefix(final int n);
68 
69   /**
70    * Clears the backing slice
71    */
clear()72   public abstract void clear();
73 
74   /**
75    * Return the length (in bytes) of the data.
76    *
77    * @return The length in bytes.
78    */
size()79   public int size() {
80     return size0(getNativeHandle());
81   }
82 
83   /**
84    * Return true if the length of the
85    * data is zero.
86    *
87    * @return true if there is no data, false otherwise.
88    */
empty()89   public boolean empty() {
90     return empty0(getNativeHandle());
91   }
92 
93   /**
94    * Creates a string representation of the data
95    *
96    * @param hex When true, the representation
97    *   will be encoded in hexadecimal.
98    *
99    * @return The string representation of the data.
100    */
toString(final boolean hex)101   public String toString(final boolean hex) {
102     return toString0(getNativeHandle(), hex);
103   }
104 
105   @Override
toString()106   public String toString() {
107     return toString(false);
108   }
109 
110   /**
111    * Three-way key comparison
112    *
113    *  @param other A slice to compare against
114    *
115    *  @return Should return either:
116    *    1) &lt; 0 if this &lt; other
117    *    2) == 0 if this == other
118    *    3) &gt; 0 if this &gt; other
119    */
compare(final AbstractSlice<?> other)120   public int compare(final AbstractSlice<?> other) {
121     assert (other != null);
122     if(!isOwningHandle()) {
123       return other.isOwningHandle() ? -1 : 0;
124     } else {
125       if(!other.isOwningHandle()) {
126         return 1;
127       } else {
128         return compare0(getNativeHandle(), other.getNativeHandle());
129       }
130     }
131   }
132 
133   @Override
hashCode()134   public int hashCode() {
135     return toString().hashCode();
136   }
137 
138   /**
139    * If other is a slice object, then
140    * we defer to {@link #compare(AbstractSlice) compare}
141    * to check equality, otherwise we return false.
142    *
143    * @param other Object to test for equality
144    *
145    * @return true when {@code this.compare(other) == 0},
146    *   false otherwise.
147    */
148   @Override
equals(final Object other)149   public boolean equals(final Object other) {
150     if (other != null && other instanceof AbstractSlice) {
151       return compare((AbstractSlice<?>)other) == 0;
152     } else {
153       return false;
154     }
155   }
156 
157   /**
158    * Determines whether this slice starts with
159    * another slice
160    *
161    * @param prefix Another slice which may of may not
162    *   be a prefix of this slice.
163    *
164    * @return true when this slice starts with the
165    *   {@code prefix} slice
166    */
startsWith(final AbstractSlice<?> prefix)167   public boolean startsWith(final AbstractSlice<?> prefix) {
168     if (prefix != null) {
169       return startsWith0(getNativeHandle(), prefix.getNativeHandle());
170     } else {
171       return false;
172     }
173   }
174 
createNewSliceFromString(final String str)175   protected native static long createNewSliceFromString(final String str);
size0(long handle)176   private native int size0(long handle);
empty0(long handle)177   private native boolean empty0(long handle);
toString0(long handle, boolean hex)178   private native String toString0(long handle, boolean hex);
compare0(long handle, long otherHandle)179   private native int compare0(long handle, long otherHandle);
startsWith0(long handle, long otherHandle)180   private native boolean startsWith0(long handle, long otherHandle);
181 
182   /**
183    * Deletes underlying C++ slice pointer.
184    * Note that this function should be called only after all
185    * RocksDB instances referencing the slice are closed.
186    * Otherwise an undefined behavior will occur.
187    */
188   @Override
disposeInternal(final long handle)189   protected final native void disposeInternal(final long handle);
190 
191 }
192