2006/06/23 tmccolm
authortmccolm <tmccolm@cinecert.com>
Fri, 23 Jun 2006 19:48:03 +0000 (19:48 +0000)
committertmccolm <>
Fri, 23 Jun 2006 19:48:03 +0000 (19:48 +0000)
14 files changed:
src/AS_DCP_MXF.cpp
src/JP2K.cpp
src/KLV.h
src/KM_util.cpp
src/KM_util.h
src/KM_xml.cpp
src/MXF.cpp
src/asdcp-test.cpp
src/blackwave.cpp
src/h__Reader.cpp
src/klvwalk.cpp
src/kmfilegen.cpp [new file with mode: 0755]
src/kmrandgen.cpp [new file with mode: 0644]
src/kmuuidgen.cpp [new file with mode: 0644]

index 1c8b6e9d5c95513ad1f1191e4f9e4e5780e75f03..5c8fc16af8a9440a8b606736c2100e59e47f4d28 100755 (executable)
@@ -447,7 +447,7 @@ ASDCP::IntegrityPack::TestValues(const ASDCP::FrameBuffer& FB, byte_t* AssetID,
   // test the sequence value
   if ( test_sequence != sequence )
     {
-      DefaultLogSink().Error("IntegrityPack failure: sequence is %lu, expecting %lu.\n", test_sequence, sequence);
+      DefaultLogSink().Error("IntegrityPack failure: sequence is %u, expecting %u.\n", test_sequence, sequence);
       return RESULT_HMACFAIL;
     }
 
index 3c798ceef3352293bb1dac5dfc53407cf7f01ead..14789f17f13b289bbedfb523d1e3efb2ce0a4b98 100755 (executable)
@@ -120,15 +120,15 @@ ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream)
 
   fprintf(stream, "SIZ: \n");
   fprintf(stream, "  Rsize: %hu\n", Rsize());
-  fprintf(stream, "  Xsize: %u\n", Xsize());
-  fprintf(stream, "  Ysize: %u\n", Xsize());
-  fprintf(stream, " XOsize: %u\n", XOsize());
-  fprintf(stream, " YOsize: %u\n", XOsize());
-  fprintf(stream, " XTsize: %u\n", XTsize());
-  fprintf(stream, " YTsize: %u\n", XTsize());
-  fprintf(stream, "XTOsize: %u\n", XTOsize());
-  fprintf(stream, "YTOsize: %u\n", YTOsize());
-  fprintf(stream, "  Csize: %u\n", Csize());
+  fprintf(stream, "  Xsize: %u\n",  Xsize());
+  fprintf(stream, "  Ysize: %u\n",  Xsize());
+  fprintf(stream, " XOsize: %u\n",  XOsize());
+  fprintf(stream, " YOsize: %u\n",  XOsize());
+  fprintf(stream, " XTsize: %u\n",  XTsize());
+  fprintf(stream, " YTsize: %u\n",  XTsize());
+  fprintf(stream, "XTOsize: %u\n",  XTOsize());
+  fprintf(stream, "YTOsize: %u\n",  YTOsize());
+  fprintf(stream, "  Csize: %u\n",  Csize());
 
   if ( Csize() > 0 )
     {
index ba291b6170a6c7f0a169d53b945fb31326dfefa5..42719998eec5cf677053055c09f16449e12d93f0 100755 (executable)
--- a/src/KLV.h
+++ b/src/KLV.h
@@ -102,12 +102,6 @@ inline const char* ui64sz(ui64_t i, char* buf)
       UL(const byte_t* value) : Kumu::Identifier<SMPTE_UL_LENGTH>(value) {}
       virtual ~UL() {}
 
-      const UL& operator=(const UL& rhs) {
-       if ( m_HasValue = rhs.m_HasValue )
-         memcpy(m_Value, rhs.m_Value, SMPTE_UL_LENGTH);
-       return *this;
-      }
-
       const char* EncodeString(char* str_buf, ui32_t buf_len) const;
     };
 
@@ -120,12 +114,6 @@ inline const char* ui64sz(ui64_t i, char* buf)
       UMID(const byte_t* value) : Kumu::Identifier<SMPTE_UMID_LENGTH>(value) {}
       virtual ~UMID() {}
 
-      const UMID& operator=(const UMID& rhs) {
-       if ( m_HasValue = rhs.m_HasValue )
-         memcpy(m_Value, rhs.m_Value, SMPTE_UMID_LENGTH);
-       return *this;
-      }
-
       void MakeUMID(int Type);
       void MakeUMID(int Type, const UUID& ID);
       const char* EncodeString(char* str_buf, ui32_t buf_len) const;
index a07d33e3986e5616519b83a29564052230ead53b..7dd6719ba28d0083c19d6d48fadfe6a2fc7ebb56 100755 (executable)
@@ -433,12 +433,12 @@ Kumu::GenRandomUUID(byte_t* buf)
 
 //
 void
-Kumu::GenRandomValue(SymmetricKey& ID)
+Kumu::GenRandomValue(SymmetricKey& Key)
 {
   byte_t tmp_buf[SymmetricKey_Length];
   FortunaRNG RNG;
   RNG.FillRandom(tmp_buf, SymmetricKey_Length);
-  ID.Set(tmp_buf);
+  Key.Set(tmp_buf);
 }
 
 
@@ -796,41 +796,73 @@ Kumu::Timestamp::EncodeString(char* str_buf, ui32_t buf_len) const
 bool
 Kumu::Timestamp::DecodeString(const char* datestr)
 {
+  Timestamp TmpStamp;
+
   if ( ! ( isdigit(datestr[0]) && isdigit(datestr[1]) && isdigit(datestr[2]) && isdigit(datestr[3]) )
        || datestr[4] != '-'
        || ! ( isdigit(datestr[5]) && isdigit(datestr[6]) )
        || datestr[7] != '-'
-       || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) )
-       || datestr[10] != 'T'
-       || ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
-       || datestr[13] != ':'
-       || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) )
-       || datestr[16] != ':'
-       || ! ( isdigit(datestr[17]) && isdigit(datestr[18]) )
-       || ! ( datestr[19] == '-' || datestr[19] == '+' )
-       || ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
-       || datestr[22] != ':'
-       || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
+       || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) )
     return false;
 
