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

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...