TEST_F(TestIBUtilLogformat, test_parse_default) { ib_status_t rc; ib_logformat_t *lf = NULL; const ib_list_node_t *node; const ib_logformat_item_t *item; static char linebuf[buflen + 1]; static const char *formatted = \ TIME_STAMP " " HOST_NAME " " REMOTE_IP " " SENSOR_ID " " SITE_ID " " \ TX_ID " " LOG_FILE; size_t len; rc = ib_logformat_create(MM(), &lf); ASSERT_EQ(IB_OK, rc); rc = ib_logformat_parse(lf, IB_LOGFORMAT_DEFAULT); ASSERT_EQ(IB_OK, rc); ASSERT_STREQ(IB_LOGFORMAT_DEFAULT, lf->format); ASSERT_EQ(13U, ib_list_elements(lf->items)); node = ib_list_first_const(lf->items); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('T', item->item.field.fchar); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_literal, item->itype); ASSERT_STREQ(" ", item->item.literal.buf.short_str); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('h', item->item.field.fchar); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_literal, item->itype); ASSERT_STREQ(" ", item->item.literal.buf.short_str); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('a', item->item.field.fchar); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_literal, item->itype); ASSERT_STREQ(" ", item->item.literal.buf.short_str); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('S', item->item.field.fchar); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_literal, item->itype); ASSERT_STREQ(" ", item->item.literal.buf.short_str); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('s', item->item.field.fchar); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_literal, item->itype); ASSERT_STREQ(" ", item->item.literal.buf.short_str); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('t', item->item.field.fchar); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_literal, item->itype); ASSERT_STREQ(" ", item->item.literal.buf.short_str); node = ib_list_node_next_const(node); ASSERT_TRUE(node); item = (const ib_logformat_item_t *)node->data; ASSERT_EQ(item_type_format, item->itype); ASSERT_EQ('f', item->item.field.fchar); rc = ib_logformat_format(lf, linebuf, buflen, &len, format_field, NULL); ASSERT_EQ(IB_OK, rc); ASSERT_STREQ(formatted, linebuf); /* Verify that truncation is handled correctly */ rc = ib_logformat_format(lf, linebuf, trunclen, &len, format_field, NULL); ASSERT_EQ(IB_ETRUNC, rc); ASSERT_EQ(len, trunclen-1); char trunc_buf[trunclen]; strncpy(trunc_buf, formatted, trunclen-1); trunc_buf[trunclen-1] = '\0'; ASSERT_STREQ(trunc_buf, linebuf); }
ib_status_t ib_string_join( const char *join_string, ib_list_t *list, ib_mm_t mm, const char **pout, size_t *pout_len ) { assert(join_string != NULL); assert(list != NULL); assert(pout != NULL); assert(pout_len != NULL); const ib_list_node_t *node; char *end; /* Points to the \0 in out. */ const char *out; size_t out_len = 1; /* Size to hold an empty string, '\0' */ size_t *str_len; /* Array of lengths of char*s in list. */ size_t str_idx; /* Index into str_len. */ size_t join_string_len; join_string_len = strlen(join_string); /* Handle the base-case and avoid asking for size 0 memory segments. */ if (ib_list_elements(list) == 0) { *pout = ""; *pout_len = 0; return IB_OK; } /* First, build a place to cache string lengths. */ str_len = ib_mm_alloc(mm, sizeof(*str_len) * ib_list_elements(list)); if (str_len == NULL) { return IB_EALLOC; } /* Record each string length and sum those lengths into out_len. * Recall that out_len starts equal to 1 for the '\0'. */ str_idx = 0; IB_LIST_LOOP_CONST(list, node) { const size_t len = strlen((const char *)ib_list_node_data_const(node)); out_len += len; str_len[str_idx] = len; ++str_idx; } /* Increase out_len by the join string length * (n-1) elements. */ out_len += (ib_list_elements(list) - 1)* join_string_len; /* Allocate the final string. */ end = ib_mm_alloc(mm, out_len); if (end == NULL) { return IB_EALLOC; } /* Setup vars for joining the strings into out. */ out = end; str_idx = 0; node = ib_list_first(list); /* Copy the first string. We know the list is > 0 elements long. */ strcpy(end, (const char *)ib_list_node_data_const(node)); end += str_len[str_idx]; ++str_idx; /* Having copied the first string, now copy the join string, then the * the next string until the end of the list. */ for ( node = ib_list_node_next_const(node); node != NULL; node = ib_list_node_next_const(node) ) { /* Copy the join string first. */ strcpy(end, join_string); end += join_string_len; /* Copy the lagging string. */ strcpy(end, (const char *)ib_list_node_data_const(node)); end += str_len[str_idx]; ++str_idx; } /* Commit work back to the caller. */ *pout = out; *pout_len = out_len-1; return IB_OK; }