ReadFileIntoString() modified to return OK when the file is empty
[asdcplib.git] / src / KLV.cpp
index b31969e3467a92b7ce707219a30d4f502d7034b4..303a6725372d1e95b073800563b87132be30e9be 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2009, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -30,7 +30,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include "KLV.h"
-#include <hex_utils.h>
+#include <KM_log.h>
+using Kumu::DefaultLogSink;
 
 
 // This is how much we read when we're reading from a file and we don't know
@@ -44,17 +45,37 @@ const ui32_t tmp_read_size = 32;
 
 // 
 ASDCP::Result_t
-ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len, const byte_t* label)
+ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len, const UL& label)
 {
   Result_t result = KLVPacket::InitFromBuffer(buf, buf_len);
 
   if ( ASDCP_SUCCESS(result) )
-    result = ( memcmp(m_KeyStart, label, SMPTE_UL_LENGTH) == 0 ) ?
-      RESULT_OK : RESULT_FAIL;
+    result = ( UL(m_KeyStart) == label ) ? RESULT_OK : RESULT_FAIL;
 
   return result;
 }
 
+//
+ASDCP::UL
+ASDCP::KLVPacket::GetUL()
+{
+  if ( m_KeyStart != 0 )
+    return UL(m_KeyStart);
+
+  return m_UL;
+}
+
+//
+bool
+ASDCP::KLVPacket::SetUL(const UL& new_ul)
+{
+  if ( m_KeyStart != 0 )
+    return false;
+
+  m_UL = new_ul;
+  return true;
+}
+
 //
 ASDCP::Result_t
 ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
@@ -69,12 +90,29 @@ ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
       return RESULT_FAIL;
     }
 
+  ui32_t ber_len = Kumu::BER_length(buf + SMPTE_UL_LENGTH);
+
+  if ( ber_len > ( buf_len - SMPTE_UL_LENGTH ) )
+    {
+      DefaultLogSink().Error("BER encoding length exceeds buffer size.\n");
+      return RESULT_FAIL;
+    }
+
+  if ( ber_len == 0 )
+    {
+      DefaultLogSink().Error("KLV format error, zero BER length not allowed.\n");
+      return RESULT_FAIL;
+    }
+
   ui64_t tmp_size;
