-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathText.TextString.cs
More file actions
150 lines (127 loc) · 5.28 KB
/
Copy pathText.TextString.cs
File metadata and controls
150 lines (127 loc) · 5.28 KB
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
* Idmr.LfdReader.dll, Library file to read and write LFD resource files
* Copyright (C) 2009-2026 Michael Gaisser (mjgaisser@gmail.com)
* Licensed under the MPL v2.0 or later
*
* Full notice in help/Idmr.LfdReader.chm
* Version: 3.0
*/
/* CHANGE LOG
* v3.0, 260821
* [NEW] created
*/
using System;
namespace Idmr.LfdReader
{
public partial class Text
{
/// <summary>Represents a single string within a Text resource.</summary>
// Developer note: all of the substring functions operate on _value directly, so there isn't a separate instance to track
public class TextString : IDisposable
{
Text _parent;
string _value;
/// <summary>Create a new string with the specified value.</summary>
/// <param name="parent">The parent Text resource.</param>
/// <param name="value">The initial value</param>
internal TextString(Text parent, string value)
{
_parent = parent;
_value = value;
}
/// <summary>Creates a new empty string.</summary>
/// <param name="parent">The parent Text resource.</param>
internal TextString(Text parent) : this(parent, "") { }
/// <summary>Gets the full length of the string.</summary>
/// <remarks>Accounts for the final null-terms that are trimmed from <see cref="Value"/>.</remarks>
public short Length => (short)(_value.Length + 2);
/// <summary>Gets or sets the raw string value.</summary>
/// <remarks>String and final SubString 0x00 End Markers are trimmed.<br/>
/// <b>WARNING:</b> This is the raw string with null chars, no line breaks. Use <see cref="FormattedValue"/> for the user-friendly format.</remarks>
public string Value
{
get => _value;
set
{
_value = value.TrimEnd('\0');
_parent.Dirty();
}
}
/// <summary>Gets or sets <see cref="Value"/> in a text-friendly format.</summary>
/// <remarks>Trailing null chars will be trimmed, substrings will be separated by line breaks.<br/>
/// When setting, line breaks will be treated as substring separators, blank lines will be retained.</remarks>
public string FormattedValue
{
get => _value.Replace("\n\0", "\r\n").Replace("\0", "\r\n");
set
{
_value = value.TrimEnd('\0').Replace("\r\n", "\0").Replace("\0\0", "\0\n\0");
_parent.Dirty();
}
}
#region IDisposable members
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing) { /* do nothing */ }
_value = null;
_parent = null;
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region substrings
/// <summary>Gets if the string is comprised of multiple substrings.</summary>
/// <remarks>This is the preferred presence check versus a <see cref="SubstringCount"/> value check.</remarks>
public bool HasSubstrings => _value.Contains("\0");
/// <summary>Gets a copy of the substrings as an array.</summary>
/// <remarks>Editing strings in the array will *not* be reflected in the resource. Use <see cref="SetSubstring(int, string)"/>.</remarks>
public string[] GetSubstringArray() => _value.Split('\0');
/// <summary>Gets the number of substrings.</summary>
/// <remarks>A value of <b>1</b> denotes no additional substrings.</remarks>
public int SubstringCount => GetSubstringArray().Length;
/// <summary>Gets the specified substring.</summary>
/// <param name="index">The substring index.</param>
/// <returns>A new string.</returns>
/// <exception cref="ArgumentOutOfRangeException">Invalid value for <paramref name="index"/>.</exception>
public string GetSubstring(int index)
{
var subs = GetSubstringArray();
if (index < 0 || index >= subs.Length) throw new ArgumentOutOfRangeException("index", $"index must be between 0-{subs.Length - 1}");
return subs[index];
}
/// <summary>Sets the specified substring to a new value.</summary>
/// <param name="index">The substring index.</param>
/// <param name="value">The new value.</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid value for <paramref name="index"/>.</exception>
/// <remarks>If <paramref name="value"/> is <see langword="null"/> or empty, it is removed.</remarks>
public void SetSubstring(int index, string value)
{
var subs = GetSubstringArray();
if (index < 0 || index >= subs.Length) throw new ArgumentOutOfRangeException("index", $"index must be between 0-{subs.Length - 1}");
subs[index] = value;
_value = string.Join("\0", subs).Replace("\0\0", "\0"); // the Replace removes a null/empty set
_parent.Dirty();
}
/// <summary>Adds a substring to the end of <see cref="Value"/>.</summary>
/// <param name="value">The new string.</param>
/// <remarks>If <paramref name="value"/> is <see langword="null"/> or empty, no action is taken.</remarks>
public void AddSubstring(string value)
{
if (string.IsNullOrEmpty(value)) return;
_value += "\0" + value;
_parent.Dirty();
}
/// <summary>Removes the substring at the specified index.</summary>
/// <param name="index">The substring index.</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid value for <paramref name="index"/>.</exception>
public void RemoveSubstringAt(int index) => SetSubstring(index, "");
#endregion
}
}
}