OSDN Git Service

chnlib:構造体のハッシュ値取得を実装。検索の高速化に利用する予定。文字列の連結・コピーも実装。合わせてlibtestも更新。
[chnosproject/CHNOSProject.git] / CHNOSProject / chn / chnlib00.c
index f846051..d81a01a 100755 (executable)
@@ -26,7 +26,9 @@
 //Declare internal functions\r
 //\r
 CHNLIB_UIPArray *CHNLIB_UIPArray_Internal_Allocate(void);\r
+const CHNLIB_UIPArray **CHNLIB_UIPArray_Internal_CheckIndex(const CHNLIB_UIPArray **array, int *index);\r
 void CHNLIB_UIPArray_Internal_Destruct(void **structure);\r
+uint CHNLIB_UIPArray_Internal_GetHash(const void *structure);\r
 \r
 //\r
 //Define types\r
@@ -101,28 +103,18 @@ int CHNLIB_UIPArray_AppendLast_ProtectFromDuplication(CHNLIB_UIPArray **array, u
 \r
 int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index)\r
 {\r
-    //戻り値:削除が成功したか(0:成功,-1:指定された添字の要素は存在しない)\r
+    //戻り値:関数が失敗したか(False:成功,True:指定された添字の要素は存在しない)\r
     //indexが指し示す要素を削除し、後続の要素は前へつめる。\r
     //削除された要素のpointerの参照先の所有を放棄する(Release)。\r
     int i;\r
     \r
-    for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
-        if(*array == NULL){\r
-            return -1;\r
-        }\r
-        array = &(*array)->next;\r
-    }\r
-    if(*array == NULL){\r
-        //大雑把に見て、配列の範囲外\r
-        return -1;\r
-    }\r
-    if(index >= (*array)->using_tags){\r
-        //詳細に見て、一つのパックの中で、配列の範囲外\r
-        return -1;\r
+    array = (CHNLIB_UIPArray **)CHNLIB_UIPArray_Internal_CheckIndex((const CHNLIB_UIPArray **)array, &index);\r
+    if(index == CHNLIB_UIPArray_INDEX_NOTFOUND){\r
+        return True;\r
     }\r
     \r
     //参照先の所有を放棄\r
-    CHNLIB_Release(&(*array)->tag[index].pointer);\r
+    release((*array)->tag[index].pointer);\r
     \r
     for(i = index; i < (*array)->using_tags - 1; i++){\r
         (*array)->tag[i] = (*array)->tag[i + 1];\r
@@ -150,7 +142,7 @@ int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index)
             break;\r
         }\r
     }\r
-    return 0;\r
+    return False;\r
 }\r
 \r
 void CHNLIB_UIPArray_FreeOnlyArray(CHNLIB_UIPArray **array)\r
