# “Purging” by Paige Alexis Rudnick

Ever since I read Julia Seranno’s Whipping Girl, where she points out that in media practically without fail when a transwoman is depicted there is a scene of her putting on makeup that trope has bothered me. It seemed to me that there were more interesting topics to portray such as, what do you when you realize you’re trans at a very young age?

My short story “Purging” is about just that.

It ain’t autobiographical, but you could say it’s inspired by true events. And! It’s available here.

# In Browser, Computer Vision Based, Pong

To begin, I just couldn’t resist using an a Atari harkening font in this one. 🙂

This particular project evolved my GLSL skills and started to teach my brain how to work on a GPU better which, naturally, means I have a very nicely decorated whiteboard to my right at the moment. And I’ll be sharing it too, in a moment…

I’ve been thinking about doing a Computer Vision project for a little while now. I was inclined to do a desktop app and use OpenCV but on doing some research on what goes in to computer vision I realized, “Hey, I know the tools to make this work in browser.” So, I did.

My first task to get Computer Vision working was take the RGB feed from my WebCam and convert it to HSV. I’ve done chroma keys before just using the raw RGB values but with the recommendation that HSV might work better, I figured why not give it a try? This is where the GLSL came in and what I had to write was an implementation of the following:

Let $$R =$$ the Red RGB component in the range 0.0 to 1.0

Let $$G =$$ the Green RGB component in the range 0.0 to 1.0

Let $$B =$$ the

Blue RGB component in the range 0.0 to 1.0

Let $$Epsilon =$$ a inconsequential float value to prevent division by 0.

The definition of $$max$$ is elided, but it just returns the maximum of the values it was passed in.

$$H =\begin{cases} G – B & max(R, G, B) = R \\ B – R & max(R, G, B) = G \\ R – G & max(R, G, B) = B\end{cases}$$

$$H$$ had to be accompanied with a related offset value:

$$H’ =\begin{cases} 0 & max(R, G, B) = R \\ 1/3 & max(R, G, B) = G\\ 2/3 & max(R, G, B) = B\end{cases}$$

So my final result for Hue is actually $$H”=H+H’$$ This was because in the HSV colorspace, $$H$$ is represented as a circle going round from $$R \rightarrow G \rightarrow B \rightarrow R$$ So, in order to get select the right hue, an offset will need to be applied to get the value round to the right place.

$$S=\frac{\Delta}{max(R, G, B) + Epsilon}$$

And finally

$$V=max(R, G, B)$$

I found some other documentation about this calculation online and found it messy. That might be normal when discussing math like, I don’t really know,  this but my engineering brain likes things broken down into their individual components. Hopefully, the above will help someone else out! 🙂 Now to calculate that on the GPU making it time to live up to my promise of bringing the whiteboard in…

I ended up being heavy on mix() and step() in order to reduce the branching I had to write. Branching, as I understand, is getting to be less of a concern in GPU programs but the article saying that branching implementation was improving was from 2011 and that’s too recent to assume all GPU’s will behave nicely. Below those function notes, there’s a tracking of how my values were going to flow through in the vectors so I could end up with a the maximum in the first position, the two values I needed to subtract to get my $$H$$ and finally the offset $$H’$$ that went with the selected $$H$$ so I could calculate $$H”$$ properly. For the curious, the shuffling that’s done with mix() and step() was effectively a vectorized ternary operator.

The conversation of RGB to HSV and writing the GLSL shader to do that was most of the effort. But the shader wasn’t quite done yet. The final step was passing Min and Max values for each value: H, S, V. When all three where within the defined min and max, the shader needed to return white, when any of them were out of bounds, the shader had to return black. This way, the user can select an object in the real world by its color that will function as a paddle. Now I did look for and find shader implementations of RGB to HSV online, however, I opted to roll my own to make sure I understood what was going on as this was pretty much the beating heart of this project.

