int main () { /* Empty string. */ { static const uint32_t input[] = { 0 }; ASSERT (u32_strlen (input) == 0); } /* Simple string. */ { /* "Grüß Gott. Здравствуйте! x=(-b±sqrt(b²-4ac))/(2a) 日本語,中文,한글" */ static const uint32_t input[] = { 'G', 'r', 0x00FC, 0x00DF, ' ', 'G', 'o', 't', 't', '.', ' ', 0x0417, 0x0434, 0x0440, 0x0430, 0x0432, 0x0441, 0x0442, 0x0432, 0x0443, 0x0439, 0x0442, 0x0435, '!', ' ', 'x', '=', '(', '-', 'b', 0x00B1, 's', 'q', 'r', 't', '(', 'b', 0x00B2, '-', '4', 'a', 'c', ')', ')', '/', '(', '2', 'a', ')', ' ', ' ', 0x65E5, 0x672C, 0x8A9E, ',', 0x4E2D, 0x6587, ',', 0xD55C, 0xAE00, 0 }; ASSERT (u32_strlen (input) == SIZEOF (input) - 1); } /* String with characters outside the BMP. */ { static const uint32_t input[] = { '-', '(', 0x1D51E, 0x00D7, 0x1D51F, ')', '=', 0x1D51F, 0x00D7, 0x1D51E, 0 }; ASSERT (u32_strlen (input) == SIZEOF (input) - 1); } return 0; }
static void test_function (uint32_t * (*my_asnprintf) (uint32_t *, size_t *, const char *, ...)) { /* Test the support of the 's' conversion specifier for strings. */ { const char *locale_string = "\304rger"; /* Ärger */ { size_t length; uint32_t *result = my_asnprintf (NULL, &length, "%s %d", locale_string, 33, 44, 55); static const uint32_t expected[] = { 0x00c4, 'r', 'g', 'e', 'r', ' ', '3', '3', 0 }; ASSERT (result != NULL); ASSERT (u32_strcmp (result, expected) == 0); ASSERT (length == u32_strlen (result)); free (result); } { /* Width. */ size_t length; uint32_t *result = my_asnprintf (NULL, &length, "%10s %d", locale_string, 33, 44, 55); static const uint32_t expected[] = { ' ', ' ', ' ', ' ', ' ', 0x00c4, 'r', 'g', 'e', 'r', ' ', '3', '3', 0 }; ASSERT (result != NULL); ASSERT (u32_strcmp (result, expected) == 0); ASSERT (length == u32_strlen (result)); free (result); } { /* FLAG_LEFT. */ size_t length; uint32_t *result = my_asnprintf (NULL, &length, "%-10s %d", locale_string, 33, 44, 55); static const uint32_t expected[] = { 0x00c4, 'r', 'g', 'e', 'r', ' ', ' ', ' ', ' ', ' ', ' ', '3', '3', 0 }; ASSERT (result != NULL); ASSERT (u32_strcmp (result, expected) == 0); ASSERT (length == u32_strlen (result)); free (result); } { /* FLAG_ZERO: no effect. */ size_t length; uint32_t *result = my_asnprintf (NULL, &length, "%010s %d", locale_string, 33, 44, 55); static const uint32_t expected[] = { ' ', ' ', ' ', ' ', ' ', 0x00c4, 'r', 'g', 'e', 'r', ' ', '3', '3', 0 }; ASSERT (result != NULL); ASSERT (u32_strcmp (result, expected) == 0); ASSERT (length == u32_strlen (result)); free (result); } } }
w_string_t *w_string_new(const char *str) { w_string_t *s; uint32_t len = u32_strlen(str); uint32_t hval; char *buf; hval = w_hash_bytes(str, len, 0); s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->hval = hval; s->len = len; s->slice = NULL; buf = (char*)(s + 1); memcpy(buf, str, len); buf[len] = 0; s->buf = buf; return s; }
w_string_t *w_string_path_cat_cstr(w_string_t *parent, const char *rhs) { w_string_t *s; int len; char *buf; uint32_t rhs_len = u32_strlen(rhs); if (rhs_len == 0) { w_string_addref(parent); return parent; } len = parent->len + rhs_len + 1; s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); memcpy(buf, parent->buf, parent->len); buf[parent->len] = WATCHMAN_DIR_SEP; memcpy(buf + parent->len + 1, rhs, rhs_len); buf[parent->len + 1 + rhs_len] = '\0'; s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
/* make a lowercased copy of string */ w_string_t *w_string_new_lower(const char *str) { w_string_t *s; uint32_t len = u32_strlen(str); char *buf; uint32_t i; s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->len = len; s->slice = NULL; buf = (char*)(s + 1); // TODO: optionally use ICU for (i = 0; i < len; i++) { buf[i] = (char)tolower((uint8_t)str[i]); } buf[len] = 0; s->buf = buf; s->hval = w_hash_bytes(buf, len, 0); return s; }
static uint32_t * my_xasprintf (const char *format, ...) { va_list args; uint32_t buf[1000]; int retval; size_t length; uint32_t *result; va_start (args, format); retval = u32_vsprintf (buf, format, args); va_end (args); if (retval < 0 || retval >= (int) sizeof (buf)) return NULL; length = u32_strlen (buf); result = XNMALLOC (length + 1, uint32_t); u32_cpy (result, buf, length + 1); return result; }
// Given a json array, concat the elements using a delimiter w_string_t *w_string_implode(json_t *arr, const char *delim) { uint32_t delim_len = u32_strlen(delim); uint32_t len = 0; uint32_t i; w_string_t *s; char *buf; if (json_array_size(arr) == 0) { return w_string_new(""); } if (json_array_size(arr) == 1) { return w_string_new(json_string_value(json_array_get(arr, 0))); } len = ((uint32_t)json_array_size(arr) - 1) * delim_len; for (i = 0; i < json_array_size(arr); i++) { const char *str; str = json_string_value(json_array_get(arr, i)); len += u32_strlen(str); } s = malloc(sizeof(*s) + len + 1); if (!s) { perror("no memory available"); abort(); } s->refcnt = 1; s->slice = NULL; buf = (char*)(s + 1); s->buf = buf; for (i = 0; i < json_array_size(arr); i++) { const char *str; uint32_t l; str = json_string_value(json_array_get(arr, i)); l = u32_strlen(str); memcpy(buf, str, l); // Final string doesn't want delimiter after it if (i == json_array_size(arr) - 1) { buf += l; break; } memcpy(buf + l, delim, delim_len); buf += l + delim_len; } *buf = '\0'; s->len = (uint32_t)(buf - s->buf); s->hval = w_hash_bytes(s->buf, s->len, 0); return s; }
bool w_string_equal_cstring(const w_string_t *a, const char *b) { uint32_t blen = u32_strlen(b); if (a->len != blen) return false; return memcmp(a->buf, b, a->len) == 0 ? true : false; }
static int glist_key(GGadget *g, GEvent *event) { GDList *gl = (GDList *) g; uint16_t keysym = event->u.chr.keysym; int sofar_pos = gl->sofar_pos; int loff, xoff, sel=-1; int refresh = false; if ( event->type == et_charup ) return( false ); if ( !g->takes_input || (g->state!=gs_enabled && g->state!=gs_active && g->state!=gs_focused )) return(false ); if ( gl->ispopup && event->u.chr.keysym == GK_Return ) { GListDoubleClick(gl,false,-1); return( true ); } else if ( gl->ispopup && event->u.chr.keysym == GK_Escape ) { GListClose(gl); return( true ); } if ( event->u.chr.keysym == GK_Return || event->u.chr.keysym == GK_Tab || event->u.chr.keysym == GK_BackTab || event->u.chr.keysym == GK_Escape ) return( false ); GDrawCancelTimer(gl->enduser); gl->enduser = NULL; gl->sofar_pos = 0; loff = 0x80000000; xoff = 0x80000000; sel = -1; if ( keysym == GK_Home || keysym == GK_KP_Home || keysym == GK_Begin || keysym == GK_KP_Begin ) { loff = -gl->loff; xoff = -gl->xoff; sel = 0; } else if ( keysym == GK_End || keysym == GK_KP_End ) { loff = GListTopInWindow(gl,gl->ltot-1)-gl->loff; xoff = -gl->xoff; sel = gl->ltot-1; } else if ( keysym == GK_Up || keysym == GK_KP_Up ) { if (( sel = GListGetFirstSelPos(&gl->g)-1 )<0 ) { /*if ( gl->loff!=0 ) loff = -1; else loff = 0;*/ sel = 0; } } else if ( keysym == GK_Down || keysym == GK_KP_Down ) { if (( sel = GListGetFirstSelPos(&gl->g))!= -1 ) ++sel; else /*if ( gl->loff + GListLinesInWindow(gl,gl->loff)<gl->ltot ) loff = 1; else loff = 0;*/ sel = 0; } else if ( keysym == GK_Left || keysym == GK_KP_Left ) { xoff = -GDrawPointsToPixels(gl->g.base,6); } else if ( keysym == GK_Right || keysym == GK_KP_Right ) { xoff = GDrawPointsToPixels(gl->g.base,6); } else if ( keysym == GK_Page_Up || keysym == GK_KP_Page_Up ) { loff = GListTopInWindow(gl,gl->loff); if ( loff == gl->loff ) /* Normally we leave one line in window from before, except if only one line fits */ loff = GListTopInWindow(gl,gl->loff-1); loff -= gl->loff; if (( sel = GListGetFirstSelPos(&gl->g))!= -1 ) { if (( sel += loff )<0 ) sel = 0; } } else if ( keysym == GK_Page_Down || keysym == GK_KP_Page_Down ) { loff = GListLinesInWindow(gl,gl->loff)-1; if ( loff<=0 ) loff = 1; if ( loff + gl->loff >= gl->ltot ) loff = GListTopInWindow(gl,gl->ltot-1)-gl->loff; if (( sel = GListGetFirstSelPos(&gl->g))!= -1 ) { if (( sel += loff )>=gl->ltot ) sel = gl->ltot-1; } } else if ( keysym == GK_BackSpace && gl->orderer ) { /* ordered lists may be reversed by typing backspace */ gl->backwards = !gl->backwards; GListOrderIt(gl); sel = GListGetFirstSelPos(&gl->g); if ( sel!=-1 ) { int top = GListTopInWindow(gl,gl->ltot-1); gl->loff = sel-1; if ( gl->loff > top ) gl->loff = top; if ( sel-1<0 ) gl->loff = 0; } GScrollBarSetPos(&gl->vsb->g,gl->loff); _ggadget_redraw(&gl->g); return( true ); } else if ( event->u.chr.chars[0]!='\0' && gl->orderer ) { int len = u32_strlen(event->u.chr.chars); if ( sofar_pos+len >= gl->sofar_max ) { if ( gl->sofar_max == 0 ) gl->sofar = xmalloc((gl->sofar_max = len+10) * sizeof(uint32_t)); else gl->sofar = xrealloc(gl->sofar,(gl->sofar_max = sofar_pos+len+10)*sizeof(uint32_t)); } u32_strcpy(gl->sofar+sofar_pos,event->u.chr.chars); gl->sofar_pos = sofar_pos + len; sel = GListFindPosition(gl,gl->sofar); gl->enduser = GDrawRequestTimer(gl->g.base,GListTypeTime,0,NULL); } if ( loff==0x80000000 && sel>=0 ) { if ( sel>=gl->ltot ) sel = gl->ltot-1; if ( sel<gl->loff ) loff = sel-gl->loff; else if ( sel>=gl->loff+GListLinesInWindow(gl,gl->loff) ) loff = sel-(gl->loff+GListLinesInWindow(gl,gl->loff)-1); } else sel = -1; if ( sel!=-1 ) { int wassel = gl->ti[sel]->selected; refresh = GListAnyOtherSels(gl,sel) || !wassel; GListSelectOne(&gl->g,sel); if ( refresh ) GListSelected(gl,false,sel); } if ( loff!=0x80000000 || xoff!=0x80000000 ) { if ( loff==0x80000000 ) loff = 0; if ( xoff==0x80000000 ) xoff = 0; GListScrollBy(gl,loff,xoff); } if ( refresh ) _ggadget_redraw(g); if ( loff!=0x80000000 || xoff!=0x80000000 || sel!=-1 ) return( true ); return( false ); }
char * GIODecomposeURL (const uint32_t *url, char **host, int *port, char **username, char **password) { uint32_t *pt, *pt2, *upt, *ppt; char *path; char proto[40]; /* ftp://[user[:password]@]ftpserver[:port]/url-path */ *username = NULL; *password = NULL; *port = -1; pt = uc_strstr (url, "://"); if (pt == NULL) { *host = NULL; return (x_u32_to_u8 (u32_force_valid (url))); } cu_strncpy (proto, url, pt - url < sizeof (proto) ? pt - url : sizeof (proto)); pt += 3; pt2 = u32_strchr (pt, '/'); if (pt2 == NULL) { pt2 = pt + u32_strlen (pt); path = xstrdup ("/"); } else { path = x_u32_to_u8 (u32_force_valid (pt2)); } upt = u32_strchr (pt, '@'); if (upt != NULL && upt < pt2) { ppt = u32_strchr (pt, ':'); if (ppt == NULL) *username = x_u32_to_u8 (x_gc_u32_strmbndup (pt, upt - pt)); else { *username = x_u32_to_u8 (x_gc_u32_strmbndup (pt, ppt - pt)); *password = x_u32_to_u8 (x_gc_u32_strmbndup (ppt + 1, upt - ppt - 1)); } pt = upt + 1; } ppt = u32_strchr (pt, ':'); if (ppt != NULL && ppt < pt2) { char *temp = x_u32_to_u8 (x_gc_u32_strmbndup (ppt + 1, pt2 - ppt - 1)); char *end; *port = strtol (temp, &end, 10); if (*end != '\0') *port = -2; free (temp); pt2 = ppt; } *host = x_u32_to_u8 (x_gc_u32_strmbndup (pt, pt2 - pt)); if (*username) *password = GIO_PasswordCache (proto, *host, *username, *password); return (path); }