public void simulateTimeChange(long offsetToAddInMillis) {
    ImmutableMap.Builder<Long, Event> eventMapBuilder = ImmutableMap.builder();
    for (Event event : eventsByTimeStamp.values()) {
      long newTimestamp = event.getTimeStamp() + offsetToAddInMillis;
      eventMapBuilder.put(
          newTimestamp, EventBuilder.fromEvent(event).setTimeStamp(newTimestamp).build());
    }
    eventsByTimeStamp.putAll(eventMapBuilder.build());
  }

public void simulateTimeChange ( long offsetToAddInMillis ) { ImmutableMap . Builder < Long , Event > eventMapBuilder = ImmutableMap . builder ( ) ; for ( Event event : eventsByTimeStamp . values ( ) ) { long newTimestamp = event . getTimeStamp ( ) + offsetToAddInMillis ; eventMapBuilder . put ( newTimestamp , EventBuilder . fromEvent ( event ) . setTimeStamp ( newTimestamp ) . build ( ) ) ; } eventsByTimeStamp . putAll ( eventMapBuilder . build ( ) ) ; }

Simulates the operations done by the framework when there is a time change. If the time is
changed, the timestamps of all existing usage events will be shifted by the same offset as the
time change, in order to make sure they remain stable relative to the new time.

<p>This method won't affect the results of {@link #queryUsageStats} method.

@param offsetToAddInMillis the offset to be applied to all events. For example, if {@code
offsetInMillis} is 60,000, then all {@link Event}s will be shifted forward by 1 minute
(into the future). Likewise, if {@code offsetInMillis} is -60,000, then all {@link Event}s
will be shifted backward by 1 minute (into the past).

Simulates the operations done by the framework when there is a time change . If the time is changed the timestamps of all existing usage events will be shifted by the same offset as the time change in order to make sure they remain stable relative to the new time .


private static Bundle metaDataToBundle(Map<String, Object> meta) {
    if (meta.size() == 0) {
      return null;
    }

    Bundle bundle = new Bundle();

    for (Map.Entry<String, Object> entry : meta.entrySet()) {
      String key = entry.getKey();
      Object value = entry.getValue();
      if (Boolean.class.isInstance(value)) {
        bundle.putBoolean(key, (Boolean) value);
      } else if (Float.class.isInstance(value)) {
        bundle.putFloat(key, (Float) value);
      } else if (Integer.class.isInstance(value)) {
        bundle.putInt(key, (Integer) value);
      } else {
        bundle.putString(key, value == null ? null : value.toString());
      }
    }
    return bundle;
  }

private static Bundle metaDataToBundle ( Map < String , Object > meta ) { if ( meta . size ( ) == 0 ) { return null ; } Bundle bundle = new Bundle ( ) ; for ( Map . Entry < String , Object > entry : meta . entrySet ( ) ) { String key = entry . getKey ( ) ; Object value = entry . getValue ( ) ; if ( Boolean . class . isInstance ( value ) ) { bundle . putBoolean ( key , ( Boolean ) value ) ; } else if ( Float . class . isInstance ( value ) ) { bundle . putFloat ( key , ( Float ) value ) ; } else if ( Integer . class . isInstance ( value ) ) { bundle . putInt ( key , ( Integer ) value ) ; } else { bundle . putString ( key , value == null ? null : value . toString ( ) ) ; } } return bundle ; }

Goes through the meta data and puts each value in to a bundle as the correct type.

<p>Note that this will convert resource identifiers specified via the value attribute as well.

@param meta Meta data to put in to a bundle
@return bundle containing the meta data

Goes through the meta data and puts each value in to a bundle as the correct type .


static String convertSQLWithLocalizedUnicodeCollator(String sql) {
    Matcher matcher = COLLATE_LOCALIZED_UNICODE_PATTERN.matcher(sql);
    return matcher.replaceAll(" COLLATE NOCASE");
  }

static
String
convertSQLWithLocalizedUnicodeCollator
(
String
sql
)
{
Matcher
matcher
=
COLLATE_LOCALIZED_UNICODE_PATTERN
.
matcher
(
sql
)
;
return
matcher
.
replaceAll
(
" COLLATE NOCASE"
)
;
}

Convert SQL with phrase COLLATE LOCALIZED or COLLATE UNICODE to COLLATE NOCASE.

Convert SQL with phrase COLLATE LOCALIZED or COLLATE UNICODE to COLLATE NOCASE .


private static PackageInfo newPackageInfo(PackageInfo orig) {
    Parcel parcel = Parcel.obtain();
    orig.writeToParcel(parcel, 0);
    parcel.setDataPosition(0);
    return PackageInfo.CREATOR.createFromParcel(parcel);
  }

private static PackageInfo newPackageInfo ( PackageInfo orig ) { Parcel parcel = Parcel . obtain ( ) ; orig . writeToParcel ( parcel , 0 ) ; parcel . setDataPosition ( 0 ) ; return PackageInfo . CREATOR . createFromParcel ( parcel ) ; }

There is no copy constructor for PackageInfo


private boolean isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo) {
    // Note: it might be cleaner to auto-grant these permissions when the package is added to the
    // PackageManager. But many existing tests modify the requested permissions _after_ adding the
    // package to the PackageManager, without updating the requestedPermissionsFlags.
    return permissionsInfo.requestedPermissionsFlags == null
        // Robolectric uses the PackageParser to create the current test package's PackageInfo from
        // the manifest XML. The parser populates the requestedPermissionsFlags, but doesn't grant
        // the permissions. Several tests rely on the test package being granted all permissions, so
        // we treat this as a special case.
        || pkgName.equals(RuntimeEnvironment.application.getPackageName());
  }

Returns whether a permission should be treated as granted to the package for backward
compatibility reasons.

Before Robolectric 4.0 the ShadowPackageManager treated every requested permission as
automatically granted. 4.0 changes this behavior, and only treats a permission as granted if
PackageInfo.requestedPermissionFlags[permissionIndex] & REQUESTED_PERMISSION_GRANTED ==
REQUESTED_PERMISSION_GRANTED which matches the real PackageManager's behavior.

Since many existing tests didn't set the requestedPermissionFlags on their {@code
PackageInfo} objects, but assumed that all permissions are granted, we auto-grant all
permissions if the requestedPermissionFlags is not set. If the requestedPermissionFlags is set,
we assume that the test is configuring the permission grant state, and we don't override this
setting.

Returns whether a permission should be treated as granted to the package for backward compatibility reasons .


private void applyFlagsToComponentInfo(ComponentInfo componentInfo, int flags)
      throws NameNotFoundException {
    componentInfo.name = (componentInfo.name == null) ? "" : componentInfo.name;
    ApplicationInfo applicationInfo = componentInfo.applicationInfo;
    boolean isApplicationEnabled = true;
    if (applicationInfo != null) {
      if (applicationInfo.packageName == null) {
        applicationInfo.packageName = componentInfo.packageName;
      }
      applyFlagsToApplicationInfo(componentInfo.applicationInfo, flags);
      componentInfo.packageName = applicationInfo.packageName;
      isApplicationEnabled = applicationInfo.enabled;
    }
    if ((flags & GET_META_DATA) == 0) {
      componentInfo.metaData = null;
    }
    boolean isComponentEnabled = isComponentEnabled(componentInfo);
    if ((flags & MATCH_ALL) != 0 && Build.VERSION.SDK_INT >= 23) {
      return;
    }
    // Android don't override the enabled field of component with the actual value.
    boolean isEnabledForFiltering =
        isComponentEnabled
            && (Build.VERSION.SDK_INT >= 24 ? isApplicationEnabled : true);
    if ((flags & MATCH_DISABLED_COMPONENTS) == 0 && !isEnabledForFiltering) {
      throw new NameNotFoundException("Disabled component: " + componentInfo);
    }
    if (isFlagSet(flags, PackageManager.MATCH_SYSTEM_ONLY)) {
      if (applicationInfo == null) {
        // TODO: for backwards compatibility just skip filtering. In future should just remove
        // invalid resolve infos from list
      } else {
        final int applicationFlags = applicationInfo.flags;
        if ((applicationFlags & ApplicationInfo.FLAG_SYSTEM) != ApplicationInfo.FLAG_SYSTEM) {
          throw new NameNotFoundException("Not system component: " + componentInfo);
        }
      }
    }
    if (!isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)
        && isValidComponentInfo(componentInfo)
        && hiddenPackages.contains(componentInfo.applicationInfo.packageName)) {
      throw new NameNotFoundException("Uninstalled package: " + componentInfo);
    }
  }

Modifies the component in place using.

@throws NameNotFoundException when component is filtered out by a flag


private int getPermissionIndex(PackageInfo packageInfo, String permissionName) {
    if (packageInfo.requestedPermissions != null) {
      for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
        if (permissionName.equals(packageInfo.requestedPermissions[i])) {
          return i;
        }
      }
    }

    return -1;
  }

private int getPermissionIndex ( PackageInfo packageInfo , String permissionName ) { if ( packageInfo . requestedPermissions != null ) { for ( int i = 0 ; i < packageInfo . requestedPermissions . length ; i ++ ) { if ( permissionName . equals ( packageInfo . requestedPermissions [ i ] ) ) { return i ; } } } return - 1 ; }

Returns the index of the given permission in the PackageInfo.requestedPermissions array, or -1
if it's not found.

Returns the index of the given permission in the PackageInfo . requestedPermissions array or - 1 if it s not found .


@Implementation(minSdk = LOLLIPOP)
  protected Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
    return icon;
  }

@ Implementation ( minSdk = LOLLIPOP ) protected Drawable getUserBadgedIcon ( Drawable icon , UserHandle user ) { return icon ; }

Adds a profile badge to the icon.

This implementation just returns the unbadged icon, as some default implementations add an
internal resource to the icon that is unavailable to Robolectric.


