Tuesday, March 30, 2010

Insert, delete space at any place in file without making temporary file copy

Goal:
Implement methods that insert or delete space at any place in file (affecting file length), using technique that copies content within file so there is no need for temporary file.

Implementation idea:
When inserting space of N bytes:
    1. Extend file size by N bytes
    2. Copy/shift all data after insertion position, N bytes towards file's end
    When deleting space of N bytes:
        1. Copy/shift all data after deletion position + N bytes, N bytes towards file's beginning
        2. Shrink file size by N bytes

    Why?
    Framework and system file API offer functions to write new file or append to existing, there are no functions to insert new data (and not overwriting existing) in existing file at some arbitrary position e.g. beginning of file or middle of file. Also, there are no functions for removing data in similar way.

    Usual solutions that I've seen tend to (to simulate insert):
    1. make temporary file
    2. append data before insert position from original file
    3. append data to insert
    4. append data after insert position from original file
    5. delete original file
    6. rename temporary file to original file's name
    Similar technique is used to simulate deletion of part of file.

    Problem with that approach is:
    • choosing name for temporary file
    • need for disk space for original and temporary file
    • copying of original data positioned before insert/delete position (no need for that)
    Usage example:

    Legend:
    Unchanged
    Copied
    Filled/Inserted

    Notes:
     - Each step works on resulting data from previous step.
     - Inserted part can be also interpreted as unchanged data, but logically it is treated as uninitialized as it is expected that user will write new data after the part is inserted.


    Initial file stream (letter 'A' is at position 0)
    FileStream file = new FileStream("test.txt", FileMode.Create, FileAccess.ReadWrite);
    byte[] initial = Encoding.ASCII.GetBytes("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    file.Write(initial, 0, initial.Length);
    
    Result: ABCDEFGHIJKLMNOPQRSTUVWXYZ


    Insert (make room for) 4 bytes at position 7(letter 'H')
    Quazistax.QSFile.InsertFilePart(file, 7, 4);
    
    Result: ABCDEFGHIJKHIJKLMNOPQRSTUVWXYZ


    Fill 4 bytes at position 7 with '='
    Quazistax.QSFile.FillFilePart(file, 7, 4, (byte)'=');
    
    Result: ABCDEFG====HIJKLMNOPQRSTUVWXYZ


    Delete 7 bytes at position 16 (part 'MNOPQRS', letter 'M' is at position 16)
    Quazistax.QSFile.DeleteFilePart(file, 16, 7);
    
    Result: ABCDEFG====HIJKLTUVWXYZ


    Copy 8 bytes from position 5 (letter 'F') to position 14 (letter 'K')
    Quazistax.QSFile.CopyFilePart(file, 5, 14, 8);
    
    Result: ABCDEFG====HIJFG====HIZ

    Test:
     
    Source code:
    You can download the source here.

    Friday, March 26, 2010

    Managed way to show Drag&Drop feedback image while dragging

    Goal:
    Show translucent image under cursor while dragging data, inside own application or between applications, without using P/Invoke.

    Implementation idea:
    Using translucent top level Form that follows cursor while dragging

    Test results:
    Test is done only on Windows XP so i don't know if there is some unexpected different behavior on other platforms.

    Using image with specified transparent color
    [Cursor is in the middle, but isn't captured with Print Screen]

    Using dynamically generated image
    Features:
    • Show image with same level of translucency through pixels
    • Show image in shape other then rectangle by specifying color which is rendered transparent
    • Specify relative offset of cursor to image
    • Specify image opacity (greater opacity = lower translucency)
    Caveats:
    • Can not render images with different alpha per pixel.
    Source code:
    You can get the source here.

    Thursday, March 25, 2010

    Dynamic constructor invocation - based on Timwi's dynamic method invocation

    This is an addition to Timwi's excellent post: Dynamic method invocation without the TargetInvocationException wrapping.

    What I find it useful for:

        When you write a program that invokes methods through delegate's "Invoke" function, debugger does not break on place where that exception is thrown in invoked method, it breaks on "Invoke" function, with original exception wrapped as InnerException of TargetInvocationException.
        Timwi's approach solves that problem (debugger break position is in the invoked method, and there is no exception wrapping)

    What is changed:
    • made some modifications so it can be compiled for .Net 2.0
    • InvokeDirect renamed to Invoke
    • added Invoke overload that invokes constructor by ConstructorInfo
    • (details can be seen in source, search for "Quazistax" in comments)
    Basic idea behind implementation:
    • For each new constructor signature, dynamically create class with static method that returns object created using "new" on desired ConstructorInfo, and cache that method in dictionary with provided ConstructorInfo as key.
    e.g. for Form parameterless constructor we dynamically create something like this:
    public class FormConstructorGeneratedClass
    {
        public static Form Construct()
        {    return new Form();    }
    }
    
    Dynamically creating method that calls constructor with specified signature:
    private static MethodInfo createConstructorMethod(ConstructorInfo con, string sig)
    {
        var typeBuilder = modBuilder.DefineType("construct " + sig + ".GeneratedClass",
            TypeAttributes.Public,
            typeof(object));
    
        // Create a Construct method that creates new object trough given constructor
        var methodBuilder = typeBuilder.DefineMethod("Construct",
           MethodAttributes.Public | MethodAttributes.Static,
           con.DeclaringType, getParameterTypes(con));
    
        // Now generate IL which will do constructing.
        // Generated IL is equivalent to the following single line of C# code:
        // return new ConstructedType(parameters[0],  parameters[1], ...);
        // assuming that ConstructedType is type for which ConstructorInfo is given
        var il = methodBuilder.GetILGenerator();
        ParameterInfo[] parameters = con.GetParameters();
        for (int i = 0; i < parameters.Length; ++i)
            EmitLdarg(il, i);
    
        il.Emit(OpCodes.Newobj, con); //calling constructor
        il.Emit(OpCodes.Ret);
    
        return typeBuilder.CreateType().GetMethod("Construct");
    }
    
    • When invoking constructor, get from cache method created in step before and invoke it through Timwi's approach
    Source code:
    You can get the source here.