/* Return the number of multibyte characters in the character string starting at STRING and ending at STRING + LEN. */ size_t mbsnlen (const char *string, size_t len) { if (MB_CUR_MAX > 1) { size_t count; mbi_iterator_t iter; count = 0; for (mbi_init (iter, string, len); mbi_avail (iter); mbi_advance (iter)) count++; return count; } else return len; }
int mbmemcasecmp (const char *s1, size_t n1, const char *s2, size_t n2) { if (s1 == s2) return (n1 < n2 ? -1 : n1 > n2 ? 1 : 0); if (MB_CUR_MAX > 1) { mbi_iterator_t iter1; mbi_iterator_t iter2; mbi_init (iter1, s1, n1); mbi_init (iter2, s2, n2); while (mbi_avail (iter1) && mbi_avail (iter2)) { int cmp = mb_casecmp (mbi_cur (iter1), mbi_cur (iter2)); if (cmp != 0) return cmp; mbi_advance (iter1); mbi_advance (iter2); } if (mbi_avail (iter1)) /* s2 terminated before s1. */ return 1; if (mbi_avail (iter2)) /* s1 terminated before s2. */ return -1; return 0; } else { const unsigned char *s1_end = (const unsigned char *) (s1 + n1); const unsigned char *s2_end = (const unsigned char *) (s2 + n2); const unsigned char *p1 = (const unsigned char *) s1; const unsigned char *p2 = (const unsigned char *) s2; while (p1 < s1_end && p2 < s2_end) { unsigned char c1 = TOLOWER (*p1); unsigned char c2 = TOLOWER (*p2); if (c1 != c2) { if (UCHAR_MAX <= INT_MAX) return c1 - c2; else /* On machines where 'char' and 'int' are types of the same size, the difference of two 'unsigned char' values - including the sign bit - doesn't fit in an 'int'. */ return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); } ++p1; ++p2; } if (p1 < s1_end) /* s2 terminated before s1. */ return 1; if (p2 < s2_end) /* s1 terminated before s2. */ return -1; return 0; } }
char * trim2(const char *s, int how) { char *d; d = strdup(s); if (!d) xalloc_die(); if (MB_CUR_MAX > 1) { mbi_iterator_t i; /* Trim leading whitespaces. */ if (how != TRIM_TRAILING) { mbi_init (i, d, strlen (d)); for (; mbi_avail (i) && mb_isspace (mbi_cur (i)); mbi_advance (i)) ; memmove (d, mbi_cur_ptr (i), strlen (mbi_cur_ptr (i)) + 1); } /* Trim trailing whitespaces. */ if (how != TRIM_LEADING) { int state = 0; char *r IF_LINT (= NULL); /* used only while state = 2 */ mbi_init (i, d, strlen (d)); for (; mbi_avail (i); mbi_advance (i)) { if (state == 0 && mb_isspace (mbi_cur (i))) { state = 0; continue; } if (state == 0 && !mb_isspace (mbi_cur (i))) { state = 1; continue; } if (state == 1 && !mb_isspace (mbi_cur (i))) { state = 1; continue; } if (state == 1 && mb_isspace (mbi_cur (i))) { state = 2; r = (char *) mbi_cur_ptr (i); } else if (state == 2 && mb_isspace (mbi_cur (i))) { state = 2; } else { state = 1; } } if (state == 2) *r = '\0'; }
static int tag_image (char *text, struct text_buffer *outbuf) { mbi_iterator_t iter; enum { state_kw, state_val, state_qstr, state_delim } state = state_kw; struct text_buffer tmpbuf; char *kw; struct info_tag *tag_head = NULL, *tag; int escaped = 0; text_buffer_init (&tmpbuf); for (mbi_init (iter, text, strlen (text)); mbi_avail (iter); mbi_advance (iter)) { const char *cur_ptr; size_t cur_len; if (mb_isspace (mbi_cur (iter))) { if (state == state_val) { struct info_tag *new_kw = tag_found_keyword (&tmpbuf, &kw); new_kw->next = tag_head; tag_head = new_kw; state = state_delim; continue; } if (state == state_delim) continue; } cur_len = mb_len (mbi_cur (iter)); cur_ptr = mbi_cur_ptr (iter); if (state == state_qstr && escaped) { escaped = 0; } else if (cur_len == 1) { switch (*cur_ptr) { case '=': text_buffer_add_char (&tmpbuf, 0); kw = tmpbuf.base; if (!mbi_avail (iter)) break; mbi_advance (iter); state = state_val; cur_len = mb_len (mbi_cur (iter)); cur_ptr = mbi_cur_ptr (iter); if (!(cur_len == 1 && *cur_ptr == '"')) break; /* fall through */ case '"': if (state == state_val) { state = state_qstr; continue; } if (state == state_qstr) { struct info_tag *new_kw = tag_found_keyword (&tmpbuf, &kw); new_kw->next = tag_head; tag_head = new_kw; state = state_delim; continue; } break; case '\\': if (state == state_qstr) { escaped = 1; continue; } } } text_buffer_add_string (&tmpbuf, cur_ptr, cur_len); } tag = info_tag_find (tag_head, "text"); if (!tag) tag = info_tag_find (tag_head, "alt"); if (tag) { text_buffer_add_string (outbuf, tag->val, strlen (tag->val)); } text_buffer_free (&tmpbuf); info_tag_free (tag_head); return 0; }