Jump to content
terjeio

Compact command parser/dispatcher example

Recommended Posts

@@yyrkoon : no offense taken, I guess we all have different coding styles. Having just restarted coding in C the last few years I have had a lot to refresh and (re)learn.

 

Some examples again, first my original command parser - returning an integer (the index into the command table) which fed a switch statement:

unsigned char parseCommand (char *cmd) {

	unsigned char x = 0, hit = 0;

	while(!hit && x < NUMCOMMANDS) {

		if(!strncmp(command[x], cmd, strlen(command[x])))
			hit = 1;
		else
			x++;

	}

	return x;

}

This was written when I just started coding in C again, and I am utilizing the fact that any non-null value is regarded as true. Surely negating the result of strncmp() may seem counterintuitive at first but I believe it is a common method to test for match - this since it returns 0 (i.e. false) when a match is found. I am also utilizing this fact for the "hit" variable - this because because I had not yet disovered stdbool.h and this was how I coded booleans way back in time... As a side note I did use function pointers in C back then, could be because I was extensively using indirect JMPs when coding (in assembly) for the 6502 microprosessor - so not a new concept for me.

 

Another example, this time from Grbl which I am in the process of HALifying. For me some of the code is hard to read (just because whitespace is not used [properly]?):

plan_block_t *plan_get_current_block() 
{
  if (block_buffer_head == block_buffer_tail) { return(NULL); } // Buffer empty  
  return(&block_buffer[block_buffer_tail]);
}

I would have written it like this:

// Returns NULL if buffer empty 
plan_block_t *plan_get_current_block() 
{
  return block_buffer_head == block_buffer_tail ?  NULL : &block_buffer[block_buffer_tail];
}

... but then maybe harder to read if not well versed in C? Anyway, I did not change it because maintainability (against the main source tree) would be reduced.

 

Readability, maintainability and complexity are surely concepts that are perceived differently - we have to accept that.

 

As a final thought: maybe I should explain the code I post in some more detail, I know I am a bit terse at times - due to my name?

 

Oops - did I do it again (beeing terse) with my last example...? ;)

Share this post


Link to post
Share on other sites

@@yyrkoon : no offense taken, I guess we all have different coding styles. Having just restarted coding in C the last few years I have had a lot to refresh and (re)learn.

 

Some examples again, first my original command parser - returning an integer (the index into the command table) which fed a switch statement:

unsigned char parseCommand (char *cmd) {

	unsigned char x = 0, hit = 0;

	while(!hit && x < NUMCOMMANDS) {

		if(!strncmp(command[x], cmd, strlen(command[x])))
			hit = 1;
		else
			x++;

	}

	return x;

}

This was written when I just started coding in C again, and I am utilizing the fact that any non-null value is regarded as true. Surely negating the result of strncmp() may seem counterintuitive at first but I believe it is a common method to test for match - this since it returns 0 (i.e. false) when a match is found. I am also utilizing this fact for the "hit" variable - this because because I had not yet disovered stdbool.h and this was how I coded booleans way back in time... As a side note I did use function pointers in C back then, could be because I was extensively using indirect JMPs when coding (in assembly) for the 6502 microprosessor - so not a new concept for me.

 

Another example, this time from Grbl which I am in the process of HALifying. For me some of the code is hard to read (just because whitespace is not used [properly]?):

plan_block_t *plan_get_current_block() 
{
  if (block_buffer_head == block_buffer_tail) { return(NULL); } // Buffer empty  
  return(&block_buffer[block_buffer_tail]);
}

I would have written it like this:

// Returns NULL if buffer empty 
plan_block_t *plan_get_current_block() 
{
  return block_buffer_head == block_buffer_tail ?  NULL : &block_buffer[block_buffer_tail];
}

... but then maybe harder to read if not well versed in C? Anyway, I did not change it because maintainability (against the main source tree) would be reduced.

 

Readability, maintainability and complexity are surely concepts that are perceived differently - we have to accept that.

 

As a final thought: maybe I should explain the code I post in some more detail, I know I am a bit terse at times - due to my name?

 

Oops - did I do it again (beeing terse) with my last example...? ;)

 

Yeah, I do not personally like ternary statements all that much because they're harder to read when compared to another way of doing the same thing. But . . . https://github.com/wphermans/Bonejs/blob/master/examples/pmic-example.js that example code I wrote using my Bonejs wrapper library, and 347 lines of code with many, many ternary statement. Care to guess how many ? Anyhow, could you imagine what that code would have looked like without them( replacing with maybe if/else statements ) ?

 

It'd have been a mess.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×