-  // TODO -- test this!
-  Year = atoi(datestr);
-  Month = atoi(datestr + 5);
-  Day = atoi(datestr + 8);
-  Hour = atoi(datestr + 11);
-  Minute = atoi(datestr + 14);
-  Second = atoi(datestr + 17);
+  TmpStamp.Year = atoi(datestr);
+  TmpStamp.Month = atoi(datestr + 5);
+  TmpStamp.Day = atoi(datestr + 8);
+  TmpStamp.Hour = TmpStamp.Minute = TmpStamp.Second = 0;
+  if ( datestr[10] == 'T' )
+    {
+      if ( ! ( isdigit(datestr[11]) && isdigit(datestr[12]) )
+          || datestr[13] != ':'
+          || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) )
+       return false;
 
-  ui32_t TZ_hh = atoi(datestr + 20);
-  ui32_t TZ_mm = atoi(datestr + 23);
+      TmpStamp.Hour = atoi(datestr + 11);
+      TmpStamp.Minute = atoi(datestr + 14);
 
-  if ( TZ_mm != 0 )
-    DefaultLogSink().Error("Ignoring sub-hours timezone offset: %u\n", TZ_mm);
-  if ( TZ_hh > 12 )
-    DefaultLogSink().Error("Ignoring large timezone offset: %s\n", (datestr+19));
-  else 
-    AddHours(TZ_hh);
+      if ( datestr[16] == ':' )
+       {
+         if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) )
+           return false;
+
+         TmpStamp.Second = atoi(datestr + 17);
+       }
+    }
+
+  if ( datestr[19] == '-' || datestr[19] == '+' )
+    {
+      if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) )
+          || datestr[22] != ':'
+          || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) )
+       return false;
+
+      ui32_t TZ_hh = atoi(datestr + 20);
+      ui32_t TZ_mm = atoi(datestr + 23);
+      
+      if ( TZ_mm != 0 )
+       DefaultLogSink().Error("Ignoring minutes in timezone offset: %u\n", TZ_mm);
+
+      if ( TZ_hh > 12 )
+       return false;
+
+      else 
+       AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh));
+    }
+
+#ifdef KM_WIN32
+  SYSTEMTIME st;
+  FILETIME ft;
+  TIMESTAMP_TO_SYSTIME(TmpStamp, &st);
+  if ( SystemTimeToFileTime(&st, &ft) == 0 )
+    return false;
+  SYSTIME_TO_TIMESTAMP(&st, *this);
+#else
+  struct tm stm;
+  TIMESTAMP_TO_TM(TmpStamp, &stm);
+  if ( timegm(&stm) == 0 )
+    return false;
+  TM_TO_TIMESTAMP(&stm, *this);
+#endif
 
   return true;
 }
index 344cfd161d704fc2c4490a88e3d0b2fcea41ebf9..9d975b9ebe46f0b40dad514327d39e12f6b852e8 100755 (executable)
@@ -167,8 +167,6 @@ namespace Kumu
   template <ui32_t SIZE>
     class Identifier : public IArchive
     {
-      const Identifier& operator=(const Identifier& rhs);
-
     protected:
       bool   m_HasValue;
       byte_t m_Value[SIZE];
@@ -183,6 +181,12 @@ namespace Kumu
 
       virtual ~Identifier() {}
 
+      const Identifier& operator=(const Identifier& rhs) {
+       m_HasValue = rhs.m_HasValue;
+       memcpy(m_Value, rhs.m_Value, SIZE);
+        return *this;
+      }
+
       inline void Set(const byte_t* value) { m_HasValue = true; memcpy(m_Value, value, SIZE); }
       inline const byte_t* Value() const { return m_Value; }
       inline ui32_t Size() const { return SIZE; }
@@ -262,19 +266,13 @@ namespace Kumu
       UUID(const byte_t* value) : Identifier<UUID_Length>(value) {}
       UUID(const UUID& rhs) : Identifier<UUID_Length>(rhs) {}
       virtual ~UUID() {}
-      
-      const UUID& operator=(const UUID& rhs) {
-        if ( m_HasValue = rhs.m_HasValue )
-          memcpy(m_Value, rhs.m_Value, UUID_Length);
-        return *this;
-      }
 
       inline const char* EncodeHex(char* buf, ui32_t buf_len) const {
        return bin2UUIDhex(m_Value, Size(), buf, buf_len);
       }
     };
   
-  void GenRandomUUID(byte_t* buf);
+  void GenRandomUUID(byte_t* buf); // buf must be UUID_Length or longer
   void GenRandomValue(UUID&);
   
   // a self-wiping key container
@@ -292,12 +290,6 @@ namespace Kumu
       SymmetricKey(const byte_t* value) : Identifier<SymmetricKey_Length>(value) {}
       SymmetricKey(const UUID& rhs) : Identifier<SymmetricKey_Length>(rhs) {}
       virtual ~SymmetricKey() { memcpy(m_Value, NilKey, 16); m_HasValue = false; }
-
-      const SymmetricKey& operator=(const SymmetricKey& rhs) {
-        if ( m_HasValue = rhs.m_HasValue )
-          memcpy(m_Value, rhs.m_Value, SymmetricKey_Length);
-        return *this;
-      }
     };
 
   void GenRandomValue(SymmetricKey&);
index 794e2e799a0b9660bad2cc87040f256181a66747..605ea11abed74a6ba7d7629e78c3402f71484669 100644 (file)
@@ -138,10 +138,12 @@ Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth)
       outbuf += "\"";
     }
 
+  outbuf += ">";
+
   // body contents and children
   if ( ! m_ChildList.empty() )
     {
-      outbuf += ">\n";
+      outbuf += "\n";
 
       // render body
       if ( m_Body.length() > 0 )
@@ -151,22 +153,15 @@ Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth)
        (*i)->RenderElement(outbuf, depth + 1);
 
       add_spacer(outbuf, depth);
-      outbuf += "</";
-      outbuf += m_Name;
-      outbuf += ">\n";
     }
   else if ( m_Body.length() > 0 )
     {
-      outbuf += ">";
       outbuf += m_Body;
-      outbuf += "</";
-      outbuf += m_Name;
-      outbuf += ">\n";
-    }
-  else
-    {
-      outbuf += " />\n";
     }
+
+  outbuf += "</";
+  outbuf += m_Name;
+  outbuf += ">\n";
 }
 
 
index 9d4fba82f246ddd01b9eb9b3856db49fafd3c98b..0913f1bb84688a384bef1fa05e7408dca7f09856 100755 (executable)
@@ -577,7 +577,7 @@ ASDCP::MXF::Preface::Dump(FILE* stream)
   InterchangeObject::Dump(stream);
   fprintf(stream, "  %22s = %s\n",  "LastModifiedDate", LastModifiedDate.EncodeString(identbuf, IdentBufferLen));
   fprintf(stream, "  %22s = %hu\n", "Version", Version);
