uint32_t LLCALL_C io_hash_path(char const *path, char const **out_end) { if (path == NULL) { if (out_end) *out_end = NULL; return 0; } uint32_t cp = 0; uint32_t cp2 = 0; uint32_t cp3 = 0; uint32_t hash = 0; char const *iter = next_codepoint(path, cp); while (cp != 0) { cp2 = UTF8_TOUPPER(cp); cp3 = cp != '\\' ? cp2 : '/'; hash = ROTATE_LEFT(hash, 7) + cp3; iter = next_codepoint(iter, cp); } if (out_end) { *out_end = iter + 1; } return hash; }
void gui::measure_string(gui::bitmap_font_t const *font, char const *str, size_t *out_w, size_t *out_h) { if (str != NULL) { size_t l = 0; // length, in characters size_t w = 0; // total width, in pixels size_t h = 0; // total height, in pixels uint32_t c = 0; // current UTF-8 codepoint, 0xFFFFFFFFU = invalid uint32_t p = 0; // previous UTF-8 codepoint, 0xFFFFFFFFU = invalid uint32_t const m = uint32_t(font->BucketCount - 1); char const *n = next_codepoint(str, c); while (c != 0) { uint32_t bucket = uint32_hash(c) & m; uint32_t const *table = font->GTable[bucket]; uint32_t const count = font->GTable[bucket][FONT_SIZE_INDEX]; for (size_t i = FONT_CODEPOINT_OFFSET; i < FONT_CODEPOINT_OFFSET + count; ++i) { if (table[i] == c) { size_t gi = table[i]; // the index in into font->Glyphs. w += advance_x(font, p, c, font->Glyphs[gi].AdvanceX); break; } } if (c == '\n') h += font->LineHeight; p = c; n = next_codepoint(n, c); l++; } if (l > 0) h += font->LineHeight; if (out_w)*out_w = w; if (out_h)*out_h = h; } else { if (out_w) *out_w = 0; if (out_h) *out_h = 0; } }
/* hash a string of the specified length. The string does not need to be null terminated hash alghorithm changed to FNV1 by [email protected] (Simo Sorce). see http://www.isthe.com/chongo/tech/comp/fnv/index.html for a discussion on Fowler / Noll / Vo (FNV) Hash by one of it's authors */ uint32_t pvfs_name_hash(const char *key, size_t length) { const uint32_t fnv1_prime = 0x01000193; const uint32_t fnv1_init = 0xa6b93095; uint32_t value = fnv1_init; while (*key && length--) { size_t c_size; codepoint_t c = next_codepoint(key, &c_size); c = toupper_m(c); value *= fnv1_prime; value ^= (uint32_t)c; key += c_size; } return value; }
/* See if a filename is a legal long filename. A filename ending in a '.' is not legal unless it's "." or "..". JRA. */ static bool is_legal_name(struct pvfs_mangle_context *ctx, const char *name) { while (*name) { size_t c_size; codepoint_t c = next_codepoint(name, &c_size); if (c == INVALID_CODEPOINT) { return false; } /* all high chars are OK */ if (c >= 128) { name += c_size; continue; } if (FLAG_CHECK(c, FLAG_ILLEGAL)) { return false; } name += c_size; } return true; }
/** String replace. NOTE: oldc and newc must be 7 bit characters **/ void string_replace( char *s, char oldc, char newc ) { char *p; /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ for (p = s; *p; p++) { if (*p & 0x80) /* mb string - slow path. */ break; if (*p == oldc) { *p = newc; } } if (!*p) return; /* Slow (mb) path. */ #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS /* With compose characters we must restart from the beginning. JRA. */ p = s; #endif while (*p) { size_t c_size; next_codepoint(p, &c_size); if (c_size == 1) { if (*p == oldc) { *p = newc; } } p += c_size; } }
/* Will decode an array of utf-8-encoded bytes, buff, into an array of Unicode * code points, and return a pointer to the array. Requires the number of bytes * in buff, passed as in_len. Writes the length of the buffer returned into * the address of out_len. */ UNICHAR * utf8_decode_buffer(const char * buff, size_t in_len, size_t *out_len) { size_t bytes_left = in_len; UNICHAR target; UNICHAR * temp; UNICHAR * out_buffer; size_t written = 0; #ifdef UNICODEC_DEBUG fprintf(stderr, "in utf8_decode_buffer(%p, %lu, %p):\n", buff, in_len, out_len); #endif temp = malloc(sizeof(UNICHAR) * in_len); while(bytes_left > 0) { #ifdef UNICODEC_DEBUG fprintf(stderr, " bytes_left: %lu\n", bytes_left); #endif target = next_codepoint(&(buff[in_len-bytes_left]), &bytes_left); #ifdef UNICODEC_DEBUG fprintf(stderr, " decoded: %u; bytes_left: %lu\n", target, bytes_left); #endif temp[written] = target; ++written; } out_buffer = malloc(sizeof(UNICHAR) * written); for(size_t n = 0; n < written; ++n) out_buffer[n] = temp[n]; free(temp); *out_len = written; return(out_buffer); }
bool set_conn_connectpath(connection_struct *conn, const char *connectpath) { char *destname; char *d; const char *s = connectpath; bool start_of_name_component = true; if (connectpath == NULL || connectpath[0] == '\0') { return false; } /* Allocate for strlen + '\0' + possible leading '/' */ destname = SMB_MALLOC(strlen(connectpath) + 2); if (!destname) { return false; } d = destname; *d++ = '/'; /* Always start with root. */ while (*s) { if (*s == '/') { /* Eat multiple '/' */ while (*s == '/') { s++; } if ((d > destname + 1) && (*s != '\0')) { *d++ = '/'; } start_of_name_component = True; continue; } if (start_of_name_component) { if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { /* Uh oh - "/../" or "/..\0" ! */ /* Go past the ../ or .. */ if (s[2] == '/') { s += 3; } else { s += 2; /* Go past the .. */ } /* If we just added a '/' - delete it */ if ((d > destname) && (*(d-1) == '/')) { *(d-1) = '\0'; d--; } /* Are we at the start ? Can't go back further if so. */ if (d <= destname) { *d++ = '/'; /* Can't delete root */ continue; } /* Go back one level... */ /* Decrement d first as d points to the *next* char to write into. */ for (d--; d > destname; d--) { if (*d == '/') { break; } } /* We're still at the start of a name component, just the previous one. */ continue; } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) { /* Component of pathname can't be "." only - skip the '.' . */ if (s[1] == '/') { s += 2; } else { s++; } continue; } } if (!(*s & 0x80)) { *d++ = *s++; } else { size_t siz; /* Get the size of the next MB character. */ next_codepoint(s,&siz); switch(siz) { case 5: *d++ = *s++; /*fall through*/ case 4: *d++ = *s++; /*fall through*/ case 3: *d++ = *s++; /*fall through*/ case 2: *d++ = *s++; /*fall through*/ case 1: *d++ = *s++; break; default: break; } } start_of_name_component = false; } *d = '\0'; /* And must not end in '/' */ if (d > destname + 1 && (*(d-1) == '/')) { *(d-1) = '\0'; } DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n", lp_servicename(SNUM(conn)), destname )); string_set(&conn->connectpath, destname); SAFE_FREE(destname); return true; }