<commit_before>void build(Solution &s)
{
    auto &tess = s.addProject("google.tesseract", "master");
    tess += Git("https://github.com/tesseract-ocr/tesseract", "", "{v}");

    auto &libtesseract = tess.addTarget<LibraryTarget>("libtesseract");
    {
        libtesseract.setChecks("libtesseract");

        libtesseract.ExportAllSymbols = true;
        libtesseract.PackageDefinitions = true;
        libtesseract +=
            "src/api/.*\\.cpp"_rr,
            "src/api/.*\\.h"_rr,
            "src/api/tess_version.h.in",
            "src/arch/.*\\.cpp"_rr,
            "src/arch/.*\\.h"_rr,
            "src/ccmain/.*\\.cpp"_rr,
            "src/ccmain/.*\\.h"_rr,
            "src/ccstruct/.*\\.cpp"_rr,
            "src/ccstruct/.*\\.h"_rr,
            "src/ccutil/.*\\.cpp"_rr,
            "src/ccutil/.*\\.h"_rr,
            "src/classify/.*\\.cpp"_rr,
            "src/classify/.*\\.h"_rr,
            "src/cutil/.*\\.cpp"_rr,
            "src/cutil/.*\\.h"_rr,
            "src/dict/.*\\.cpp"_rr,
            "src/dict/.*\\.h"_rr,
            "src/lstm/.*\\.cpp"_rr,
            "src/lstm/.*\\.h"_rr,
            "src/opencl/.*\\.cpp"_rr,
            "src/opencl/.*\\.h"_rr,
            "src/textord/.*\\.cpp"_rr,
            "src/textord/.*\\.h"_rr,
            "src/viewer/.*\\.cpp"_rr,
            "src/viewer/.*\\.h"_rr,
            "src/wordrec/.*\\.cpp"_rr,
            "src/wordrec/.*\\.h"_rr;

        libtesseract -=
            "src/api/tesseractmain.cpp",
            "src/viewer/svpaint.cpp";

        libtesseract.Public +=
            "src/opencl"_id,
            "src/ccmain"_id,
            "src/api"_id,
            "src/dict"_id,
            "src/viewer"_id,
            "src/wordrec"_id,
            "src/ccstruct"_id,
            "src/cutil"_id,
            "src/textord"_id,
            "src/ccutil"_id,
            "src/lstm"_id,
            "src/classify"_id,
            //"src/training"_id,
            "src/arch"_id;

        if (libtesseract.getCompilerType() == CompilerType::MSVC ||
            libtesseract.getCompilerType() == CompilerType::ClangCl)
        {
            libtesseract += "__SSE4_1__"_def;
            libtesseract.CompileOptions.push_back("-arch:AVX2");

            libtesseract -=
                "src/arch/dotproductfma.cpp";
        }

        libtesseract.Public += "HAVE_CONFIG_H"_d;
        libtesseract.Public += "_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1"_d;
        libtesseract.Public += "HAVE_LIBARCHIVE"_d;
        libtesseract.Interface += sw::Shared, "TESS_IMPORTS"_d;
        libtesseract.Private += sw::Shared, "TESS_EXPORTS"_d;

        libtesseract.Public += "org.sw.demo.danbloomberg.leptonica-master"_dep;
        libtesseract.Public += "org.sw.demo.libarchive.libarchive"_dep;

        if (libtesseract.getBuildSettings().TargetOS.Type == OSType::Windows)
        {
            libtesseract.Public += "ws2_32.lib"_l;
            libtesseract.Protected += "NOMINMAX"_def;
        }

        libtesseract.Variables["TESSERACT_MAJOR_VERSION"] = libtesseract.Variables["PACKAGE_MAJOR_VERSION"];
        libtesseract.Variables["TESSERACT_MINOR_VERSION"] = libtesseract.Variables["PACKAGE_MINOR_VERSION"];
        libtesseract.Variables["TESSERACT_MICRO_VERSION"] = libtesseract.Variables["PACKAGE_PATCH_VERSION"];
        libtesseract.Variables["TESSERACT_VERSION_STR"] = "master";
        libtesseract.configureFile("src/api/tess_version.h.in", "tess_version.h");

        // install
        if (!libtesseract.DryRun)
        {
            const Files files
            {
                // from api/makefile.am
                "src/api/apitypes.h",
                "src/api/baseapi.h",
                "src/api/capi.h",
                "src/api/renderer.h",
                "tess_version.h",

                //from arch/makefile.am
                "src/arch/dotproduct.h",
                "src/arch/intsimdmatrix.h",
                "src/arch/simddetect.h",

                //from ccmain/makefile.am
                "src/ccmain/thresholder.h",
                "src/ccmain/ltrresultiterator.h",
                "src/ccmain/pageiterator.h",
                "src/ccmain/resultiterator.h",
                "src/ccmain/osdetect.h",

                //from ccstruct/makefile.am
                "src/ccstruct/publictypes.h",

                //from ccutil/makefile.am
                "src/ccutil/errcode.h",
                "src/ccutil/fileerr.h",
                "src/ccutil/genericvector.h",
                "src/ccutil/helpers.h",
                "src/ccutil/params.h",
                "src/ccutil/ocrclass.h",
                "src/ccutil/platform.h",
                "src/ccutil/serialis.h",
                "src/ccutil/strngs.h",
                "src/ccutil/unichar.h",
                "src/ccutil/unicharcompress.h",
                "src/ccutil/unicharmap.h",
                "src/ccutil/unicharset.h",

                //from lstm/makefile.am
                "src/lstm/convolve.h",
                "src/lstm/fullyconnected.h",
                "src/lstm/functions.h",
                "src/lstm/input.h",
                "src/lstm/lstm.h",
                "src/lstm/lstmrecognizer.h",
                "src/lstm/maxpool.h",
                "src/lstm/network.h",
                "src/lstm/networkio.h",
                "src/lstm/networkscratch.h",
                "src/lstm/parallel.h",
                "src/lstm/plumbing.h",
                "src/lstm/recodebeam.h",
                "src/lstm/reconfig.h",
                "src/lstm/reversed.h",
                "src/lstm/series.h",
                "src/lstm/static_shape.h",
                "src/lstm/stridemap.h",
                "src/lstm/tfnetwork.h",
                "src/lstm/weightmatrix.h",
            };

            auto d = libtesseract.BinaryDir / "tesseract";
            fs::create_directories(d);
            for (auto f : files)
            {
                libtesseract.check_absolute(f);
                fs::copy_file(f, d / f.filename(), fs::copy_options::overwrite_existing);
            }
        }
    }

    //
    auto &tesseract = tess.addExecutable("tesseract");
    tesseract += "src/api/tesseractmain.cpp";
    tesseract += libtesseract;

    //
    auto &tessopt = tess.addStaticLibrary("tessopt");
    tessopt += "src/training/tessopt.*"_rr;
    tessopt.Public += libtesseract;

    //
    auto &common_training = tess.addStaticLibrary("common_training");
    common_training +=
        "src/training/commandlineflags.cpp",
        "src/training/commandlineflags.h",
        "src/training/commontraining.cpp",
        "src/training/commontraining.h";
    common_training.Public += tessopt;

    //
    auto &unicharset_training = tess.addStaticLibrary("unicharset_training");
    unicharset_training +=
        "src/training/fileio.*"_rr,
        "src/training/icuerrorcode.*"_rr,
        "src/training/icuerrorcode.h",
        "src/training/lang_model_helpers.*"_rr,
        "src/training/lstmtester.*"_rr,
        "src/training/lstmtrainer.*"_rr,
        "src/training/normstrngs.*"_rr,
        "src/training/unicharset_training_utils.*"_rr,
        "src/training/validat.*"_rr;
    unicharset_training.Public += common_training;
    unicharset_training.Public += "org.sw.demo.unicode.icu.i18n"_dep;

    //
#define ADD_EXE(n, ...)               \
    auto &n = tess.addExecutable(#n); \
    n += "src/training/" #n ".*"_rr;  \
    n.Public += __VA_ARGS__;          \
    n

    ADD_EXE(ambiguous_words, libtesseract);
    ADD_EXE(classifier_tester, common_training);
    ADD_EXE(combine_lang_model, unicharset_training);
    ADD_EXE(combine_tessdata, libtesseract);
    ADD_EXE(cntraining, common_training);
    ADD_EXE(dawg2wordlist, libtesseract);
    ADD_EXE(mftraining, common_training) += "src/training/mergenf.*"_rr;
    ADD_EXE(shapeclustering, common_training);
    ADD_EXE(unicharset_extractor, unicharset_training);
    ADD_EXE(wordlist2dawg, libtesseract);
    ADD_EXE(lstmeval, unicharset_training);
    ADD_EXE(lstmtraining, unicharset_training);
    ADD_EXE(set_unicharset_properties, unicharset_training);

    ADD_EXE(text2image, unicharset_training);
    text2image +=
        "src/training/boxchar.cpp",
        "src/training/boxchar.h",
        "src/training/degradeimage.cpp",
        "src/training/degradeimage.h",
        "src/training/icuerrorcode.h",
        "src/training/ligature_table.cpp",
        "src/training/ligature_table.h",
        "src/training/normstrngs.cpp",
        "src/training/normstrngs.h",
        "src/training/pango_font_info.cpp",
        "src/training/pango_font_info.h",
        "src/training/stringrenderer.cpp",
        "src/training/stringrenderer.h",
        "src/training/text2image.cpp",
        "src/training/tlog.cpp",
        "src/training/tlog.h",
        "src/training/util.h";
    text2image.Public += "org.sw.demo.gnome.pango.pangocairo"_dep;
}

void check(Checker &c)
{
    auto &s = c.addSet("libtesseract");
    s.checkFunctionExists("getline");
    s.checkIncludeExists("dlfcn.h");
    s.checkIncludeExists("inttypes.h");
    s.checkIncludeExists("limits.h");
    s.checkIncludeExists("malloc.h");
    s.checkIncludeExists("memory.h");
    s.checkIncludeExists("stdbool.h");
    s.checkIncludeExists("stdint.h");
    s.checkIncludeExists("stdlib.h");
    s.checkIncludeExists("string.h");
    s.checkIncludeExists("sys/ipc.h");
    s.checkIncludeExists("sys/shm.h");
    s.checkIncludeExists("sys/stat.h");
    s.checkIncludeExists("sys/types.h");
    s.checkIncludeExists("sys/wait.h");
    s.checkIncludeExists("tiffio.h");
    s.checkIncludeExists("unistd.h");
    s.checkTypeSize("long long int");
    s.checkTypeSize("mbstate_t");
    s.checkTypeSize("off_t");
    s.checkTypeSize("size_t");
    s.checkTypeSize("void *");
    s.checkTypeSize("wchar_t");
    s.checkTypeSize("_Bool");
    {
        auto &c = s.checkSymbolExists("snprintf");
        c.Parameters.Includes.push_back("stdio.h");
    }
}
<commit_msg>[sw] Update build for commit e84cb24def47cb08d9614110fbc1d5d57934cf98<commit_after>void build(Solution &s)
{
    auto &tess = s.addProject("google.tesseract", "master");
    tess += Git("https://github.com/tesseract-ocr/tesseract", "", "{v}");

    auto &libtesseract = tess.addTarget<LibraryTarget>("libtesseract");
    {
        libtesseract.setChecks("libtesseract");

        libtesseract.ExportAllSymbols = true;
        libtesseract.PackageDefinitions = true;
        libtesseract +=
            "src/api/.*\\.cpp"_rr,
            "src/api/.*\\.h"_rr,
            "src/api/tess_version.h.in",
            "src/arch/.*\\.cpp"_rr,
            "src/arch/.*\\.h"_rr,
            "src/ccmain/.*\\.cpp"_rr,
            "src/ccmain/.*\\.h"_rr,
            "src/ccstruct/.*\\.cpp"_rr,
            "src/ccstruct/.*\\.h"_rr,
            "src/ccutil/.*\\.cpp"_rr,
            "src/ccutil/.*\\.h"_rr,
            "src/classify/.*\\.cpp"_rr,
            "src/classify/.*\\.h"_rr,
            "src/cutil/.*\\.cpp"_rr,
            "src/cutil/.*\\.h"_rr,
            "src/dict/.*\\.cpp"_rr,
            "src/dict/.*\\.h"_rr,
            "src/lstm/.*\\.cpp"_rr,
            "src/lstm/.*\\.h"_rr,
            "src/opencl/.*\\.cpp"_rr,
            "src/opencl/.*\\.h"_rr,
            "src/textord/.*\\.cpp"_rr,
            "src/textord/.*\\.h"_rr,
            "src/viewer/.*\\.cpp"_rr,
            "src/viewer/.*\\.h"_rr,
            "src/wordrec/.*\\.cpp"_rr,
            "src/wordrec/.*\\.h"_rr;

        libtesseract -=
            "src/api/tesseractmain.cpp",
            "src/viewer/svpaint.cpp";

        libtesseract.Public +=
            "src/opencl"_id,
            "src/ccmain"_id,
            "src/api"_id,
            "src/dict"_id,
            "src/viewer"_id,
            "src/wordrec"_id,
            "src/ccstruct"_id,
            "src/cutil"_id,
            "src/textord"_id,
            "src/ccutil"_id,
            "src/lstm"_id,
            "src/classify"_id,
            "src/arch"_id,
            "src/training"_id;

        if (libtesseract.getCompilerType() == CompilerType::MSVC ||
            libtesseract.getCompilerType() == CompilerType::ClangCl)
        {
            libtesseract += "__SSE4_1__"_def;
            libtesseract.CompileOptions.push_back("-arch:AVX2");

            libtesseract -=
                "src/arch/dotproductfma.cpp";
        }

        libtesseract.Public += "HAVE_CONFIG_H"_d;
        libtesseract.Public += "_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS=1"_d;
        libtesseract.Public += "HAVE_LIBARCHIVE"_d;
        libtesseract.Interface += sw::Shared, "TESS_IMPORTS"_d;
        libtesseract.Private += sw::Shared, "TESS_EXPORTS"_d;

        libtesseract.Public += "org.sw.demo.danbloomberg.leptonica-master"_dep;
        libtesseract.Public += "org.sw.demo.libarchive.libarchive"_dep;

        if (libtesseract.getBuildSettings().TargetOS.Type == OSType::Windows)
        {
            libtesseract.Public += "ws2_32.lib"_l;
            libtesseract.Protected += "NOMINMAX"_def;
        }

        libtesseract.Variables["TESSERACT_MAJOR_VERSION"] = libtesseract.Variables["PACKAGE_MAJOR_VERSION"];
        libtesseract.Variables["TESSERACT_MINOR_VERSION"] = libtesseract.Variables["PACKAGE_MINOR_VERSION"];
        libtesseract.Variables["TESSERACT_MICRO_VERSION"] = libtesseract.Variables["PACKAGE_PATCH_VERSION"];
        libtesseract.Variables["TESSERACT_VERSION_STR"] = "master";
        libtesseract.configureFile("src/api/tess_version.h.in", "tess_version.h");

        // install
        if (!libtesseract.DryRun)
        {
            const Files files
            {
                // from api/makefile.am
                "src/api/apitypes.h",
                "src/api/baseapi.h",
                "src/api/capi.h",
                "src/api/renderer.h",
                "tess_version.h",

                //from arch/makefile.am
                "src/arch/dotproduct.h",
                "src/arch/intsimdmatrix.h",
                "src/arch/simddetect.h",

                //from ccmain/makefile.am
                "src/ccmain/thresholder.h",
                "src/ccmain/ltrresultiterator.h",
                "src/ccmain/pageiterator.h",
                "src/ccmain/resultiterator.h",
                "src/ccmain/osdetect.h",

                //from ccstruct/makefile.am
                "src/ccstruct/publictypes.h",

                //from ccutil/makefile.am
                "src/ccutil/errcode.h",
                "src/ccutil/fileerr.h",
                "src/ccutil/genericvector.h",
                "src/ccutil/helpers.h",
                "src/ccutil/params.h",
                "src/ccutil/ocrclass.h",
                "src/ccutil/platform.h",
                "src/ccutil/serialis.h",
                "src/ccutil/strngs.h",
                "src/ccutil/unichar.h",
                "src/ccutil/unicharcompress.h",
                "src/ccutil/unicharmap.h",
                "src/ccutil/unicharset.h",

                //from lstm/makefile.am
                "src/lstm/convolve.h",
                "src/lstm/fullyconnected.h",
                "src/lstm/functions.h",
                "src/lstm/input.h",
                "src/lstm/lstm.h",
                "src/lstm/lstmrecognizer.h",
                "src/lstm/maxpool.h",
                "src/lstm/network.h",
                "src/lstm/networkio.h",
                "src/lstm/networkscratch.h",
                "src/lstm/parallel.h",
                "src/lstm/plumbing.h",
                "src/lstm/recodebeam.h",
                "src/lstm/reconfig.h",
                "src/lstm/reversed.h",
                "src/lstm/series.h",
                "src/lstm/static_shape.h",
                "src/lstm/stridemap.h",
                "src/lstm/tfnetwork.h",
                "src/lstm/weightmatrix.h",
            };

            auto d = libtesseract.BinaryDir / "tesseract";
            fs::create_directories(d);
            for (auto f : files)
            {
                libtesseract.check_absolute(f);
                fs::copy_file(f, d / f.filename(), fs::copy_options::overwrite_existing);
            }
        }
    }

    //
    auto &tesseract = tess.addExecutable("tesseract");
    tesseract += "src/api/tesseractmain.cpp";
    tesseract += libtesseract;

    //
    auto &tessopt = tess.addStaticLibrary("tessopt");
    tessopt += "src/training/tessopt.*"_rr;
    tessopt.Public += libtesseract;

    //
    auto &common_training = tess.addStaticLibrary("common_training");
    common_training +=
        "src/training/commandlineflags.cpp",
        "src/training/commandlineflags.h",
        "src/training/commontraining.cpp",
        "src/training/commontraining.h",
        "src/training/ctc.cpp",
        "src/training/ctc.h",
        "src/training/errorcounter.cpp",
        "src/training/errorcounter.h",
        "src/training/intfeaturedist.cpp",
        "src/training/intfeaturedist.h",
        "src/training/intfeaturemap.cpp",
        "src/training/intfeaturemap.h",
        "src/training/mastertrainer.cpp",
        "src/training/mastertrainer.h",
        "src/training/networkbuilder.cpp",
        "src/training/networkbuilder.h",
        "src/training/sampleiterator.cpp",
        "src/training/sampleiterator.h",
        "src/training/trainingsampleset.cpp",
        "src/training/trainingsampleset.h";
    common_training.Public += tessopt;

    //
    auto &unicharset_training = tess.addStaticLibrary("unicharset_training");
    unicharset_training +=
        "src/training/fileio.*"_rr,
        "src/training/icuerrorcode.*"_rr,
        "src/training/icuerrorcode.h",
        "src/training/lang_model_helpers.*"_rr,
        "src/training/lstmtester.*"_rr,
        "src/training/lstmtrainer.*"_rr,
        "src/training/normstrngs.*"_rr,
        "src/training/unicharset_training_utils.*"_rr,
        "src/training/validat.*"_rr;
    unicharset_training.Public += common_training;
    unicharset_training.Public += "org.sw.demo.unicode.icu.i18n"_dep;

    //
#define ADD_EXE(n, ...)               \
    auto &n = tess.addExecutable(#n); \
    n += "src/training/" #n ".*"_rr;  \
    n.Public += __VA_ARGS__;          \
    n

    ADD_EXE(ambiguous_words, libtesseract);
    ADD_EXE(classifier_tester, common_training);
    ADD_EXE(combine_lang_model, unicharset_training);
    ADD_EXE(combine_tessdata, libtesseract);
    ADD_EXE(cntraining, common_training);
    ADD_EXE(dawg2wordlist, libtesseract);
    ADD_EXE(mftraining, common_training) += "src/training/mergenf.*"_rr;
    ADD_EXE(shapeclustering, common_training);
    ADD_EXE(unicharset_extractor, unicharset_training);
    ADD_EXE(wordlist2dawg, libtesseract);
    ADD_EXE(lstmeval, unicharset_training);
    ADD_EXE(lstmtraining, unicharset_training);
    ADD_EXE(set_unicharset_properties, unicharset_training);

    ADD_EXE(text2image, unicharset_training);
    text2image +=
        "src/training/boxchar.cpp",
        "src/training/boxchar.h",
        "src/training/degradeimage.cpp",
        "src/training/degradeimage.h",
        "src/training/icuerrorcode.h",
        "src/training/ligature_table.cpp",
        "src/training/ligature_table.h",
        "src/training/normstrngs.cpp",
        "src/training/normstrngs.h",
        "src/training/pango_font_info.cpp",
        "src/training/pango_font_info.h",
        "src/training/stringrenderer.cpp",
        "src/training/stringrenderer.h",
        "src/training/text2image.cpp",
        "src/training/tlog.cpp",
        "src/training/tlog.h",
        "src/training/util.h";
    text2image.Public += "org.sw.demo.gnome.pango.pangocairo"_dep;
}

void check(Checker &c)
{
    auto &s = c.addSet("libtesseract");
    s.checkFunctionExists("getline");
    s.checkIncludeExists("dlfcn.h");
    s.checkIncludeExists("inttypes.h");
    s.checkIncludeExists("limits.h");
    s.checkIncludeExists("malloc.h");
    s.checkIncludeExists("memory.h");
    s.checkIncludeExists("stdbool.h");
    s.checkIncludeExists("stdint.h");
    s.checkIncludeExists("stdlib.h");
    s.checkIncludeExists("string.h");
    s.checkIncludeExists("sys/ipc.h");
    s.checkIncludeExists("sys/shm.h");
    s.checkIncludeExists("sys/stat.h");
    s.checkIncludeExists("sys/types.h");
    s.checkIncludeExists("sys/wait.h");
    s.checkIncludeExists("tiffio.h");
    s.checkIncludeExists("unistd.h");
    s.checkTypeSize("long long int");
    s.checkTypeSize("mbstate_t");
    s.checkTypeSize("off_t");
    s.checkTypeSize("size_t");
    s.checkTypeSize("void *");
    s.checkTypeSize("wchar_t");
    s.checkTypeSize("_Bool");
    {
        auto &c = s.checkSymbolExists("snprintf");
        c.Parameters.Includes.push_back("stdio.h");
    }
}
<|endoftext|>


<commit_before>/*
* Copyright 2008, 2009 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

//#define NDEBUG
#include "radioInterface.h"
#include <Logger.h>

GSM::Time VectorQueue::nextTime() const
{
  GSM::Time retVal;
  ScopedLock lock(mLock);
  while (mQ.size()==0) mWriteSignal.wait(mLock);
  return mQ.top()->time();
}

radioVector* VectorQueue::getStaleBurst(const GSM::Time& targTime)
{
  ScopedLock lock(mLock);
  if ((mQ.size()==0)) {
    return NULL;
  }
  if (mQ.top()->time() < targTime) {
    radioVector* retVal = mQ.top();
    mQ.pop();
    return retVal;
  }
  return NULL;
}

radioVector* VectorQueue::getCurrentBurst(const GSM::Time& targTime)
{
  ScopedLock lock(mLock);
  if ((mQ.size()==0)) {
    return NULL;
  }
  if (mQ.top()->time() == targTime) {
    radioVector* retVal = mQ.top();
    mQ.pop();
    return retVal;
  }
  return NULL;
}

RadioInterface::RadioInterface(RadioDevice *wRadio,
                               int wReceiveOffset,
			       int wRadioOversampling,
			       int wTransceiverOversampling,
			       GSM::Time wStartTime)

{
  underrun = false;

  sendCursor = 0;
  rcvCursor = 0;
  mOn = false;

  mRadio = wRadio;
  receiveOffset = wReceiveOffset;
  samplesPerSymbol = wRadioOversampling;
  mClock.set(wStartTime);
  powerScaling = 1.0;
}

RadioInterface::~RadioInterface(void) {
  if (rcvBuffer!=NULL) delete rcvBuffer;
  //mReceiveFIFO.clear();
}

double RadioInterface::fullScaleInputValue(void) {
  return mRadio->fullScaleInputValue();
}

double RadioInterface::fullScaleOutputValue(void) {
  return mRadio->fullScaleOutputValue();
}

void RadioInterface::setPowerAttenuation(double dBAtten)
{
  float HWdBAtten = mRadio->setTxGain(-dBAtten);
  dBAtten -= (-HWdBAtten);
  float linearAtten = powf(10.0F,0.1F*dBAtten);
  if (linearAtten < 1.0)
    powerScaling = 1.0;
  else
    powerScaling = 1.0/sqrt(linearAtten);
  LOG(INFO) << "setting HW gain to " << HWdBAtten << " and power scaling to " << powerScaling;
}

short *RadioInterface::radioifyVector(signalVector &wVector, short *retVector, double scale, bool zeroOut)
{

  signalVector::iterator itr = wVector.begin();
  short *shortItr = retVector;
  if (zeroOut) {
    while (itr < wVector.end()) {
      *shortItr++ = 0;
      *shortItr++ = 0;
      itr++;
    }
  }
  else if (scale != 1.0) {
    while (itr < wVector.end()) {
      *shortItr++ = (short) (itr->real()*scale);
      *shortItr++ = (short) (itr->imag()*scale);
      itr++;
    }
  }
  else {
    while (itr < wVector.end()) {
      *shortItr++ = (short) (itr->real());
      *shortItr++ = (short) (itr->imag());
      itr++;
    }
  }

  return retVector;

}

void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
{

  signalVector::iterator itr = newVector.begin();
  short *shortItr = shortVector;
  while (itr < newVector.end()) {
    *itr++ = Complex<float>(*shortItr,*(shortItr+1));
    //LOG(DEBUG) << (*(itr-1));
    shortItr += 2;
  }

}

bool started = false;

void RadioInterface::pushBuffer(void) {

  if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;

  // send resampleVector
  int samplesWritten = mRadio->writeSamples(sendBuffer,
					  INCHUNK*samplesPerSymbol,
					  &underrun,
					  writeTimestamp);
  //LOG(DEBUG) << "writeTimestamp: " << writeTimestamp << ", samplesWritten: " << samplesWritten;

  writeTimestamp += (TIMESTAMP) samplesWritten;

  if (sendCursor > 2*samplesWritten)
    memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
  sendCursor = sendCursor - 2*samplesWritten;
}

void RadioInterface::pullBuffer(void)
{

  bool localUnderrun;

   // receive receiveVector
  short* shortVector = rcvBuffer+rcvCursor;
  //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
  int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
  underrun |= localUnderrun;
  readTimestamp += (TIMESTAMP) samplesRead;
  while (samplesRead < OUTCHUNK*samplesPerSymbol) {
    int oldSamplesRead = samplesRead;
    samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
				     OUTCHUNK*samplesPerSymbol-samplesRead,
				     &overrun,
				     readTimestamp,
				     &localUnderrun);
    underrun |= localUnderrun;
    readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
  }
  //LOG(DEBUG) << "samplesRead " << samplesRead;

  rcvCursor += samplesRead*2;

}

bool RadioInterface::tuneTx(double freq)
{
  return mRadio->setTxFreq(freq);
}

bool RadioInterface::tuneRx(double freq)
{
  return mRadio->setRxFreq(freq);
}

void RadioInterface::start()
{
  LOG(INFO) << "starting radio interface...";
  mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
                                     (void*)this);
  writeTimestamp = mRadio->initialWriteTimestamp();
  readTimestamp = mRadio->initialReadTimestamp();
  mRadio->start();
  LOG(DEBUG) << "Radio started";
  mRadio->updateAlignment(writeTimestamp-10000);
  mRadio->updateAlignment(writeTimestamp-10000);

  sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
  rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];

  mOn = true;

}

void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
{
  while (1) {
    radioInterface->alignRadio();
    pthread_testcancel();
  }
  return NULL;
}

void RadioInterface::alignRadio() {
  sleep(60);
  mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
}

void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {

  if (!mOn) return;

  radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);

  sendCursor += (radioBurst.size()*2);

  pushBuffer();
}

void RadioInterface::driveReceiveRadio() {

  if (!mOn) return;

  if (mReceiveFIFO.size() > 8) return;

  pullBuffer();

  GSM::Time rcvClock = mClock.get();
  rcvClock.decTN(receiveOffset);
  unsigned tN = rcvClock.TN();
  int rcvSz = rcvCursor/2;
  int readSz = 0;
  const int symbolsPerSlot = gSlotLen + 8;

  // while there's enough data in receive buffer, form received
  //    GSM bursts and pass up to Transceiver
  // Using the 157-156-156-156 symbols per timeslot format.
  while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
    signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
    unRadioifyVector(rcvBuffer+readSz*2,rxVector);
    GSM::Time tmpTime = rcvClock;
    if (rcvClock.FN() >= 0) {
      //LOG(DEBUG) << "FN: " << rcvClock.FN();
      radioVector *rxBurst = NULL;
      if (!loadTest)
        rxBurst = new radioVector(rxVector,tmpTime);
      else {
	if (tN % 4 == 0)
	  rxBurst = new radioVector(*finalVec9,tmpTime);
        else
          rxBurst = new radioVector(*finalVec,tmpTime);
      }
      mReceiveFIFO.put(rxBurst);
    }
    mClock.incTN();
    rcvClock.incTN();
    //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
    //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
    readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
    rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;

    tN = rcvClock.TN();
  }

  if (readSz > 0) {
    memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
    rcvCursor = rcvCursor-2*readSz;
  }
}

<commit_msg>transceiver: fix initialization segfault in radio interface<commit_after>/*
* Copyright 2008, 2009 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

//#define NDEBUG
#include "radioInterface.h"
#include <Logger.h>

GSM::Time VectorQueue::nextTime() const
{
  GSM::Time retVal;
  ScopedLock lock(mLock);
  while (mQ.size()==0) mWriteSignal.wait(mLock);
  return mQ.top()->time();
}

radioVector* VectorQueue::getStaleBurst(const GSM::Time& targTime)
{
  ScopedLock lock(mLock);
  if ((mQ.size()==0)) {
    return NULL;
  }
  if (mQ.top()->time() < targTime) {
    radioVector* retVal = mQ.top();
    mQ.pop();
    return retVal;
  }
  return NULL;
}

radioVector* VectorQueue::getCurrentBurst(const GSM::Time& targTime)
{
  ScopedLock lock(mLock);
  if ((mQ.size()==0)) {
    return NULL;
  }
  if (mQ.top()->time() == targTime) {
    radioVector* retVal = mQ.top();
    mQ.pop();
    return retVal;
  }
  return NULL;
}

RadioInterface::RadioInterface(RadioDevice *wRadio,
                               int wReceiveOffset,
			       int wRadioOversampling,
			       int wTransceiverOversampling,
			       GSM::Time wStartTime)

{
  underrun = false;

  sendCursor = 0;
  rcvCursor = 0;
  mOn = false;

  mRadio = wRadio;
  receiveOffset = wReceiveOffset;
  samplesPerSymbol = wRadioOversampling;
  mClock.set(wStartTime);
  powerScaling = 1.0;
  loadTest = false;
}

RadioInterface::~RadioInterface(void) {
  if (rcvBuffer!=NULL) delete rcvBuffer;
  //mReceiveFIFO.clear();
}

double RadioInterface::fullScaleInputValue(void) {
  return mRadio->fullScaleInputValue();
}

double RadioInterface::fullScaleOutputValue(void) {
  return mRadio->fullScaleOutputValue();
}

void RadioInterface::setPowerAttenuation(double dBAtten)
{
  float HWdBAtten = mRadio->setTxGain(-dBAtten);
  dBAtten -= (-HWdBAtten);
  float linearAtten = powf(10.0F,0.1F*dBAtten);
  if (linearAtten < 1.0)
    powerScaling = 1.0;
  else
    powerScaling = 1.0/sqrt(linearAtten);
  LOG(INFO) << "setting HW gain to " << HWdBAtten << " and power scaling to " << powerScaling;
}

short *RadioInterface::radioifyVector(signalVector &wVector, short *retVector, double scale, bool zeroOut)
{

  signalVector::iterator itr = wVector.begin();
  short *shortItr = retVector;
  if (zeroOut) {
    while (itr < wVector.end()) {
      *shortItr++ = 0;
      *shortItr++ = 0;
      itr++;
    }
  }
  else if (scale != 1.0) {
    while (itr < wVector.end()) {
      *shortItr++ = (short) (itr->real()*scale);
      *shortItr++ = (short) (itr->imag()*scale);
      itr++;
    }
  }
  else {
    while (itr < wVector.end()) {
      *shortItr++ = (short) (itr->real());
      *shortItr++ = (short) (itr->imag());
      itr++;
    }
  }

  return retVector;

}

void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
{

  signalVector::iterator itr = newVector.begin();
  short *shortItr = shortVector;
  while (itr < newVector.end()) {
    *itr++ = Complex<float>(*shortItr,*(shortItr+1));
    //LOG(DEBUG) << (*(itr-1));
    shortItr += 2;
  }

}

bool started = false;

void RadioInterface::pushBuffer(void) {

  if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;

  // send resampleVector
  int samplesWritten = mRadio->writeSamples(sendBuffer,
					  INCHUNK*samplesPerSymbol,
					  &underrun,
					  writeTimestamp);
  //LOG(DEBUG) << "writeTimestamp: " << writeTimestamp << ", samplesWritten: " << samplesWritten;

  writeTimestamp += (TIMESTAMP) samplesWritten;

  if (sendCursor > 2*samplesWritten)
    memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
  sendCursor = sendCursor - 2*samplesWritten;
}

void RadioInterface::pullBuffer(void)
{

  bool localUnderrun;

   // receive receiveVector
  short* shortVector = rcvBuffer+rcvCursor;
  //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
  int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
  underrun |= localUnderrun;
  readTimestamp += (TIMESTAMP) samplesRead;
  while (samplesRead < OUTCHUNK*samplesPerSymbol) {
    int oldSamplesRead = samplesRead;
    samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
				     OUTCHUNK*samplesPerSymbol-samplesRead,
				     &overrun,
				     readTimestamp,
				     &localUnderrun);
    underrun |= localUnderrun;
    readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
  }
  //LOG(DEBUG) << "samplesRead " << samplesRead;

  rcvCursor += samplesRead*2;

}

bool RadioInterface::tuneTx(double freq)
{
  return mRadio->setTxFreq(freq);
}

bool RadioInterface::tuneRx(double freq)
{
  return mRadio->setRxFreq(freq);
}

void RadioInterface::start()
{
  LOG(INFO) << "starting radio interface...";
  mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
                                     (void*)this);
  writeTimestamp = mRadio->initialWriteTimestamp();
  readTimestamp = mRadio->initialReadTimestamp();
  mRadio->start();
  LOG(DEBUG) << "Radio started";
  mRadio->updateAlignment(writeTimestamp-10000);
  mRadio->updateAlignment(writeTimestamp-10000);

  sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
  rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];

  mOn = true;

}

void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
{
  while (1) {
    radioInterface->alignRadio();
    pthread_testcancel();
  }
  return NULL;
}

void RadioInterface::alignRadio() {
  sleep(60);
  mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
}

void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {

  if (!mOn) return;

  radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);

  sendCursor += (radioBurst.size()*2);

  pushBuffer();
}

void RadioInterface::driveReceiveRadio() {

  if (!mOn) return;

  if (mReceiveFIFO.size() > 8) return;

  pullBuffer();

  GSM::Time rcvClock = mClock.get();
  rcvClock.decTN(receiveOffset);
  unsigned tN = rcvClock.TN();
  int rcvSz = rcvCursor/2;
  int readSz = 0;
  const int symbolsPerSlot = gSlotLen + 8;

  // while there's enough data in receive buffer, form received
  //    GSM bursts and pass up to Transceiver
  // Using the 157-156-156-156 symbols per timeslot format.
  while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
    signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
    unRadioifyVector(rcvBuffer+readSz*2,rxVector);
    GSM::Time tmpTime = rcvClock;
    if (rcvClock.FN() >= 0) {
      //LOG(DEBUG) << "FN: " << rcvClock.FN();
      radioVector *rxBurst = NULL;
      if (!loadTest)
        rxBurst = new radioVector(rxVector,tmpTime);
      else {
	if (tN % 4 == 0)
	  rxBurst = new radioVector(*finalVec9,tmpTime);
        else
          rxBurst = new radioVector(*finalVec,tmpTime);
      }
      mReceiveFIFO.put(rxBurst);
    }
    mClock.incTN();
    rcvClock.incTN();
    //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
    //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
    readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
    rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;

    tN = rcvClock.TN();
  }

  if (readSz > 0) {
    memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
    rcvCursor = rcvCursor-2*readSz;
  }
}

<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef NET_ROUTER_HPP
#define NET_ROUTER_HPP

#include <map>
#include <net/inet.hpp>

namespace net {

  template <class IPV>
  struct Route {

    using Stack = Inet<IPV>;
    using Stack_ptr = Stack*;
    using Addr = typename IPV::addr;
    using Netmask = typename IPV::addr;

    Addr dest_net()
    { return dest_net_; }

    Netmask netmask()
    { return netmask_; }

    Addr gateway()
    { return gateway_; }

    int cost()
    { return cost_; }

    Stack_ptr interface()
    { return iface_; };

    Route(Addr dest_net, Netmask mask, Addr gateway, Stack& iface, int cost)
      : dest_net_{dest_net}, netmask_{mask}, gateway_{gateway}, iface_{&iface}, cost_{cost}
    {}

  private:
    Addr dest_net_;
    Netmask netmask_;
    Addr gateway_;
    Stack_ptr iface_;
    int cost_;
  };

  template<class IPV>
  struct Router {

    using Stack   = typename Route<IPV>::Stack;
    using Stack_ptr = typename Route<IPV>::Stack_ptr;
    using Forward_delg = typename Inet<IPV>::Forward_delg;
    using Addr    = typename IPV::addr;
    using Interfaces = std::vector<std::unique_ptr<Stack>>;
    using Routing_table = std::vector<Route<IPV>>;

    /**
     * Forward an IP packet according to local policy / routing table.
     **/
    void forward(Stack& source, typename IPV::IP_packet_ptr);

    /**
     * Get forwarding delegate
     * (And ensure forward signature Matches the signature of IP forwarding delegate.)
     **/
    Forward_delg forward_delg()
    { return Forward_delg(*this, forward); }

    /** Get the interface route for a certain IP **/
    virtual Stack_ptr get_interface(typename IPV::addr dest) {

      for (auto&& route : routing_table_) {
        if ((dest & route.netmask()) == route.dest_net())
          return route.interface();
      }

      return nullptr;

    };

    bool route_check(typename IPV::addr dest){
      return get_interface(dest);
    }

    /** Construct a router over a set of interfaces **/
    Router(Interfaces& ifaces, Routing_table&& tbl = {})
      : networks_{ifaces}, routing_table_{tbl}
    {  }

    void set_routing_table(Routing_table&& tbl) {
      routing_table_ = std::forward(tbl);
    };

    void set_routing_table(Routing_table tbl) {
      routing_table_ = tbl;
    };

  private:
    Interfaces& networks_;
    Routing_table routing_table_;

  };

} //< namespace net

