create blog

go home go home
  1. about
  2. code
  3. wiki
  4. blog

Script & the USPS Intelligent Mail Barcode

We need a way to integrate the new USPS Intelligent Mail Barcode nicely into our existing workflow. The software we use for most of our composition seems to have some… disagreements (or something)… with it at times, even though it officially supports it.

Other people using the same software recommend using the USPS’s library. That’s fine and all, but we don’t want to write a C program for each job — writing in C or C++ can be quite time consuming. And it requires compiling, creating projects, etc. In short, a lot of hassle.

While this may not be the course we end up following, I decided, tonight, that although I was half-asleep, I’d attempt to add scripting support for USPS’s library. At around 10:00, I downloaded the software from USPS. Now, roughly fifty minutes later, I have managed to write a script that uses the USPS barcode.

Here’s the script:

function main(input, output)
{
	var inputFile = new InputStream(input);
	var outputFile = new OutputStream(output);
 
	while (inputFile.ok)
	{
		//get line
		var line = inputFile.getLine();
 
		//split
		var fields = line.splitQuoted(",");
 
		//if there aren't the required amount of fields, continue to next line (if any)
		if (fields.length < 2)
		{
			outputFile.writeLine(line);
			continue;
		}
 
		//get needed fields
		var track = fields[0].trim(), route = fields[1].trim();
 
		//set output
		line = line + ",\"" + USPSBarcode.encode(track, route) + "\"";
 
		//write
		outputFile.writeLine(line);
	}
}
 
<!-- snipped: the splitQuoted string function -->

The Framework’s Script Engine made adding this to the Shell very easy (really, it should be moved into Spec, and Shell should get it from there, but for now…).

I will, over the course of the next couple of days, figure out a workflow for how I can get this code online without breaking the build for compiles without the library. Perhaps a command line switch? I will probably also move it to where it belongs: in Spec.

I will, however, go ahead and post the majority of the code here. I could have done it much quicker with a single function in global scope, but I prefer the cleanliness of using a JavaScript object (I could have still used an empty dummy object, but that wouldn’t have been proper).

#ifndef SHELL_WRAPPERS_USPSBARCODEWRAPPER_H_
#define SHELL_WRAPPERS_USPSBARCODEWRAPPER_H_
 
#ifdef SHELL_WITH_USPS_BARCODE
 
#include <string>
 
extern "C" {
	int USPS4CB( char *TrackPtr, char *RoutePtr, char *BarPtr);	
}
 
namespace Shell
{
	class USPSBarcodeProvider
	{
	public:
		USPSBarcodeProvider()
		{
 
		}
 
		std::string encode(std::string tracker, std::string route)
		{
			if (tracker.size() != 20)
			{
				return "";
			}
			if (
				route.size() != 11 && 
				route.size() != 5 && 
				route.size() != 9 &&
				route.size() != 0)
			{
				return "";
			}
 
			char res[66];
			int result = USPS4CB(
								 const_cast<char *> (tracker.data()), 
								 const_cast<char *> (route.data()), 
								 res
			);
			if (result != 0)
				return "";
 
			res[65] = NULL;
 
			return res;
		}
	};
}
 
ScriptBaseNative(Shell::USPSBarcodeProvider);
 
namespace Shell
{
	SWrap(USPSBarcodeWrapper, USPSBarcodeProvider)
	{
	public:
		USPSBarcodeWrapper()
		{
			set("encode", $(encode));
			className = "USPSBarcodeProvider";
		}
 
		SMember(encode)
		{
			if (extract(self))
			{
				return $(extract(self)->encode(arguments[0]->stringValue(), arguments[1]->stringValue()));
			}
 
			return $();
		}
	};
 
}
 
#endif
 
#endif

Leave a Reply