Release 4.0.0-preview1-00235
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / Common.Internal / MediaBufferBase.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Diagnostics;
19 using System.Runtime.InteropServices;
20
21 namespace Tizen.Multimedia
22 {
23     internal abstract class MediaBufferBase : IMediaBuffer
24     {
25         private readonly IntPtr _dataHandle;
26
27         public int Length { get; }
28
29         internal MediaBufferBase(IntPtr dataHandle, int size, bool isReadOnly)
30         {
31             Debug.Assert(dataHandle != IntPtr.Zero, "dataHandle is null!");
32             Debug.Assert(size >= 0, "size must not be negative!");
33
34             _dataHandle = dataHandle;
35             Length = size;
36             IsReadOnly = false;
37         }
38
39         internal MediaBufferBase(IntPtr dataHandle, int size) :
40             this(dataHandle, size, false)
41         {
42         }
43
44         internal IntPtr DataHandle => _dataHandle;
45
46         public bool IsReadOnly { get; }
47
48         /// <summary>
49         /// Validates the range.
50         /// </summary>
51         /// <param name="offset"></param>
52         /// <param name="length"></param>
53         /// <exception cref="ArgumentOutOfRangeException">
54         ///     The offset + length is greater than <see cref="Length"/>.
55         ///     <para>-or-</para>
56         ///     The offset or length is less than zero.
57         /// </exception>
58         private void ValidateRange(int offset, int length)
59         {
60             if (offset + length > Length)
61             {
62                 throw new ArgumentOutOfRangeException($"{nameof(offset)}, {nameof(length)}",
63                     "offset + length can't be greater than length of the buffer.");
64             }
65             if (length < 0)
66             {
67                 throw new ArgumentOutOfRangeException(nameof(length), length,
68                     $"length can't be less than zero.");
69             }
70             if (offset < 0)
71             {
72                 throw new ArgumentOutOfRangeException(nameof(offset), offset,
73                     $"offset can't be less than zero.");
74             }
75         }
76
77         public byte this[int index]
78         {
79             get
80             {
81                 ThrowIfBufferIsNotReadable();
82
83                 if (index < 0 || index >= Length)
84                 {
85                     throw new ArgumentOutOfRangeException(nameof(index), index,
86                         $"Valid index range is [0, { nameof(Length) }).");
87                 }
88
89                 return Marshal.ReadByte(DataHandle, index);
90             }
91             set
92             {
93                 ThrowIfBufferIsNotWritable();
94
95                 Marshal.WriteByte(DataHandle, index, value);
96             }
97         }
98
99         private void ThrowIfBufferIsNotReadable()
100         {
101             ValidateBufferReadable();
102         }
103
104         private void ThrowIfBufferIsNotWritable()
105         {
106             if (IsReadOnly)
107             {
108                 throw new NotSupportedException("The buffer is read-only.");
109             }
110
111             ValidateBufferWritable();
112         }
113
114         internal abstract void ValidateBufferReadable();
115
116         internal abstract void ValidateBufferWritable();
117
118         public void CopyFrom(byte[] source, int startIndex, int length, int offset)
119         {
120             ThrowIfBufferIsNotReadable();
121
122             if (source == null)
123             {
124                 throw new ArgumentNullException(nameof(source));
125             }
126
127             if (startIndex < 0)
128             {
129                 throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex,
130                     "startIndex can't be less than zero.");
131             }
132             if (startIndex + length > source.Length)
133             {
134                 throw new ArgumentOutOfRangeException($"{nameof(startIndex)}, {nameof(length)}",
135                     "startIndex + length can't be greater than source.Length.");
136             }
137
138             ValidateRange(offset, length);
139
140             Marshal.Copy(source, startIndex, IntPtr.Add(_dataHandle, offset), length);
141         }
142
143         public void CopyFrom(byte[] source, int startIndex, int length)
144         {
145             CopyFrom(source, startIndex, length, 0);
146         }
147
148         public void CopyTo(byte[] dest, int startIndex, int length, int offset)
149         {
150             ThrowIfBufferIsNotWritable();
151
152             if (dest == null)
153             {
154                 throw new ArgumentNullException(nameof(dest));
155             }
156
157             if (startIndex < 0)
158             {
159                 throw new ArgumentOutOfRangeException(nameof(startIndex), startIndex,
160                     "startIndex can't be less than zero.");
161             }
162             if (startIndex + length > dest.Length)
163             {
164                 throw new ArgumentOutOfRangeException($"{nameof(startIndex)}, {nameof(length)}",
165                     "startIndex + length can't be greater than dest.Length.");
166             }
167
168             ValidateRange(offset, length);
169
170             Marshal.Copy(IntPtr.Add(_dataHandle, offset), dest, startIndex, length);
171         }
172
173         public void CopyTo(byte[] dest, int startIndex, int length)
174         {
175             CopyTo(dest, startIndex, length, 0);
176         }
177     }
178 }