#endif // NET_ROUTER_HPP
<commit_msg>router: a little more functionality<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef NET_ROUTER_HPP
#define NET_ROUTER_HPP

#include <map>
#include <net/inet.hpp>

namespace net {

  template <class IPV>
  struct Route {

    using Stack = Inet<IPV>;
    using Stack_ptr = Stack*;
    using Addr = typename IPV::addr;
    using Netmask = typename IPV::addr;

    Addr net() const noexcept
    { return net_; }

    Netmask netmask() const noexcept
    { return netmask_; }

    Addr gateway() const noexcept
    { return gateway_; }

    int cost() const noexcept
    { return cost_; }

    Stack_ptr interface() const noexcept
    { return iface_; };

    Stack_ptr match(typename IPV::addr dest) const noexcept
    { return (dest & netmask_) == net_ ? iface_ : nullptr; }

    bool operator<(const Route& b) const
    { return cost() < b.cost(); }

    bool operator==(const Route& b) const
    {
      return net_ == b.net() and
        netmask_ == b.netmask() and
        cost_ == b.cost() and
        iface_ == b.interface();
    }

    Route(Addr net, Netmask mask, Addr gateway, Stack& iface, int cost)
      : net_{net}, netmask_{mask}, gateway_{gateway}, iface_{&iface}, cost_{cost}
    {}