On the JavaScript side of things I did run into a problem. I wanted to use sliders so users could hone in on the color they wanted to select. However, HTML5 only allocates one thumb per slider. I know I could have used jQueryUI for to get two thumbs but I opted to stay away and handle the problem myself. It was also tempting to use three.js to handle the WebGL side of things but I decided to not bring it in either. The changes weren’t too significant from my ANSI.WebGL project so I saw no need to take on another dependency.

The JavaScript I did write is pretty straight forward. There’s a ball (a div that’s been styled to look like aball) that flys around and when it hits a paddle it flies back the other way. Hitting here has been defined as the left or right side of the ball hits a white paddle pixel. When that happens, the column of pixels is counted for connected white pixels to figure out the length of the paddle. If it’s above a threshold (provided to filter out artifacts) the calculation figures out where the ball was hit in relation to the paddle then the ball will bounce away at an angle. The only “gotcha” I ran into with this part was when I read the pixels from the buffer, I found them inverted which broke my hit detection! But it was a simple fix to right them thankfully.

For much larger computer vision problems I probably would turn to something like OpenCV. Still getting to understand something like sometimes, we convert to the HSV color space, is I think very important! Understanding how the tools you are using work I hold to be key to actually using them well. It also allows you to answer a question I’ve mentioned before as being part of my process. 😉

You will need either a recent version of Firefox or Chrome in order to run this project due to the needs of getUserMedia() and WebGL.

https://github.com/dreambbqchild/CVPong

http://www.animetedstudios.com/webapps/CVPong/

# ANSI.WebGL

The problem I set out for myself of rendering ANSI art in a web browser turned out to have more ins and outs than I anticipated and quickly became a case where I needed to iterate and refine my idea in order to carry it out. In the beginning, I knew doing something like rendering a few thousand <span>s, one for each character so each character could be styled, was not going to be a viable solution because it would not scale to work well on all browsers. So I attempted to go with SVG as my solution and use a mask in order to get all the colors I needed, kinda like using an image brush,  as this would afford me the possibility of limiting the number of elements I needed to create. After I got the right @font-face setup, the solution worked great in Opera (Blink), but not so hot in Firefox.

At that point I considered dropping the whole project as I found myself being pushed to a HTML5 canvas based renderer for speed and I didn’t really want to reinvent the wheel as I found an implementation online that solved the problem that way already. Then, I lost my job. 🙁

But! Ok! 🙂 New reasons to putter: Keep my skills fresh, solve an interesting problem, learn something new and have a new project to show off to would be employers!

On project resumption, I opted to try and go the WebGL route. One thing I like about this solution is I only needed one sprite of all the characters to render any color combination I wanted as I’m able to draw each character with a fragment shader. When it reads black for the current texture pixel, put the background color, white put the foreground. Simple rule with a lot of flexibility.

The project was also a great opportunity to play with newer features to JavaScript that I haven’t been able to use due to the need to support legacy browsers. In addition, it features my ability organize which represents one of my two greatest strengths as a software engineer. The other being I do this job primarily because I have a passion for it. 🙂

https://github.com/dreambbqchild/ANSI.WebGL

http://www.animetedstudios.com/webapps/ANSI.WebGL/

# OS X Found me Within 23 Feet

Same topic as my last post, only this time a OS X implementation. Which is a little more troubling because now I’m next door to iOS and therefore iPhones. And iPads. And iPod touches…

int main(int argc, const char * argv[])
{
@autoreleasepool {

//Get the WiFi
NSMutableArray* wifiAccessPoints = [[NSMutableArray alloc] init];
for(NSString *name in [CWInterface interfaceNames])
{
CWInterface* interface = [CWInterface interfaceWithName:name];
//enumerate over all visible networks.
for(CWNetwork *network in [interface scanForNetworksWithName:nil error:nil])
{
NSDictionary* dict = @{@"macAddress" : [network bssid],
@"signalStrength" : [NSNumber numberWithInteger:
}
}

//Create the request object;
NSDictionary* dictRequest = @{@"wifiAccessPoints" : wifiAccessPoints};
NSError* err = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dictRequest
options:NSJSONWritingPrettyPrinted
error:&err];

//Transmit the request.
NSURL *url = [NSURL URLWithString:(Still Elided)];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonData];

err = nil;
NSHTTPURLResponse *res = nil;
NSData *locationData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&res
error:&err];
if(!err)
{
//There I am!
NSString* locationString = [[NSString alloc] initWithData:locationData
encoding:NSUTF8StringEncoding];
NSLog(@"%@", locationString);
}
}
return 0;
}

