构建具有不同参数且可扩展的字符串
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
c89
只是想知道是否有更好的方法可以使用我在下面提供的代码来做到这一点。
我正在根据一些参数构建 sdp(会话描述协议)字符串。
但是,我可能需要扩展 sdp 以包含其他参数,即视频编解码器。
但是,我真的不想再用 if else 来构建我在下面完成的完整字符串。
我只是想知道这是否足够可扩展?我可以使用比我所做的更好的技术吗?
我刚刚复制了构建 sdp 的函数:
void create_sdp_string(char *sdp_string, char reinvite)
{
char session_id[MAX_STRING_LEN];
char session_version[MAX_STRING_LEN];
const char *local_ip_addr = "10.10.10.244";
apr_time_t time_usec = 0;
char session_identifier[MAX_STRING_LEN];
char media_transport[MAX_STRING_LEN];
char connection_info[MAX_STRING_LEN];
const char *audio_port = "49152";
/* Required sdp attributes */
#define V_PROTOCOL_VERSION "0"
#define USERNAME "JOEBLOGGS"
#define NETTYPE "IN"
#define ADDR_TYPE "IP4"
#define S_SESSION_NAME "SIP_CALL"
#define T_TIME_DESCRIPTION "0 0"
#define M_MEDIA_NAME_TRANSPORT_ADDR "RTP/AVP 0 8 101"
#define A_PCMU "rtpmap:0 PCMU/8000"
#define A_PCMA "rtpmap:8 PCMA/8000"
#define A_TELEPHONE "rtpmap:101 telephone-event/8000"
/* Get the time in micro seconds to create an unique session id */
time_usec = apr_time_usec(apr_time_now());
apr_snprintf(session_id, MAX_STRING_LEN, "%lu", (unsigned long)time_usec);
/* Get the time in micro seconds to create an unique session version */
time_usec = apr_time_usec(apr_time_now());
apr_snprintf(session_version, MAX_STRING_LEN, "%lu", (unsigned long)time_usec);
/* Build session identifier */
apr_snprintf(session_identifier,
MAX_STRING_LEN,
"o="USERNAME" "NETTYPE" %s %s "ADDR_TYPE" %s\n",
session_id,
session_version,
local_ip_addr);
/* Build media transport */
apr_snprintf(media_transport,
MAX_STRING_LEN,
"m=audio %s "M_MEDIA_NAME_TRANSPORT_ADDR"\n",
audio_port);
/* Build connection information */
apr_snprintf(connection_info,
MAX_STRING_LEN,
"c="NETTYPE" "ADDR_TYPE" %s\n",
local_ip_addr);
if(reinvite == FALSE) {
/* Build complete sdp string for cases that are not reinvite */
apr_snprintf(sdp_string,
MAX_SDP_STRING_LEN,
"v="V_PROTOCOL_VERSION"\n"
"%s"
"s="S_SESSION_NAME"\n"
"%s"
"t="T_TIME_DESCRIPTION"\n"
"%s"
"a="A_PCMU"\n"
"a="A_PCMA"\n"
"a="A_TELEPHONE"\n",
session_identifier,
connection_info,
media_transport);
}
else if(reinvite == TRUE) {
/* Build complete sdp string for cases that are for reinvite 'inactive' */
#define INACTIVE "inactive"
apr_snprintf(sdp_string,
MAX_SDP_STRING_LEN,
"v="V_PROTOCOL_VERSION"\n"
"%s"
"s="S_SESSION_NAME"\n"
"%s"
"t="T_TIME_DESCRIPTION"\n"
"%s"
"a="A_PCMU"\n"
"a="A_PCMA"\n"
"a="A_TELEPHONE"\n"
"a="INACTIVE"\n",
session_identifier,
connection_info,
media_transport);
}
}
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
c89
Just wondering is there a better way to do this with the code I have provided below.
I am building a sdp (session description protocol) string from some parameters.
However, I might need to extend the sdp to include other parameters i.e. video codecs.
However, I don't really want to have another if else to build the complete string I have done below.
I am just wondering is this scalable enough? Is there any technique I could use that is better than what I have done.
I have just copied the function that does the sdp building:
void create_sdp_string(char *sdp_string, char reinvite)
{
char session_id[MAX_STRING_LEN];
char session_version[MAX_STRING_LEN];
const char *local_ip_addr = "10.10.10.244";
apr_time_t time_usec = 0;
char session_identifier[MAX_STRING_LEN];
char media_transport[MAX_STRING_LEN];
char connection_info[MAX_STRING_LEN];
const char *audio_port = "49152";
/* Required sdp attributes */
#define V_PROTOCOL_VERSION "0"
#define USERNAME "JOEBLOGGS"
#define NETTYPE "IN"
#define ADDR_TYPE "IP4"
#define S_SESSION_NAME "SIP_CALL"
#define T_TIME_DESCRIPTION "0 0"
#define M_MEDIA_NAME_TRANSPORT_ADDR "RTP/AVP 0 8 101"
#define A_PCMU "rtpmap:0 PCMU/8000"
#define A_PCMA "rtpmap:8 PCMA/8000"
#define A_TELEPHONE "rtpmap:101 telephone-event/8000"
/* Get the time in micro seconds to create an unique session id */
time_usec = apr_time_usec(apr_time_now());
apr_snprintf(session_id, MAX_STRING_LEN, "%lu", (unsigned long)time_usec);
/* Get the time in micro seconds to create an unique session version */
time_usec = apr_time_usec(apr_time_now());
apr_snprintf(session_version, MAX_STRING_LEN, "%lu", (unsigned long)time_usec);
/* Build session identifier */
apr_snprintf(session_identifier,
MAX_STRING_LEN,
"o="USERNAME" "NETTYPE" %s %s "ADDR_TYPE" %s\n",
session_id,
session_version,
local_ip_addr);
/* Build media transport */
apr_snprintf(media_transport,
MAX_STRING_LEN,
"m=audio %s "M_MEDIA_NAME_TRANSPORT_ADDR"\n",
audio_port);
/* Build connection information */
apr_snprintf(connection_info,
MAX_STRING_LEN,
"c="NETTYPE" "ADDR_TYPE" %s\n",
local_ip_addr);
if(reinvite == FALSE) {
/* Build complete sdp string for cases that are not reinvite */
apr_snprintf(sdp_string,
MAX_SDP_STRING_LEN,
"v="V_PROTOCOL_VERSION"\n"
"%s"
"s="S_SESSION_NAME"\n"
"%s"
"t="T_TIME_DESCRIPTION"\n"
"%s"
"a="A_PCMU"\n"
"a="A_PCMA"\n"
"a="A_TELEPHONE"\n",
session_identifier,
connection_info,
media_transport);
}
else if(reinvite == TRUE) {
/* Build complete sdp string for cases that are for reinvite 'inactive' */
#define INACTIVE "inactive"
apr_snprintf(sdp_string,
MAX_SDP_STRING_LEN,
"v="V_PROTOCOL_VERSION"\n"
"%s"
"s="S_SESSION_NAME"\n"
"%s"
"t="T_TIME_DESCRIPTION"\n"
"%s"
"a="A_PCMU"\n"
"a="A_PCMA"\n"
"a="A_TELEPHONE"\n"
"a="INACTIVE"\n",
session_identifier,
connection_info,
media_transport);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果你想要更通用的东西,请看这个:
这样可以很容易地将任何内容附加到你已经创建的字符串中。
If you want something more generic look at this:
This way it's easy to append anything to string which you already created.
我认为代码底部的 if/else if 语句非常丑陋,因为您已将大量代码复制到两个不同的位置。您可能会在一处编辑它,但忘记在另一处编辑它。你真的应该尽力避免这种情况。一种方法是用以下语句替换
if/else if
语句:EDIT1: 使此代码更好的另一种方法是编写您自己的 printf 版本bytes 到 sdp_string,然后为要添加到字符串的每个不同信息调用该函数一次。
I consider the
if/else if
statement at the bottom of your code to be pretty ugly because you have copied a lot of code to two different places. You might edit it one place but forget to edit it in another. You should really try to avoid this. One way to do this is to replace theif/else if
statement with this:EDIT1: Another way to make this code better would be to write your own version of printf adds bytes to sdp_string, and then call that function once for each different piece of information you want to add to the string.
如果您的代码中存在性能瓶颈,那么这不是
if/else
结构的问题,而是您多次扫描所有字符串的事实。基本上,您主要使用
snprintf
的变体来连接字符串,这是非常低效的。切换到一种策略,将字符串一个接一个地写入到位,就像您在文件中使用
fputs
所做的那样:通过
snprintf
的返回给出的字符串长度。#define
中,而是将它们放在实际数组中,例如static char const V_PROTOCOL_VERSION = { "0" };
。此类字符串的大小是一个编译时常量,您可以通过(sizeof V_PROTOCOL_VERSION)-1
来获取。与您编写的字符串的已知长度
这可确保您复制的每个字符恰好接触所有这些常量字符串一次。
If there is a performance bottleneck in your code this is not the
if/else
structure, but the fact that you scan all your strings several times.Basically you use your variant of
snprintf
mostly to concatenate strings, this is very unefficient.Switch to a strategy that writes the strings in place just one after another, as you would do with
fputs
if this were a file:string length which is given through the return of
snprintf
.#define
put the in a real array such asstatic char const V_PROTOCOL_VERSION = { "0" };
. the size of such an string is a compile time constant that you can optain by(sizeof V_PROTOCOL_VERSION)-1
.with the known length of the string that you have written
This ensures that you touch all those constant strings exactly once per character that you copy.