  private:
    Addr net_;
    Netmask netmask_;
    Addr gateway_;
    Stack_ptr iface_;
    int cost_;
  };

  template<class IPV>
  struct Router {

    using Stack   = typename Route<IPV>::Stack;
    using Stack_ptr = typename Route<IPV>::Stack_ptr;
    using Forward_delg = typename Inet<IPV>::Forward_delg;
    using Addr    = typename IPV::addr;
    using Interfaces = std::vector<std::unique_ptr<Stack>>;
    using Routing_table = std::vector<Route<IPV>>;

    /**
     * Forward an IP packet according to local policy / routing table.
     **/
    void forward(Stack& source, typename IPV::IP_packet_ptr);

    /**
     * Get forwarding delegate
     * (And ensure forward signature Matches the signature of IP forwarding delegate.)
     **/
    Forward_delg forward_delg()
    { return Forward_delg(*this, forward); }

    /** Get any interface route for a certain IP **/
    Route<IPV>* get_first_route(typename IPV::addr dest) {

      for (auto&& route : routing_table_) {
        Stack_ptr match = route.match(dest);
        if (match) return &route;
      }

      return nullptr;
    };

    /** Get any interface route for a certain IP **/
    Stack_ptr get_first_interface(typename IPV::addr dest) {
      auto route = get_first_route(dest);
      if (route) return route->interface();
      return nullptr;
    };