I’m also a little shocked by how short it is.

# Exploiting HTML5 Geolocation is Too Easy

Titling this post was hard. I wanted something attention getting but yet not hyperbolic. Hopefully what I’ve selected works. I do think it’s a pretty no nonsense way to sum up what I’m about to go into here because Computer Security boils down to answering the question of, “Secure against whom?” Well, I think I should have been driven to a point where I gave up and started to work on something else instead of being here now, able to write this post with the findings I have.

What got this started was when I took Introduction to Computer Security in Grad School my professor’s stated goal was to make the students in the class think like an attacker. Today, I think the “attacker” mentality is a good one for all software engineers to have. It gets us thinking off the happy path, in the weeds and muck, perhaps finding a path to somewhere that you as the author didn’t even know existed.

In this post, that path metaphor may be too literal.

After I was done with the class I remember thinking to myself, “Gee, I know how to do some Internet Explorer automation, I wonder if I can use IE to get my physical location on Earth?” So, I spent some time figuring out how to do just that and those results results are here. I was going to make this post a retelling of that find but I got to thinking, “You know Paige? Over the years a lot of people have picked on Internet Explorer. Don’t cha think there’s enough fodder out there for that?” Well, I happened to agree with me so I thought, what else could I go after? Well, what about the service that makes HTML5’s Geolocation work itself?

Using the HTML5 Geolocation service via the familiar way is done in browser, through JavaScript, with code that has these basic parts:

navigator.geolocation.getCurrentPosition(function(p) {
console.log(p.coords.latitude);
console.log(p.coords.longitude);
});

This is pretty much what my Internet Explorer solution relied on. Back then, I found that my IE instance was “hung” and that turned out to be because there was a, “Do you want to allow [X] website access to your location?” prompt up. I didn’t want to look at a flashing IE window as automation ran so I added some registry keys to grant permanent permission to IE for it to be able to use Geolocaiton on a website I browsed to, automatically. When I was done I realized I’d in effect created something that could get my location on Earth without my permission.

Now, back to the task at hand.

What happens at the lower levels when you call getCurrentPosition in JavaScript? Well, in my case where the only wireless access I have is WiFi, all the wireless access points are scanned for their MAC addresses and signal strength because HTML5 Geolocation works by triangulating your device with the Access Points that it can see.

A lot of code is about to follow but all this C++/CLI code is doing is collecting the aforementioned information.

