Package erjang.beam

Source Code of erjang.beam.EUtil

/**
* This file is part of Erjang - A JVM-based Erlang VM
*
* Copyright (c) 2009 by Trifork
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

package erjang.beam;

import java.io.File;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import org.objectweb.asm.Type;

import erjang.EAtom;
import erjang.EBinary;
import erjang.beam.repr.ExtFun;

/**
*
*/
public class EUtil {

  static final Pattern SIMPLE_ID = Pattern
      .compile("^([a-z]|[A-Z])\\p{Alnum}*$");

  private static final String EOBJECT_DESC = CompilerVisitor.EOBJECT_TYPE
      .getDescriptor();
  private static final String EPROC_DESC = CompilerVisitor.EPROC_TYPE
      .getDescriptor();

  static Map<Integer, String> signatures = new HashMap<Integer, String>();
  static Map<Integer, String> noproc_signatures = new HashMap<Integer, String>();

  public static String getSignature(int arity, boolean withProc) {

    Map<Integer, String> signatures = withProc ? noproc_signatures
        : EUtil.signatures;

    String res = signatures.get(arity);
    if (res == null) {
      StringBuffer sb = new StringBuffer("(");

      if (withProc) {
        sb.append(EPROC_DESC);
      }

      for (int i = 0; i < arity; i++) {
        sb.append(EOBJECT_DESC);
      }

      sb.append(")");
      sb.append(EOBJECT_DESC);

      signatures.put(arity, res = sb.toString());
    }

    return res;
  }

  static String toJavaIdentifier(EAtom name) {
    return toJavaIdentifier(name.getName());
  }

  /** encode any char sequence into a valid java identifier */
  static String toJavaIdentifier(String name) {
    if (SIMPLE_ID.matcher(name).matches())
      return name;

    StringBuilder sb = new StringBuilder();
    for (char c : name.toCharArray()) {

      if (c == '$') {
        sb.append("$$");
        continue;
      } else if (sb.length() == 0) {
        if (Character.isJavaIdentifierStart(c)) {
          sb.append(c);
          continue;
        }
      } else if (Character.isJavaIdentifierPart(c)) {
        sb.append(c);
        continue;
      }

      try {
        sb.append('$');

        ByteArrayOutputStream baro = new ByteArrayOutputStream(5);
        DataOutputStream dao = new DataOutputStream(baro);
        dao.writeUTF(new String(new char[] { c }));
        dao.close();

        byte[] data = baro.toByteArray();

        writeHexByte(sb, 0xff & data[2]);

        if (data.length > 3)
          writeHexByte(sb, 0xff & data[3]);

        if (data.length > 4)
          writeHexByte(sb, 0xff & data[4]);

      } catch (IOException ex) {
        throw new Error();
      }

    }

    return sb.toString();
  }

  private static void writeHexByte(StringBuilder sb, int b) {
    if (b < 0x10) {
      sb.append('0');
    }

    sb.append(Integer.toHexString(b).toUpperCase());
  }

  public static String plen(Object o) {
    String s = String.valueOf(o);
    StringBuilder sb = new StringBuilder("_");
    writeHexByte(sb, s.length());
    sb.append(s);
    return s.toString();
  }

  public static String getJavaName(EAtom fun, int arity) {
    String fname = fun.getName();
    if (fname.indexOf("__") == -1) {
      return toJavaIdentifier(fun.getName() + "__" + arity);
    } else {
      return toJavaIdentifier(plen(fun.getName()) + "__" + arity);
    }
  }

  /**
   * @param fun
   * @return
   */
  public static String getJavaName(ExtFun fun) {
    return toJavaIdentifier(fun.mod) + "__" + getJavaName(fun.fun, fun.arity);
  }

  /**
   * @param selfType
   * @param efun
   * @return
   */
  public static String getFunClassName(Type self_type, ExtFun efun) {
    return self_type.getInternalName() + "$FN_"
        + getJavaName(efun.fun, efun.arity);
  }

  public static String getFunClassName(Type self_type, ExtFun efun, int freevars) {
    return self_type.getInternalName() + "$FN_"
        + getJavaName(efun.fun, efun.arity-freevars);
  }

  /**
   * @param arity
   * @param proc
   * @param returnType
   * @return
   */
  public static String getSignature(int arity, boolean withProc,
      Type returnType) {

    StringBuffer sb = new StringBuffer("(");

    if (withProc) {
      sb.append(EPROC_DESC);
    }

    for (int i = 0; i < arity; i++) {
      sb.append(EOBJECT_DESC);
    }

    sb.append(")");
    sb.append(returnType.getDescriptor());

    return sb.toString();
  }

  /**
   * @param methodName
   * @return
   */
  public static String decodeJavaName(String methodName) {

    int idx;
    if ((idx = methodName.indexOf('$')) == -1)
      return methodName;

    StringBuilder sb = new StringBuilder();

    int start = 0;
    while (idx != -1) {
      sb.append(methodName.substring(start, idx));
      if (methodName.charAt(idx+1) == '$') {
        sb.append('$');
        start = idx + 2;
      } else {
        String hex = methodName.substring(idx + 1, idx + 3);
        char chval;
        try {
          chval = (char) Integer.parseInt(hex, 16);
        } catch (NumberFormatException e) {
          chval = '?';
        }
        sb.append(chval);
        start = idx + 3;
      }
      idx = methodName.indexOf('$', start);
    }

    sb.append(methodName.substring(start));

    return sb.toString();
  }

  public static EBinary readFile(File file) throws IOException {
    int length = (int) file.length();
    byte[] data = new byte[length];
    FileInputStream fi = new FileInputStream(file);
    try {
      ByteArrayOutputStream bo = new ByteArrayOutputStream();
      int read = 0;
      while (read < length) {
        read += fi.read(data, read, length-read);
      }
    } finally {
      fi.close();
    }

    EBinary bin = new EBinary(data);
    return bin;
  }
}
TOP

Related Classes of erjang.beam.EUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.