1 using System;
2 using System.Collections;
3 using System.IO;
4
5 void PrintHelp()
6 {
7 Console.WriteLine("Usage: hexdump [options] { <filename> }");
8 Console.WriteLine("options:");
9 Console.WriteLine("--help | -h");
10 Console.WriteLine(" print this help");
11 }
12
13 const uint bytesInLine = 16u;
14
15 Result<string> HexDumpLine(uint addr, byte* bytes, uint numBytes)
16 {
17 #assert(numBytes > 0 && numBytes <= bytesInLine);
18 auto lineResult = ToHexString(addr);
19 if (lineResult.Error())
20 {
21 return Result<string>(ErrorId(lineResult.GetErrorId()));
22 }
23 string line = lineResult.Value();
24 line.Append(": ");
25 for (uint i = 0u; i < bytesInLine; ++i;)
26 {
27 if (i == bytesInLine / 2)
28 {
29 line.Append("- ");
30 }
31 if (i < numBytes)
32 {
33 auto byteResult = ToHexString(bytes[i]);
34 if (byteResult.Error())
35 {
36 return Result<string>(ErrorId(byteResult.GetErrorId()));
37 }
38 string hexByteStr = byteResult.Value();
39 line.Append(hexByteStr);
40 }
41 else
42 {
43 line.Append(" ");
44 }
45 line.Append(' ');
46 }
47 line.Append('|');
48 for (uint i = 0u; i < bytesInLine; ++i;)
49 {
50 char c = ' ';
51 if (i < numBytes)
52 {
53 char b = cast<char>(bytes[i]);
54 if (IsPrintable(b))
55 {
56 c = b;
57 }
58 }
59 line.Append(c);
60 }
61 line.Append('|');
62 return Result<string>(line);
63 }
64
65 Result<bool> HexDump(const string& fileName)
66 {
67 Console.WriteLine(fileName + ":");
68 auto fileSizeResult = File.Size(fileName);
69 if (fileSizeResult.Error())
70 {
71 return Result<bool>(ErrorId(fileSizeResult.GetErrorId()));
72 }
73 long fileSize = fileSizeResult.Value();
74 auto readerResult = File.OpenBinary(fileName);
75 if (readerResult.Error())
76 {
77 return Result<bool>(ErrorId(readerResult.GetErrorId()));
78 }
79 BinaryReader& reader = readerResult.Value();
80 byte[bytesInLine] bytes;
81 uint addr = 0u;
82 long numRows = fileSize / bytesInLine;
83 for (ulong i = 0u; i < numRows; ++i;)
84 {
85 for (uint j = 0u; j < bytesInLine; ++j;)
86 {
87 auto byteResult = reader.ReadByte();
88 if (byteResult.Error())
89 {
90 return Result<bool>(ErrorId(byteResult.GetErrorId()));
91 }
92 bytes[j] = byteResult.Value();
93 }
94 auto lineResult = HexDumpLine(addr, &bytes[0], bytesInLine);
95 if (lineResult.Error())
96 {
97 return Result<bool>(ErrorId(lineResult.GetErrorId()));
98 }
99 string line = lineResult.Value();
100 Console.WriteLine(line);
101 addr = addr + bytesInLine;
102 }
103 uint rest = cast<uint>(fileSize % bytesInLine);
104 for (uint j = 0u; j < rest; ++j;)
105 {
106 auto byteResult = reader.ReadByte();
107 if (byteResult.Error())
108 {
109 return Result<bool>(ErrorId(byteResult.GetErrorId()));
110 }
111 bytes[j] = byteResult.Value();
112 }
113 auto lineResult = HexDumpLine(addr, &bytes[0], rest);
114 if (lineResult.Error())
115 {
116 return Result<bool>(ErrorId(lineResult.GetErrorId()));
117 }
118 string line = lineResult.Value();
119 Console.WriteLine(line);
120 addr = addr + rest;
121 uint size = addr;
122 auto sizeLineResult = ToHexString(size);
123 if (sizeLineResult.Error())
124 {
125 return Result<bool>(ErrorId(sizeLineResult.GetErrorId()));
126 }
127 string sizeLine = sizeLineResult.Value();
128 sizeLine.Append(';');
129 Console.WriteLine(sizeLine);
130 return Result<bool>(true);
131 }
132
133 int main(int argc, const char** argv)
134 {
135 List<string> fileNames;
136 for (int i = 1; i < argc; ++i;)
137 {
138 string arg = argv[i];
139 if (arg.StartsWith("-"))
140 {
141 if (arg == "--help" || arg == "-h")
142 {
143 PrintHelp();
144 return 0;
145 }
146 else
147 {
148 int errorId = AllocateError("unknown arguent \'" + arg + "\'");
149 Console.Error() << GetErrorMessage(errorId) << endl();
150 return 1;
151 }
152 }
153 else
154 {
155 auto fullPathResult = GetFullPath(arg);
156 if (fullPathResult.Error())
157 {
158 Console.Error() << fullPathResult.GetErrorMessage();
159 return 1;
160 }
161 fileNames.Add(fullPathResult.Value());
162 }
163 }
164 if (fileNames.IsEmpty())
165 {
166 int errorId = AllocateError("no files given");
167 Console.Error() << GetErrorMessage(errorId) << endl();
168 return 1;
169 }
170 else
171 {
172 for (const string& fileName : fileNames)
173 {
174 auto result = HexDump(fileName);
175 if (result.Error())
176 {
177 Console.Error() << result.GetErrorMessage() << endl();
178 return 1;
179 }
180 }
181 }
182 return 0;
183 }