/*
* HashTable - ハッシュテーブル。
*
* Date: 2014-04-10
* Author: Leonardone
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG_FLAG 1
#if DEBUG_FLAG
# define DebugDo(d) d
#else
# define DebugDo(d)
#endif
/* --- hashtable.h --- */
#define MINIMUM_HASHTABLESIZE (0x0002)
#define MAXIMUM_HASHTABLESIZE (0x7FFF)
struct _hashtable;
struct _tabledata;
typedef struct _hashtable HashTable, *LPHashTable;
typedef struct _tabledata TableData, *LPTableData;
extern LPHashTable newHashTable(int tablesize);
extern void releaseHashTable(LPHashTable htable);
extern int addDataIntoHashTable(LPHashTable htable, const char *key, const void *data, const int size);
extern int getDataFromHashTable(const LPHashTable htable, const char *key, void *data, const int size);
extern int removeDataFromHashTable(LPHashTable htable, const char *key);
extern int existKeyInHashTable(LPHashTable htable, const char *key);
extern int setDataIntoHashTable(LPHashTable htable, const char *key, const void *data, const int size);
extern int countDataInHashTable(LPHashTable htable);
extern int getAllKeysInHashTable(const LPHashTable htable, int (*func)(const char *key));
struct _hashtable {
int count;
int tablesize;
LPTableData *table;
};
struct _tabledata {
char *key;
void *data;
int size;
LPTableData next;
};
/* --- hashtable_static.h --- */
#define HASH_DEEP (5)
static int hash(const char *key, const int tablesize);
static LPTableData *searchPlace(const LPHashTable htable, const char *key);
static void releaseTableData(LPTableData ptbdata, int chain);
/* --- test.c --- */
int addIntIntoHashTable(LPHashTable htable, const char *key, const int value) {
return addDataIntoHashTable(htable, key, &value, sizeof(int));
}
int getIntFromHashTable(const LPHashTable htable, const char *key, int *value) {
return getDataFromHashTable(htable, key, (void*)value, sizeof(int));
}
int setIntIntoHashTable(LPHashTable htable, const char *key, const int value) {
return setDataIntoHashTable(htable, key, &value, sizeof(int));
}
int func1(const char* key) {
return 0;
}
int main(void) {
LPHashTable htable = newHashTable(1024);
int v = 0;
addIntIntoHashTable(htable, "foo", 111);
addIntIntoHashTable(htable, "bar", 222);
addIntIntoHashTable(htable, "baz", 333);
addIntIntoHashTable(htable, "fuga", 987);
addIntIntoHashTable(htable, "piyo", 654);
printf("cnt: %d\n", htable
->count
); printf("cnt: %d\n", countDataInHashTable
(htable
));
addIntIntoHashTable(htable, "hoge", 123);
addIntIntoHashTable(htable, "hoge", 345);
getIntFromHashTable(htable, "hoge", &v);
printf("cnt: %d\n", countDataInHashTable
(htable
));
setIntIntoHashTable(htable, "hoge", 345);
setIntIntoHashTable(htable, "foobar", 999);
getIntFromHashTable(htable, "hoge", &v);
printf("cnt: %d\n", countDataInHashTable
(htable
));
getAllKeysInHashTable(htable, func1);
removeDataFromHashTable(htable, "baz");
removeDataFromHashTable(htable, "baz");
removeDataFromHashTable(htable, "test");
printf("cnt: %d\n", countDataInHashTable
(htable
));
printf("sch: %d\n", searchPlace
(htable
, "hoge")); printf("sch: %d\n", searchPlace
(htable
, "abc")); printf("*sch: %d\n", *searchPlace
(htable
, "hoge")); printf("*sch: %d\n", *searchPlace
(htable
, "abc")); printf("*sch-d: %d\n", *(int*)(*searchPlace
(htable
, "hoge"))->data
); printf("*sch-d: %d\n", *(int*)(*searchPlace
(htable
, "bar"))->data
);
printf("ext: %d\n", existKeyInHashTable
(htable
, "hoge")); printf("ext: %d\n", existKeyInHashTable
(htable
, "abc")); printf("ext: %d\n", existKeyInHashTable
(htable
, "foo")); printf("ext: %d\n", existKeyInHashTable
(htable
, "baz")); printf("ext: %d\n", existKeyInHashTable
(htable
, "fuga")); printf("ext: %d\n", existKeyInHashTable
(htable
, "piyo"));
releaseHashTable(htable);
return 0;
}
/* --- hashtable.c --- */
/* +++ extern functions +++ */
/**
* 新しいHashTableを作る。
* @param tablesize
* @return
*/
LPHashTable newHashTable(const int tablesize) {
/* calloc は 0 で初期化される */
LPHashTable htable;
if (tablesize < MINIMUM_HASHTABLESIZE || tablesize > MAXIMUM_HASHTABLESIZE) {
return NULL; /* 引数エラー */
}
htable
= (LPHashTable
)calloc(1, sizeof(HashTable
)); if (htable == NULL) {
return NULL; /* メモリ確保失敗 */
}
htable
->table
= (LPTableData
*)calloc(tablesize
, sizeof(LPTableData
)); if (htable->table == NULL) {
return NULL; /* メモリ確保失敗 */
}
htable->tablesize = tablesize;
DebugDo
(printf("init HashTable(%d)\n", tablesize
)); return htable;
}
/**
* HashTableをメモリから解放する。
* @param htable
*/
void releaseHashTable(LPHashTable htable) {
int i;
int tablesize;
LPTableData *ptbdata;
if (htable == NULL) {
return; /* ぬるぽ */
}
tablesize = htable->tablesize;
for (i = 0; i < tablesize; ++i) {
ptbdata = htable->table + i;
if (*ptbdata != NULL) {
releaseTableData(*ptbdata, 1);
}
}
DebugDo
(printf("release HashTable(%d)\n", tablesize
));}
/**
* HashTableにデータを追加する。既にキー名が存在する場合は失敗する。
* @param htable
* @param key
* @param data
* @param size
* @return
*/
int addDataIntoHashTable(LPHashTable htable, const char *key, const void *data, const int size) {
int len;
LPTableData *ptbdata;
if (htable == NULL || key == NULL || data == NULL || size < 1) {
return 0; /* 引数エラー */
}
ptbdata = searchPlace(htable, key);
if (*ptbdata == NULL) {
*ptbdata
= (LPTableData
)calloc(1, sizeof(TableData
)); if (*ptbdata == NULL) {
return 0; /* メモリ確保失敗 */
}
(*ptbdata
)->key
= (char *)calloc(len
, sizeof(char)); if ((*ptbdata)->key == NULL) {
*ptbdata = NULL;
return 0; /* メモリ確保失敗 */
}
(*ptbdata
)->data
= calloc(size
, 1); if ((*ptbdata)->data == NULL) {
*ptbdata = NULL;
return 0; /* メモリ確保失敗 */
}
memcpy((*ptbdata
)->key
, key
, len
); memcpy((*ptbdata
)->data
, data
, size
); (*ptbdata)->size = size;
++(htable->count);
DebugDo
(printf("add(success): %s\n", key
)); return 1;
}
DebugDo
(printf("add(failure): %s\n", key
)); return 2;
}
/**
* HashTableからキー名のデータを取得する。
* @param htable
* @param key
* @param data
* @param size
* @return
*/
int getDataFromHashTable(const LPHashTable htable, const char *key, void *data, const int size) {
int minsize;
LPTableData tbdata;
if (htable == NULL || key == NULL || data == NULL || size < 1) {
return 0; /* 引数エラー */
}
tbdata = *searchPlace(htable, key);
if (tbdata != NULL) {
if (strcmp(tbdata
->key
, key
) == 0) { minsize = tbdata->size < size ? tbdata->size : size;
memcpy(data
, tbdata
->data
, minsize
); DebugDo
(printf("get(success): %s\n", key
)); return minsize;
}
tbdata = tbdata->next;
}
DebugDo
(printf("get(failure): %s\n", key
)); return 0;
}
/**
* HashTableにデータを書き込む。既にキー名のデータがある場合は上書きする。
* @param htable
* @param key
* @param data
* @param size
* @return
*/
int setDataIntoHashTable(LPHashTable htable, const char *key, const void *data, const int size) {
int len;
int ret = 1;
void *temp;
LPTableData *ptbdata;
if (htable == NULL || key == NULL || data == NULL || size < 1) {
return 0; /* 引数エラー */
}
ptbdata = searchPlace(htable, key);
if (*ptbdata == NULL) {
*ptbdata
= (LPTableData
)calloc(1, sizeof(TableData
)); if (*ptbdata == NULL) {
return 0; /* メモリ確保失敗 */
}
(*ptbdata
)->key
= (char *)calloc(len
, sizeof(char)); if ((*ptbdata)->key == NULL) {
*ptbdata = NULL;
return 0; /* メモリ確保失敗 */
}
(*ptbdata
)->data
= calloc(size
, 1); if ((*ptbdata)->data == NULL) {
*ptbdata = NULL;
return 0; /* メモリ確保失敗 */
}
memcpy((*ptbdata
)->key
, key
, len
); (*ptbdata)->size = size;
++(htable->count);
DebugDo
(printf("set/new(success): %s\n", key
)); } else {
if ((*ptbdata)->size != size) {
temp
= realloc((*ptbdata
)->data
, size
); if (temp == NULL) {
return 0; /* メモリ確保失敗 */
}
(*ptbdata)->data = temp;
(*ptbdata)->size = size;
}
ret = 2;
DebugDo
(printf("set/update(success): %s\n", key
)); }
memcpy((*ptbdata
)->data
, data
, size
); return ret;
}
/**
* HashTable内の指定キー名のデータを削除する。
* @param htable HashTable。
* @param key キー名。
* @return 削除できたら(1)、失敗したら(0)。
*/
int removeDataFromHashTable(LPHashTable htable, const char *key) {
LPTableData *ptbdata;
LPTableData tbdata;
if (htable == NULL || key == NULL) {
return 0; /* ぬるぽ */
}
ptbdata = searchPlace(htable, key);
if (*ptbdata != NULL) {
tbdata = *ptbdata;
*ptbdata = tbdata->next;
releaseTableData(tbdata, 0);
--(htable->count);
DebugDo
(printf("remove(success): %s\n", key
)); return 1;
}
DebugDo
(printf("remove(failure): %s\n", key
)); return 0;
}
/**
* HashTable内にキー名のデータが存在するか書くにする。
* @param htable HashTable。
* @param key 探すキー名。
* @return 存在すれば(1)、存在しなければ(0)。
*/
int existKeyInHashTable(LPHashTable htable, const char *key) {
if (htable == NULL || key == NULL) {
return 0; /* ぬるぽ */
}
return *searchPlace(htable, key) != NULL;
}
/**
* HashTable内のデータ数を返す。
* @param htable HashTable。
* @return データ数。
*/
int countDataInHashTable(LPHashTable htable) {
if (htable == NULL) {
return 0; /* ぬるぽ */
}
return htable->count;
}
/**
* HashTable内のキー名を全て取得する。
* @param htable
* @param func
* @return
*/
int getAllKeysInHashTable(const LPHashTable htable, int (*func)(const char *key)) {
int i;
int ret;
int tablesize;
LPTableData *ptbdata;
LPTableData tbdata;
if (htable == NULL || func == NULL) {
return 0;
}
DebugDo
(printf("allkey(start)\n")); ptbdata = htable->table;
tablesize = htable->tablesize;
for (i = 0; i < tablesize; ++i) {
tbdata = *ptbdata;
while (tbdata != NULL) {
ret = (*func)(tbdata->key);
if (ret) {
DebugDo
(printf("allkey(stop)\n")); return 2;
}
tbdata = tbdata->next;
}
++ptbdata;
}
DebugDo
(printf("allkey(done)\n")); return 1;
}
/* +++ static functions +++ */
/**
* ハッシュ関数。キー名からハッシュ値を生成する。
* @param key キー名。
* @param tablesize ハッシュ値の制限値。
* @return ハッシュ値。
*/
int hash(const char *key, const int tablesize) {
int i;
int v = (int)*key;
for (i = 0; i < HASH_DEEP && *key != '\0'; i++) {
v ^= (int)(*key) * (int)(*(key + 1));
++key;
}
return v % tablesize;
}
/**
* HashTableからキー名のデータを格納する場所(アドレス)を探す。
* @param htable キー名を探すHashTable。
* @param key 探すキー名。
* @return 格納されてる場所(アドレス)。
*/
LPTableData *searchPlace(const LPHashTable htable, const char *key) {
int h = hash(key, htable->tablesize);
LPTableData *ptbdata = htable->table + h;
while (*ptbdata != NULL) {
if (strcmp((*ptbdata
)->key
, key
) == 0) { break;
}
ptbdata = &(*ptbdata)->next;
}
DebugDo
(printf("hash(%d): %s\n", h
, key
)); return ptbdata;
}
/**
* TableDataをメモリから解放する。
* @param ptbdata 解放するデータ。
* @param chain nextにあるTableDataも解放する(1)かしない(0)か。
*/
void releaseTableData(LPTableData tbdata, int chain) {
if (tbdata == NULL) {
return;
}
if (chain) {
releaseTableData(tbdata->next, chain);
}
DebugDo
(printf("release TableData: %s\n", tbdata
->key
));}
LyoKICogSGFzaFRhYmxlIC0g44OP44OD44K344Ol44OG44O844OW44Or44CCCiAqCiAqIERhdGU6IDIwMTQtMDQtMTAKICogQXV0aG9yOiBMZW9uYXJkb25lCiAqLwojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CgojZGVmaW5lIERFQlVHX0ZMQUcgMQoKI2lmIERFQlVHX0ZMQUcKIyAgZGVmaW5lIERlYnVnRG8oZCkgZAojZWxzZQojICBkZWZpbmUgRGVidWdEbyhkKQojZW5kaWYKCi8qIC0tLSBoYXNodGFibGUuaCAtLS0gKi8KCiNkZWZpbmUgTUlOSU1VTV9IQVNIVEFCTEVTSVpFICgweDAwMDIpCiNkZWZpbmUgTUFYSU1VTV9IQVNIVEFCTEVTSVpFICgweDdGRkYpCgpzdHJ1Y3QgX2hhc2h0YWJsZTsKc3RydWN0IF90YWJsZWRhdGE7Cgp0eXBlZGVmIHN0cnVjdCBfaGFzaHRhYmxlIEhhc2hUYWJsZSwgKkxQSGFzaFRhYmxlOwp0eXBlZGVmIHN0cnVjdCBfdGFibGVkYXRhIFRhYmxlRGF0YSwgKkxQVGFibGVEYXRhOwoKZXh0ZXJuIExQSGFzaFRhYmxlIG5ld0hhc2hUYWJsZShpbnQgdGFibGVzaXplKTsKZXh0ZXJuIHZvaWQgcmVsZWFzZUhhc2hUYWJsZShMUEhhc2hUYWJsZSBodGFibGUpOwpleHRlcm4gaW50IGFkZERhdGFJbnRvSGFzaFRhYmxlKExQSGFzaFRhYmxlIGh0YWJsZSwgY29uc3QgY2hhciAqa2V5LCBjb25zdCB2b2lkICpkYXRhLCBjb25zdCBpbnQgc2l6ZSk7CmV4dGVybiBpbnQgZ2V0RGF0YUZyb21IYXNoVGFibGUoY29uc3QgTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXksIHZvaWQgKmRhdGEsIGNvbnN0IGludCBzaXplKTsKZXh0ZXJuIGludCByZW1vdmVEYXRhRnJvbUhhc2hUYWJsZShMUEhhc2hUYWJsZSBodGFibGUsIGNvbnN0IGNoYXIgKmtleSk7CmV4dGVybiBpbnQgZXhpc3RLZXlJbkhhc2hUYWJsZShMUEhhc2hUYWJsZSBodGFibGUsIGNvbnN0IGNoYXIgKmtleSk7CmV4dGVybiBpbnQgc2V0RGF0YUludG9IYXNoVGFibGUoTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXksIGNvbnN0IHZvaWQgKmRhdGEsIGNvbnN0IGludCBzaXplKTsKZXh0ZXJuIGludCBjb3VudERhdGFJbkhhc2hUYWJsZShMUEhhc2hUYWJsZSBodGFibGUpOwpleHRlcm4gaW50IGdldEFsbEtleXNJbkhhc2hUYWJsZShjb25zdCBMUEhhc2hUYWJsZSBodGFibGUsIGludCAoKmZ1bmMpKGNvbnN0IGNoYXIgKmtleSkpOwoKc3RydWN0IF9oYXNodGFibGUgewoJaW50IGNvdW50OwoJaW50IHRhYmxlc2l6ZTsKCUxQVGFibGVEYXRhICp0YWJsZTsKfTsKCnN0cnVjdCBfdGFibGVkYXRhIHsKCWNoYXIgKmtleTsKCXZvaWQgKmRhdGE7CglpbnQgc2l6ZTsKCUxQVGFibGVEYXRhIG5leHQ7Cn07CgovKiAtLS0gaGFzaHRhYmxlX3N0YXRpYy5oIC0tLSAqLwoKI2RlZmluZSBIQVNIX0RFRVAgKDUpCgpzdGF0aWMgaW50IGhhc2goY29uc3QgY2hhciAqa2V5LCBjb25zdCBpbnQgdGFibGVzaXplKTsKc3RhdGljIExQVGFibGVEYXRhICpzZWFyY2hQbGFjZShjb25zdCBMUEhhc2hUYWJsZSBodGFibGUsIGNvbnN0IGNoYXIgKmtleSk7CnN0YXRpYyB2b2lkIHJlbGVhc2VUYWJsZURhdGEoTFBUYWJsZURhdGEgcHRiZGF0YSwgaW50IGNoYWluKTsKCi8qIC0tLSB0ZXN0LmMgLS0tICovCgppbnQgYWRkSW50SW50b0hhc2hUYWJsZShMUEhhc2hUYWJsZSBodGFibGUsIGNvbnN0IGNoYXIgKmtleSwgY29uc3QgaW50IHZhbHVlKSB7CglyZXR1cm4gYWRkRGF0YUludG9IYXNoVGFibGUoaHRhYmxlLCBrZXksICZ2YWx1ZSwgc2l6ZW9mKGludCkpOwp9CgppbnQgZ2V0SW50RnJvbUhhc2hUYWJsZShjb25zdCBMUEhhc2hUYWJsZSBodGFibGUsIGNvbnN0IGNoYXIgKmtleSwgaW50ICp2YWx1ZSkgewoJcmV0dXJuIGdldERhdGFGcm9tSGFzaFRhYmxlKGh0YWJsZSwga2V5LCAodm9pZCopdmFsdWUsIHNpemVvZihpbnQpKTsKfQoKaW50IHNldEludEludG9IYXNoVGFibGUoTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXksIGNvbnN0IGludCB2YWx1ZSkgewoJcmV0dXJuIHNldERhdGFJbnRvSGFzaFRhYmxlKGh0YWJsZSwga2V5LCAmdmFsdWUsIHNpemVvZihpbnQpKTsKfQoKaW50IGZ1bmMxKGNvbnN0IGNoYXIqIGtleSkgewoJcHJpbnRmKCJrZXk6ICVzXG4iLCBrZXkpOwoJcmV0dXJuIDA7Cn0KCmludCBtYWluKHZvaWQpIHsKCQoJTFBIYXNoVGFibGUgaHRhYmxlID0gbmV3SGFzaFRhYmxlKDEwMjQpOwoJaW50IHYgPSAwOwoJCglhZGRJbnRJbnRvSGFzaFRhYmxlKGh0YWJsZSwgImZvbyIsIDExMSk7CglhZGRJbnRJbnRvSGFzaFRhYmxlKGh0YWJsZSwgImJhciIsIDIyMik7CglhZGRJbnRJbnRvSGFzaFRhYmxlKGh0YWJsZSwgImJheiIsIDMzMyk7CglhZGRJbnRJbnRvSGFzaFRhYmxlKGh0YWJsZSwgImZ1Z2EiLCA5ODcpOwoJYWRkSW50SW50b0hhc2hUYWJsZShodGFibGUsICJwaXlvIiwgNjU0KTsKCQoKCXByaW50ZigiY250OiAlZFxuIiwgaHRhYmxlLT5jb3VudCk7CglwcmludGYoImNudDogJWRcbiIsIGNvdW50RGF0YUluSGFzaFRhYmxlKGh0YWJsZSkpOwoKCWFkZEludEludG9IYXNoVGFibGUoaHRhYmxlLCAiaG9nZSIsIDEyMyk7CglhZGRJbnRJbnRvSGFzaFRhYmxlKGh0YWJsZSwgImhvZ2UiLCAzNDUpOwoJZ2V0SW50RnJvbUhhc2hUYWJsZShodGFibGUsICJob2dlIiwgJnYpOwoJcHJpbnRmKCJnZXQ6ICVkXG4iLCB2KTsKCglwcmludGYoImNudDogJWRcbiIsIGNvdW50RGF0YUluSGFzaFRhYmxlKGh0YWJsZSkpOwoKCXNldEludEludG9IYXNoVGFibGUoaHRhYmxlLCAiaG9nZSIsIDM0NSk7CglzZXRJbnRJbnRvSGFzaFRhYmxlKGh0YWJsZSwgImZvb2JhciIsIDk5OSk7CglnZXRJbnRGcm9tSGFzaFRhYmxlKGh0YWJsZSwgImhvZ2UiLCAmdik7CglwcmludGYoImdldDogJWRcbiIsIHYpOwoKCXByaW50ZigiY250OiAlZFxuIiwgY291bnREYXRhSW5IYXNoVGFibGUoaHRhYmxlKSk7CgkKCWdldEFsbEtleXNJbkhhc2hUYWJsZShodGFibGUsIGZ1bmMxKTsKCQoJcmVtb3ZlRGF0YUZyb21IYXNoVGFibGUoaHRhYmxlLCAiYmF6Iik7CglyZW1vdmVEYXRhRnJvbUhhc2hUYWJsZShodGFibGUsICJiYXoiKTsKCXJlbW92ZURhdGFGcm9tSGFzaFRhYmxlKGh0YWJsZSwgInRlc3QiKTsKCglwcmludGYoImNudDogJWRcbiIsIGNvdW50RGF0YUluSGFzaFRhYmxlKGh0YWJsZSkpOwoKCXByaW50Zigic2NoOiAlZFxuIiwgc2VhcmNoUGxhY2UoaHRhYmxlLCAiaG9nZSIpKTsKCXByaW50Zigic2NoOiAlZFxuIiwgc2VhcmNoUGxhY2UoaHRhYmxlLCAiYWJjIikpOwoJcHJpbnRmKCIqc2NoOiAlZFxuIiwgKnNlYXJjaFBsYWNlKGh0YWJsZSwgImhvZ2UiKSk7CglwcmludGYoIipzY2g6ICVkXG4iLCAqc2VhcmNoUGxhY2UoaHRhYmxlLCAiYWJjIikpOwoJcHJpbnRmKCIqc2NoLWQ6ICVkXG4iLCAqKGludCopKCpzZWFyY2hQbGFjZShodGFibGUsICJob2dlIikpLT5kYXRhKTsKCXByaW50ZigiKnNjaC1kOiAlZFxuIiwgKihpbnQqKSgqc2VhcmNoUGxhY2UoaHRhYmxlLCAiYmFyIikpLT5kYXRhKTsKCglwcmludGYoImV4dDogJWRcbiIsIGV4aXN0S2V5SW5IYXNoVGFibGUoaHRhYmxlLCAiaG9nZSIpKTsKCXByaW50ZigiZXh0OiAlZFxuIiwgZXhpc3RLZXlJbkhhc2hUYWJsZShodGFibGUsICJhYmMiKSk7CglwcmludGYoImV4dDogJWRcbiIsIGV4aXN0S2V5SW5IYXNoVGFibGUoaHRhYmxlLCAiZm9vIikpOwoJcHJpbnRmKCJleHQ6ICVkXG4iLCBleGlzdEtleUluSGFzaFRhYmxlKGh0YWJsZSwgImJheiIpKTsKCXByaW50ZigiZXh0OiAlZFxuIiwgZXhpc3RLZXlJbkhhc2hUYWJsZShodGFibGUsICJmdWdhIikpOwoJcHJpbnRmKCJleHQ6ICVkXG4iLCBleGlzdEtleUluSGFzaFRhYmxlKGh0YWJsZSwgInBpeW8iKSk7CgkKCXJlbGVhc2VIYXNoVGFibGUoaHRhYmxlKTsKCQoJcmV0dXJuIDA7Cn0KCi8qIC0tLSBoYXNodGFibGUuYyAtLS0gKi8KCi8qICsrKyBleHRlcm4gZnVuY3Rpb25zICsrKyAqLwoKLyoqCiAqIOaWsOOBl+OBhEhhc2hUYWJsZeOCkuS9nOOCi+OAggogKiBAcGFyYW0gdGFibGVzaXplCiAqIEByZXR1cm4KICovCkxQSGFzaFRhYmxlIG5ld0hhc2hUYWJsZShjb25zdCBpbnQgdGFibGVzaXplKSB7CgkvKiBjYWxsb2Mg44GvIDAg44Gn5Yid5pyf5YyW44GV44KM44KLICovCglMUEhhc2hUYWJsZSBodGFibGU7CglpZiAodGFibGVzaXplIDwgTUlOSU1VTV9IQVNIVEFCTEVTSVpFIHx8IHRhYmxlc2l6ZSA+IE1BWElNVU1fSEFTSFRBQkxFU0laRSkgewoJCXJldHVybiBOVUxMOyAvKiDlvJXmlbDjgqjjg6njg7wgKi8gCgl9CglodGFibGUgPSAoTFBIYXNoVGFibGUpY2FsbG9jKDEsIHNpemVvZihIYXNoVGFibGUpKTsKCWlmIChodGFibGUgPT0gTlVMTCkgewoJCXJldHVybiBOVUxMOyAvKiDjg6Hjg6Ljg6rnorrkv53lpLHmlZcgKi8KCX0KCWh0YWJsZS0+dGFibGUgPSAoTFBUYWJsZURhdGEgKiljYWxsb2ModGFibGVzaXplLCBzaXplb2YoTFBUYWJsZURhdGEpKTsKCWlmIChodGFibGUtPnRhYmxlID09IE5VTEwpIHsKCQlmcmVlKGh0YWJsZSk7CgkJcmV0dXJuIE5VTEw7IC8qIOODoeODouODqueiuuS/neWkseaVlyAqLwoJfQoJaHRhYmxlLT50YWJsZXNpemUgPSB0YWJsZXNpemU7CglEZWJ1Z0RvKHByaW50ZigiaW5pdCBIYXNoVGFibGUoJWQpXG4iLCB0YWJsZXNpemUpKTsKCXJldHVybiBodGFibGU7Cn0KCi8qKgogKiBIYXNoVGFibGXjgpLjg6Hjg6Ljg6rjgYvjgonop6PmlL7jgZnjgovjgIIKICogQHBhcmFtIGh0YWJsZQogKi8Kdm9pZCByZWxlYXNlSGFzaFRhYmxlKExQSGFzaFRhYmxlIGh0YWJsZSkgewoJaW50IGk7CglpbnQgdGFibGVzaXplOwoJTFBUYWJsZURhdGEgKnB0YmRhdGE7CglpZiAoaHRhYmxlID09IE5VTEwpIHsKCQlyZXR1cm47IC8qIOOBrOOCi+OBvSAqLwoJfQoJdGFibGVzaXplID0gaHRhYmxlLT50YWJsZXNpemU7Cglmb3IgKGkgPSAwOyBpIDwgdGFibGVzaXplOyArK2kpIHsKCQlwdGJkYXRhID0gaHRhYmxlLT50YWJsZSArIGk7CgkJaWYgKCpwdGJkYXRhICE9IE5VTEwpIHsKCQkJcmVsZWFzZVRhYmxlRGF0YSgqcHRiZGF0YSwgMSk7CgkJfQoJfQoJZnJlZShodGFibGUtPnRhYmxlKTsKCWZyZWUoaHRhYmxlKTsKCURlYnVnRG8ocHJpbnRmKCJyZWxlYXNlIEhhc2hUYWJsZSglZClcbiIsIHRhYmxlc2l6ZSkpOwp9CgovKioKICogSGFzaFRhYmxl44Gr44OH44O844K/44KS6L+95Yqg44GZ44KL44CC5pei44Gr44Kt44O85ZCN44GM5a2Y5Zyo44GZ44KL5aC05ZCI44Gv5aSx5pWX44GZ44KL44CCCiAqIEBwYXJhbSBodGFibGUKICogQHBhcmFtIGtleQogKiBAcGFyYW0gZGF0YQogKiBAcGFyYW0gc2l6ZQogKiBAcmV0dXJuCiAqLwppbnQgYWRkRGF0YUludG9IYXNoVGFibGUoTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXksIGNvbnN0IHZvaWQgKmRhdGEsIGNvbnN0IGludCBzaXplKSB7CglpbnQgbGVuOwoJTFBUYWJsZURhdGEgKnB0YmRhdGE7CglpZiAoaHRhYmxlID09IE5VTEwgfHwga2V5ID09IE5VTEwgfHwgZGF0YSA9PSBOVUxMIHx8IHNpemUgPCAxKSB7CgkJcmV0dXJuIDA7IC8qIOW8leaVsOOCqOODqeODvCAqLwoJfQoJcHRiZGF0YSA9IHNlYXJjaFBsYWNlKGh0YWJsZSwga2V5KTsKCWlmICgqcHRiZGF0YSA9PSBOVUxMKSB7CgkJKnB0YmRhdGEgPSAoTFBUYWJsZURhdGEpY2FsbG9jKDEsIHNpemVvZihUYWJsZURhdGEpKTsKCQlpZiAoKnB0YmRhdGEgPT0gTlVMTCkgewoJCQlyZXR1cm4gMDsgLyog44Oh44Oi44Oq56K65L+d5aSx5pWXICovCgkJfQoJCSgqcHRiZGF0YSktPmtleSA9IChjaGFyICopY2FsbG9jKGxlbiwgc2l6ZW9mKGNoYXIpKTsKCQlpZiAoKCpwdGJkYXRhKS0+a2V5ID09IE5VTEwpIHsKCQkJZnJlZSgqcHRiZGF0YSk7CgkJCSpwdGJkYXRhID0gTlVMTDsKCQkJcmV0dXJuIDA7IC8qIOODoeODouODqueiuuS/neWkseaVlyAqLwoJCX0KCQkoKnB0YmRhdGEpLT5kYXRhID0gY2FsbG9jKHNpemUsIDEpOwoJCWlmICgoKnB0YmRhdGEpLT5kYXRhID09IE5VTEwpIHsKCQkJZnJlZSgoKnB0YmRhdGEpLT5rZXkpOwoJCQlmcmVlKCpwdGJkYXRhKTsKCQkJKnB0YmRhdGEgPSBOVUxMOwoJCQlyZXR1cm4gMDsgLyog44Oh44Oi44Oq56K65L+d5aSx5pWXICovCgkJfQoJCWxlbiA9IHN0cmxlbihrZXkpICsgMTsKCQltZW1jcHkoKCpwdGJkYXRhKS0+a2V5LCBrZXksIGxlbik7CgkJbWVtY3B5KCgqcHRiZGF0YSktPmRhdGEsIGRhdGEsIHNpemUpOwoJCSgqcHRiZGF0YSktPnNpemUgPSBzaXplOwoJCSsrKGh0YWJsZS0+Y291bnQpOwoJCURlYnVnRG8ocHJpbnRmKCJhZGQoc3VjY2Vzcyk6ICVzXG4iLCBrZXkpKTsKCQlyZXR1cm4gMTsKCX0KCURlYnVnRG8ocHJpbnRmKCJhZGQoZmFpbHVyZSk6ICVzXG4iLCBrZXkpKTsKCXJldHVybiAyOwp9CgovKioKICogSGFzaFRhYmxl44GL44KJ44Kt44O85ZCN44Gu44OH44O844K/44KS5Y+W5b6X44GZ44KL44CCCiAqIEBwYXJhbSBodGFibGUKICogQHBhcmFtIGtleQogKiBAcGFyYW0gZGF0YQogKiBAcGFyYW0gc2l6ZQogKiBAcmV0dXJuCiAqLwppbnQgZ2V0RGF0YUZyb21IYXNoVGFibGUoY29uc3QgTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXksIHZvaWQgKmRhdGEsIGNvbnN0IGludCBzaXplKSB7CglpbnQgbWluc2l6ZTsKCUxQVGFibGVEYXRhIHRiZGF0YTsKCWlmIChodGFibGUgPT0gTlVMTCB8fCBrZXkgPT0gTlVMTCB8fCBkYXRhID09IE5VTEwgfHwgc2l6ZSA8IDEpIHsKCQlyZXR1cm4gMDsgLyog5byV5pWw44Ko44Op44O8ICovCgl9Cgl0YmRhdGEgPSAqc2VhcmNoUGxhY2UoaHRhYmxlLCBrZXkpOwoJaWYgKHRiZGF0YSAhPSBOVUxMKSB7CgkJaWYgKHN0cmNtcCh0YmRhdGEtPmtleSwga2V5KSA9PSAwKSB7CgkJCW1pbnNpemUgPSB0YmRhdGEtPnNpemUgPCBzaXplID8gdGJkYXRhLT5zaXplIDogc2l6ZTsKCQkJbWVtY3B5KGRhdGEsIHRiZGF0YS0+ZGF0YSwgbWluc2l6ZSk7CgkJCURlYnVnRG8ocHJpbnRmKCJnZXQoc3VjY2Vzcyk6ICVzXG4iLCBrZXkpKTsKCQkJcmV0dXJuIG1pbnNpemU7CgkJfQoJCXRiZGF0YSA9IHRiZGF0YS0+bmV4dDsKCX0KCURlYnVnRG8ocHJpbnRmKCJnZXQoZmFpbHVyZSk6ICVzXG4iLCBrZXkpKTsKCXJldHVybiAwOwp9CgovKioKICogSGFzaFRhYmxl44Gr44OH44O844K/44KS5pu444GN6L6844KA44CC5pei44Gr44Kt44O85ZCN44Gu44OH44O844K/44GM44GC44KL5aC05ZCI44Gv5LiK5pu444GN44GZ44KL44CCCiAqIEBwYXJhbSBodGFibGUKICogQHBhcmFtIGtleQogKiBAcGFyYW0gZGF0YQogKiBAcGFyYW0gc2l6ZQogKiBAcmV0dXJuCiAqLwppbnQgc2V0RGF0YUludG9IYXNoVGFibGUoTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXksIGNvbnN0IHZvaWQgKmRhdGEsIGNvbnN0IGludCBzaXplKSB7CglpbnQgbGVuOwoJaW50IHJldCA9IDE7Cgl2b2lkICp0ZW1wOwoJTFBUYWJsZURhdGEgKnB0YmRhdGE7CglpZiAoaHRhYmxlID09IE5VTEwgfHwga2V5ID09IE5VTEwgfHwgZGF0YSA9PSBOVUxMIHx8IHNpemUgPCAxKSB7CgkJcmV0dXJuIDA7IC8qIOW8leaVsOOCqOODqeODvCAqLwoJfQoJcHRiZGF0YSA9IHNlYXJjaFBsYWNlKGh0YWJsZSwga2V5KTsKCWlmICgqcHRiZGF0YSA9PSBOVUxMKSB7CgkJKnB0YmRhdGEgPSAoTFBUYWJsZURhdGEpY2FsbG9jKDEsIHNpemVvZihUYWJsZURhdGEpKTsKCQlpZiAoKnB0YmRhdGEgPT0gTlVMTCkgewoJCQlyZXR1cm4gMDsgLyog44Oh44Oi44Oq56K65L+d5aSx5pWXICovCgkJfQoJCSgqcHRiZGF0YSktPmtleSA9IChjaGFyICopY2FsbG9jKGxlbiwgc2l6ZW9mKGNoYXIpKTsKCQlpZiAoKCpwdGJkYXRhKS0+a2V5ID09IE5VTEwpIHsKCQkJZnJlZSgqcHRiZGF0YSk7CgkJCSpwdGJkYXRhID0gTlVMTDsKCQkJcmV0dXJuIDA7IC8qIOODoeODouODqueiuuS/neWkseaVlyAqLwoJCX0KCQkoKnB0YmRhdGEpLT5kYXRhID0gY2FsbG9jKHNpemUsIDEpOwoJCWlmICgoKnB0YmRhdGEpLT5kYXRhID09IE5VTEwpIHsKCQkJZnJlZSgoKnB0YmRhdGEpLT5rZXkpOwoJCQlmcmVlKCpwdGJkYXRhKTsKCQkJKnB0YmRhdGEgPSBOVUxMOwoJCQlyZXR1cm4gMDsgLyog44Oh44Oi44Oq56K65L+d5aSx5pWXICovCgkJfQoJCWxlbiA9IHN0cmxlbihrZXkpICsgMTsKCQltZW1jcHkoKCpwdGJkYXRhKS0+a2V5LCBrZXksIGxlbik7CgkJKCpwdGJkYXRhKS0+c2l6ZSA9IHNpemU7CgkJKysoaHRhYmxlLT5jb3VudCk7CgkJRGVidWdEbyhwcmludGYoInNldC9uZXcoc3VjY2Vzcyk6ICVzXG4iLCBrZXkpKTsKCX0gZWxzZSB7CgkJaWYgKCgqcHRiZGF0YSktPnNpemUgIT0gc2l6ZSkgewoJCQl0ZW1wID0gcmVhbGxvYygoKnB0YmRhdGEpLT5kYXRhLCBzaXplKTsKCQkJaWYgKHRlbXAgPT0gTlVMTCkgewoJCQkJcmV0dXJuIDA7IC8qIOODoeODouODqueiuuS/neWkseaVlyAqLwoJCQl9CgkJCSgqcHRiZGF0YSktPmRhdGEgPSB0ZW1wOwoJCQkoKnB0YmRhdGEpLT5zaXplID0gc2l6ZTsKCQl9CgkJcmV0ID0gMjsKCQlEZWJ1Z0RvKHByaW50Zigic2V0L3VwZGF0ZShzdWNjZXNzKTogJXNcbiIsIGtleSkpOwoJfQoJbWVtY3B5KCgqcHRiZGF0YSktPmRhdGEsIGRhdGEsIHNpemUpOwoJcmV0dXJuIHJldDsKfQoKLyoqCiAqIEhhc2hUYWJsZeWGheOBruaMh+WumuOCreODvOWQjeOBruODh+ODvOOCv+OCkuWJiumZpOOBmeOCi+OAggogKiBAcGFyYW0gaHRhYmxlIEhhc2hUYWJsZeOAggogKiBAcGFyYW0ga2V5ICAgIOOCreODvOWQjeOAggogKiBAcmV0dXJuIOWJiumZpOOBp+OBjeOBn+OCiSgxKeOAgeWkseaVl+OBl+OBn+OCiSgwKeOAggogKi8KaW50IHJlbW92ZURhdGFGcm9tSGFzaFRhYmxlKExQSGFzaFRhYmxlIGh0YWJsZSwgY29uc3QgY2hhciAqa2V5KSB7CglMUFRhYmxlRGF0YSAqcHRiZGF0YTsKCUxQVGFibGVEYXRhIHRiZGF0YTsKCWlmIChodGFibGUgPT0gTlVMTCB8fCBrZXkgPT0gTlVMTCkgewoJCXJldHVybiAwOyAvKiDjgazjgovjgb0gKi8KCX0KCXB0YmRhdGEgPSBzZWFyY2hQbGFjZShodGFibGUsIGtleSk7CglpZiAoKnB0YmRhdGEgIT0gTlVMTCkgewoJCXRiZGF0YSA9ICpwdGJkYXRhOwoJCSpwdGJkYXRhID0gdGJkYXRhLT5uZXh0OwoJCXJlbGVhc2VUYWJsZURhdGEodGJkYXRhLCAwKTsKCQktLShodGFibGUtPmNvdW50KTsKCQlEZWJ1Z0RvKHByaW50ZigicmVtb3ZlKHN1Y2Nlc3MpOiAlc1xuIiwga2V5KSk7CgkJcmV0dXJuIDE7Cgl9CglEZWJ1Z0RvKHByaW50ZigicmVtb3ZlKGZhaWx1cmUpOiAlc1xuIiwga2V5KSk7CglyZXR1cm4gMDsKfQoKLyoqCiAqIEhhc2hUYWJsZeWGheOBq+OCreODvOWQjeOBruODh+ODvOOCv+OBjOWtmOWcqOOBmeOCi+OBi+abuOOBj+OBq+OBmeOCi+OAggogKiBAcGFyYW0gaHRhYmxlIEhhc2hUYWJsZeOAggogKiBAcGFyYW0ga2V5ICAgIOaOouOBmeOCreODvOWQjeOAggogKiBAcmV0dXJuIOWtmOWcqOOBmeOCjOOBsCgxKeOAgeWtmOWcqOOBl+OBquOBkeOCjOOBsCgwKeOAggogKi8KaW50IGV4aXN0S2V5SW5IYXNoVGFibGUoTFBIYXNoVGFibGUgaHRhYmxlLCBjb25zdCBjaGFyICprZXkpIHsKCWlmIChodGFibGUgPT0gTlVMTCB8fCBrZXkgPT0gTlVMTCkgewoJCXJldHVybiAwOyAvKiDjgazjgovjgb0gKi8KCX0KCXJldHVybiAqc2VhcmNoUGxhY2UoaHRhYmxlLCBrZXkpICE9IE5VTEw7Cn0KCi8qKgogKiBIYXNoVGFibGXlhoXjga7jg4fjg7zjgr/mlbDjgpLov5TjgZnjgIIKICogQHBhcmFtIGh0YWJsZSBIYXNoVGFibGXjgIIKICogQHJldHVybiDjg4fjg7zjgr/mlbDjgIIKICovCmludCBjb3VudERhdGFJbkhhc2hUYWJsZShMUEhhc2hUYWJsZSBodGFibGUpIHsKCWlmIChodGFibGUgPT0gTlVMTCkgewoJCXJldHVybiAwOyAvKiDjgazjgovjgb0gKi8KCX0KCXJldHVybiBodGFibGUtPmNvdW50Owp9CgovKioKICogSGFzaFRhYmxl5YaF44Gu44Kt44O85ZCN44KS5YWo44Gm5Y+W5b6X44GZ44KL44CCCiAqIEBwYXJhbSBodGFibGUKICogQHBhcmFtIGZ1bmMKICogQHJldHVybgogKi8KaW50IGdldEFsbEtleXNJbkhhc2hUYWJsZShjb25zdCBMUEhhc2hUYWJsZSBodGFibGUsIGludCAoKmZ1bmMpKGNvbnN0IGNoYXIgKmtleSkpIHsKCWludCBpOwoJaW50IHJldDsKCWludCB0YWJsZXNpemU7CglMUFRhYmxlRGF0YSAqcHRiZGF0YTsKCUxQVGFibGVEYXRhIHRiZGF0YTsKCWlmIChodGFibGUgPT0gTlVMTCB8fCBmdW5jID09IE5VTEwpIHsKCQlyZXR1cm4gMDsKCX0KCURlYnVnRG8ocHJpbnRmKCJhbGxrZXkoc3RhcnQpXG4iKSk7CglwdGJkYXRhID0gaHRhYmxlLT50YWJsZTsKCXRhYmxlc2l6ZSA9IGh0YWJsZS0+dGFibGVzaXplOwoJZm9yIChpID0gMDsgaSA8IHRhYmxlc2l6ZTsgKytpKSB7CgkJdGJkYXRhID0gKnB0YmRhdGE7CgkJd2hpbGUgKHRiZGF0YSAhPSBOVUxMKSB7CgkJCXJldCA9ICgqZnVuYykodGJkYXRhLT5rZXkpOwoJCQlpZiAocmV0KSB7CgkJCQlEZWJ1Z0RvKHByaW50ZigiYWxsa2V5KHN0b3ApXG4iKSk7CgkJCQlyZXR1cm4gMjsKCQkJfQoJCQl0YmRhdGEgPSB0YmRhdGEtPm5leHQ7CgkJfQoJCSsrcHRiZGF0YTsKCX0KCURlYnVnRG8ocHJpbnRmKCJhbGxrZXkoZG9uZSlcbiIpKTsKCXJldHVybiAxOwp9CgovKiArKysgc3RhdGljIGZ1bmN0aW9ucyArKysgKi8KCi8qKgogKiDjg4/jg4Pjgrfjg6XplqLmlbDjgILjgq3jg7zlkI3jgYvjgonjg4/jg4Pjgrfjg6XlgKTjgpLnlJ/miJDjgZnjgovjgIIKICogQHBhcmFtIGtleSAgICAgICAg44Kt44O85ZCN44CCCiAqIEBwYXJhbSB0YWJsZXNpemUgIOODj+ODg+OCt+ODpeWApOOBruWItumZkOWApOOAggogKiBAcmV0dXJuIOODj+ODg+OCt+ODpeWApOOAggogKi8KaW50IGhhc2goY29uc3QgY2hhciAqa2V5LCBjb25zdCBpbnQgdGFibGVzaXplKSB7CglpbnQgaTsKCWludCB2ID0gKGludCkqa2V5OwoJZm9yIChpID0gMDsgaSA8IEhBU0hfREVFUCAmJiAqa2V5ICE9ICdcMCc7IGkrKykgewoJCXYgXj0gKGludCkoKmtleSkgKiAoaW50KSgqKGtleSArIDEpKTsKCQkrK2tleTsKCX0KCXJldHVybiB2ICUgdGFibGVzaXplOwp9CgovKioKICogSGFzaFRhYmxl44GL44KJ44Kt44O85ZCN44Gu44OH44O844K/44KS5qC857SN44GZ44KL5aC05omAKOOCouODieODrOOCuSnjgpLmjqLjgZnjgIIKICogQHBhcmFtIGh0YWJsZSDjgq3jg7zlkI3jgpLmjqLjgZlIYXNoVGFibGXjgIIKICogQHBhcmFtIGtleSAgICDmjqLjgZnjgq3jg7zlkI3jgIIKICogQHJldHVybiDmoLzntI3jgZXjgozjgabjgovloLTmiYAo44Ki44OJ44Os44K5KeOAggogKi8KTFBUYWJsZURhdGEgKnNlYXJjaFBsYWNlKGNvbnN0IExQSGFzaFRhYmxlIGh0YWJsZSwgY29uc3QgY2hhciAqa2V5KSB7CglpbnQgaCA9IGhhc2goa2V5LCBodGFibGUtPnRhYmxlc2l6ZSk7CglMUFRhYmxlRGF0YSAqcHRiZGF0YSA9IGh0YWJsZS0+dGFibGUgKyBoOwoJd2hpbGUgKCpwdGJkYXRhICE9IE5VTEwpIHsKCQlpZiAoc3RyY21wKCgqcHRiZGF0YSktPmtleSwga2V5KSA9PSAwKSB7CgkJCWJyZWFrOwoJCX0KCQlwdGJkYXRhID0gJigqcHRiZGF0YSktPm5leHQ7Cgl9CglEZWJ1Z0RvKHByaW50ZigiaGFzaCglZCk6ICVzXG4iLCBoLCBrZXkpKTsKCXJldHVybiBwdGJkYXRhOwp9CgovKioKICogVGFibGVEYXRh44KS44Oh44Oi44Oq44GL44KJ6Kej5pS+44GZ44KL44CCCiAqIEBwYXJhbSBwdGJkYXRhIOino+aUvuOBmeOCi+ODh+ODvOOCv+OAggogKiBAcGFyYW0gY2hhaW4gICBuZXh044Gr44GC44KLVGFibGVEYXRh44KC6Kej5pS+44GZ44KLKDEp44GL44GX44Gq44GEKDAp44GL44CCCiAqLwp2b2lkIHJlbGVhc2VUYWJsZURhdGEoTFBUYWJsZURhdGEgdGJkYXRhLCBpbnQgY2hhaW4pIHsKCWlmICh0YmRhdGEgPT0gTlVMTCkgewoJCXJldHVybjsKCX0KCWlmIChjaGFpbikgewoJCXJlbGVhc2VUYWJsZURhdGEodGJkYXRhLT5uZXh0LCBjaGFpbik7Cgl9CglEZWJ1Z0RvKHByaW50ZigicmVsZWFzZSBUYWJsZURhdGE6ICVzXG4iLCB0YmRhdGEtPmtleSkpOwoJZnJlZSh0YmRhdGEtPmtleSk7CglmcmVlKHRiZGF0YS0+ZGF0YSk7CglmcmVlKHRiZGF0YSk7Cn0=