1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 using System.IO;
  9 using System.Os;
 10 
 11 void PrintHelp()
 12 {
 13     Console.WriteLine("Usage: hexdump [options] [FILE]...");
 14     Console.WriteLine("Options:");
 15     Console.WriteLine("--help | -h");
 16     Console.WriteLine("  Print help and exit.");
 17 }
 18 
 19 const int bytesInLine = 16;
 20 
 21 string HexDumpLine(int addrbyte* bytesint numBytes)
 22 {
 23     string line(ToHexString(addr));
 24     line.Append(": ");
 25     for (int i = 0; i < bytesInLine; ++i;)
 26     {
 27         if (i == bytesInLine / 2)
 28         {
 29             line.Append("- ");
 30         }
 31         if (i < numBytes)
 32         {
 33             line.Append(ToHexString(bytes[i]));
 34         }
 35         else
 36         {
 37             line.Append("  ");
 38         }
 39         line.Append(' ');
 40     }
 41     line.Append('|');
 42     for (int i = 0; i < bytesInLine; ++i;)
 43     {
 44         char c = ' ';
 45         if (i < numBytes)
 46         {
 47             char b = cast<char>(bytes[i]);
 48             if (IsPrintable(b))
 49             {
 50                 c = b;
 51             }
 52         }
 53         line.Append(c);
 54     }
 55     line.Append('|');
 56     return line;
 57 }
 58 
 59 int ReadBytes(byte[bytesInLine]& bytesBinaryReader& reader)
 60 {
 61     int n = 0;
 62     for (int j = 0; j < bytesInLine; ++j;)
 63     {
 64         int x = reader.ReadByteOrEnd();
 65         if (x != -1)
 66         {
 67             bytes[j] = cast<byte>(x);
 68             ++n;
 69         }
 70         else
 71         {
 72             return n;
 73         }
 74     }
 75     return n;
 76 }
 77 
 78 void HexDump(const string& fileName)
 79 {
 80     if (!fileName.IsEmpty())
 81     {
 82         Console.WriteLine(GetFullPath(fileName) + ":");
 83     }
 84     BinaryReader reader(SharedPtr<Stream>());
 85     if (!fileName.IsEmpty())
 86     {
 87         reader = File.OpenBinary(fileName);
 88     }
 89     else if (IsConsole(0))
 90     {
 91         reader = BinaryReader(SharedPtr<Stream>(new FileStream(0)));
 92     }
 93     else
 94     {
 95         reader = BinaryReader(SharedPtr<Stream>(new BufferedStream(SharedPtr<Stream>(new FileStream(0)))));
 96     }
 97     byte[bytesInLine] bytes;
 98     int addr = 0u;
 99     int n = ReadBytes(bytesreader);
100     while (n != 0)
101     {
102         Console.WriteLine(HexDumpLine(addr&bytes[0]n));
103         addr = addr + n;
104         n = ReadBytes(bytesreader);
105     }
106     int size = addr;
107     string sizeLine = ToHexString(size);
108     sizeLine.Append(';');
109     Console.WriteLine(sizeLine);
110 }
111 
112 int main(int argcconst char** argv)
113 {
114     try
115     {
116         List<string> fileNames;
117         for (int i = 1; i < argc; ++i;)
118         {
119             string arg = argv[i];
120             if (arg.StartsWith("--"))
121             {
122                 if (arg == "--help")
123                 {
124                     PrintHelp();
125                     return 1;
126                 }
127                 else
128                 {
129                     throw Exception("unknown option '" + arg + "'");
130                 }
131             }
132             else if (arg.StartsWith("-"))
133             {
134                 string options = arg.Substring(1);
135                 if (options.IsEmpty())
136                 {
137                     throw Exception("unknown option '" + arg + "'");
138                 }
139                 else
140                 {
141                     for (char o : options)
142                     {
143                         if (o == 'h')
144                         {
145                             PrintHelp();
146                             return 1;
147                         }
148                         else
149                         {
150                             throw Exception("unknown option '-" + string(o) + "'");
151                         }
152                     }
153                 }
154             }
155             else
156             {
157                 fileNames.Add(arg);
158             }
159         }
160         if (fileNames.IsEmpty())
161         {
162             fileNames.Add(string());
163         }
164         for (const string& fileName : fileNames)
165         {
166             HexDump(fileName);
167         }
168     }
169     catch (const Exception& ex)
170     {
171         Console.Error() << ex.ToString() << endl();
172         return 1;
173     }
174     return 0;
175 }