In writing a compiler, I’ve come across a sleek part of the standard c library that I just can’t help and a take a few minutes to write a blog post about it!
You can send any number of arguments to a method / macro that you want. It’s called Variadic methods and they have a crazy syntax. Here is a piece of code that I am using in the compiler. It’s super similar to the printf method (the printf method itself is a variadic method, if you’ve ever wondered…)
char *stringerize(const char *fmt, ...) {
char *buf = safe_malloc(sizeof(char)*BUFSIZE);
va_list args;
va_start(args, fmt);
if (args && strlen(args) > 0)
(void) vsnprintf(buf, BUFSIZE, fmt, args);
va_end(args);
return (buf);
}
Kind uninteresting, huh? I’ll show you a much more interesting one at the end of the post thatallows you to safely concatenate any number of strings.
The basic idea is that you define a method with the … syntax, such as
char *stringerize(const char *fmt, ...)
...
There are two two ways to access those variables.
One by one
First, you declare all your variables that you are going to use in the method. That has to be before accessing the list. Then, you start the list with
va_list args;
Make sure you don’t forget to declare the args as a list otherwise C will throw a fit.
Then, when you are ready to get the variables, call
va_start(args, fmt);
The second parameter is the last required argument in the command. You do need at least one required argument in a function. The same requirement does not hold true for macros, though.
Then, to get to the variable you call
va_arg(args, const char *);
The second parameter is the type you are expecting to come back. This gives C a heads up as to what to expect.
Then, when you are done and want to move on to the next one in the list, simply call:
va_end(args);
That’s it!
Accessing the variables all at once
You can either do this in a macro that would look something like (untested):
#define VARGS(...) fprintf(stderr, __VA_ARGS__)
// or
#define VARGS(fmt, args...) fprintf(stderr, fmt, args)
There are other ways as well, but those are the ones that stood out to me. In a method, you can do this as I had done in the example above. Just call list and all the arguments are accessible to you, right there in your shirt pocket!
And now, finally for the more important snippet that:
char *concat_commands(const char* str,...) {
va_list args; char *s; size_t held_memory = 100;
char *res = safe_malloc(sizeof(char)*held_memory);
if (res != NULL) {
char *new_pointer, *word_pointer;
va_start(args, str);
word_pointer = res;
for (s=str;s!=NULL;s=va_arg(args, const char *)) {
size_t len = strlen(s);
if (word_pointer + len + 1 > res + held_memory) {
held_memory = (held_memory + len) * 2;
new_pointer = (char *) realloc (res, held_memory);
if (new_pointer == NULL) { free(res); return NULL; }
word_pointer = new_pointer + (word_pointer - res);
res = new_pointer;
}
word_pointer = memcpy(word_pointer,s,len);
word_pointer = word_pointer + len;
}
*word_pointer++ = ' ';
new_pointer = (char *) realloc(res, word_pointer-res);
if (new_pointer != NULL) {res = new_pointer;}
va_end(args);
}
return res;
}
I hope this helps someone out there save a few hours and remember how cool C even in the midst of the ruby we all love so much. On that note, I urge you to look at the ruby interpreter source code. It’s a tad jumbled up, my guess is because there are a few people working on it, but it is sure damn sexy code. Thanks once again matz!
I’ll be back more in a week or so for more fervent posts after my compiler is done.
More information here
Have you ever found yourself writing a code similar to this
[source:ruby]
class Post < ActiveRecord::Base
has_one :image
def get_image
image_id.nil? ? Image.default_image : Image.find(image_id)
end
end
[/source]
Where you have an instance where rather than catching an AR Exception, you want to have a default value for a model?
I noticed I was writing code like this, all the time
[source:ruby]
def get_image
begin
Image.find(params[:id])
rescue Exception => e
Image.default_image
end
end
[/source]
Imagine that, all over the place. How ugly!
So, rather than continue with this semi-ruby-style code, let’s use ActiveRecord and create ourselves a fun 20 minutes creating a fallback.
Let’s get started.
First things first, I like to place things in modules to separate the different methods, you may have your own thing, but… this is my article so I’ll tell you what works for me:
I usually start with a basic template when I am either a) creating a plugin that will extend an object or b) creating a file that will extend an object.
[source:ruby]
module CitrusByte
module ARFinderExtensions
def self.included(receiver)
receiver.extend MeatMethods
end
module MeatMethods
def something_here(*args)
extend CitrusByte::ARFinderExtensions::ClassMethods
include CitrusByte::ARFinderExtensions::InstanceMethods
end
end
module ClassMethods
end
module InstanceMethods
end
end
end
end
[/source]
In case you’ve never seen this schtuff before, it’s pretty cool. Check out the ruby docs for more information, but in a nutshell, if you place the something_here method inside a class, then that class with have the class methods and the instances will have the instance methods. It’s that simple. Check out the acts_as plugins. This is how they do it.
Anyways, so we have the basic template, now let’s fill some stuff in and get our find missing stuff moved into place.
Before we go any further, in my extensions, I am going to use a callback. This way we can have methods that operate at the class level and are defined on the instance and the two can fit seamlessly together.
So, what is a callback? Don’t tell me you haven’t used a callback before. The before_save, after_create methods are all callbacks that we use and take for granted as rails developers daily. Well, what are they already?
Callbacks are nothing more than attr_accessors that are accessible on the entire hierarchy of the instance. The difference is that the accessor in a callback is not the same as the one “owned” by the parent.
So now, we are going to use that to our advantage and define our own callback.
Time for some code (Going back to the example above… ):
[source:ruby]
def self.included(receiver)
receiver.extend MeatMethods
receiver.class_eval do
class << self
alias_method_chain :find, :catch
end
# Add the callback
def self.rescue_not_found(*callbacks, &block)
callbacks << block if block_given?
write_inheritable_array(:rescue_not_found, [block])
end
end
end
[/source]
Whenever any module is included into a class, the included method is called on the module. It’s ruby’s ultra-useful callback on itself. We can use it to do some really funky neat stuff. Can you think of other things we can use it for?
line 1 extends the MeatMethods (which we will deal with later) to the object
line 2 evaluates the block at the class level
lines 3-5 places inside the class, the ability to extend the instance with a class variable (confusing? Jay Fields has some awesome thoughts about this he hashes out Here) and alias_method_chain’s the methods find and catch.
If you don’t know what alias_method_chain does, ooo it’s slick. Basically it adds two methods to the class (first _with_ second AND first _without_ second) at hand and calls them in order. Wha? Meaning… for our circumstance, it will add find_with_catch and find_without_catch! How cool
line 7-10 have to do with the callbacks. First off, the callback name is going to be rescue_not_found. It is described as a block (as you are used to) and appends it , a block or not on to the inheritable_array.
How cool! I hope you are having fun, I sure am.
Now let’s actually add a method:
[source:ruby]
def find_with_catch(*args)
options = args.extract_options!
validate_find_options(options)
set_readonly_option!(options)
begin
case args.first
when :first then find_initial(options)
when :all then find_every(options)
else find_from_ids(args, options)
end
rescue Exception => e
callback :rescue_not_found
end
[/source]
This is basically the rails way of handling a find method with two major differences. First, this is the find_with_catch method that we defined above. Second, there is the rescue part which is what will be doing our work for us. Notice the rescue:
[source:ruby]
rescue Exception => e
callback :rescue_not_found
end
[/source]
If the ActiveRecord::Base#find can’t find an associated object in the database, it will throw a RecordNotFoundException… but in our scenario, we don’t want that… we want to have a method called instead, the entire point of our adventure! So we are going to catch that exception and instead, call the defined callback rescue_not_found.
There are a few more unimportant methods on the module, so I’ll skip those for now and you can check them out (including the callback method), but the one last important tidbit that you will need to know if you are going to use this fun-ness is that you actually have to add this stuff to ActiveRecord somehow… depending on the context, you could call the method defined above or just include it to the base…
For us, in this circumstance, we’ll use
[source:ruby]
ActiveRecord::Base.send(:include, CitrusByte::ARFinderExtensions)
[/source]
’cause we want all the finds to call the callback!
This allows you to do something like:
[source:ruby]
class Image < ActiveRecord::Base
rescue_not_found do
Image.new {:id => 1, :filename => “no_image.jpg”}.freeze
end
end
[/source]
This is much nicer than the former where a find had to be nested inside a begin;rescue;end statement.
Let me know how this works for you!
Also, you should stay tuned! Some big things are just on the horizon. I have a few plugins I am going to release here in a few days, I have a new blog posting coming out shortly too about rmagick and it’s use in production and I have a stellar joke in the mix too! That’s not all, but that’s I’ll I will say for now
active_record_extensions.rb