From e564a9810fe1937be7028b0d880bcd2e50d58085 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@Germany>
Date: Mon, 9 Aug 2010 17:27:09 +0200
Subject: [PATCH] ENH: add IO support for PackedList, PackedBoolList

---
 .../test/PackedList1/PackedListTest1.C        |  82 ++---
 .../test/PackedList3/PackedListTest3.C        |   3 +-
 .../test/PackedList4/PackedListTest4.C        |  36 +-
 src/OpenFOAM/Make/files                       |   2 +-
 src/OpenFOAM/containers/Lists/List/ListIO.C   |   2 +-
 .../Lists/PackedList/PackedBoolList.C         | 322 ++++++++++++++++++
 .../Lists/PackedList/PackedBoolList.H         |  44 ++-
 .../Lists/PackedList/PackedBoolListI.H        |   8 +
 .../containers/Lists/PackedList/PackedList.C  | 205 +++++++++++
 .../containers/Lists/PackedList/PackedList.H  |  28 +-
 .../db/IOstreams/Sstreams/readHexLabel.C      |   5 +-
 11 files changed, 686 insertions(+), 51 deletions(-)

diff --git a/applications/test/PackedList1/PackedListTest1.C b/applications/test/PackedList1/PackedListTest1.C
index 5e1902f3828..461db541586 100644
--- a/applications/test/PackedList1/PackedListTest1.C
+++ b/applications/test/PackedList1/PackedListTest1.C
@@ -42,42 +42,42 @@ int main(int argc, char *argv[])
 
     Info<< "\ntest allocation with value\n";
     PackedList<3> list1(5,1);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign uniform value\n";
     list1 = 3;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign uniform value (with overflow)\n";
     list1 = -1;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest zero\n";
     list1 = 0;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest set() with default argument (max_value)\n";
     list1.set(1);
     list1.set(3);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest unset() with in-range and out-of-range\n";
     list1.unset(3);
     list1.unset(100000);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign between references\n";
     list1[2] = 3;
     list1[4] = list1[2];
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign between references, with chaining\n";
     list1[0] = list1[4] = 1;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign between references, with chaining and auto-vivify\n";
     list1[1] = list1[8] = list1[10] = list1[14] = 2;
-    list1.print(Info);
+    list1.print(Info, true);
 
 
     Info<< "\ntest operator== between references\n";
@@ -126,7 +126,7 @@ int main(int argc, char *argv[])
     {
         const PackedList<3>& constLst = list1;
         Info<< "\ntest operator[] const with out-of-range index\n";
-        constLst.print(Info);
+        constLst.print(Info, true);
         if (constLst[20])
         {
             Info<< "[20] is true (unexpected)\n";
@@ -136,7 +136,7 @@ int main(int argc, char *argv[])
             Info<< "[20] is false (expected) list size should be unchanged "
                 << "(const)\n";
         }
-        constLst.print(Info);
+        constLst.print(Info, true);
 
         Info<< "\ntest operator[] non-const with out-of-range index\n";
         if (list1[20])
@@ -148,7 +148,7 @@ int main(int argc, char *argv[])
             Info<< "[20] is false (expected) but list was resized?? "
                 << "(non-const)\n";
         }
-        list1.print(Info);
+        list1.print(Info, true);
     }
 
 
@@ -157,85 +157,85 @@ int main(int argc, char *argv[])
     {
         Info<< "[20] is false, as expected\n";
     }
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest resize with value (without reallocation)\n";
     list1.resize(8, list1.max_value());
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest flip() function\n";
     list1.flip();
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\nre-flip()\n";
     list1.flip();
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest set() function\n";
     list1.set(1, 5);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign bool\n";
     list1 = false;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest assign bool\n";
     list1 = true;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest resize without value (with reallocation)\n";
     list1.resize(12);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest resize with value (with reallocation)\n";
     list1.resize(25, list1.max_value());
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest resize smaller (should not touch allocation)\n";
     list1.resize(8);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest append() operation\n";
     list1.append(2);
     list1.append(3);
     list1.append(4);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest reserve() operation\n";
     list1.reserve(32);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest shrink() operation\n";
     list1.shrink();
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest setCapacity() operation\n";
     list1.setCapacity(15);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest setCapacity() operation\n";
     list1.setCapacity(100);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest operator[] assignment\n";
     list1[16] = 5;
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest operator[] assignment with auto-vivify\n";
     list1[36] = list1.max_value();
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest setCapacity smaller\n";
     list1.setCapacity(24);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest resize much smaller\n";
     list1.resize(150);
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest trim\n";
     list1.trim();