List<AccessPoint^>^ AccessPoint::QueryAll()
{
DWORD dwCurrentVersion = 0;
HANDLE hClient = INVALID_HANDLE_VALUE;
DWORD dwResult = WlanOpenHandle(2, nullptr, &dwCurrentVersion, &hClient);
auto results = gcnew List<AccessPoint^>();

if(dwResult != ERROR_SUCCESS)
return results;

PWLAN_INTERFACE_INFO_LIST pIfList = nullptr;

dwResult = WlanEnumInterfaces(hClient, nullptr, &pIfList);
for(int i = 0; i < pIfList->dwNumberOfItems; i++)
{
PWLAN_BSS_LIST pBSSList = nullptr;
dwResult = WlanGetNetworkBssList(hClient,
&pIfList->InterfaceInfo[i].InterfaceGuid,
nullptr, dot11_BSS_type_any, false,
nullptr, &pBSSList);
if(dwResult == ERROR_SUCCESS)
{
PWLAN_AVAILABLE_NETWORK_LIST pAvailableList = nullptr;
dwResult = WlanGetAvailableNetworkList(hClient,
&pIfList->InterfaceInfo[i].InterfaceGuid,
WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_MANUAL_HIDDEN_PROFILES,
nullptr, &pAvailableList);

if(dwResult == ERROR_SUCCESS)
{
for (int availableIndex = 0; availableIndex < pAvailableList->dwNumberOfItems;
availableIndex++)
{
for(int bssIndex = 0; bssIndex < pBSSList->dwNumberOfItems; bssIndex++)
{
if(!memcmp(&pAvailableList->Network[availableIndex].dot11Ssid,
&pBSSList->wlanBssEntries[bssIndex].dot11Ssid,
sizeof(DOT11_SSID)))
{
auto name = String::Empty;

for(int c = 0;
c < pBSSList->wlanBssEntries[bssIndex].dot11Ssid.uSSIDLength;
c++)
name += (Char)pBSSList->wlanBssEntries[bssIndex].dot11Ssid.ucSSID[c];

for(int c = 0; c < 6; c++)
{
if(c > 0)

.ToString("X02");
}

int quality = -(pAvailableList->Network[availableIndex].wlanSignalQuality
/ 2);
break;
}
}
}

if(pAvailableList != nullptr)
WlanFreeMemory(pAvailableList);
}

if(pBSSList != nullptr)
WlanFreeMemory(pBSSList);
}
}

if(pIfList != nullptr)
WlanFreeMemory(pIfList);

if(hClient != INVALID_HANDLE_VALUE)
WlanCloseHandle(hClient, nullptr);

return results;
}

Then I just had to send off the collected information to the right Web Service which I did in C#:

class Program
{
static void Main(string[] args)
{
var list = AccessPoint.QueryAll().Select(ap => new WiFiAccessPoint()
{
signalStrength = ap.SignalStrength
});
var data = new Request()
{
cellTowers = new object[0],
wifiAccessPoints = list.ToArray()
};
var serializer = new JavaScriptSerializer();
var message = serializer.Serialize(data);

byte[] bytes = System.Text.Encoding.ASCII.GetBytes(message);

var request = WebRequest.Create([Elided but easy to get what is needed])
as HttpWebRequest;
request.UserAgent = [Elided but also very easy to figure out, if even needed];
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = bytes.Length;
using (var stream = request.GetRequestStream())
stream.Write(bytes, 0, bytes.Length);

string result = string.Empty;
using (var response = request.GetResponse())
{
if (response == null)
throw new Exception("Yeah! I think this could be a good thing!");

using (var responseStream = response.GetResponseStream())
{
{
Console.WriteLine(result);
}
}
}

using (var file = new StreamWriter("result.txt", false))
file.Write(result);
}
}

Regarding the elided bits, I’m not going to reveal what I did to fill them in cause that gets into information I’d rather you discover on your own. A little bit of critical thinking is all that’s needed to find it just like only a little bit of critical thinking was needed to carry this out end to end. Anyway and as for WiFiAccessPoint and Request, they are simply:

public class WiFiAccessPoint
{
public string macAddress { get; set; }
public int signalStrength { get; set; }
}

public class Request
{
public object cellTowers { get; set; }
public WiFiAccessPoint[] wifiAccessPoints { get; set; }
}

When I ran my project, my position was returned to me with an error of 33 feet. I was given no prompt and if I hid my console window I would have had no indicator that my process was running unless I was staring at process monitor.

The only thing that prevents an attacker from developing software that gets your device location is a requirement from the W3C (The group that dictates how HTML5 Geolocation shall work) that mandates apps ask for permission. If it would always have to ask instead of leaving it to merely trusting developers, or if it took someone with more knowledge than I to pull this off I wouldn’t be bothered. As much. I like Geolocation for navigation, but I also like being asked my permission to opt apps in to using the Geolocation services on my devices. Google Maps, ok. Others, it depends.

