001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.mmtk.vm.gcspy;
014    
015    import org.mmtk.utility.Log;
016    import org.vmmagic.unboxed.*;
017    import org.vmmagic.pragma.*;
018    
019    /**
020     * Abstract class that provides generally useful
021     * methods.
022     */
023    @Uninterruptible public abstract class Util {
024    
025      /**
026       * Allocate an array of bytes with malloc
027       *
028       * @param size The size to allocate
029       * @return The start address of the memory allocated in C space
030       * @see #free
031      */
032      public abstract Address malloc(int size);
033    
034      /**
035       * Free an array of bytes previously allocated with malloc
036       *
037       * @param addr The address of some memory previously allocated with malloc
038       * @see #malloc
039       */
040      public abstract void free(Address addr);
041    
042      /**
043       * Dump a range in format [start,end)
044       *
045       * @param start The start of the range
046       * @param end The end of the range
047       */
048      public static void dumpRange(Address start, Address end) {
049        Log.write("["); Log.write(start);
050        Log.write(","); Log.write(end);
051        Log.write(')');
052      }
053    
054      /**
055       * Convert a String to a 0-terminated array of bytes
056       *
057       * @param str The string to convert
058       * @return The address of a null-terminated array in C-space
059       */
060      public abstract Address getBytes(String str);
061    
062      /**
063       * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
064       *
065       * @param buffer The buffer (in C space) in which to place the formatted size
066       * @param size The size in bytes
067       */
068      public abstract void formatSize(Address buffer, int size);
069    
070      /**
071       * Pretty print a size, converting from bytes to kilo- or mega-bytes as appropriate
072       *
073       * @param format A format string
074       * @param bufsize The size of a buffer large enough to hold the formatted result
075       * @param size The size in bytes
076       */
077      public abstract Address formatSize(String format, int bufsize, int size);
078    
079    //  public abstract Address formatSize(String format, int bufsize, int size);
080    
081      /**
082       * Place a string representation of a long in an array of bytes
083       * without incurring allocation
084       *
085       * @param buffer The byte array
086       * @param value The long to convert
087       * @return The length of the string representation of the integer
088       *         -1 indicates some problem (e.g the char buffer was too small)
089       */
090      public static int numToBytes(byte[] buffer, long value) {
091        return numToBytes(buffer, value, 10);
092      }
093    
094      /**
095       * Place a string representation of a long in an array of bytes
096       * without incurring allocation
097       *
098       * @param buffer The byte array
099       * @param value The long to convert
100       * @param radix the base to use for conversion
101       * @return The length of the string representation of the integer
102       *         -1 indicates some problem (e.g the char buffer was too small)
103       */
104      public static int numToBytes(byte[] buffer, long value, int radix) {
105    
106        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
107          radix = 10;
108    
109        if (value == 0) {
110          buffer[0] = (byte)'0';
111          return 1;
112        }
113    
114        boolean negative;
115        long longValue;
116        int count;
117        if (!(negative = (value < 0))) {
118          longValue = -value;
119          count = 1;
120        } else {
121          longValue = value;
122          count = 2;
123        }
124    
125        long j = longValue;
126        while ((j /= radix) != 0) count++;
127        if (count > buffer.length)
128          return -1; // overflow
129    
130        int i = count;
131        do {
132          int ch = (int) -(longValue % radix);
133          if (ch > 9)
134            ch -= (10 - 'a');
135          else
136            ch += '0';
137          buffer [--i] = (byte) ch;
138        } while ((longValue /= radix) != 0);
139        if (negative) buffer [0] = (byte)'-';
140    
141        return count;
142    
143      }
144    
145      /**
146       * {@code sprintf(char *str, char *format, char* value)}
147       *
148       * @param str The destination 'string' (memory in C space)
149       * @param format The format 'string' (memory in C space)
150       * @param value The value 'string' (memory in C space)
151       * @return The number of characters printed (as returned by C's sprintf
152       */
153      public abstract int sprintf(Address str, Address format, Address value);
154    
155      /**
156       * Create an array of a particular type.
157       * The easiest way to use this is:
158       *     {@code Foo[] x = (Foo [])Stream.createDataArray(new Foo[0], numElements);}
159       * @param templ a data array to use as a template
160       * @param numElements number of elements in new array
161       * @return the new array
162       */
163      @Interruptible
164      public abstract Object createDataArray(Object templ, int numElements);
165    }
166