private boolean hasProfileOwnerOrDeviceOwnerOnCurrentUser() {
    DevicePolicyManager devicePolicyManager =
        (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    return devicePolicyManager.getProfileOwner() != null
        || (UserHandle.of(UserHandle.myUserId()).isSystem()
            && devicePolicyManager.getDeviceOwner() != null);
  }

Returns whether the current user profile has a profile owner or a device owner.

Returns whether the current user profile has a profile owner or a device owner .


private static char[] extractCodePoint(String codePoint) {
    try {
      return Character.toChars(Integer.valueOf(codePoint, 16));
    } catch (IllegalArgumentException e) {
      // This may be caused by NumberFormatException of Integer.valueOf() or
      // IllegalArgumentException of Character.toChars().
      throw new IllegalArgumentException("Invalid code point: \\u" + codePoint, e);
    }
  }

Converts code points in a given string to actual characters. This method doesn't handle code
points whose char counts are 2. In other words, this method doesn't handle U+10XXXX.

Converts code points in a given string to actual characters . This method doesn t handle code points whose char counts are 2 . In other words this method doesn t handle U + 10XXXX .


public static <T> T reflector(Class<T> iClass, Object target) {
    Class<?> targetClass = determineTargetClass(iClass);

    Constructor<? extends T> ctor = (Constructor<? extends T>) CACHE.get(iClass);
    try {
      if (ctor == null) {
        Class<? extends T> reflectorClass = createReflectorClass(iClass, targetClass);
        ctor = reflectorClass.getConstructor(targetClass);
        ctor.setAccessible(true);
      }

      CACHE.put(iClass, ctor);

      return ctor.newInstance(target);
    } catch (NoSuchMethodException
        | InstantiationException
        | IllegalAccessException
        | InvocationTargetException e) {
      throw new IllegalStateException(e);
    }
  }

public static < T > T reflector ( Class < T > iClass , Object target ) { Class < ? > targetClass = determineTargetClass ( iClass ) ; Constructor < ? extends T > ctor = ( Constructor < ? extends T > ) CACHE . get ( iClass ) ; try { if ( ctor == null ) { Class < ? extends T > reflectorClass = createReflectorClass ( iClass , targetClass ) ; ctor = reflectorClass . getConstructor ( targetClass ) ; ctor . setAccessible ( true ) ; } CACHE . put ( iClass , ctor ) ; return ctor . newInstance ( target ) ; } catch ( NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e ) { throw new IllegalStateException ( e ) ; } }

Returns an object which provides accessors for invoking otherwise inaccessible methods and
fields.

@param iClass an interface with methods matching private methods on the target
@param target the target object

Returns an object which provides accessors for invoking otherwise inaccessible methods and fields .


public static Status getStatus(Account account, String authority, boolean create) {
    Map<Account, Status> map = syncableAccounts.get(authority);
    if (map == null) {
      map = new HashMap<>();
      syncableAccounts.put(authority, map);
    }
    Status status = map.get(account);
    if (status == null && create) {
      status = new Status();
      map.put(account, status);
    }
    return status;
  }

public static Status getStatus ( Account account , String authority , boolean create ) { Map < Account , Status > map = syncableAccounts . get ( authority ) ; if ( map == null ) { map = new HashMap <> ( ) ; syncableAccounts . put ( authority , map ) ; } Status status = map . get ( account ) ; if ( status == null && create ) { status = new Status ( ) ; map . put ( account , status ) ; } return status ; }

Retrieve information on the status of the given account.

@param account the account
@param authority the authority
@param create whether to create if no such account is found
@return the account's status

Retrieve information on the status of the given account .


public Collection<ContentObserver> getContentObservers(Uri uri) {
    ArrayList<ContentObserver> observers = new ArrayList<>(1);
    for (ContentObserverEntry entry : contentObservers) {
      if (entry.matches(uri)) {
        observers.add(entry.observer);
      }
    }
    return observers;
  }

public Collection < ContentObserver > getContentObservers ( Uri uri ) { ArrayList < ContentObserver > observers = new ArrayList <> ( 1 ) ; for ( ContentObserverEntry entry : contentObservers ) { if ( entry . matches ( uri ) ) { observers . add ( entry . observer ) ; } } return observers ; }

Returns the content observers registered for updates under the given URI.

Will be empty if no observer is registered.

@param uri Given URI
@return The content observers, or null

Returns the content observers registered for updates under the given URI .


public static int addDisplay(String qualifiersStr) {
    int id = getShadowDisplayManagerGlobal().addDisplay(createDisplayInfo(qualifiersStr, null));
    shadowMainLooper().idle();
    return id;
  }

public static int addDisplay ( String qualifiersStr ) { int id = getShadowDisplayManagerGlobal ( ) . addDisplay ( createDisplayInfo ( qualifiersStr , null ) ) ; shadowMainLooper ( ) . idle ( ) ; return id ; }

Adds a simulated display and drain the main looper queue to ensure all the callbacks are
processed.

@param qualifiersStr the {@link Qualifiers} string representing characteristics of the new
display.
@return the new display's ID

Adds a simulated display and drain the main looper queue to ensure all the callbacks are processed .


static void changeDisplay(int displayId, Consumer<DisplayConfig> consumer) {
    DisplayInfo displayInfo = DisplayManagerGlobal.getInstance().getDisplayInfo(displayId);
    if (displayInfo != null) {
      DisplayConfig displayConfig = new DisplayConfig(displayInfo);
      consumer.accept(displayConfig);
      displayConfig.copyTo(displayInfo);
      fixNominalDimens(displayInfo);
    }

    getShadowDisplayManagerGlobal().changeDisplay(displayId, displayInfo);
  }

static void changeDisplay ( int displayId , Consumer < DisplayConfig > consumer ) { DisplayInfo displayInfo = DisplayManagerGlobal . getInstance ( ) . getDisplayInfo ( displayId ) ; if ( displayInfo != null ) { DisplayConfig displayConfig = new DisplayConfig ( displayInfo ) ; consumer . accept ( displayConfig ) ; displayConfig . copyTo ( displayInfo ) ; fixNominalDimens ( displayInfo ) ; } getShadowDisplayManagerGlobal ( ) . changeDisplay ( displayId , displayInfo ) ; }

Changes properties of a simulated display. The original properties will be passed to the
`consumer`, which may modify them in place. The display will be updated with the new
properties.

@param displayId the display id to change
@param consumer a function which modifies the display properties

Changes properties of a simulated display . The original properties will be passed to the consumer which may modify them in place . The display will be updated with the new properties .


private static String fixTracePath(String tracePath) {
    String defaultTraceBody = "dmtrace";
    String defaultTraceExtension = ".trace";

    if (tracePath == null || tracePath.charAt(0) != '/') {
      final File dir = RuntimeEnvironment.application.getExternalFilesDir(null);
      if (tracePath == null) {
        tracePath = new File(dir, defaultTraceBody).getAbsolutePath();
      } else {
        tracePath = new File(dir, tracePath).getAbsolutePath();
      }
    }
    if (!tracePath.endsWith(defaultTraceExtension)) {
      tracePath += defaultTraceExtension;
    }
    return tracePath;
  }

private static String fixTracePath ( String tracePath ) { String defaultTraceBody = "dmtrace" ; String defaultTraceExtension = ".trace" ; if ( tracePath == null || tracePath . charAt ( 0 ) != ' ' ) { final File dir = RuntimeEnvironment . application . getExternalFilesDir ( null ) ; if ( tracePath == null ) { tracePath = new File ( dir , defaultTraceBody ) . getAbsolutePath ( ) ; } else { tracePath = new File ( dir , tracePath ) . getAbsolutePath ( ) ; } } if ( ! tracePath . endsWith ( defaultTraceExtension ) ) { tracePath += defaultTraceExtension ; } return tracePath ; }


private int findNext(BitSet bits, int value, Calendar calendar, int field, int nextField, List<Integer> lowerOrders) {
		int nextValue = bits.nextSetBit(value);
		// roll over if needed
		if (nextValue == -1) {
			calendar.add(nextField, 1);
			reset(calendar, Arrays.asList(field));
			nextValue = bits.nextSetBit(0);
		}
		if (nextValue != value) {
			calendar.set(field, nextValue);
			reset(calendar, lowerOrders);
		}
		return nextValue;
	}

private
int
findNext
(
BitSet
bits
,
int
value
,
Calendar
calendar
,
int
field
,
int
nextField
,
List
<
Integer
>
lowerOrders
)
{
int
nextValue
=
bits
.
nextSetBit
(
value
)
;
// roll over if needed
if
(
nextValue
==
1
)
{
calendar
.
add
(
nextField
,
1
)
;
reset
(
calendar
,
Arrays
.
asList
(
field
)
)
;
nextValue
=
bits
.
nextSetBit
(
0
)
;
}
if
(
nextValue
!=
value
)
{
calendar
.
set
(
field
,
nextValue
)
;
reset
(
calendar
,
lowerOrders
)
;
}
return
nextValue
;
}

Search the bits provided for the next set bit after the value provided,
and reset the calendar.
@param bits a {@link BitSet} representing the allowed values of the field
@param value the current value of the field
@param calendar the calendar to increment as we move through the bits
@param field the field to increment in the calendar (@see
{@link Calendar} for the static constants defining valid fields)
@param lowerOrders the Calendar field ids that should be reset (i.e. the
ones of lower significance than the field of interest)
@return the value of the calendar field that is next in the sequence

Search the bits provided for the next set bit after the value provided and reset the calendar .


private void reset(Calendar calendar, List<Integer> fields) {
		for (int field : fields) {
			calendar.set(field, field == Calendar.DAY_OF_MONTH ? 1 : 0);
		}
	}

private void reset ( Calendar calendar , List < Integer > fields ) { for ( int field : fields ) { calendar . set ( field , field == Calendar . DAY_OF_MONTH ? 1 : 0 ) ; } }

Reset the calendar setting all the fields provided to zero.

Reset the calendar setting all the fields provided to zero .


private void parse(String expression) throws IllegalArgumentException {
		String[] fields = Strings.splitIgnoreBlank(expression, " ");
		if (fields.length != 6) {
			throw new IllegalArgumentException(String.format(
					"Cron expression must consist of 6 fields (found %d in \"%s\")", fields.length, expression));
		}
		setNumberHits(this.seconds, fields[0], 0, 60);
		setNumberHits(this.minutes, fields[1], 0, 60);
		setNumberHits(this.hours, fields[2], 0, 24);
		setDaysOfMonth(this.daysOfMonth, fields[3]);
		setMonths(this.months, fields[4]);
		setDays(this.daysOfWeek, replaceOrdinals(fields[5], "SUN,MON,TUE,WED,THU,FRI,SAT"), 8);
		if (this.daysOfWeek.get(7)) {
			// Sunday can be represented as 0 or 7
			this.daysOfWeek.set(0);
			this.daysOfWeek.clear(7);
		}
	}


private int getArgIndex(final int arg) {
        int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
        for (int i = 0; i < arg; i++) {
            index += argumentTypes[i].getSize();
        }
        return index;
    }

private int getArgIndex ( final int arg ) { int index = ( access & Opcodes . ACC_STATIC ) == 0 ? 1 : 0 ; for ( int i = 0 ; i < arg ; i ++ ) { index += argumentTypes [ i ] . getSize ( ) ; } return index ; }

Returns the index of the given method argument in the frame's local
variables array.

@param arg
the index of a method argument.
@return the index of the given method argument in the frame's local
variables array.

Returns the index of the given method argument in the frame s local variables array .


private void loadInsn(final Type type, final int index) {
        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
    }

private void loadInsn ( final Type type , final int index ) { mv . visitVarInsn ( type . getOpcode ( Opcodes . ILOAD ) , index ) ; }

Generates the instruction to push a local variable on the stack.

@param type
the type of the local variable to be loaded.
@param index
an index in the frame's local variables array.

Generates the instruction to push a local variable on the stack .


private void storeInsn(final Type type, final int index) {
        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
    }

private void storeInsn ( final Type type , final int index ) { mv . visitVarInsn ( type . getOpcode ( Opcodes . ISTORE ) , index ) ; }

Generates the instruction to store the top stack value in a local
variable.

@param type
the type of the local variable to be stored.
@param index
an index in the frame's local variables array.

Generates the instruction to store the top stack value in a local variable .


public void loadArgs(final int arg, final int count) {
        int index = getArgIndex(arg);
        for (int i = 0; i < count; ++i) {
            Type t = argumentTypes[arg + i];
            loadInsn(t, index);
            index += t.getSize();
        }
    }

public void loadArgs ( final int arg , final int count ) { int index = getArgIndex ( arg ) ; for ( int i = 0 ; i < count ; ++ i ) { Type t = argumentTypes [ arg + i ] ; loadInsn ( t , index ) ; index += t . getSize ( ) ; } }

Generates the instructions to load the given method arguments on the
stack.

@param arg
the index of the first method argument to be loaded.
@param count
the number of method arguments to be loaded.

Generates the instructions to load the given method arguments on the stack .


public void loadArgArray() {
        push(argumentTypes.length);
        newArray(OBJECT_TYPE);
        for (int i = 0; i < argumentTypes.length; i++) {
            dup();
            push(i);
            loadArg(i);
            box(argumentTypes[i]);
            arrayStore(OBJECT_TYPE);
        }
    }

public void loadArgArray ( ) { push ( argumentTypes . length ) ; newArray ( OBJECT_TYPE ) ; for ( int i = 0 ; i < argumentTypes . length ; i ++ ) { dup ( ) ; push ( i ) ; loadArg ( i ) ; box ( argumentTypes [ i ] ) ; arrayStore ( OBJECT_TYPE ) ; } }

Generates the instructions to load all the method arguments on the stack,
as a single object array.

Generates the instructions to load all the method arguments on the stack as a single object array .


public void loadLocal(final int local, final Type type) {
        setLocalType(local, type);
        loadInsn(type, local);
    }

public void loadLocal ( final int local , final Type type ) { setLocalType ( local , type ) ; loadInsn ( type , local ) ; }

Generates the instruction to load the given local variable on the stack.

@param local
a local variable identifier, as returned by
{@link LocalVariablesSorter#newLocal(Type) newLocal()}.
@param type
the type of this local variable.

Generates the instruction to load the given local variable on the stack .


public void storeLocal(final int local, final Type type) {
        setLocalType(local, type);
        storeInsn(type, local);
    }

public void storeLocal ( final int local , final Type type ) { setLocalType ( local , type ) ; storeInsn ( type , local ) ; }

Generates the instruction to store the top stack value in the given local
variable.

@param local
a local variable identifier, as returned by
{@link LocalVariablesSorter#newLocal(Type) newLocal()}.
@param type
the type of this local variable.

Generates the instruction to store the top stack value in the given local variable .


public void swap(final Type prev, final Type type) {
        if (type.getSize() == 1) {
            if (prev.getSize() == 1) {
                swap(); // same as dupX1(), pop();
            } else {
                dupX2();
                pop();
            }
        } else {
            if (prev.getSize() == 1) {
                dup2X1();
                pop2();
            } else {
                dup2X2();
                pop2();
            }
        }
    }

public
void
swap
(
final
Type
prev
,
final
Type
type
)
{
if
(
type
.
getSize
(
)
==
1
)
{
if
(
prev
.
getSize
(
)
==
1
)
{
swap
(
)
;
// same as dupX1(), pop();
}
else
{
dupX2
(
)
;
pop
(
)
;
}
}
else
{
if
(
prev
.
getSize
(
)
==
1
)
{
dup2X1
(
)
;
pop2
(
)
;
}
else
{
dup2X2
(
)
;
pop2
(
)
;
}
}
}

Generates the instructions to swap the top two stack values.

@param prev
type of the top - 1 stack value.
@param type
type of the top stack value.

Generates the instructions to swap the top two stack values .


public void box(final Type type) {
        if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
            return;
        }
        if (type == Type.VOID_TYPE) {
            push((String) null);
        } else {
            Type boxed = getBoxedType(type);
            newInstance(boxed);
            if (type.getSize() == 2) {
                // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
                dupX2();
                dupX2();
                pop();
            } else {
                // p -> po -> opo -> oop -> o
                dupX1();
                swap();
            }
            invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
                    new Type[] { type }));
        }
    }