@@ -238,14 +230,10 @@ int CHNLIB_UIPArray_GetNumberOfDatas(const CHNLIB_UIPArray *array)
 \r
 uint CHNLIB_UIPArray_GetData32ByIndex(const CHNLIB_UIPArray *array, int index)\r
 {\r
-    //retv:array[index]->data32\r
-    for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
-        if(array == NULL){\r
-            return 0;\r
-        }\r
-        array = array->next;\r
-    }\r
-    if(array == NULL){\r
+    //index番目のdata32を返す。\r
+    //無効なindex及びArrayを指定した場合は、0を返す。\r
+    array = *CHNLIB_UIPArray_Internal_CheckIndex(&array, &index);\r
+    if(index == CHNLIB_UIPArray_INDEX_NOTFOUND){\r
         return 0;\r
     }\r
     return array->tag[index].data32;\r
@@ -253,19 +241,14 @@ uint CHNLIB_UIPArray_GetData32ByIndex(const CHNLIB_UIPArray *array, int index)
 \r
 uint CHNLIB_UIPArray_SetData32ByIndex(CHNLIB_UIPArray *array, int index, uint data32)\r
 {\r
-    //retv = old data32\r
-    \r
+    //変更前のdata32が返される。\r
     uint olddata;\r
-    \r
-    for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
-        if(array == NULL){\r
-            return 0;\r
-        }\r
-        array = array->next;\r
-    }\r
-    if(array == NULL){\r
+\r
+    array = (CHNLIB_UIPArray *)*CHNLIB_UIPArray_Internal_CheckIndex((const CHNLIB_UIPArray **)&array, &index);\r
+    if(index == CHNLIB_UIPArray_INDEX_NOTFOUND){\r
         return 0;\r
     }\r
+\r
     olddata = array->tag[index].data32;\r
     array->tag[index].data32 = data32;\r
     return olddata;\r
@@ -274,15 +257,12 @@ uint CHNLIB_UIPArray_SetData32ByIndex(CHNLIB_UIPArray *array, int index, uint da
 void *CHNLIB_UIPArray_GetPointerByIndex(const CHNLIB_UIPArray *array, int index)\r
 {\r
     //retv:array[index]->pointer\r
-    for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
-        if(array == NULL){\r
-            return NULL;\r
-        }\r
-        array = array->next;\r
-    }\r
-    if(array == NULL){\r
+    \r
+    array = *CHNLIB_UIPArray_Internal_CheckIndex(&array, &index);\r
+    if(index == CHNLIB_UIPArray_INDEX_NOTFOUND){\r
         return NULL;\r
     }\r
+    \r
     return array->tag[index].pointer;\r
 }\r
 \r
@@ -378,11 +358,45 @@ CHNLIB_UIPArray *CHNLIB_UIPArray_Internal_Allocate(void)
     \r
     CHNLIB_StructureHeader_Initialize(&tag->header, CHNLIB_STRUCT_ID_UIPArray);\r
     tag->header.destructor = &CHNLIB_UIPArray_Internal_Destruct;\r
+    tag->header.getHash = &CHNLIB_UIPArray_Internal_GetHash;\r
     \r
     return tag;\r
 \r
 }\r
 \r
+const CHNLIB_UIPArray **CHNLIB_UIPArray_Internal_CheckIndex(const CHNLIB_UIPArray **array, int *index)\r
+{\r
+    //*indexの指す要素の含まれるパックを指すポインタへのアドレスを返し、*indexにはそのパック内での添字を格納する。\r
+    //*indexが配列の範囲外だった場合、*indexにCHNLIB_UIPArray_INDEX_NOTFOUNDを格納する。\r
+    //内部関数なので、arrayおよびindexがNULLでないことを仮定する。\r
+    \r
+    if((*index) < 0){\r
+        //添字がマイナスの要素は存在しない\r
+        (*index) = CHNLIB_UIPArray_INDEX_NOTFOUND;\r
+        return array;\r
+    }\r
+    if(*array == NULL){\r
+        //次のPackが存在しない\r
+        (*index) = CHNLIB_UIPArray_INDEX_NOTFOUND;\r
+        return array;\r
+    }\r
+    for(; ((*index) / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; (*index) -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
+        array = (const CHNLIB_UIPArray **)&(*array)->next;\r
+        if(*array == NULL){\r
+            //次のPackが存在しない\r
+            (*index) = CHNLIB_UIPArray_INDEX_NOTFOUND;\r
+            return array;\r
+        }\r
+    }\r
+\r
+    if((*index) >= (*array)->using_tags){\r
+        //詳細に見て、一つのパックの中で、配列の範囲外\r
+        (*index) = CHNLIB_UIPArray_INDEX_NOTFOUND;\r
+        return array;\r
+    }\r
+    return array;\r
+}\r
+\r
 void CHNLIB_UIPArray_Internal_Destruct(void **structure)\r
 {\r
     //デストラクタ(実際にRelease->freeされる時に呼ばれる)\r
@@ -416,4 +430,24 @@ void CHNLIB_UIPArray_Internal_Destruct(void **structure)
     return;\r
 }\r
 \r
+uint CHNLIB_UIPArray_Internal_GetHash(const void *structure)\r
+{\r
+    const CHNLIB_UIPArray *array;\r
+    int i, i_max;\r
+    uint hash;\r
+    \r
+    if(CHNLIB_StructureHeader_GetTypeID(structure) != CHNLIB_STRUCT_ID_UIPArray){\r
+        return 0;\r
+    }\r
+    \r
+    hash = 0;\r
+    array = (const CHNLIB_UIPArray *)structure;\r
+    i_max = CHNLIB_UIPArray_GetNumberOfDatas(array);\r
+    for(i = 0; i < i_max; i++){\r
+        hash += CHNLIB_StructureHeader_GetHash(CHNLIB_UIPArray_GetPointerByIndex(array, i));\r
+    }\r
+    \r
+    return hash;\r
+}\r
+\r
 \r