text: #include "AccessFlag.h"
  #include "Debug.h"
  #include "JavaType.h"
  
  void Inspector::printConstantPool(const JavaClass& jc) {
      using namespace std;
      DbgPleasant d("Constant pool", 3);
      d.setCellWidth(30);
      d.addCell("Index");
      d.addCell("Slot Type");
      d.addCell("Extra information");
      for (int i = 1; i <= jc.raw.constPoolCount - 1; i++) {
          d.addCell("#" + std::to_string(i));
          d.addCell(typeid(*jc.raw.constPoolInfo[i]).name());
  
          // Extra information about specified CONSTANT_* structure
          if (typeid(*jc.raw.constPoolInfo[i]) == typeid(CONSTANT_Utf8)) {
              d.addCell(
                  (char*)dynamic_cast<CONSTANT_Utf8*>(jc.raw.constPoolInfo[i])
                      ->bytes);
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_String)) {
              d.addCell(jc.getString(
                  dynamic_cast<CONSTANT_String*>(jc.raw.constPoolInfo[i])
                      ->stringIndex));
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_Integer)) {
              d.addCell(std::to_string(
                  dynamic_cast<CONSTANT_Integer*>(jc.raw.constPoolInfo[i])->val));
          } else if (typeid(*jc.raw.constPoolInfo[i]) == typeid(CONSTANT_Float)) {
              d.addCell(std::to_string(
                  dynamic_cast<CONSTANT_Float*>(jc.raw.constPoolInfo[i])->val));
          } else if (typeid(*jc.raw.constPoolInfo[i]) == typeid(CONSTANT_Long)) {
              d.addCell(std::to_string(
                  dynamic_cast<CONSTANT_Long*>(jc.raw.constPoolInfo[i])->val));
              i++;
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_Double)) {
              d.addCell(std::to_string(
                  dynamic_cast<CONSTANT_Double*>(jc.raw.constPoolInfo[i])->val));
              i++;
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_Fieldref)) {
              d.addCell(jc.getString(
                  dynamic_cast<CONSTANT_NameAndType*>(
                      jc.raw.constPoolInfo[dynamic_cast<CONSTANT_Fieldref*>(
                                               jc.raw.constPoolInfo[i])
                                               ->nameAndTypeIndex])
                      ->nameIndex));
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_Methodref)) {
              d.addCell(jc.getString(
                  dynamic_cast<CONSTANT_NameAndType*>(
                      jc.raw.constPoolInfo[dynamic_cast<CONSTANT_Methodref*>(
                                               jc.raw.constPoolInfo[i])
                                               ->nameAndTypeIndex])
                      ->nameIndex));
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_InterfaceMethodref)) {
              d.addCell(jc.getString(
                  dynamic_cast<CONSTANT_NameAndType*>(
                      jc.raw.constPoolInfo
                          [dynamic_cast<CONSTANT_InterfaceMethodref*>(
                               jc.raw.constPoolInfo[i])
                               ->nameAndTypeIndex])
                      ->nameIndex));
          } else if (typeid(*jc.raw.constPoolInfo[i]) == typeid(CONSTANT_Class)) {
              d.addCell(jc.getString(
                  dynamic_cast<CONSTANT_Class*>(jc.raw.constPoolInfo[i])
                      ->nameIndex));
          } else if (typeid(*jc.raw.constPoolInfo[i]) ==
                     typeid(CONSTANT_NameAndType)) {
              std::string nameAndType;
              nameAndType += jc.getString(
                  dynamic_cast<CONSTANT_NameAndType*>(jc.raw.constPoolInfo[i])
                      ->nameIndex);
              nameAndType += " ! ";
              nameAndType += jc.getString(
                  dynamic_cast<CONSTANT_NameAndType*>(jc.raw.constPoolInfo[i])
                      ->descriptorIndex);
              d.addCell(nameAndType);
          } else {
              d.addCell(" ");
          }
      }
      d.show();
  }
  
  void Inspector::printField(const JavaClass& jc) {
      using namespace std;
      DbgPleasant d("Class fields", 4);
      d.setCellWidth(30);
      d.addCell("Flags");
      d.addCell("Field name");
      d.addCell("Field descriptor");
      d.addCell("Attrs count");
      FOR_EACH(i, jc.raw.fieldsCount) {
          int flag = jc.raw.fields[i].accessFlags;
  
          std::string flagstr;
          if (IS_FIELD_PUBLIC(flag)) {
              flagstr += "[public]";
          } else if (IS_FIELD_PRIVATE(flag)) {
              flagstr += "[private]";
          } else if (IS_FIELD_PROTECTED(flag)) {
              flagstr += "[protected]";
          }
  
          if (IS_FIELD_STATIC(flag)) {
              flagstr += "[static]";
          }
          if (IS_FIELD_FINAL(flag)) {
              flagstr += "[final]";
          }
          if (IS_FIELD_VOLATILE(flag)) {
              flagstr += "[volatile]";
          }
          if (IS_FIELD_TRANSIENT(flag)) {
              flagstr += "[transient]";
          }
          if (IS_FIELD_SYNTHETIC(flag)) {
              flagstr += "[synthetic_by_compiler]";
          }
          if (IS_FIELD_ENUM(flag)) {
              flagstr += "[enum]";
          }
          d.addCell(flagstr);
          d.addCell(jc.getString(jc.raw.fields[i].nameIndex));
          d.addCell(jc.getString(jc.raw.fields[i].descriptorIndex));
          d.addCell(std::to_string(jc.raw.fields[i].attributeCount));
      }
      d.show();
  }
  
  void Inspector::printClassAccessFlag(const JavaClass& jc) {
      using namespace std;
      DbgPleasant d("Class access flags", 1);
      d.addCell("Flags");
  
      std::string flagstr;
      if (IS_CLASS_PUBLIC(jc.raw.accessFlags)) {
          flagstr += "[public] ";
      }
      if (IS_CLASS_ABSTRACT(jc.raw.accessFlags)) {
          flagstr += "[abstract] ";
      }
      if (IS_CLASS_FINAL(jc.raw.accessFlags)) {
          flagstr += "[final] ";
      }
      if (IS_CLASS_SUPER(jc.raw.accessFlags)) {
          flagstr += "[super] ";
      }
      if (IS_CLASS_INTERFACE(jc.raw.accessFlags)) {
          flagstr += "[interface] ";
      }
      if (IS_CLASS_SYNTHETIC(jc.raw.accessFlags)) {
          flagstr += "[synthetic_by_compiler] ";
      }
      if (IS_CLASS_ANNOTATION(jc.raw.accessFlags)) {
          flagstr += "[annotation] ";
      }
      if (IS_CLASS_ENUM(jc.raw.accessFlags)) {
          flagstr += "[enum] ";
      }
      d.addCell(flagstr);
      d.show();
  }
  
  void Inspector::printMethod(const JavaClass& jc) {
      using namespace std;
      DbgPleasant d("Methods", 5);
      d.addCell("Flags");
      d.addCell("Method name");
      d.addCell("Method descriptor");
      d.addCell("Attrs count");
      d.addCell("Attrs type");
      FOR_EACH(i, jc.raw.methodsCount) {
          std::string flagstr;
  
          if (IS_METHOD_PUBLIC(jc.raw.methods[i].accessFlags)) {
              flagstr += "[public]";
          } else if (IS_METHOD_PRIVATE(jc.raw.methods[i].accessFlags)) {
              flagstr += "[private]";
          } else if (IS_METHOD_PROTECTED(jc.raw.methods[i].accessFlags)) {
              flagstr += "[protected]";
          }
  
          if (IS_METHOD_STATIC(jc.raw.methods[i].accessFlags)) {
              flagstr += "[static]";
          }
          if (IS_METHOD_FINAL(jc.raw.methods[i].accessFlags)) {
              flagstr += "[final]";
          }
          if (IS_METHOD_SYNCHRONIZED(jc.raw.methods[i].accessFlags)) {
              flagstr += "[synchronized]";
          }
          if (IS_METHOD_BRIDGE(jc.raw.methods[i].accessFlags)) {
              flagstr += "[bridge]";
          }
          if (IS_METHOD_VARARGS(jc.raw.methods[i].accessFlags)) {
              cout << " [VARARGS]";
          }
          if (IS_METHOD_NATIVE(jc.raw.methods[i].accessFlags)) {
              flagstr += "[native]";
          }
          if (IS_METHOD_ABSTRACT(jc.raw.methods[i].accessFlags)) {
              flagstr += "[abstract]";
          }
          if (IS_METHOD_STRICT(jc.raw.methods[i].accessFlags)) {
              flagstr += "[strictfp_mode]";
          }
          if (IS_METHOD_SYNTHETIC(jc.raw.methods[i].accessFlags)) {
              flagstr += "[synthetic]";
          }
  
          d.addCell(flagstr);
          d.addCell(jc.getString(jc.raw.methods[i].nameIndex));
          d.addCell(jc.getString(jc.raw.methods[i].descriptorIndex));
          d.addCell(std::to_string(jc.raw.methods[i].attributeCount));
          std::string attrsType;
          FOR_EACH(k, jc.raw.methods[i].attributeCount) {
              attrsType.append(typeid(*jc.raw.methods[i].attributes[k]).name());
              attrsType.append(" ");
          }
          d.addCell(attrsType);
      }
      d.show();
  }
  
  void Inspector::printClassFileVersion(const JavaClass& jc) {
      DbgPleasant d("Class file versions", 2);
      d.addCell("Minor version");
      d.addCell(std::to_string(jc.raw.minorVersion));
      d.addCell("Major version");
      d.addCell(std::to_string(jc.raw.majorVersion));
      d.show();
  }
  
  void Inspector::printInterfaces(const JavaClass& jc) {
      DbgPleasant d("Interfaces", 2);
      d.addCell("Index");
      d.addCell("Interface name");
      FOR_EACH(i, jc.raw.interfacesCount) {
          d.addCell("#" + std::to_string(i));
          d.addCell(jc.getString(dynamic_cast<CONSTANT_Class*>(
                                     jc.raw.constPoolInfo[jc.raw.interfaces[i]])
                                     ->nameIndex));
      }
      d.show();
  }
  
  void Inspector::printClassFileAttrs(const JavaClass& jc) {
      DbgPleasant d("Class file attributes", 2);
      d.addCell("Attribute type");
      d.addCell("Attribute byte length");
      FOR_EACH(i, jc.raw.attributesCount) {
          d.addCell(typeid(*jc.raw.attributes[i]).name());
          d.addCell(std::to_string(jc.raw.attributes[i]->attributeLength));
      }
      d.show();
  }
  
  void Inspector::printSizeofInternalTypes() {
      DbgPleasant d("All size of internal types", 2);
      d.addCell("Type");
      d.addCell("Bytes");
  
      d.addCell(typeid(JDouble).name());
      d.addCell(std::to_string(sizeof(JDouble)));
      d.addCell(typeid(JFloat).name());
      d.addCell(std::to_string(sizeof(JFloat)));
      d.addCell(typeid(JInt).name());
      d.addCell(std::to_string(sizeof(JInt)));
      d.addCell(typeid(JLong).name());
      d.addCell(std::to_string(sizeof(JLong)));
      d.addCell(typeid(JObject).name());
      d.addCell(std::to_string(sizeof(JObject)));
      d.addCell(typeid(JArray).name());
      d.addCell(std::to_string(sizeof(JArray)));
      d.show();
  }
  
  void Inspector::printOpcode(u1* code, u4 index) {
      switch (code[index]) {
          case 0:
              std::cout << "nop\n";
              break;
          case 1:
              std::cout << "aconst_null\n";
              break;
          case 2:
              std::cout << "iconst_m1\n";
              break;
          case 3:
              std::cout << "iconst_0\n";
              break;
          case 4:
              std::cout << "iconst_1\n";
              break;
          case 5:
              std::cout << "iconst_2\n";
              break;
          case 6:
              std::cout << "iconst_3\n";
              break;
          case 7:
              std::cout << "iconst_4\n";
              break;
          case 8:
              std::cout << "iconst_5\n";
              break;
          case 9:
              std::cout << "lconst_0\n";
              break;
          case 10:
              std::cout << "lconst_1\n";
              break;
          case 11:
              std::cout << "fconst_0\n";
              break;
          case 12:
              std::cout << "fconst_1\n";
              break;
          case 13:
              std::cout << "fconst_2\n";
              break;
          case 14:
              std::cout << "dconst_0\n";
              break;
          case 15:
              std::cout << "dconst_1\n";
              break;
          case 16:
              std::cout << "bipush\n";
              break;
          case 17:
              std::cout << "sipush\n";
              break;
          case 18:
              std::cout << "ldc\n";
              break;
          case 19:
              std::cout << "ldc_w\n";
              break;
          case 20:
              std::cout << "ldc2_w\n";
              break;
          case 21:
              std::cout << "iload\n";
              break;
          case 22:
              std::cout << "lload\n";
              break;
          case 23:
              std::cout << "fload\n";
              break;
          case 24:
              std::cout << "dload\n";
              break;
          case 25:
              std::cout << "aload\n";
              break;
          case 26:
              std::cout << "iload_0\n";
              break;
          case 27:
              std::cout << "iload_1\n";
              break;
          case 28:
              std::cout << "iload_2\n";
              break;
          case 29:
              std::cout << "iload_3\n";
              break;
          case 30:
              std::cout << "lload_0\n";
              break;
          case 31:
              std::cout << "lload_1\n";
              break;
          case 32:
              std::cout << "lload_2\n";
              break;
          case 33:
              std::cout << "lload_3\n";
              break;
          case 34:
              std::cout << "fload_0\n";
              break;
          case 35:
              std::cout << "fload_1\n";
              break;
          case 36:
              std::cout << "fload_2\n";
              break;
          case 37:
              std::cout << "fload_3\n";
              break;
          case 38:
              std::cout << "dload_0\n";
              break;
          case 39:
              std::cout << "dload_1\n";
              break;
          case 40:
              std::cout << "dload_2\n";
              break;
          case 41:
              std::cout << "dload_3\n";
              break;
          case 42:
              std::cout << "aload_0\n";
              break;
          case 43:
              std::cout << "aload_1\n";
              break;
          case 44:
              std::cout << "aload_2\n";
              break;
          case 45:
              std::cout << "aload_3\n";
              break;
          case 46:
              std::cout << "iaload\n";
              break;
          case 47:
              std::cout << "laload\n";
              break;
          case 48:
              std::cout << "faload\n";
              break;
          case 49:
              std::cout << "daload\n";
              break;
          case 50:
              std::cout << "aaload\n";
              break;
          case 51:
              std::cout << "baload\n";
              break;
          case 52:
              std::cout << "caload\n";
              break;
          case 53:
              std::cout << "saload\n";
              break;
          case 54:
              std::cout << "istore\n";
              break;
          case 55:
              std::cout << "lstore\n";
              break;
          case 56:
              std::cout << "fstore\n";
              break;
          case 57:
              std::cout << "dstore\n";
              break;
          case 58:
              std::cout << "astore\n";
              break;
          case 59:
              std::cout << "istore_0\n";
              break;
          case 60:
              std::cout << "istore_1\n";
              break;
          case 61:
              std::cout << "istore_2\n";
              break;
          case 62:
              std::cout << "istore_3\n";
              break;
          case 63:
              std::cout << "lstore_0\n";
              break;
          case 64:
              std::cout << "lstore_1\n";
              break;
          case 65:
              std::cout << "lstore_2\n";
              break;
          case 66:
              std::cout << "lstore_3\n";
              break;
          case 67:
              std::cout << "fstore_0\n";
              break;
          case 68:
              std::cout << "fstore_1\n";
              break;
          case 69:
              std::cout << "fstore_2\n";
              break;
          case 70:
              std::cout << "fstore_3\n";
              break;
          case 71:
              std::cout << "dstore_0\n";
              break;
          case 72:
              std::cout << "dstore_1\n";
              break;
          case 73:
              std::cout << "dstore_2\n";
              break;
          case 74:
              std::cout << "dstore_3\n";
              break;
          case 75:
              std::cout << "astore_0\n";
              break;
          case 76:
              std::cout << "astore_1\n";
              break;
          case 77:
              std::cout << "astore_2\n";
              break;
          case 78:
              std::cout << "astore_3\n";
              break;
          case 79:
              std::cout << "iastore\n";
              break;
          case 80:
              std::cout << "lastore\n";
              break;
          case 81:
              std::cout << "fastore\n";
              break;
          case 82:
              std::cout << "dastore\n";
              break;
          case 83:
              std::cout << "aastore\n";
              break;
          case 84:
              std::cout << "bastore\n";
              break;
          case 85:
              std::cout << "castore\n";
              break;
          case 86:
              std::cout << "sastore\n";
              break;
          case 87:
              std::cout << "pop\n";
              break;
          case 88:
              std::cout << "pop2\n";
              break;
          case 89:
              std::cout << "dup\n";
              break;
          case 90:
              std::cout << "dup_x1\n";
              break;
          case 91:
              std::cout << "dup_x2\n";
              break;
          case 92:
              std::cout << "dup2\n";
              break;
          case 93:
              std::cout << "dup2_x1\n";
              break;
          case 94:
              std::cout << "dup2_x2\n";
              break;
          case 95:
              std::cout << "swap\n";
              break;
          case 96:
              std::cout << "iadd\n";
              break;
          case 97:
              std::cout << "ladd\n";
              break;
          case 98:
              std::cout << "fadd\n";
              break;
          case 99:
              std::cout << "dadd\n";
              break;
          case 100:
              std::cout << "isub\n";
              break;
          case 101:
              std::cout << "lsub\n";
              break;
          case 102:
              std::cout << "fsub\n";
              break;
          case 103:
              std::cout << "dsub\n";
              break;
          case 104:
              std::cout << "imul\n";
              break;
          case 105:
              std::cout << "lmul\n";
              break;
          case 106:
              std::cout << "fmul\n";
              break;
          case 107:
              std::cout << "dmul\n";
              break;
          case 108:
              std::cout << "idiv\n";
              break;
          case 109:
              std::cout << "ldiv\n";
              break;
          case 110:
              std::cout << "fdiv\n";
              break;
          case 111:
              std::cout << "ddiv\n";
              break;
          case 112:
              std::cout << "irem\n";
              break;
          case 113:
              std::cout << "lrem\n";
              break;
          case 114:
              std::cout << "frem\n";
              break;
          case 115:
              std::cout << "drem\n";
              break;
          case 116:
              std::cout << "ineg\n";
              break;
          case 117:
              std::cout << "lneg\n";
              break;
          case 118:
              std::cout << "fneg\n";
              break;
          case 119:
              std::cout << "dneg\n";
              break;
          case 120:
              std::cout << "ishl\n";
              break;
          case 121:
              std::cout << "lshl\n";
              break;
          case 122:
              std::cout << "ishr\n";
              break;
          case 123:
              std::cout << "lshr\n";
              break;
          case 124:
              std::cout << "iushr\n";
              break;
          case 125:
              std::cout << "lushr\n";
              break;
          case 126:
              std::cout << "iand\n";
              break;
          case 127:
              std::cout << "land\n";
              break;
          case 128:
              std::cout << "ior\n";
              break;
          case 129:
              std::cout << "lor\n";
              break;
          case 130:
              std::cout << "ixor\n";
              break;
          case 131:
              std::cout << "lxor\n";
              break;
          case 132:
              std::cout << "iinc\n";
              break;
          case 133:
              std::cout << "i2l\n";
              break;
          case 134:
              std::cout << "i2f\n";
              break;
          case 135:
              std::cout << "i2d\n";
              break;
          case 136:
              std::cout << "l2i\n";
              break;
          case 137:
              std::cout << "l2f\n";
              break;
          case 138:
              std::cout << "l2d\n";
              break;
          case 139:
              std::cout << "f2i\n";
              break;
          case 140:
              std::cout << "f2l\n";
              break;
          case 141:
              std::cout << "f2d\n";
              break;
          case 142:
              std::cout << "d2i\n";
              break;
          case 143:
              std::cout << "d2l\n";
              break;
          case 144:
              std::cout << "d2f\n";
              break;
          case 145:
              std::cout << "i2b\n";
              break;
          case 146:
              std::cout << "i2c\n";
              break;
          case 147:
              std::cout << "i2s\n";
              break;
          case 148:
              std::cout << "lcmp\n";
              break;
          case 149:
              std::cout << "fcmpl\n";
              break;
          case 150:
              std::cout << "fcmpg\n";
              break;
          case 151:
              std::cout << "dcmpl\n";
              break;
          case 152:
              std::cout << "dcmpg\n";
              break;
          case 153:
              std::cout << "ifeq\n";
              break;
          case 154:
              std::cout << "ifne\n";
              break;
          case 155:
              std::cout << "iflt\n";
              break;
          case 156:
              std::cout << "ifge\n";
              break;
          case 157:
              std::cout << "ifgt\n";
              break;
          case 158:
              std::cout << "ifle\n";
              break;
          case 159:
              std::cout << "if_icmpeq\n";
              break;
          case 160:
              std::cout << "if_icmpne\n";
              break;
          case 161:
              std::cout << "if_icmplt\n";
              break;
          case 162:
              std::cout << "if_icmpge\n";
              break;
          case 163:
              std::cout << "if_icmpgt\n";
              break;
          case 164:
              std::cout << "if_icmple\n";
              break;
          case 165:
              std::cout << "if_acmpeq\n";
              break;
          case 166:
              std::cout << "if_acmpne\n";
              break;
          case 167:
              std::cout << "goto\n";
              break;
          case 168:
              std::cout << "jsr\n";
              break;
          case 169:
              std::cout << "ret\n";
              break;
          case 170:
              std::cout << "tableswitch\n";
              break;
          case 171:
              std::cout << "lookupswitch\n";
              break;
          case 172:
              std::cout << "ireturn\n";
              break;
          case 173:
              std::cout << "lreturn\n";
              break;
          case 174:
              std::cout << "freturn\n";
              break;
          case 175:
              std::cout << "dreturn\n";
              break;
          case 176:
              std::cout << "areturn\n";
              break;
          case 177:
              std::cout << "return\n";
              break;
          case 178:
              std::cout << "getstatic\n";
              break;
          case 179:
              std::cout << "putstatic\n";
              break;
          case 180:
              std::cout << "getfield\n";
              break;
          case 181:
              std::cout << "putfield\n";
              break;
          case 182:
              std::cout << "invokevirtual\n";
              break;
          case 183:
              std::cout << "invokespecial\n";
              break;
          case 184:
              std::cout << "invokestatic\n";
              break;
          case 185:
              std::cout << "invokeinterface\n";
              break;
          case 186:
              std::cout << "invokedynamic\n";
              break;
          case 187:
              std::cout << "new\n";
              break;
          case 188:
              std::cout << "newarray\n";
              break;
          case 189:
              std::cout << "anewarray\n";
              break;
          case 190:
              std::cout << "arraylength\n";
              break;
          case 191:
              std::cout << "athrow\n";
              break;
          case 192:
              std::cout << "checkcast\n";
              break;
          case 193:
              std::cout << "instanceof\n";
              break;
          case 194:
              std::cout << "monitorenter\n";
              break;
          case 195:
              std::cout << "monitorexit\n";
              break;
          case 196:
              std::cout << "wide\n";
              break;
          case 197:
              std::cout << "multianewarray\n";
              break;
          case 198:
              std::cout << "ifnull\n";
              break;
          case 199:
              std::cout << "ifnonnull\n";
              break;
          case 200:
              std::cout << "goto_w\n";
              break;
          case 201:
              std::cout << "jsr_w\n";
              break;
          case 202:
              std::cout << "breakpoint\n";
              break;
          case 254:
              std::cout << "impdep1\n";
              break;
          case 255:
              std::cout << "impdep2\n";
              break;
          default:
              std::cout << "Invalid opcode detected!\n";
      }
  }
  