Another comic-book exercise here, this time taking the very full life of a historical figure, Jacques Lusseyran, as the topic. I don't think I entirely succeeded in capturing his full life in 9 panels - too much to record really - but here it is.
Sunwheel
Dave Crane's blog ::: Web Tech, Comic Books, Traceability, Digital Art, Sustainability, Stuff
Thursday 7 October 2010
Monday 27 September 2010
Life in One Page
I've been playing with a load of other wannabe cartoonists over at At Millarworld recently, and set up a challenge to depict someone's entire life in a one-page, nine-panel story, and see how far we could push the envelope within that restricted format. Here's one of my attempts, in which the narration only covers the entire life (second-hand), and the panels cover a single moment. Does it work for you?
Wednesday 8 September 2010
When is a log() statement not just a log() statement?
Came across the following interesting situation today in a Groovy app we're developing.
We read some data into a ByteArrayInputStream, in order to pass it into a shared interface that takes an InputStream as argument. Stopping the code in the debugger at this point shoes that the stream cursor is set at the first byte.
Stepping through into the service that implements the interface, the same InputStream now has it's cursor set at the end of the stream?! (And hence, iterating through it won't return any data.) As we're passing in a ByteArrayInputStream, we can call reset(), but not every InputStream implementation supports reset(), and the interface we're calling expects a generic InputStream. But, more fundamentally, why has the InputStream cursor moved from the start to the end of the stream anyway? What's going on?
Well, first thing to mention is that the implementation uses a standardised parameter-checking piece of code, that is injected into the code via the Groovy meta-class mechanism. So between passing the stream to the interface, and the implementation seeing it, it's been through the parameter-checker.
Within the parameter-checker is the offending line of code:
originally written with the expectation that the value would be a simple primitive. Here, value is the InputStream. So, in order to construct the log statement (whether or not our logger config is set up to display it or not, as we've omitted the recommended if(log.isDebugEnabled()) clause), we call Groovy's GString interpolator on our InputStream, which - guess what? - reads through the stream (not, as I would have expected, calling InputStream.toString()).
So, main lessons from this for today:
Here's a sample Groovy script that demonstrates the issue in a nutshell:
resulting in this:
UPDATE: If you want to have a play with the script, it's at the funkadelic Groovy Web Console here.
Thanks to Al & Gav at HF for helping to dig this one out!
We read some data into a ByteArrayInputStream, in order to pass it into a shared interface that takes an InputStream as argument. Stopping the code in the debugger at this point shoes that the stream cursor is set at the first byte.
Stepping through into the service that implements the interface, the same InputStream now has it's cursor set at the end of the stream?! (And hence, iterating through it won't return any data.) As we're passing in a ByteArrayInputStream, we can call reset(), but not every InputStream implementation supports reset(), and the interface we're calling expects a generic InputStream. But, more fundamentally, why has the InputStream cursor moved from the start to the end of the stream anyway? What's going on?
Well, first thing to mention is that the implementation uses a standardised parameter-checking piece of code, that is injected into the code via the Groovy meta-class mechanism. So between passing the stream to the interface, and the implementation seeing it, it's been through the parameter-checker.
Within the parameter-checker is the offending line of code:
log.debug("parameter ${name} -> ${value}")
originally written with the expectation that the value would be a simple primitive. Here, value is the InputStream. So, in order to construct the log statement (whether or not our logger config is set up to display it or not, as we've omitted the recommended if(log.isDebugEnabled()) clause), we call Groovy's GString interpolator on our InputStream, which - guess what? - reads through the stream (not, as I would have expected, calling InputStream.toString()).
So, main lessons from this for today:
- Injecting code in sideways via meta-programming techniques is great, but don't forget that it's there!
- GString variable interpolation isn't always the same as calling toString()
Here's a sample Groovy script that demonstrates the issue in a nutshell:
def bytes=new Byte[5]; bytes[0]='h'; bytes[1]='e'; bytes[2]='l'; bytes[3]='l'; bytes[4]='o'; def is=new ByteArrayInputStream(bytes) println "BEFORE: bytes available - ${is.available()}" println is.toString() println "AFTER toString(): bytes available - ${is.available()}" println "stream ${is}" println "AFTER interpolation: bytes available - ${is.available()}"
resulting in this:
BEFORE: bytes available - 5 java.io.ByteArrayInputStream@104ce99 AFTER toString(): bytes available - 5 stream hello AFTER interpolation: bytes available - 0
UPDATE: If you want to have a play with the script, it's at the funkadelic Groovy Web Console here.
Thanks to Al & Gav at HF for helping to dig this one out!
Tuesday 24 August 2010
PHP Library 64-bit Bug Shocker!
I've just spent a happy day troubleshooting one of our legacy systems after we transplanted it to a new server. The system runs on PHP, and uses the PEAR package spreadsheet reader to pull apart Excel spreadsheets uploaded by the user. Using exactly the same code as on our old server, and with all necessary config for our app double-checked, to account for differences in the filesystem, the PP error log suddenly started filling up with strange error messages.
Eventually, I came across a few comments in a forum on PHPBuilder that pointed me to the problem. The oleread.inc file is using some hard-core bitwise operators to decode the XL file format, and by default, these assume a 32-bit instruction set. Our new server, is, of course, 64-bit, and fails spectacularly.
I can't find any official patches. I took the code from the comment, and patched the oleread file myself, and suddenly it works. So, replace this (gotta love one-line functions for clarity, eh?):
with this:
We're using POI and jXLS to handle our spreadsheet processing systems these days, and after today, I'm very glad that we are.
Hope this helps some lost soul perusing the web in search of a reason for their spreadsheet processor failing to transplant nicely.
UPDATE
I've found the up-to-date version of the oleread.inc library, which is quite an adventure in itself. Searching for "spreadsheet" in the PEAR packages list returns a spreadsheet writer and a datasource based on Excel files, but no reader. Surely the datasource reads the spreadsheets first?
http://pear.php.net/package/Structures_DataGrid_DataSource_Excel
has this to say:
"This is a DataSource driver for Structures_DataGrid using Excel spreadsheets. It
requires that the package Spreadsheet_Excel_Reader is installed (not available
as a PEAR package, but via Sourceforge: http://sourceforge.net/projects/phpexcelreader)."
So, I download the latest version of phpexcelreader, and it does appear to have a patch, at any rate, a slightly different implementation of GetInt4d().
So, if you're using a recent version of oleread.inc, you should be OK.
Notice: Uninitialized string offset: 2199023255040 in /home/archi/sites/service/public_html/ui/dataloader/excellib/oleread.inc on line 27
Eventually, I came across a few comments in a forum on PHPBuilder that pointed me to the problem. The oleread.inc file is using some hard-core bitwise operators to decode the XL file format, and by default, these assume a 32-bit instruction set. Our new server, is, of course, 64-bit, and fails spectacularly.
I can't find any official patches. I took the code from the comment, and patched the oleread file myself, and suddenly it works. So, replace this (gotta love one-line functions for clarity, eh?):
function GetInt4d($data, $pos) {
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24);
}
with this:
function GetInt4d($data, $pos) {
$_or_24 = ord($data[$pos+3]);
if ($_or_24>=128)
$_ord_24 = -abs((256-$_or_24) << 24);
else
$_ord_24 = ($_or_24&127) << 24;
return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $_ord_24;
}
We're using POI and jXLS to handle our spreadsheet processing systems these days, and after today, I'm very glad that we are.
Hope this helps some lost soul perusing the web in search of a reason for their spreadsheet processor failing to transplant nicely.
UPDATE
I've found the up-to-date version of the oleread.inc library, which is quite an adventure in itself. Searching for "spreadsheet" in the PEAR packages list returns a spreadsheet writer and a datasource based on Excel files, but no reader. Surely the datasource reads the spreadsheets first?
http://pear.php.net/package/Structures_DataGrid_DataSource_Excel
has this to say:
"This is a DataSource driver for Structures_DataGrid using Excel spreadsheets. It
requires that the package Spreadsheet_Excel_Reader is installed (not available
as a PEAR package, but via Sourceforge: http://sourceforge.net/projects/phpexcelreader)."
So, I download the latest version of phpexcelreader, and it does appear to have a patch, at any rate, a slightly different implementation of GetInt4d().
function GetInt4d($data, $pos)
{
$value = ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24);
if ($value>=4294967294)
{
$value=-2;
}
return $value;
}
So, if you're using a recent version of oleread.inc, you should be OK.
Sunday 13 June 2010
Hello World
Is the Google pretty printer working? Will my code samples come out looking rather nice?
Looks like it is. Thanks to Luka Marinko's post on how to set it up.
I modified Luka's recipe slightly, as I found that setting the onload attribute on the body worked for the blog, but was giving me Javascript errors when I tried to use the blogger layout/design tools. All I did was move the onload up to a script tag in the head of the page, and check for the presence of the function before calling it. So, my template looks like this:
which has the added advantage of keeping all the changes in one place.
In sequence, what I'm doing is:
class HelloWorld{
public static void main(String[] args){
String hw="Hello World";
System.out.println(hw);
}
}
Looks like it is. Thanks to Luka Marinko's post on how to set it up.
I modified Luka's recipe slightly, as I found that setting the onload attribute on the body worked for the blog, but was giving me Javascript errors when I tried to use the blogger layout/design tools. All I did was move the onload up to a script tag in the head of the page, and check for the presence of the function before calling it. So, my template looks like this:
<link href='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css'
rel='stylesheet' type='text/css'/>
<style type='text/css'>
pre.prettyprint{
font-size: 0.9em;
padding: 4px; background-color:#adf;
border-radius: 8px; -webkit-border-radius: 8px; -moz-border-radius: 8px;
}
pre.lang-html{ background-color: #afd; }
</style>
<script src='http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js'
type='text/javascript'>
</script>
<script type='text/javascript'>
window.onload=function(){
if (prettyPrint){ prettyPrint(); }
}
</script>
which has the added advantage of keeping all the changes in one place.
In sequence, what I'm doing is:
- Importing the prettyprint CSS stylesheet
- Adding a few extra styles to put the text in funky rounded boxes (where the browser supports it), and make the text a bit smaller so I have to worry less about truncating lines
- Import the prettyprint library code from google code
- Add a script to safely invoke the pretty printer
Subscribe to:
Posts (Atom)