So, I worked on an interesting problem today - parsing iCal feeds. My desire to parse iCal feeds stems from the fact that I want to translate an iCal feed to an RSS feed. This would let me turn a calendar into an RSS feed that can be added to for example. (Obviously you would only publish events in the future.)

So, working on this I ran into an interesting issue. I needed to parse a string that looked a bit like this:


Everything after the colon was data. Everything before the data is considered params. There are two ways we can make this crazy. First off - the params side can have colons too - if they are in quotes, and not just ":", but...


Let's make things interesting again - you can have multiple params if you separate them by commas - but again, commas can be inside quotes:


Now - as we all know - ColdFusion has some nifty string parsing functions. The list functions are especially useful for cutting up strings, but in this case, are useless. What I ended up doing then was writing a UDF called: findNotInQuotes. Here it is:

function findNotInQuotes(data,target) {
   var inQuotes = false;
   var x = 1;
   var c ="";
   if(arraylen(arguments) gte 3) x = arguments[3];
   for(; x lte len(data); x=x+1) {
      c = mid(data,x,1);
      if(c is"""") {
         if(inQuotes) inQuotes=false;
         else inQuotes = true;
      if(c is target and not inQuotes) return x;
   return 0;

This worked for me, and I was able to write a conditional loop. However - I think it could be done better. My first thought was - why not rewrite all the list functions so they will ignore delimiters in quotes. This seems a bit crazy. Instead - why not simply write a function that will "split" a string into an array, using your delimiters (and why not allow for delimiters of multi-chars, something CF doesn't let you do). Then you can simply loop over the array.

Any thoughts on this?

For those interested in the iCal code - I've got it working, but I want to convert it to a nice CFC first. There are a set of helper functions also included with it so you can parse their time formats. I'm also going to add a function so you can pass in an iCal start date and an iCal duration value and get an end date.