Commit 30c4159e by Szeberényi Imre

Genetika

parents
#
# Egyszerű makefile (GNU)
# Feltételezi, hogy minden forrás fugg minden headertől
#
CCX = g++
CXXFLAGS = -std=c++11 -Wall -Werror -Wdeprecated -pedantic -DMEMTRACE -g
TARGET := genetika_teszt
HEADERS := $(wildcard *.h) $(wildcard *.hpp)
SOURCES := $(wildcard *.cpp)
OBJECTS := $(SOURCES:%.cpp=%.o)
$(TARGET): $(OBJECTS)
$(CCX) $^ -g -o $@ -ldl
%.o: %.c $(HEADERS)
$(CCX) $(CXXFLAGS) -c $<
clean:
rm -rf $(OBJECTS) genetika_teszt
\ No newline at end of file
# Egy kis genetika
**Szorgalmi feladat Karsa Zoltántól**. (extra pont: 2)
# Egy kis genetika
Genetikai kódunkat a következő 4 bázis alkotja:
* Adenin (A)
* Citozin (C)
* Guanin (G)
* Timin (T)
A genetikai vizsgálatunkhoz egy olyan programot kell írni, ami egy előre meghatározott leírásból (továbbiakban konfiguráció) képes létrehozni egy állapotgépet és egy DNS lánc elemzését el tudja végezni a konfiguráció alapján.
## Emlékeztető
Emlékezz vissza a Programozás alapjai 1 illetve a Digitális technikák tárgyon használt állapotgépekre (véges automaták), mire voltak elegendőek? Hogyan működtek?
A korábbi tantárgyakkal ellentétben itt az egyes állapotátmeneteknél nem lesz elvégzendő tevékenység (pl.: ly számláló esetén a számláló növelése, ha ly-t találtunk), hanem lesznek érvényes, "elfogadó" állapotok, azaz miután a bemenet elfogyott, és ebben az állapotban (vagy állapotokban) van az automata, elfogadunk, a bemenet jó volt, különben nem. Ezzel gyakorlatilag a véges automaták matematikai modelljéhez jutunk (Bővebben majd algoritmuselmélet tárgyon). Emiatt a korábban megismert ly számláló mását (pl. AC számláló) nem lehet megvalósítani, csak azt tudjuk eldönteni hogy van-e benne AC szakasz, vagy van-e benne 3db AC szakasz, számlálni nem lehet.
## Konfiguráció
Konfigurációs fájl első sora az állapotok számát kódolja (N), a következő N sorban, soronként az állapotok típusa (elfogadó - I, nem elfogadó - H) és az állapotok nevei (max 20 karakter) találhatóak, szóközzel elválasztva. Az első megadott állapot a felsorolásban a kezdőállapot. Ezután az állapotátmeneteket tartalmazó NxN-es mátrix következik a következő formában (a fejléc és az első oszlop nem része a konfigurációnak):
Állapotok | A_1 | A_2 | ... | A_N |
--- | --- | --- | --- |--- |
A_1 | A_1->A_1 | A_1->A_2 | ... | A_1->A_N |
A_2 | A_2->A_1 | A_2->A_2 | ... | A_2->A_N |
... | ... | ... | ... | ... |
A_N | A_N->A_1 | A_N->A_2 | ... | A_N->A_N |
Az első sor (A_1-hez tartozó) a mátrixban az első állapotból induló átmeneteket mutatja az előző felsorolás sorrendjében, mely bemeneti bázis esetén mely állapotba kerül onnan az automata. A mátrix 2. (A_2) sorában és 3. (A_3) oszlopában találhatóak azon bázisok, melyek hatására a 2. állapotból a 3.-ba kell kerüljön az automata... A celábban a bázisok a rövidítésekkel vannak feltüntetve elválasztó jelek nélkül (pl. CAT), a mátrix soraiban több és eltérő db szóköz gondoskodik a szeparálásról. Ha valahol nincs átmenet, ott nulla ('0') szerepel.
Beolvasáshoz ajánlott a `std::ifstream` használata, hasonlóan használható, mint az `std::cin`, azaz `>>`-val történő beolvaásákor eldobja a felesleges whitespace-eket.
Minden egyes sorban pontosan egyszer fordulhatnak elő valahol az ACGT betűk, így nem lehet olyan, hogy egy állapotból több állapotba is tudnánk menni egy bázis hatására vagy nem tudnánk eldönteni hova kellene lépni (= az automata determinisztikus és teljes).
## Skeleton program
A beadáshoz készetettem egy testprogramot (*genetika_teszt*.cpp) és megadtam, hogy az **Allapotgep** osztály miyen publikus interfésszel rendelkezik
(*allapotgep.h*):
```c++
// A bázisokhoz tartozó enum.
enum Bazis {
Adenin, Citozin, Guanin, Timin
};
// Állapotgép publikis interfésze
class Allapotgep {
public:
//konfig fájl beolvasása, ha a fájl nem létezik/nem lehet megnyitni eldobja a NEPTUN-kódot
//újra felépíti az állapotgépet, a korábbit törli ha volt
void konfigural(const char* fajlnev);
//visszaadja melyik állapot aktív
const char* aktualisallapot();
//éppen elfogadó állapotban van az állapotgép
bool elfogad();
//beérkező bázis hatására, mi történjen
void atmenet(Bazis b);
//a lánc feldolgozás után elfogadunk-e, nem áll vissza alaphelyzetbe
bool feldolgoz(Bazis *b, int n);
//visszaállítás a kezdő állapotba
void alaphelyzet();
};
```
Két globális függvényt is készítettem az enum kezeléséhez (`cast`-`cast`), ami a `char -> Bazis` és `Bazis -> char` konverziót segíti elő.
A megolshoz az **Allapotgep** belső logikája, mezői szabadon megváltoztathatóak, a publikus interfész azonben nem változtatható és nem bővíthető. Új osztályok azonban szabadon felvehetők az `allapothep.h` fájlba. Tipikusan legalább még 1-2 osztály felvétele szükséges a szép megoldáshoz. Az osztályok tagfüggvényeit `allapotgep.cpp` fájlban kell megvalósítani.
A `konfigural(const char* fajlnev)` függvény kivételt dob, ha a fájlt nem lehet megnyitni, a kivétel során a neptun kódodat kell eldobni. A konfiguráció minden esetben a fenti leírásnak megfelelő, más hibakezelést nem kell támogatni.
## Példa
A konfigurációs fájl:
```
2
I ParosTimin
H ParatlanTimin
ACG T
T ACG
```
Ezen fájlhoz tartozó állapotgép diagramja:
![állapotgép](statechart.png)
Példa bemenet: `{Adenin, Guanin, Timin, Citozin, Citozin, Timin}`, ekkor elfogadunk. Ezen bemenet végeztével az `aktualisallapot()` függvény `ParosTimin` karakterláncot adja vissza.
## Megoldás
A Git tárolóból letölthető [https://git.ik.bme.hu/Prog2/szorgalmi_feladat/genetike](https://git.ik.bme.hu/Prog2/szorgalmi_feladat/genetika)
fájlok felhasználásával hozzon létre a lokális fejlesztőkörnyezetében egy C++ projektet! Ehhez felhasználhatja a *Makefile* -t, amiben megtalálja a fordítási opciókat. Tervezzen, fejlesszen, teszteljen, majd adja tölse fel a megoldását a Jporta rendszerbe!
## Beadás
Beadandó az `allapotgep.cpp` és `allapotgep.h`, a genetika_teszt.cpp kell beadni, az a teszteléshez van. A Jporta nagyon hasonló módon fog tesztelni.
\ No newline at end of file
/**
* \file allapotgep.cpp
*
* Ebben a fájlban kell megvalósítania az Allapotgép osztány
* metódusait, valamint mindazon további osztályokat, melyek szükségesek
* a feladat megvalósításához.
*
* Ezt a fájlt be kell adni (fel kell tölteni) a megoldással.
*/
#include <iostream>
#include <fstream>
#include "allapotgep.h"
#include "memtrace.h"
/**
* \file allapotgep.h
*
* Ebben a fájlban találja az Allapotgép osztály kezdeti definicióját
* és két segédfüggvényt.
*
* A fájlt tetszés szerint múdosíthatja, azzal a megkütéssel, hogy
* nem hozhat létre globális függvényt és nem változtathatja az Allapotgép osztáy
* publikus interfészét.
*
* Új osztályokat, típusokat felvehet
*
* Ezt a fájlt be kell adni (fel kell tölteni) a megoldással.
*/
#ifndef ALLAPOTGEP_H
#define ALLAPOTGEP_H
#include <ctype.h>
#include <cstring>
#include <iostream>
#include <exception>
#include "memtrace.h"
/**
* Bázisok
*/
enum Bazis {
Adenin, Citozin, Guanin, Timin
};
/**
* Állapotgép publikus interfésze
* A privát részt szabadon változtathatja, de a publikus részt
* ne változtassa, ne bővítse!
*/
class Allapotgep {
public:
//visszaadja melyik állapot aktív
const char* aktualisallapot();
//éppen elfogadó állapotban van az állapotgép
bool elfogad();
//beérkező bázis hatására, mi történjen
void atmenet(Bazis b);
//a lánc feldolgozás után elfogadunk-e
bool feldolgoz(Bazis *b, int n);
//konfig fájl beolvasása
void konfigural(const char* fajlnev);
//visszaállítás a kezdő állapotba
void alaphelyzet();
~Allapotgep();
};
/**
* Segédfüggvény, karakterből enummá konvertál
* @param: b - bázis 1 betűs jele
* @return: Bazis enum kontans
*/
inline Bazis cast(char b) {
char k = tolower(b);
Bazis ret;
switch(k) {
case 'a': ret = Adenin; break;
case 'c': ret = Citozin; break;
case 'g': ret = Guanin; break;
case 't': ret = Timin; break;
default: throw "Format!!"; break;
}
return ret;
}
/**
* Segédfüggvény, Bazis konstansból karakterré konvertál
* @param: b - bazis enmu konstansa
* @param: upper - nagybetűs legyen-e
* @return: bázis 1 betűs jele
*/
inline char cast(Bazis b, bool upper = true) {
char ret = '0';
switch (b)
{
case Adenin: ret = 'a'; break;
case Citozin: ret = 'c'; break;
case Guanin: ret = 'g'; break;
case Timin: ret = 't'; break;
}
if(upper)
ret = toupper(ret);
return ret;
}
#endif
/**
* \file genetika_teszt.cpp
*
* Genetika nevű szorgalmi feladat tesztjei gtest_lite eszközkészletével megvalósítva.
* A szorgalmi feladat megoldásához ezt az állományt nem kell beadni (feltölteni).
*
* A ELKESZULT makró vezérli az egyes tesztesetek fordítását, ezzel lehetővé válik
* hogy kisebb lépésekben teszteljünk.
* Kezdetben ez 0, azaz nem tesztel semmit!
*
*/
#include <iostream>
#include "gtest_lite.h"
#include "allapotgep.h"
#include "memtrace.h"
#define ELKESZULT 0
int main() {
GTINIT(std::cin); // Csak C(J)PORTA működéséhez kell
#if ELKESZULT > 0
/// Azt vizsgálja, hogy dob-e hibát a fájl megnyitásakor
TEST(Konfig, KonfigHiba) {
Allapotgep gep;
try {
EXPECT_THROW_THROW(gep.konfigural("nincs_ilyen_fajl"), const char* p);
} catch (const char *p) {
#ifdef CPORTA
EXPECT_ENVCASEEQ("ORG_ID", p);
#endif
}
} END
#endif // ELKESZULT > 0
#if ELKESZULT > 1
/// Azt vizsgálja, hogy be tudja-e olvasni a konfiguráiós fájlt
TEST(ParosTrimin, fajbolkonfig1) {
Allapotgep gep;
ASSERT_NO_THROW(gep.konfigural("paros.txt"));
EXPECT_STREQ("ParosTimin", gep.aktualisallapot());
} END
#endif // ELKESZULT > 1
#if ELKESZULT > 1
/// Kipróbálja az egyik pédakonfigot
TEST(ParosTrimin, fajbolkonfig1) {
Allapotgep gep;
ASSERT_NO_THROW(gep.konfigural("paros.txt"));
EXPECT_STREQ("ParosTimin", gep.aktualisallapot());
Bazis demo[] = {Timin, Citozin, Guanin, Adenin, Timin};
EXPECT_EQ(true, gep.feldolgoz(demo, 5));
gep.alaphelyzet();
EXPECT_STREQ("ParosTimin", gep.aktualisallapot());
EXPECT_EQ(true, gep.elfogad());
EXPECT_EQ(false, gep.feldolgoz(demo, 4));
} END
#endif
#if ELKESZULT > 2
/// Kipróbálja az másik pédakonfigot
TEST(Implikacio: AA->CC, fajbolkonfig2) {
Allapotgep gep;
ASSERT_NO_THROW(gep.konfigural("implikacio.txt"));
EXPECT_STREQ("Alap", gep.aktualisallapot());
Bazis demo[] = {Adenin, Adenin, Timin, Citozin, Adenin, Citozin, Citozin, Guanin};
EXPECT_EQ(true, gep.feldolgoz(demo, 8));
gep.alaphelyzet();
gep.atmenet(Citozin);
EXPECT_STREQ("C1", gep.aktualisallapot());
gep.atmenet(Adenin);
gep.atmenet(Timin);
EXPECT_STREQ("A1", gep.aktualisallapot());
Bazis test[] = {Citozin, Citozin, Timin, Adenin, Guanin, Citozin};
gep.feldolgoz(test, 6);
EXPECT_STREQ("C2", gep.aktualisallapot());
} END
#endif
/// Itt a vége
if (ELKESZULT < 3)
ADD_FAILURE() << "\nNem futott minden testeset!" << std::endl;
GTEND(std::cerr); // Csak C(J)PORTA működéséhez kell
return 0;
}
#ifndef GTEST_LITE_H
#define GTEST_LITE_H
/**
* \file gtest_lite.h (v3/2019)
*
* Google gtest keretrendszerhez hasonló rendszer.
* Sz.I. 2015., 2016., 2017. (_Has_X)
* Sz.I. 2018 (template), ENDM, ENDMsg, nullptr_t
* Sz.I. 2019 singleton
* Sz.I. 2021 ASSERT.., STRCASE...
*
* A tesztelés legalapvetőbb funkcióit támogató függvények és makrók.
* Nem szálbiztos megvalósítás.
*
*
* Szabadon felhasználható, bővíthető.
*
* Használati példa:
* Teszteljük az f(x)=2*x függvényt:
* int f(int x) { return 2*x; }
*
* int main() {
* TEST(TeszEsetNeve, TesztNeve)
* EXPECT_EQ(0, f(0));
* EXPECT_EQ(4, f(2)) << "A függvény hibás eredményt adott" << std::endl;
* ...
* END
* ...
* // Fatális hiba esetén a teszteset nem fut tovább. Ezek az ASSERT... makrók.
* // Nem lehet a kiírásukhoz további üzenetet fűzni. PL:
* TEST(TeszEsetNeve, TesztNeve)
* ASSERT_NO_THROW(f(0)); // itt nem lehet << "duma"
* EXPECT_EQ(4, f(2)) << "A függvény hibás eredményt adott" << std::endl;
* ...
* END
* ...
*
* A működés részleteinek megértése szorgalmi feladat.
*/
#include <iostream>
#include <cassert>
#include <cmath>
#include <cstring>
#include <limits>
#include <cstdlib>
#include <string>
#include <fstream>
#ifdef MEMTRACE
#include "memtrace.h"
#endif
// Két makró az egyes tesztek elé és mögé:
// A két makró a kapcsos zárójelekkel egy új blokkot hoz létre, amiben
// a nevek lokálisak, így elkerülhető a névütközés.
/// Teszt kezdete. A makró paraméterezése hasonlít a gtest
/// paraméterezéséhez. Így az itt elkészített testek könnyen átemelhetők
/// a gtest keretrendszerbe.
/// @param C - teszteset neve (csak a gtest kompatibilitás miatt van külön neve az eseteknek)
/// @param N - teszt neve
#define TEST(C, N) do { gtest_lite::test.begin(#C"."#N);
/// Teszteset vége.
#define END gtest_lite::test.end(); } while (false);
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
#define ENDM gtest_lite::test.end(true); } while (false);
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
/// Ha hiba van kiírja az üzenetet.
#define ENDMsg(t) gtest_lite::test.end(true) << t << std::endl; } while (false);
// Eredmények vizsgálatát segítő makrók.
// A paraméterek és a funkciók a gtest keretrendszerrel megegyeznek.
/// Sikeres teszt makrója
#define SUCCEED() gtest_lite::test.expect(true, __FILE__, __LINE__, "SUCCEED()", true)
/// Sikertelen teszt fatális hiba makrója
#define FAIL() gtest_lite::test.expect(false, __FILE__, __LINE__, "FAIL()", true)
/// Sikertelen teszt makrója
#define ADD_FAILURE() gtest_lite::test.expect(false, __FILE__, __LINE__, "ADD_FAILURE()", true)
/// Azonosságot elváró makró
#define EXPECT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_EQ(" #expected ", " #actual ")" )
/// Eltérést elváró makró
#define EXPECT_NE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::ne, __FILE__, __LINE__, "EXPECT_NE(" #expected ", " #actual ")", "etalon" )
/// Kisebb, vagy egyenlő relációt elváró makró
#define EXPECT_LE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::le, __FILE__, __LINE__, "EXPECT_LE(" #expected ", " #actual ")", "etalon" )
/// Kisebb, mint relációt elváró makró
#define EXPECT_LT(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::lt, __FILE__, __LINE__, "EXPECT_LT(" #expected ", " #actual ")", "etalon" )
/// Nagyobb, vagy egyenlő relációt elváró makró
#define EXPECT_GE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::ge, __FILE__, __LINE__, "EXPECT_GE(" #expected ", " #actual ")", "etalon" )
/// Nagyobb, mint relációt elváró makró
#define EXPECT_GT(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::gt, __FILE__, __LINE__, "EXPECT_GT(" #expected ", " #actual ")", "etalon" )
/// Igaz értéket elváró makró
#define EXPECT_TRUE(actual) gtest_lite::EXPECT_(true, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_TRUE(" #actual ")" )
/// Hamis értéket elváró makró
#define EXPECT_FALSE(actual) gtest_lite::EXPECT_(false, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_FALSE(" #actual ")" )
/// Valós számok azonosságát elváró makró
#define EXPECT_FLOAT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::almostEQ, __FILE__, __LINE__, "EXPECT_FLOAT_EQ(" #expected ", " #actual ")" )
/// Valós számok azonosságát elváró makró
#define EXPECT_DOUBLE_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::almostEQ, __FILE__, __LINE__, "EXPECT_DOUBLE_EQ(" #expected ", " #actual ")" )
/// C stringek (const char *) azonosságát tesztelő makró
#define EXPECT_STREQ(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::eqstr, __FILE__, __LINE__, "EXPECT_STREQ(" #expected ", " #actual ")" )
/// C stringek (const char *) eltéréset tesztelő makró
#define EXPECT_STRNE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestr, __FILE__, __LINE__, "EXPECT_STRNE(" #expected ", " #actual ")", "etalon" )
/// C stringek (const char *) azonosságát tesztelő makró (kisbetű/nagybetű azonos)
#define EXPECT_STRCASEEQ(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::eqstrcase, __FILE__, __LINE__, "EXPECT_STRCASEEQ(" #expected ", " #actual ")" )
/// C stringek (const char *) eltéréset tesztelő makró (kisbetű/nagybetű azonos)
#define EXPECT_STRCASENE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestrcase, __FILE__, __LINE__, "EXPECT_STRCASENE(" #expected ", " #actual ")", "etalon" )
/// Kivételt várunk
#define EXPECT_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \
catch (exception_type) { gtest_lite::test.tmp = true; } \
catch (...) { } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.")
/// Kivételt várunk
#define EXPECT_ANY_THROW(statement) try { gtest_lite::test.tmp = false; statement; } \
catch (...) { gtest_lite::test.tmp = true; } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott kivetelt.")
/// Nem várunk kivételt
#define EXPECT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
EXPECTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Nem várunk kivételt
#define ASSERT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
ASSERTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Kivételt várunk és továbbdobjuk -- ilyen nincs a gtest-ben
#define EXPECT_THROW_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \
catch (exception_type) { gtest_lite::test.tmp = true; throw; } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.")
/// Környezeti változóhoz hasonlít -- ilyen nincs a gtest-ben
#define EXPECT_ENVEQ(expected, actual) gtest_lite::EXPECTSTR(std::getenv(expected), actual, gtest_lite::eqstr, __FILE__, __LINE__, "EXPECT_ENVEQ(" #expected ", " #actual ")" )
/// Környezeti változóhoz hasonlít -- ilyen nincs a gtest-ben (kisbetű/nagybetű azonos)
#define EXPECT_ENVCASEEQ(expected, actual) gtest_lite::EXPECTSTR(std::getenv(expected), actual, gtest_lite::eqstrcase, __FILE__, __LINE__, "EXPECT_ENVCASEEQ(" #expected ", " #actual ")" )
////--------------------------------------------------------------------------------------------
/// ASSERT típusú ellenőrzések. CSak 1-2 van megvalósítva. Nem ostream& -val térnek vissza !!!
/// Kivételt várunk
/// Azonosságot elváró makró
#define ASSERT_EQ(expected, actual) gtest_lite::ASSERT_(expected, actual, gtest_lite::eq, "ASSER_EQ")
/// Nem várunk kivételt
#define ASSERT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
ASSERTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Segédmakró egy adattag, vagy tagfüggvény létezésének tesztelésére futási időben
/// Ötlet:
/// https://cpptalk.wordpress.com/2009/09/12/substitution-failure-is-not-an-error-2
/// Használat:
/// CREATE_Has_(size)
/// ... if (Has_size<std::string>::member)...
#define CREATE_Has_(X) \
template<typename T> struct _Has_##X { \
struct Fallback { int X; }; \
struct Derived : T, Fallback {}; \
template<typename C, C> struct ChT; \
template<typename D> static char (&f(ChT<int Fallback::*, &D::X>*))[1]; \
template<typename D> static char (&f(...))[2]; \
static bool const member = sizeof(f<Derived>(0)) == 2; \
};
/// Segédfüggvény egy publikus adattag, vagy tagfüggvény létezésének tesztelésére
/// fordítási időben
inline void hasMember(...) {}
/// Segédsablon típuskonverzió futás közbeni ellenőrzésere
template <typename F, typename T>
struct _Is_Types {
template<typename D> static char (&f(D))[1];
template<typename D> static char (&f(...))[2];
static bool const convertable = sizeof(f<T>(F())) == 1;
};
/// -----------------------------------
/// Belső megvalósításhoz tartozó makrók, és osztályok.
/// Nem célszerű közvetlenül használni, vagy módosítani
/// -----------------------------------
/// EXPECTTHROW: kivételkezelés
#define EXPECTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
<< "** Az utasitas " << (act) \
<< "\n** Azt vartuk, hogy " << (exp) << std::endl
#define ASSERTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
<< "** Az utasitas " << (act) \
<< "\n** Azt vartuk, hogy " << (exp) << std::endl; if (!gtest_lite::test.status) { gtest_lite::test.end(); break; }
#define ASSERT_(expected, actual, fn, op) EXPECT_(expected, actual, fn, __FILE__, __LINE__, #op "(" #expected ", " #actual ")" ); \
if (!gtest_lite::test.status) { gtest_lite::test.end(); break; }
#ifdef CPORTA
#define GTINIT(is) \
int magic; \
is >> magic;
#else
#define GTINIT(IS)
#endif // CPORTA
#ifdef CPORTA
#define GTEND(os) \
os << magic << (gtest_lite::test.fail() ? " NO" : " OK?") << std::endl;
#else
#define GTEND(os)
#endif // CPORTA
/// gtest_lite: a keretrendszer függvényinek és objektumainak névtere
namespace gtest_lite {
/// Tesztek állapotát tároló osztály.
/// Egyetlen egy statikus példány keletkezik, aminek a
/// destruktora a futás végén hívódik meg.
struct Test {
int sum; ///< tesztek számlálója
int failed; ///< hibás tesztek
int ablocks; ///< allokált blokkok száma
bool status; ///< éppen futó teszt státusza
bool tmp; ///< temp a kivételkezeléshez;
std::string name; ///< éppen futó teszt neve
std::fstream null; ///< nyelő, ha nem kell kiírni semmit
static Test& getTest() {
static Test instance;///< egyedüli (singleton) példány
return instance;
}
private: /// singleton minta miatt
Test() :sum(0), failed(0), status(false), null("/dev/null") {}
Test(const Test&);
void operator=(const Test&);
public:
/// Teszt kezdete
void begin(const char *n) {
name = n; status = true;
#ifdef MEMTRACE
ablocks = memtrace::allocated_blocks();
#endif
#ifndef CPORTA
std::cerr << "\n---> " << name << std::endl;
#endif // CPORTA
++sum;
}
/// Teszt vége
std::ostream& end(bool memchk = false) {
#ifdef MEMTRACE
if (memchk && ablocks != memtrace::allocated_blocks()) {
status = false;
return std::cerr << "** Lehet, hogy nem szabaditott fel minden memoriat! **" << std::endl;
}
#endif
#ifdef CPORTA
if (!status)
#endif // CPORTA
std::cerr << (status ? " SIKERES" : "** HIBAS ****") << "\t" << name << " <---" << std::endl;
if (!status)
return std::cerr;
else
return null;
}
bool fail() { return failed; }
bool astatus() { return status; }
/// Eredményt adminisztráló tagfüggvény True a jó eset.
std::ostream& expect(bool st, const char *file, int line, const char *expr, bool pr = false) {
if (!st) {
++failed;
status = false;
}
if (!st || pr) {
std::string str(file);
size_t i = str.rfind("\\");
if (i == std::string::npos) i = str.rfind("/");
if (i == std::string::npos) i = 0; else i++;
return std::cerr << "\n**** " << &file[i] << "(" << line << "): " << expr << " ****" << std::endl;
}
return null;
}
/// Destruktor
~Test() {
#ifdef CPORTA
if (failed)
#endif // CPORTA
std::cerr << "\n==== TESZT VEGE ==== HIBAS/OSSZES: " << failed << "/" << sum << std::endl;
}
};
/// A statikus referencia minden fordítási egységben keletkezik, de
/// mindegyik egyetlen példányra fog hivatkozni a singleton minta miatt
static Test& test = Test::getTest();
/// általános sablon a várt értékhez.
template <typename T1, typename T2>
std::ostream& EXPECT_(T1 exp, T2 act, bool (*pred)(T1, T2), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << std::boolalpha << exp
<< "\n** " << rhs << ": " << std::boolalpha << act << std::endl;
}
/// pointerre specializált sablon a várt értékhez.
template <typename T1, typename T2>
std::ostream& EXPECT_(T1* exp, T2* act, bool (*pred)(T1*, T2*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (void*) exp
<< "\n** " << rhs << ": " << (void*) act << std::endl;
}
#if __cplusplus >= 201103L
/// nullptr-re specializált sablon a várt értékhez.
template <typename T1>
std::ostream& EXPECT_(T1* exp, std::nullptr_t act, bool (*pred)(T1*, std::nullptr_t), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (void*) exp
<< "\n** " << rhs << ": " << (void*) act << std::endl;
}
#endif
/// stringek összehasonlításához.
/// azért nem spec. mert a sima EQ-ra másként kell működnie.
inline
std::ostream& EXPECTSTR(const char *exp, const char *act, bool (*pred)(const char*, const char*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (exp == NULL ? "NULL pointer" : std::string("\"") + exp + std::string("\""))
<< "\n** " << rhs << ": " << (act == NULL ? "NULL pointer" : std::string("\"") + act + std::string("\"")) << std::endl;
}
/// segéd sablonok a relációkhoz.
/// azért nem STL (algorithm), mert csak a függvény lehet, hogy menjen a deduckció
template <typename T1, typename T2>
bool eq(T1 a, T2 b) { return a == b; }
inline
bool eqstr(const char *a, const char *b) {
if (a != NULL && b != NULL)
return strcmp(a, b) == 0;
return false;
}
inline
bool eqstrcase(const char *a, const char *b) {
if (a != NULL && b != NULL) {
while (toupper(*a) == toupper(*b) && *a != '\0') {
a++;
b++;
}
return *a == *b;
}
return false;
}
template <typename T1, typename T2>
bool ne(T1 a, T2 b) { return a != b; }
inline
bool nestr(const char *a, const char *b) {
if (a != NULL && b != NULL)
return strcmp(a, b) != 0;
return false;
}
template <typename T1, typename T2>
bool le(T1 a, T2 b) { return a <= b; }
template <typename T1, typename T2>
bool lt(T1 a, T2 b) { return a < b; }
template <typename T1, typename T2>
bool ge(T1 a, T2 b) { return a >= b; }
template <typename T1, typename T2>
bool gt(T1 a, T2 b) { return a > b; }
/// Segédsablon valós számok összehasonlításához
/// Nem bombabiztos, de nekünk most jó lesz
/// Elméleti hátér:
/// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
template <typename T>
bool almostEQ(T a, T b) {
// eps: ha a relatív, vagy abszolút hiba ettől kisebb, akkor elfogadjuk
T eps = 10 * std::numeric_limits<T>::epsilon(); // 10-szer a legkisebb érték
if (a == b) return true;
if (fabs(a - b) < eps)
return true;
double aa = fabs(a);
double ba = fabs(b);
if (aa < ba) {
aa = ba;
ba = fabs(a);
}
return (aa - ba) < aa * eps;
}
} // namespace gtest_lite
#endif // GTEST_LITE_H
7
I Alap
I A1
H A2
H C'1
I C'2
I C1
I C2
TG A 0 0 0 C 0
0 TG A 0 0 C 0
0 0 TGA C 0 0 0
0 0 A TG C 0 0
0 0 0 0 ACGT 0 0
0 A 0 0 0 TG C
0 0 0 0 0 0 ACGT
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.
VS 2012: Szeberényi Imre, 2015.,
mem_dump: 2016.
meset felszabaditaskor: 2018.
typo: 2019.
*********************************/
/*definialni kell, ha nem paracssorbol allitjuk be (-DMEMTRACE) */
/*#define MEMTRACE */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#ifdef MEMTRACE
#define FROM_MEMTRACE_CPP
#include "memtrace.h"
#define FMALLOC 0
#define FCALLOC 1
#define FREALLOC 2
#define FFREE 3
#define FNEW 4
#define FDELETE 5
#define FNEWARR 6
#define FDELETEARR 7
#define COMP(a,d) (((a)<=3 && (d)<=3) || ((d)==(a)+1))
#define PU(p) ((char*)p+CANARY_LEN) // mem pointerbol user poi
#define P(pu) ((char*)pu-CANARY_LEN) // user pointerbol mem poi
#define XSTR(s) STR(s)
#define STR(s) #s
/*******************************************************************/
/* Segedfuggvenyek es egyebek */
/*******************************************************************/
START_NAMESPACE
static FILE *fperror;
#ifdef MEMTRACE_TO_MEMORY
static const unsigned int CANARY_LEN = 64;
#else
static const unsigned int CANARY_LEN = 0;
#endif
static const unsigned char canary_byte1 = 'k';
static const unsigned char canary_byte2 = 'K';
static unsigned char random_byte;
typedef enum {FALSE,TRUE} BOOL;
static const char * pretty[] = {"malloc(", "calloc(", "realloc(", "free(",
"new", "delete", "new[]", "delete[]"};
static const char * basename(const char * s) {
const char *s1,*s2;
s1 = strrchr(s,'/');
if(s1==NULL) s1 = s; else s1++;
s2 = strrchr(s1, '\\');
if(s2==NULL) s2 = s1; else s2++;
return s2;
}
static char *StrCpy(char ** to, const char * from) {
if(from == NULL) {
*to = NULL;
} else {
*to = (char*)malloc(strlen(from)+1);
if(*to) strcpy(*to, from);
}
return *to;
}
static void *canary_malloc(size_t size, unsigned char data) {
char *p = (char *)malloc(size+2*CANARY_LEN);
if (p) {
memset(p, canary_byte1, CANARY_LEN);
memset(p+CANARY_LEN, data, size);
memset(p+CANARY_LEN+size, canary_byte2, CANARY_LEN);
}
return p;
}
static int chk_canary(void *p, size_t size) {
unsigned char *pc = (unsigned char*)p;
unsigned int i;
for (i = 0; i < CANARY_LEN; i++)
if (pc[i] != canary_byte1)
return -1;
pc += CANARY_LEN+size;
for (i = 0; i < CANARY_LEN; i++)
if (pc[i] != canary_byte2)
return 1;
return 0;
}
typedef struct {
int f; /* allocator func */
int line;
char * par_txt;
char * file;
} call_t;
static call_t pack(int f, const char * par_txt, int line, const char * file) {
call_t ret;
ret.f = f;
ret.line = line;
StrCpy(&ret.par_txt, par_txt);
StrCpy(&ret.file, file);
return ret;
}
static void print_call(const char * msg, call_t call) {
if(msg) fprintf(fperror, "%s", msg);
fprintf(fperror, "%s", pretty[call.f]);
fprintf(fperror, "%s", call.par_txt ? call.par_txt : "?");
if (call.f <= 3) fprintf(fperror, ")");
fprintf(fperror," @ %s:", call.file ? basename(call.file) : "?");
fprintf(fperror,"%d\n",call.line ? call.line : 0);
}
/* memoriateruletet dump */
static void dump_memory(void const *mem, size_t size, size_t can_len, FILE* fp) {
unsigned char const *m=(unsigned char const *) mem;
unsigned int s, o;
if (can_len > 0)
fprintf(fp, "Dump (addr: %p kanari hossz: %d):\n", m+can_len, (int)can_len);
else
fprintf(fp, "Dump: (addr: %p) \n", m);
size += 2*can_len;
for (s = 0; s < (size+15)/16; s++) {
fprintf(fp, "%04x:%c ", s*16, s*16 < can_len || s*16 >= size-can_len ? ' ' : '*');
for (o = 0; o < 16; o++) {
if (o == 8) fprintf(fp, " ");
if (s*16+o < size)
fprintf(fp, "%02x ", m[s*16+o]);
else
fprintf(fp, " ");
}
fprintf(fp, " ");
for (o = 0; o < 16; o++) {
if (s*16+o < size)
fprintf(fp, "%c", isprint(m[s*16+o]) ? m[s*16+o] : '.');
else
fprintf(fp, " ");
}
fprintf(fp, "\n");
}
}
void mem_dump(void const *mem, size_t size, FILE* fp) {
dump_memory(mem, size, 0, fp);
}
static BOOL dying;
static void die(const char * msg, void * p, size_t size, call_t * a, call_t * d) {
#ifdef MEMTRACE_ERRFILE
fperror = fopen(XSTR(MEMTRACE_ERRFILE), "w");
#endif
fprintf(fperror,"%s\n",msg);
if (p) {
fprintf(fperror, "\tPointer:\t%p", PU(p));
if (size) fprintf(fperror," (%d byte)", (int)size);
fprintf(fperror,"\n");
}
if (a) print_call("\tFoglalas:\t", *a);
if (d) print_call("\tFelszabaditas:\t", *d);
if (p) dump_memory(p, size, CANARY_LEN, fperror);
dying = TRUE;
exit(120);
}
static void initialize();
END_NAMESPACE
/*******************************************************************/
/* MEMTRACE_TO_MEMORY */
/*******************************************************************/
#ifdef MEMTRACE_TO_MEMORY
START_NAMESPACE
typedef struct _registry_item {
void * p; /* mem pointer*/
size_t size; /* size*/
call_t call;
struct _registry_item * next;
} registry_item;
static registry_item registry; /*sentinel*/
static void print_registry_item(registry_item * p) {
if (p) {
print_registry_item(p->next);
fprintf(fperror, "\t%p%5d byte ",p->p, (int)p->size);
print_call(NULL, p->call);
if(p->call.par_txt) free(p->call.par_txt);
if(p->call.file) free(p->call.file);
free(p);
}
}
/* ha nincs hiba, akkor 0-val tér vissza */
int mem_check(void) {
initialize();
if(dying) return 2; /* címzési hiba */
if(registry.next) {
/*szivarog*/
#ifdef MEMTRACE_ERRFILE
fperror = fopen(XSTR(MEMTRACE_ERRFILE), "w");
#endif
fprintf(fperror, "Szivargas:\n");
print_registry_item(registry.next);
registry.next = NULL;
return 1; /* memória fogyás */
}
return 0;
}
END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY*/
/*******************************************************************/
/* MEMTRACE_TO_FILE */
/*******************************************************************/
#ifdef MEMTRACE_TO_FILE
START_NAMESPACE
static FILE * trace_file;
END_NAMESPACE
#endif
/*******************************************************************/
/* register/unregister */
/*******************************************************************/
START_NAMESPACE
static int allocated_blks;
int allocated_blocks() { return allocated_blks; }
static BOOL register_memory(void * p, size_t size, call_t call) {
initialize();
allocated_blks++;
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file, "%p\t%d\t%s%s", PU(p), (int)size, pretty[call.f], call.par_txt ? call.par_txt : "?");
if (call.f <= 3) fprintf(trace_file, ")");
fprintf(trace_file, "\t%d\t%s\n", call.line, call.file ? call.file : "?");
fflush(trace_file);
#endif
#ifdef MEMTRACE_TO_MEMORY
{/*C-blokk*/
registry_item * n = (registry_item*)malloc(sizeof(registry_item));
if(n==NULL) return FALSE;
n->p = p;
n->size = size;
n->call = call;
n->next = registry.next;
registry.next = n;
}/*C-blokk*/
#endif
return TRUE;
}
#ifdef MEMTRACE_TO_MEMORY
static registry_item *find_registry_item(void * p) {
registry_item *n = &registry;
for(; n->next && n->next->p != p ; n=n->next);
return n;
}
#endif
static void unregister_memory(void * p, call_t call) {
initialize();
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file, "%p\t%d\t%s%s", PU(p), -1, pretty[call.f], call.par_txt ? call.par_txt : "?");
if (call.f <= 3) fprintf(trace_file, ")");
fprintf(trace_file,"\t%d\t%s\n",call.line, call.file ? call.file : "?");
fflush(trace_file);
#endif
#ifdef MEMTRACE_TO_MEMORY
{ /*C-blokk*/
registry_item * n = find_registry_item(p);
if(n->next) {
allocated_blks--;
registry_item * r = n->next;
n->next = r->next;
if(COMP(r->call.f,call.f)) {
int chk = chk_canary(r->p, r->size);
if (chk < 0)
die("Blokk elott serult a memoria:", r->p,r->size,&r->call,&call);
if (chk > 0)
die("Blokk utan serult a memoria", r->p,r->size,&r->call,&call);
/*rendben van minden*/
if(call.par_txt) free(call.par_txt);
if(r->call.par_txt) free(r->call.par_txt);
if(call.file) free(call.file);
if(r->call.file) free(r->call.file);
memset(PU(r->p), 'f', r->size);
PU(r->p)[r->size-1] = 0;
free(r);
} else {
/*hibas felszabaditas*/
die("Hibas felszabaditas:",r->p,r->size,&r->call,&call);
}
} else {
die("Nem letezo, vagy mar felszabaditott adat felszabaditasa:", p, 0,NULL,&call);
}
} /*C-blokk*/
#endif
}
END_NAMESPACE
/*******************************************************************/
/* C-stílusú memóriakezelés */
/*******************************************************************/
#ifdef MEMTRACE_C
START_NAMESPACE
void * traced_malloc(size_t size, const char * par_txt, int line, const char * file) {
void * p;
initialize();
p = canary_malloc(size, random_byte);
if (p) {
if(!register_memory(p,size,pack(FMALLOC,par_txt,line,file))) {
free(p);
return NULL;
}
return PU(p);
}
return NULL;
}
void * traced_calloc(size_t count, size_t size, const char * par_txt, int line, const char * file) {
void * p;
initialize();
size *= count;
p = canary_malloc(size, 0);
if(p) {
if(!register_memory(p,size,pack(FCALLOC,par_txt,line,file))) {
free(p);
return NULL;
}
return PU(p);
}
return NULL;
}
void traced_free(void * pu, const char * par_txt, int line, const char * file) {
initialize();
if(pu) {
unregister_memory(P(pu), pack(FFREE,par_txt,line,file));
free(P(pu));
} else {
/*free(NULL) eset*/
#ifdef MEMTRACE_TO_FILE
fprintf(trace_file,"%s\t%d\t%10s\t","NULL",-1,pretty[FFREE]);
fprintf(trace_file,"%d\t%s\n",line,file ? file : "?");
fflush(trace_file);
#endif
#ifndef ALLOW_FREE_NULL
{/*C-blokk*/
call_t call;
call = pack(FFREE,par_txt,line,file);
die("free(NULL) hivasa:",NULL,0,NULL,&call);
}/*C-blokk*/
#endif
}
}
void * traced_realloc(void * old, size_t size, const char * par_txt, int line, const char * file) {
void * p;
size_t oldsize = 0;
registry_item * n;
initialize();
#ifdef MEMTRACE_TO_MEMORY
n = find_registry_item(P(old));
if (n) oldsize = n->next->size;
p = canary_malloc(size, random_byte);
#else
p = realloc(old, size);
#endif
if (p) {
/*Ha sikerult a foglalas, regisztraljuk*/
register_memory(p,size,pack(FREALLOC, par_txt, line,file));
if (old) {
#ifdef MEMTRACE_TO_MEMORY
int cpsize = 2*CANARY_LEN;
if (oldsize < size) cpsize += oldsize;
else cpsize += size;
memcpy(p, P(old), cpsize);
#endif
unregister_memory(P(old), pack(FREALLOC, par_txt, line, file));
#ifdef MEMTRACE_TO_MEMORY
free P(old);
#endif
}
return PU(p);
} else {
return NULL;
}
}
END_NAMESPACE
#endif/*MEMTRACE_C*/
/*******************************************************************/
/* C++-stílusú memóriakezelés */
/*******************************************************************/
#ifdef MEMTRACE_CPP
START_NAMESPACE
std::new_handler _new_handler;
void _set_new_handler(std::new_handler h) {
initialize();
_new_handler = h;
}
static call_t delete_call;
static BOOL delete_called;
void set_delete_call(int line, const char * file) {
initialize();
delete_call=pack(0,"",line,file); /*func értéke lényegtelen, majd felülírjuk*/
delete_called = TRUE;
}
void * traced_new(size_t size, int line, const char * file, int func) {
initialize();
for (;;) {
void * p = canary_malloc(size, random_byte);
if(p) {
register_memory(p,size,pack(func,"",line,file));
return PU(p);
}
if (_new_handler == 0)
throw std::bad_alloc();
_new_handler();
}
}
void traced_delete(void * pu, int func) {
initialize();
if(pu) {
/*kiolvasom call-t, ha van*/
memtrace::call_t call = delete_called ? (delete_call.f=func, delete_call) : pack(func,NULL,0,NULL);
memtrace::unregister_memory(P(pu),call);
free(P(pu));
}
delete_called=FALSE;
}
END_NAMESPACE
void * operator new(size_t size, int line, const char * file) THROW_BADALLOC {
return memtrace::traced_new(size,line,file,FNEW);
}
void * operator new[](size_t size, int line, const char * file) THROW_BADALLOC {
return memtrace::traced_new(size,line,file,FNEWARR);
}
void * operator new(size_t size) THROW_BADALLOC {
return memtrace::traced_new(size,0,NULL,FNEW);
}
void * operator new[](size_t size) THROW_BADALLOC {
return memtrace::traced_new(size,0,NULL,FNEWARR);
}
void operator delete(void * p) THROW_NOTHING {
memtrace::traced_delete(p,FDELETE);
}
void operator delete[](void * p) THROW_NOTHING {
memtrace::traced_delete(p,FDELETEARR);
}
/* Visual C++ 2012 miatt kell, mert háklis, hogy nincs megfelelő delete, bár senki sem használja */
void operator delete(void * p, int, const char *) THROW_NOTHING {
memtrace::traced_delete(p,FDELETE);
}
void operator delete[](void * p, int, const char *) THROW_NOTHING {
memtrace::traced_delete(p,FDELETE);
}
#endif/*MEMTRACE_CPP*/
/*******************************************************************/
/* initialize */
/*******************************************************************/
START_NAMESPACE
static void initialize() {
static BOOL first = TRUE;
if(first) {
fperror = stderr;
random_byte = (unsigned char)time(NULL);
first = FALSE;
dying = FALSE;
#ifdef MEMTRACE_TO_MEMORY
registry.next = NULL;
#if !defined(USE_ATEXIT_OBJECT) && defined(MEMTRACE_AUTO)
atexit((void(*)(void))mem_check);
#endif
#endif
#ifdef MEMTRACE_TO_FILE
trace_file = fopen("memtrace.dump","w");
#endif
#ifdef MEMTRACE_CPP
_new_handler = NULL;
delete_called = FALSE;
delete_call = pack(0,NULL,0,NULL);
#endif
}
}
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
int atexit_class::counter = 0;
int atexit_class::err = 0;
#endif
END_NAMESPACE
#endif
/*********************************
Memoriaszivargas-detektor
Keszitette: Peregi Tamas, BME IIT, 2011
petamas@iit.bme.hu
Kanari: Szeberenyi Imre, 2013.,
VS 2012: Szeberényi Imre, 2015.,
mem_dump: 2016.
inclue-ok: 2017., 2018. 2019.
*********************************/
#ifndef MEMTRACE_H
#define MEMTRACE_H
#if defined(MEMTRACE)
/*ha definiálva van, akkor a hibakat ebbe a fajlba írja, egyébkent stderr-re*/
/*#define MEMTRACE_ERRFILE MEMTRACE.ERR*/
/*ha definialva van, akkor futas kozben lancolt listat epit. Javasolt a hasznalata*/
#define MEMTRACE_TO_MEMORY
/*ha definialva van, akkor futas kozben fajlba irja a foglalasokat*/
/*ekkor nincs ellenorzes, csak naplozas*/
/*#define MEMTRACE_TO_FILE*/
/*ha definialva van, akkor a megallaskor automatikus riport keszul */
#define MEMTRACE_AUTO
/*ha definialva van, akkor malloc()/calloc()/realloc()/free() kovetve lesz*/
#define MEMTRACE_C
#ifdef MEMTRACE_C
/*ha definialva van, akkor free(NULL) nem okoz hibat*/
#define ALLOW_FREE_NULL
#endif
#ifdef __cplusplus
/*ha definialva van, akkor new/delete/new[]/delete[] kovetve lesz*/
#define MEMTRACE_CPP
#endif
#if defined(__cplusplus) && defined(MEMTRACE_TO_MEMORY)
/*ha definialva van, akkor atexit helyett objektumot hasznal*/
/*ajanlott bekapcsolni*/
#define USE_ATEXIT_OBJECT
#endif
/******************************************/
/* INNEN NE MODOSITSD */
/******************************************/
#ifdef NO_MEMTRACE_TO_FILE
#undef MEMTRACE_TO_FILE
#endif
#ifdef NO_MEMTRACE_TO_MEMORY
#undef MEMTRACE_TO_MEMORY
#endif
#ifndef MEMTRACE_AUTO
#undef USE_ATEXIT_OBJECT
#endif
#ifdef __cplusplus
#define START_NAMESPACE namespace memtrace {
#define END_NAMESPACE } /*namespace*/
#define TRACEC(func) memtrace::func
#include <new>
#else
#define START_NAMESPACE
#define END_NAMESPACE
#define TRACEC(func) func
#endif
// THROW deklaráció változatai
#if defined(_MSC_VER)
// VS rosszul kezeli az __cplusplus makrot
#if _MSC_VER < 1900
// * nem biztos, hogy jó így *
#define THROW_BADALLOC
#define THROW_NOTHING
#else
// C++11 vagy újabb
#define THROW_BADALLOC noexcept(false)
#define THROW_NOTHING noexcept
#endif
#else
#if __cplusplus < 201103L
// C++2003 vagy régebbi
#define THROW_BADALLOC throw (std::bad_alloc)
#define THROW_NOTHING throw ()
#else
// C++11 vagy újabb
#define THROW_BADALLOC noexcept(false)
#define THROW_NOTHING noexcept
#endif
#endif
START_NAMESPACE
int allocated_blocks();
END_NAMESPACE
#if defined(MEMTRACE_TO_MEMORY)
START_NAMESPACE
int mem_check(void);
END_NAMESPACE
#endif
#if defined(MEMTRACE_TO_MEMORY) && defined(USE_ATEXIT_OBJECT)
#include <cstdio>
START_NAMESPACE
class atexit_class {
private:
static int counter;
static int err;
public:
atexit_class() {
#if defined(CPORTA) && !defined(CPORTA_NOSETBUF)
if (counter == 0) {
setbuf(stdout, 0);
setbuf(stderr, 0);
}
#endif
counter++;
}
int check() {
if(--counter == 0)
err = mem_check();
return err;
}
~atexit_class() {
check();
}
};
static atexit_class atexit_obj;
END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY && USE_ATEXIT_OBJECT*/
/*Innentol csak a "normal" include eseten kell, kulonben osszezavarja a mukodest*/
#ifndef FROM_MEMTRACE_CPP
#include <stdlib.h>
#ifdef __cplusplus
#include <iostream>
/* ide gyűjtjük a nemtrace-vel összeakadó headereket, hogy előbb legyenek */
#include <fstream> // VS 2013 headerjében van deleted definició
#include <sstream>
#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <functional>
#include <memory>
#include <iomanip>
#include <locale>
#include <typeinfo>
#include <ostream>
#include <stdexcept>
#endif
#ifdef MEMTRACE_CPP
namespace std {
typedef void (*new_handler)();
}
#endif
#ifdef MEMTRACE_C
START_NAMESPACE
#undef malloc
#define malloc(size) TRACEC(traced_malloc)(size,#size,__LINE__,__FILE__)
void * traced_malloc(size_t size, const char *size_txt, int line, const char * file);
#undef calloc
#define calloc(count,size) TRACEC(traced_calloc)(count, size, #count","#size,__LINE__,__FILE__)
void * traced_calloc(size_t count, size_t size, const char *size_txt, int line, const char * file);
#undef free
#define free(p) TRACEC(traced_free)(p, #p,__LINE__,__FILE__)
void traced_free(void * p, const char *size_txt, int line, const char * file);
#undef realloc
#define realloc(old,size) TRACEC(traced_realloc)(old,size,#size,__LINE__,__FILE__)
void * traced_realloc(void * old, size_t size, const char *size_txt, int line, const char * file);
void mem_dump(void const *mem, size_t size, FILE* fp = stdout);
END_NAMESPACE
#endif/*MEMTRACE_C*/
#ifdef MEMTRACE_CPP
START_NAMESPACE
#undef set_new_handler
#define set_new_handler(f) TRACEC(_set_new_handler)(f)
void _set_new_handler(std::new_handler h);
void set_delete_call(int line, const char * file);
END_NAMESPACE
void * operator new(size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new[](size_t size, int line, const char * file) THROW_BADALLOC;
void * operator new(size_t size) THROW_BADALLOC;
void * operator new[](size_t size) THROW_BADALLOC;
void operator delete(void * p) THROW_NOTHING;
void operator delete[](void * p) THROW_NOTHING;
/* Visual C++ 2012 miatt kell, mert háklis, hogy nincs megfelelő delete, bár senki sem használja */
void operator delete(void *p, int, const char *) THROW_NOTHING;
void operator delete[](void *p, int, const char *) THROW_NOTHING;
#define new new(__LINE__, __FILE__)
#define delete memtrace::set_delete_call(__LINE__, __FILE__),delete
#ifdef CPORTA
#define system(...) // system(__VA_ARGS__)
#endif
#endif /*MEMTRACE_CPP*/
#endif /*FROM_MEMTRACE_CPP*/
#else
#pragma message ( "MEMTRACE NOT DEFINED" )
#endif /*MEMTRACE*/
#endif /*MEMTRACE_H*/
2
I ParosTimin
H ParatlanTimin
ACG T
T ACG
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment