2015-09-30 55 views
3

我有一個稍微更先進的階級,我想寫一個toString()問題與Android的

爲了完成什麼,我想,我需要能夠改變的分配toString()實現某些變數在做toString()

爲了讓它變得簡單我將刪除一些除了允許它工作的東西。

public enum PacketElementType { 
    NONE((byte)0, "None"), 
    BYTE((byte)1, "Byte"), 
    SHORT((byte)2, "Short"), 
    INT((byte)3, "Int"), 
    LONG((byte)4, "Long"), 
    FLOAT((byte)5, "Float"), 
    STRING((byte)6, "String"), 
    BIN((byte)7, "Bin"); 

    private final byte typeValue; 
    private final String typeName; 

    PacketElementType(byte type, String name) 
    { 
     this.typeValue = type; 
     this.typeName = name; 
    } 

    public String getTypeName() { 
     return typeName; 
    } 

    public byte getTypeValue() { 
     return typeValue; 
    } 
} 

public class Packet { 
    private final int DEFAULT_SIZE = 1024 * 2; 
    private final int ADD_SIZE = 1024; 

    private byte[] _buffer = new byte[1]; 
    private int _ptr = 0; 
    private int _bodyStart = 0; 
    private int _elements, _bodyLen = 0; 

    private int op; 
    private long id; 

    public Packet(int op, long id) { 
     setOp(op); 
     setId(id); 

     _buffer = new byte[DEFAULT_SIZE]; 
    } 

    public int getOp() { 
     return op; 
    } 

    public void setOp(int op) { 
     this.op = op; 
    } 

    public long getId() { 
     return id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    public PacketElementType peek() { 
     int pie = _ptr; 
     if (pie + 2 > _buffer.length) 
      return PacketElementType.NONE; 
     return PacketElementType.values()[_buffer[_ptr]]; 
    } 

    protected Packet putSimple(PacketElementType type, byte... val) { 
     int len = val.length + 1; 
     this.ensureSize(len); 

     _buffer[++_ptr] = type.getTypeValue(); 
     System.arraycopy(val, 0, _buffer, _ptr, val.length); 
     _ptr += val.length; 

     _elements++; 
     _bodyLen += len; 

     return this; 
    } 

    public Packet putByte(byte val) { 
     return this.putSimple(PacketElementType.BYTE, val); 
    } 

    public Packet putByte(boolean val) { 
     return this.putByte(val ? (byte) 1 : (byte) 0); 
    } 

    public byte getByte() throws Exception { 
     if (this.peek() != PacketElementType.BYTE) 
      throw new Exception("Expected Byte, got " + this.peek().getTypeName() + "."); 

     _ptr += 1; 
     return _buffer[++_ptr]; 
    } 

    protected void ensureSize(int required) { 
     if (_ptr + required >= _buffer.length) { 
      byte[] b = new byte[_buffer.length + Math.max(ADD_SIZE, required * 2)]; 
      System.arraycopy(_buffer, 0, b, 0, _buffer.length); 
      _buffer = b; 
     } 
    } 

    private boolean isValidType(PacketElementType type) 
    { 
     return (type.getTypeValue() >= PacketElementType.BYTE.getTypeValue() && type.getTypeValue() <= PacketElementType.BIN.getTypeValue()); 
    } 

    protected String toStringHack() 
    { 
     StringBuilder result = new StringBuilder(); 
     int prevPtu = _ptr; 
     _ptr = _bodyStart; 

     try { 
      result.append(String.format("Op: %1$08d %3$s, Id: %2$016d\r\n", this.getOp(), this.getId(), Op.getName(this.getOp()))); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
      return result.append("Failed to convert packet to string").toString(); 
     } 

     PacketElementType type; 
     for (int i = 1; (this.isValidType(type = this.peek()) && _ptr < _buffer.length); ++i) 
     { 
      if (type == PacketElementType.BYTE) 
      { 
       byte data = 0; 
       try { 
        data = getByte(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
        result.append("Failed to parse element at position ").append(i); 
        continue; 
       } 
       result.append(String.format("%1&03d [%2$s] Byte : %3$s", i, String.format("%1$016d", data), data)); 
      } 
     } 

     return result.toString(); 
    } 

    //TODO: toString 
    @Override 
    public String toString() 
    { 
     return toStringHack(); 
    } 
} 


public class Op { 

    public class Msgr 
    { 

    } 

    public static String getName(int op) throws IllegalAccessException { 
     for (Field field : Op.class.getFields()) 
     { 
      if ((int)field.get(null) == op) 
       return field.getName(); 
     } 

     for (Field field : Op.Msgr.class.getFields()) 
     { 
      if ((int)field.get(null) == op) 
       return field.getName(); 
     } 

     return "?"; 
    } 
} 

debug view close [debug view far (after some instructions)2

當調試,_ptr不會toString()設置,而不是在調試時,_ptr不會putSimple()設置。

我真的很喜歡拉我的頭髮,謝謝,如果你能幫助我,我真的很高興!請再次感謝你!

爲了測試這種錯誤,請查看下面的例子:

Packet p = new Packet(1, 10001).putByte(true); 
Toast.makeText(this, p.toString(), Toast.LENGTH_LONG).show(); 

我,我扔在這裏面內置的測試類,然後再嘗試它在OnCreate從主要活動。

toString()將只返回操作和Id,因爲_ptr是,peek()將嘗試讀取從該位置開始的字節,而不是在0,它會找到我們的1個字節。

編輯

好像... _ptr = _bodyStart;被看作是比其他的分配的東西,這可能嗎?

+0

什麼是將其作爲獨立類進行調試的步驟?你會有一個主要方法來創建一個數據包對象,然後在最終調用toString()之前設置一些數據?你能發佈測試代碼嗎? – ramp

+0

謝謝你看看!〜我繼續編輯我的問題,以提供更多細節和缺課。 ^^ – ImaBrokeDude

回答

1

所以事實證明,我錯過了一個小小的細節.....根本不是微小的,我很抱歉沒有看到這一點。 toString()將因爲格式錯誤的String.format()調用而失敗,並且toString()完成後無法將ptr恢復爲原始值。

result.append(String.format("%1&03d [%2$s] Byte : %3$s", i, String.format("%1$016d", data), data)); 

本來應該(其中%1之後我有一個&而不是$

String hello = String.format("%1$03d [%2$s] Byte : %3$d\r\n", i, StringUtils.leftPad(String.format("%02X", data), 16, '.'), (int) data); 

,只是返回字符串之前,我需要做下面的

ptr = prevPtu; 

與此,發生以下情況:

COrrectly Working picture :D

1

您看到的結果沒問題 - 調試程序在評估之前向您顯示這些變量。在這個之後添加一行(如日誌或者平頭),並在其上設置斷點。

+0

嘿,在那裏,你告訴我這些,我現在不知道我在哪裏可以遇到這個特殊問題,感覺ti可能與線程相關。見[此圖片](http://i.imgur.com/eeH0rqI.png) – ImaBrokeDude