# Using IE to Save SVGs as Bitmaps to Wherever

You know, something that’ll make you appreciate .NET really fast is programming COM by hand in C++. I suspect what follows can be converted into C# but I didn’t go that route because while working to get to this point, I didn’t want to worry about doing COM Interop in .NET on top of the problem I was trying to solve. Therefore, I ended up in C++ and COM.

For the SVG to bitmap problem I was originally trying to solve, I started out by going using the canvg JavaScript library. Definitely a recommended way to go if you’re trying to solve this problem and the output works for you. Personally, the Graphic Designer side of me looked at my nice pretty anti-aliased browser handled SVG renderings, then at my jaggy HTML Canvas rendering and went, “Aw.” I also didn’t like being limited because SVG has those spiffy diffy filters and I wanted to be able to use them too. So I figured I was going to have to do the rendering server side.

On writing that last, now seems like a good time to remind folks, sanitize/be mindful of your inputs! 🙂

I knew I could get another library to handle the rendering but I didn’t see why I needed to. I have a perfectly good SVG renderer on my computer after all. It’s just embedded in Internet Explorer and much of IE is COM. That means I can get at its objects too, if one knows how.

I’m going to assume that most of the people who read this are more comfortable with C#. I’m also going to assume that because you’ve made it this far after I’ve talked about C++ and COM, odds are you’re my kind of developer! 🙂

Finally, before the good stuff a note that as is my motif I’m not going to be giving ya’ll a final working solution here but I will give you the knowledge to make it work for you. I’m a teach a developer to code kind of gal after all!

I like to start with the beginning so, here’s your includes because it drives me batty when people leave those out of their code walk throughs!

#include <windows.h>
#include <mshtml.h>
#include <gdiplus.h>
#include <functional>
#include <iostream>

#import <mshtml.tlb>

#pragma comment( lib, "gdiplus" )

const int HIMETRIC_INCH = 2540;

using namespace Gdiplus;
using namespace std;

I’ll assume knowledge of the basic #include, the #import directive is going to pull in type description information for the COM interfaces I’ll be using. The #pragma comment() is a way to add a reference to a type library in code instead of adding the reference to the project. Great way to avoid, “Gagh! I setup my libraries for Debug/Release mode only!” Finally, HIMETRIC_INCH is a constant needed to get the output to render at the right size. We’ll see that again later.

From here we’re clear to look at main:

int main(int argc, char* argv[])
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
ConvertToImage();
CoUninitialize();
GdiplusShutdown(gdiplusToken);
return 0;
}

First thing to note is the GdiplusStartup call. That’s getting our application prepared to do the final rendering using GDI+. You wanna use GDI+ in your application, you gotta do this. As cleanup, when you’re done you need to call GdiplusShutdown as shown above.

Next is the actual initialization of COM with CoInitalizeEx. This is responsible for setting up COM for use by the calling thread. I’m also calling it with COINIT_APARTMENTTHREADED so I don’t have to worry about concurrency.

Ok, now on to ConvertToImage:

void ConvertToImage()
{
HRESULT hr = E_FAIL;
int width = 120, height = 120;
MSHTML::IHTMLDocument2Ptr pDoc = nullptr;
hr = CoCreateInstance(CLSID_HTMLDocument, nullptr, CLSCTX_INPROC_SERVER,
IID_IHTMLDocument2, (void**)&pDoc);
if(SUCCEEDED(hr))
hr = SetDocumentViewPort(pDoc, width, height);

if(SUCCEEDED(hr))

if(SUCCEEDED(hr))
RenderImage(pDoc, width, height);
}

I have some constants here (width, height) that just happen to match my SVG output. Bad, icky, terrible thing to do but I’m here to illustrate as simply as possible.

The most interesting thing happening here is the call to CoCreateInstance. Here I’m creating an HTML Document and note, I am bypassing IE entirely. Also note the CLSCTX_INPROC_SERVER parameter. That’s telling COM To create the document in the space of the running process. This is one of the very extremely important things for our goal here.