Generates the instructions to box the top stack value. This value is
replaced by its boxed equivalent on top of the stack.

@param type
the type of the top stack value.

Generates the instructions to box the top stack value . This value is replaced by its boxed equivalent on top of the stack .


public void unbox(final Type type) {
        Type t = NUMBER_TYPE;
        Method sig = null;
        switch (type.getSort()) {
        case Type.VOID:
            return;
        case Type.CHAR:
            t = CHARACTER_TYPE;
            sig = CHAR_VALUE;
            break;
        case Type.BOOLEAN:
            t = BOOLEAN_TYPE;
            sig = BOOLEAN_VALUE;
            break;
        case Type.DOUBLE:
            sig = DOUBLE_VALUE;
            break;
        case Type.FLOAT:
            sig = FLOAT_VALUE;
            break;
        case Type.LONG:
            sig = LONG_VALUE;
            break;
        case Type.INT:
        case Type.SHORT:
        case Type.BYTE:
            sig = INT_VALUE;
        }
        if (sig == null) {
            checkCast(type);
        } else {
            checkCast(t);
            invokeVirtual(t, sig);
        }
    }

public void unbox ( final Type type ) { Type t = NUMBER_TYPE ; Method sig = null ; switch ( type . getSort ( ) ) { case Type . VOID : return ; case Type . CHAR : t = CHARACTER_TYPE ; sig = CHAR_VALUE ; break ; case Type . BOOLEAN : t = BOOLEAN_TYPE ; sig = BOOLEAN_VALUE ; break ; case Type . DOUBLE : sig = DOUBLE_VALUE ; break ; case Type . FLOAT : sig = FLOAT_VALUE ; break ; case Type . LONG : sig = LONG_VALUE ; break ; case Type . INT : case Type . SHORT : case Type . BYTE : sig = INT_VALUE ; } if ( sig == null ) { checkCast ( type ) ; } else { checkCast ( t ) ; invokeVirtual ( t , sig ) ; } }

Generates the instructions to unbox the top stack value. This value is
replaced by its unboxed equivalent on top of the stack.

@param type
the type of the top stack value.

Generates the instructions to unbox the top stack value . This value is replaced by its unboxed equivalent on top of the stack .


public void ifCmp(final Type type, final int mode, final Label label) {
        switch (type.getSort()) {
        case Type.LONG:
            mv.visitInsn(Opcodes.LCMP);
            break;
        case Type.DOUBLE:
            mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
                    : Opcodes.DCMPG);
            break;
        case Type.FLOAT:
            mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
                    : Opcodes.FCMPG);
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            switch (mode) {
            case EQ:
                mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
                return;
            case NE:
                mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
                return;
            }
            throw new IllegalArgumentException("Bad comparison for type "
                    + type);
        default:
            int intOp = -1;
            switch (mode) {
            case EQ:
                intOp = Opcodes.IF_ICMPEQ;
                break;
            case NE:
                intOp = Opcodes.IF_ICMPNE;
                break;
            case GE:
                intOp = Opcodes.IF_ICMPGE;
                break;
            case LT:
                intOp = Opcodes.IF_ICMPLT;
                break;
            case LE:
                intOp = Opcodes.IF_ICMPLE;
                break;
            case GT:
                intOp = Opcodes.IF_ICMPGT;
                break;
            }
            mv.visitJumpInsn(intOp, label);
            return;
        }
        mv.visitJumpInsn(mode, label);
    }

public
void
ifCmp
(
final
Type
type
,
final
int
mode
,
final
Label
label
)
{
switch
(
type
.
getSort
(
)
)
{
case
Type
.
LONG
:
mv
.
visitInsn
(
Opcodes
.
LCMP
)
;
break
;
case
Type
.
DOUBLE
:
mv
.
visitInsn
(
mode
==
GE
||
mode
==
GT
Opcodes
.
DCMPL
:
Opcodes
.
DCMPG
)
;
break
;
case
Type
.
FLOAT
:
mv
.
visitInsn
(
mode
==
GE
||
mode
==
GT
Opcodes
.
FCMPL
:
Opcodes
.
FCMPG
)
;
break
;
case
Type
.
ARRAY
:
case
Type
.
OBJECT
:
switch
(
mode
)
{
case
EQ
:
mv
.
visitJumpInsn
(
Opcodes
.
IF_ACMPEQ
,
label
)
;
return
;
case
NE
:
mv
.
visitJumpInsn
(
Opcodes
.
IF_ACMPNE
,
label
)
;
return
;
}
throw
new
IllegalArgumentException
(
"Bad comparison for type "
+
type
)
;
default
:
int
intOp
=
1
;
switch
(
mode
)
{
case
EQ
:
intOp
=
Opcodes
.
IF_ICMPEQ
;
break
;
case
NE
:
intOp
=
Opcodes
.
IF_ICMPNE
;
break
;
case
GE
:
intOp
=
Opcodes
.
IF_ICMPGE
;
break
;
case
LT
:
intOp
=
Opcodes
.
IF_ICMPLT
;
break
;
case
LE
:
intOp
=
Opcodes
.
IF_ICMPLE
;
break
;
case
GT
:
intOp
=
Opcodes
.
IF_ICMPGT
;
break
;
}
mv
.
visitJumpInsn
(
intOp
,
label
)
;
return
;
}
mv
.
visitJumpInsn
(
mode
,
label
)
;
}

Generates the instructions to jump to a label based on the comparison of
the top two stack values.

@param type
the type of the top two stack values.
@param mode
how these values must be compared. One of EQ, NE, LT, GE, GT,
LE.
@param label
where to jump if the comparison result is <tt>true</tt>.

Generates the instructions to jump to a label based on the comparison of the top two stack values .


private void fieldInsn(final int opcode, final Type ownerType,
            final String name, final Type fieldType) {
        mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
                fieldType.getDescriptor());
    }

private void fieldInsn ( final int opcode , final Type ownerType , final String name , final Type fieldType ) { mv . visitFieldInsn ( opcode , ownerType . getInternalName ( ) , name , fieldType . getDescriptor ( ) ) ; }

Generates a get field or set field instruction.

@param opcode
the instruction's opcode.
@param ownerType
the class in which the field is defined.
@param name
the name of the field.
@param fieldType
the type of the field.

Generates a get field or set field instruction .


public void getStatic(final Type owner, final String name, final Type type) {
        fieldInsn(Opcodes.GETSTATIC, owner, name, type);
    }

public void getStatic ( final Type owner , final String name , final Type type ) { fieldInsn ( Opcodes . GETSTATIC , owner , name , type ) ; }

Generates the instruction to push the value of a static field on the
stack.

@param owner
the class in which the field is defined.
@param name
the name of the field.
@param type
the type of the field.

Generates the instruction to push the value of a static field on the stack .


public void putStatic(final Type owner, final String name, final Type type) {
        fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
    }

public void putStatic ( final Type owner , final String name , final Type type ) { fieldInsn ( Opcodes . PUTSTATIC , owner , name , type ) ; }

Generates the instruction to store the top stack value in a static field.

@param owner
the class in which the field is defined.
@param name
the name of the field.
@param type
the type of the field.

Generates the instruction to store the top stack value in a static field .


public void getField(final Type owner, final String name, final Type type) {
        fieldInsn(Opcodes.GETFIELD, owner, name, type);
    }

public void getField ( final Type owner , final String name , final Type type ) { fieldInsn ( Opcodes . GETFIELD , owner , name , type ) ; }

Generates the instruction to push the value of a non static field on the
stack.

@param owner
the class in which the field is defined.
@param name
the name of the field.
@param type
the type of the field.

Generates the instruction to push the value of a non static field on the stack .


public void putField(final Type owner, final String name, final Type type) {
        fieldInsn(Opcodes.PUTFIELD, owner, name, type);
    }

public void putField ( final Type owner , final String name , final Type type ) { fieldInsn ( Opcodes . PUTFIELD , owner , name , type ) ; }

Generates the instruction to store the top stack value in a non static
field.

@param owner
the class in which the field is defined.
@param name
the name of the field.
@param type
the type of the field.

Generates the instruction to store the top stack value in a non static field .


private void invokeInsn(final int opcode, final Type type,
            final Method method, final boolean itf) {
        String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
                : type.getInternalName();
        mv.visitMethodInsn(opcode, owner, method.getName(),
                method.getDescriptor(), itf);
    }

private void invokeInsn ( final int opcode , final Type type , final Method method , final boolean itf ) { String owner = type . getSort ( ) == Type . ARRAY ? type . getDescriptor ( ) : type . getInternalName ( ) ; mv . visitMethodInsn ( opcode , owner , method . getName ( ) , method . getDescriptor ( ) , itf ) ; }