-  fprintf(stream, "  %22s = %u\n", "ObjectModelVersion", ObjectModelVersion);
+  fprintf(stream, "  %22s = %u\n",  "ObjectModelVersion", ObjectModelVersion);
   fprintf(stream, "  %22s = %s\n",  "PrimaryPackage", PrimaryPackage.EncodeHex(identbuf, IdentBufferLen));
   fprintf(stream, "  %22s:\n", "Identifications");  Identifications.Dump(stream);
   fprintf(stream, "  %22s = %s\n",  "ContentStorage", ContentStorage.EncodeHex(identbuf, IdentBufferLen));
index 5eaffe32b073a7a17bd0a1a2d082538f69c3b3bb..e43569efa41179f230c016422442bd7c2fc8864c 100755 (executable)
@@ -277,11 +277,11 @@ public:
     for ( int i = 1; i < argc; i++ )
       {
 
-         if ( (strcmp( argv[i], "-help") == 0) )
-           {
-             help_flag = true;
-             continue;
-           }
+       if ( (strcmp( argv[i], "-help") == 0) )
+         {
+           help_flag = true;
+           continue;
+         }
          
        if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
          {
index c84774fa66983fbbfde73eda08b6a4da5208f4c3..b704b47d515dbebf4ceba0771664438cb9ce4c7e 100644 (file)
@@ -169,7 +169,7 @@ make_black_wav_file(CommandOptions& Options)
 
   if ( 1 ) // Options.verbose_flag )
     {
-      fprintf(stderr, "48Khz PCM Audio, %s fps (%lu spf)\n", "24",
+      fprintf(stderr, "48Khz PCM Audio, %s fps (%u spf)\n", "24",
              PCM::CalcSamplesPerFrame(ADesc));
       fputs("AudioDescriptor:\n", stderr);
       PCM::AudioDescriptorDump(ADesc);
index 1ebc5d41023b8fc3aa4bda27aaf747212a34a298..2179ca68459675a5ef6bc1ce233c9e3e0fb49ce8 100755 (executable)
@@ -108,19 +108,23 @@ ASDCP::h__Reader::OpenMXFRead(const char* filename)
   if ( ASDCP_SUCCESS(result) )
     result = m_HeaderPart.InitFromFile(m_File);
 
-  // if this is a three partition file, go to the body
-  // partition and read off the partition pack
-  if ( m_HeaderPart.m_RIP.PairArray.size() == 3 )
+  if ( ASDCP_SUCCESS(result) )
     {
-      Array<RIP::Pair>::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin();
-      r_i++;
-      m_File.Seek((*r_i).ByteOffset);
+      // if this is a three partition file, go to the body
+      // partition and read the partition pack
+      if ( m_HeaderPart.m_RIP.PairArray.size() == 3 )
+       {
+         Array<RIP::Pair>::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin();
+         r_i++;
+         m_File.Seek((*r_i).ByteOffset);
 
-      result = m_BodyPart.InitFromFile(m_File);
+         result = m_BodyPart.InitFromFile(m_File);
+       }
+
+      m_EssenceStart = m_File.Tell();
     }
 
-  m_EssenceStart = m_File.Tell();
-  return RESULT_OK;
+  return result;
 }
 
 
index 395aa543f6bb30c23c9e62d09ab3bedd42701c96..467eff938fc9e37633b481b37e33f29277169db7 100755 (executable)
@@ -42,94 +42,217 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace ASDCP;
 using Kumu::DefaultLogSink;
 
-const char* PACKAGE = "klvwalk";
-
 
 //------------------------------------------------------------------------------------------
 //
+// command line option parser class
 
+static const char* PACKAGE = "klvwalk";    // program name for messages
+typedef std::list<std::string> FileList_t;
 
-int
-main(int argc, char** argv)
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c)    if ( ++i >= argc || argv[(i)][0] == '-' ) \
+                                 { \
+                                   fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+                                   return; \
+                                 }
+
+//
+void
+banner(FILE* stream = stdout)
 {
-  Result_t result = RESULT_OK;
-  bool read_mxf = false;
-  int arg_i = 1;
+  fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2005-2006 John Hurst\n\
+%s is part of the asdcplib DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+         PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
 
-  if ( argc > arg_i && strcmp(argv[1], "-r") == 0 )
-    {
-      read_mxf = true;
-      arg_i++;
-    }
+//
+void
+usage(FILE* stream = stdout)
+{
+  fprintf(stream, "\
+USAGE: %s [-r] [-v] <input-file> [<input-file2> ...]\n\
+\n\
+       %s [-h|-help] [-V]\n\
+\n\
+  -h | -help  - Show help\n\
+  -r          - When KLV data is an OPAtom file, additionally\n\
+                display OPAtom headers\n\
+  -v          - Verbose. Prints informative messages to stderr\n\
+  -V          - Show version information\n\
+\n\
+  NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+         o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
 
-  if ( argc - arg_i != 1 )
-    {
-      fprintf(stderr, "usage: %s [-r] <infile>\n", PACKAGE);
-      return 1;
-    }
+//
+//
+ class CommandOptions
+ {
+   CommandOptions();
 
-  fprintf(stderr, "Opening file %s\n", argv[arg_i]);
+ public:
+   bool   error_flag;               // true if the given options are in error or not complete
+   bool   version_flag;             // true if the version display option was selected
+   bool   help_flag;                // true if the help display option was selected
+   bool   verbose_flag;             // true if the informative messages option was selected
+   bool   read_mxf_flag;            // true if the -r option was selected
+   FileList_t inFileList;           // File to operate on
 
-  if ( read_mxf )
-    {
-      Kumu::FileReader        Reader;
-      ASDCP::MXF::OPAtomHeader Header;
+   CommandOptions(int argc, const char** argv) :
+     error_flag(true), version_flag(false), help_flag(false), verbose_flag(false), read_mxf_flag(false)
+   {
+     for ( int i = 1; i < argc; i++ )
+       {
 
-      result = Reader.OpenRead(argv[arg_i]);
+        if ( (strcmp( argv[i], "-help") == 0) )
+          {
+            help_flag = true;
+            continue;
+          }
+         
+        if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+          {
+            switch ( argv[i][1] )
+              {
 
-      if ( ASDCP_SUCCESS(result) )
-       result = Header.InitFromFile(Reader);
+              case 'h': help_flag = true; break;
+              case 'r': read_mxf_flag = true; break;
+              case 'V': version_flag = true; break;
+              case 'v': verbose_flag = true; break;
 
-      Header.Dump(stdout);
+              default:
+                fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+                return;
+              }
+          }
+        else
+          {
+            if ( argv[i][0] != '-' )
+              inFileList.push_back(argv[i]);
 
-      if ( ASDCP_SUCCESS(result) )
-       {
-         ASDCP::MXF::OPAtomIndexFooter Index;
-         result = Reader.Seek(Header.FooterPartition);
+            else
+              {
+                        fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+                return;
+              }
+          }
+       }
 
-         if ( ASDCP_SUCCESS(result) )
-           {
-             Index.m_Lookup = &Header.m_Primer;
-             result = Index.InitFromFile(Reader);
-           }
+     if ( help_flag || version_flag )
+       return;
+     
+     if ( inFileList.empty() )
+       {
+        fputs("Input filename(s) required.\n", stderr);
+        return;
+       }
+     
+     error_flag = false;
+   }
+ };
 
-         if ( ASDCP_SUCCESS(result) )
-           Index.Dump(stdout);
-       }
-    }
-  else // dump klv
-    {
-      Kumu::FileReader Reader;
-      KLVFilePacket KP;
 
-      result = Reader.OpenRead(argv[arg_i]);
+//---------------------------------------------------------------------------------------------------
+//
+
+int
+main(int argc, const char** argv)
+{
+  CommandOptions Options(argc, argv);
 
-      if ( ASDCP_SUCCESS(result) )
-       result = KP.InitFromFile(Reader);
+  if ( Options.version_flag )
+    banner();
 
-      while ( ASDCP_SUCCESS(result) )
+  if ( Options.help_flag )
+    usage();
+
+  if ( Options.version_flag || Options.help_flag )
+    return 0;
+
+  if ( Options.error_flag )
+    {
+      fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+      return 3;
+    }
+
+  FileList_t::iterator fi;
+  Result_t result = RESULT_OK;
+
+  for ( fi = Options.inFileList.begin(); ASDCP_SUCCESS(result) && fi != Options.inFileList.end(); fi++ )
+    {
+      if (Options.verbose_flag)
+       fprintf(stderr, "Opening file %s\n", ((*fi).c_str()));
+      
+      if ( Options.read_mxf_flag )
        {
-         KP.Dump(stdout, true);
-         result = KP.InitFromFile(Reader);
+         Kumu::FileReader        Reader;
+         ASDCP::MXF::OPAtomHeader Header;
+         
+         result = Reader.OpenRead((*fi).c_str());
+         
+         if ( ASDCP_SUCCESS(result) )
+           result = Header.InitFromFile(Reader);
+         
+         Header.Dump(stdout);
+         
+         if ( ASDCP_SUCCESS(result) )
+           {
+             ASDCP::MXF::OPAtomIndexFooter Index;
+             result = Reader.Seek(Header.FooterPartition);
+             
+             if ( ASDCP_SUCCESS(result) )
+               {
+                 Index.m_Lookup = &Header.m_Primer;
+                 result = Index.InitFromFile(Reader);
+               }
+             
+             if ( ASDCP_SUCCESS(result) )
+               Index.Dump(stdout);
+           }
+       }
+      else // dump klv
+       {
+         Kumu::FileReader Reader;
+         KLVFilePacket KP;
+         
+         result = Reader.OpenRead((*fi).c_str());
+         
+         if ( ASDCP_SUCCESS(result) )
+           result = KP.InitFromFile(Reader);
+         
+         while ( ASDCP_SUCCESS(result) )
+           {
+             KP.Dump(stdout, true);
+             result = KP.InitFromFile(Reader);
+           }
+         
+         if( result == RESULT_ENDOFFILE )
+           result = RESULT_OK;
        }
-
-      if( result == RESULT_ENDOFFILE )
-       result = RESULT_OK;
     }
 
   if ( ASDCP_FAILURE(result) )
     {
       fputs("Program stopped on error.\n", stderr);
-
+      
       if ( result != RESULT_FAIL )
        {
          fputs(result, stderr);
          fputc('\n', stderr);
        }
-
+      
       return 1;
     }
-
+  
   return 0;
 }
 
diff --git a/src/kmfilegen.cpp b/src/kmfilegen.cpp
new file mode 100755 (executable)
index 0000000..bc1243d
--- /dev/null
@@ -0,0 +1,604 @@
+/*
+Copyright (c) 2005-2006, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*! \file    kmfilegen.cpp
+    \version $Id$
+    \brief   large file test program
+*/
+
+
+#include "AS_DCP.h"
+#include <iostream>
+#include <KM_fileio.h>
+#include <KM_prng.h>
+#include <openssl/aes.h>
+#include <assert.h>
+
+using namespace Kumu;
+
+// constants
+static const char* PACKAGE = "kmfilegen";  // program name for messages
+const ui32_t RNG_KEY_SIZE = 16;
+const ui32_t RNG_KEY_SIZE_BITS = 128;
+const ui32_t RNG_BLOCK_SIZE = 16;
+
+// globals
+ui32_t      s_Nonce = 0;
+FortunaRNG  s_RNG;
+
+
+//------------------------------------------------------------------------------------------
+//
+// command line option parser class
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c)    if ( ++i >= argc || argv[(i)][0] == '-' ) \
+                                 { \
+                                   fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+                                   return; \
+                                 }
+
+//
+void
+banner(FILE* stream = stdout)
+{
+  fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2005-2006 John Hurst\n\
+%s is part of the asdcplib DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+         PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+
+//
+void
+usage(FILE* stream = stdout)
+{
+  fprintf(stream, "\
+USAGE: %s [-c <file-size>][-o <fwd|rev|rand>][-w <filename>][-v]\n\
+       <filename>\n\
+\n\
+       %s [-h|-help] [-V]\n\
+\n\
+  -c <file-size>  - Create a test file containing <file-size> megabytes of data\n\
+  -h | -help      - Show help\n\
+  -o <order>      - Specify order used when validating a file.\n\
+                    One of fwd|rev|rand, default is rand\n\
+  -v              - Verbose. Prints informative messages to stderr\n\
+  -V              - Show version information\n\
+  -w              - Read-Validate-Write - file is written to <filename>\n\
+                    (sequential read only)\n\
+\n\
+  NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+         o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
+
+enum MajorMode_t {
+  MMT_NONE,
+  MMT_CREATE,
+  MMT_VALIDATE,
+  MMT_VAL_WRITE
+};
+
+//
+class CommandOptions
+{
+  CommandOptions();
+
+public:
+  bool   error_flag;     // true if the given options are in error or not complete
+  const char* order;     // one of fwd|rev|rand
+  bool   verbose_flag;   // true if the verbose option was selected
+  bool   version_flag;   // true if the version display option was selected
+  bool   help_flag;      // true if the help display option was selected
+  const char* filename;  // filename to be processed
+  const char* write_filename;  // filename to write with val_write_flag
+  ui32_t chunk_count;
+  MajorMode_t mode;      // MajorMode selector
+
+  //
+  CommandOptions(int argc, const char** argv) :
+    error_flag(true), order(0), verbose_flag(false), version_flag(false), help_flag(false),
+    filename(""), write_filename(""), chunk_count(0), mode(MMT_VALIDATE)
+  {
+    order = "rand";
+
+    for ( int i = 1; i < argc; i++ )
+      {
+
+        if ( (strcmp( argv[i], "-help") == 0) )
+          {
+            help_flag = true;
+            continue;
+          }
+     
+       if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+         {
+           switch ( argv[i][1] )
+             {
+             case 'c':
+               mode = MMT_CREATE;
+               TEST_EXTRA_ARG(i, 'c');
+               chunk_count = atoi(argv[i]);
+               break;
+               
+             case 'V': version_flag = true; break;
+             case 'h': help_flag = true; break;
+             case 'v': verbose_flag = true; break;
+
+             case 'o':
+               TEST_EXTRA_ARG(i, 'o');
+               order = argv[i];
+
+               if ( strcmp(order, "fwd" ) != 0 
+                    && strcmp(order, "rev" ) != 0
+                    && strcmp(order, "rand" ) != 0 )
+                 {
+                   fprintf(stderr, "Unexpected order token: %s, expecting fwd|rev|rand\n", order);
+                   return;
+                 }
+
+               break;
+
+             case 'w':
+               mode = MMT_VAL_WRITE;
+               TEST_EXTRA_ARG(i, 'w');
+               write_filename = argv[i];
+               break;
+                   
+             default:
+               fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+               return;
+             }
+         }
+       else
+         {
+           if (argv[i][0] != '-' )
+             {
+               if ( filename != "" )
+                 {
+                   fprintf(stderr, "Extra filename found: %s\n", argv[i]);
+                   return;
+                 }
+               else
+                 filename = argv[i];
+             }
+           else
+             {
+               fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+               return;
+             }
+         }
+      }
+    
+     if ( help_flag || version_flag )
+       return;
+  
+     if ( strlen ( filename ) == 0 )
+      {
+       fprintf(stderr, "Filename required.\n");
+       return;
+      }
+
+   if ( strcmp ( filename, write_filename ) == 0 )
+     {
+       fprintf(stderr, "Output and input files must be different.\n");
+       return;
+     }
+
+   error_flag = false;
+  }
+};
+
+//------------------------------------------------------------------------------------------
+
+
+//
+#pragma pack(4)
+class CTR_Setup
+{
+  AES_KEY  m_Context;
+  byte_t   m_key[RNG_KEY_SIZE];
+  byte_t   m_preamble[8];
+  ui32_t   m_nonce;
+  ui32_t   m_ctr;
+
+  KM_NO_COPY_CONSTRUCT(CTR_Setup);
+
+public:
+  CTR_Setup() {}
+  ~CTR_Setup() {}
+
+  inline ui32_t Nonce()     { return KM_i32_LE(m_nonce); }
+  inline ui32_t WriteSize() { return ( sizeof(m_key) + sizeof(m_preamble)
+                                      + sizeof(m_nonce) + sizeof(m_ctr) ); }
+
+  //
+  void SetupWrite(byte_t* buf)
+  {
+    assert(buf);
+    s_RNG.FillRandom(m_key, WriteSize());
+    assert(s_Nonce > 0);
+    m_nonce = KM_i32_LE(s_Nonce--);
+    m_ctr &= KM_i32_LE(0x7fffffff); // make sure we have 2GB headroom
+    memcpy(buf, m_key, WriteSize());
+    AES_set_encrypt_key(m_key, RNG_KEY_SIZE_BITS, &m_Context);
+  }
+
+  //
+  void SetupRead(const byte_t* buf)
+  {
+    assert(buf);
+    memcpy(m_key, buf, WriteSize());
+    AES_set_encrypt_key(m_key, RNG_KEY_SIZE_BITS, &m_Context);
+  }
+
+  //
+  void FillRandom(byte_t* buf, ui32_t buf_len)
+  {
+    ui32_t gen_count = 0;
+    while ( gen_count + RNG_BLOCK_SIZE <= buf_len )
+      {
+       AES_encrypt(m_preamble, buf + gen_count, &m_Context);
+       m_ctr = KM_i32_LE(KM_i32_LE(m_ctr) + 1);
+       gen_count += RNG_BLOCK_SIZE;
+      }
+  }
+};
+
+//
+Result_t
+CreateLargeFile(CommandOptions& Options)
+{
+  ui32_t write_total = 0;
+  ui32_t write_count = 0;
+  FileWriter  Writer;
+  ByteString  FB;
+
+  FB.Capacity(Megabyte);
+  assert(FB.Capacity() == Megabyte);
+
+  fprintf(stderr, "Writing %lu chunks:\n", Options.chunk_count);
+  s_Nonce = Options.chunk_count;
+  Result_t result = Writer.OpenWrite(Options.filename);
+
+  while ( KM_SUCCESS(result) && write_total < Options.chunk_count )
+    {
+      if ( KM_SUCCESS(result))
+       {
+         CTR_Setup CTR;
+         CTR.SetupWrite(FB.Data());
+         CTR.FillRandom(FB.Data() + CTR.WriteSize(), Megabyte - CTR.WriteSize());
+         result = Writer.Write(FB.RoData(), Megabyte, &write_count);
+         assert(write_count == Megabyte);
+         fprintf(stderr, "\r%8lu ", ++write_total);
+       }
+    }
+  
+  fputs("\n", stderr);
+
+  return result;
+}
+
+//
+Result_t
+validate_chunk(ByteString& FB, ByteString& CB, ui32_t* nonce_value)
+{
+  assert(nonce_value);
+  CTR_Setup CTR;
+  CTR.SetupRead(FB.RoData());
+
+  CTR.FillRandom(CB.Data() + CTR.WriteSize(),
+                Megabyte - CTR.WriteSize());
+
+  if ( memcmp(FB.RoData() + CTR.WriteSize(),
+             CB.RoData() + CTR.WriteSize(),
+             Megabyte - CTR.WriteSize()) != 0 )
+    {
+      fprintf(stderr, "Check data mismatched in chunk\n");
+      return RESULT_FAIL;
+    }
+
+  *nonce_value = CTR.Nonce();
+
+  return RESULT_OK;
+}
+
+//
+struct read_list_t
+{
+  ui32_t nonce;
+  Kumu::fpos_t position;
+};
+
+//
+void
+randomize_list(read_list_t* read_list, ui32_t check_total)
+{
+  static ui32_t tmp_ints[4];
+  static ui32_t seq = 0;
+
+  for ( ui32_t j = 0; j < check_total; j++ )
+    {
+      if ( seq > 3 )
+       seq = 0;
+
+      if ( seq == 0 )
+       s_RNG.FillRandom((byte_t*)tmp_ints, 16);
+
+      ui32_t i = tmp_ints[seq++] % (check_total - 1);
+
+      if ( i == j )
+       continue;
+
+      read_list_t t = read_list[i];
+      read_list[i] = read_list[j];
+      read_list[j] = t;
+    }
+}
+
+//
+Result_t
+ReadValidateWriteLargeFile(CommandOptions& Options)
+{
+  assert(Options.write_filename);
+  ui32_t  check_total = 0;
+  ui32_t  write_total = 0;
+  ui32_t  read_count = 0;
+  ui32_t write_count = 0;
+  FileReader  Reader;
+  FileWriter  Writer;
+  ByteString  FB, CB; // Frame Buffer and Check Buffer
+
+
+  FB.Capacity(Megabyte);
+  assert(FB.Capacity() == Megabyte);
+  CB.Capacity(Megabyte);
+  assert(CB.Capacity() == Megabyte);
+
+  Result_t result = Reader.OpenRead(Options.filename);
+
+  if ( KM_SUCCESS(result) )
+    result = Writer.OpenWrite(Options.write_filename);
+
+  // read the first chunk and get set up
+  while ( KM_SUCCESS(result) )
+    {
+      result = Reader.Read(FB.Data(), Megabyte, &read_count);
+
+      if ( KM_SUCCESS(result) )
+       {
+         if ( read_count < Megabyte )
+           {
+             fprintf(stderr, "Read() returned short buffer: %lu\n", read_count);
+             result = RESULT_FAIL;
+           }
+
+         result = validate_chunk(FB, CB, &check_total);
+
+         if ( KM_SUCCESS(result) )
+           {
+             result = Writer.Write(FB.RoData(), Megabyte, &write_count);
+             assert(write_count == Megabyte);
+             fprintf(stderr, "\r%8lu ", ++write_total);
+           }
+       }
+      else if ( result == RESULT_ENDOFFILE )
+       {
+         result = RESULT_OK;
+         break;
+       }
+    }
+
+  fputs("\n", stderr);
+  return result;
+}
+
+
+//
+Result_t
+ValidateLargeFile(CommandOptions& Options)
+{
+  ui32_t  check_total = 0;
+  ui32_t  read_count = 0;
+  ui32_t  read_list_i = 0;
+  read_list_t* read_list = 0;
+  FileReader Reader;
+  ByteString FB, CB; // Frame Buffer and Check Buffer
+
+  FB.Capacity(Megabyte);
+  assert(FB.Capacity() == Megabyte);
+  CB.Capacity(Megabyte);
+  assert(CB.Capacity() == Megabyte);
+
+  Result_t result = Reader.OpenRead(Options.filename);
+
+  // read the first chunk and get set up
+  if ( KM_SUCCESS(result) )
+    {
+      result = Reader.Read(FB.Data(), Megabyte, &read_count);
+
+      if ( read_count < Megabyte )
+       {
+         fprintf(stderr, "Read() returned short buffer: %lu\n", read_count);
+         result = RESULT_FAIL;
+       }
+      else if ( KM_SUCCESS(result) )
+       result = validate_chunk(FB, CB, &check_total);
+
+      if ( KM_SUCCESS(result) )
+       {
+         fprintf(stderr, "Validating %lu chunk%s in %s order:\n",
+                 check_total, (check_total == 1 ? "" : "s"), Options.order);
+         assert(read_list == 0);
+         read_list = (read_list_t*)malloc(check_total * sizeof(read_list_t));
+         assert(read_list);
+
+         // Set up an index to the chunks. The chunks are written
+         // to the file in order of descending nonce value.
+         if ( strcmp(Options.order, "fwd") == 0 )
+           {
+             for ( ui32_t i = 0; i < check_total; i++ )
+               {
+                 read_list[i].nonce = check_total - i;
+                 Kumu::fpos_t ofst = check_total - read_list[i].nonce;
+                 read_list[i].position = ofst * (Kumu::fpos_t)Megabyte;
+               }
+           }
+         else
+           {
+             for ( ui32_t i = 0; i < check_total; i++ )
+               {
+                 read_list[i].nonce = i + 1;
+                 Kumu::fpos_t ofst = check_total - read_list[i].nonce;
+                 read_list[i].position = ofst * (Kumu::fpos_t)Megabyte;
+               }
+
+             if ( strcmp(Options.order, "rand") == 0 )
+               randomize_list(read_list, check_total); // this makes it random
+           }
+       }
+    }
+
+  if ( KM_SUCCESS(result) )
+    {
+      assert(read_list);
+      ui32_t nonce = 0;
+
+      for ( read_list_i = 0;
+           read_list_i < check_total && KM_SUCCESS(result);
+           read_list_i++ )
+       {
+         fprintf(stderr, "\r%8lu [%8lu] ", read_list_i+1, read_list[read_list_i]);
+         result = Reader.Seek(read_list[read_list_i].position);
+
+         if ( KM_SUCCESS(result) )
+           result = Reader.Read(FB.Data(), Megabyte, &read_count);
+
+         if ( result == RESULT_ENDOFFILE )
+           break;
+
+         else if ( read_count < Megabyte )
+           {
+             fprintf(stderr, "Read() returned short buffer: %lu\n", read_count);
+             result = RESULT_FAIL;
+           }
+         else if ( KM_SUCCESS(result) )
+           {
+             result = validate_chunk(FB, CB, &nonce);
+             
+             if ( nonce != read_list[read_list_i].nonce )
+               {
+                 fprintf(stderr, "Nonce mismatch: expecting %lu, got %lu\n",
+                         nonce, read_list[read_list_i].nonce);
+
+                 return RESULT_FAIL;
+               }
+           }
+       }
+    }
+
+  fputs("\n", stderr);
+
+  if ( result == RESULT_ENDOFFILE )
+    {
+      if ( check_total == read_list_i )
+       result = RESULT_OK;
+      else
+       {
+         fprintf(stderr, "Unexpected chunk count, got %lu, wanted %lu\n",
+                 read_list_i, check_total);
+         result = RESULT_FAIL;
+       }
+    }
+
+  return result;
+}
+
+//
+int
+main(int argc, const char **argv)
+{
+  Result_t result = RESULT_FAIL;
+  CommandOptions Options(argc, argv);
+
+  if ( Options.version_flag )
+    banner();
+
+  if ( Options.help_flag )
+    usage();
+
+  if ( Options.version_flag || Options.help_flag )
+    return 0;
+
+  if ( Options.error_flag )
+    {
+      fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+      return 3;
+    }
+
+  switch ( Options.mode )
+    {
+
+    case MMT_CREATE:
+      result = CreateLargeFile(Options);
+      break;
+
+    case MMT_VALIDATE:
+      result = ValidateLargeFile(Options);
+      break;
+
+    case MMT_VAL_WRITE:
+      result = ReadValidateWriteLargeFile(Options);
+      break;
+    }
+
+  if ( result != RESULT_OK )
+    {
+      fputs("Program stopped on error.\n", stderr);
+
+      if ( result != RESULT_FAIL )
+       {
+         fputs(result.Label(), stderr);
+         fputc('\n', stderr);
+       }
+
+      return 1;
+    }
+
+  return 0;
+}
+
+
+//
+// end kmfilegen.cpp
+//
diff --git a/src/kmrandgen.cpp b/src/kmrandgen.cpp
new file mode 100644 (file)
index 0000000..c953244
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+Copyright (c) 2005-2006, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+  /*! \file    kmrandgen.cpp
+    \version $Id$
+    \brief   psuedo-random number generation utility
+  */
+
+#include "AS_DCP.h"
+#include <KM_fileio.h>
+#include <KM_prng.h>
+#include <ctype.h>
+
+using namespace Kumu;
+
+const ui32_t RandBlockSize = 16;
+const char* PACKAGE = "kmrandgen";
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c)    if ( ++i >= argc || argv[(i)][0] == '-' ) \
+                                 { \
+                                   fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+                                   return; \
+                                 }
+
+//
+void
+banner(FILE* stream = stdout)
+{
+  fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2003-2006 John Hurst\n\n\
+%s is part of the asdcp DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+         PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+//
+void
+usage(FILE* stream = stdout)
+{
+  fprintf(stream, "\
+USAGE: %s [-b|-c] [-n] [-s <size>]\n\
+\n\
+       %s [-h|-help] [-V]\n\
+\n\
+  -b          - Output a stream of binary data\n\
+  -c          - Output a C-language struct containing the values\n\
+  -h | -help  - Show help\n\
+  -n          - Suppress newlines\n\
+  -s <size>   - Number of random bytes to generate (default 32, supplied value\n\
+                is rounded up to nearest multiple of 16)\n\
+  -v          - Verbose. Prints informative messages to stderr\n\
+  -V          - Show version information\n\
+\n\
+  NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+         o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
+
+//
+class CommandOptions
+{
+  CommandOptions();
+
+public:
+  bool   error_flag;      // true if the given options are in error or not complete
+  bool   no_newline_flag; // 
+  bool   c_array_flag;    // 
+  bool   binary_flag;     // 
+  bool   verbose_flag;    // true if the verbose option was selected
+  bool   version_flag;    // true if the version display option was selected
+  bool   help_flag;       // true if the help display option was selected
+  ui32_t request_size;
+
+ //
+  CommandOptions(int argc, const char** argv) :
+    error_flag(true), no_newline_flag(false), c_array_flag(false), binary_flag(false),
+    verbose_flag(false), version_flag(false), help_flag(false), request_size(32)
+  {
+    ui32_t tmp_size = 0, diff = 0;
+
+    for ( int i = 1; i < argc; i++ )
+      {
+
+        if ( (strcmp( argv[i], "-help") == 0) )
+          {
+            help_flag = true;
+            continue;
+          }
+     
+       if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+         {
+           switch ( argv[i][1] )
+             {
+             case 'b': binary_flag = true; break;
+             case 'c': c_array_flag = true; break;
+             case 'n': no_newline_flag = true; break;
+             case 'h': help_flag = true; break;
+
+             case 's':
+               TEST_EXTRA_ARG(i, 's');
+               tmp_size = atoi(argv[i]);
+               diff = tmp_size % RandBlockSize;
+
+               if ( diff != 0 )
+                 tmp_size += RandBlockSize - diff;
+
+               request_size = tmp_size;
+               break;
+
+             case 'v': verbose_flag = true; break;
+             case 'V': version_flag = true; break;
+
+             default:
+               fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+               return;
+             }
+         }
+       else
+         {
+           fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+           return;
+         }
+      }
+
+       if ( help_flag || version_flag )
+         return;
+
+       if ( binary_flag && c_array_flag )
+         {
+           fprintf(stderr, "Error, must use only one of -b and -c options.\n");
+           return;
+         }
+
+    error_flag = false;
+  }
+};
+
+
+//
+int
+main(int argc, const char** argv)
+{
+  CommandOptions Options(argc, argv);
+
+   if ( Options.version_flag )
+    banner();
+
+  if ( Options.help_flag )
+    usage();
+
+  if ( Options.version_flag || Options.help_flag )
+    return 0;
+
+  if ( Options.error_flag )
+    {
+      fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+      return 3;
+    }
+
+  FortunaRNG    RandGen;
+  ByteString    Buf(Kumu::Kilobyte);
+
+  if ( Options.verbose_flag )
+    fprintf(stderr, "Creating %d random values.\n", Options.request_size);
+
+  if ( Options.binary_flag )
+    {
+      for ( ui32_t i = 0; i < Options.request_size; i += Kumu::Kilobyte )
+       {
+         RandGen.FillRandom(Buf);
+         ui32_t write_size = ((i + Kumu::Kilobyte) > Options.request_size) ? Options.request_size - i : Kumu::Kilobyte;
+         fwrite((byte_t*)Buf.Data(), 1, write_size, stdout);
+       }
+    }
+  else if ( Options.c_array_flag )
+    {
+      byte_t* p = Buf.Data();
+      printf("byte_t rand_buf[%u] = {\n", Options.request_size);
+
+      while ( Options.request_size > 0 )
+       {
+         RandGen.FillRandom(p, RandBlockSize);
+         fputc(' ', stdout);
+
+         for ( ui32_t i = 0; i < RandBlockSize; i++ )
+           printf(" 0x%02x,", p[i]);
+
+         fputc('\n', stdout);
+         Options.request_size -= RandBlockSize;
+       }
+
+      fputs("};", stdout);
+
+      if ( ! Options.no_newline_flag )
+       fputc('\n', stdout);
+    }
+  else
+    {
+      char hex_buf[64];
+      byte_t* p = Buf.Data();
+
+      for ( ui32_t i = 0; i < Options.request_size; i += RandBlockSize )
+       {
+         RandGen.FillRandom(p, RandBlockSize);
+         bin2hex(p, RandBlockSize, hex_buf, 64);
+         fputs(hex_buf, stdout);
+
+         if ( ! Options.no_newline_flag )
+           fputc('\n', stdout);
+       }
+    }
+
+  return 0;
+}
+
+
+//
+// end kmrandgen.cpp
+//
diff --git a/src/kmuuidgen.cpp b/src/kmuuidgen.cpp
new file mode 100644 (file)
index 0000000..bb9afaf
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+Copyright (c) 2005-2006, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+  /*! \file    kmuuidgen.cpp
+    \version $Id$
+    \brief   UUID generation utility
+  */
+
+#include "AS_DCP.h"
+#include <KM_util.h>
+#include <ctype.h>
+
+
+const char* PACKAGE = "kmuuidgen";
+
+// Increment the iterator, test for an additional non-option command line argument.
+// Causes the caller to return if there are no remaining arguments or if the next
+// argument begins with '-'.
+#define TEST_EXTRA_ARG(i,c)    if ( ++i >= argc || argv[(i)][0] == '-' ) \
+                                 { \
+                                   fprintf(stderr, "Argument not found for option -%c.\n", (c)); \
+                                   return; \
+                                 }
+
+//
+void
+banner(FILE* stream = stdout)
+{
+  fprintf(stream, "\n\
+%s (asdcplib %s)\n\n\
+Copyright (c) 2003-2006 John Hurst\n\n\
+%s is part of the asdcp DCP tools package.\n\
+asdcplib may be copied only under the terms of the license found at\n\
+the top of every file in the asdcplib distribution kit.\n\n\
+Specify the -h (help) option for further information about %s\n\n",
+         PACKAGE, ASDCP::Version(), PACKAGE, PACKAGE);
+}
+
+//
+void
+usage(FILE* stream = stdout)
+{
+  fprintf(stream, "\
+USAGE: %s [-c][-n]\n\
+\n\
+       %s [-h|-help] [-V]\n\
+\n\
+  -c          - Output a C-language struct containing the value\n\
+  -h | -help  - Show help\n\
+  -n          - Suppress the newline\n\
+  -v          - Verbose. Prints informative messages to stderr\n\
+  -V          - Show version information\n\
+\n\
+  NOTES: o There is no option grouping, all options must be distinct arguments.\n\
+         o All option arguments must be separated from the option by whitespace.\n\
+\n", PACKAGE, PACKAGE);
+}
+
+//
+class CommandOptions
+{
+  CommandOptions();
+
+public:
+  bool   error_flag;      // true if the given options are in error or not complete
+  bool   no_newline_flag; //
+  bool   c_array_flag;    //
+  bool   version_flag;    // true if the version display option was selected
+  bool   help_flag;       // true if the help display option was selected
+  bool   verbose_flag;    // true if the verbose flag was selected
+
+ //
+  CommandOptions(int argc, const char** argv) :
+    error_flag(true), no_newline_flag(false), c_array_flag(false), version_flag(false),
+    help_flag(false), verbose_flag(false)
+  {
+    for ( int i = 1; i < argc; i++ )
+      {
+
+        if ( (strcmp( argv[i], "-help") == 0) )
+          {
+            help_flag = true;
+            continue;
+          }
+     
+       if ( argv[i][0] == '-' && isalpha(argv[i][1]) && argv[i][2] == 0 )
+         {
+           switch ( argv[i][1] )
+             {
+             case 'c': c_array_flag = true; break;
+             case 'n': no_newline_flag = true; break;
+             case 'h': help_flag = true; break;
+             case 'v': verbose_flag = true; break;
+             case 'V': version_flag = true; break;
+
+             default:
+               fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+               return;
+             }
+         }
+       else
+         {
+           fprintf(stderr, "Unrecognized option: %s\n", argv[i]);
+           return;
+         }
+      }
+
+    if ( help_flag || version_flag )
+      return;
+    
+    error_flag = false;
+  }
+};
+
+
+
+//
+int
+main(int argc, const char** argv)
+{
+  CommandOptions Options(argc, argv);
+
+   if ( Options.version_flag )
+    banner();
+
+  if ( Options.help_flag )
+    usage();
+
+  if ( Options.version_flag || Options.help_flag )
+    return 0;
+
+  if ( Options.error_flag )
+    {
+      fprintf(stderr, "There was a problem. Type %s -h for help.\n", PACKAGE);
+      return 3;
+    }
+
+  Kumu::UUID UUID;
+  Kumu::GenRandomValue(UUID);
+  char uuid_buf[40];
+
+  if ( Options.c_array_flag )
+    {
+      const byte_t* p = UUID.Value();
+
+      printf("\
+byte_t uuid_buf[] = {\n\
+  // %s\n ",
+            UUID.EncodeHex(uuid_buf, 40));
+         
+      for ( ui32_t i = 0; i < 16; i++ )
+       printf(" 0x%02x,", p[i]);
+
+      printf("\n");
+      printf("};\n");
+      return 0;
+    }
+  else
+    {
+      fputs(UUID.EncodeHex(uuid_buf, 40), stdout);
+    }
+
+  if ( Options.no_newline_flag == 0 )
+    printf("\n");
+
+  return 0;
+}
+
+
+//
+// end kmuuidgen.cpp
+//