view 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 source

#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