C言語でCMSを書く その2 CMSのための構造体

記事
IT・テクノロジー
HTMLのもととなる構造体 element 型
さて、前回のブログは、CMSについてHTMLの重大な問題について、ほぼ愚痴としてぐちぐち書きました。
今回は、もっともっと具体的な話になります。
HTMLをベタ書きしてWEBページを造ることはほとんどなくなり、HTMLというのは、いわば裏にかくれたWEB用ページ記述言語になっています。しかも、WEBページを生成する CMS 自身がHTMLを生成することもなくなりつつあり、HTMLを生成しているのは、WEBページ内に埋め込まれた、あるいはWEBページからリンクされたJavaScriptのスクリプトが、なんらかのページの元となるデータ(構造化されたコンテンツとかいうものかな)から、HTMLを生成する、という形がほとんどです。
最初のブログ↓にも書きましたが、WEBサイトというのは、多層構造になっています。
まず、WEBサイトのいろいろなページの元になるデータがデータベースサーバに入っています。そして、ブラウザからのリクエストでCGIが、リクエストされたページの元になるデータをデータベースに問い合わせて、そしてデータベース中のページの元からHTMLページを作り出すわけですね。ブラウザからのリクエストの中には、データベースの内容を書き換えることを要求するものもあって、その場合は、CGIがデータベースの内容の更新をする問い合わせをデータベースに対して行う、というような構造です。

ということで、データベースの中には、WEBページの元になるデータを表現する仕組みが必要です。そのWEBページの元になるデータとはどういう構造をもったデータ構造か、というのが今回のブログの内容です。
WEBページの構成という場合、だいたいページの左右とか上下とかにメニューとかタブとかがあって、そこからサイト内の関連ページに飛んでいけるようになっていて、そして、中心にどかっとメインのフレームっていうか、そういうのがあって、そこにテキストと画像と動画というようなものがあります。
たとえば、弊社のプラットフォームのHOTPortで、投稿されたタイトル(ブログとか記事とかの意味)を開いた場合の例は、以下の画像です。
PageSample1.png

左右や上下にあるようなメニューやタブなどは、だいたいCGIやCMS内にその部分を生成するHTMLを持っている場合がほとんどですので、ページの元になるデータは、その中央にどかっと存在するメインのフレームを記述できればよいことになります。つまり、概ねテキストで、テキストの中に画像や動画などが埋め込まれていたり、あるいは、他の関連ページへのリンクがサムネイル付きで表示されたりする、っていうようなものです。
そうすると、それを表現するデータ構造は、基本的にいわゆるリスト構造というやつで、しかも、入れ子構造が可能なリスト構造になります。つまり、JSON (JavaScript Object Notation)や、XMLで表現されるようなデータ構造です。
HOTPortでは、それは、element型という構造体になっています。element型は、データ(オブジェクトというべきか)の配列で、その配列の中は、タグで参照できるようになっています。しかも、データ(オブジェクト)のデータ構造(型)も指定できるようになっています。
まずは、型の定義を見てみます。

----ここから----
//element型の配列要素となる tagBlock型

typedef struct          tagBlock
{
/ハッシュタグは文字列で、これで参照できる。
  hashTag*              HashTag;
//内容が更新されたときのUNIX時間
  int64                 UpdateTime;
//内容の型を示すstructId型の構造体へのポインタ
//structId型は、仮想関数テーブルでもある。
  structId*             StructId;
//内容が更新された場合、以前の内容を保存するためのもの
  tagBlock*             Archive;
//データを入れる本体となる、block ユニオン
  block                 Block;
};

//element型の構造体
typedef struct          element
{
//配列要素の数
  int32                 NumTagBlocks;
//用意されている配列要素の最大数
  int32                 MaxNumTagBlocks;
//tagBlockの配列へのポインタ
  tagBlock*             TagBlockArray;
};
----ここまで----
まず、element構造体の中のTagBlockArrayに、elementの中身となるタグ付きデータを保存します。この配列のサイズはいくらでも大きくできるようになっています。つまり、確保されている配列の大きさはMaxNumTagBlocksであり、そのうち、内容が書き込まれたtagBlockは、NumTagBlocks だということです。で、書き込まれたtagBlockが、MaxNumTagBlocksに達すると、自動的に、MaxNumTagBlokcsを二倍にして、新しい内容の書き込みに備えます。element型データ構造を最初に作ったときは、MaxNumTagBlocksは、8に設定されます。
tagBlock型の構造体には、ハッシュタグ(HashTag)があって(なくてもよい)、TagBlockArray配列の要素は、ハッシュタグで検索できます。そして、Blockという部分に内容のデータそのもの(128ビット長までの整数や浮動小数点数、複素数など)か、あるいはデータ(文字列、content型データなど)が格納されている領域へのポインタが格納されます。文字列はNULL('\0')で終了するのでサイズがわかりますが、content型は以下のようなデータ構造です。