-    list1.print(Info);
+    list1.print(Info, true);
 
     // add in some misc values
     list1[31] = 1;
@@ -250,7 +250,7 @@ int main(int argc, char *argv[])
     Info<< "iterator:" << iter() << "\n";
     iter() = 5;
     iter.print(Info);
-    list1.print(Info);
+    list1.print(Info, true);
 
     iter = list1[31];
     Info<< "iterator:" << iter() << "\n";
@@ -259,7 +259,7 @@ int main(int argc, char *argv[])
 
     Info<< "\ntest get() method\n";
     Info<< "get(10):" << list1.get(10) << " and list[10]:" << list1[10] << "\n";
-    list1.print(Info);
+    list1.print(Info, true);
 
     Info<< "\ntest iterator indexing\n";
     Info<< "cend() ";
@@ -267,7 +267,7 @@ int main(int argc, char *argv[])
 
     {
         Info<< "\ntest assignment of iterator\n";
-        list1.print(Info);
+        list1.print(Info, true);
         Info<< "cend()\n";
         list1.end().print(Info);
         PackedList<3>::iterator cit = list1[100];
@@ -304,16 +304,16 @@ int main(int argc, char *argv[])
     Info<< "size after write:" << list1.size() << "\n";
     Info<< "list[45]:" << list1[45] << "\n";
     list1[49] = list1[100];
-    list1.print(Info);
+    list1.print(Info, true);
 
 
     Info<< "\ntest copy constructor + append\n";
     PackedList<3> list2(list1);
     list2.append(4);
     Info<< "source list:\n";
-    list1.print(Info);
+    list1.print(Info, true);
     Info<< "destination list:\n";
-    list2.print(Info);
+    list2.print(Info, true);
 
     Info<< "\ntest pattern that fills all bits\n";
     PackedList<4> list3(8, 8);
@@ -323,10 +323,12 @@ int main(int argc, char *argv[])
     list3[pos--] = list3.max_value();
     list3[pos--] = 0;
     list3[pos--] = list3.max_value();
-    list3.print(Info);
+    list3.print(Info, true);
 
     Info<< "removed final value: " << list3.remove() << endl;
-    list3.print(Info);
+    list3.print(Info, true);
+
+    Info<<"list: " << list3 << endl;
 
 
     List<bool> list4(16, false);
diff --git a/applications/test/PackedList3/PackedListTest3.C b/applications/test/PackedList3/PackedListTest3.C
index 5ff6ee8644b..7b27ffda09a 100644
--- a/applications/test/PackedList3/PackedListTest3.C
+++ b/applications/test/PackedList3/PackedListTest3.C
@@ -33,7 +33,6 @@ Description
 #include "StaticHashTable.H"
 #include "cpuTime.H"
 #include <vector>
-#include "PackedList.H"
 #include "PackedBoolList.H"
 
 using namespace Foam;
@@ -57,7 +56,7 @@ int main(int argc, char *argv[])
     {
         if ((i % nReport) == 0 && i)
         {
-            Info<< "i:" << i << " in " << timer.cpuTimeIncrement() << " s" 
+            Info<< "i:" << i << " in " << timer.cpuTimeIncrement() << " s"
                 <<endl;
         }
         packed[i] = 1;
diff --git a/applications/test/PackedList4/PackedListTest4.C b/applications/test/PackedList4/PackedListTest4.C
index 7271a3f1dd2..d1e4e5b143d 100644
--- a/applications/test/PackedList4/PackedListTest4.C
+++ b/applications/test/PackedList4/PackedListTest4.C
@@ -30,6 +30,7 @@ Description
 #include "uLabel.H"
 #include "IOstreams.H"
 #include "PackedBoolList.H"
+#include "IStringStream.H"
 
 using namespace Foam;
 
@@ -45,7 +46,7 @@ int main(int argc, char *argv[])
         list1[i] = i % 2;
     }
 
-    Info<< "\nalternative bit pattern\n";
+    Info<< "\nalternating bit pattern\n";
     list1.print(Info, true);
 
     PackedBoolList list2 = ~list1;
@@ -117,6 +118,39 @@ int main(int argc, char *argv[])
         (list3 -= list2Labels).print(Info, true);
     }
 
