return s;
}
+/** Return the the first occurrence of <b>needle</b> in <b>haystack</b> that
+ * occurs at the start of a line (that is, at the beginning of <b>haystack</b>
+ * or immediately after a newline). Return NULL if no such string is found.
+ */
+const char *
+find_str_at_start_of_line(const char *haystack, const char *needle)
+{
+ size_t needle_len = strlen(needle);
+
+ do {
+ if (!strncmp(haystack, needle, needle_len))
+ return haystack;
+
+ haystack = strchr(haystack, '\n');
+ if (!haystack)
+ return NULL;
+ else
+ ++haystack;
+ } while (*haystack);
+
+ return NULL;
+}
+
/** Return true iff the 'len' bytes at 'mem' are all zero. */
int
tor_mem_is_zero(const char *mem, size_t len)
const char *eat_whitespace_eos_no_nl(const char *s, const char *eos) ATTR_PURE;
const char *find_whitespace(const char *s) ATTR_PURE;
const char *find_whitespace_eos(const char *s, const char *eos) ATTR_PURE;
+const char *find_str_at_start_of_line(const char *haystack, const char *needle)
+ ATTR_PURE;
int tor_mem_is_zero(const char *mem, size_t len) ATTR_PURE;
int tor_digest_is_zero(const char *digest) ATTR_PURE;
int tor_digest256_is_zero(const char *digest) ATTR_PURE;
{
char stats_end_str[ISO_TIME_LEN+1], stats_start_str[ISO_TIME_LEN+1],
*controller_str, *eos, *eol, *summary;
- const char *stats_end_first = "bridge-stats-end ",
- *stats_end_middle = "\nbridge-stats-end ",
- *ips_first = "bridge-ips",
- *ips_middle = "\nbridge-ips",
- *tmp;
+
+ const char *BRIDGE_STATS_END = "bridge-stats-end ";
+ const char *BRIDGE_IPS = "bridge-ips ";
+ const char *tmp;
time_t stats_end_time;
size_t controller_len;
int seconds;
/* Parse timestamp and number of seconds from
"bridge-stats-end YYYY-MM-DD HH:MM:SS (N s)" */
- if (!strncmp(stats_str, stats_end_first, strlen(stats_end_first))) {
- tmp = stats_str + strlen(stats_end_first);
- } else {
- tmp = strstr(stats_str, stats_end_middle);
- if (!tmp)
- return NULL;
- tmp += strlen(stats_end_middle);
- }
+ tmp = find_str_at_start_of_line(stats_str, BRIDGE_STATS_END);
+ if (!tmp)
+ return NULL;
+ tmp += strlen(BRIDGE_STATS_END);
+
if (strlen(tmp) < ISO_TIME_LEN + 6)
return NULL;
strlcpy(stats_end_str, tmp, sizeof(stats_end_str));
format_iso_time(stats_start_str, stats_end_time - seconds);
/* Parse: "bridge-ips CC=N,CC=N,..." */
- if (!strncmp(stats_str, ips_first, strlen(ips_first))) {
- tmp = stats_str + strlen(ips_first);
- } else {
- tmp = strstr(stats_str, ips_middle);
- if (!tmp)
- return NULL;
- tmp += strlen(ips_middle);
- }
- if (strlen(tmp) > 2 && !strncmp(tmp, " ", 1))
- tmp += 1;
- else
- tmp = "";
- summary = tor_malloc(strlen(tmp) + 1);
- strlcpy(summary, tmp, strlen(tmp) + 1);
- eol = strstr(summary, "\n");
+ tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS);
+ if (!tmp)
+ return NULL;
+ tmp += strlen(BRIDGE_IPS);
+
+ tmp = eat_whitespace_no_nl(tmp);
+
+ eol = strchr(tmp, '\n');
if (eol)
- eol[0] = '\0';
+ summary = tor_strndup(tmp, eol-tmp);
+ else
+ summary = tor_strdup(tmp);
+
controller_len = strlen("TimeStarted=\"\" CountrySummary=") +
strlen(summary) + 42;
controller_str = tor_malloc(controller_len);
;
}
+static void
+test_util_find_str_at_start_of_line(void *ptr)
+{
+ const char *long_string =
+ "hello world. hello world. hello hello. howdy.\n"
+ "hello hello world\n";
+
+ (void)ptr;
+
+ /* not-found case. */
+ tt_assert(! find_str_at_start_of_line(long_string, "fred"));
+
+ /* not-found case where haystack doesn't end with \n */
+ tt_assert(! find_str_at_start_of_line("foobar\nbaz", "fred"));
+
+ /* start-of-string case */
+ tt_assert(long_string ==
+ find_str_at_start_of_line(long_string, "hello world."));
+
+ /* start-of-line case */
+ tt_assert(strchr(long_string,'\n')+1 ==
+ find_str_at_start_of_line(long_string, "hello hello"));
+ done:
+ ;
+}
+
+
#define UTIL_LEGACY(name) \
{ #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
+#define UTIL_TEST(name, flags) \
+ { #name, test_util_ ## name, flags, NULL, NULL }
+
struct testcase_t util_tests[] = {
UTIL_LEGACY(time),
UTIL_LEGACY(config_line),
UTIL_LEGACY(threads),
UTIL_LEGACY(sscanf),
UTIL_LEGACY(strtok),
+ UTIL_TEST(find_str_at_start_of_line, 0),
END_OF_TESTCASES
};