scpsection1.cs

来自「ecg tool kit for medical image retrieval」· CS 代码 · 共 1,473 行 · 第 1/3 页

CS
1,473
字号
/***************************************************************************
Copyright 2004-2005,2008, Thoraxcentrum, Erasmus MC, Rotterdam, The Netherlands

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Written by Maarten JB van Ettinger.

****************************************************************************/
using System;
using System.Runtime.InteropServices;
using Communication.IO.Tools;
using ECGConversion.ECGDemographics;

namespace ECGConversion.SCP
{
	/// <summary>
	/// Class contains section 1 (Header Information).
	/// </summary>
	public class SCPSection1 : SCPSection, IDemographic
	{
		// Fields that must be made empty for anonymous. (must be sorted from low to high)
		private static byte[] _AnonymousFields = {0, 1, 2, 3, 5, 30, 31};
		// Defined in SCP.
		private static byte[] _MustBePresent = {2, 14, 25, 26}; // defined in paragraph 5.4.3.1 of SCP
		private static byte[] _MultipleInstanceFields = {10, 13, 30, 32, 35}; // Must be sorted
		private static ushort _MaximumFieldLength = 64;
		private static byte[] _MaximumLengthExceptions = {13, 14, 15, 30, 35}; // Must be sorted
		private static ushort _ExceptionsMaximumLength = 128; // should be 80, but some scp file doen't use this maximum.
		private static byte _ManufactorField = 0xc8;
		private static ushort _SectionID = 1;
		private static byte _DemographicTerminator = 0xff;

		// ResizeSpeed for the array to store the Fields.
		private static int _ResizeSpeed = 8;