+
+    PackedBoolList list4
+    (
+        IStringStream
+        (
+            "(AB 05 10 0F F0)"
+        )()
+    );
+
+    Info<< "\ntest Istream constructor\n";
+
+    list4.print(Info, true);
+    Info<< list4 << " indices: " << list4.used()() <<endl;
+
+    Info<< "\nassign from labelList\n";
+    list4 = labelList
+    (
+        IStringStream
+        (
+            "(0 1 2 3 12 13 14 15 17 19 20 21)"
+        )()
+    );
+
+    list4.print(Info, true);
+    Info<< list4 << " indices: " << list4.used()() <<endl;
+
+    Info<< "\nread from Istream\n";
+    IStringStream("(0f 3a)")() >> list4;
+
+    list4.print(Info, true);
+    Info<< list4 << " indices: " << list4.used()() <<endl;
+
+
     return 0;
 }
 
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index bc4369cf48e..30289870e38 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -67,7 +67,7 @@ containers/HashTables/HashTable/HashTableCore.C
 containers/HashTables/StaticHashTable/StaticHashTableCore.C
 containers/Lists/SortableList/ParSortableListName.C
 containers/Lists/PackedList/PackedListName.C
-containers/Lists/PackedList/APackedBoolList.C
+containers/Lists/PackedList/PackedBoolList.C
 containers/Lists/ListOps/ListOps.C
 containers/LinkedLists/linkTypes/SLListBase/SLListBase.C
 containers/LinkedLists/linkTypes/DLListBase/DLListBase.C
diff --git a/src/OpenFOAM/containers/Lists/List/ListIO.C b/src/OpenFOAM/containers/Lists/List/ListIO.C
index 984971ecc46..a70cc8f9e6b 100644
--- a/src/OpenFOAM/containers/Lists/List/ListIO.C
+++ b/src/OpenFOAM/containers/Lists/List/ListIO.C
@@ -135,7 +135,7 @@ Foam::Istream& Foam::operator>>(Istream& is, List<T>& L)
                 << exit(FatalIOError);
         }
 
-        // Putback the openning bracket
+        // Putback the opening bracket
         is.putBack(firstToken);
 
         // Now read as a singly-linked list
diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.C b/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.C
index f393e144daa..548d21414de 100644
--- a/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.C
+++ b/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.C
@@ -24,9 +24,51 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "PackedBoolList.H"
+#include "IOstreams.H"
+#include <cctype>
+
+// * * * * * * * * * * * * * * * Static Members * * * * * * * * * * * * * * * //
+
+// table-lookup instead of printf("%02x", char)
+//! @cond localScope
+static const char hexLookup[] =
+{
+    "000102030405060708090a0b0c0d0e0f"
+    "101112131415161718191a1b1c1d1e1f"
+    "202122232425262728292a2b2c2d2e2f"
+    "303132333435363738393a3b3c3d3e3f"
+    "404142434445464748494a4b4c4d4e4f"
+    "505152535455565758595a5b5c5d5e5f"
+    "606162636465666768696a6b6c6d6e6f"
+    "707172737475767778797a7b7c7d7e7f"
+    "808182838485868788898a8b8c8d8e8f"
+    "909192939495969798999a9b9c9d9e9f"
+    "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+    "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+    "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+    "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+    "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+    "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+};
+
+
+// number of bytes required to pack nElem
+static inline unsigned int packedBytes(const Foam::label nElem)
+{
+    return (nElem + CHAR_BIT - 1) / CHAR_BIT;
+}
+//! @endcond
+
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
+Foam::PackedBoolList::PackedBoolList(Istream &is)
+:
+    PackedList<1>()
+{
+    is  >> *this;
+}
+
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
 
@@ -232,6 +274,286 @@ Foam::PackedBoolList::operator^=(const PackedList<1>& lst)
     return *this;
 }
 