----ここから----
typedef struct          content
//コンテントの名前(もとのファイル名など)
  char*                 Name;
//コンテントのタイプ。Content-Type と同じもの。
  char*                 Type;
//コンテントのサイズ。Content-Lengthと同じもの。
  size_t                Size;
//コンテントへの実体へのポインタ
  uint8*                UInt8Array;
};
----ここまで----
ここに、画像や動画、その他、ファイルなどが入ります。

element型構造体を扱う関数
element型に入っているデータを参照するときには、element_search()という関数があります。element_searchPathというのもあって、elementが入れ子になっているときに、親element の下のelementの下のデータを検索することもできます。概ね、element型の構造体は、ファイルシステムのディレクトリ(フォルダ)の構造とほとんど同じように使えます。

また、elementに新たなデータを加えるためには、element_addSubdata()という関数があります。このelement_addSubdata()はかなり頑張って作ったもので、最初はバグに悩まされました。っていうのは、たんに新しいデータを加えるのではなくて、既にあるデータにマージさせる形で追加できるようになっています。っていうのは、CMSに対応しているので、たとえば、すでに登録したコンテンツで、中に入っている画像だけを変更したい、という場合、既に入っている画像の部分をだけを変更し、他は入力されていないので、変更はしない、というようなことができるようになっています。このelement_addSubdata()は、行数が60行もあります。しかも、中で再帰呼び出しになっていたりします。

HOTPortでは、メインの文書ページは、パラグラフが一つまたは複数から構成されています。たとえば、サーバのトップページ、ユーザのホームページ(プロフィールページ)、投稿されたコンテンツのカバーページ(無料で読めるトップページ)は、パラグラフが一つだけ。サーバやユーザのポリシーページ、コンテンツの続きページ、有料ページは、複数のパラグラフを書き込むことができます。で、一つのパラグラフには文字は2千字、大きい画像(横幅いっぱい)が一枚、それから添付ファイル(動画、画像、データファイルなんでも)が一つ、そして、リンクはいくらでも書けます(文字数制限の範囲で)。
ですから、一つのパラグラフのデータ構造は、こんな感じになっています。
element Paragraph
{
 content BigImage;
 string MainText;
 content Content;
};

content, stringは、データ型を表し、BigImage, MainText, Contentは、ハッシュタグです。
で、複数のパラグラフからなる、たとえば、有料ページ(PaidPage)の場合は、以下のように、複数のパラグラフからなる以下のようなデータになっています。
element PaidPage
{
 element Par00;
 element Par01;
 element Par02;
 ......
};
実際のところ、C言語ではこういう感じにかけないわけで、中で関数をつかってプログラミングしないとデータ構造をかけませんが、ブラウザからform分でデータ構造を指定するときは、比較的簡単に投稿するデータなどが書けます。つまり、HTMLでこんな感じです。
<form .... >
<input type="hidden" name="Par00" value="!paragraph">
<input type="file" name="(content)Par00/BigImage">
<input name="Par00/MainText">
<input type="file" name="(content)Par00/Content">
<button type="submit">送信</button>
</form ...>
こうすると、ブラウザから、Par00のBigImageのファイルや、MainText、添付ファイルなどを受け取ることができるようになっています。そして、ブラウザからおくられてきた、multipart-formdata の部分は、自動的に element型に展開されて、それでデータベースの内容を更新することができるわけです。
いや、ここ、かなり頑張ったですよね。

まとめに変えて
ということで、今回は、C言語でCMSを書く上で重要な element型構造体について、御説明いたしました。次のステップは、というと、HTML生成と、CSSとの絡み、みたいな話になりそうです。そこは二回に分るかどうか。

ここで一部掲載したプログラムのソースコードは以下のサービスにて提供いたします。


サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す