コード例 #1
0
ファイル: rinku.c プロジェクト: Arkham/rinku
int
rinku_autolink(
	struct buf *ob,
	const uint8_t *text,
	size_t size,
	autolink_mode mode,
	unsigned int flags,
	const char *link_attr,
	const char **skip_tags,
	void (*link_text_cb)(struct buf *ob, const struct buf *link, void *payload),
	void *payload)
{
	size_t i, end, last_link_found = 0;
	struct buf *link = bufnew(16);
	char active_chars[256];
	void (*link_url_cb)(struct buf *, const struct buf *, void *);
	int link_count = 0;

	if (!text || size == 0)
		return 0;

	memset(active_chars, 0x0, sizeof(active_chars));

	active_chars['<'] = AUTOLINK_ACTION_SKIP_TAG;

	if (mode & AUTOLINK_EMAILS)
		active_chars['@'] = AUTOLINK_ACTION_EMAIL;

	if (mode & AUTOLINK_URLS) {
		active_chars['w'] = AUTOLINK_ACTION_WWW;
		active_chars['W'] = AUTOLINK_ACTION_WWW;
		active_chars[':'] = AUTOLINK_ACTION_URL;
	}

	if (link_text_cb == NULL)
		link_text_cb = &autolink__print;

	if (link_attr != NULL) {
		while (isspace(*link_attr))
			link_attr++;
	}

	bufgrow(ob, size);

	i = end = 0;

	while (i < size) {
		size_t rewind, link_end;
		char action = 0;

		while (end < size && (action = active_chars[text[end]]) == 0)
			end++;

		if (end == size) {
			if (link_count > 0)
				bufput(ob, text + i, end - i);
			break;
		}

		if (action == AUTOLINK_ACTION_SKIP_TAG) {
			end += autolink__skip_tag(ob,
				text + end, size - end, skip_tags);

			continue;
		}

		link->size = 0;

		link_end = g_callbacks[(int)action](
			&rewind, link, (uint8_t *)text + end,
			end - last_link_found,
			size - end, flags);

		/* print the link */
		if (link_end > 0) {
			bufput(ob, text + i, end - i - rewind);

			bufputs(ob, g_hrefs[(int)action]);
			print_link(ob, link->data, link->size);

			if (link_attr) {
				BUFPUTSL(ob, "\" ");
				bufputs(ob, link_attr);
				bufputc(ob, '>');
			} else {
				BUFPUTSL(ob, "\">");
			}

			link_text_cb(ob, link, payload);
			BUFPUTSL(ob, "</a>");

			link_count++;
			i = end + link_end;
			last_link_found = end = i;
		} else {
			end = end + 1;
		}
	}

	bufrelease(link);
	return link_count;
}
コード例 #2
0
ファイル: rinku.c プロジェクト: vmg/rinku
int
rinku_autolink(
	struct buf *ob,
	const uint8_t *text,
	size_t size,
	autolink_mode mode,
	unsigned int flags,
	const char *link_attr,
	const char **skip_tags,
	void (*link_text_cb)(struct buf *, const uint8_t *, size_t, void *),
	void *payload)
{
	size_t i, end;
	char active_chars[256] = {0};
	int link_count = 0;

	if (!text || size == 0)
		return 0;

	active_chars['<'] = AUTOLINK_ACTION_SKIP_TAG;

	if (mode & AUTOLINK_EMAILS)
		active_chars['@'] = AUTOLINK_ACTION_EMAIL;

	if (mode & AUTOLINK_URLS) {
		active_chars['w'] = AUTOLINK_ACTION_WWW;
		active_chars['W'] = AUTOLINK_ACTION_WWW;
		active_chars[':'] = AUTOLINK_ACTION_URL;
	}

	if (link_attr != NULL) {
		while (rinku_isspace(*link_attr))
			link_attr++;
	}

	bufgrow(ob, size);

	i = end = 0;

	while (i < size) {
		struct autolink_pos link;
		bool link_found;
		char action = 0;

		while (end < size && (action = active_chars[text[end]]) == 0)
			end++;

		if (end == size) {
			if (link_count > 0)
				bufput(ob, text + i, end - i);
			break;
		}

		if (action == AUTOLINK_ACTION_SKIP_TAG) {
			end += autolink__skip_tag(ob,
				text + end, size - end, skip_tags);
			continue;
		}

		link_found = g_callbacks[(int)action](
			&link, text, end, size, flags);

		if (link_found && link.start >= i) {
			const uint8_t *link_str = text + link.start;
			const size_t link_len = link.end - link.start;

			bufput(ob, text + i, link.start - i);
			bufputs(ob, g_hrefs[(int)action]);
			print_link(ob, link_str, link_len);

			if (link_attr) {
				BUFPUTSL(ob, "\" ");
				bufputs(ob, link_attr);
				bufputc(ob, '>');
			} else {
				BUFPUTSL(ob, "\">");
			}

			if (link_text_cb) {
				link_text_cb(ob, link_str, link_len, payload);
			} else {
				bufput(ob, link_str, link_len);
			}

			BUFPUTSL(ob, "</a>");

			link_count++;
			end = i = link.end;
		} else {
			end = end + 1;
		}
	}

	return link_count;
}