+// * * * * * * * * * * * * * *  Friend Operators * * * * * * * * * * * * * * //
+
+Foam::Istream& Foam::operator>>
+(
+    Istream& istr,
+    PackedBoolList& lst
+)
+{
+    // Takes into account that 'a' (or 'A') is 10
+    static const label alphaOffset = toupper('A') - 10;
+    // Takes into account that '0' is 0
+    static const label zeroOffset = int('0');
+
+    ISstream& is = dynamicCast<ISstream>(istr);
+
+    lst.clear();
+    is.fatalCheck("operator>>(Istream&, PackedBoolList&)");
+
+    token firstTok(is);
+    is.fatalCheck
+    (
+        "operator>>(Istream&, PackedBoolList&) : reading first token"
+    );
+
+    if (firstTok.isLabel())
+    {
+        const label sz = firstTok.labelToken();
+
+        // Set list length to that read
+        lst.resize(sz);
+
+        // Read list contents as ASCII
+
+        // Read beginning of contents
+        const char delimiter = is.readBeginList("PackedBoolList");
+
+        if (sz)
+        {
+            if (delimiter == token::BEGIN_LIST)
+            {
+                // number of bytes when packed:
+                unsigned int nBytes = packedBytes(lst.size());
+
+                for (label i=0, storeI=0; i < sz; ++storeI)
+                {
+                    PackedList<1>::StorageType& stored = lst.storage()[storeI];
+
+                    // byte-wise read
+                    for
+                    (
+                        unsigned byte=0;
+                        byte < sizeof(PackedList<1>::StorageType);
+                        ++byte
+                    )
+                    {
+                        PackedList<1>::StorageType result = 0;
+                        char c = 0;
+
+                        // Get next non-whitespace character
+                        while (is.get(c) && isspace(c))
+                        {}
+
+                        for (label nibble=0; nibble < 2; ++nibble)
+                        {
+                            if (!isxdigit(c))
+                            {
+                                FatalIOErrorIn
+                                (
+                                    "operator>>(Istream&, PackedBoolList&) : "
+                                    "reading first token",
+                                    is
+                                )
+                                    << "Illegal hex digit: '" << c << "'"
+                                    << exit(FatalIOError);
+                            }
+
+                            result <<= 4;
+
+                            if (isdigit(c))
+                            {
+                                result += int(c) - zeroOffset;
+                            }
+                            else
+                            {
+                                result += toupper(c) - alphaOffset;
+                            }
+
+                            // Get character for the lower part of the byte
+                            if (!nibble)
+                            {
+                                is.get(c);
+                            }
+                        }
+
+                        stored |= result << (byte*CHAR_BIT);
+
+                        if (!--nBytes)
+                        {
+                            break;
+                        }
+                    }
+                    i += PackedList<1>::packing();
+                }
+
+                // trim possible trailing junk
+                // mask off the final partial segment
+                {
+                    const unsigned int off = sz % PackedList<1>::packing();
+                    if (off)
+                    {
+                        const unsigned int seg = sz / PackedList<1>::packing();
+
+                        lst.storage()[seg] &= PackedList<1>::maskLower(off);
+                    }
+                }
+
+
+                // skip over all trailing whitespace and zeroes
+                char c = 0;
+                while (is.get(c) && (isspace(c) || c == '0'))
+                {}
+
+                // put back for later readEndList() to deal with
+                is.putback(c);
+            }
+            else
+            {
+                const label val = readLabel(is);
+
+                is.fatalCheck
+                (
+                    "operator>>(Istream&, PackedBoolList&) : "
+                    "reading the single entry"
+                );
+
+                lst = val;
+            }
+        }
+
+        // Read end of contents
+        is.readEndList("PackedList");
+    }
+    else if (firstTok.isPunctuation())
+    {
+        if (firstTok.pToken() != token::BEGIN_LIST)
+        {
+            FatalIOErrorIn
+            (
+                "operator>>(Istream&, PackedBoolList&)",
+                is
+            )
+                << "incorrect first token, expected '(', found "
+                << firstTok.info()
+                << exit(FatalIOError);
+        }
+
+        char c = '(';
+
+        for (label storeI=0; c && c != ')'; ++storeI)
+        {
+            lst.resize((storeI+1)*PackedList<1>::packing());
+
+            PackedList<1>::StorageType& stored = lst.storage()[storeI];
+
+            // byte-wise read
+            for
+            (
+                unsigned byte=0;
+                byte < sizeof(PackedList<1>::StorageType);
+                ++byte
+            )
+            {
+                PackedList<1>::StorageType result = 0;
+                c = 0;
+
+                // Get next non-whitespace character
+                while (is.get(c) && isspace(c))
+                {}
+
+                if (!c || c == ')')
+                {
+                    break;
+                }
+
+                for (label nibble=0; nibble < 2; ++nibble)
+                {
+                    if (!isxdigit(c))
+                    {
+                        FatalIOErrorIn
+                        (
+                            "operator>>(Istream&, PackedBoolList&)",
+                            is
+                        )
+                            << "Illegal hex digit: '" << c << "'"
+                            << exit(FatalIOError);
+                    }
+
+                    result *= 16;
+
+                    if (isdigit(c))
+                    {
+                        result += int(c) - zeroOffset;
+                    }
+                    else
+                    {
+                        result += toupper(c) - alphaOffset;
+                    }
+
+                    // Get character for the lower part of the byte
+                    if (!nibble)
+                    {
+                        is.get(c);
+                    }
+                }
+
+                stored |= result << (byte*CHAR_BIT);
+            }
+        }
+
+        // put back for later readEndList() to deal with
+        is.putback(c);
+
+        // Read end of contents
+        is.readEndList("PackedList");
+    }
+    else
+    {
+        FatalIOErrorIn
+        (
+            "operator>>(Istream&, PackedBoolList&)",
+            is
+        )
+            << "incorrect first token, expected <int> or '(', found "
+            << firstTok.info()
+            << exit(FatalIOError);
+    }
+
+    return is;
+}
+
+
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    const PackedBoolList& lst
+)
+{
+    const label sz = lst.size();
+
+    unsigned int nBytes = packedBytes(sz);
+
+    os  << sz << token::BEGIN_LIST;
+
+    for (label storeI=0; nBytes; ++storeI)
+    {
+        PackedList<1>::StorageType stored = lst.storage()[storeI];
+
+        for
+        (
+            unsigned byte=0;
+            byte < sizeof(PackedList<1>::StorageType);
+            ++byte
+        )
+        {
+            os  << hexLookup[((stored & 0xFF) << 1)]
+                << hexLookup[((stored & 0xFF) << 1) + 1];
+
+            if (!--nBytes)
+            {
+                break;
+            }
+            stored >>= 8;
+        }
+    }
+
+    os  << token::END_LIST;
+
+    return os;
+}
+
 
 // * * * * * * * * * * * * * *  Global Operators * * * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.H b/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.H
