2012-03-01

Hey! That crummy file downloader written in Vala doesn't work with the Rathole Radio Ogg feed. What gives?

I'm glad you asked. In higher level programming languages, it is quite common to have the ability to read chunks of data from an HTTP stream when using a module or library designed to handle HTTP traffic. However, since the Vala based downloader uses low-level sockets to read from the stream, it is up to the developer to implement reading of Chunked HTTP data.

In parsing terms, the format is quite simple:

  1. Read a line from the steam. This will be a number and it represents the number of bytes of data in the chunk. We'll call it "x"
  2. Read "x" number of bytes from the next line. This is a "chunk" of data.
  3. repeat until "x" is equal to 0

While that should be nice and easy, the number of bytes that are supposed to be read is in hexadecimal and I couldn't find a Vala function to convert a hexadecimal string into an integer value. After spending way too much time searching for a solution, I took the DIY approach and hacked together a few functions to do exactly what I needed to do.

So without further ado, here is my Vala code to convert a hexadecimal string to an integer.

Enter the Vala

public int hexvalstring ) {
  switch(c) {
    case "a":
    return 10;
    case "b":
    return 11;
    case "c":
    return 12;
    case "d":
    return 13;
    case "e":
    return 14;
    case "f":
    return 15;
    default:
    return int.parse(c);
  }
}

public int64 hextoint(string hex){
  //convert the string to lowercase
  string hexdown hex.down();
  //get the length of the hex string
  int hexlen hex.length;
  int64 ret_val 0;
  string chr;
  int chr_int;
  int multiplier;
  
  //loop through the string 
  for (int 0hexlen i++) {
    //get the string chars from right to left
    int inv = (hexlen-1)-i;
    chr hexdown[inv:inv+1];
    chr_int hexval(chr);
    
    //how are we going to multiply the current characters value?
    multiplier 1;
    for(int j++) {
      multiplier *= 16;
    }
    ret_val += chr_int multiplier;
  }
  return ret_val;
}

public static void main() {
  string[] hexvals = {"9AC3","1234","b525","abcdef","bbb"};
  int64 i;
  foreachstring hexval in hexvals) {
    hextoint(hexval);
    stdout.printf(@"$hexval = $i\n");
  }
}

Only the hextoint and hexval functions are needed, but I though it would be nice to add a bit of code to use the fuctions.

Alright, now that that is done, it's time to implement the reading of Chunked data in the downloader so that eventually I will be able to add audcatching functionality to MuttonChop.

Comments
2012-03-23 okin56:
moi je fais comme ça.
c'est plus concis

<code>
public int hexval(string c)
{
string ref = "0123456789abcdef";
return ref.index_of(c);
}
</code>
2012-03-23 jezra:
merci!
2012-11-20 Luca Bruno:
long n = "deadbeef".to_long(null,16);
2012-11-29 gilzad:
Strange enough the current compiler (v0.18) warns that str.to_long(..) is deprecated and one should use long.parse() instead. But in the current vapi long.parse does not support any base specification.
I hope there will be a substitute before the deprecated version vanishes.
2012-11-30 Luca Bruno:
It's reported and I think there will be an alternative for sure in the future: https://bugzilla.gnome.org/show_bug.cgi?id=656691
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
7 minus 0
Answer:
required
subscribe
 
2016
2015
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008