

- What are you currently hacking on?
- What are you currently getting better at?
- What do you do when your computer is asleep?
- Describe that ‘big fish’ project that’s been stewing in your brain.
- What are you gonna post about this coming week?
I'm 01100110 01100101 01100101 01101100 01101001 01101110 01100111 00100000 01101100 01110101 01100011 01101011 01111001 00001010This looks suspiciously like ASCII, so I set out to render it in a more human readable form:
Bin Hex ASCIII doubt I'm the first to post this, but there you have it :-)
0110 0110 66 f
0110 0101 65 e
0110 0101 65 e
0110 1100 6C l
0110 1001 69 i
0110 1110 6E n
0110 0111 67 g
0010 0000 20 (space)
0110 1100 6C l
0111 0101 75 u
0110 0011 63 c
0110 1011 6B k
0111 1001 79 y
0000 1010 0A \n
The long vertical lines are the strings, while the horizontal lines are the frets. The lower pitched strings are on the left, while the higher pitched are on the right. Finger placement is indicated by the numbers written in the strings. The index finger is 1 and the pinky is 4. This diagram is of a G major chord and it uses three fingers, two on the third fret, and one on the second.
E A D G B e
0___________
| | | | | |
| | | | | |
| | | | | |
1-----------
| | | | | |
| 2 | | | |
| | | | | |
2-----------
| | | | | |
1 | | | | 4
| | | | | |
3-----------
| | | | | |
| | | | | |
| | | | | |
4-----------
The above looks a bit more like the neck of the guitar from the point of view of the person holding it.
0 1 2 3 4
e|-------|-------|---4---|-------|
B|-------|-------|-------|-------|
G|-------|-------|-------|-------|
D|-------|-------|-------|-------|
A|-------|---2---|-------|-------|
E|-------|-------|---1---|-------|
Unless, of course, you are watching one of the many left-handed guitar players (Hendrix, McCartney, etc.) in which case, you neck would look like this:
4 3 2 1 0
|-------|---1---|-------|-------|E
|-------|-------|---2---|-------|A
|-------|-------|-------|-------|D
|-------|-------|-------|-------|G
|-------|-------|-------|-------|B
|-------|---4---|-------|-------|e
The interesting thing about learning to play guitar using tabs, is that you actually have less information to go on than with sheet music. Tabs tend to lack information about the rhythm being played, tempo, and volume which are all present in sheet music. The one thing which sheet music lacks, however, is an indication of where your fingers should go when playing a particular chord or riff. Unpacking finger placement information from a cluster of notes on a staff can be difficult enough that guitar tabs make an attractive tradeoff. It is the musical equivalent of a domain specific language.
0 1 2 3 4
E|-------|-------|---1---|-------|
A|-------|---2---|-------|-------|
D|-------|-------|-------|-------|
G|-------|-------|-------|-------|
B|-------|-------|-------|-------|
e|-------|-------|---4---|-------|
class AtomFeed(XmlElement):Now for the whys and hows.
_qname = '{http://www.w3.org/2005/Atom}feed'
title = Title
entries = [Entry]
class Entry(XmlElement):
_qname = '{http://www.w3.org/2005/Atom}entry'
links = [Link]
title = Title
content = Content
class Link(XmlElement):
_qname = '{http://www.w3.org/2005/Atom}link'
rel = 'rel'
address = 'href'
class Url(XmlElement):
_qname = '{http://www.w3.org/2005/Atom}url'
class Title(XmlElement):
_qname = '{http://www.w3.org/2005/Atom}title'
title_type = 'type'
help()
get_elements
method. XML attributes are handled in a similar fashion and can be searched using get_attributes
.class Control(XmlElement):If you create an instance of the Control element like this:
_qname = ('{http://purl.org/atom/app#}control', #v1
'{http://www.w3.org/2007/app}control') #v2
draft = Draft
uri = 'atomURI'
lang = 'atomLanguageTag'
tag = ('control_tag', 'tag') # v1, v2
class Draft(XmlElement):
_qname = ('{http://purl.org/atom/app#}draft',
'{http://www.w3.org/2007/app}draft')
c = Control(draft=Draft('yes'), tag='test')Then you can generate XML for each version like this:
c.to_string(1)returns
<control xmlns="http://purl.org/atom/app#"while
control_tag="test">
<draft>yes</draft>
</control>
c.to_string(2)returns
<control xmlns="http://www.w3.org/2007/app"Note the difference in XML namespaces in the above. I also added an example of an attribute name which changed between versions, though "tag" doesn't actually belong in
tag="test">
<draft>yes</draft>
</control>
AtomPub control
(so don't go trying to use it m'kay).XML --> objectWhen generating XML the process is similar but slightly different.
- find out the desired version
- is there an entry for this version in _rule_set?
- if not, look at all XML members of this class
in _members
- create XML matching rules based on each member's type
(and store in _rule_set so we don't need to generate
the rules again)
- iterate over all sub-elements in the XML tree
- sub-elements and attributes which are in the rule set
are converted into the declared type
- sub-elements and attributes which don't fit a rule are
stored in _other_elements or _other_attributes
object --> XMLArmed with the above explanation, understanding the source code should be a bit easier.
- create an XML tree with the tag and namespace for this
object given the desired version
- look at all members of this class in _members
- tell each member to attach itself to the tree using
it's rules for the desired version
- iterate through _other_elements and _other_attributes
and tell each to attach to the XML tree
vi
text editor. I also happen to be a fan of code style guidelines. And sometimes it is very handy to know if a line in your source code has gone over eighty characters long. Some style guides still recommend a max line length of eighty characters, a tradition dating all the way back to IBM punch cards, circa 1928. For an even more impressive feat of long term engineering influence look up how the size of Roman war chariots determined the size of NASA space shuttle booster rockets. But I digress.vim
or in your .vimrc
file.:match ErrorMsg '\%>80v.\+'I've noticed that some blogger templates tend to display fifty-five characters in a fixed width format (as in a
<pre>
block or <code>
). To edit code which I plan to post on Blogger, I sometimes turn on:match ErrorMsg '\%>55v.\+'
import sippycode.http.core as http_coreIn the above, the client sends an authenticated POST to the updates URL. Using the
import sippycode.auth.core as auth_core
class TwitterClient(object):
def __init__(self, username, password):
self._credentials = auth_core.BasicAuth(username,
password)
def update(self, message):
request = http_core.HttpRequest(method='POST')
http_core.parse_uri(
'http://twitter.com/statuses/update.xml'
).modify_request(request)
request.add_form_inputs({'status': message})
self._credentials.modify_request(request)
client = http_core.HttpClient()
response = client.request(request)
return response
TwitterClient
in your code looks like this:client = TwitterClient('my-username', 'my-password')To try out this Twitter console app, unpack the download and run
client.update('Try out this Twitter client: http://oji.me/wP')
sippy_twitter.py
. With it, you can update your status on Twitter or read the updates from your friends. When reading, the client displays five updates at a time, since showing more at once would likely cause some to scroll off the top of the screen (assuming the terminal displays twenty-five lines). ncurses
), ability to follow users, and read updates from just one user. If you'd like to participate in any of these, let me know in the comments. PUT
or DELETE
with urllib2.def post_photo(url, url_parameters, escape_parameters,To use the above, you have to gather all of the information in one place, and make the function call. There are cases where you want a design like the above.
photo_mime_type, photo_file_handle,
photo_file_size, metadata_xml,
metadata_mime_type, auth_token,
additional_http_headers)
...
# Sets the request's Host, port, and uri.
# Makes the request into a MIME multipart request,
# adjusts the Content-Type and recalculates
# Content-Length.
# Sets the Authorization header
post_photo('http://picasaweb.google.com/data/'
'feed/api/user/userID/albumid/albumID', None,
False, 'image/jpeg', photo_file, photo_size,
atom_xml, 'application/atom-xml',
client_login_token, None)
HttpRequest
object which various parts of the program modify. Once all of the modifications have been applied, the fully constructed request is passed to an HttpClient which communicates with the server using httplib or urlfetch if you happen to be on Google App Engine. (Support for more HTTP libraries is certainly possible.)photo_post = HttpRequest(method='POST')In fact, the above code could make up the body of the
# Sets the Authorization header
client_login_token.modify_request(photo_post)
# Adds to the body and calculated Content-Length,
# sets the Content-Type.
photo_post.add_body_part(atom_xml,
'application/atom+xml')
# Makes the request into a MIME multipart request,
# adjusts the Content-Type and recalculates
# Content-Length.
photo_post.add_body_part(photo_file, 'image/jpeg',
photo_size)
# Sets the request's Host, port, and uri.
parse_uri('http://picasaweb.google.com/data/'
'feed/api/user/userID/albumid/albumID'
).modify_request(photo_post)
post_photo
function described in the first code snippet.sippycode
(a play on sippy cup). This is a place where code can grow up.
ctrl-alt-fn-2
), I was using screen to simulate multiple terminals, and I needed to copy and paste text between them. In the past, I've usually used screen when ssh-ing into a machine, and putty (my ssh client of choice) provided copy and paste, so I had never needed screen's system. ctrl-a [
to enter copy mode, press enter
to mark the start point and enter
again to mark the end point. You have now copied the text. Switch to the desired window, and paste in the text using ctrl-a ]
.One Laptop per Child is launching its second 'Give One, Get One' (G1,G1) program starting in November, 2008, delivering its XO Laptop globally via Amazon.com. Although the first iteration of the 'G1G1' program was extremely successful and sold more than 185,000 laptops, the delivery of the laptops in the USA did not run as smoothly as we anticipated. Selling the laptops on Amazon.com will provide us with the resources to process and ship the laptops globally in a timely fashion.
The laptop's operating system will be Linux-based (it will not dual-boot Windows and Linux, contrary to some reports).
ctrl-fn-alt-1
. To switch back to the normal view. press ctrl-fn-alt-3
. For some reason, I can only start screen as root.
(NS_ERROR_FAILURE) [nsIXMLHttpRequest.setRequestHeader]
, try opening the HTTP request first (as I recently learned). I've always said that writing this library was for education more than any anticipated serious use.document.cookie = something
, reading document.cookie
doesn't give you the same thing back (the expiration, domain, and path information are squirreled away somewhere else)./content_manager
page which lets me assign a specific blob of text to the desired URL under my domain. I can also set some basic metadata, like the content type (so that your browser knows how the content should be rendered) and cache control information, since HTTP caching is excellent and saves puppies from drowning in lakes (ok seriously it will alleviate congestion and unnecessary traffic when you want to give the same content to thousands or millions of people). /content_manager
looks like this:Opera 9.51 for Linux i386
, selected RedHat
as the distribution in the drop down menu, then I selected RedHat 6.2, 7.1, 7.2, 7.3, 8.0, 9
and checked the box to Download this package in TAR.GZ format
. Whew. tar zxvf opera-9.51.gcc4-static-qt3.i386.tar.gzand then run
install.sh -sFrom there, you can just type
opera
on the command line in the terminal to start it up.
typedef struct {You can think of
size_t (*memberLookup)(char*);
} TypedStruct;
typedef struct {
size_t (*memberLookup)(char*);
unsigned int age;
unsigned int weight;
char* name;
} Person;
size_t PersonLookup(char*);
typedef struct {
size_t (*memberLookup)(char*);
char* breed;
unsigned int weight;
unsigned int age;
char* name;
} Dog;
size_t DogLookup(char*);
Person
and Dog
as subclasses of a common parent. They share a few member attributes, but the attributes are in different places within the structure. I want to write a function which can find the age
member in whatever structure is passed in to it. How do we find out where a member lies within a structure? With this design, we ask the structure to tell us. The memberLookup
function takes a name, and returns the offset for the desired member. Here are the lookup functions that describe the above structures:#include"typed_struct.h"With the data structures in place and the functions which map member names to locations, we can now write functions which dynamically lookup the location of a member. This simple function displays the age of the entity which is passed in. The static variables are designed to speed up repeated calls with the same type. For example, if a
#include<stdio.h>
size_t PersonLookup(char* memberName) {
if(strcmp(memberName, "age") == 0) {
return sizeof(size_t);
} else if(strcmp(memberName, "weight") == 0) {
return sizeof(int) + sizeof(size_t);
} else if(strcmp(memberName, "name") == 0) {
return 2*sizeof(int) + sizeof(size_t);
} else {
return -1;
}
}
size_t DogLookup(char* memberName) {
if(strcmp(memberName, "breed") == 0) {
return sizeof(size_t);
} else if(strcmp(memberName, "weight") == 0) {
return sizeof(size_t) + sizeof(char*);
} else if(strcmp(memberName, "age") == 0) {
return sizeof(size_t) + sizeof(char*) + sizeof(int);
} else if(strcmp(memberName, "name") == 0) {
return sizeof(size_t) + sizeof(char*) + 2*sizeof(int);
} else {
return -1;
}
}
Person
is passed in as entity several times in a row, the location of the age member will only need to be looked up on the first call.void GiveIntroduction(void* entity) {Here is a program which uses the above structures and functions.
static size_t age_offset = 0;
static size_t (*last_lookup)(char*) = NULL;
if(last_lookup != ((TypedStruct*)entity)->memberLookup) {
// In words, convert entity to a TypedStruct pointer
// (TypedStruct*)entity
// Find the function pointer called memberLookup
// ((TypedStruct*)entity)->memberLookup
// Call the function at memberLookup with "age" as the parameter
// (*(((TypedStruct*)entity)->memberLookup))("age")
age_offset = (*(((TypedStruct*)entity)->memberLookup))("age");
last_lookup = ((TypedStruct*)entity)->memberLookup;
}
printf("I am %i years old\n", *((int*)(entity + age_offset)));
}
int main() {When the above is run, it should display "I am 4 years old".
Dog nelly;
nelly.memberLookup = &DogLookup;
nelly.age = 4;
nelly.name = "Nelly";
GiveIntroduction(&nelly);
}
Dog
structure, the compiler knows that age
is 12 bytes from the start of the structure (on most 32-bit processors), and that it's type is int
. All of the offsets are calculated at compile time. By moving the offset lookup into a function which is executed at runtime, we free up the compiler from having to know where to look for a particular member. Now we can pass in any data type into GiveIntroduction
and as long as the object's memberLookup
function tells us where to find the age
member, everything will work.memberLookup
on every instance of a TypedStruct
uses a bit of memory, and calling the function to find the necessary offset adds a runtime cost. This example has been a bit simple, even too simple, as there are ways to provide more aggressive caching of the lookups and faster ways to perform the lookup within the XLookup
functions.
typedef struct {Now when you say
uint16_t age;
uint16_t weight;
wchar* name;
} Person;
Person fred
, your program will grab a chunk of memory (likely from the stack) that is 8 bytes, or 12 bytes, or something similar depending on the compiler, size of pointers, ect. Now if I write fred.age
in my program, this is translated to "the value of the two bytes at the start of fred's address" and if I ask for fred.weight
, that turns into "the value of two bytes which are at exactly fred's address + 2". Since C is early bound (AKA static), the compiler knows that weight
is always found in the same location relative to the start of fred
, and as a result, the machine code generated by the compiler can be very fast and efficient. typedef struct {Now if I want to reuse the code I wrote earlier to find out the age of a Dog, I have a small problem. You see, the
wchar* breed;
uint16_t weight;
uint16_t age;
wchar* name;
} Dog;
age
is in a different location for a Dog than a Person. If it had been in the same position, I could have cast the Dog to a Person, and then my compiled code would be looking for age
at the same location. But for one reason or another, the layout of Dog is different. Person fred
and a Dog nelly
, then age is converted into a different offset from the start of the data. However this means that you would need to write the same function multiple times, once for Person and once for Dog.typedef struct {Now that the type information is stored along with the data, I could write a
void* type;
uint16_t age;
uint16_t weight;
wchar* name;
} Person;
typedef struct {
void* type;
wchar* breed;
uint16_t weight;
uint16_t age;
wchar* name;
} Dog;
PrintAge
function that would lookup the correct location of the age
member. Here's some pseudocode for how this more dynamic code would look:function PrintAge()I haven't decided yet on the best way to lookup the offset based on the member name. I think it might be a close call between pointing to a lookup function with if statements, and a lookup in a presorted binary tree. Depending on the number of members, I could see it going either way. What do you think, what is the best way to implement a dynamic member lookup?
// Note that this age offset is stored between function calls so
// that if the function is called with the same type as in the most recent call,
// the offset will not have to be looked up again. This should improve
// performance by avoiding the need to perform a lookup in some cases.
static long age_offset = -1
static void* most_recent_type
if most_recent_type != current_type || age_offset == -1
age_offset = lookup(age)
printf("age is *(person+age_offset)")