D,
pasted
on May 30:
|
|
import std.stdio, std.string;
// 文字列のエスケープを行う。
string c_escape(string s) {
string t;
foreach(c; s) {
switch(c) {
case '"': t ~= "\\\""; break;
case '\\': t ~= "\\\\"; break;
case '\a': t ~= "\\a"; break;
case '\b': t ~= "\\b"; break;
case '\f': t ~= "\\f"; break;
case '\n': t ~= "\\n"; break;
case '\r': t ~= "\\r"; break;
case '\t': t ~= "\\t"; break;
case '\v': t ~= "\\v"; break;
case '\0': t ~= "\\0"; break;
default:
if (c <= 0x7F) {
t ~= c;
} else {
t ~= "\\x";
t ~= hexdigits[c >>> 4];
t ~= hexdigits[c & 0xF];
}
}
}
return t;
}
// 基底クラス。
abstract class RbObject {
/*C++と違って、クラスはデフォルトpublic*/
// オブジェクトID。
int m_id; //public!
// パス(インデックスリスト)。
size_t[] m_path; //public!
// 次のオブジェクトID。
static int s_idNext = 0; //public!
protected:
this() {
m_id = s_idNext;
s_idNext++;
}
public:
// 出力する。
version(none) abstract void write(); //toString()をオーバーライドしよう
version(none) void writeln() {
write();
writef("\n");
}
// 複製を作る。
abstract RbObject clone();
// 型名を返す。
version(none) abstract string type(); //.classinfo.nameを使おう
// 比較する。
abstract bool opEquals(RbObject);
abstract int opCmp(RbObject o);
// オブジェクトID。
int id() {
return m_id;
}
void id(int id) {
m_id = id;
}
// パス。
size_t[] path() {
return m_path;
}
void path(size_t[] p) {
m_path = p;
}
void setRoot() {
size_t[] a;
path(a);
}
}
// 整数クラス。
class RbInteger : public RbObject {
int m_i; //public!
public:
this(int i) {
super();
m_i = i;
}
// int型へのキャスト。
int opCast() {
return m_i;
}
// 比較。
bool opEquals(RbInteger i) {
return opEquals(i.m_i);
}
version(none) bool opEquals(RbString) { //不要
return false;
}
version(none) bool opEquals(RbArray) { //不要
return false;
}
bool opEquals(int i) {
return m_i == i;
}
bool opEquals(RbObject o) { //この重複コードどうしようか・・・
if (this.classinfo.name == o.classinfo.name) return false;
return opEquals(cast(typeof(this))o);
}
// RbInteger < RbString < RbArray この定義は好ましくない!
int opCmp(RbInteger i) {
return opCmp(i.m_i);
}
int opCmp(RbString) {
return -1;
}
int opCmp(RbArray) {
return -1;
}
int opCmp(int i) {
if (m_i < i)
return -1;
if (m_i > i)
return 1;
return 0;
}
int opCmp(RbObject o) { //この重複コードもどうしようか・・・w
string oname = o.classinfo.name;
if(oname == RbInteger.classinfo.name)
{
return opCmp(cast(RbInteger)o);
}
else if(oname == RbString.classinfo.name)
{
return opCmp(cast(RbString)o);
}
else if(oname == RbArray.classinfo.name)
{
return opCmp(cast(RbArray)o);
}
else
{
assert(false);
}
}
version(D_Version2) //D1非対応のコード
{
// 2項演算子。
RbInteger opBinary(string s)(RbInteger i) {
return opBinary(s)(i.m_i);
}
RbInteger opBinary(string s)(int i) {
static if (s == "+") {
return new RbInteger(m_i + i);
}
static if (s == "-") {
return new RbInteger(m_i - i);
}
static if (s == "*") {
return new RbInteger(m_i * i);
}
static if (s == "/") {
return new RbInteger(m_i / i);
}
static if (s == "%") {
return new RbInteger(m_i % i);
}
}
}
// 代入。
RbInteger opAssign(int i) {
m_i = i;
return this;
}
RbInteger opOpAssign(string s)(RbInteger i) {
return opOpAssign(s)(i.m_i);
}
RbInteger opOpAssign(string s)(int i) {
static if (s == "+=") {
m_i += i;
}
static if (s == "-=") {
m_i -= i;
}
static if (s == "*=") {
m_i *= i;
}
static if (s == "/=") {
m_i /= i;
}
static if (s == "%=") {
m_i %= i;
}
return this;
}
override string toString() {
return format(m_i);
}
RbInteger clone() {
return new RbInteger(m_i);
}
}
// 文字列クラス。
class RbString : public RbObject {
string m_s; //public!
public:
this(string s) {
super();
m_s = s;
}
// string型へのキャスト。
string opCast() {
return m_s;
}
// 比較。
version(none) bool opEquals(RbInteger i) {
return false;
}
bool opEquals(RbString s) {
return opEquals(s.m_s);
}
version(none) bool opEquals(RbArray) {
return false;
}
bool opEquals(string s) {
return m_s == s;
}
bool opEquals(RbObject o) {
if (this.classinfo.name == o.classinfo.name) return false;
return opEquals(cast(typeof(this))o);
}
// RbInteger < RbString < RbArray
int opCmp(RbInteger) {
return 1;
}
int opCmp(RbString s) {
return opCmp(s.m_s);
}
int opCmp(RbArray) {
return -1;
}
int opCmp(string s) {
if (m_s < s)
return -1;
if (m_s > s)
return 1;
return 0;
}
int opCmp(RbObject o) {
string oname = o.classinfo.name;
if(oname == RbInteger.classinfo.name)
{
return opCmp(cast(RbInteger)o);
}
else if(oname == RbString.classinfo.name)
{
return opCmp(cast(RbString)o);
}
else if(oname == RbArray.classinfo.name)
{
return opCmp(cast(RbArray)o);
}
else
{
assert(false);
}
}
// インデックス演算子。
char opIndex(size_t i) { return m_s[i]; }
char opIndexAssign(char c, size_t i) {
m_s[i] = c;
return m_s[i];
}
// スライス演算子。
RbString opSlice(size_t i, size_t j) {
return new RbString(m_s[i .. j]);
}
void opSliceAssign(char c) {
m_s[] = c;
}
void opSliceAssign(char c, size_t i, size_t j) {
m_s[i .. j] = c;
}
// 代入。
RbString opAssign(string s) {
m_s = s;
return this;
}
RbString opOpAssign(string op)(RbString s) {
return opOpAssign(op)(s.m_s);
}
RbString opOpAssign(string op)(string s) {
static if (op == "~=") {
m_s ~= s;
}
return this;
}
override string toString() {
return format("\"" ~ c_escape(m_s) ~ "\"");
}
RbString clone() {
return new RbString(m_s);
}
}
// 配列クラス。
class RbArray : public RbObject {
RbObject[] m_objects; //public!
public:
this() {
super();
}
this(RbObject[] objects ...) {
super();
m_objects = objects;
}
// 比較。
version(none) bool opEquals(RbInteger) {
return false;
}
version(none) bool opEquals(RbString) {
return false;
}
bool opEquals(RbArray ra) {
if (m_objects.length != ra.m_objects.length)
return false;
size_t len = m_objects.length;
for(size_t i = 0; i < len; i++) {
if (m_objects[i] != ra.m_objects[i])
return false;
}
return true;
}
bool opEquals(RbObject o) {
if (this.classinfo.name == o.classinfo.name) return false;
return opEquals(cast(typeof(this))o);
}
// RbInteger < RbString < RbArray
int opCmp(RbInteger) {
return 1;
}
int opCmp(RbString) {
return 1;
}
int opCmp(RbArray ra) {
size_t len;
if (m_objects.length < ra.m_objects.length)
len = m_objects.length;
else
len = ra.m_objects.length;
for(size_t i = 0; i < len; i++) {
if (m_objects[i] > ra.m_objects[i])
return 1;
if (m_objects[i] < ra.m_objects[i])
return -1;
}
return cast(int)m_objects.length - cast(int)ra.m_objects.length;
}
int opCmp(RbObject o) {
string oname = o.classinfo.name;
if(oname == RbInteger.classinfo.name)
{
return opCmp(cast(RbInteger)o);
}
else if(oname == RbString.classinfo.name)
{
return opCmp(cast(RbString)o);
}
else if(oname == RbArray.classinfo.name)
{
return opCmp(cast(RbArray)o);
}
else
{
assert(false);
}
}
// インデックス演算子。
RbObject opIndex(size_t i) { return m_objects[i]; }
RbObject opIndexAssign(RbObject w, size_t i) {
m_objects[i] = w;
return m_objects[i];
}
// スライス演算子。
RbObject[] opSlice() { return m_objects; }
RbObject[] opSlice(size_t i, size_t j) { return m_objects[i .. j]; }
void opSliceAssign(RbObject o) {
m_objects[] = o;
}
void opSliceAssign(RbObject o, size_t i, size_t j) {
m_objects[i .. j] = o;
}
// パス(インデックスリスト)からオブジェクトを得る。
RbObject objectFromPath(size_t[] indexList ...) {
RbObject o = null;
RbArray array = this;
size_t i = 0;
if (i < indexList.length) {
for(;;) {
o = array[indexList[i]];
i++;
if (i == indexList.length)
break;
array = cast(RbArray)o;
}
}
return o;
}
// パス(インデックスリスト)から整数を得る。
RbInteger integerFromPath(size_t[] indexList ...) {
return cast(RbInteger)objectFromPath(indexList);
}
// パス(インデックスリスト)から文字列を得る。
RbString stringFromPath(size_t[] indexList ...) {
return cast(RbString)objectFromPath(indexList);
}
// パス(インデックスリスト)から配列を得る。
RbArray arrayFromPath(size_t[] indexList ...) {
return cast(RbArray)objectFromPath(indexList);
}
override string toString() {
char[] str;
str ~= "[";
if (m_objects.length > 0) {
str ~= m_objects[0].toString();
for(size_t i = 1; i < m_objects.length; i++) {
str ~= ", ";
str ~= m_objects[i].toString();
}
}
str ~= "]";
return cast(string) str;
}
RbArray clone() {
RbObject[] objects;
objects.length = m_objects.length;
for(size_t i = 0; i < m_objects.length; i++) {
objects[i] = m_objects[i].clone();
}
return new RbArray(objects);
}
size_t length() {
return m_objects.length;
}
// ソートする。
void sort() {
if (m_objects.length <= 1) return;
for(size_t i = 0; i < m_objects.length; i++) {
if (m_objects[i].classinfo.name == RbArray.classinfo.name) {
(cast(RbArray)m_objects[i]).sort();
}
}
for(size_t i = 0; i < m_objects.length - 1; i++) {
for(size_t j = i + 1; j < m_objects.length; j++) {
if (m_objects[i] > m_objects[j]) {
RbObject tmp = m_objects[i];
m_objects[i] = m_objects[j];
m_objects[j] = tmp;
}
}
}
}
// パス。
void path(size_t[] p) {
super.path(p);
for(size_t i = 0; i < m_objects.length; i++) {
m_objects[i].path(p ~ i);
}
}
}
// メイン関数。
int main() {
// [34, "test2", 12, ["test", 324], [11]]
RbArray ra = new RbArray(
new RbInteger(34),
new RbString("test2"),
new RbInteger(12),
new RbArray(new RbString("test"), new RbInteger(324)),
new RbArray(new RbInteger(11))
);
writef("newed: ");
writefln(ra);
RbArray ra2 = ra.clone();
writef("cloned: ");
writefln(ra2);
delete ra;
writef("[3, 1]: ");
writefln(ra2.objectFromPath(3, 1));
ra2.sort();
writef("sorted: ");
writefln(ra2);
delete ra2;
writefln("ending");
fflush(stdout);
return 0;
}
|
Output:
|
|
newed: [34, "test2", 12, ["test", 324], [11]]
cloned: [34, "test2", 12, ["test", 324], [11]]
[3, 1]: 324
sorted: [12, 34, "test2", [11], [324, "test"]]
ending
|
|