CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Poor Man's snprintf()

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
jeremiah



Joined: 20 Jul 2010
Posts: 1314

View user's profile Send private message

Poor Man's snprintf()
PostPosted: Thu Mar 12, 2015 2:28 pm     Reply with quote

Below is a quick and dirty way to get a snprintf() method without having to write all the parsing code. It leverages a CCS extension to work. It makes use of macros, so always be aware of the dangers there.

Code:

/******************************************************************************
* Name:  snprintf.h
* Auth:  Jeremiah
* Desc:  This file contains a poor man's implementation of snprintf() for the
*        CCS compiler.  It is not meant to be as efficient as a homemade
*        snprintf() method.  It leverages the putc() substitution in printf(),
*        which is a CCS extension.
*
*        FUNCTIONS:
*           snprintf()
*
* Compiled with PCWHD v5.025
*
* History:
* 03/12/2015 - JHB - Creation
******************************************************************************/
#ifndef SNPRINTF_H
#define SNPRINTF_H

///////////////////////////////////////////////////////////////////////////////
// NAME: snprintf()
// DESC: Composes a string with the same text that would be printed if fmt
//       was used on printf, but instead of being printed, the content is
//       stored as a string in the buffer pointed by buf (taking max as the
//       maximum buffer capacity to fill).
// IN:   buf = Pointer to a buffer where the resulting string is stored
//       max = Maximum number of bytes to be used in the buffer.  The
//             generated string has a length of max-1, leaving space for a
//             null character.  Expects an unsigned int16 > 0.
//       fmt = CString that contains a format that follows the same format
//             in printf (see printf for details).  This must be a constant
//             string (not a variable).
//       ... = List of parameters used as inputs to the format string.
// OUT:  The number of characters that would have been written if max was
//       large enough to hold them.
// NOTE: Does not return a negative value for format errors.  However the
//       CCS compiler reports format errors at compile time.
///////////////////////////////////////////////////////////////////////////////
#define snprintf(buf,max,fmt,...) (       \
   snprintf_init(buf,max),                \
   printf(snprintf_putc,fmt,__VA_ARGS__), \
   snprintf_cleanup(),                    \
   g_snprintfNum                          )
//Macros that use a comma separated list of statements return the final
//statement as if it were a function return value.  Also note that
//semicolons are not needed using this method (they are implied)

///////////////////////////////////////////////////////////////////////////////
//****************** Implementation (Do Not Use Directly) *******************//
///////////////////////////////////////////////////////////////////////////////
static unsigned int16 g_snprintfMax;  //this will decrement with each character
static unsigned int16 g_snprintfNum;  //this will increment with each character
static char *         g_snprintfBuf;  //holds address of the output buffer

//function passed to printf() ... CCS option only
void snprintf_putc(char c){
   //only copy the maximum number of allowed characters
   if(g_snprintfMax){ 
      if(--g_snprintfMax){ 
         g_snprintfBuf[g_snprintfNum] = c;   
      }else{ //last spot in the buffer must be a '\0'
         g_snprintfBuf[g_snprintfNum] = '\0';  //append a null
      }
   }
   //update this regardless of max so the snprintf() return value is correct.
   g_snprintfNum++;
}

//function used to prepare for a new snprintf() call
void snprintf_init(char *buf, unsigned int16 max){
   g_snprintfMax = max; 
   g_snprintfNum = 0;   
   g_snprintfBuf = buf;
   if(g_snprintfMax){  //only write to it if buffer size non zero
      g_snprintfBuf[0] = '\0';
   }
}

//function used to finish up buffer with a null if needed. 
void snprintf_cleanup(){
   //if maximum buffer size was never reached, then null terminate
   if(g_snprintfMax){
      g_snprintfBuf[g_snprintfNum] = '\0';
   }
}

#endif


Test Code (supply your own FUSES, etc.):
Code:

#case
#include "pic.h"  //has #device, #FUSES, #use delay(), #use rs232()

#include "snprintf.h"

void main(void){
   char buffer[15] = {
      'z','z','z','z','z',
      'z','z','z','z','z',
      'z','z','z','z','\0'
   };
   unsigned int16 i;
   unsigned int16 val=255;
   
   printf("\r\n*********Program Start*********\r\n");
   
   //Test empty input string
   val = snprintf(buffer,sizeof(buffer),"");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   
   //Test being under the max
   val = snprintf(buffer,sizeof(buffer),"Hello");
   //show remaining buffer just for this one to verify algorithm isn't
   //overwriting the entire buffer.
   printf("BUFFER(%03u,%03u): %s %s\r\n", sizeof(buffer),
                                          val,
                                          buffer,
                                          &buffer[val+1]);
   val = snprintf(buffer,sizeof(buffer),"Hello ");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 7");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 78");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789A");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789AB");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789ABC");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789ABCD");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789ABCDE");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   val = snprintf(buffer,sizeof(buffer),"Hello 789ABCDEF");
   printf("BUFFER(%03u,%03u): %s\r\n",sizeof(buffer),val,buffer);
   
   //Test exceeding the max.  First loop should print out results from
   //previous snprintf() call since buffer max is 0
   for(i=0; i<=sizeof(buffer); i++){
      val = snprintf(buffer,i,"Hello %d ABCDEFGHIJKLMNOP",78);
      printf("BUFFER(%03u,%03u): %s\r\n",i,val,buffer);
   }
   
   while(TRUE);
}



Expected Output:
Code:

*********Program Start*********
BUFFER(015,000):
BUFFER(015,005): Hello zzzzzzzz
BUFFER(015,006): Hello
BUFFER(015,007): Hello 7
BUFFER(015,008): Hello 78
BUFFER(015,009): Hello 789
BUFFER(015,010): Hello 789A
BUFFER(015,011): Hello 789AB
BUFFER(015,012): Hello 789ABC
BUFFER(015,013): Hello 789ABCD
BUFFER(015,014): Hello 789ABCDE
BUFFER(015,015): Hello 789ABCDE
BUFFER(000,025): Hello 789ABCDE
BUFFER(001,025):
BUFFER(002,025): H
BUFFER(003,025): He
BUFFER(004,025): Hel
BUFFER(005,025): Hell
BUFFER(006,025): Hello
BUFFER(007,025): Hello
BUFFER(008,025): Hello 7
BUFFER(009,025): Hello 78
BUFFER(010,025): Hello 78
BUFFER(011,025): Hello 78 A
BUFFER(012,025): Hello 78 AB
BUFFER(013,025): Hello 78 ABC
BUFFER(014,025): Hello 78 ABCD
BUFFER(015,025): Hello 78 ABCDE

Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group