mirror of https://github.com/flysand7/ciabatta.git
				
				
				
			uchar.h
This commit is contained in:
		
							parent
							
								
									337e6734a7
								
							
						
					
					
						commit
						673a363d4b
					
				
							
								
								
									
										136
									
								
								src/code/uchar.c
								
								
								
								
							
							
						
						
									
										136
									
								
								src/code/uchar.c
								
								
								
								
							| 
						 | 
					@ -9,6 +9,7 @@ size_t mbrtoc16(
 | 
				
			||||||
    mbstate_t  *restrict ps
 | 
					    mbstate_t  *restrict ps
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    if(s == NULL) {
 | 
					    if(s == NULL) {
 | 
				
			||||||
 | 
					        *ps = (mbstate_t) {0};
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    size_t nbytes;
 | 
					    size_t nbytes;
 | 
				
			||||||
| 
						 | 
					@ -49,8 +50,8 @@ size_t mbrtoc16(
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            cp -= 0x10000;
 | 
					            cp -= 0x10000;
 | 
				
			||||||
            parsed_char = 0xd800 | (cp & 0x3ff);
 | 
					            parsed_char = 0xd800 | (cp >> 10);
 | 
				
			||||||
            next_char   = 0xdc00 | (cp >> 10);
 | 
					            next_char   = 0xdc00 | (cp & 0x3ff);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
| 
						 | 
					@ -73,17 +74,142 @@ size_t c16rtomb(
 | 
				
			||||||
    char *restrict      s,
 | 
					    char *restrict      s,
 | 
				
			||||||
    char16_t            c16,
 | 
					    char16_t            c16,
 | 
				
			||||||
    mbstate_t *restrict ps
 | 
					    mbstate_t *restrict ps
 | 
				
			||||||
);
 | 
					) {
 | 
				
			||||||
 | 
					    if(*s == NULL) {
 | 
				
			||||||
 | 
					        *ps = (mbstate_t) {0};
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    unsigned cp;
 | 
				
			||||||
 | 
					    // High surrogate (save)
 | 
				
			||||||
 | 
					    if(0xd800 <= c16 && c16 < 0xdc00) {
 | 
				
			||||||
 | 
					        ps->leftover = c16;
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Low surrogate (parse)
 | 
				
			||||||
 | 
					    else if(0xdc00 <= c16 && c16 < 0xe000) {
 | 
				
			||||||
 | 
					        if(ps->leftover == 0) goto encoding_error;
 | 
				
			||||||
 | 
					        cp = ((ps->leftover & 0x3ff) << 10) | (c16 & 0x3ff);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // Other char
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        cp = c16;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    size_t nbytes = 4;
 | 
				
			||||||
 | 
					    if(cp < 0x10000) nbytes = 3;
 | 
				
			||||||
 | 
					    if(cp < 0x800)   nbytes = 2;
 | 
				
			||||||
 | 
					    if(cp < 0x80)    nbytes = 1;
 | 
				
			||||||
 | 
					    switch(nbytes) {
 | 
				
			||||||
 | 
					        case 1: {
 | 
				
			||||||
 | 
					            s[0] = cp;
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					        case 2: {
 | 
				
			||||||
 | 
					            s[0] = 0xc0 | (cp >> 6);
 | 
				
			||||||
 | 
					            s[1] = 0x80 | ((cp >> 0)  & 0x3f);
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					        case 3: {
 | 
				
			||||||
 | 
					            s[0] = 0xe0 | (cp >> 12);
 | 
				
			||||||
 | 
					            s[1] = 0x80 | ((cp >> 6)  & 0x3f);
 | 
				
			||||||
 | 
					            s[2] = 0x80 | ((cp >> 0)  & 0x3f);
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					        case 4: {
 | 
				
			||||||
 | 
					            s[0] = 0xf0 | (cp >> 18);
 | 
				
			||||||
 | 
					            s[1] = 0x80 | ((cp >> 12) & 0x3f);
 | 
				
			||||||
 | 
					            s[2] = 0x80 | ((cp >> 6)  & 0x3f);
 | 
				
			||||||
 | 
					            s[3] = 0x80 | ((cp >> 0)  & 0x3f);
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return nbytes;
 | 
				
			||||||
 | 
					encoding_error:
 | 
				
			||||||
 | 
					    errno = EILSEQ;
 | 
				
			||||||
 | 
					    return (size_t)(-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t mbrtoc32(
 | 
					size_t mbrtoc32(
 | 
				
			||||||
    char32_t   *restrict pc32,
 | 
					    char32_t   *restrict pc32,
 | 
				
			||||||
    char const *restrict s,
 | 
					    char const *restrict s,
 | 
				
			||||||
    size_t               n,
 | 
					    size_t               n,
 | 
				
			||||||
    mbstate_t  *restrict ps
 | 
					    mbstate_t  *restrict ps
 | 
				
			||||||
);
 | 
					) {
 | 
				
			||||||
 | 
					    if(s == NULL) {
 | 
				
			||||||
 | 
					        *ps = (mbstate_t) {0};
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    size_t nbytes;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // Decode the first byte of UTF-8 sequence
 | 
				
			||||||
 | 
					    unsigned byte0 = *s;
 | 
				
			||||||
 | 
					    if     (0x00 <= byte0 && byte0 < 0x80) nbytes = 1;
 | 
				
			||||||
 | 
					    else if(0xc0 <= byte0 && byte0 < 0xe0) nbytes = 2;
 | 
				
			||||||
 | 
					    else if(0xe0 <= byte0 && byte0 < 0xf0) nbytes = 3;
 | 
				
			||||||
 | 
					    else if(0xf0 <= byte0 && byte0 < 0xf8) nbytes = 4;
 | 
				
			||||||
 | 
					    else goto encoding_error;
 | 
				
			||||||
 | 
					    unsigned nbytesreq = nbytes;
 | 
				
			||||||
 | 
					    if(n < nbytesreq) {
 | 
				
			||||||
 | 
					        return (size_t)(-2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    char32_t cp = byte0;
 | 
				
			||||||
 | 
					    switch(nbytesreq) {
 | 
				
			||||||
 | 
					        case 2: cp &= 0x1f; break;
 | 
				
			||||||
 | 
					        case 3: cp &= 0x0f; break;
 | 
				
			||||||
 | 
					        case 4: cp &= 0x07; break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    while(--nbytesreq)
 | 
				
			||||||
 | 
					        cp |= (cp << 6) | ((*++s) & 0x3f);
 | 
				
			||||||
 | 
					    if(0xdc00 <= cp && cp <= 0xe000)
 | 
				
			||||||
 | 
					        goto encoding_error;
 | 
				
			||||||
 | 
					    // Overloing seqs
 | 
				
			||||||
 | 
					    if(cp < 0x80    && nbytes > 1) goto encoding_error;
 | 
				
			||||||
 | 
					    if(cp < 0x800   && nbytes > 2) goto encoding_error;
 | 
				
			||||||
 | 
					    if(cp < 0x10000 && nbytes > 3) goto encoding_error;
 | 
				
			||||||
 | 
					    if(cp > 0x10ffff) goto encoding_error;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if(pc32 != NULL) *pc32 = cp;
 | 
				
			||||||
 | 
					    if(cp == 0)
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        return nbytes;
 | 
				
			||||||
 | 
					encoding_error:
 | 
				
			||||||
 | 
					    errno = EILSEQ;
 | 
				
			||||||
 | 
					    return (size_t)(-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t c32rtomb(
 | 
					size_t c32rtomb(
 | 
				
			||||||
    char *restrict      s,
 | 
					    char *restrict      s,
 | 
				
			||||||
    char32_t            c32,
 | 
					    char32_t            c32,
 | 
				
			||||||
    mbstate_t *restrict ps
 | 
					    mbstate_t *restrict ps
 | 
				
			||||||
);
 | 
					) {
 | 
				
			||||||
 | 
					    if(*s == NULL) {
 | 
				
			||||||
 | 
					        *ps = (mbstate_t) {0};
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    unsigned cp = c32;
 | 
				
			||||||
 | 
					    if(cp >= 0x10ffff) goto encoding_error;
 | 
				
			||||||
 | 
					    size_t nbytes = 4;
 | 
				
			||||||
 | 
					    if(cp < 0x10000) nbytes = 3;
 | 
				
			||||||
 | 
					    if(cp < 0x800)   nbytes = 2;
 | 
				
			||||||
 | 
					    if(cp < 0x80)    nbytes = 1;
 | 
				
			||||||
 | 
					    switch(nbytes) {
 | 
				
			||||||
 | 
					        case 1: {
 | 
				
			||||||
 | 
					            s[0] = cp;
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					        case 2: {
 | 
				
			||||||
 | 
					            s[0] = 0xc0 | (cp >> 6);
 | 
				
			||||||
 | 
					            s[1] = 0x80 | ((cp >> 0)  & 0x3f);
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					        case 3: {
 | 
				
			||||||
 | 
					            s[0] = 0xe0 | (cp >> 12);
 | 
				
			||||||
 | 
					            s[1] = 0x80 | ((cp >> 6)  & 0x3f);
 | 
				
			||||||
 | 
					            s[2] = 0x80 | ((cp >> 0)  & 0x3f);
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					        case 4: {
 | 
				
			||||||
 | 
					            s[0] = 0xf0 | (cp >> 18);
 | 
				
			||||||
 | 
					            s[1] = 0x80 | ((cp >> 12) & 0x3f);
 | 
				
			||||||
 | 
					            s[2] = 0x80 | ((cp >> 6)  & 0x3f);
 | 
				
			||||||
 | 
					            s[3] = 0x80 | ((cp >> 0)  & 0x3f);
 | 
				
			||||||
 | 
					        } break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return nbytes;
 | 
				
			||||||
 | 
					encoding_error:
 | 
				
			||||||
 | 
					    errno = EILSEQ;
 | 
				
			||||||
 | 
					    return (size_t)(-1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue