diff WindowsOnly/WinScript2/vm_value.h @ 0:db40c85cad7a default tip

upload sample source
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 May 2011 03:11:59 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WindowsOnly/WinScript2/vm_value.h	Mon May 09 03:11:59 2011 +0900
@@ -0,0 +1,185 @@
+#ifndef	__vm_value_h__
+#define	__vm_value_h__
+
+#include <iostream>
+#include <exception>
+#include <string>
+
+namespace vm {
+
+	// 参照カウンタ付きstring
+	class string {
+	  public:
+		string(): ref_(0)
+		{
+		}
+		string(const std::string &str): ref_(1), str_(str)
+		{
+		}
+
+		void addref()
+		{
+			ref_++;
+		}
+
+		void release()
+		{
+			if (--ref_ == 0)
+				delete this;
+		}
+
+	  public:
+		int ref_;
+		std::string str_;
+	} ;
+
+	// 変数
+	class value {
+		enum	{
+			type_integer,
+			type_string,
+		} ;
+
+	  public:
+		value()
+		{
+			s_ = 0;
+			type_ = type_integer;
+		}
+
+		value(int ival)
+		{
+			i_ = ival;
+			type_ = type_integer;
+		}
+
+		value(const std::string &str)
+		{
+			s_ = new string(str);
+			type_ = type_string;
+		}
+
+		value(string *p)
+		{
+			s_ = p;
+			type_ = type_string;
+		}
+
+		~value()
+		{
+			clear();
+		}
+
+		value(const value &a)
+		{
+			copy(a);
+		}
+
+		value& operator=(const value &a)
+		{
+			if (this == &a)
+				return *this;
+
+			clear();
+			copy(a);
+
+			return *this;
+		}
+
+		void clear()
+		{
+			if (type_ == type_string)
+				s_->release();
+		}
+
+		void copy(const value &a)
+		{
+			type_ = a.type_;
+			s_ = a.s_;
+			if (type_ == type_string)
+				s_->addref();
+		}
+
+	  public:
+		union {
+			string *s_;
+			int i_;
+		} ;
+		char type_;
+	} ;
+
+	class stack_overflow: public std::exception {
+	  public:
+		const char *what() const throw()
+		{
+			return "stack overflow";
+		}
+	} ;
+
+	// 固定サイズのスタック
+	// スタックオーバーフローの場合は例外を送出
+
+	template< typename Ty, int Size >
+	class stack {
+	  public:
+		stack(): size_(0)
+		{
+		}
+
+		~stack()
+		{
+			resize(0);
+		}
+
+		void push(const Ty& value)
+		{
+			if (Size <= size_)
+				throw stack_overflow();
+			*(::new(data_[size_++]) Ty) = value;
+		}
+
+		void pop()
+		{
+			((Ty *)data_[--size_])->~Ty();
+		}
+
+		void pop(int count)
+		{
+			resize(size_ - count);
+		}
+
+		void resize(int newsize)
+		{
+			int oldsize = size_;
+
+			if (oldsize > newsize) {
+				for (int i = newsize; i < oldsize; ++i)
+					((Ty *)data_[i])->~Ty();
+			}
+			if (oldsize < newsize) {
+				if (Size < newsize)
+					throw stack_overflow();
+				for (int i = oldsize; i < newsize; ++i)
+					::new(data_[i]) Ty;
+			}
+			size_ = newsize;
+		}
+
+		const Ty& top() const { return *(const Ty *)data_[size_ - 1]; }
+		Ty& top() { return *(Ty *)data_[size_ - 1]; }
+
+		bool overflow() const { return size_ >= Size; }
+		bool empty() const { return size_ == 0; }
+		int size() const { return size_; }
+
+		const Ty& operator[](int index) const { return *(const Ty *)data_[index]; }
+		Ty& operator[](int index) { return *(Ty *)data_[index]; }
+
+	  protected:
+		char data_[Size][sizeof(Ty)];
+		int size_;
+	} ;
+
+}	// namespace
+
+#endif