The way that I’m checking if my HRESULTS succeed with SUCCEEDED(hr) is a result of my absolute abhorrence to using goto statements and desire to avoid arrow code. Also, I’m using smart COM pointers here. Usually I’d have to be aware of:

• IUnknown->Release()

In order to avoid a memory leak. If you don’t know what I’m talking about here, that’s okay for the moment just if you find yourself working with raw COM you will need to know about it, else you’re going to have a bad time. By that I mean you’ll have a memory leak.

Next, we have to set the size of our document which SetDocumentViewPort handles.

HRESULT SetDocumentViewPort(MSHTML::IHTMLDocument2Ptr pDoc, int width, int height)
{
auto hdc = GetDC(NULL);
auto x = MulDiv(width, HIMETRIC_INCH, GetDeviceCaps(hdc, LOGPIXELSX));
auto y = MulDiv(height, HIMETRIC_INCH, GetDeviceCaps(hdc, LOGPIXELSY));
ReleaseDC(NULL, hdc); IOleObjectPtr pOle = nullptr;
HRESULT hr = pDoc->QueryInterface(IID_IOleObject, (void**)&pOle);
if(SUCCEEDED(hr))
{
SIZEL size = {x , y};
return pOle->SetExtent(DVASPECT_CONTENT, &size);
}
return hr;
}

In completing the task at hand, this was one of the trickiest things to figure out starting with what interface to use and setting it to size in what units? The MulDiv lines are handing the unit conversion from pixels to “device units”. Then, via a IOleObject, SetExtent is called which tells the object, in our case our HTMLDocument its size.

Next for you JavaScript developers we’re actually going to get into a little familiar territory.

HRESULT LoadHTML(MSHTML::IHTMLDocument2Ptr pDoc)
{
SAFEARRAY* psa = SafeArrayCreateVector(VT_VARIANT, 0, 1);
VARIANT *param;
_bstr_t bsData("<!DOCTYPE html><html>...<meta http-equiv=\"X-UA-Compatible\"
content=\"IE=11\" />...svg...</html>");
HRESULT hr = SafeArrayAccessData(psa, (LPVOID*)&param);
if(SUCCEEDED(hr))
{
param->vt = VT_BSTR;
param->bstrVal = bsData;
hr = pDoc->write(psa);
if(SUCCEEDED(hr))
hr = pDoc->close();
SafeArrayDestroy(psa);
}
if(SUCCEEDED(hr))
{
MSHTML::IHTMLDocument6Ptr pDoc6 = nullptr;
if(SUCCEEDED(hr))
hr = pDoc->QueryInterface(IID_IHTMLDocument6, (void**)&pDoc6);

if(SUCCEEDED(hr))
{
_variant_t mode = pDoc6->documentMode;
cout << mode.fltVal << endl;
MessagePump([&]() -> bool {return strcmp(pDoc->readyState, "complete") != 0;});
}
}
return hr;
}

Need to do a little manual memory management here around the SafeArrays. But another one of those very extremely important things to note is the X-UA-Compatible meta tag. This’ll be familiar and I’ve got mine set to IE=11 for no good reason beyond it’s not IE 7. It turns out, when you embed IE objects like this it will default to IE 7 for rendering. Therefore, to be able get the SVG rendering goodness we’re after we need to tell IE to please be a current version of the browser.

The body tag of the HTML is elided but it’ll also necessary to set your CSS margins and padding on your body element to be 0px.

Next see those calls to write() and close()? Those are in fact the same write() and close() you know of from JavaScript! They end up being a handy way to create the document we want to render.

From there I’ve got a check on the current documentMode to verify we’re not using IE 7. The documentMode property however, is not implemented on the IHTMLDocument2Ptr I’ve got currently so I needed to get an IHTMLDocument6Ptr. From there I pump Windows messages to get the document into the complete state. Sleeping here will get you nowhere in the COM Context that we’re using.

