File: ZipStorage.cs

package info (click to toggle)
mono 6.12.0.199%2Bds-4
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,192 kB
  • sloc: cs: 11,181,844; xml: 2,850,076; ansic: 689,413; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,845; makefile: 19,951; sh: 15,030; python: 4,771; pascal: 925; sql: 859; sed: 16; php: 1
file content (134 lines) | stat: -rw-r--r-- 2,887 bytes parent folder | download | duplicates (8)
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
using System;
using System.IO;
using System.Xml;
using System.Linq;
using System.Text;
using System.Collections.Generic;

using ICSharpCode.SharpZipLib.Zip;

namespace Monodoc.Storage
{
	public class ZipStorage : IDocStorage
	{
		string zipFileName;
		int code;
		ZipOutputStream zipOutput;
		ZipFile zipFile;
		// SharpZipLib use linear search to map name to index, correct that a bit
		Dictionary<string, int> entries = new Dictionary<string, int> ();

		public ZipStorage (string zipFileName)
		{
			this.zipFileName = zipFileName;
		}

		public bool SupportRevision {
			get {
				return false;
			}
		}

		public IDocRevisionManager RevisionManager {
			get {
				return null;
			}
		}

		public bool SupportChange {
			get {
				return true;
			}
		}

		public string Store (string id, string text)
		{
			EnsureOutput ();
			SetupEntry (zipOutput, ref id);
			var writer = new StreamWriter (zipOutput);
			writer.Write (text);
			writer.Flush ();
			
			return id;
		}

		public string Store (string id, byte[] data)
		{
			EnsureOutput ();
			SetupEntry (zipOutput, ref id);
			zipOutput.Write (data, 0, data.Length);
			return id;
		}

		public string Store (string id, Stream stream)
		{
			EnsureOutput ();
			SetupEntry (zipOutput, ref id);
			stream.CopyTo (zipOutput);
			return id;
		}

		void SetupEntry (ZipOutputStream zipOutput, ref string id)
		{
			if (string.IsNullOrEmpty (id))
				id = GetNewCode ();

			ZipEntry entry = new ZipEntry (id);
			zipOutput.PutNextEntry (entry);
		}

		public Stream Retrieve (string id)
		{
			EnsureInput ();
			int index;
			ZipEntry entry;
			if (!entries.TryGetValue (id, out index) || (entry = zipFile[index]) == null)
				entry = zipFile.GetEntry (id);
			if (entry != null)
				return zipFile.GetInputStream (entry);
			else
				throw new ArgumentException ("id", string.Format ("'{0}' isn't a valid id for this storage", id));
		}

		public IEnumerable<string> GetAvailableIds ()
		{
			EnsureInput ();
			return zipFile.Cast<ZipEntry> ().Select (ze => ze.Name);
		}

		void EnsureOutput ()
		{
			if (zipFile != null)
				throw new InvalidOperationException ("This ZipStorage instance is already used in read-mode");
			if (zipOutput != null)
				return;
			zipOutput = new ZipOutputStream (File.Create (zipFileName));
#if !MONO
            zipOutput.UseZip64 = UseZip64.Off;
#endif
		}

		void EnsureInput ()
		{
			if (zipOutput != null)
				throw new InvalidOperationException ("This ZipStorage instance is already used in write-mode");
			if (zipFile != null)
				return;
			zipFile = new ZipFile (zipFileName);
			entries = Enumerable.Range (0, zipFile.Size).ToDictionary (i => zipFile[i].Name, i => i);
		}

		public void Dispose ()
		{
			if (zipOutput != null)
				zipOutput.Dispose ();
			if (zipFile != null)
				zipFile.Close ();
		}

		string GetNewCode ()
		{
			return String.Format ("{0}", code++);
		}
	}
}