index 1d2b19ac078..cf0ba7d6a56 100644
--- a/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.H
+++ b/src/OpenFOAM/containers/Lists/PackedList/PackedBoolList.H
@@ -27,6 +27,31 @@ Class
 Description
     A bit-packed bool list
 
+Note
+    The input/output format differs from that of Foam::PackedBoolList in
+    that it is also packed. The input/output is always byte-wise, with
+    the lowest bytes first.
+
+    Thus this label sequence
+    @code
+        0 1 2 3 12 13 14 15 17 19 20 21
+    @endcode
+    which has this bit representation:
+    @code
+        ..........111-1-1111--------1111
+    @endcode
+    and this internal representation
+    @code
+        0x003AF00F
+    @endcode
+    would be read/written in one of these formats:
+    @code
+        22(0f f0 3a)
+        22(0ff03a)
+    @endcode
+    Whitespace can be used to separate byte values, but must not appear
+    within a byte itself.
+
 SourceFiles
     PackedBoolListI.H
     PackedBoolList.C
@@ -47,6 +72,16 @@ SeeAlso
 namespace Foam
 {
 
+// Forward declaration of classes
+class Istream;
+class Ostream;
+
+// Forward declaration of friend functions and operators
+class PackedBoolList;
+Istream& operator>>(Istream&, PackedBoolList&);
+Ostream& operator<<(Ostream&, const PackedBoolList&);
+
+
 /*---------------------------------------------------------------------------*\
                        Class PackedBoolList Declaration
 \*---------------------------------------------------------------------------*/
@@ -55,7 +90,6 @@ class PackedBoolList
 :
     public PackedList<1>
 {
-
     // Private Member Functions
 
         //- Modulo is everything that is not in lst
@@ -72,7 +106,6 @@ class PackedBoolList
         template<class LabelListType>
         label unsetFromIndices(const LabelListType& indices);
 
-
 public:
 
     // Constructors
@@ -80,6 +113,9 @@ public:
         //- Construct null
         inline PackedBoolList();
 
+        //- Construct from Istream
+        PackedBoolList(Istream&);
+
         //- Construct with given size, initializes list to 0
         explicit inline PackedBoolList(const label size);
 
@@ -217,6 +253,10 @@ public:
             //- Remove entries from this list
             inline PackedBoolList& operator-=(const UIndirectList<label>&);
 
+    // IOstream Operators
+
+        friend Istream& operator>>(Istream&, PackedBoolList&);
+        friend Ostream& operator<<(Ostream&, const PackedBoolList&);
 };
 
 
diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedBoolListI.H b/src/OpenFOAM/containers/Lists/PackedList/PackedBoolListI.H
index f9a7f383e41..754590a864d 100644
--- a/src/OpenFOAM/containers/Lists/PackedList/PackedBoolListI.H
+++ b/src/OpenFOAM/containers/Lists/PackedList/PackedBoolListI.H
@@ -73,6 +73,14 @@ inline Foam::PackedBoolList::PackedBoolList(const Xfer<PackedList<1> >& lst)
 {}
 
 
+inline Foam::PackedBoolList::PackedBoolList(const UList<bool>& lst)
+:
+    PackedList<1>()
+{
+    operator=(lst);
+}
+
+
 inline Foam::PackedBoolList::PackedBoolList(const UList<label>& indices)
 :
     PackedList<1>(indices.size(), 0u)
diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C
index b077c1c54b9..cb80e6db02b 100644
--- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C
+++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C
@@ -24,6 +24,8 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "PackedList.H"
+#include "IOstreams.H"
+
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -40,6 +42,16 @@ Foam::PackedList<nBits>::PackedList(const label size, const unsigned int val)
 }
 
 