    /** Check if there exists a route for a given IP **/
    bool route_check(typename IPV::addr dest){
      return get_first_interface(dest) != nullptr;
    }

    /**
     * Get all routes for a certain IP
     * @todo : Optimize!
     **/
    Routing_table get_all_routes(typename IPV::addr dest) {

      Routing_table t;
      std::copy_if(routing_table_.begin(),
                   routing_table_.end(),
                   std::back_inserter(t), [dest](const Route<IPV>& route) {
                     return route.match(dest);
                   });
      return t;
    }

    /**
     * Get cheapest route for a certain IP
     * @todo : Optimize!
     **/
    Route<IPV>* get_cheapest_route(typename IPV::addr dest) {
      Routing_table all = get_all_routes(dest);
      std::sort(all.begin(), all.end());
      if (not all.empty()) return &all.front();
      return nullptr;
    };

    /** Construct a router over a set of interfaces **/
    Router(Interfaces& ifaces, Routing_table tbl = {})
      : networks_{ifaces}, routing_table_{tbl}
    {  }

    void set_routing_table(Routing_table tbl) {
      routing_table_ = tbl;
    };

  private:
    Interfaces& networks_;
    Routing_table routing_table_;

  };

} //< namespace net

#endif // NET_ROUTER_HPP
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   KWSys - Kitware System Library
  Module:    DynamicLoader.cxx

  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)

