CHNLIB_UIPArray *AI_Think_SlideLookUpWordByHistory(CHNLIB_String *input)\r
{\r
//入力文字列と履歴文字列を照らし合わせ、単語の候補を抜き出す。\r
+ //候補単語は、新たに確保されたUIPArrayに格納され、そのArrayへのポインタを返す。\r
+ //data32=入力文字列中に含まれる候補単語の数。\r
+ //pointer=候補単語を示すCHNLIB_String.\r
+ //[UTF-8]\r
CHNLIB_UIPArray *candidatewordlist;\r
int i, i_max;\r
int j, j_max;\r
int k, k_max;\r
+ const char *cstr_input, *cstrp_input;\r
+ const char *cstr_history, *cstrp_history;\r
int candidatelength, templength;\r
- const char *cstr_input, *cstr_history;\r
+ int cstrp_input_length;\r
\r
candidatewordlist = CHNLIB_UIPArray_Initialize();\r
- \r
i_max = CHNLIB_UIPArray_GetNumberOfDatas(WorkingSet.InputHistory);\r
\r
cstr_input = CHNLIB_String_GetReferencePointerOfCString(input);\r
- k_max = CHNLIB_CString_GetLength(cstr_input);\r
-\r
+ k_max = CHNLIB_UTF8_GetStringLengthByCharacter(cstr_input);\r
+ cstrp_input = cstr_input;\r
+ \r
for(k = 0; k < k_max; k++){\r
- //**UTF-8 only\r
- //UTF-8のマルチバイト部分でないことを確認\r
- if(CHNLIB_UTF8_GetCharacterType(cstr_input[k]) != 0){\r
- //****\r
- candidatelength = 0;\r
- for(i = 0; i < i_max; i++){\r
- cstr_history = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(WorkingSet.InputHistory, i));\r
- j_max = CHNLIB_CString_GetLength(cstr_history);\r
- for(j = 0; j < j_max; j++){\r
- templength = CHNLIB_CString_CompareString_LeftHand(&cstr_history[j], &cstr_input[k]);\r
- if(templength > candidatelength && templength != (k_max - k)){\r
- //前方一致の長さが、\r
- //これまで見つかった単語よりも長く、かつ\r
- //入力文字列の検索部分の全長ではない場合、\r
- //単語の候補とする。\r
- candidatelength = templength;\r
- }\r
+ //input character loop\r
+ candidatelength = 0;\r
+ cstrp_input_length = CHNLIB_UTF8_GetStringLengthByCharacter(cstrp_input);\r
+ for(i = 0; i < i_max; i++){\r
+ //history entry loop\r
+ cstr_history = CHNLIB_String_GetReferencePointerOfCString(CHNLIB_UIPArray_GetPointerByIndex(WorkingSet.InputHistory, i));\r
+ j_max = CHNLIB_UTF8_GetStringLengthByCharacter(cstr_history);\r
+ cstrp_history = cstr_history;\r
+ \r
+ for(j = 0; j < j_max; j++){\r
+ //history character loop\r
+ templength = CHNLIB_UTF8_CompareString_LeftHand(cstrp_history, cstrp_input);\r
+ if(templength > candidatelength && templength != cstrp_input_length){\r
+ //前方一致の長さが、これまで見つかった単語よりも長く、かつ入力文字列の検索部分の全長ではない場合、\r
+ //単語の候補とする。\r
+ candidatelength = templength;\r
}\r
+ CHNLIB_UTF8_GetNextUnicodeOfCharacter(cstrp_history, &cstrp_history);\r
}\r
- if(candidatelength > 0){\r
- //AI_Memory_AddRootWordData(CHNLIB_String_ExtractByLength(input, k, candidatelength));\r
- CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(&candidatewordlist, 0, CHNLIB_String_ExtractByLength(input, k, candidatelength), &AI_Memory_AddRootWordData_IsDuplicated);\r
- }\r
}\r
+ if(candidatelength > 0){\r
+ CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(&candidatewordlist, 0, CHNLIB_String_ExtractByLength(input, CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(cstr_input, 0, k - 1), CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(cstrp_input, 0, candidatelength - 1)), &AI_Memory_AddRootWordData_IsDuplicated);\r
+ }\r
+ CHNLIB_UTF8_GetNextUnicodeOfCharacter(cstrp_input, &cstrp_input);\r
}\r
\r
//各候補単語が入力文字列にいくつ含まれているかをdata32に保存する。\r
//Define library values\r
//\r
\r
-#define CHNLIB_STRUCTURE_SIGNATURE ((uint)0x43484E4C) //"CHNL"\r
+#define CHNLIB_STRUCTURE_SIGNATURE ((uint)0x4C4E4843) //"CHNL"(Little Endian)\r
\r
#define False 0\r
#define True 1\r
int CHNLIB_CString_CompareString(const char s[], const char search[]);\r
int CHNLIB_CString_CompareString_Strict(const char s[], const char search[]);\r
int CHNLIB_CString_CompareString_LeftHand(const char s[], const char search[]);\r
-uint CHNLIB_CString_GetCountOfContain(const char s[], const char search[]);\r
//@chnlib02.c\r
int CHNLIB_String_Search_UIPArrayStringLocation(const CHNLIB_String *s, int s_start, const CHNLIB_UIPArray *list, int *location);\r
int CHNLIB_UIPArray_GetSeparatedStringByUIPArray(CHNLIB_UIPArray **separated, const CHNLIB_UIPArray *list, const CHNLIB_String *s);\r
\r
//@chnlib05.c\r
int CHNLIB_UTF8_GetCharacterType(char c);\r
+int CHNLIB_UTF8_GetStringLengthByCharacter(const char s[]);\r
+uint CHNLIB_UTF8_GetNextUnicodeOfCharacter(const char s[], const char **next);\r
+int CHNLIB_UTF8_CompareString(const char s[], const char search[]);\r
+int CHNLIB_UTF8_CompareString_LeftHand(const char s[], const char search[]);\r
+int CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(const char s[], int start, int end);\r
+uint CHNLIB_UTF8_GetCountOfContain(const char s[], const char search[]);\r
\r
#endif\r
//\r
\r
//\r
+//Define static values\r
+//\r
+char *CHNLIB_String_Intenal_NullCString = "";\r
+\r
+//\r
//Declare internal functions\r
//\r
\r
void CHNLIB_String_Free(CHNLIB_String *strtag)\r
{\r
//strtagを解放する。\r
- \r
if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
return;\r
}\r
const char *CHNLIB_String_GetReferencePointerOfCString(const CHNLIB_String *strtag)\r
{\r
//strtagが格納している文字列へのポインタを返す。\r
- //strtag==Invalidの場合、NULLを返す。\r
+ //strtag->str==NULLの場合、constな空文字へのポインタを返す。\r
if(CHNLIB_StructureHeader_GetTypeID(strtag) != CHNLIB_STRUCT_ID_String){\r
return NULL;\r
}\r
\r
+ if(strtag->str == NULL){\r
+ return CHNLIB_String_Intenal_NullCString;\r
+ }\r
+ \r
return (const char *)strtag->str;\r
}\r
\r
\r
uint CHNLIB_String_GetCountOfContain(const CHNLIB_String *s, const CHNLIB_String *search)\r
{\r
- return CHNLIB_CString_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(search));\r
+ return CHNLIB_UTF8_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(search));\r
}\r
\r
//\r
\r
return i;\r
}\r
-\r
-uint CHNLIB_CString_GetCountOfContain(const char s[], const char search[])\r
-{\r
- //[Not implemented]\r
- uint count;\r
- int i;\r
- \r
- if(s == NULL || search == NULL){\r
- CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
- return 0;\r
- }\r
- \r
- count = 0;\r
- for(i = 0; s[i] != '\0'; i++){\r
- if(CHNLIB_CString_CompareString(&s[i], search)){\r
- count++;\r
- }\r
- }\r
- return count;\r
-}\r
\r
//\r
//Internal functions\r
return 0;\r
}\r
\r
-int CHNLIB_UIPArray_GetSeparatedUTF8Character(CHNLIB_UIPArray **separated, const CHNLIB_String *s){\r
+int CHNLIB_UIPArray_GetSeparatedUTF8Character(CHNLIB_UIPArray **separated, const CHNLIB_String *s)\r
+{\r
//文字列sを、UTF-8の一文字ごとに分割し、その文字のUnicodeをdata32、その一文字に該当するStringをpointerに格納し、separatedに追加する形で返す。\r
//不完全なUTF-8文字列は無視される。\r
- const char *refstr;\r
- int i, i_max, type;\r
- int phase, start;\r
- uint unicode;\r
+ //[UTF-8]\r
+ const char *p, *q, *p_base;\r
+ uint u;\r
\r
if(separated == NULL || CHNLIB_StructureHeader_GetTypeID(s) != CHNLIB_STRUCT_ID_String){\r
return 1;\r
}\r
\r
- refstr = CHNLIB_String_GetReferencePointerOfCString(s);\r
- i_max = CHNLIB_String_GetLength(s);\r
+ p_base = CHNLIB_String_GetReferencePointerOfCString(s);;\r
+ p = p_base;\r
\r
- phase = 0;\r
- unicode = 0;\r
- for(i = 0; i < i_max; i++){\r
- type = CHNLIB_UTF8_GetCharacterType(refstr[i]);\r
- switch (type) {\r
- case 1:\r
- CHNLIB_UIPArray_AppendLast(separated, refstr[i], CHNLIB_String_ExtractByLength(s, i, 1));\r
- phase = 0;\r
- unicode = 0;\r
- break;\r
- \r
- case 0:\r
- if(phase > 0){\r
- unicode <<= 6;\r
- unicode |= (refstr[i] & 0x3f);\r
- phase--;\r
- if(phase == 0){\r
- //一文字完成\r
- CHNLIB_UIPArray_AppendLast(separated, unicode, CHNLIB_String_ExtractByLength(s, start, i - start + 1));\r
- }\r
- }\r
- break;\r
- \r
- case 2:\r
- case 3:\r
- case 4:\r
- start = i;\r
- unicode = (refstr[i] << (type + 1)) >> (type + 1);\r
- phase = type - 1;\r
- break;\r
+ for(;;){\r
+ u = CHNLIB_UTF8_GetNextUnicodeOfCharacter(p, &q);\r
+ if(u == 0){\r
+ //終端文字\r
+ break;\r
}\r
+ CHNLIB_UIPArray_AppendLast(separated, u, CHNLIB_String_ExtractByLength(s, (int)(p - p_base), (int)(q - p)));\r
+ p = q;\r
}\r
\r
return 0;\r
}\r
\r
-\r
CHNLIB_String *CHNLIB_ReadLine(FILE *fp)\r
{\r
char s[CHNLIB_MAX_STRING_LENGTH];\r
int CHNLIB_UTF8_GetCharacterType(char c)\r
{\r
//UTF-8文字列中の1バイトcが、UTF-8文字列中でどのような役割を持つのかを返す。\r
+ //0:マルチバイト文字の後続バイト\r
+ //1:1バイト文字\r
+ //2以上の数値n:nバイト文字の最初のバイト。後続のn個のマルチバイト後続バイトと組み合わせて一つの文字を示す。\r
+ //判断不能な場合は-1を返す。\r
+ //[UTF-8]\r
if(((c >> 6) & 3) == 2){\r
//マルチバイト後続バイト\r
//10xxxxxx\r
return 4;\r
}\r
\r
+ return -1;\r
+}\r
+\r
+int CHNLIB_UTF8_GetStringLengthByCharacter(const char s[])\r
+{\r
+ //sをUTF-8文字列として解釈し、文字としては何文字で構成された文字列かを返す。\r
+ //無効な(マルチバイトの一部が欠けているような)文字はカウントしない。\r
+ //[UTF-8]\r
+ int i, mbsize, n;\r
+ int count;\r
+ \r
+ if(s == NULL){\r
+ return 0;\r
+ }\r
+ \r
+ count = 0;\r
+ mbsize = 0;\r
+ for(i = 0; s[i] != '\0'; i++){\r
+ n = CHNLIB_UTF8_GetCharacterType(s[i]);\r
+ switch(n){\r
+ case -1:\r
+ //無効なバイト\r
+ mbsize = 0;\r
+ break;\r
+ case 0:\r
+ //マルチバイト後続バイト\r
+ if(mbsize > 0){\r
+ mbsize--;\r
+ if(mbsize == 0){\r
+ count++;\r
+ }\r
+ }\r
+ break;\r
+ case 1:\r
+ //1バイト文字\r
+ count++;\r
+ if(mbsize > 0){\r
+ mbsize = 0;\r
+ }\r
+ break;\r
+ default:\r
+ //nバイト文字の最初のバイト\r
+ mbsize = n - 1;\r
+ break;\r
+ }\r
+ }\r
+ return count;\r
+}\r
+\r
+uint CHNLIB_UTF8_GetNextUnicodeOfCharacter(const char s[], const char **next)\r
+{\r
+ //sをUTF-8文字列として解釈し、その文字列の最初の文字のUnicodeを返す。\r
+ //また、nextがNULLでないとき、*nextに、この文字列中で次の文字にあたる部分へのポインタを格納する。\r
+ //s==NULLの時、*nextの値は変更されない。\r
+ //次の文字が存在しない場合は、*nextはs中の終端文字へのポインタとなる。また、戻り値は0となる。\r
+ //無効な(マルチバイトの一部が欠けているような)文字は無視する。\r
+ //[UTF-8]\r
+ int i, n, mbsize;\r
+ uint unicode;\r
+ \r
+ if(s == NULL){\r
+ return 0;\r
+ }\r
+ \r
+ unicode = 0;\r
+ for(i = 0; s[i] != '\0'; i++){\r
+ n = CHNLIB_UTF8_GetCharacterType(s[i]);\r
+ switch(n){\r
+ case -1:\r
+ //無効なバイト\r
+ mbsize = 0;\r
+ break;\r
+ case 0:\r
+ //マルチバイト後続バイト\r
+ if(mbsize > 0){\r
+ mbsize--;\r
+ unicode <<= 6;\r
+ unicode |= (0x3f & s[i]);\r
+ if(mbsize == 0){\r
+ return unicode;\r
+ }\r
+ }\r
+ break;\r
+ case 1:\r
+ //1バイト文字\r
+ if(next != NULL){\r
+ *next = (char *)(s + 1);\r
+ }\r
+ return s[i];\r
+ default:\r
+ //nバイト文字の最初のバイト\r
+ unicode = (((s[i]) << (n + 1)) >> n + 1);\r
+ mbsize = n - 1;\r
+ if(next != NULL){\r
+ *next = (char *)(s + n);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ if(next != NULL){\r
+ *next = &s[i];\r
+ }\r
return 0;\r
}\r
\r
+int CHNLIB_UTF8_CompareString(const char s[], const char search[])\r
+{\r
+ //s,searchをUTF-8文字列として解釈し、s[]の先頭からsearch[]と比較し、searchの終端まで一致したらTrue, 一致しなかったらFalseを返す。\r
+ //終端文字は比較せず、search[]に含まれる文字(終端文字除く)がすべて入っていれば一致とみなす。\r
+ //ただし、searchの先頭文字が終端文字、つまり空文字列だった場合は、常にFalseを返す。\r
+ //[UTF-8]\r
+ int i, i_max;\r
+ \r
+ if(s == NULL || search == NULL){\r
+ CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
+ return False;\r
+ }\r
+ if(search[0] == '\0'){\r
+ //空文字はいかなる文字列とも一致しない。\r
+ return False;\r
+ }\r
+ \r
+ i_max = CHNLIB_UTF8_GetStringLengthByCharacter(search);\r
+ for(i = 0; i < i_max; i++){\r
+ if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) != CHNLIB_UTF8_GetNextUnicodeOfCharacter(search, &search)){\r
+ return False;\r
+ }\r
+ }\r
+ return True;\r
+}\r
+\r
+int CHNLIB_UTF8_CompareString_LeftHand(const char s[], const char search[])\r
+{\r
+ //s,searchをUTF-8文字列として解釈し、二つの文字列がどの程度一致するか調べる。前方一致。\r
+ //戻り値は、終端文字を除く、同一だった文字数。\r
+ //[UTF-8]\r
+ int i, i_max;\r
+ \r
+ if(s == NULL || search == NULL){\r
+ CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
+ return 0;\r
+ }\r
+ \r
+ i_max = CHNLIB_UTF8_GetStringLengthByCharacter(search);\r
+ for(i = 0; i < i_max; i++){\r
+ if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) != CHNLIB_UTF8_GetNextUnicodeOfCharacter(search, &search)){\r
+ break;\r
+ }\r
+ }\r
+ return i;\r
+}\r
\r
+int CHNLIB_UTF8_GetByteSizeFromLengthByCharacter(const char s[], int start, int end)\r
+{\r
+ //sをUTF-8文字列として解釈し、start番目の文字からend番目の文字までの占めるバイト数を返す。\r
+ //start番目の文字が終端文字以降の文字を指している場合は0を返す。\r
+ //end番目の文字が\r
+ //[UTF-8]\r
+ int i;\r
+ const char *p;\r
+ \r
+ if(s == NULL){\r
+ CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
+ return 0;\r
+ }\r
+ if(end < start){\r
+ CHNLIB_ReportError("Invalid index.\n", CHNLIB_DEBUG_ARGUMENTS);\r
+ return 0;\r
+ }\r
+ \r
+ for(i = 0; i < start; i++){\r
+ if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) == 0){\r
+ return 0;\r
+ }\r
+ }\r
+ p = s;\r
+ for(; i <= end; i++){\r
+ CHNLIB_UTF8_GetNextUnicodeOfCharacter(p, &p);\r
+ }\r
+ \r
+ return (int)(p - s);\r
+}\r
\r
+uint CHNLIB_UTF8_GetCountOfContain(const char s[], const char search[])\r
+{\r
+ //文字列s中に、文字列searchがいくつ含まれているかを返す。\r
+ //[UTF-8]\r
+ uint count;\r
+ \r
+ if(s == NULL || search == NULL){\r
+ CHNLIB_ReportError("Null str.\n", CHNLIB_DEBUG_ARGUMENTS);\r
+ return 0;\r
+ }\r
+ \r
+ count = 0;\r
+ for(;;){\r
+ if(CHNLIB_UTF8_CompareString(s, search)){\r
+ count++;\r
+ }\r
+ if(CHNLIB_UTF8_GetNextUnicodeOfCharacter(s, &s) == 0){\r
+ break;\r
+ }\r
+ }\r
+ return count;\r
+}\r
int main(int argc, const char * argv[])
{
- CHNLIB_String *s;
+ CHNLIB_String *s, *t;
CHNLIB_UIPArray *separated;
separated = CHNLIB_UIPArray_Initialize();
- s = CHNLIB_String_Initialize("あいうえお漢字。test aa");
+ s = CHNLIB_String_Initialize("このたけやぶにたけたてかけたかったのは、たけたてかけたてたかったからです。");
+ t = CHNLIB_String_Initialize("た");
- CHNLIB_UIPArray_GetSeparatedUTF8Character(&separated, s);
- CHNLIB_Debug_PrintStructureData(separated, 0);
+ printf("%d bytes, %d characters\n", CHNLIB_String_GetLength(s), CHNLIB_UTF8_GetStringLengthByCharacter(CHNLIB_String_GetReferencePointerOfCString(s)));
+ printf("%d bytes, %d characters\n", CHNLIB_String_GetLength(t), CHNLIB_UTF8_GetStringLengthByCharacter(CHNLIB_String_GetReferencePointerOfCString(t)));
+
+ printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(t)));
+ printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(t), CHNLIB_String_GetReferencePointerOfCString(s)));
+ printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(s)));
+ printf("match %d character(s).\n", CHNLIB_UTF8_CompareString_LeftHand(CHNLIB_String_GetReferencePointerOfCString(t), CHNLIB_String_GetReferencePointerOfCString(t)));
+
+ printf("%d\n", CHNLIB_UTF8_GetCountOfContain(CHNLIB_String_GetReferencePointerOfCString(s), CHNLIB_String_GetReferencePointerOfCString(t)));
return 0;
}