On to the home stretch.

void RenderImage(MSHTML::IHTMLDocument2Ptr pDoc, int width, int height)
{
IViewObjectPtr pView = nullptr;
if(SUCCEEDED(pDoc->QueryInterface(IID_IViewObject, (void**)&pView)))
{
auto bmp = new Bitmap(width, height);
auto g = Graphics::FromImage(bmp);
auto graphicsHDC = g->GetHDC();
RECT rcClient = {0, 0, width, height};
HRESULT hr = pView->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, graphicsHDC,
reinterpret_cast<LPRECTL>(&rcClient), NULL, NULL, 0);
g->ReleaseHDC(graphicsHDC);
if(SUCCEEDED(hr))
{
CLSID pngClsid;
GetEncoderClsid(L"image/png", &pngClsid);
bmp->Save(L"circle.png", &pngClsid, nullptr);
}
delete g;
delete bmp;
}
}

And we’ve got our image! What this does is gets an IViewObject which handles rendering to a Device Context Handle, in this case our GDI+ graphics object context. Note, here is why we told COM we wanted to create objects in the current processes’ memory space too. Had we not done that, we wouldn’t have an image coming. But we did and do so we’ll render out with the Save() call.

We could actually render out a whole lot more than just SVG here, I’m talking full webpages with no changes to the code. This has also been only one demonstration of what you can do with IE automation. I’m thinking of revisiting another soon. But for now, a demo project for ya is available here. Enjoy!

# Making C# Curry

A colleague of mine told me about currying sometime ago and I’ve been intrigued by the idea ever since. After playing around a little bit with F# and coming to understand the concept better, I thought I’d take a crack at making it work in C# because it seemed like a fun technical challenge to take on.

To begin, currying is taking a function with multiple arguments like:

string Foo(string str, object obj, int num)

And transforming it so the function call be called as a chain of function where the single parameter to that function correlates to a parameter in the original function call.

Foo(str)(obj)(num)

Currying is apparently a common thing in functional programming languages, like F# is.

So I got to thinking that this is interesting, but I wanted to be able to use the concept on an arbitrary function in C#. I didn’t want to create a bunch of Func<> templates by hand either. I just wanted it to work with any method that takes multiple parameters.

Now, I’ve chosen to start with focus here and so I didn’t bother with instance methods yet. Not going to be hard to add, I just wanted as clean a path to solving the problem at hand: the transformation itself.

First, I started to think about the individual method signatures. In the case of Foo, they would be:

str = Func<String, Func<Object, Func<Int32, String>>>
obj = Func<Object, Func<Int32, String>>
num = Func<Int32, String>

I think you can see why I didn’t want to get bogged down in Func<>s 🙂

What I needed to do then, was generate these types, define a way to capture the arguments passed in by the caller, and generate a function. The class I’ve come up with thus far to do that is as follows:

public static class Curry
{
//Makes the return types for Func<,[THIS ONE!!!]>
private static Type[] ReturnTypes(Type returnType,
ParameterInfo[] parameterInfo)
{
var result = new Stack<Type>();
result.Push(returnType);
foreach (var param in parameterInfo.Skip(1).Reverse())
result.Push(typeof(Func<,>).MakeGenericType(param.ParameterType,
result.Peek()));

return result.ToArray();
}

private static LambdaExpression Make(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
//Prepare the pieces for the Func<>s
var returnTypes = ReturnTypes(methodInfo.ReturnType, parameters);
var expressions = new ParameterExpression[parameters.Length];

//Create the expression parameters str, obj, num
for (int i = 0; i < expressions.Length; i++)
expressions[i] = Expression.Parameter(parameters[i].ParameterType,
parameters[i].Name);

//Create the call Program.Foo(str, obj, num)
Expression lastOperation = Expression.Call(methodInfo, expressions);
//Build Curried Method Call, note I'm building back from
//the method invocation.
//str => obj => num => Program.Foo(str, obj, num)
for (int i = parameters.Length - 1; i >= 0; i--)
{
var genericType = typeof(Func<,>)
.MakeGenericType(parameters[i].ParameterType,
returnTypes[i]);
lastOperation = Expression.Lambda(genericType,
lastOperation,
expressions[i]);
}

return (LambdaExpression)lastOperation;
}
}