#include KWSYS_HEADER(Configure.hxx)

#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#include <string.h> // for strlen
#endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#endif // __APPLE__

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "DynamicLoader.hxx.in"
# include "Configure.hxx.in"
#endif

// This file is actually 3 different implementations.
// 1. HP machines which uses shl_load
// 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
// 3. Windows which uses LoadLibrary
// 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen (default)
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
DynamicLoader::DynamicLoader()
{
}

//----------------------------------------------------------------------------
DynamicLoader::~DynamicLoader()
{
}

}

// ---------------------------------------------------------------
// 1. Implementation for HPUX  machines
#ifdef __hpux
#include <dl.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return !shl_unload(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction
DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* addr;
  int status;

  /* TYPE_PROCEDURE Look for a function or procedure.
   * TYPE_DATA      Look for a symbol in the data segment (for example, variables).
   * TYPE_UNDEFINED Look for any symbol.
   */
  status = shl_findsym (&lib, sym, TYPE_UNDEFINED, &addr);
  void* result = (status < 0) ? (void*)0 : addr;

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".sl";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  // TODO: Need implementation with errno/strerror
  /* If successful, shl_findsym returns an integer (int) value zero. If
   * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
   * If any other errors occur, shl_findsym returns -1 and sets errno to one
   * of these values (defined in <errno.h>):
   * ENOEXEC
   * A format error was detected in the specified library.
   * ENOSYM
   * A symbol on which sym depends could not be found.
   * EINVAL
   * The specified handle is invalid.
   */

  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //__hpux

