1 /*
   2  * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.awt.X11;
  27 
  28 import sun.misc.Unsafe;
  29 import java.util.Vector;
  30 import java.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 
  33 /**
  34  * This class contains the collection of utility functions to help work with
  35  * native data types on different platforms similarly.
  36  */
  37 
  38 class Native {
  39 
  40     private static Unsafe unsafe = XlibWrapper.unsafe;
  41 
  42     static int longSize;
  43 
  44     static int dataModel;
  45     static {
  46         String dataModelProp = AccessController.doPrivileged(
  47             new PrivilegedAction<String>() {
  48                 public String run() {
  49                     return System.getProperty("sun.arch.data.model");
  50                 }
  51             });
  52         try {
  53             dataModel = Integer.parseInt(dataModelProp);
  54         } catch (Exception e) {
  55             dataModel = 32;
  56         }
  57         if (dataModel == 32) {
  58             longSize = 4;
  59         } else {
  60             longSize = 8;
  61         }
  62     }
  63 
  64     /**
  65      * Set of helper function to read data of different PLATFORM types
  66      * from memory pointer by <code>ptr</code>
  67      * Note, names of types in function are NATIVE PLATFORM types
  68      * and they have the same size as they would have in C compiler
  69      * on the same platform.
  70      */
  71 
  72     static boolean getBool(long ptr) { return getInt(ptr) != 0; }
  73     static boolean getBool(long ptr, int index) { return getInt(ptr, index) != 0; }
  74     static void putBool(long ptr, boolean data) { putInt(ptr, (data)?(1):(0)); }
  75     static void putBool(long ptr, int index, boolean data) { putInt(ptr, index, (data)?(1):(0)); }
  76 
  77 
  78     /**
  79      * Access to C byte data(one byte)
  80      */
  81     static int getByteSize() { return 1; }
  82     static byte getByte(long ptr) { return unsafe.getByte(ptr); }
  83 
  84     static byte getByte(long ptr, int index) {
  85         return getByte(ptr+index);
  86     }
  87     /**
  88      * Stores to C byte data(one byte)
  89      */
  90     static void putByte(long ptr, byte data) { unsafe.putByte(ptr, data); }
  91 
  92     static void putByte(long ptr, int index, byte data) {
  93         putByte(ptr+index, data);
  94     }
  95     /**
  96      * Converts length bytes of data pointed by <code>data</code> into byte array
  97      * Returns null if data is zero
  98      * @param data native pointer to native memory
  99      * @param length size in bytes of native memory
 100      */
 101     static byte[] toBytes(long data, int length) {
 102         if (data == 0) {
 103             return null;
 104         }
 105         byte[] res = new byte[length];
 106         for (int i = 0; i < length; i++, data++) {
 107             res[i] = getByte(data);
 108         }
 109         return res;
 110     }
 111     /**
 112      * Stores byte array into native memory and returns pointer to this memory
 113      * Returns 0 if bytes is null
 114      */
 115     static long toData(byte[] bytes) {
 116         if (bytes == null) {
 117             return 0;
 118         }
 119         long res = XlibWrapper.unsafe.allocateMemory(bytes.length);
 120         for (int i = 0; i < bytes.length; i++) {
 121             putByte(res+i, bytes[i]);
 122         }
 123         return res;
 124     }
 125 
 126     /**
 127      * Access to C unsigned byte data(one byte)
 128      */
 129     static int getUByteSize() { return 1; }
 130     static short getUByte(long ptr) { return (short)(0xFF & unsafe.getByte(ptr));  }
 131 
 132     static short getUByte(long ptr, int index) {
 133         return getUByte(ptr+index);
 134     }
 135 
 136     /**
 137      * Stores to C unsigned byte data(one byte)
 138      */
 139     static void putUByte(long ptr, short data) { unsafe.putByte(ptr, (byte)data); }
 140 
 141     static void putUByte(long ptr, int index, short data) {
 142         putUByte(ptr+index, data);
 143     }
 144 
 145     /**
 146      * Converts length usnigned bytes of data pointed by <code>data</code> into
 147      * short array
 148      * Returns null if data is zero
 149      * @param data native pointer to native memory
 150      * @param length size in bytes of native memory
 151      */
 152     static short[] toUBytes(long data, int length) {
 153         if (data == 0) {
 154             return null;
 155         }
 156         short[] res = new short[length];
 157         for (int i = 0; i < length; i++, data++) {
 158             res[i] = getUByte(data);
 159         }
 160         return res;
 161     }
 162     /**
 163      * Stores short array as unsigned bytes into native memory and returns pointer
 164      * to this memory
 165      * Returns 0 if bytes is null
 166      */
 167     static long toUData(short[] bytes) {
 168         if (bytes == null) {
 169             return 0;
 170         }
 171         long res = XlibWrapper.unsafe.allocateMemory(bytes.length);
 172         for (int i = 0; i < bytes.length; i++) {
 173             putUByte(res+i, bytes[i]);
 174         }
 175         return res;
 176     }
 177 
 178     /**
 179      * Access to C short data(two bytes)
 180      */
 181     static int getShortSize() { return 2; }
 182     static short getShort(long ptr) { return unsafe.getShort(ptr); }
 183     /**
 184      * Stores to C short data(two bytes)
 185      */
 186     static void putShort(long ptr, short data) { unsafe.putShort(ptr, data); }
 187     static void putShort(long ptr, int index, short data) {
 188         putShort(ptr + index*getShortSize(), data);
 189     }
 190     static long toData(short[] shorts) {
 191         if (shorts == null) {
 192             return 0;
 193         }
 194         long res = XlibWrapper.unsafe.allocateMemory(shorts.length*getShortSize());
 195         for (int i = 0; i < shorts.length; i++) {
 196             putShort(res, i, shorts[i]);
 197         }
 198         return res;
 199     }
 200 
 201     /**
 202      * Access to C unsigned short data(two bytes)
 203      */
 204     static int getUShortSize() { return 2; }
 205 
 206     static int getUShort(long ptr) { return 0xFFFF & unsafe.getShort(ptr); }
 207     /**
 208      * Stores to C unsigned short data(two bytes)
 209      */
 210     static void putUShort(long ptr, int data) { unsafe.putShort(ptr, (short)data); }
 211     static void putUShort(long ptr, int index, int data) {
 212         putUShort(ptr + index*getShortSize(), data);
 213     }
 214 
 215     /**
 216      * Stores int array as unsigned shorts into native memory and returns pointer
 217      * to this memory
 218      * Returns 0 if bytes is null
 219      */
 220     static long toUData(int[] shorts) {
 221         if (shorts == null) {
 222             return 0;
 223         }
 224         long res = XlibWrapper.unsafe.allocateMemory(shorts.length*getShortSize());
 225         for (int i = 0; i < shorts.length; i++) {
 226             putUShort(res, i, shorts[i]);
 227         }
 228         return res;
 229     }
 230 
 231     /**
 232      * Access to C int data(four bytes)
 233      */
 234     static int getIntSize() { return 4; }
 235     static int getInt(long ptr) { return unsafe.getInt(ptr); }
 236     static int getInt(long ptr, int index) { return getInt(ptr +getIntSize()*index); }
 237     /**
 238      * Stores to C int data(four bytes)
 239      */
 240     static void putInt(long ptr, int data) { unsafe.putInt(ptr, data); }
 241     static void putInt(long ptr, int index, int data) {
 242         putInt(ptr + index*getIntSize(), data);
 243     }
 244     static long toData(int[] ints) {
 245         if (ints == null) {
 246             return 0;
 247         }
 248         long res = XlibWrapper.unsafe.allocateMemory(ints.length*getIntSize());
 249         for (int i = 0; i < ints.length; i++) {
 250             putInt(res, i, ints[i]);
 251         }
 252         return res;
 253     }
 254 
 255     /**
 256      * Access to C unsigned int data(four bytes)
 257      */
 258     static int getUIntSize() { return 4; }
 259     static long getUInt(long ptr) { return 0xFFFFFFFFL & unsafe.getInt(ptr); }
 260     static long getUInt(long ptr, int index) { return getUInt(ptr +getIntSize()*index); }
 261     /**
 262      * Stores to C unsigned int data(four bytes)
 263      */
 264     static void putUInt(long ptr, long data) { unsafe.putInt(ptr, (int)data); }
 265     static void putUInt(long ptr, int index, long data) {
 266         putUInt(ptr + index*getIntSize(), data);
 267     }
 268 
 269     /**
 270      * Stores long array as unsigned intss into native memory and returns pointer
 271      * to this memory
 272      * Returns 0 if bytes is null
 273      */
 274     static long toUData(long[] ints) {
 275         if (ints == null) {
 276             return 0;
 277         }
 278         long res = XlibWrapper.unsafe.allocateMemory(ints.length*getIntSize());
 279         for (int i = 0; i < ints.length; i++) {
 280             putUInt(res, i, ints[i]);
 281         }
 282         return res;
 283     }
 284 
 285     /**
 286      * Access to C long data(size depends on platform)
 287      */
 288     static int getLongSize() {
 289         return longSize;
 290     }
 291     static long getLong(long ptr) {
 292         if (XlibWrapper.dataModel == 32) {
 293             return unsafe.getInt(ptr);
 294         } else {
 295             return unsafe.getLong(ptr);
 296         }
 297     }
 298     /**
 299      * Stores to C long data(four bytes)
 300      * Note: <code>data</code> has <code>long</code> type
 301      * to be able to keep 64-bit C <code>long</code> data
 302      */
 303     static void putLong(long ptr, long data) {
 304         if (XlibWrapper.dataModel == 32) {
 305             unsafe.putInt(ptr, (int)data);
 306         } else {
 307             unsafe.putLong(ptr, data);
 308         }
 309     }
 310 
 311     static void putLong(long ptr, int index, long data) {
 312         putLong(ptr+index*getLongSize(), data);
 313     }
 314 
 315     /**
 316      * Returns index's element of the array of native long pointed by ptr
 317      */
 318     static long getLong(long ptr, int index) {
 319         return getLong(ptr + index*getLongSize());
 320     }
 321     /**
 322      * Stores Java long[] array into memory. Memory location is treated as array
 323      * of native <code>long</code>s
 324      */
 325     static void put(long ptr, long[] arr) {
 326         for (int i = 0; i < arr.length; i ++, ptr += getLongSize()) {
 327             putLong(ptr, arr[i]);
 328         }
 329     }
 330 
 331     /**
 332      * Stores Java Vector of Longs into memory. Memory location is treated as array
 333      * of native <code>long</code>s
 334      */
 335     static void putLong(long ptr, Vector<Long> arr) {
 336         for (int i = 0; i < arr.size(); i ++, ptr += getLongSize()) {
 337             putLong(ptr, arr.elementAt(i).longValue());
 338         }
 339     }
 340 
 341     /**
 342      * Stores Java Vector of Longs into memory. Memory location is treated as array
 343      * of native <code>long</code>s. Array is stored in reverse order
 344      */
 345     static void putLongReverse(long ptr, Vector<Long> arr) {
 346         for (int i = arr.size()-1; i >= 0; i--, ptr += getLongSize()) {
 347             putLong(ptr, arr.elementAt(i).longValue());
 348         }
 349     }
 350     /**
 351      * Converts length bytes of data pointed by <code>data</code> into byte array
 352      * Returns null if data is zero
 353      * @param data native pointer to native memory
 354      * @param length size in longs(platform dependent) of native memory
 355      */
 356     static long[] toLongs(long data, int length) {
 357         if (data == 0) {
 358             return null;
 359         }
 360         long[] res = new long[length];
 361         for (int i = 0; i < length; i++, data += getLongSize()) {
 362             res[i] = getLong(data);
 363         }
 364         return res;
 365     }
 366     static long toData(long[] longs) {
 367         if (longs == null) {
 368             return 0;
 369         }
 370         long res = XlibWrapper.unsafe.allocateMemory(longs.length*getLongSize());
 371         for (int i = 0; i < longs.length; i++) {
 372             putLong(res, i, longs[i]);
 373         }
 374         return res;
 375     }
 376 
 377 
 378     /**
 379      * Access to C "unsigned long" date type, which is XID in X
 380      */
 381     static long getULong(long ptr) {
 382         if (XlibWrapper.dataModel == 32) {
 383             // Compensate sign-expansion
 384             return ((long)unsafe.getInt(ptr)) & 0xFFFFFFFFL;
 385         } else {
 386             // Can't do anything!!!
 387             return unsafe.getLong(ptr);
 388         }
 389     }
 390 
 391     static void putULong(long ptr, long value) {
 392         putLong(ptr, value);
 393     }
 394 
 395     /**
 396      * Allocates memory for array of native <code>long</code>s of the size <code>length</code>
 397      */
 398     static long allocateLongArray(int length) {
 399         return unsafe.allocateMemory(getLongSize() * length);
 400     }
 401 
 402 
 403     static long getWindow(long ptr) {
 404         return getLong(ptr);
 405     }
 406     static long getWindow(long ptr, int index) {
 407         return getLong(ptr + getWindowSize()*index);
 408     }
 409 
 410     static void putWindow(long ptr, long window) {
 411         putLong(ptr, window);
 412     }
 413 
 414     static void putWindow(long ptr, int index, long window) {
 415         putLong(ptr, index, window);
 416     }
 417 
 418     /**
 419      * Set of function to return sizes of C data of the appropriate
 420      * type.
 421      */
 422     static int getWindowSize() {
 423         return getLongSize();
 424     }
 425 
 426 
 427     /**
 428      * Set of function to access CARD32 type. All data which types are derived
 429      * from CARD32 should be accessed using this accessors.
 430      * These types are: XID(Window, Drawable, Font, Pixmap, Cursor, Colormap, GContext, KeySym),
 431      *                  Atom, Mask, VisualID, Time
 432      */
 433     static long getCard32(long ptr) {
 434         return getLong(ptr);
 435     }
 436     static void putCard32(long ptr, long value) {
 437         putLong(ptr, value);
 438     }
 439     static long getCard32(long ptr, int index) {
 440         return getLong(ptr, index);
 441     }
 442     static void putCard32(long ptr, int index, long value) {
 443         putLong(ptr, index, value);
 444     }
 445     static int getCard32Size() {
 446         return getLongSize();
 447     }
 448     static long[] card32ToArray(long ptr, int length) {
 449         return toLongs(ptr, length);
 450     }
 451     static long card32ToData(long[] arr) {
 452         return toData(arr);
 453     }
 454 }