/* * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved * * 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. */ using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace Tizen.Multimedia { internal abstract class MediaBufferBase : IMediaBuffer { private readonly IntPtr _dataHandle; public int Length { get; } internal MediaBufferBase(IntPtr dataHandle, int size, bool isReadOnly) { Debug.Assert(dataHandle != IntPtr.Zero, "dataHandle is null!"); Debug.Assert(size >= 0, "size must not be negative!"); _dataHandle = dataHandle; Length = size; IsReadOnly = false; } internal MediaBufferBase(IntPtr dataHandle, int size) : this(dataHandle, size, false) { } internal IntPtr DataHandle => _dataHandle; public bool IsReadOnly { get; } /// /// Validates the range. /// /// /// /// /// The offset + length is greater than . /// -or- /// The offset or length is less than zero. /// private void ValidateRange(int offset, int length) { if (offset + length > Length) { throw new ArgumentOutOfRangeException($"{nameof(offset)}, {nameof(length)}", "offset + length can't be greater than length of the buffer."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), length, $"length can't be less than zero."); } if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), offset, $"offset can't be less than zero."); } } public byte this[int index] { get { ThrowIfBufferIsNotReadable(); if (index < 0 || index >= Length) { throw new ArgumentOutOfRangeException(nameof(index), index, $"Valid index range is [0, { nameof(Length) })."); } return Marshal.ReadByte(DataHandle, index); } set { ThrowIfBufferIsNotWritable(); Marshal.WriteByte(DataHandle, index, value); } } private void ThrowIfBufferIsNotReadable() { ValidateBufferReadable(); } private void ThrowIfBufferIsNotWritable() { if (IsReadOnly) { throw new NotSupportedException("The buffer is read-only."); } ValidateBufferWritable(); } internal abstract void ValidateBufferReadable(); internal abstract void ValidateBufferWritable(); public void CopyFrom(byte[] source, int startIndex, int length, int offset) { ThrowIfBufferIsNotReadable(); if (source == null) { throw new ArgumentNullException(nameof(source)); } if (startIndex < 0) { throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex, "startIndex can't be less than zero."); } if (startIndex + length > source.Length) { throw new ArgumentOutOfRangeException($"{nameof(startIndex)}, {nameof(length)}", "startIndex + length can't be greater than source.Length."); } ValidateRange(offset, length); Marshal.Copy(source, startIndex, IntPtr.Add(_dataHandle, offset), length); } public void CopyFrom(byte[] source, int startIndex, int length) { CopyFrom(source, startIndex, length, 0); } public void CopyTo(byte[] dest, int startIndex, int length, int offset) { ThrowIfBufferIsNotWritable(); if (dest == null) { throw new ArgumentNullException(nameof(dest)); } if (startIndex < 0) { throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex, "startIndex can't be less than zero."); } if (startIndex + length > dest.Length) { throw new ArgumentOutOfRangeException($"{nameof(startIndex)}, {nameof(length)}", "startIndex + length can't be greater than dest.Length."); } ValidateRange(offset, length); Marshal.Copy(IntPtr.Add(_dataHandle, offset), dest, startIndex, length); } public void CopyTo(byte[] dest, int startIndex, int length) { CopyTo(dest, startIndex, length, 0); } } }