Hmmm [UPDATE]
Well, this updated version actually works with optimization turned on, doesn’t use custom structs for passing data.
It’s now using the sofia-sip way of passing type and value in multiple arguments, this one is still a simplified version though…
There’s some additional code for passing uri parameters each in a single tag now too.
Download: Tag based SIP URI generator example code #2
#include <stdio.h> #include <stdarg.h> #include <string.h> #include <stdlib.h> typedef int switch_core_session_t; char * sofia_printf_uri( switch_core_session_t *session, ... ); typedef enum { URI_TAG_TYPE_USERNAME = 1, URI_TAG_TYPE_DESTINATION, URI_TAG_TYPE_HOST, URI_TAG_TYPE_PORT, URI_TAG_TYPE_PARAMETER, URI_TAG_TYPE_PARAMETER_LIST, URI_TAG_TYPE_URIONLY } uri_tag_type; #define URI_TAG_USERNAME(x) URI_TAG_TYPE_USERNAME, (x) #define URI_TAG_DESTINATION(x) URI_TAG_TYPE_DESTINATION, (x) #define URI_TAG_HOST(x) URI_TAG_TYPE_HOST, (x) #define URI_TAG_PARAMETER(n, v) URI_TAG_TYPE_PARAMETER, (n), (v) #define URI_TAG_PARAMETER_LIST(x) URI_TAG_TYPE_PARAMETER_LIST, (x) #define URI_TAG_PORT(x) URI_TAG_TYPE_PORT, (x) #define URI_TAG_URI_ONLY(x) URI_TAG_TYPE_URIONLY, (x) #define TAG_END NULL #define URI_MAX_PARAMS 10 char * sofia_printf_uri( switch_core_session_t *session, ... ) { va_list ap; char *username = NULL, *destination = NULL, *host = NULL, *param_str = NULL, *uri_str = NULL; struct { char *name, *val; } param[URI_MAX_PARAMS]; int tag, port = 0, uri_only = 0, num_params = 0, len_params = 0; va_start( ap, session ); while( 1 ) { tag = va_arg( ap, int ); if( !tag ) break; switch( tag ) { case URI_TAG_TYPE_USERNAME: username = va_arg( ap, char * ); break; case URI_TAG_TYPE_DESTINATION: destination = va_arg( ap, char * ); break; case URI_TAG_TYPE_HOST: host = va_arg( ap, char * ); break; case URI_TAG_TYPE_PARAMETER: param[num_params].name = va_arg( ap, char * ); param[num_params].val = va_arg( ap, char * ); len_params += strlen(param[num_params].name) + strlen(param[num_params].val); num_params++; break; case URI_TAG_TYPE_PARAMETER_LIST: param_str = va_arg( ap, char * ); num_params = -1; break; case URI_TAG_TYPE_PORT: port = va_arg( ap, int ); break; case URI_TAG_TYPE_URIONLY: uri_only = va_arg( ap, int ); break; default: printf( "Unknown tag type\n" ); } } va_end( ap ); /* * We need at least host and destination here */ if( !host ) { printf( "no host tag specified\n" ); return NULL; } if( !destination ) { printf( "no destination tag specified\n" ); return NULL; } /* * Default value */ if( !username ) username = "user"; /* * Ugly code ahead... * Now if we'd manually allocate memory here we could count string lengths * and reserve enough room for the uri incl. parameters in one go and * put the params in after snprint'ing the first part... * (saving us the trouble of using alloca here) */ if( num_params > 0 ) { int n, len; char *p; param_str = alloca( len_params + num_params ); if( !param_str ) return NULL; p = param_str; for( n=0; n < num_params; n++ ) { len = strlen( param[n].name ); memcpy( p, param[n].name, len ); p += len; *p++ = '='; len = strlen( param[n].val ); memcpy( p, param[n].val, len ); p += len; if( n < num_params - 1 ) *p++ = '&'; } *p = '\0'; } else if( num_params == 0 ) { param_str = ""; } /* * The (fugly) output part */ if( !uri_only ) { if( port ) { printf( "\"%s\" <sip:%s@%s:%d>%s%s\n", username, destination, host, port, num_params ? ";" : "", param_str ); } else { printf( "\"%s\" <sip:%s@%s>%s%s\n", username, destination, host, num_params ? ";" : "", param_str ); } } else { if( port ) { printf( "sip:%s@%s:%d%s%s\n", destination, host, port, num_params ? ";" : "", param_str ); } else { printf( "sip:%s@%s%s%s\n", destination, host, num_params ? ";" : "", param_str ); } } return uri_str; } int main( void ) { switch_core_session_t session; printf( "\nCreating full uri...\n" ); sofia_printf_uri( &session, URI_TAG_USERNAME( "foobar" ), URI_TAG_HOST( "konata" ), URI_TAG_PORT( 1234 ), URI_TAG_DESTINATION( "myext" ), URI_TAG_PARAMETER( "transport", "tls" ), URI_TAG_PARAMETER( "rport", "12345" ), TAG_END ); printf( "\nCreating uri only (output w/o username)...\n" ); sofia_printf_uri( &session, URI_TAG_USERNAME( "foobar" ), URI_TAG_HOST( "konata" ), URI_TAG_PORT( 1234 ), URI_TAG_DESTINATION( "myext" ), URI_TAG_URI_ONLY( 1 ), URI_TAG_PARAMETER( "transport", "tls" ), TAG_END ); printf( "\nCreating full uri w/o port...\n" ); sofia_printf_uri( &session, URI_TAG_USERNAME( "foobar" ), URI_TAG_HOST( "konata" ), URI_TAG_DESTINATION( "myext" ), URI_TAG_PARAMETER_LIST( "transport=tls;bla=foo" ), TAG_END ); return 0; }