Welcome to mirror list, hosted at ThFree Co, Russian Federation.

CharStream.cs « Storage « TextModel « Impl « Text « src - github.com/microsoft/vs-editor-api.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9a8e0f8d4042597eef7793eb951a24287485d1e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//
//  Copyright (c) Microsoft Corporation. All rights reserved.
//  Licensed under the MIT License. See License.txt in the project root for license information.
//
// This file contain implementations details that are subject to change without notice.
// Use at your own risk.
//
using System;
using System.Diagnostics;
using System.IO;

namespace Microsoft.VisualStudio.Text.Implementation
{
    /// <summary>
    /// Stream that converts between characters and bytes.
    /// </summary>
    internal class CharStream : Stream
    {
        char[] data;
        int length;         // *byte* length of data
        int position = 0;   // *byte* offset into data
        byte? pendingByte;

        public CharStream(char[] data, int length)
        {
            this.data = data;
            this.length = 2 * length;
        }

        public override bool CanRead { get { return true; } }
        public override bool CanSeek { get { return false; } }
        public override bool CanWrite { get { return true; } }

        public override void Flush()
        {
        }

        public override long Length { get { return (int)this.length; } }

        public override long Position
        {
            get { return this.position; }
            set { throw new NotSupportedException(); }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            int actualCount = Math.Min(count, this.length - this.position);
            if (actualCount > 0)
            {
                int residue = actualCount;
                byte hi, lo;
                if (this.position % 2 == 1)
                {
                    Split(this.data[this.position / 2], out hi, out lo);
                    buffer[offset++] = hi;
                    this.position++;
                    residue--;
                }
                for (int i = 0; i < residue / 2; ++i)
                {
                    Split(this.data[this.position / 2], out hi, out lo);
                    buffer[offset++] = hi;
                    buffer[offset++] = lo;
                    this.position += 2;
                }
                if (residue % 2 == 1)
                {
                    Split(this.data[this.position / 2], out hi, out lo);
                    buffer[offset++] = lo;
                    this.position++;
                }
            }
            return actualCount;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (count == 0)
            {
                return;
            }

            if (this.pendingByte.HasValue)
            {
                // finish previous character
                Debug.Assert(this.position % 2 == 1);
                this.data[this.position / 2] = Make(this.pendingByte.Value, buffer[offset]);
                this.position++;
                offset++;
                count--;
            }

            for (int i = 0; i < count / 2; ++i)
            {
                this.data[this.position / 2] = Make(buffer[offset], buffer[offset + 1]);
                this.position += 2;
                offset += 2;
            }

            if (count % 2 == 0)
            {
                this.pendingByte = null;
            }
            else
            {
                this.pendingByte = buffer[offset];
                this.position++;
            }
        }

        private static char Make(byte hi, byte lo)
        {
            return (char)((hi << 8) | lo);
        }

        private static void Split(char c, out byte hi, out byte lo)
        {
            hi = (byte)(c >> 8);
            lo = (byte)(c & 255);
        }
    }
}