-  if ( ! read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
-       return RESULT_FAIL;
+  if ( ! Kumu::read_BER(buf + SMPTE_UL_LENGTH, &tmp_size) )
+    {
+      DefaultLogSink().Error("KLV format error, BER decode failure.\n");
+      return RESULT_FAIL;
+    }
 
   m_ValueLength = tmp_size;
-  m_KLLength = SMPTE_UL_LENGTH + BER_length(buf + SMPTE_UL_LENGTH);
+  m_KLLength = SMPTE_UL_LENGTH + Kumu::BER_length(buf + SMPTE_UL_LENGTH);
   m_KeyStart = buf;
   m_ValueStart = buf + m_KLLength;
   return RESULT_OK;
@@ -84,25 +122,34 @@ ASDCP::KLVPacket::InitFromBuffer(const byte_t* buf, ui32_t buf_len)
 bool
 ASDCP::KLVPacket::HasUL(const byte_t* ul)
 {
-  if ( m_KeyStart == 0 )
-    return false;
+  if ( m_KeyStart != 0 )
+    {
+      return UL(ul) == UL(m_KeyStart);
+    }
 
-  return ( memcmp(ul, m_KeyStart, SMPTE_UL_LENGTH) == 0 ) ? true : false;
+  if ( m_UL.HasValue() )
+    {
+      return UL(ul) == m_UL;
+    }
+
+  return false;
 }
 
 //
 ASDCP::Result_t
-ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const byte_t* label, ui32_t length)
+ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const UL& label, ui32_t length)
 {
+  assert(label.HasValue());
+
   if ( Buffer.Size() + kl_length > Buffer.Capacity() )
     {
       DefaultLogSink().Error("Small write buffer\n");
       return RESULT_FAIL;
     }
   
-  memcpy(Buffer.Data() + Buffer.Size(), label, SMPTE_UL_LENGTH);
+  memcpy(Buffer.Data() + Buffer.Size(), label.Value(), label.Size());
 
-  if ( ! write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
+  if ( ! Kumu::write_BER(Buffer.Data() + Buffer.Size() + SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
     return RESULT_FAIL;
 
   Buffer.Size(Buffer.Size() + kl_length);
@@ -111,23 +158,28 @@ ASDCP::KLVPacket::WriteKLToBuffer(ASDCP::FrameBuffer& Buffer, const byte_t* labe
 
 //
 void
-ASDCP::KLVPacket::Dump(FILE* stream, bool show_hex)
+ASDCP::KLVPacket::Dump(FILE* stream, const Dictionary& Dict, bool show_value)
 {
+  char buf[64];
+
   if ( stream == 0 )
     stream = stderr;
 
   if ( m_KeyStart != 0 )
     {
       assert(m_ValueStart);
+      UL TmpUL(m_KeyStart);
+      fprintf(stream, "%s", TmpUL.EncodeString(buf, 64));
 
-      for ( ui32_t i = 0; i < SMPTE_UL_LENGTH; i++ )
-       fprintf(stream, "%02x.", m_KeyStart[i]);
+      const MDDEntry* Entry = Dict.FindULAnyVersion(m_KeyStart);
+      fprintf(stream, "  len: %7llu (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
 
-      const MDDEntry* Entry = Dict::FindUL(m_KeyStart);
-      fprintf(stream, "\b  len: %7lu (%s)\n", m_ValueLength, (Entry ? Entry->name : "Unknown"));
-
-      if ( show_hex && m_ValueLength < 1000 )
-       hexdump(m_ValueStart, ASDCP::xmin(m_ValueLength, (ui32_t)64), stream);
+      if ( show_value && m_ValueLength < 1000 )
+       Kumu::hexdump(m_ValueStart, Kumu::xmin(m_ValueLength, (ui64_t)128), stream);
+    }
+  else if ( m_UL.HasValue() )
+    {
+      fprintf(stream, "%s\n", m_UL.EncodeString(buf, 64));
     }
   else
     {
@@ -137,20 +189,19 @@ ASDCP::KLVPacket::Dump(FILE* stream, bool show_hex)
 
 // 
 ASDCP::Result_t
-ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader, const byte_t* label)
+ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader, const UL& label)
 {
   Result_t result = KLVFilePacket::InitFromFile(Reader);
 
   if ( ASDCP_SUCCESS(result) )
-    result = ( memcmp(m_KeyStart, label, SMPTE_UL_LENGTH) == 0 ) ?
-      RESULT_OK : RESULT_FAIL;
+    result = ( UL(m_KeyStart) == label ) ? RESULT_OK : RESULT_FAIL;
 
   return result;
 }
 
-//
+// TODO: refactor to use InitFromBuffer
 ASDCP::Result_t
-ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
+ASDCP::KLVFilePacket::InitFromFile(const Kumu::FileReader& Reader)
 {
   ui32_t read_count;
   byte_t tmp_data[tmp_read_size];
@@ -166,7 +217,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
 
   if ( read_count < (SMPTE_UL_LENGTH + 1) )
     {
-      DefaultLogSink().Error("Short read of Key and Length got %lu\n", read_count);
+      DefaultLogSink().Error("Short read of Key and Length got %u\n", read_count);
       return RESULT_READFAIL;
     }
 
@@ -177,7 +228,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
       return RESULT_FAIL;
     }
 
-  if ( ! read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
+  if ( ! Kumu::read_BER(tmp_data + SMPTE_UL_LENGTH, &tmp_size) )
     {
       DefaultLogSink().Error("BER Length decoding error\n");
       return RESULT_FAIL;
@@ -185,16 +236,16 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
 
   if ( tmp_size > MAX_KLV_PACKET_LENGTH )
     {
-      char intbuf[IntBufferLen];
-      DefaultLogSink().Error("Packet length %s exceeds internal limit\n",
-                            ui64sz(tmp_size, intbuf));
+      Kumu::ui64Printer tmp_size_str(tmp_size);
+      DefaultLogSink().Error("Packet length %s exceeds internal limit\n", tmp_size_str.c_str());
       return RESULT_FAIL;
     }
 
   ui32_t remainder = 0;
-  ui32_t ber_len = BER_length(tmp_data + SMPTE_UL_LENGTH);
+  ui32_t ber_len = Kumu::BER_length(tmp_data + SMPTE_UL_LENGTH);
   m_KLLength = SMPTE_UL_LENGTH + ber_len;
-  m_ValueLength = tmp_size;
+  assert(tmp_size <= 0xFFFFFFFFL);
+  m_ValueLength = (ui32_t) tmp_size;
   ui32_t packet_length = m_ValueLength + m_KLLength;
 
   result = m_Buffer.Capacity(packet_length);
@@ -215,7 +266,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
       if ( (remainder = read_count - packet_length) != 0 )
        {
          DefaultLogSink().Warn("Repositioning pointer for short packet\n");
-         ASDCP::fpos_t pos = Reader.Tell();
+         Kumu::fpos_t pos = Reader.Tell();
          assert(pos > remainder);
          result = Reader.Seek(pos - remainder);
        }
@@ -224,7 +275,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
     {
       if ( read_count < tmp_read_size )
        {
-         DefaultLogSink().Error("Short read of packet body, expecting %lu, got %lu\n",
+         DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
                                 m_Buffer.Size(), read_count);
          return RESULT_READFAIL;
        }
@@ -238,7 +289,7 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
       
          if ( read_count != remainder )
            {
-             DefaultLogSink().Error("Short read of packet body, expecting %lu, got %lu\n",
+             DefaultLogSink().Error("Short read of packet body, expecting %u, got %u\n",
                                     remainder+tmp_read_size, read_count+tmp_read_size);
              result = RESULT_READFAIL;
            }
@@ -250,12 +301,12 @@ ASDCP::KLVFilePacket::InitFromFile(const FileReader& Reader)
 
 //
 ASDCP::Result_t
-ASDCP::KLVFilePacket::WriteKLToFile(FileWriter& Writer, const byte_t* label, ui32_t length)
+ASDCP::KLVFilePacket::WriteKLToFile(Kumu::FileWriter& Writer, const UL& label, ui32_t length)
 {
   byte_t buffer[kl_length];
-  memcpy(buffer, label, SMPTE_UL_LENGTH);
+  memcpy(buffer, label.Value(), label.Size());
 
-  if ( ! write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
+  if ( ! Kumu::write_BER(buffer+SMPTE_UL_LENGTH, length, MXF_BER_LENGTH) )
     return RESULT_FAIL;
 
   ui32_t write_count;