Generates an invoke method instruction.

@param opcode
the instruction's opcode.
@param type
the class in which the method is defined.
@param method
the method to be invoked.

Generates an invoke method instruction .


public void invokeVirtual(final Type owner, final Method method) {
        invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false);
    }

public void invokeVirtual ( final Type owner , final Method method ) { invokeInsn ( Opcodes . INVOKEVIRTUAL , owner , method , false ) ; }

Generates the instruction to invoke a normal method.

@param owner
the class in which the method is defined.
@param method
the method to be invoked.

Generates the instruction to invoke a normal method .


public void invokeConstructor(final Type type, final Method method) {
        invokeInsn(Opcodes.INVOKESPECIAL, type, method, false);
    }

public void invokeConstructor ( final Type type , final Method method ) { invokeInsn ( Opcodes . INVOKESPECIAL , type , method , false ) ; }

Generates the instruction to invoke a constructor.

@param type
the class in which the constructor is defined.
@param method
the constructor to be invoked.

Generates the instruction to invoke a constructor .


public void invokeStatic(final Type owner, final Method method) {
        invokeInsn(Opcodes.INVOKESTATIC, owner, method, false);
    }

public void invokeStatic ( final Type owner , final Method method ) { invokeInsn ( Opcodes . INVOKESTATIC , owner , method , false ) ; }

Generates the instruction to invoke a static method.

@param owner
the class in which the method is defined.
@param method
the method to be invoked.

Generates the instruction to invoke a static method .


public void invokeInterface(final Type owner, final Method method) {
        invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true);
    }

public void invokeInterface ( final Type owner , final Method method ) { invokeInsn ( Opcodes . INVOKEINTERFACE , owner , method , true ) ; }

Generates the instruction to invoke an interface method.

@param owner
the class in which the method is defined.
@param method
the method to be invoked.

Generates the instruction to invoke an interface method .


public void throwException(final Type type, final String msg) {
        newInstance(type);
        dup();
        push(msg);
        invokeConstructor(type, Method.getMethod("void <init> (String)"));
        throwException();
    }

public
void
throwException
(
final
Type
type
,
final
String
msg
)
{
newInstance
(
type
)
;
dup
(
)
;
push
(
msg
)
;
invokeConstructor
(
type
,
Method
.
getMethod
(
"void <init> (String)"
)
)
;
throwException
(
)
;
}

Generates the instructions to create and throw an exception. The
exception class must have a constructor with a single String argument.

@param type
the class of the exception to be thrown.
@param msg
the detailed message of the exception.

Generates the instructions to create and throw an exception . The exception class must have a constructor with a single String argument .


public void checkCast(final Type type) {
        if (!type.equals(OBJECT_TYPE)) {
            typeInsn(Opcodes.CHECKCAST, type);
        }
    }

public void checkCast ( final Type type ) { if ( ! type . equals ( OBJECT_TYPE ) ) { typeInsn ( Opcodes . CHECKCAST , type ) ; } }

Generates the instruction to check that the top stack value is of the
given type.

@param type
a class or interface type.

Generates the instruction to check that the top stack value is of the given type .


private void visitImplicitFirstFrame() {
        // There can be at most descriptor.length() + 1 locals
        int frameIndex = startFrame(0, descriptor.length() + 1, 0);
        if ((access & Opcodes.ACC_STATIC) == 0) {
            if ((access & ACC_CONSTRUCTOR) == 0) {
                frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
            } else {
                frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
            }
        }
        int i = 1;
        loop: while (true) {
            int j = i;
            switch (descriptor.charAt(i++)) {
            case 'Z':
            case 'C':
            case 'B':
            case 'S':
            case 'I':
                frame[frameIndex++] = 1; // Opcodes.INTEGER;
                break;
            case 'F':
                frame[frameIndex++] = 2; // Opcodes.FLOAT;
                break;
            case 'J':
                frame[frameIndex++] = 4; // Opcodes.LONG;
                break;
            case 'D':
                frame[frameIndex++] = 3; // Opcodes.DOUBLE;
                break;
            case '[':
                while (descriptor.charAt(i) == '[') {
                    ++i;
                }
                if (descriptor.charAt(i) == 'L') {
                    ++i;
                    while (descriptor.charAt(i) != ';') {
                        ++i;
                    }
                }
                frame[frameIndex++] = Frame.OBJECT
                        | cw.addType(descriptor.substring(j, ++i));
                break;
            case 'L':
                while (descriptor.charAt(i) != ';') {
                    ++i;
                }
                frame[frameIndex++] = Frame.OBJECT
                        | cw.addType(descriptor.substring(j + 1, i++));
                break;
            default:
                break loop;
            }
        }
        frame[1] = frameIndex - 3;
        endFrame();
    }

Visit the implicit first frame of this method.

Visit the implicit first frame of this method .


private int startFrame(final int offset, final int nLocal, final int nStack) {
        int n = 3 + nLocal + nStack;
        if (frame == null || frame.length < n) {
            frame = new int[n];
        }
        frame[0] = offset;
        frame[1] = nLocal;
        frame[2] = nStack;
        return 3;
    }

private int startFrame ( final int offset , final int nLocal , final int nStack ) { int n = 3 + nLocal + nStack ; if ( frame == null || frame . length < n ) { frame = new int [ n ] ; } frame [ 0 ] = offset ; frame [ 1 ] = nLocal ; frame [ 2 ] = nStack ; return 3 ; }

Starts the visit of a stack map frame.

@param offset
the offset of the instruction to which the frame corresponds.
@param nLocal
the number of local variables in the frame.
@param nStack
the number of stack elements in the frame.
@return the index of the next element to be written in this frame.


Item newMethodItem(final String owner, final String name,
            final String desc, final boolean itf) {
        int type = itf ? IMETH : METH;
        key3.set(type, owner, name, desc);
        Item result = get(key3);
        if (result == null) {
            put122(type, newClass(owner), newNameType(name, desc));
            result = new Item(index++, key3);
            put(result);
        }
        return result;
    }

Item newMethodItem ( final String owner , final String name , final String desc , final boolean itf ) { int type = itf ? IMETH : METH ; key3 . set ( type , owner , name , desc ) ; Item result = get ( key3 ) ; if ( result == null ) { put122 ( type , newClass ( owner ) , newNameType ( name , desc ) ) ; result = new Item ( index ++ , key3 ) ; put ( result ) ; } return result ; }

Adds a method reference to the constant pool of the class being build.
Does nothing if the constant pool already contains a similar item.

@param owner
the internal name of the method's owner class.
@param name
the method's name.
@param desc
the method's descriptor.
@param itf
<tt>true</tt> if <tt>owner</tt> is an interface.
@return a new or already existing method reference item.

Adds a method reference to the constant pool of the class being build . Does nothing if the constant pool already contains a similar item .


Item newFloat(final float value) {
        key.set(value);
        Item result = get(key);
        if (result == null) {
            pool.putByte(FLOAT).putInt(key.intVal);
            result = new Item(index++, key);
            put(result);
        }
        return result;
    }

Item newFloat ( final float value ) { key . set ( value ) ; Item result = get ( key ) ; if ( result == null ) { pool . putByte ( FLOAT ) . putInt ( key . intVal ) ; result = new Item ( index ++ , key ) ; put ( result ) ; } return result ; }

Adds a float to the constant pool of the class being build. Does nothing
if the constant pool already contains a similar item.

@param value
the float value.
@return a new or already existing float item.

Adds a float to the constant pool of the class being build . Does nothing if the constant pool already contains a similar item .


private Item newString(final String value) {
        key2.set(STR, value, null, null);
        Item result = get(key2);
        if (result == null) {
            pool.put12(STR, newUTF8(value));
            result = new Item(index++, key2);
            put(result);
        }
        return result;
    }

private Item newString ( final String value ) { key2 . set ( STR , value , null , null ) ; Item result = get ( key2 ) ; if ( result == null ) { pool . put12 ( STR , newUTF8 ( value ) ) ; result = new Item ( index ++ , key2 ) ; put ( result ) ; } return result ; }

Adds a string to the constant pool of the class being build. Does nothing
if the constant pool already contains a similar item.

@param value
the String value.
@return a new or already existing string item.

Adds a string to the constant pool of the class being build . Does nothing if the constant pool already contains a similar item .


Item newNameTypeItem(final String name, final String desc) {
        key2.set(NAME_TYPE, name, desc, null);
        Item result = get(key2);
        if (result == null) {
            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
            result = new Item(index++, key2);
            put(result);
        }
        return result;
    }

Item newNameTypeItem ( final String name , final String desc ) { key2 . set ( NAME_TYPE , name , desc , null ) ; Item result = get ( key2 ) ; if ( result == null ) { put122 ( NAME_TYPE , newUTF8 ( name ) , newUTF8 ( desc ) ) ; result = new Item ( index ++ , key2 ) ; put ( result ) ; } return result ; }

Adds a name and type to the constant pool of the class being build. Does
nothing if the constant pool already contains a similar item.

@param name
a name.
@param desc
a type descriptor.
@return a new or already existing name and type item.

Adds a name and type to the constant pool of the class being build . Does nothing if the constant pool already contains a similar item .


private Item get(final Item key) {
        Item i = items[key.hashCode % items.length];
        while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
            i = i.next;
        }
        return i;
    }

private Item get ( final Item key ) { Item i = items [ key . hashCode % items . length ] ; while ( i != null && ( i . type != key . type || ! key . isEqualTo ( i ) ) ) { i = i . next ; } return i ; }

Returns the constant pool's hash table item which is equal to the given
item.

@param key
a constant pool item.
@return the constant pool's hash table item which is equal to the given
item, or <tt>null</tt> if there is no such item.

Returns the constant pool s hash table item which is equal to the given item .


private void put122(final int b, final int s1, final int s2) {
        pool.put12(b, s1).putShort(s2);
    }

private void put122 ( final int b , final int s1 , final int s2 ) { pool . put12 ( b , s1 ) . putShort ( s2 ) ; }

Puts one byte and two shorts into the constant pool.

@param b
a byte.
@param s1
a short.
@param s2
another short.

Puts one byte and two shorts into the constant pool .


private void put112(final int b1, final int b2, final int s) {
        pool.put11(b1, b2).putShort(s);
    }

private void put112 ( final int b1 , final int b2 , final int s ) { pool . put11 ( b1 , b2 ) . putShort ( s ) ; }

Puts two bytes and one short into the constant pool.

@param b1
a byte.
@param b2
another byte.
@param s
a short.

Puts two bytes and one short into the constant pool .


public void visitEnum(String name, String desc, String value) {
        if (av != null) {
            av.visitEnum(name, desc, value);
        }
    }

public void visitEnum ( String name , String desc , String value ) { if ( av != null ) { av . visitEnum ( name , desc , value ) ; } }

Visits an enumeration value of the annotation.

@param name
the value name.
@param desc
the class descriptor of the enumeration class.
@param value
the actual enumeration value.

Visits an enumeration value of the annotation .


public AnnotationVisitor visitAnnotation(String name, String desc) {
        if (av != null) {
            return av.visitAnnotation(name, desc);
        }
        return null;
    }

public AnnotationVisitor visitAnnotation ( String name , String desc ) { if ( av != null ) { return av . visitAnnotation ( name , desc ) ; } return null ; }

Visits a nested annotation value of the annotation.

@param name
the value name.
@param desc
the class descriptor of the nested annotation class.
@return a visitor to visit the actual nested annotation value, or
<tt>null</tt> if this visitor is not interested in visiting this
nested annotation. <i>The nested annotation value must be fully
visited before calling other methods on this annotation
visitor</i>.

