From b3128e6ced87dcfbf97665ba7573edfcdcb19449 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Fri, 11 Aug 2017 08:39:45 +0200
Subject: [PATCH] STYLE: replace file-local functions with the Ostream
 writeEntry() method

ENH: use std C++ for conversions instead of sscanf()
---
 src/OSspecific/POSIX/cpuInfo/cpuInfo.C | 129 +++++++++----------------
 src/OSspecific/POSIX/cpuInfo/cpuInfo.H |   8 +-
 src/OSspecific/POSIX/memInfo/memInfo.C |  96 ++++++++++--------
 src/OSspecific/POSIX/memInfo/memInfo.H |  68 ++++++-------
 4 files changed, 135 insertions(+), 166 deletions(-)

diff --git a/src/OSspecific/POSIX/cpuInfo/cpuInfo.C b/src/OSspecific/POSIX/cpuInfo/cpuInfo.C
index ef71120a747..6dbd6abf4b2 100644
--- a/src/OSspecific/POSIX/cpuInfo/cpuInfo.C
+++ b/src/OSspecific/POSIX/cpuInfo/cpuInfo.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2016-2017 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -24,102 +24,61 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "cpuInfo.H"
-#include "IFstream.H"
 #include "IOstreams.H"
 
+#include <fstream>
+
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 // file-scope function
-template<class T>
-inline static void writeEntry
-(
-    Foam::Ostream& os, const Foam::word& key, const T& value
-)
+// split things like "a key word\t: value information"
+// into ("a_key_word", "value information")
+//
+static bool split(const std::string& line, std::string& key, std::string& val)
 {
-    os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
-}
+    key.clear();
+    val.clear();
 
+    const auto keyLen = line.find_first_of("\t:");
+    const auto sep = line.find(':');
 
-// file-scope function
-static bool split(std::string& line, std::string& key, std::string& val)
-{
-    std::string::size_type sep = line.find(':');
-
-    if (sep == std::string::npos)
+    if (keyLen == std::string::npos || sep == std::string::npos)
     {
         return false;
     }
 
-    std::string::size_type endKey = line.find_last_not_of("\t:", sep);
-    std::string::size_type begVal = line.find_first_not_of(" :", sep);
+    const auto begVal = line.find_first_not_of(" :", sep);
 
-    if (endKey == std::string::npos || begVal == std::string::npos)
+    if (begVal == std::string::npos)
     {
         return false;
     }
-    ++endKey;
-
-    // replace spaces in key with '_' for ease of use/consistency
-    for
-    (
-        std::string::iterator iter = line.begin();
-        iter != line.end();
-        ++iter
-    )
+
+    key = line.substr(0, keyLen);
+    val = line.substr(begVal);
+
+    // Avoid spaces in key - replace with '_'
+    for (auto iter = key.begin(); iter < key.end(); ++iter)
     {
         if (*iter == ' ')
         {
             *iter = '_';
         }
-        else if (*iter == ':')
-        {
-            break;
-        }
     }
 
-    key = line.substr(0, endKey);
-    val = line.substr(begVal);
-
-    // std::cerr<<"key=" << key << " val= " << val << '\n';
+    // std::cerr<<"key=<" << key << "> val=<" << val << ">\n";
 
     return true;
 }
 
 
-// file-scope function - get int
-static inline bool getInt(const std::string& str, int& val)
-{
-    int i;
-    if (sscanf(str.c_str(), "%d", &i) == 1)
-    {
-        val = i;
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-// file-scope function - get float
-static inline bool getFlt(const std::string& str, float& val)
-{
-    float f;
-    if (sscanf(str.c_str(), "%f", &f) == 1)
-    {
-        val = f;
-        return true;
-    }
-    else
-    {
-        return false;
-    }
-}
-
-
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
-// parse this type of content:
+// Parse the following type of content.
+// A TAB separates the keyword from content. Eg,
+//
+// "cpu cores\t: 6"
+//
 // ===========================
 // processor       : 0
 // vendor_id       : GenuineIntel
@@ -151,14 +110,14 @@ static inline bool getFlt(const std::string& str, float& val)
 void Foam::cpuInfo::parse()
 {
     int ncpu = 0;
+    std::string line, key, val;
 
-    IFstream is("/proc/cpuinfo");
+    std::ifstream is("/proc/cpuinfo");
     while (is.good())
     {
-        string line, key, value;
-        is.getLine(line);
+        std::getline(is, line);
 
-        if (!split(line, key, value))
+        if (!split(line, key, val))
         {
             continue;
         }
@@ -170,13 +129,13 @@ void Foam::cpuInfo::parse()
                 break; // stop after the first cpu
             }
         }
-        else if (key == "vendor_id")   { vendor_id  = value;        }
-        else if (key == "model_name")  { model_name = value;        }
-        else if (key == "cpu_family")  { getInt(value, cpu_family); }
-        else if (key == "model")       { getInt(value, model);      }
-        else if (key == "cpu_MHz")     { getFlt(value, cpu_MHz);    }
-        else if (key == "cpu_cores")   { getInt(value, cpu_cores);  }
-        else if (key == "siblings")    { getInt(value, siblings);   }
+        else if (key == "vendor_id")   { vendor_id  = val; }
+        else if (key == "model_name")  { model_name = val; }
+        else if (key == "cpu_family")  { cpu_family = std::stoi(val); }
+        else if (key == "model")       { model = std::stoi(val); }
+        else if (key == "cpu_MHz")     { cpu_MHz = std::stof(val); }
+        else if (key == "cpu_cores")   { cpu_cores = std::stoi(val);  }
+        else if (key == "siblings")    { siblings = std::stoi(val); }
     }
 }
 
