#include "ctype.h" #include "jctype.h" #include "jstring.h" #define GLOBAL /*#define JSTRING_TYPE_1*/ /* 定義すれば旧仕様. しなければ mbstring系もどき */ GLOBAL size_t mtob(const char *src, size_t n) { /* n文字までのバイト数 */ const unsigned char *s; int c; s = (const unsigned char *)src; while (n && *s != '\0') { if (iskanji(*s)) { if (s[1] == '\0') break; s++; } s++; --n; } return (size_t)(s - src); } GLOBAL size_t btom(const char *src, size_t nbyte) { /* nバイトまでの文字数 */ const unsigned char *s, *e; size_t n; int c; s = (const unsigned char *)src; e = s + nbyte; n = 0; while (*s != '\0' && s != e) { if (iskanji(*s)) { s++; if (*s == '\0' || s == e) break; } s++; n++; } return n; } GLOBAL size_t jstrlen(const char *src) { /* 文字列の文字数 */ const unsigned char *s; size_t n; s = (const unsigned char *)src; n = 0; while (*s != '\0') { if (iskanji(*s)) { s++; if (*s == '\0') break; } s++; n++; } return n; } GLOBAL char *jstradv(const char *src, int n) { /* n文字分ポインタを進める */ const unsigned char *s; s = (const unsigned char *)src; while (n && *s != '\0') { if (iskanji(*s)) { if (s[1] == '\0') break; s++; } s++; --n; } return (char*)s; } GLOBAL int jstrcmp(const char *left, const char *right) { /* 全角を考慮した strcmp */ const unsigned char *lp, *rp; unsigned l,r; lp = (const unsigned char *)left; rp = (const unsigned char *)right; do{ l = *lp++; if (iskanji(l) && *lp) l = (l << 8) | *lp++; r = *rp++; if (iskanji(r) && *rp) r = (r << 8) | *rp++; l -= r; } while (l == 0 && r); return l; } GLOBAL int jstrncmp(const char *left, const char *right, size_t n) { /* n文字までの文字列の比較 */ const unsigned char *lp, *rp; unsigned l,r; l = 0; lp = (const unsigned char *)left; rp = (const unsigned char *)right; if (n) { do{ l = *lp++; if (iskanji(l) && *lp) l = (l << 8) | *lp++; r = *rp++; if (iskanji(r) && *rp) r = (r << 8) | *rp++; l -= r; } while (--n && l == 0 && r); } return l; } GLOBAL int jstricmp(const char *left, const char *right) { /* 全角を考慮した strcmp */ const unsigned char *lp, *rp; unsigned l,r; lp = (const unsigned char *)left; rp = (const unsigned char *)right; do{ l = *lp++; if (iskanji(l) && *lp) { l = (l << 8) | *lp++; l = jtoupper(l); } else { l = toupper(l); } r = *rp++; if (iskanji(r) && *rp) { r = (r << 8) | *rp++; r = jtoupper(r); } else { r = toupper(r); } l -= r; } while (l == 0 && r); return l; } GLOBAL int jstrnicmp(const char *left, const char *right, size_t n) { /* n文字までの文字列の比較 */ const unsigned char *lp, *rp; unsigned l,r; l = 0; lp = (const unsigned char *)left; rp = (const unsigned char *)right; if (n) { do{ l = *lp++; if (iskanji(l) && *lp) { l = (l << 8) | *lp++; l = jtoupper(l); } else { l = toupper(l); } r = *rp++; if (iskanji(r) && *rp) { r = (r << 8) | *rp++; r = jtoupper(r); } else { r = toupper(r); } l -= r; } while (--n && l == 0 && r); } return l; } GLOBAL char *jstrchr(const char *src, unsigned short key) { const unsigned char *s; int c, k; k = key; s = (const unsigned char *)src; if (key < 0x100) { while ((c = *s) != '\0') { if (iskanji(c)) { s++; if (*s == '\0') break; } else if (c == k) { return (char *)s; } s++; } } else { while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == '\0') break; c = (c << 8) | s[1]; if (c == k) return (char *)s; s++; } s++; } } return NULL; } GLOBAL char *jstrrchr(const char *src, unsigned short key) { const unsigned char *s; const unsigned char *t; int c, k; k = key; t = NULL; s = (const unsigned char *)src; if (key < 0x100) { while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == '\0') break; s++; } else if (c == k) { t = s; } s++; } } else { while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == '\0') break; c = (c << 8) | s[1]; if (c == k) t = s; s++; } s++; } } return (char *)t; } GLOBAL char *jstrncpy(char *dst, const char *src, size_t n) { const unsigned char *s; unsigned char *d; int c; d = (unsigned char *)dst; s = (const unsigned char *)src; if (n) { do { c = *s++; if (iskanji(c)) { if (*s == 0) { #if 1 /* n文字以上のときに最後に\0を置かない場合 */ *d = 0; #endif break; } *d++ = c; c = *s++; } *d++ = c; } while (--n); #if 0 /* n文字以上のときに最後に\0を置く場合 */ *d = 0; #endif } return dst; } GLOBAL char *jstrncat(char *dst, const char *src, size_t n) { const unsigned char *s; unsigned char *d; int c; d = (unsigned char *)dst; s = (const unsigned char *)src; if (n) { while (*d) { if (iskanji(*d)) { if (d[1] == 0) break; d++; } d++; } do { c = *s++; if (iskanji(c)) { if (*s == 0) break; *d++ = c; c = *s++; } *d++ = c; } while (--n); *d = 0; } return dst; } GLOBAL char *jstrrev(char *src) { unsigned char *s; unsigned char *e; int c; s = (unsigned char *)src; e = s; while ((c = *e) != '\0') { if (iskanji(c)) { if (e[1] == '\0') break; e[0] = e[1]; e[1] = c; e++; } e++; } *e = '\0'; while (s < --e) { c = *e; *e = *s; *s++ = c; } return src; } GLOBAL char *jstrupr(char *src) { unsigned char *s; int c; s = (unsigned char *)src; while ((c = *s) != 0) { if (iskanji(c)) { if (s[1] == 0) { *s = 0; break; } #ifdef JSTRING_TYPE_1 /* 全角アルファベットも対象にするとき */ c = c << 8 | s[1]; if (0x829a >= c && c >= 0x8281) { /* (jislower(c)) */ c = c - 0x21; /* c = jtoupper(c); */ s[0] = c >> 8; s[1] = c; } #endif s+=2; } else { #ifndef JSTRING_TYPE_1 /* 旧仕様では半角は対象外 */ if ('a' <= c && c <= 'z') { /* (islower(c)) */ s[0] = c - 0x20; /* toupper(c) */ } #endif s++; } } return src; } GLOBAL char *jstrlwr(char *src) { unsigned char *s; int c; s = (unsigned char *)src; while ((c = *s) != 0) { if (iskanji(c)) { if (s[1] == 0) { *s = 0; break; } #ifdef JSTRING_TYPE_1 /* 全角アルファベットも対象にするとき */ c = c << 8 | s[1]; if (0x8279 >= (c) && (c) >= 0x8260) { /* (jisupper(c)) */ c = c+0x21; /*c = jtolower(c);*/ s[0] = c >> 8; s[1] = c; } #endif s += 2; } else { #ifndef JSTRING_TYPE_1 /* 旧仕様では半角は対象外 */ if ('Z' >= c && c >= 'A') { /* (isupper(c)) */ s[0] = c + 0x20; /* tolower(c) */ } #endif s++; } } return src; } GLOBAL char *jstrtok(char *str, const char *tbl) { static char *st = NULL; const char *t; char *s; int c, k; if (str) st = str; s = st; if (s == NULL || tbl == NULL) return (char *)NULL; while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == 0) break; c = (c << 8) | s[1]; t = tbl; for (;;) { k = *t++; if (k == 0) goto RET; if (iskanji(k)) { if (*t == 0) goto RET; k = (k<<8) | *t++; if (c == k) break; } } s += 2; } else { t = tbl; while (c != *t) { if (iskanji(*t)) t++; if (*t == 0) goto RET; t++; } s++; } } st = NULL; return NULL; RET: str = s; while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == 0) break; c = (c << 8) | s[1]; t = tbl; for (;;) { k = *t++; if (k == 0) break; if (iskanji(k)) { if (*t == 0) break; k = (k<<8) | *t++; if (c == k) { *s++ = 0; *s++ = 0; st = s; return str; } } } s += 2; } else { t = tbl; while (*t != '\0') { if (iskanji(*t) && t[1]) { t+=2; continue; } if (c == *t) { *s++ = 0; st = s; return str; } t++; } s++; } } st = NULL; return str; } GLOBAL char *jstrskip(const char *src, const char *tbl) { const unsigned char *s, *t; int c,k; //size_t n; s = (const unsigned char*)src; //n = 0; while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == 0) break; c = (c << 8) | s[1]; t = (const unsigned char *)tbl; for (;;) { k = *t++; if (k == 0) return (char *)s; if (iskanji(k)) { if (*t == 0) return (char *)s; k = (k<<8) | *t++; if (c == k) break; } } s+=2; //n++; } else { t = (const unsigned char *)tbl; while (c != *t) { if (iskanji(*t)) t++; if (*t == 0) return (char *)s; t++; } s++; //n++; } } #if 1 /* VC/LSIC互換 */ return (char *)s; #else /* Borland-C互換/watcom-c */ return NULL; #endif } GLOBAL size_t jstrspn(const char *src, const char *tbl) { // ※とりあえずバイト数を返す版だが、文字数の場合もあるかも? const unsigned char *s, *t; int c,k; size_t n; s = (const unsigned char*)src; n = 0; while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == 0) break; c = (c << 8) | s[1]; t = (const unsigned char *)tbl; for (;;) { k = *t++; if (k == 0) goto RET; if (iskanji(k)) { if (*t == 0) goto RET; k = (k<<8) | *t++; if (c == k) break; } } s+=2; n++; } else { t = (const unsigned char *)tbl; while (c != *t) { if (iskanji(*t)) t++; if (*t == 0) goto RET; t++; } s++; n++; } } RET: #ifdef JSTRING_TYPE_1 /* 旧仕様なら文字数 */ return n; #else /* mbstring系ならバイト数 */ return (size_t)(s - src); #endif } GLOBAL char *jstrmatch(const char *src, const char *tbl) { const unsigned char *s, *t; int c,k; //size_t n; //n = 0; s = (const unsigned char*)src; while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == 0) break; c = (c << 8) | s[1]; t = (const unsigned char *)tbl; for (;;) { k = *t++; if (k == 0) break; if (iskanji(k)) { if (*t == 0) break; k = (k<<8) | *t++; if (c == k) { return (char *)s; } } } s += 2; //n++; } else { t = (const unsigned char *)tbl; while (*t != '\0') { if (iskanji(*t) && t[1]) { t+=2; continue; } if (c == *t) { return (char *)s; } t++; } s++; //n++; } } return NULL; } GLOBAL size_t jstrcspn(const char *src, const char *tbl) { // ※とりあえずバイト数を返す版だが、文字数の場合もあるかも? const unsigned char *s, *t; int c,k; size_t n; s = (const unsigned char*)src; n = 0; while ((c = *s) != '\0') { if (iskanji(c)) { if (s[1] == 0) break; c = (c << 8) | s[1]; t = (const unsigned char *)tbl; for (;;) { k = *t++; if (k == 0) break; if (iskanji(k)) { if (*t == 0) break; k = (k<<8) | *t++; if (c == k) { goto RET; } } } s += 2; n++; } else { t = (const unsigned char *)tbl; while (*t != '\0') { if (iskanji(*t) && t[1]) { t+=2; continue; } if (c == *t) { goto RET; } t++; } s++; n++; } } RET: #ifdef JSTRING_TYPE_1 /* 旧仕様なら文字数 */ return n; #else /* mbstring系ならバイト数 */ return (size_t)(s - src); #endif } GLOBAL char *jstrset(char *dst, unsigned short c) { char *d, *e; char a,b; d = dst; e = d; while (*e != '\0') e++; if (c < 0x100) { while (d != e) *d++ = c; } else { a = c >> 8; b = c; c = (e - d) & 1; e -= c; /* 偶数バイトにする */ while (d != e) { *d++ = a; *d++ = b; } if (c) /* 端数には 空白を詰める */ *d++ = ' '; *d = 0; } return dst; } GLOBAL char *jstrnset(char *dst, unsigned short c, size_t n) { char *d, *e; char a,b; size_t l; d = (char *)dst; e = d; #if 1 /* n が文字数のとき */ l = 0; while (*e != '\0' && l < n) { if (iskanji(*e) && e[1]) e++; e++; l++; } #else /* n がバイト数のとき */ d += n; while (*e != '\0' && e != d) e++; l = (size_t)((char*)e - (char*)dst); d = (char *)dst; #endif if (c < 0x100) { while (d != e) *d++ = c; #if 1 /* n 以上あるときは最後に \0 を置かない場合 */ if (l < n) #endif *d = 0; } else { a = c >> 8; b = c; c = (e - d) & 1; e -= c; /* 偶数バイトにする */ while (d != e) { *d++ = a; *d++ = b; } if (c) /* 端数には 空白を詰める */ *d++ = ' '; #if 1 /* n 以上あるときは最後に \0 を置かない場合 */ if (l < n) #endif *d = 0; } return dst; } GLOBAL char *jstrstr(const char *src, const char *ptn) { /* src : 検索される文字列 */ /* ptn : 探す文字列 */ const unsigned char *s, *t, *p, *e; unsigned k,c; s = (const unsigned char*)src; p = (const unsigned char*)ptn; k = *p++; if (k == 0) return (char *)s; e = p; while (*e) e++; if (iskanji(k)) { if (*p == 0) return (char *)s; k = (k << 8) | *p++; while ((c = *s) != 0) { if (iskanji(c) && s[1]) { c = (c << 8) | s[1]; s += 2; if (c == k) { const unsigned char *l, *r; l = (const unsigned char *)s; r = (const unsigned char *)p; c = 0; while (r != e) { c = *l++; if (c == 0) return NULL; c = c - *r++; if (c != 0) break; } if (c == 0) return (char *)s-2; } } else { s++; } } } else { while ((c = *s) != 0) { if (iskanji(c) && s[1]) { s += 2; } else { ++s; if (k == c) { const unsigned char *l, *r; l = (const unsigned char *)s; r = (const unsigned char *)p; c = 0; while (r != e) { c = *l++; if (c == 0) return NULL; c = c - *r++; if (c != 0) break; } if (c == 0) return (char *)(s-1); } } } } return NULL; }