Visits a nested annotation value of the annotation .


private static int pos4twist(double rank,
                                 double phase,
                                 double period,
                                 int hOrW,
                                 int xOrY,
                                 int yOrX) {
        double dyOrX = Math.PI * rank * yOrX / hOrW + phase;
        double dxOrY = Math.sin(dyOrX);
        return xOrY + (int) (dxOrY * period);
    }

private static int pos4twist ( double rank , double phase , double period , int hOrW , int xOrY , int yOrX ) { double dyOrX = Math . PI * rank * yOrX / hOrW + phase ; double dxOrY = Math . sin ( dyOrX ) ; return xOrY + ( int ) ( dxOrY * period ) ; }


private static BufferedImage createJPEG4(Raster raster) {
        int w = raster.getWidth();
        int h = raster.getHeight();
        byte[] rgb = new byte[w * h * 3];

        float[] Y = raster.getSamples(0, 0, w, h, 0, (float[]) null);
        float[] Cb = raster.getSamples(0, 0, w, h, 1, (float[]) null);
        float[] Cr = raster.getSamples(0, 0, w, h, 2, (float[]) null);
        float[] K = raster.getSamples(0, 0, w, h, 3, (float[]) null);

        for (int i = 0, imax = Y.length, base = 0; i < imax; i++, base += 3) {
            float k = 220 - K[i], y = 255 - Y[i], cb = 255 - Cb[i], cr = 255 - Cr[i];

            double val = y + 1.402 * (cr - 128) - k;
            val = (val - 128) * .65f + 128;
            rgb[base] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff : (byte) (val + 0.5);

            val = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128) - k;
            val = (val - 128) * .65f + 128;
            rgb[base + 1] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff : (byte) (val + 0.5);

            val = y + 1.772 * (cb - 128) - k;
            val = (val - 128) * .65f + 128;
            rgb[base + 2] = val < 0.0 ? (byte) 0 : val > 255.0 ? (byte) 0xff : (byte) (val + 0.5);
        }

        raster = Raster.createInterleavedRaster(new DataBufferByte(rgb, rgb.length),
                                                w,
                                                h,
                                                w * 3,
                                                3,
                                                new int[]{0, 1, 2},
                                                null);

        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        ColorModel cm = new ComponentColorModel(cs,
                                                false,
                                                true,
                                                Transparency.OPAQUE,
                                                DataBuffer.TYPE_BYTE);
        return new BufferedImage(cm, (WritableRaster) raster, true, null);
    }

private static BufferedImage createJPEG4 ( Raster raster ) { int w = raster . getWidth ( ) ; int h = raster . getHeight ( ) ; byte [ ] rgb = new byte [ w * h * 3 ] ; float [ ] Y = raster . getSamples ( 0 , 0 , w , h , 0 , ( float [ ] ) null ) ; float [ ] Cb = raster . getSamples ( 0 , 0 , w , h , 1 , ( float [ ] ) null ) ; float [ ] Cr = raster . getSamples ( 0 , 0 , w , h , 2 , ( float [ ] ) null ) ; float [ ] K = raster . getSamples ( 0 , 0 , w , h , 3 , ( float [ ] ) null ) ; for ( int i = 0 , imax = Y . length , base = 0 ; i < imax ; i ++ , base += 3 ) { float k = 220 - K [ i ] , y = 255 - Y [ i ] , cb = 255 - Cb [ i ] , cr = 255 - Cr [ i ] ; double val = y + 1.402 * ( cr - 128 ) - k ; val = ( val - 128 ) * .65f + 128 ; rgb [ base ] = val < 0.0 ? ( byte ) 0 : val > 255.0 ? ( byte ) 0xff : ( byte ) ( val + 0.5 ) ; val = y - 0.34414 * ( cb - 128 ) - 0.71414 * ( cr - 128 ) - k ; val = ( val - 128 ) * .65f + 128 ; rgb [ base + 1 ] = val < 0.0 ? ( byte ) 0 : val > 255.0 ? ( byte ) 0xff : ( byte ) ( val + 0.5 ) ; val = y + 1.772 * ( cb - 128 ) - k ; val = ( val - 128 ) * .65f + 128 ; rgb [ base + 2 ] = val < 0.0 ? ( byte ) 0 : val > 255.0 ? ( byte ) 0xff : ( byte ) ( val + 0.5 ) ; } raster = Raster . createInterleavedRaster ( new DataBufferByte ( rgb , rgb . length ) , w , h , w * 3 , 3 , new int [ ] { 0 , 1 , 2 } , null ) ; ColorSpace cs = ColorSpace . getInstance ( ColorSpace . CS_sRGB ) ; ColorModel cm = new ComponentColorModel ( cs , false , true , Transparency . OPAQUE , DataBuffer . TYPE_BYTE ) ; return new BufferedImage ( cm , ( WritableRaster ) raster , true , null ) ; }

Java's ImageIO can't process 4-component images and Java2D can't apply
AffineTransformOp either, so convert raster data to RGB. Technique due to
MArk Stephens. Free for any use.

Java s ImageIO can t process 4 - component images and Java2D can t apply AffineTransformOp either so convert raster data to RGB . Technique due to MArk Stephens . Free for any use .


public void visitParameter(String name, int access) {
        if (api < Opcodes.ASM5) {
            throw new RuntimeException();
        }
        if (mv != null) {
            mv.visitParameter(name, access);
        }
    }

public void visitParameter ( String name , int access ) { if ( api < Opcodes . ASM5 ) { throw new RuntimeException ( ) ; } if ( mv != null ) { mv . visitParameter ( name , access ) ; } }

Visits a parameter of this method.

@param name
parameter name or null if none is provided.
@param access
the parameter's access flags, only <tt>ACC_FINAL</tt>,
<tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
allowed (see {@link Opcodes}).


public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        if (mv != null) {
            return mv.visitAnnotation(desc, visible);
        }
        return null;
    }

public AnnotationVisitor visitAnnotation ( String desc , boolean visible ) { if ( mv != null ) { return mv . visitAnnotation ( desc , visible ) ; } return null ; }

Visits an annotation of this method.

@param desc
the class descriptor of the annotation class.
@param visible
<tt>true</tt> if the annotation is visible at runtime.
@return a visitor to visit the annotation values, or <tt>null</tt> if
this visitor is not interested in visiting this annotation.


public AnnotationVisitor visitParameterAnnotation(int parameter,
            String desc, boolean visible) {
        if (mv != null) {
            return mv.visitParameterAnnotation(parameter, desc, visible);
        }
        return null;
    }

public AnnotationVisitor visitParameterAnnotation ( int parameter , String desc , boolean visible ) { if ( mv != null ) { return mv . visitParameterAnnotation ( parameter , desc , visible ) ; } return null ; }

Visits an annotation of a parameter this method.

@param parameter
the parameter index.
@param desc
the class descriptor of the annotation class.
@param visible
<tt>true</tt> if the annotation is visible at runtime.
@return a visitor to visit the annotation values, or <tt>null</tt> if
this visitor is not interested in visiting this annotation.

Visits an annotation of a parameter this method .


public void visitTypeInsn(int opcode, String type) {
        if (mv != null) {
            mv.visitTypeInsn(opcode, type);
        }
    }

public void visitTypeInsn ( int opcode , String type ) { if ( mv != null ) { mv . visitTypeInsn ( opcode , type ) ; } }

Visits a type instruction. A type instruction is an instruction that
takes the internal name of a class as parameter.

@param opcode
the opcode of the type instruction to be visited. This opcode
is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
@param type
the operand of the instruction to be visited. This operand
must be the internal name of an object or array class (see
{@link Type#getInternalName() getInternalName}).

Visits a type instruction . A type instruction is an instruction that takes the internal name of a class as parameter .


public void visitFieldInsn(int opcode, String owner, String name,
            String desc) {
        if (mv != null) {
            mv.visitFieldInsn(opcode, owner, name, desc);
        }
    }

public void visitFieldInsn ( int opcode , String owner , String name , String desc ) { if ( mv != null ) { mv . visitFieldInsn ( opcode , owner , name , desc ) ; } }

Visits a field instruction. A field instruction is an instruction that
loads or stores the value of a field of an object.

@param opcode
the opcode of the type instruction to be visited. This opcode
is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
@param owner
the internal name of the field's owner class (see
{@link Type#getInternalName() getInternalName}).
@param name
the field's name.
@param desc
the field's descriptor (see {@link Type Type}).

Visits a field instruction . A field instruction is an instruction that loads or stores the value of a field of an object .


@Deprecated
    public void visitMethodInsn(int opcode, String owner, String name,
            String desc) {
        if (api >= Opcodes.ASM5) {
            boolean itf = opcode == Opcodes.INVOKEINTERFACE;
            visitMethodInsn(opcode, owner, name, desc, itf);
            return;
        }
        if (mv != null) {
            mv.visitMethodInsn(opcode, owner, name, desc);
        }
    }

@ Deprecated public void visitMethodInsn ( int opcode , String owner , String name , String desc ) { if ( api >= Opcodes . ASM5 ) { boolean itf = opcode == Opcodes . INVOKEINTERFACE ; visitMethodInsn ( opcode , owner , name , desc , itf ) ; return ; } if ( mv != null ) { mv . visitMethodInsn ( opcode , owner , name , desc ) ; } }

Visits a method instruction. A method instruction is an instruction that
invokes a method.

@param opcode
the opcode of the type instruction to be visited. This opcode
is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
INVOKEINTERFACE.
@param owner
the internal name of the method's owner class (see
{@link Type#getInternalName() getInternalName}).
@param name
the method's name.
@param desc
the method's descriptor (see {@link Type Type}).

Visits a method instruction . A method instruction is an instruction that invokes a method .


public void visitTableSwitchInsn(int min, int max, Label dflt,
            Label... labels) {
        if (mv != null) {
            mv.visitTableSwitchInsn(min, max, dflt, labels);
        }
    }

public void visitTableSwitchInsn ( int min , int max , Label dflt , Label ... labels ) { if ( mv != null ) { mv . visitTableSwitchInsn ( min , max , dflt , labels ) ; } }

Visits a TABLESWITCH instruction.

@param min
the minimum key value.
@param max
the maximum key value.
@param dflt
beginning of the default handler block.
@param labels
beginnings of the handler blocks. <tt>labels[i]</tt> is the
beginning of the handler block for the <tt>min + i</tt> key.


public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
        if (mv != null) {
            mv.visitLookupSwitchInsn(dflt, keys, labels);
        }
    }

public void visitLookupSwitchInsn ( Label dflt , int [ ] keys , Label [ ] labels ) { if ( mv != null ) { mv . visitLookupSwitchInsn ( dflt , keys , labels ) ; } }

Visits a LOOKUPSWITCH instruction.

@param dflt
beginning of the default handler block.
@param keys
the values of the keys.
@param labels
beginnings of the handler blocks. <tt>labels[i]</tt> is the
beginning of the handler block for the <tt>keys[i]</tt> key.


public void visitMultiANewArrayInsn(String desc, int dims) {
        if (mv != null) {
            mv.visitMultiANewArrayInsn(desc, dims);
        }
    }

public void visitMultiANewArrayInsn ( String desc , int dims ) { if ( mv != null ) { mv . visitMultiANewArrayInsn ( desc , dims ) ; } }

Visits a MULTIANEWARRAY instruction.

@param desc
an array type descriptor (see {@link Type Type}).
@param dims
number of dimensions of the array to allocate.


public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
            TypePath typePath, Label[] start, Label[] end, int[] index,
            String desc, boolean visible) {
        if (api < Opcodes.ASM5) {
            throw new RuntimeException();
        }
        if (mv != null) {
            return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
                    end, index, desc, visible);
        }
        return null;
    }

public AnnotationVisitor visitLocalVariableAnnotation ( int typeRef , TypePath typePath , Label [ ] start , Label [ ] end , int [ ] index , String desc , boolean visible ) { if ( api < Opcodes . ASM5 ) { throw new RuntimeException ( ) ; } if ( mv != null ) { return mv . visitLocalVariableAnnotation ( typeRef , typePath , start , end , index , desc , visible ) ; } return null ; }

Visits an annotation on a local variable type.

@param typeRef
a reference to the annotated type. The sort of this type
reference must be {@link TypeReference#LOCAL_VARIABLE
LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
RESOURCE_VARIABLE}. See {@link TypeReference}.
@param typePath
the path to the annotated type argument, wildcard bound, array
element type, or static inner type within 'typeRef'. May be
<tt>null</tt> if the annotation targets 'typeRef' as a whole.
@param start
the fist instructions corresponding to the continuous ranges
that make the scope of this local variable (inclusive).
@param end
the last instructions corresponding to the continuous ranges
that make the scope of this local variable (exclusive). This
array must have the same size as the 'start' array.
@param index
the local variable's index in each range. This array must have
the same size as the 'start' array.
@param desc
the class descriptor of the annotation class.
@param visible
<tt>true</tt> if the annotation is visible at runtime.
@return a visitor to visit the annotation values, or <tt>null</tt> if
this visitor is not interested in visiting this annotation.

Visits an annotation on a local variable type .


public void visitLineNumber(int line, Label start) {
        if (mv != null) {
            mv.visitLineNumber(line, start);
        }
    }

public void visitLineNumber ( int line , Label start ) { if ( mv != null ) { mv . visitLineNumber ( line , start ) ; } }

Visits a line number declaration.

@param line
a line number. This number refers to the source file from
which the class was compiled.
@param start
the first instruction corresponding to this line number.
@throws IllegalArgumentException
if <tt>start</tt> has not already been visited by this
visitor (by the {@link #visitLabel visitLabel} method).


private int readFrameType(final Object[] frame, final int index, int v,
            final char[] buf, final Label[] labels) {
        int type = b[v++] & 0xFF;
        switch (type) {
        case 0:
            frame[index] = Opcodes.TOP;
            break;
        case 1:
            frame[index] = Opcodes.INTEGER;
            break;
        case 2:
            frame[index] = Opcodes.FLOAT;
            break;
        case 3:
            frame[index] = Opcodes.DOUBLE;
            break;
        case 4:
            frame[index] = Opcodes.LONG;
            break;
        case 5:
            frame[index] = Opcodes.NULL;
            break;
        case 6:
            frame[index] = Opcodes.UNINITIALIZED_THIS;
            break;
        case 7: // Object
            frame[index] = readClass(v, buf);
            v += 2;
            break;
        default: // Uninitialized
            frame[index] = readLabel(readUnsignedShort(v), labels);
            v += 2;
        }
        return v;
    }

private
int
readFrameType
(
final
Object
[
]
frame
,
final
int
index
,
int
v
,
final
char
[
]
buf
,
final
Label
[
]
labels
)
{
int
type
=
b
[
v
++
]
&
0xFF
;
switch
(
type
)
{
case
0
:
frame
[
index
]
=
Opcodes
.
TOP
;
break
;
case
1
:
frame
[
index
]
=
Opcodes
.
INTEGER
;
break
;
case
2
:
frame
[
index
]
=
Opcodes
.
FLOAT
;
break
;
case
3
:
frame
[
index
]
=
Opcodes
.
DOUBLE
;
break
;
case
4
:
frame
[
index
]
=
Opcodes
.
LONG
;
break
;
case
5
:
frame
[
index
]
=
Opcodes
.
;
break
;
case
6
:
frame
[
index
]
=
Opcodes
.
UNINITIALIZED_THIS
;
break
;
case
7
:
// Object
frame
[
index
]
=
readClass
(
v
,
buf
)
;
v
+=
2
;
break
;
default
:
// Uninitialized
frame
[
index
]
=
readLabel
(
readUnsignedShort
(
v
)
,
labels
)
;
v
+=
2
;
}
return
v
;
}

Reads a stack map frame type and stores it at the given index in the
given array.

@param frame
the array where the parsed type must be stored.
@param index
the index in 'frame' where the parsed type must be stored.
@param v
the start offset of the stack map frame type to read.
@param buf
a buffer to read strings.
@param labels
the labels of the method currently being parsed, indexed by
their offset. If the parsed type is an Uninitialized type, a
new label for the corresponding NEW instruction is stored in
this array if it does not already exist.
@return the offset of the first byte after the parsed type.

Reads a stack map frame type and stores it at the given index in the given array .


final void set(ClassWriter cw, final int nLocal, final Object[] local,
            final int nStack, final Object[] stack) {
        int i = convert(cw, nLocal, local, inputLocals);
        while (i < local.length) {
            inputLocals[i++] = TOP;
        }
        int nStackTop = 0;
        for (int j = 0; j < nStack; ++j) {
            if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) {
                ++nStackTop;
            }
        }
        inputStack = new int[nStack + nStackTop];
        convert(cw, nStack, stack, inputStack);
        outputStackTop = 0;
        initializationCount = 0;
    }

final void set ( ClassWriter cw , final int nLocal , final Object [ ] local , final int nStack , final Object [ ] stack ) { int i = convert ( cw , nLocal , local , inputLocals ) ; while ( i < local . length ) { inputLocals [ i ++ ] = TOP ; } int nStackTop = 0 ; for ( int j = 0 ; j < nStack ; ++ j ) { if ( stack [ j ] == Opcodes . LONG || stack [ j ] == Opcodes . DOUBLE ) { ++ nStackTop ; } } inputStack = new int [ nStack + nStackTop ] ; convert ( cw , nStack , stack , inputStack ) ; outputStackTop = 0 ; initializationCount = 0 ; }

Sets this frame to the given value.

@param cw
the ClassWriter to which this label belongs.
@param nLocal
the number of local variables.
@param local
the local variable types. Primitive types are represented by
{@link Opcodes#TOP}, {@link Opcodes#INTEGER},
{@link Opcodes#FLOAT}, {@link Opcodes#LONG},
{@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
{@link Opcodes#UNINITIALIZED_THIS} (long and double are
represented by a single element). Reference types are
represented by String objects (representing internal names),
and uninitialized types by Label objects (this label
designates the NEW instruction that created this uninitialized
value).
@param nStack
the number of operand stack elements.
@param stack
the operand stack types (same format as the "local" array).


private int get(final int local) {
        if (outputLocals == null || local >= outputLocals.length) {
            // this local has never been assigned in this basic block,
            // so it is still equal to its value in the input frame
            return LOCAL | local;
        } else {
            int type = outputLocals[local];
            if (type == 0) {
                // this local has never been assigned in this basic block,
                // so it is still equal to its value in the input frame
                type = outputLocals[local] = LOCAL | local;
            }
            return type;
        }
    }

Returns the output frame local variable type at the given index.

@param local
the index of the local that must be returned.
@return the output frame local variable type at the given index.

Returns the output frame local variable type at the given index .


private void set(final int local, final int type) {
        // creates and/or resizes the output local variables array if necessary
        if (outputLocals == null) {
            outputLocals = new int[10];
        }
        int n = outputLocals.length;
        if (local >= n) {
            int[] t = new int[Math.max(local + 1, 2 * n)];
            System.arraycopy(outputLocals, 0, t, 0, n);
            outputLocals = t;
        }
        // sets the local variable
        outputLocals[local] = type;
    }

Sets the output frame local variable type at the given index.

@param local
the index of the local that must be set.
@param type
the value of the local that must be set.

Sets the output frame local variable type at the given index .


private void push(final ClassWriter cw, final String desc) {
        int type = type(cw, desc);
        if (type != 0) {
            push(type);
            if (type == LONG || type == DOUBLE) {
                push(TOP);
            }
        }
    }

private void push ( final ClassWriter cw , final String desc ) { int type = type ( cw , desc ) ; if ( type != 0 ) { push ( type ) ; if ( type == LONG || type == DOUBLE ) { push ( TOP ) ; } } }

Pushes a new type onto the output frame stack.

@param cw
the ClassWriter to which this label belongs.
@param desc
the descriptor of the type to be pushed. Can also be a method
descriptor (in this case this method pushes its return type
onto the output frame stack).

Pushes a new type onto the output frame stack .


private static int type(final ClassWriter cw, final String desc) {
        String t;
        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
        switch (desc.charAt(index)) {
        case 'V':
            return 0;
        case 'Z':
        case 'C':
        case 'B':
        case 'S':
        case 'I':
            return INTEGER;
        case 'F':
            return FLOAT;
        case 'J':
            return LONG;
        case 'D':
            return DOUBLE;
        case 'L':
            // stores the internal name, not the descriptor!
            t = desc.substring(index + 1, desc.length() - 1);
            return OBJECT | cw.addType(t);
            // case '[':
        default:
            // extracts the dimensions and the element type
            int data;
            int dims = index + 1;
            while (desc.charAt(dims) == '[') {
                ++dims;
            }
            switch (desc.charAt(dims)) {
            case 'Z':
                data = BOOLEAN;
                break;
            case 'C':
                data = CHAR;
                break;
            case 'B':
                data = BYTE;
                break;
            case 'S':
                data = SHORT;
                break;
            case 'I':
                data = INTEGER;
                break;
            case 'F':
                data = FLOAT;
                break;
            case 'J':
                data = LONG;
                break;
            case 'D':
                data = DOUBLE;
                break;
            // case 'L':
            default:
                // stores the internal name, not the descriptor
                t = desc.substring(dims + 1, desc.length() - 1);
                data = OBJECT | cw.addType(t);
            }
            return (dims - index) << 28 | data;
        }
    }

Returns the int encoding of the given type.

@param cw
the ClassWriter to which this label belongs.
@param desc
a type descriptor.
@return the int encoding of the given type.

Returns the int encoding of the given type .


private void pop(final int elements) {
        if (outputStackTop >= elements) {
            outputStackTop -= elements;
        } else {
            // if the number of elements to be popped is greater than the number
            // of elements in the output stack, clear it, and pops the remaining
            // elements from the input stack.
            owner.inputStackTop -= elements - outputStackTop;
            outputStackTop = 0;
        }
    }

Pops the given number of types from the output frame stack.

@param elements
the number of types that must be popped.

Pops the given number of types from the output frame stack .


private void pop(final String desc) {
        char c = desc.charAt(0);
        if (c == '(') {
            pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
        } else if (c == 'J' || c == 'D') {
            pop(2);
        } else {
            pop(1);
        }
    }

private void pop ( final String desc ) { char c = desc . charAt ( 0 ) ; if ( c == ' ' ) { pop ( ( Type . getArgumentsAndReturnSizes ( desc ) >> 2 ) - 1 ) ; } else if ( c == ' ' || c == ' ' ) { pop ( 2 ) ; } else { pop ( 1 ) ; } }

Pops a type from the output frame stack.

@param desc
the descriptor of the type to be popped. Can also be a method
descriptor (in this case this method pops the types
corresponding to the method arguments).

Pops a type from the output frame stack .


private void init(final int var) {
        // creates and/or resizes the initializations array if necessary
        if (initializations == null) {
            initializations = new int[2];
        }
        int n = initializations.length;
        if (initializationCount >= n) {
            int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
            System.arraycopy(initializations, 0, t, 0, n);
            initializations = t;
        }
        // stores the type to be initialized
        initializations[initializationCount++] = var;
    }

Adds a new type to the list of types on which a constructor is invoked in
the basic block.

@param var
a type on a which a constructor is invoked.

Adds a new type to the list of types on which a constructor is invoked in the basic block .


private int init(final ClassWriter cw, final int t) {
        int s;
        if (t == UNINITIALIZED_THIS) {
            s = OBJECT | cw.addType(cw.thisName);
        } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
            String type = cw.typeTable[t & BASE_VALUE].strVal1;
            s = OBJECT | cw.addType(type);
        } else {
            return t;
        }
        for (int j = 0; j < initializationCount; ++j) {
            int u = initializations[j];
            int dim = u & DIM;
            int kind = u & KIND;
            if (kind == LOCAL) {
                u = dim + inputLocals[u & VALUE];
            } else if (kind == STACK) {
                u = dim + inputStack[inputStack.length - (u & VALUE)];
            }
            if (t == u) {
                return s;
            }
        }
        return t;
    }

private int init ( final ClassWriter cw , final int t ) { int s ; if ( t == UNINITIALIZED_THIS ) { s = OBJECT | cw . addType ( cw . thisName ) ; } else if ( ( t & ( DIM | BASE_KIND ) ) == UNINITIALIZED ) { String type = cw . typeTable [ t & BASE_VALUE ] . strVal1 ; s = OBJECT | cw . addType ( type ) ; } else { return t ; } for ( int j = 0 ; j < initializationCount ; ++ j ) { int u = initializations [ j ] ; int dim = u & DIM ; int kind = u & KIND ; if ( kind == LOCAL ) { u = dim + inputLocals [ u & VALUE ] ; } else if ( kind == STACK ) { u = dim + inputStack [ inputStack . length - ( u & VALUE ) ] ; } if ( t == u ) { return s ; } } return t ; }

Replaces the given type with the appropriate type if it is one of the
types on which a constructor is invoked in the basic block.

@param cw
the ClassWriter to which this label belongs.
@param t
a type
@return t or, if t is one of the types on which a constructor is invoked
in the basic block, the type corresponding to this constructor.

Replaces the given type with the appropriate type if it is one of the types on which a constructor is invoked in the basic block .


public void visitSource(String source, String debug) {
        if (cv != null) {
            cv.visitSource(source, debug);
        }
    }

public void visitSource ( String source , String debug ) { if ( cv != null ) { cv . visitSource ( source , debug ) ; } }

Visits the source of the class.

@param source
the name of the source file from which the class was compiled.
May be <tt>null</tt>.
@param debug
additional debug information to compute the correspondance
between source and compiled elements of the class. May be
<tt>null</tt>.


public void visitOuterClass(String owner, String name, String desc) {
        if (cv != null) {
            cv.visitOuterClass(owner, name, desc);
        }
    }

public void visitOuterClass ( String owner , String name , String desc ) { if ( cv != null ) { cv . visitOuterClass ( owner , name , desc ) ; } }

Visits the enclosing class of the class. This method must be called only
if the class has an enclosing class.

@param owner
internal name of the enclosing class of the class.
@param name
the name of the method that contains the class, or
<tt>null</tt> if the class is not enclosed in a method of its
enclosing class.
@param desc
the descriptor of the method that contains the class, or
<tt>null</tt> if the class is not enclosed in a method of its
enclosing class.

Visits the enclosing class of the class . This method must be called only if the class has an enclosing class .


public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
        if (cv != null) {
            return cv.visitAnnotation(desc, visible);
        }
        return null;
    }

public AnnotationVisitor visitAnnotation ( String desc , boolean visible ) { if ( cv != null ) { return cv . visitAnnotation ( desc , visible ) ; } return null ; }

Visits an annotation of the class.

@param desc
the class descriptor of the annotation class.
@param visible
<tt>true</tt> if the annotation is visible at runtime.
@return a visitor to visit the annotation values, or <tt>null</tt> if
this visitor is not interested in visiting this annotation.


public AnnotationVisitor visitTypeAnnotation(int typeRef,
            TypePath typePath, String desc, boolean visible) {
        if (api < Opcodes.ASM5) {
            throw new RuntimeException();
        }
        if (cv != null) {
            return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
        }
        return null;
    }

public AnnotationVisitor visitTypeAnnotation ( int typeRef , TypePath typePath , String desc , boolean visible ) { if ( api < Opcodes . ASM5 ) { throw new RuntimeException ( ) ; } if ( cv != null ) { return cv . visitTypeAnnotation ( typeRef , typePath , desc , visible ) ; } return null ; }

Visits an annotation on a type in the class signature.

@param typeRef
a reference to the annotated type. The sort of this type
reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
CLASS_TYPE_PARAMETER},
{@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
CLASS_TYPE_PARAMETER_BOUND} or
{@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
{@link TypeReference}.
@param typePath
the path to the annotated type argument, wildcard bound, array
element type, or static inner type within 'typeRef'. May be
<tt>null</tt> if the annotation targets 'typeRef' as a whole.
@param desc
the class descriptor of the annotation class.
@param visible
<tt>true</tt> if the annotation is visible at runtime.
@return a visitor to visit the annotation values, or <tt>null</tt> if
this visitor is not interested in visiting this annotation.

Visits an annotation on a type in the class signature .


public static int extract(int bs, int low, int high) {
        bs = bs >> low;
        int mask = 0;
        for (int i = 0; i < (high - low); i++) {
            mask += 1 << i;
        }
        return bs & mask;
    }

public static int extract ( int bs , int low , int high ) { bs = bs >> low ; int mask = 0 ; for ( int i = 0 ; i < ( high - low ) ; i ++ ) { mask += 1 << i ; } return bs & mask ; }

Get part of one integer as a new integer

@param bs
original integer
@param low
the low bit position (inclusive), 0 base
@param high
the high bit position (exclusive), 0 base
@return new integer


public static Type getObjectType(final String internalName) {
        char[] buf = internalName.toCharArray();
        return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
    }

public static Type getObjectType ( final String internalName ) { char [ ] buf = internalName . toCharArray ( ) ; return new Type ( buf [ 0 ] == ' ' ? ARRAY : OBJECT , buf , 0 , buf . length ) ; }

Returns the Java type corresponding to the given internal name.

@param internalName
an internal name.
@return the Java type corresponding to the given internal name.

Returns the Java type corresponding to the given internal name .


public static Type[] getArgumentTypes(final String methodDescriptor) {
        char[] buf = methodDescriptor.toCharArray();
        int off = 1;
        int size = 0;
        while (true) {
            char car = buf[off++];
            if (car == ')') {
                break;
            } else if (car == 'L') {
                while (buf[off++] != ';') {
                }
                ++size;
            } else if (car != '[') {
                ++size;
            }
        }
        Type[] args = new Type[size];
        off = 1;
        size = 0;
        while (buf[off] != ')') {
            args[size] = getType(buf, off);
            off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
            size += 1;
        }
        return args;
    }

public static Type [ ] getArgumentTypes ( final String methodDescriptor ) { char [ ] buf = methodDescriptor . toCharArray ( ) ; int off = 1 ; int size = 0 ; while ( true ) { char car = buf [ off ++ ] ; if ( car == ' ' ) { break ; } else if ( car == ' ' ) { while ( buf [ off ++ ] != ' ' ) { } ++ size ; } else if ( car != ' ' ) { ++ size ; } } Type [ ] args = new Type [ size ] ; off = 1 ; size = 0 ; while ( buf [ off ] != ' ' ) { args [ size ] = getType ( buf , off ) ; off += args [ size ] . len + ( args [ size ] . sort == OBJECT ? 2 : 0 ) ; size += 1 ; } return args ; }

Returns the Java types corresponding to the argument types of the given
method descriptor.

@param methodDescriptor
a method descriptor.
@return the Java types corresponding to the argument types of the given
method descriptor.

Returns the Java types corresponding to the argument types of the given method descriptor .


public static Type getReturnType(final String methodDescriptor) {
        char[] buf = methodDescriptor.toCharArray();
        int off = 1;
        while (true) {
            char car = buf[off++];
            if (car == ')') {
                return getType(buf, off);
            } else if (car == 'L') {
                while (buf[off++] != ';') {
                }
            }
        }
    }

public static Type getReturnType ( final String methodDescriptor ) { char [ ] buf = methodDescriptor . toCharArray ( ) ; int off = 1 ; while ( true ) { char car = buf [ off ++ ] ; if ( car == ' ' ) { return getType ( buf , off ) ; } else if ( car == ' ' ) { while ( buf [ off ++ ] != ' ' ) { } } } }

Returns the Java type corresponding to the return type of the given
method descriptor.

@param methodDescriptor
a method descriptor.
@return the Java type corresponding to the return type of the given
method descriptor.

Returns the Java type corresponding to the return type of the given method descriptor .


public static int getArgumentsAndReturnSizes(final String desc) {
        int n = 1;
        int c = 1;
        while (true) {
            char car = desc.charAt(c++);
            if (car == ')') {
                car = desc.charAt(c);
                return n << 2
                        | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
            } else if (car == 'L') {
                while (desc.charAt(c++) != ';') {
                }
                n += 1;
            } else if (car == '[') {
                while ((car = desc.charAt(c)) == '[') {
                    ++c;
                }
                if (car == 'D' || car == 'J') {
                    n -= 1;
                }
            } else if (car == 'D' || car == 'J') {
                n += 2;
            } else {
                n += 1;
            }
        }
    }

public static int getArgumentsAndReturnSizes ( final String desc ) { int n = 1 ; int c = 1 ; while ( true ) { char car = desc . charAt ( c ++ ) ; if ( car == ' ' ) { car = desc . charAt ( c ) ; return n << 2 | ( car == ' ' ? 0 : ( car == ' ' || car == ' ' ? 2 : 1 ) ) ; } else if ( car == ' ' ) { while ( desc . charAt ( c ++ ) != ' ' ) { } n += 1 ; } else if ( car == ' ' ) { while ( ( car = desc . charAt ( c ) ) == ' ' ) { ++ c ; } if ( car == ' ' || car == ' ' ) { n -= 1 ; } } else if ( car == ' ' || car == ' ' ) { n += 2 ; } else { n += 1 ; } } }

Computes the size of the arguments and of the return value of a method.

@param desc
the descriptor of a method.
@return the size of the arguments of the method (plus one for the
implicit this argument), argSize, and the size of its return
value, retSize, packed into a single int i =
<tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
<tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).

Computes the size of the arguments and of the return value of a method .


private static Type getType(final char[] buf, final int off) {
        int len;
        switch (buf[off]) {
        case 'V':
            return VOID_TYPE;
        case 'Z':
            return BOOLEAN_TYPE;
        case 'C':
            return CHAR_TYPE;
        case 'B':
            return BYTE_TYPE;
        case 'S':
            return SHORT_TYPE;
        case 'I':
            return INT_TYPE;
        case 'F':
            return FLOAT_TYPE;
        case 'J':
            return LONG_TYPE;
        case 'D':
            return DOUBLE_TYPE;
        case '[':
            len = 1;
            while (buf[off + len] == '[') {
                ++len;
            }
            if (buf[off + len] == 'L') {
                ++len;
                while (buf[off + len] != ';') {
                    ++len;
                }
            }
            return new Type(ARRAY, buf, off, len + 1);
        case 'L':
            len = 1;
            while (buf[off + len] != ';') {
                ++len;
            }
            return new Type(OBJECT, buf, off + 1, len - 1);
            // case '(':
        default:
            return new Type(METHOD, buf, off, buf.length - off);
        }
    }

private
static
Type
getType
(
final
char
[
]
buf
,
final
int
off
)
{
int
len
;
switch
(
buf
[
off
]
)
{
case
'
'
:
return
VOID_TYPE
;
case
'
'
:
return
BOOLEAN_TYPE
;
case
'
'
:
return
CHAR_TYPE
;
case
'
'
:
return
BYTE_TYPE
;
case
'
'
:
return
SHORT_TYPE
;
case
'
'
:
return
INT_TYPE
;
case
'
'
:
return
FLOAT_TYPE
;
case
'
'
:
return
LONG_TYPE
;
case
'
'
:
return
DOUBLE_TYPE
;
case
'
'
:
len
=
1
;
while
(
buf
[
off
+
len
]
==
'
'
)
{
++
len
;
}
if
(
buf
[
off
+
len
]
==
'
'
)
{
++
len
;
while
(
buf
[
off
+
len
]
!=
'
'
)
{
++
len
;
}
}
return
new
Type
(
ARRAY
,
buf
,
off
,
len
+
1
)
;
case
'
'
:
len
=
1
;
while
(
buf
[
off
+
len
]
!=
'
'
)
{
++
len
;
}
return
new
Type
(
OBJECT
,
buf
,
off
+
1
,
len
1
)
;
// case '(':
default
:
return
new
Type
(
METHOD
,
buf
,
off
,
buf
.
length
off
)
;
}
}

Returns the Java type corresponding to the given type descriptor. For
method descriptors, buf is supposed to contain nothing more than the
descriptor itself.

@param buf
a buffer containing a type descriptor.
@param off
the offset of this descriptor in the previous buffer.
@return the Java type corresponding to the given type descriptor.

Returns the Java type corresponding to the given type descriptor . For method descriptors buf is supposed to contain nothing more than the descriptor itself .


private void getDescriptor(final StringBuilder buf) {
        if (this.buf == null) {
            // descriptor is in byte 3 of 'off' for primitive types (buf ==
            // null)
            buf.append((char) ((off & 0xFF000000) >>> 24));
        } else if (sort == OBJECT) {
            buf.append('L');
            buf.append(this.buf, off, len);
            buf.append(';');
        } else { // sort == ARRAY || sort == METHOD
            buf.append(this.buf, off, len);
        }
    }

Appends the descriptor corresponding to this Java type to the given
string buffer.

@param buf
the string buffer to which the descriptor must be appended.

Appends the descriptor corresponding to this Java type to the given string buffer .


public static String getDescriptor(final Class<?> c) {
        StringBuilder buf = new StringBuilder();
        getDescriptor(buf, c);
        return buf.toString();
    }

public static String getDescriptor ( final Class < ? > c ) { StringBuilder buf = new StringBuilder ( ) ; getDescriptor ( buf , c ) ; return buf . toString ( ) ; }

Returns the descriptor corresponding to the given Java type.

@param c
an object class, a primitive class or an array class.
@return the descriptor corresponding to the given class.

Returns the descriptor corresponding to the given Java type .


public int getOpcode(final int opcode) {
        if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
            // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
            // primitive types (buf == null)
            return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
        } else {
            // the offset for other instructions is in byte 2 of 'off' for
            // primitive types (buf == null)
            return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
        }
    }

Returns a JVM instruction opcode adapted to this Java type. This method
must not be used for method types.

@param opcode
a JVM instruction opcode. This opcode must be one of ILOAD,
ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
@return an opcode that is similar to the given opcode, but adapted to
this Java type. For example, if this type is <tt>float</tt> and
<tt>opcode</tt> is IRETURN, this method returns FRETURN.

Returns a JVM instruction opcode adapted to this Java type . This method must not be used for method types .


public ByteVector putByte(final int b) {
        int length = this.length;
        if (length + 1 > data.length) {
            enlarge(1);
        }
        data[length++] = (byte) b;
        this.length = length;
        return this;
    }

public ByteVector putByte ( final int b ) { int length = this . length ; if ( length + 1 > data . length ) { enlarge ( 1 ) ; } data [ length ++ ] = ( byte ) b ; this . length = length ; return this ; }

Puts a byte into this byte vector. The byte vector is automatically
enlarged if necessary.

@param b
a byte.
@return this byte vector.

Puts a byte into this byte vector . The byte vector is automatically enlarged if necessary .


ByteVector put11(final int b1, final int b2) {
        int length = this.length;
        if (length + 2 > data.length) {
            enlarge(2);
        }
        byte[] data = this.data;
        data[length++] = (byte) b1;
        data[length++] = (byte) b2;
        this.length = length;
        return this;
    }

ByteVector put11 ( final int b1 , final int b2 ) { int length = this . length ; if ( length + 2 > data . length ) { enlarge ( 2 ) ; } byte [ ] data = this . data ; data [ length ++ ] = ( byte ) b1 ; data [ length ++ ] = ( byte ) b2 ; this . length = length ; return this ; }

Puts two bytes into this byte vector. The byte vector is automatically
enlarged if necessary.

@param b1
a byte.
@param b2
another byte.
@return this byte vector.

Puts two bytes into this byte vector . The byte vector is automatically enlarged if necessary .


public ByteVector putShort(final int s) {
        int length = this.length;
        if (length + 2 > data.length) {
            enlarge(2);
        }
        byte[] data = this.data;
        data[length++] = (byte) (s >>> 8);
        data[length++] = (byte) s;
        this.length = length;
        return this;
    }

public ByteVector putShort ( final int s ) { int length = this . length ; if ( length + 2 > data . length ) { enlarge ( 2 ) ; } byte [ ] data = this . data ; data [ length ++ ] = ( byte ) ( s >>> 8 ) ; data [ length ++ ] = ( byte ) s ; this . length = length ; return this ; }

Puts a short into this byte vector. The byte vector is automatically
enlarged if necessary.

@param s
a short.
@return this byte vector.

Puts a short into this byte vector . The byte vector is automatically enlarged if necessary .


ByteVector put12(final int b, final int s) {
        int length = this.length;
        if (length + 3 > data.length) {
            enlarge(3);
        }
        byte[] data = this.data;
        data[length++] = (byte) b;
        data[length++] = (byte) (s >>> 8);
        data[length++] = (byte) s;
        this.length = length;
        return this;
    }

ByteVector put12 ( final int b , final int s ) { int length = this . length ; if ( length + 3 > data . length ) { enlarge ( 3 ) ; } byte [ ] data = this . data ; data [ length ++ ] = ( byte ) b ; data [ length ++ ] = ( byte ) ( s >>> 8 ) ; data [ length ++ ] = ( byte ) s ; this . length = length ; return this ; }

Puts a byte and a short into this byte vector. The byte vector is
automatically enlarged if necessary.

@param b
a byte.
@param s
a short.
@return this byte vector.

Puts a byte and a short into this byte vector . The byte vector is automatically enlarged if necessary .


public ByteVector putInt(final int i) {
        int length = this.length;
        if (length + 4 > data.length) {
            enlarge(4);
        }
        byte[] data = this.data;
        data[length++] = (byte) (i >>> 24);
        data[length++] = (byte) (i >>> 16);
        data[length++] = (byte) (i >>> 8);
        data[length++] = (byte) i;
        this.length = length;
        return this;
    }

public ByteVector putInt ( final int i ) { int length = this . length ; if ( length + 4 > data . length ) { enlarge ( 4 ) ; } byte [ ] data = this . data ; data [ length ++ ] = ( byte ) ( i >>> 24 ) ; data [ length ++ ] = ( byte ) ( i >>> 16 ) ; data [ length ++ ] = ( byte ) ( i >>> 8 ) ; data [ length ++ ] = ( byte ) i ; this . length = length ; return this ; }

Puts an int into this byte vector. The byte vector is automatically
enlarged if necessary.

@param i
an int.
@return this byte vector.

Puts an int into this byte vector . The byte vector is automatically enlarged if necessary .


public ByteVector putLong(final long l) {
        int length = this.length;
        if (length + 8 > data.length) {
            enlarge(8);
        }
        byte[] data = this.data;
        int i = (int) (l >>> 32);
        data[length++] = (byte) (i >>> 24);
        data[length++] = (byte) (i >>> 16);
        data[length++] = (byte) (i >>> 8);
        data[length++] = (byte) i;
        i = (int) l;
        data[length++] = (byte) (i >>> 24);
        data[length++] = (byte) (i >>> 16);
        data[length++] = (byte) (i >>> 8);
        data[length++] = (byte) i;
        this.length = length;
        return this;
    }

public ByteVector putLong ( final long l ) { int length = this . length ; if ( length + 8 > data . length ) { enlarge ( 8 ) ; } byte [ ] data = this . data ; int i = ( int ) ( l >>> 32 ) ; data [ length ++ ] = ( byte ) ( i >>> 24 ) ; data [ length ++ ] = ( byte ) ( i >>> 16 ) ; data [ length ++ ] = ( byte ) ( i >>> 8 ) ; data [ length ++ ] = ( byte ) i ; i = ( int ) l ; data [ length ++ ] = ( byte ) ( i >>> 24 ) ; data [ length ++ ] = ( byte ) ( i >>> 16 ) ; data [ length ++ ] = ( byte ) ( i >>> 8 ) ; data [ length ++ ] = ( byte ) i ; this . length = length ; return this ; }

Puts a long into this byte vector. The byte vector is automatically
enlarged if necessary.

@param l
a long.
@return this byte vector.

Puts a long into this byte vector . The byte vector is automatically enlarged if necessary .


public ByteVector putUTF8(final String s) {
        int charLength = s.length();
        if (charLength > 65535) {
            throw new IllegalArgumentException();
        }
        int len = length;
        if (len + 2 + charLength > data.length) {
            enlarge(2 + charLength);
        }
        byte[] data = this.data;
        // optimistic algorithm: instead of computing the byte length and then
        // serializing the string (which requires two loops), we assume the byte
        // length is equal to char length (which is the most frequent case), and
        // we start serializing the string right away. During the serialization,
        // if we find that this assumption is wrong, we continue with the
        // general method.
        data[len++] = (byte) (charLength >>> 8);
        data[len++] = (byte) charLength;
        for (int i = 0; i < charLength; ++i) {
            char c = s.charAt(i);
            if (c >= '\001' && c <= '\177') {
                data[len++] = (byte) c;
            } else {
                length = len;
                return encodeUTF8(s, i, 65535);
            }
        }
        length = len;
        return this;
    }

Puts an UTF8 string into this byte vector. The byte vector is
automatically enlarged if necessary.

@param s
a String whose UTF8 encoded length must be less than 65536.
@return this byte vector.

Puts an UTF8 string into this byte vector . The byte vector is automatically enlarged if necessary .


public ByteVector putByteArray(final byte[] b, final int off, final int len) {
        if (length + len > data.length) {
            enlarge(len);
        }
        if (b != null) {
            System.arraycopy(b, off, data, length, len);
        }
        length += len;
        return this;
    }

public ByteVector putByteArray ( final byte [ ] b , final int off , final int len ) { if ( length + len > data . length ) { enlarge ( len ) ; } if ( b != null ) { System . arraycopy ( b , off , data , length , len ) ; } length += len ; return this ; }

Puts an array of bytes into this byte vector. The byte vector is
automatically enlarged if necessary.

@param b
an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
null bytes into this byte vector.
@param off
index of the fist byte of b that must be copied.
@param len
number of bytes of b that must be copied.
@return this byte vector.

Puts an array of bytes into this byte vector . The byte vector is automatically enlarged if necessary .