+template<unsigned nBits>
+Foam::PackedList<nBits>::PackedList(Istream& is)
+:
+    StorageList(),
+    size_(0)
+{
+    is  >> *this;
+}
+
+
 template<unsigned nBits>
 Foam::PackedList<nBits>::PackedList(const UList<label>& lst)
 :
@@ -290,4 +302,197 @@ Foam::PackedList<nBits>::operator=(const UList<label>& lst)
 }
 
 
+// * * * * * * * * * * * * * *  Friend Operators * * * * * * * * * * * * * * //
+
+template<unsigned nBits>
+Foam::Istream& Foam::operator>>
+(
+    Istream& is,
+    PackedList<nBits>& lst
+)
+{
+    lst.clear();
+    is.fatalCheck("operator>>(Istream&, PackedList<nBits>&)");
+
+    token firstTok(is);
+    is.fatalCheck
+    (
+        "operator>>(Istream&, PackedList<nBits>&) : reading first token"
+    );
+
+    if (firstTok.isLabel())
+    {
+        const label sz = firstTok.labelToken();
+
+        // Set list length to that read
+        lst.setSize(sz);
+
+        {
+            // Read beginning of contents
+            const char delimiter = is.readBeginList("List");
+
+            if (sz)
+            {
+                unsigned int val;
+
+                if (delimiter == token::BEGIN_LIST)
+                {
+                    for (register label i=0; i<sz; ++i)
+                    {
+                        is  >> val;
+
+                        if (val > lst.max_value())
+                        {
+                            FatalIOErrorIn
+                            (
+                                "operator>>(Istream&, PackedList<nBits>&)",
+                                is
+                            )
+                                << "out-of-range value: "
+                                << val << " > " << lst.max_value()
+                                << exit(FatalIOError);
+                        }
+
+                        is.fatalCheck
+                        (
+                            "operator>>(Istream&, PackedList<nBits>&) : "
+                            "reading entry"
+                        );
+                    }
+                }
+                else
+                {
+                    is  >> val;
+
+                    is.fatalCheck
+                    (
+                        "operator>>(Istream&, PackedList<nBits>&) : "
+                        "reading the single entry"
+                    );
+
+                    if (val > lst.max_value())
+                    {
+                        FatalIOErrorIn
+                        (
+                            "operator>>(Istream&, PackedList<nBits>&)",
+                            is
+                        )
+                            << "out-of-range value: "
+                            << val << " > " << lst.max_value()
+                            << exit(FatalIOError);
+                    }
+
+                    // assign for all entries
+                    lst = val;
+                }
+            }
+
+            // Read end of contents
+            is.readEndList("PackedList<nBits>");
+        }
+    }
+    else if (firstTok.isPunctuation())
+    {
+        if (firstTok.pToken() != token::BEGIN_LIST)
+        {
+            FatalIOErrorIn
+            (
+                "operator>>(Istream&, PackedList<nBits>&)",
+                is
+            )
+                << "incorrect first token, expected '(', found "
+                << firstTok.info()
+                << exit(FatalIOError);
+        }
+
+        token nextTok(is);
+        is.fatalCheck("operator>>(Istream&, PackedList<nBits>&)");
+
+        unsigned int val;
+
+        while
+        (
+            !(nextTok.isPunctuation() && nextTok.pToken() == token::END_LIST)
+        )
+        {
+            is.putBack(nextTok);
+            is  >> val;
+            lst.append(val);
+
+            if (val > lst.max_value())
+            {
+                FatalIOErrorIn
+                (
+                    "operator>>(Istream&, PackedList<nBits>&)",
+                    is
+                )
+                    << "out-of-range value: "
+                    << val << " > " << lst.max_value()
+                    << exit(FatalIOError);
+            }
+
+            is  >> nextTok;
+            is.fatalCheck("operator>>(Istream&, PackedList<nBits>&)");
+        }
+    }
+    else
+    {
+        FatalIOErrorIn
+        (
+            "operator>>(Istream&, PackedList<nBits>&)",
+            is
+        )
+            << "incorrect first token, expected <int> or '(', found "
+            << firstTok.info()
+            << exit(FatalIOError);
+    }
+
+    return is;
+}
+
+
+template<unsigned nBits>
+Foam::Ostream& Foam::operator<<
+(
+    Ostream& os,
+    PackedList<nBits>& lst
+)
+{
+    if (lst.size() < 11)
+    {
+        // Write size and start delimiter
+        os  << lst.size() << token::BEGIN_LIST;
+
+        // Write contents
+        forAll(lst, i)
+        {
+            if (i)
+            {
+                os  << token::SPACE;
+            }
+            os  << lst[i];
+        }
+
+        // Write end delimiter
+        os  << token::END_LIST;
+    }
+    else
+    {
+        // Write size and start delimiter
+        os  << nl << lst.size() << nl << token::BEGIN_LIST;
+
+        // Write contents
+        forAll(lst, i)
+        {
+            os  << nl << lst[i];
+        }
+
+        // Write end delimiter
+        os  << nl << token::END_LIST << nl;
+    }
+
+    return os;
+}
+
+
 // ************************************************************************* //
diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H
index 2adb939e4d3..897544eb4d3 100644
--- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H
+++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H
@@ -96,11 +96,17 @@ SourceFiles
 namespace Foam
 {
 
+// Forward declaration of classes
+class Istream;
+class Ostream;
+
 // Forward declaration of friend functions and operators
 template<unsigned nBits> class PackedList;
 
-// template<unsigned nBits>
-// Ostream& operator<<(Ostream&, const PackedList<nBits>&);
+template<unsigned nBits>
+Istream& operator>>(Istream&, PackedList<nBits>&);
+template<unsigned nBits>
+Ostream& operator<<(Ostream&, const PackedList<nBits>&);
 
 
 /*---------------------------------------------------------------------------*\
@@ -180,6 +186,9 @@ public:
         //- Construct with given size and value for all elements
         PackedList(const label size, const unsigned val);
 
+        //- Construct from Istream
+        PackedList(Istream&);
+
         //- Copy constructor
         inline PackedList(const PackedList<nBits>&);
 
@@ -516,6 +525,21 @@ public:
         //- const_iterator set to beyond the end of the PackedList
         inline const_iterator end() const;
 
+
+    // IOstream Operators
+
+        friend Istream& operator>> <nBits>
+        (
+            Istream&,
+            PackedList<nBits>&
+        );
+
+        friend Ostream& operator<< <nBits>
+        (
+            Ostream&,
+            const PackedList<nBits>&
+        );
+
 };
 
 
diff --git a/src/OpenFOAM/db/IOstreams/Sstreams/readHexLabel.C b/src/OpenFOAM/db/IOstreams/Sstreams/readHexLabel.C
index 4cf39c34a7f..432ab8ac171 100644
--- a/src/OpenFOAM/db/IOstreams/Sstreams/readHexLabel.C
+++ b/src/OpenFOAM/db/IOstreams/Sstreams/readHexLabel.C
@@ -22,11 +22,12 @@ License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
 Description
-    Read of a non-delimited hex label
+    Read a non-delimited hex label
 
 \*---------------------------------------------------------------------------*/
 
 #include "readHexLabel.H"
+#include <cctype>
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -55,7 +56,7 @@ Foam::label Foam::readHexLabel(ISstream& is)
                 << exit(FatalIOError);
         }
 
-        result *= 16;
+        result <<= 4;
 
         if (isdigit(c))
         {
-- 
GitLab