		// Part of the stored Data Structure.
		private int _NrFields = 0;
		private SCPHeaderField[] _Fields = null;
		protected override int _Read(byte[] buffer, int offset)
		{
			Init();
			int end = offset - Size + Length;
			while (offset < end)
			{
				SCPHeaderField field = new SCPHeaderField();
				field.Tag = (byte) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(field.Tag), true);
				offset += Marshal.SizeOf(field.Tag);
				if (field.Tag == _DemographicTerminator)
				{
					break;
				}
				else if ((offset + 2) > end)
				{
					_Empty();
					return 0x1;
				}
				field.Length = (ushort) BytesTool.readBytes(buffer, offset, Marshal.SizeOf(field.Length), true);
				offset += Marshal.SizeOf(field.Length);
				if ((offset + field.Length) > end)
				{
					_Empty();
					return 0x2;
				}
				field.Value = new byte[field.Length];
				offset += BytesTool.copy(field.Value, 0, buffer, offset, field.Length);
				Insert(field);
			}
			return 0x0;
		}
		protected override int _Write(byte[] buffer, int offset)
		{
			for (int loper=0;loper < _NrFields;loper++)
			{
				BytesTool.writeBytes(_Fields[loper].Tag , buffer, offset, Marshal.SizeOf(_Fields[loper].Tag), true);
				offset += Marshal.SizeOf(_Fields[loper].Tag);
				BytesTool.writeBytes(_Fields[loper].Length , buffer, offset, Marshal.SizeOf(_Fields[loper].Length), true);
				offset += Marshal.SizeOf(_Fields[loper].Length);
				offset += BytesTool.copy(buffer, offset, _Fields[loper].Value, 0, _Fields[loper].Length);
			}
			return 0x0;
		}
		protected override void _Empty()
		{
			_NrFields = 0;
			_Fields = null;
		}
		public override ushort getSectionID()
		{
			return _SectionID;
		}
		protected override int _getLength()
		{
			if (Works())
			{
				int sum = 0;
				for (int loper=0;loper < _NrFields;loper++)
				{
					sum += (Marshal.SizeOf(_Fields[loper].Tag) + Marshal.SizeOf(_Fields[loper].Length) + _Fields[loper].Length);
				}
				return ((sum % 2) == 0 ? sum : sum + 1);
			}
			return 0;
		}
		public override bool Works()
		{
			if (CheckInstances())
			{
				for (int loper=0;loper < _NrFields;loper++)
				{
					if ((_Fields[loper] == null)
					||  ((_Fields[loper].Value == null) && (_Fields[loper].Length != 0))
					||  ((_Fields[loper].Value != null) && (_Fields[loper].Value.Length != _Fields[loper].Length))
					||  ((_Fields[loper].Length > _MaximumFieldLength) && (_Fields[loper].Tag < _ManufactorField) && (!isException(_MaximumLengthExceptions, _Fields[loper].Tag) || (_Fields[loper].Length > _ExceptionsMaximumLength))))
					{
						return false;
					}
				}
				for (int loper=0;loper < _MustBePresent.Length;loper++)
				{
					if (_SearchField(_MustBePresent[loper]) < 0)
					{
						return false;
					}
				}
				return (_Fields[_NrFields - 1].Tag == 0xff) &&  (_Fields[_NrFields - 1].Length == 0);
			}
			return false;
		}
		/// <summary>
		/// Function to initialize a section 1. Only needed when not reading from buffer.
		/// </summary>
		public void Init()
		{
			_Empty();
			_Fields = new SCPHeaderField[_ResizeSpeed];
			_Fields[_NrFields++] = new SCPHeaderField(_DemographicTerminator, 0, null);
		}
		/// <summary>
		/// Function to insert a field into section.
		/// </summary>
		/// <param name="field">field to insert</param>
		/// <returns>0 on success</returns>
		public int Insert(SCPHeaderField field)
		{
			if ((field != null)
			&&  (field.Tag != _DemographicTerminator)
			&&	(_Fields != null)
			&&  (_NrFields <= _Fields.Length)
			&&  (_Fields[_NrFields - 1].Tag == _DemographicTerminator))
			{
				if ((field.Length == 0)
				||	((field.Value != null)
				&&	 (field.Length <= field.Value.Length)))
				{
					int p1 = _SearchField(field.Tag);
					// If field exist must override or can be an multiple instances.
					if (p1 >= 0)
					{
						// If multiple instaces field, add field as last of this kind of field.
						if (isException(_MultipleInstanceFields, field.Tag))
						{
							// Resize if space is needed.
							if (_NrFields == _Fields.Length)
							{
								Resize();
							}
							// Find last of this kind.
							for (;(p1 < _NrFields) && (_Fields[p1].Tag == field.Tag);p1++);
							// Make space in array for field.
							for (int loper = _NrFields;loper > p1;loper--)
							{
								_Fields[loper] = _Fields[loper - 1];
							}
							_Fields[p1] = field;
							_NrFields++;
						}
						else
						{
							// Overwrite existing field.
							_Fields[p1] = field;
						}
					}
					else
					{
						// Resize if space is needed
						if (_NrFields == _Fields.Length)
						{
							Resize();
						}
						int p2 = _InsertSearch(field.Tag);
						// Make space to insert.
						for (int loper = _NrFields;loper > p2;loper--)
						{
							_Fields[loper] = _Fields[loper - 1];
						}
						_Fields[p2] = field;
						_NrFields++;
					}
					return 0x0;
				}
				return 0x2;
			}
			return 0x1;
		}
		/// <summary>
		/// Function to remove a certain field from section.
		/// </summary>
		/// <param name="tag">tag of field.</param>
		/// <returns>0 on success</returns>
		public int Remove(byte tag)
		{
			if ((tag != _DemographicTerminator)
			&&  (_Fields != null)
			&&  (_NrFields <= _Fields.Length))
			{
				int p = _SearchField(tag);
				if (p >= 0)
				{
					_NrFields--;
					for (;p < _NrFields;p++)
					{
						_Fields[p] = _Fields[p+1];
					}
					return 0x0;
				}
				return 0x2;
			}
			return 0x1;
		}
		/// <summary>
		/// Function to resize the space for header fields.
		/// </summary>
		public void Resize()
		{
			SCPHeaderField[] temp = new SCPHeaderField[_NrFields + _ResizeSpeed];
			for (int loper=0;loper < _NrFields;loper++)
			{
				temp[loper] = _Fields[loper];
			}
			_Fields = temp;
		}
		/// <summary>
		/// Function to search for a field with a certain tag.
		/// </summary>
		/// <param name="tag">tag to search for</param>
		/// <returns>position of this field</returns>
		private int _SearchField(byte tag)
		{
			int l = 0;
			int h = _NrFields-1;
			int m = (h >> 1);
			while (l <= h && _Fields[m].Tag != tag) 
			{
				if (tag > _Fields[m].Tag)
				{
					l = m + 1;
				} 
				else 
				{
					h = m - 1;
				}
				m = ((l + h) >> 1);
			}
			if ((m >= 0) && (m < _NrFields) && (_Fields[m].Tag == tag))
			{
				return m;
			}
			return -1;
		}
		/// <summary>
		/// Function to find position to insert a field with a certain tag.
		/// </summary>
		/// <param name="tag">tag to search on.</param>
		/// <returns>position to insert</returns>
		private int _InsertSearch(byte tag)
		{
			int l = 0, h = _NrFields;
			while (l < h)
			{
				int m = (l + h) / 2;
				if (_Fields[m].Tag < tag)
					l = m + 1;
				else
					h = m;
			}
			return l;
		}
		/// <summary>
		/// Function to check wheter the used fields are indeed sorted.
		/// </summary>
		private bool CheckInstances()
		{
			if ((_Fields != null)
			&&  (_NrFields > 0)
			&&  (_NrFields <= _Fields.Length)
			&&  (_Fields[0] != null))
			{
				byte prev = _Fields[0].Tag;
				for (int loper=1;loper < _NrFields;loper++)
				{
					if ((prev == _Fields[loper].Tag)
					&&  !isException(_MultipleInstanceFields, prev))
					{
						return false;
					}
					prev = _Fields[loper].Tag;
				}
				return true;
			}
			return false;
		}
		/// <summary>
		/// Function to check for exception case.
		/// </summary>
		/// <param name="condition">condition</param>
		/// <param name="tag">value of tag</param>
		/// <returns>is exception then true</returns>
		private static bool isException(byte[] condition, byte tag)
		{
			if (condition == null)
			{
				return false;
			}
			int l = 0;
			int h = condition.Length - 1;
			int m = (h >> 1);
			while (l <= h && condition[m] != tag) 
			{
				if (tag > condition[m])
				{
					l = m + 1;
				} 
				else 
				{
					h = m - 1;
				}
				m = ((l + h) >> 1);
			}
			return (m >= 0) && (m < condition.Length) && (condition[m] == tag);	
		}
		/// <summary>
		/// Function to anonymous this section.
		/// </summary>
		/// <param name="type">value to empty with</param>
		public void Anonymous(byte type)
		{
			for (int loper=0;loper < _NrFields;loper++)
			{
				if (isException(_AnonymousFields, _Fields[loper].Tag)
				&&  (_Fields[loper].Value != null)
				&&  (_Fields[loper].Length <= _Fields[loper].Value.Length))
				{
					if (_Fields[loper].Tag == 5)
					{
						SCPDate date2 = new SCPDate();
						date2.Read(_Fields[loper].Value, 0);
						date2.Day = 1;
						date2.Month = 1;
						date2.Write(_Fields[loper].Value, 0);
					}
					else
					{
						BytesTool.emptyBuffer(_Fields[loper].Value, 0, _Fields[loper].Length-1, type);
					}
				}
			}
		}
		/// <summary>
		/// Get encoding for text from language support code.
		/// </summary>
		/// <returns>used encoding</returns>
		public System.Text.Encoding getLanguageSupportCode()
		{
			System.Text.Encoding enc;

			getLanguageSupportCode(out enc);

			return enc;
		}
		/// <summary>
		/// Get encoding for text from language support code.
		/// </summary>
		/// <param name="enc">used encoding</param>
		/// <returns>0 if successfull</returns>
		public int getLanguageSupportCode(out System.Text.Encoding enc)
		{
			enc = System.Text.Encoding.ASCII;

			int p = _SearchField(14);
			if ((p >= 0)
			&&	(_Fields[p] != null)
			&&  (_Fields[p].Value != null)
			&&  (_Fields[p].Length <= _Fields[p].Value.Length)
			&&  (_Fields[p].Length > 16))
			{
				byte lsc = _Fields[p].Value[16];

				if ((lsc & 0x1) == 0x0)
				{
					return 0;
				}
				else if ((lsc & 0x3) == 0x1)
				{
					enc = System.Text.Encoding.GetEncoding("ISO-8859-1");

					return 0;
				}
				else
				{
					string encName = null;

					switch (lsc)
					{
						case 0x03: encName = "ISO-8859-2"; break;
						case 0x0b: encName = "ISO-8859-4"; break;
						case 0x13: encName = "ISO-8859-5"; break;
						case 0x1b: encName = "ISO-8859-6"; break;
						case 0x23: encName = "ISO-8859-7"; break;
						case 0x2b: encName = "ISO-8859-8"; break;
						case 0x33: encName = "ISO-8859-11"; break;
						case 0x3b: encName = "ISO-8859-15"; break;
						case 0x07: encName = "utf-16"; break; //case 0x07: encName = "ISO-60646"; break;
						case 0x0f: //encName = "JIS X0201-1976";
						case 0x17: //encName = "JIS X0208-1997";
						case 0x1f: //encName = "JIS X0212-1990";
							encName = "EUC-JP";
							break;
						case 0x27: encName = "gb2312"; break;
						case 0x2f: encName = "ks_c_5601-1987"; break;
						default: break;
					}

					if (encName != null)
					{
						enc = System.Text.Encoding.GetEncoding(encName);

						return 0;
					}
				}
			}
			return 1;
		}
		/// <summary>
		/// Set language support code based on encoding.
		/// </summary>
		/// <param name="enc">encoding to set lsc with.</param>
		/// <returns>0 if successfull</returns>
		public int setLanguageSupportCode(System.Text.Encoding enc)
		{
			int ret = 0;
			byte lsc = 0;

			switch (enc.CodePage)
			{
				case 20127: break;
				case 28591: lsc = 0x01; break;
				case 28592: lsc = 0x03; break;
				case 28594: lsc = 0x0b; break;
				case 28595: lsc = 0x13; break;
				case 28596: lsc = 0x1b; break;
				case 28597: lsc = 0x23; break;
				case 28598: lsc = 0x2b; break;
				case 28603: lsc = 0x33; break;
				case 28605: lsc = 0x3b; break;
				case  1200: lsc = 0x07; break;
				case 20932: lsc = 0x1f; break;
				case 20936: lsc = 0x27; break;
				case   949: lsc = 0x2f; break;
				default: ret = 1; break;
			}

			int p = _SearchField(14);
			if ((p >= 0)
			&&	(_Fields[p] != null)
			&&  (_Fields[p].Value != null)
			&&  (_Fields[p].Length <= _Fields[p].Value.Length)
			&&  (_Fields[p].Length > 16))
			{
				_Fields[p].Value[16] = lsc;
			}
			else if (ret != 1)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?