コマンドを格納するために C でデータ構造を作成しています。これは、私が満足していないものに切り詰められたソースです。
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include "dbg.h"
#include "commandtree.h"
struct BranchList
{
CommandTree *tree;
BranchList *next;
};
struct CommandTree
{
wchar_t id; // wchar support actually has no memory cost due to the
bool term; // padding that would otherwise exist, and may in fact be
BranchList *list; // marginally faster to access due to its alignable size.
};
static inline BranchList *BranchList_create(void)
{
return calloc(1, sizeof(BranchList));
}
inline CommandTree *CommandTree_create(void)
{
return calloc(1, sizeof(CommandTree));
}
int CommandTree_putnw(CommandTree *t, const wchar_t *s, size_t n)
{
for(BranchList **p = &t->list;;)
{
if(!*p)
{
*p = BranchList_create();
if(errno == ENOMEM) return 1;
(*p)->tree = CommandTree_create();
if(errno == ENOMEM) return 1;
(*p)->tree->id = *s;
}
else if(*s != (*p)->tree->id)
{
p = &(*p)->next;
continue;
}
if(n == 1)
{
(*p)->tree->term = 1;
return 0;
}
p = &(*p)->tree->list;
s++;
n--;
}
}
int CommandTree_putn(CommandTree *t, const char *s, size_t n)
{
wchar_t *passto = malloc(n * sizeof(wchar_t));
mbstowcs(passto, s, n);
int ret = CommandTree_putnw(t, passto, n);
free(passto);
return ret;
}
これは完全にうまく機能しますが、ツリーがwchar_t
. CommandTree
のパディングにより7 バイト未満のデータ型が同じくらい多くのメモリを消費することに気付いたので、これを追加することにしましたが、コードを複製しないようCommandTree_putn
に、 wchar_t-supporting のロジックを再利用しましたCommandTree_putnw
。
char
ただし、とのサイズの違いにより、wchar_t
単に配列を渡すことはできません。を使用して変換しmbstowcs
、一時wchar_t *
を に渡す必要がありCommandTree_putnw
ます。これは最適ではありません。これはCommandTree_putn
、 が最も多く使用され、格納された文字列のメモリ使用量が 5 倍 ( sizeof (char)
~sizeof (char) + sizeof (wchar_t)
) になることを考えると、これらの多くが長いコマンドでインスタンス化される場合にスタックする可能性があります。
ロジックを含む 3 番目の関数を作成し、渡された文字列を aにsize_t
キャストする値に応じて、またはC が静的に型付けされていることを考えると、 、それぞれのタイプへのキャストを使用してロジックをほぼ複製する必要があり、これにより、「ロジックの単一インスタンス」のアイデアが台無しになります。void *
const char *
const wchar_t *
s
したがって、最終的に問題は、プログラム ロジックを 1 回だけ提供し、ラッパーconst char *
をconst wchar_t *
それぞれ渡すことができるかwchar_t *
ということです。const char *