@@ -209,31 +168,31 @@ void Foam::cpuInfo::write(Ostream& os) const
 {
     if (!vendor_id.empty())
     {
-        writeEntry(os, "vendor_id",     vendor_id);
+        os.writeEntry("vendor_id", vendor_id);
     }
     if (!model_name.empty())
     {
-        writeEntry(os, "model_name",    model_name);
+        os.writeEntry("model_name", model_name);
     }
     if (cpu_family != -1)
     {
-        writeEntry(os, "cpu_family",    cpu_family);
+        os.writeEntry("cpu_family", cpu_family);
     }
     if (model != -1)
     {
-        writeEntry(os, "model",         model);
+        os.writeEntry("model", model);
     }
     if (cpu_MHz > 0)
     {
-        writeEntry(os, "cpu_MHz",       cpu_MHz);
+        os.writeEntry("cpu_MHz", cpu_MHz);
     }
     if (cpu_cores > 0)
     {
-        writeEntry(os, "cpu_cores",     cpu_cores);
+        os.writeEntry("cpu_cores", cpu_cores);
     }
     if (siblings > 0)
     {
-        writeEntry(os, "siblings",      siblings);
+        os.writeEntry("siblings", siblings);
     }
 }
 
diff --git a/src/OSspecific/POSIX/cpuInfo/cpuInfo.H b/src/OSspecific/POSIX/cpuInfo/cpuInfo.H
index 6821684f615..721e2f52bae 100644
--- a/src/OSspecific/POSIX/cpuInfo/cpuInfo.H
+++ b/src/OSspecific/POSIX/cpuInfo/cpuInfo.H
@@ -47,7 +47,8 @@ SourceFiles
 
 namespace Foam
 {
-// forward declarations
+
+// Forward declarations
 class Ostream;
 
 /*---------------------------------------------------------------------------*\
@@ -68,6 +69,7 @@ class cpuInfo
         int siblings;
         int cpu_cores;
 
+
     // Private Member Functions
 
         //- Parse /proc/cpuinfo
@@ -83,7 +85,7 @@ public:
 
     // Constructors
 
-        //- Construct null
+        //- Construct and populate with information
         cpuInfo();
 
 
@@ -94,7 +96,7 @@ public:
     // Member Functions
 
         //- Write content as dictionary entries
-        void write(Ostream&) const;
+        void write(Ostream& os) const;
 
 };
 
diff --git a/src/OSspecific/POSIX/memInfo/memInfo.C b/src/OSspecific/POSIX/memInfo/memInfo.C
index c0ff2dd99bf..ab27f706ce3 100644
--- a/src/OSspecific/POSIX/memInfo/memInfo.C
+++ b/src/OSspecific/POSIX/memInfo/memInfo.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  | Copyright (C) 2016-2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -24,21 +24,11 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "memInfo.H"
-#include "IFstream.H"
+#include "OSspecific.H"
 #include "IOstreams.H"
 
-// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
-
-// file-scope function
-template<class T>
-inline static void writeEntry
-(
-    Foam::Ostream& os, const Foam::word& key, const T& value
-)
-{
-    os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
-}
-
+#include <fstream>
+#include <string>
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -59,34 +49,64 @@ Foam::memInfo::~memInfo()
 
 
 // * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * * //
+//
+// Parse the following type of content.
+//
+// ===========================
+// VmPeak:    15920 kB
+// VmSize:    15916 kB
+// VmLck:         0 kB
+// VmPin:         0 kB
+// VmHWM:      6972 kB
+// VmRSS:      6972 kB
+// VmLib:      2208 kB
+// VmPTE:        52 kB
+// VmPMD:        12 kB
+// VmSwap:        0 kB
 
 const Foam::memInfo& Foam::memInfo::update()
 {
-    // reset to invalid values first
+    // Clear (invalidate) values first
     peak_ = size_ = rss_ = 0;
-    IFstream is("/proc/" + name(pid()) + "/status");
+    std::string line;
+
+    unsigned nKeys = 0;
 
-    while (is.good())
+    std::ifstream is("/proc/" + std::to_string(Foam::pid()) + "/status");
+    while (is.good() && nKeys < 3)  // Stop after getting the known keys
     {
-        string line;
-        is.getLine(line);
-        char tag[32];
-        int value;
+        std::getline(is, line);
+
+        const auto keyLen = line.find(':');
+        if (keyLen == std::string::npos)
+        {
+            continue;
+        }
+
+        // Value is after the ':', but skip any leading whitespace since
+        // strtoi will do it anyhow
+        const auto begVal = line.find_first_not_of("\t :", keyLen);
+        if (begVal == std::string::npos)
+        {
+            continue;
+        }
+
+        const std::string key = line.substr(0, keyLen);
 
-        if (sscanf(line.c_str(), "%30s %d", tag, &value) == 2)
+        if (key == "VmPeak")
+        {
+            peak_ = std::stoi(line.substr(begVal));
+            ++nKeys;
+        }
+        else if (key == "VmSize")
         {
-            if (!strcmp(tag, "VmPeak:"))
-            {
-                peak_ = value;
-            }
-            else if (!strcmp(tag, "VmSize:"))
-            {
-                size_ = value;
-            }
-            else if (!strcmp(tag, "VmRSS:"))
-            {
-                rss_ = value;
-            }
+            size_ = std::stoi(line.substr(begVal));
+            ++nKeys;
+        }
+        else if (key == "VmRSS")
+        {
+            rss_ = std::stoi(line.substr(begVal));
+            ++nKeys;
         }
     }
 
@@ -102,9 +122,9 @@ bool Foam::memInfo::valid() const
 
 void Foam::memInfo::write(Ostream& os) const
 {
-    writeEntry(os, "size",  size_);
-    writeEntry(os, "peak",  peak_);
-    writeEntry(os, "rss",   rss_);
+    os.writeEntry("size", size_);
+    os.writeEntry("peak", peak_);
+    os.writeEntry("rss", rss_);
 }
 
 
@@ -113,9 +133,7 @@ void Foam::memInfo::write(Ostream& os) const
 Foam::Istream& Foam::operator>>(Istream& is, memInfo& m)
 {
     is.readBegin("memInfo");
-
     is  >> m.peak_ >> m.size_ >> m.rss_;
-
     is.readEnd("memInfo");
 
     is.check(FUNCTION_NAME);
diff --git a/src/OSspecific/POSIX/memInfo/memInfo.H b/src/OSspecific/POSIX/memInfo/memInfo.H
index 181da5b7efa..3b7c2eda591 100644
--- a/src/OSspecific/POSIX/memInfo/memInfo.H
+++ b/src/OSspecific/POSIX/memInfo/memInfo.H
@@ -38,27 +38,20 @@ SourceFiles
 #ifndef memInfo_H
 #define memInfo_H
 
-#include "OSspecific.H"
-#include "POSIX.H"
-#include "IFstream.H"
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
 // Forward declaration of friend functions and operators
-
 class memInfo;
-
-Istream& operator>>(Istream&, memInfo&);
-Ostream& operator<<(Ostream&, const memInfo&);
-
-
-// forward declarations
 class Istream;
 class Ostream;
 
+Istream& operator>>(Istream& is, memInfo& m);
+Ostream& operator<<(Ostream& os, const memInfo& m);
+
+
 /*---------------------------------------------------------------------------*\
                            Class memInfo Declaration
 \*---------------------------------------------------------------------------*/
@@ -76,12 +69,6 @@ class memInfo
         //- Resident set size of the process (VmRSS in /proc/PID/status)
         int rss_;
 
-        //- Disallow default bitwise assignment
-        void operator=(const memInfo&) = delete;
-
-        //- Disallow default copy constructor
-        memInfo(const memInfo&) = delete;
-
 public:
 
     // Constructors
@@ -96,44 +83,47 @@ public:
 
     // Member Functions
 
-        //- Parse /proc/PID/status and update accordingly
+        //- Update according to /proc/PID/status contents
         const memInfo& update();
 
-        // Access
 
-            //- Peak memory (VmPeak in /proc/PID/status) at last update()
-            int peak() const
-            {
-                return peak_;
-            }
+      // Access
+
+        //- Peak memory (VmPeak in /proc/PID/status) at last update()
+        inline int peak() const
+        {
+            return peak_;
+        }
+
+        //- Memory size (VmSize in /proc/PID/status) at last update()
+        inline int size() const
+        {
+            return size_;
+        }
 
-            //- Memory size (VmSize in /proc/PID/status) at last update()
-            int size() const
-            {
-                return size_;
-            }
+        //- Resident set size (VmRSS in /proc/PID/status) at last update()
+        inline int rss() const
+        {
+            return rss_;
+        }
 
-            //- Resident set size (VmRSS in /proc/PID/status) at last update()
-            int rss() const
-            {
-                return rss_;
-            }
+        //- True if the memory information appears valid
+        bool valid() const;
 
-            //- True if the memory information appears valid
-            bool valid() const;
 
+      // Write
 
         //- Write content as dictionary entries
-        void write(Ostream&) const;
+        void write(Ostream& os) const;
 
 
     // IOstream Operators
 
         //- Read peak/size/rss from stream
-        friend Istream& operator>>(Istream&, memInfo&);
+        friend Istream& operator>>(Istream& is, memInfo& m);
 
         //- Write peak/size/rss to stream
-        friend Ostream& operator<<(Ostream&, const memInfo&);
+        friend Ostream& operator<<(Ostream& os, const memInfo& m);
 };
 
 
-- 
GitLab