It takes a MethodInfo object so the user can choose whatever (currently static) method they want to use. Will need to be static and public right now. So what’s happening here is Make() gets all the parameters from the MethodInfo passed in then creates the Func<>s in the way discussed above. In addition, it creates the parameter name expressions that will allow the final Lambda to capture and use the parameter values the user passes in. Note, the parameter names equal the supplied MethodInfo’s for clarity. Then finally, starting from the Method call, it builds out the curried method structure before returning a lambda.

The first way that I came up to use this with was via a dynamic method call as such.

public static dynamic Dynamic(MethodInfo methodInfo)
{
return Make(methodInfo).Compile();
}

Where the method is defined in my Curry static class and which I was then able to consume in my main program like so.

public class Program
{
public static string Foo(string str, object obj, int num)
{
return string.Concat(str, obj, num);
}

static void Main(string[] args)
{
var methodInfo = typeof(Program).GetMethod("Foo", BindingFlags.Static |
BindingFlags.Public);
dynamic fn = Curry.Dynamic(methodInfo);

//Call made in pretty much the same way.
//Prints string[System.Object]42
var result = fn("string")(new object())(42);
Console.WriteLine(result);

//Reuse parameters
//prints Hello, Worldx1
//prints Hello, Worldx2
//...
//prints Hello, Worldx10
var partial = fn("Hello, ")("World x");
for (int i = 1; i <= 10; i++)
Console.WriteLine(partial(i));

}
}

Which achieved my goals, but I’m not a fan of dynamic. I’m in a strongly typed language here so I’d like to take advantage of that. The best solution I’ve come up with to achieve that goal would be to build some kind of utility that integrates into Visual Studio to build the Curried Calls I want. Building the plugin is outside the scope of this document, but, I can render the C#:

public static string CSharp(MethodInfo methodInfo, string name)
{
var lambda = Make(methodInfo);
var builder = new StringBuilder();
builder.AppendFormat("public static class {0}\r\n", name);
builder.Append("{\r\n");
//PrettyPrint is an extension method to render the type in C#
builder.AppendFormat("\tpublic static {0} Exec()\r\n",
lambda.Type.PrettyPrint());
builder.Append("\t{\r\n");
//Actually, the lamda.ToString() needs to be fixed in order to deal with
//namespaces properly but I left that out as it's not germane to the
//theory I'm trying to work with.
builder.AppendFormat("\t\treturn {0};\r\n", lambda.ToString());
builder.Append("\t}\r\n");
builder.Append("}\r\n");

return builder.ToString();
}

Which I put in my Curry static class and will generate a static class like this for me…

public static class FooTarget
{
public static Func<String, Func<Object, Func<Int32, String>>> Exec()
{
return str => obj => num => Program.Foo(str, obj, num);
}
}

…that I can use exactly the same way as the dynamic calls above only now with strongly typed goodness which means intellisense.

I’ve gotten the ball rolling here on what I think is a pretty good start to enable currying in C#.

You can get a demo project here.

# The Axiom is Wrong

Every once and a while I see people assert that being trans is a “mistake”. Being trans isn’t a mistake, it’s just another way to be. So when someone takes as an axiom that being trans is somehow a “mistake”, let me assure you, they are mistaken.

# Nano Nano

Hi.

I’m still here. Still updating.

Only.

National Novel Writing Month is intense.

But as a taste of what’s to come here:

var il = getter.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, ezPropertyBuilder);
il.Emit(OpCodes.Ldstr, name);
il.Emit(OpCodes.Callvirt, Safe.Get(propInfo.PropertyType));
il.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getter);

I’ll be back. 🙂