// ---------------------------------------------------------------
// 2. Implementation for Mac OS X 10.2.x and earlier
#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#include <mach-o/dyld.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  NSObjectFileImageReturnCode rc;
  NSObjectFileImage image = 0;

  rc = NSCreateObjectFileImageFromFile(libname, &image);
  // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
  if( rc != NSObjectFileImageSuccess )
    {
    return 0;
    }
  return NSLinkModule(image, libname,
    NSLINKMODULE_OPTION_PRIVATE|NSLINKMODULE_OPTION_BINDNOW);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary( LibHandle lib)
{
  bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  return success;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void *result=0;
  // Need to prepend symbols with '_' on Apple-gcc compilers
  size_t len = strlen(sym);
  char *rsym = new char[len + 1 + 1];
  strcpy(rsym, "_");
  strcat(rsym+1, sym);

  NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
  if(symbol)
    {
    result = NSAddressOfSymbol(symbol);
    }

  delete[] rsym;
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  // NSCreateObjectFileImageFromFile fail when dealing with dylib image
  // it returns NSObjectFileImageInappropriateFile
  //return ".dylib";
  return ".so";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#endif // __APPLE__

// ---------------------------------------------------------------
// 3. Implementation for Windows win32 code
#ifdef _WIN32
#include <windows.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname)
{
  LibHandle lh;
#ifdef UNICODE
  wchar_t libn[MB_CUR_MAX];
  mbstowcs(libn, libname, MB_CUR_MAX);
  lh = LoadLibrary(libn);
#else
  lh = LoadLibrary(libname);
#endif
  return lh;
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return (int)FreeLibrary(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void *result;
#ifdef __BORLANDC__
  // Need to prepend symbols with '_' on borland compilers
  size_t len = strlen(sym);
  char *rsym = new char[len + 1 + 1];
  strcpy(rsym, "_");
  strcat(rsym+1, sym);
#else
  const char *rsym = sym;
#endif
#ifdef UNICODE
  wchar_t wsym[MB_CUR_MAX];
  mbstowcs(wsym, rsym, MB_CUR_MAX);
  result = GetProcAddress(lib, wsym);
#else
  result = (void*)GetProcAddress(lib, rsym);
#endif
#ifdef __BORLANDC__
  delete[] rsym;
#endif
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".dll";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  LPVOID lpMsgBuf;

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf,
    0,
    NULL
    );

  static char* str = 0;
  delete [] str;
  str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  // Free the buffer.
  LocalFree( lpMsgBuf );
  return str;
}

} // namespace KWSYS_NAMESPACE

#endif //_WIN32

// ---------------------------------------------------------------
// 4. Implementation for default UNIX machines.
// if nothing has been defined then use this
#ifndef DYNAMICLOADER_DEFINED
#define DYNAMICLOADER_DEFINED 1
// Setup for most unix machines
#include <dlfcn.h>

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return dlopen(libname, RTLD_LAZY);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  if (lib)
    {
    // The function dlclose() returns 0 on success, and non-zero on error.
    return !dlclose(lib);
    }
  // else
  return 0;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* result = dlsym(lib, sym);

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
#ifdef __CYGWIN__
  return ".dll";
#else
  return ".so";
#endif
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return dlerror();
}

} // namespace KWSYS_NAMESPACE

#endif
<commit_msg>ENH: Add support for LastError on HPUX<commit_after>/*=========================================================================

  Program:   KWSys - Kitware System Library
  Module:    DynamicLoader.cxx

  Copyright (c) Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)

#include KWSYS_HEADER(Configure.hxx)

#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#include <string.h> // for strlen
#endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#endif // __APPLE__

#ifdef __hpux
#include <errno.h>
#endif //__hpux

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
# include "DynamicLoader.hxx.in"
# include "Configure.hxx.in"
#endif

// This file is actually 3 different implementations.
// 1. HP machines which uses shl_load
// 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
// 3. Windows which uses LoadLibrary
// 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen (default)
// Each part of the ifdef contains a complete implementation for
// the static methods of DynamicLoader.

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
DynamicLoader::DynamicLoader()
{
}

//----------------------------------------------------------------------------
DynamicLoader::~DynamicLoader()
{
}

}

// ---------------------------------------------------------------
// 1. Implementation for HPUX  machines
#ifdef __hpux
#include <dl.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return !shl_unload(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction
DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* addr;
  int status;

  /* TYPE_PROCEDURE Look for a function or procedure.
   * TYPE_DATA      Look for a symbol in the data segment (for example, variables).
   * TYPE_UNDEFINED Look for any symbol.
   */
  status = shl_findsym (&lib, sym, TYPE_UNDEFINED, &addr);
  void* result = (status < 0) ? (void*)0 : addr;

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".sl";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  // TODO: Need implementation with errno/strerror
  /* If successful, shl_findsym returns an integer (int) value zero. If
   * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
   * If any other errors occur, shl_findsym returns -1 and sets errno to one
   * of these values (defined in <errno.h>):
   * ENOEXEC
   * A format error was detected in the specified library.
   * ENOSYM
   * A symbol on which sym depends could not be found.
   * EINVAL
   * The specified handle is invalid.
   */

  if(  errno == ENOEXEC
    || errno == ENOSYM
    || errno == EINVAL )
    {
    return strerror(errno);
    }
  // else
  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //__hpux

// ---------------------------------------------------------------
// 2. Implementation for Mac OS X 10.2.x and earlier
#ifdef __APPLE__
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#include <mach-o/dyld.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  NSObjectFileImageReturnCode rc;
  NSObjectFileImage image = 0;

  rc = NSCreateObjectFileImageFromFile(libname, &image);
  // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
  if( rc != NSObjectFileImageSuccess )
    {
    return 0;
    }
  return NSLinkModule(image, libname,
    NSLINKMODULE_OPTION_PRIVATE|NSLINKMODULE_OPTION_BINDNOW);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary( LibHandle lib)
{
  bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  return success;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void *result=0;
  // Need to prepend symbols with '_' on Apple-gcc compilers
  size_t len = strlen(sym);
  char *rsym = new char[len + 1 + 1];
  strcpy(rsym, "_");
  strcat(rsym+1, sym);

  NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
  if(symbol)
    {
    result = NSAddressOfSymbol(symbol);
    }

  delete[] rsym;
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  // NSCreateObjectFileImageFromFile fail when dealing with dylib image
  // it returns NSObjectFileImageInappropriateFile
  //return ".dylib";
  return ".so";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return 0;
}

} // namespace KWSYS_NAMESPACE

#endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
#endif // __APPLE__

// ---------------------------------------------------------------
// 3. Implementation for Windows win32 code
#ifdef _WIN32
#include <windows.h>
#define DYNAMICLOADER_DEFINED 1

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname)
{
  LibHandle lh;
#ifdef UNICODE
  wchar_t libn[MB_CUR_MAX];
  mbstowcs(libn, libname, MB_CUR_MAX);
  lh = LoadLibrary(libn);
#else
  lh = LoadLibrary(libname);
#endif
  return lh;
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  return (int)FreeLibrary(lib);
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void *result;
#ifdef __BORLANDC__
  // Need to prepend symbols with '_' on borland compilers
  size_t len = strlen(sym);
  char *rsym = new char[len + 1 + 1];
  strcpy(rsym, "_");
  strcat(rsym+1, sym);
#else
  const char *rsym = sym;
#endif
#ifdef UNICODE
  wchar_t wsym[MB_CUR_MAX];
  mbstowcs(wsym, rsym, MB_CUR_MAX);
  result = GetProcAddress(lib, wsym);
#else
  result = (void*)GetProcAddress(lib, rsym);
#endif
#ifdef __BORLANDC__
  delete[] rsym;
#endif
  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
  return ".dll";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  LPVOID lpMsgBuf;

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    (LPTSTR) &lpMsgBuf,
    0,
    NULL
    );

  static char* str = 0;
  delete [] str;
  str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  // Free the buffer.
  LocalFree( lpMsgBuf );
  return str;
}

} // namespace KWSYS_NAMESPACE

#endif //_WIN32

// ---------------------------------------------------------------
// 4. Implementation for default UNIX machines.
// if nothing has been defined then use this
#ifndef DYNAMICLOADER_DEFINED
#define DYNAMICLOADER_DEFINED 1
// Setup for most unix machines
#include <dlfcn.h>

namespace KWSYS_NAMESPACE
{

//----------------------------------------------------------------------------
LibHandle DynamicLoader::OpenLibrary(const char* libname )
{
  return dlopen(libname, RTLD_LAZY);
}

//----------------------------------------------------------------------------
int DynamicLoader::CloseLibrary(LibHandle lib)
{
  if (lib)
    {
    // The function dlclose() returns 0 on success, and non-zero on error.
    return !dlclose(lib);
    }
  // else
  return 0;
}

//----------------------------------------------------------------------------
DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
{
  void* result = dlsym(lib, sym);

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoaderFunction*>(&result);
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibPrefix()
{
  return "lib";
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LibExtension()
{
#ifdef __CYGWIN__
  return ".dll";
#else
  return ".so";
#endif
}

//----------------------------------------------------------------------------
const char* DynamicLoader::LastError()
{
  return dlerror();
}

} // namespace KWSYS_NAMESPACE

#endif
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(h)

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * class NestedInteger {
 *   public:
 *     // Return true if this NestedInteger holds a single integer, rather than a nested list.
 *     bool isInteger() const;
 *
 *     // Return the single integer that this NestedInteger holds, if it holds a single integer
 *     // The result is undefined if this NestedInteger holds a nested list
 *     int getInteger() const;
 *
 *     // Return the nested list that this NestedInteger holds, if it holds a nested list
 *     // The result is undefined if this NestedInteger holds a single integer
 *     const vector<NestedInteger> &getList() const;
 * };
 */
class Solution {
public:
    int depthSumInverse(vector<NestedInteger>& nestedList) {
        vector<int> result;
        for(auto list : nestedList) {
            depthSumInverseHelper(list, 0, &result);
        }

        int sum = 0;
        for (int i = result.size() - 1; i >= 0; --i) {
            sum += result[i] * (result.size() - i);
        }
        return sum;
    }

private:
    void depthSumInverseHelper(const NestedInteger &list, int depth, vector<int> *result) {
        if (result->size() < depth + 1) {
            result->emplace_back(0);
        }
        if (list.isInteger()) {
            (*result)[depth] += list.getInteger();
        } else {
            for(auto l : list.getList()) {
                depthSumInverseHelper(l, depth + 1, result);
            }
        }
    }
};
<commit_msg>Update nested-list-weight-sum-ii.cpp<commit_after>// Time:  O(n)
// Space: O(h)

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * class NestedInteger {
 *   public:
 *     // Return true if this NestedInteger holds a single integer, rather than a nested list.
 *     bool isInteger() const;
 *
 *     // Return the single integer that this NestedInteger holds, if it holds a single integer
 *     // The result is undefined if this NestedInteger holds a nested list
 *     int getInteger() const;
 *
 *     // Return the nested list that this NestedInteger holds, if it holds a nested list
 *     // The result is undefined if this NestedInteger holds a single integer
 *     const vector<NestedInteger> &getList() const;
 * };
 */
class Solution {
public:
    int depthSumInverse(vector<NestedInteger>& nestedList) {
        vector<int> result;
        for (const auto& list : nestedList) {
            depthSumInverseHelper(list, 0, &result);
        }

        int sum = 0;
        for (int i = result.size() - 1; i >= 0; --i) {
            sum += result[i] * (result.size() - i);
        }
        return sum;
    }

private:
    void depthSumInverseHelper(const NestedInteger &list, int depth, vector<int> *result) {
        if (result->size() < depth + 1) {
            result->emplace_back(0);
        }
        if (list.isInteger()) {
            (*result)[depth] += list.getInteger();
        } else {
            for(const auto& l : list.getList()) {
                depthSumInverseHelper(l, depth + 1, result);
            }
        }
    }
};
<|endoftext|>


<commit_before>/*
 * nghttp2 - HTTP/2.0 C Library
 *
 * Copyright (c) 2012 Tatsuhiro Tsujikawa
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "nghttp2_config.h"

#include <unistd.h>
#include <signal.h>
#include <getopt.h>

#include <cstdlib>
#include <cstring>
#include <cassert>
#include <string>
#include <iostream>
#include <string>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <nghttp2/nghttp2.h>

#include "app_helper.h"
#include "HttpServer.h"
#include "util.h"
#include "ssl.h"

namespace nghttp2 {

namespace {
int parse_push_config(Config& config, const char *optarg)
{
  const char *eq = strchr(optarg, '=');
  if(eq == NULL) {
    return -1;
  }
  auto paths = std::vector<std::string>();
  auto optarg_end = optarg + strlen(optarg);
  const char *i = eq + 1;
  for(;;) {
    const char *j = strchr(i, ',');
    if(j == NULL) {
      j = optarg_end;
    }
    paths.emplace_back(i, j);
    if(j == optarg_end) {
      break;
    }
    i = j;
    ++i;
  }
  config.push[std::string(optarg, eq)] = std::move(paths);
  return 0;
}
} // namespace

namespace {
void print_version(std::ostream& out)
{
  out << "nghttpd nghttp2/" NGHTTP2_VERSION << std::endl;
}
} // namespace

namespace {
void print_usage(std::ostream& out)
{
  out << "Usage: nghttpd [OPTION]... <PORT> <PRIVATE_KEY> <CERT>\n"
      << "  or:  nghttpd --no-tls [OPTION]... <PORT>\n"
      << "HTTP/2 experimental server" << std::endl;
}
} // namespace

namespace {
void print_help(std::ostream& out)
{
  print_usage(out);
  out << "\n"
      << "  <PORT>             Specify listening port number.\n"
      << "  <PRIVATE_KEY>      Set path to server's private key. Required\n"
      << "                     unless --no-tls is specified.\n"
      << "  <CERT>             Set path to server's certificate. Required\n"
      << "                     unless --no-tls is specified.\n"
      << "\n"
      << "Options:\n"
      << "  -D, --daemon       Run in a background. If -D is used, the\n"
      << "                     current working directory is changed to '/'.\n"
      << "                     Therefore if this option is used, -d option\n"
      << "                     must be specified.\n"
      << "  -V, --verify-client\n"
      << "                     The server sends a client certificate\n"
      << "                     request. If the client did not return a\n"
      << "                     certificate, the handshake is terminated.\n"
      << "                     Currently, this option just requests a\n"
      << "                     client certificate and does not verify it.\n"
      << "  -d, --htdocs=<PATH>\n"
      << "                     Specify document root. If this option is\n"
      << "                     not specified, the document root is the\n"
      << "                     current working directory.\n"
      << "  -v, --verbose      Print debug information such as reception/\n"
      << "                     transmission of frames and name/value pairs.\n"
      << "  --no-tls           Disable SSL/TLS.\n"
      << "  -c, --header-table-size=<N>\n"
      << "                     Specify decoder header table size.\n"
      << "  --color            Force colored log output.\n"
      << "  -p, --push=<PATH>=<PUSH_PATH,...>\n"
      << "                     Push resources PUSH_PATHs when PATH is\n"
      << "                     requested. This option can be used\n"
      << "                     repeatedly to specify multiple push\n"
      << "                     configurations. For example,\n"
      << "                       -p/=/foo.png -p/doc=/bar.css\n"
      << "                     PATH and PUSH_PATHs are relative to document\n"
      << "                     root. See --htdocs option.\n"
      << "  -b, --padding=<N>  Add at most <N> bytes to a frame payload as\n"
      << "                     padding. Specify 0 to disable padding.\n"
      << "  -n, --workers=<CORE>\n"
      << "                     Set the number of worker threads.\n"
      << "                     Default: 1\n"
      << "  -e, --error-gzip   Make error response gzipped.\n"
      << "  --version          Display version information and exit.\n"
      << "  -h, --help         Display this help and exit.\n"
      << std::endl;
}
} // namespace

int main(int argc, char **argv)
{
  Config config;
  bool color = false;
  while(1) {
    int flag = 0;
    static option long_options[] = {
      {"daemon", no_argument, nullptr, 'D'},
      {"htdocs", required_argument, nullptr, 'd'},
      {"help", no_argument, nullptr, 'h'},
      {"verbose", no_argument, nullptr, 'v'},
      {"verify-client", no_argument, nullptr, 'V'},
      {"header-table-size", required_argument, nullptr, 'c'},
      {"push", required_argument, nullptr, 'p'},
      {"padding", required_argument, nullptr, 'b'},
      {"workers", required_argument, nullptr, 'n'},
      {"error-gzip", no_argument, nullptr, 'e'},
      {"no-tls", no_argument, &flag, 1},
      {"color", no_argument, &flag, 2},
      {"version", no_argument, &flag, 3},
      {nullptr, 0, nullptr, 0}
    };
    int option_index = 0;
    int c = getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options,
                        &option_index);
    char *end;
    if(c == -1) {
      break;
    }
    switch(c) {
    case 'D':
      config.daemon = true;
      break;
    case 'V':
      config.verify_client = true;
      break;
    case 'b':
      config.padding = strtol(optarg, nullptr, 10);
      break;
    case 'd':
      config.htdocs = optarg;
      break;
    case 'e':
      config.error_gzip = true;
      break;
    case 'n':
      errno = 0;
      config.num_worker = strtoul(optarg, &end, 10);
      if(errno == ERANGE || *end != '\0' || config.num_worker == 0) {
        std::cerr << "-n: Bad option value: " << optarg << std::endl;
        exit(EXIT_FAILURE);
      }
      break;
    case 'h':
      print_help(std::cout);
      exit(EXIT_SUCCESS);
    case 'v':
      config.verbose = true;
      break;
    case 'c':
      errno = 0;
      config.header_table_size = strtol(optarg, &end, 10);
      if(errno == ERANGE || *end != '\0') {
        std::cerr << "-c: Bad option value: " << optarg << std::endl;
        exit(EXIT_FAILURE);
      }
      break;
    case 'p':
      if(parse_push_config(config, optarg) != 0) {
        std::cerr << "-p: Bad option value: " << optarg << std::endl;
      }
      break;
    case '?':
      util::show_candidates(argv[optind - 1], long_options);
      exit(EXIT_FAILURE);
    case 0:
      switch(flag) {
      case 1:
        // no-tls option
        config.no_tls = true;
        break;
      case 2:
        // color option
        color = true;
        break;
      case 3:
        // version
        print_version(std::cout);
        exit(EXIT_SUCCESS);
      }
      break;
    default:
      break;
    }
  }
  if(argc - optind < (config.no_tls ? 1 : 3)) {
    print_usage(std::cerr);
    std::cerr << "Too few arguments" << std::endl;
    exit(EXIT_FAILURE);
  }

  config.port = strtol(argv[optind++], nullptr, 10);

  if(!config.no_tls) {
    config.private_key_file = argv[optind++];
    config.cert_file = argv[optind++];
  }

  if(config.daemon) {
    if(config.htdocs.empty()) {
      print_usage(std::cerr);
      std::cerr << "-d option must be specified when -D is used." << std::endl;
      exit(EXIT_FAILURE);
    }
    if(daemon(0, 0) == -1) {
      perror("daemon");
      exit(EXIT_FAILURE);
    }
  }
  if(config.htdocs.empty()) {
    config.htdocs = "./";
  }

  set_color_output(color || isatty(fileno(stdout)));

  struct sigaction act;
  memset(&act, 0, sizeof(struct sigaction));
  act.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &act, nullptr);
  OpenSSL_add_all_algorithms();
  SSL_load_error_strings();
  SSL_library_init();
  ssl::LibsslGlobalLock();

  reset_timer();

  HttpServer server(&config);
  server.run();
  return 0;
}

} // namespace nghttp2

int main(int argc, char **argv)
{
  return nghttp2::main(argc, argv);
}
<commit_msg>nghttpd: Use raw-string literal to output help<commit_after>/*
 * nghttp2 - HTTP/2.0 C Library
 *
 * Copyright (c) 2012 Tatsuhiro Tsujikawa
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "nghttp2_config.h"

#include <unistd.h>
#include <signal.h>
#include <getopt.h>

#include <cstdlib>
#include <cstring>
#include <cassert>
#include <string>
#include <iostream>
#include <string>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <nghttp2/nghttp2.h>

#include "app_helper.h"
#include "HttpServer.h"
#include "util.h"
#include "ssl.h"

namespace nghttp2 {

namespace {
int parse_push_config(Config& config, const char *optarg)
{
  const char *eq = strchr(optarg, '=');
  if(eq == NULL) {
    return -1;
  }
  auto paths = std::vector<std::string>();
  auto optarg_end = optarg + strlen(optarg);
  const char *i = eq + 1;
  for(;;) {
    const char *j = strchr(i, ',');
    if(j == NULL) {
      j = optarg_end;
    }
    paths.emplace_back(i, j);
    if(j == optarg_end) {
      break;
    }
    i = j;
    ++i;
  }
  config.push[std::string(optarg, eq)] = std::move(paths);
  return 0;
}
} // namespace

namespace {
void print_version(std::ostream& out)
{
  out << "nghttpd nghttp2/" NGHTTP2_VERSION << std::endl;
}
} // namespace

namespace {
void print_usage(std::ostream& out)
{
  out << "Usage: nghttpd [OPTION]... <PORT> <PRIVATE_KEY> <CERT>\n"
      << "  or:  nghttpd --no-tls [OPTION]... <PORT>\n"
      << "HTTP/2 experimental server" << std::endl;
}
} // namespace

namespace {
void print_help(std::ostream& out)
{
  print_usage(out);
  out << R"(
  <PORT>             Specify listening port number.
  <PRIVATE_KEY>      Set  path  to  server's  private  key.   Required
                     unless --no-tls is specified.
  <CERT>             Set  path  to   server's  certificate.   Required
                     unless --no-tls is specified.
Options:
  -D, --daemon       Run in a background.  If  -D is used, the current
                     working directory  is changed to  '/'.  Therefore
                     if  this  option  is  used,  -d  option  must  be
                     specified.
  -V, --verify-client
                     The  server sends  a client  certificate request.
                     If the  client did not return  a certificate, the
                     handshake is terminated.   Currently, this option
                     just requests  a client certificate and  does not
                     verify it.
  -d, --htdocs=<PATH>
                     Specify  document root.   If this  option is  not
                     specified,  the  document  root  is  the  current
                     working directory.
  -v, --verbose      Print  debug   information  such   as  reception/
                     transmission of frames and name/value pairs.
  --no-tls           Disable SSL/TLS.
  -c, --header-table-size=<N>
                     Specify decoder header table size.
  --color            Force colored log output.
  -p, --push=<PATH>=<PUSH_PATH,...>
                     Push  resources   <PUSH_PATH>s  when   <PATH>  is
                     requested.  This option can be used repeatedly to
                     specify multiple push configurations.  <PATH> and
                     <PUSH_PATH>s are relative  to document root.  See
                     --htdocs    option.      Example:    -p/=/foo.png
                     -p/doc=/bar.css
  -b, --padding=<N>  Add  at most  <N>  bytes to  a  frame payload  as
                     padding.  Specify 0 to disable padding.
  -n, --workers=<CORE>
                     Set the number of worker threads.
                     Default: 1
  -e, --error-gzip   Make error response gzipped.
  --version          Display version information and exit.
  -h, --help         Display this help and exit.)"
      << std::endl;
}
} // namespace

int main(int argc, char **argv)
{
  Config config;
  bool color = false;
  while(1) {
    int flag = 0;
    static option long_options[] = {
      {"daemon", no_argument, nullptr, 'D'},
      {"htdocs", required_argument, nullptr, 'd'},
      {"help", no_argument, nullptr, 'h'},
      {"verbose", no_argument, nullptr, 'v'},
      {"verify-client", no_argument, nullptr, 'V'},
      {"header-table-size", required_argument, nullptr, 'c'},
      {"push", required_argument, nullptr, 'p'},
      {"padding", required_argument, nullptr, 'b'},
      {"workers", required_argument, nullptr, 'n'},
      {"error-gzip", no_argument, nullptr, 'e'},
      {"no-tls", no_argument, &flag, 1},
      {"color", no_argument, &flag, 2},
      {"version", no_argument, &flag, 3},
      {nullptr, 0, nullptr, 0}
    };
    int option_index = 0;
    int c = getopt_long(argc, argv, "DVb:c:d:ehn:p:v", long_options,
                        &option_index);
    char *end;
    if(c == -1) {
      break;
    }
    switch(c) {
    case 'D':
      config.daemon = true;
      break;
    case 'V':
      config.verify_client = true;
      break;
    case 'b':
      config.padding = strtol(optarg, nullptr, 10);
      break;
    case 'd':
      config.htdocs = optarg;
      break;
    case 'e':
      config.error_gzip = true;
      break;
    case 'n':
      errno = 0;
      config.num_worker = strtoul(optarg, &end, 10);
      if(errno == ERANGE || *end != '\0' || config.num_worker == 0) {
        std::cerr << "-n: Bad option value: " << optarg << std::endl;
        exit(EXIT_FAILURE);
      }
      break;
    case 'h':
      print_help(std::cout);
      exit(EXIT_SUCCESS);
    case 'v':
      config.verbose = true;
      break;
    case 'c':
      errno = 0;
      config.header_table_size = strtol(optarg, &end, 10);
      if(errno == ERANGE || *end != '\0') {
        std::cerr << "-c: Bad option value: " << optarg << std::endl;
        exit(EXIT_FAILURE);
      }
      break;
    case 'p':
      if(parse_push_config(config, optarg) != 0) {
        std::cerr << "-p: Bad option value: " << optarg << std::endl;
      }
      break;
    case '?':
      util::show_candidates(argv[optind - 1], long_options);
      exit(EXIT_FAILURE);
    case 0:
      switch(flag) {
      case 1:
        // no-tls option
        config.no_tls = true;
        break;
      case 2:
        // color option
        color = true;
        break;
      case 3:
        // version
        print_version(std::cout);
        exit(EXIT_SUCCESS);
      }
      break;
    default:
      break;
    }
  }
  if(argc - optind < (config.no_tls ? 1 : 3)) {
    print_usage(std::cerr);
    std::cerr << "Too few arguments" << std::endl;
    exit(EXIT_FAILURE);
  }

  config.port = strtol(argv[optind++], nullptr, 10);

  if(!config.no_tls) {
    config.private_key_file = argv[optind++];
    config.cert_file = argv[optind++];
  }

  if(config.daemon) {
    if(config.htdocs.empty()) {
      print_usage(std::cerr);
      std::cerr << "-d option must be specified when -D is used." << std::endl;
      exit(EXIT_FAILURE);
    }
    if(daemon(0, 0) == -1) {
      perror("daemon");
      exit(EXIT_FAILURE);
    }
  }
  if(config.htdocs.empty()) {
    config.htdocs = "./";
  }

  set_color_output(color || isatty(fileno(stdout)));

  struct sigaction act;
  memset(&act, 0, sizeof(struct sigaction));
  act.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &act, nullptr);
  OpenSSL_add_all_algorithms();
  SSL_load_error_strings();
  SSL_library_init();
  ssl::LibsslGlobalLock();

  reset_timer();

  HttpServer server(&config);
  server.run();
  return 0;
}

} // namespace nghttp2

int main(int argc, char **argv)
{
  return nghttp2::main(argc, argv);
}
<|endoftext|>