From 8f3ba4e8708cb72be19dacc2af4f601ee5fea292 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 19 Sep 2011 13:31:29 +0200 Subject: do not pollute namespace in the headers with using (Closes: #500198) --- methods/bzip2.cc | 6 +++--- methods/connect.cc | 14 +++++++------- methods/connect.h | 2 +- methods/copy.cc | 2 +- methods/file.cc | 6 +++--- methods/ftp.h | 10 +++++----- methods/gpgv.cc | 3 +++ methods/gzip.cc | 2 +- methods/http.h | 18 +++++++++--------- methods/rred.cc | 4 ++-- methods/rsh.cc | 18 +++++++++--------- methods/rsh.h | 10 +++++----- 12 files changed, 49 insertions(+), 46 deletions(-) (limited to 'methods') diff --git a/methods/bzip2.cc b/methods/bzip2.cc index eff83bda7..ad5db6cfb 100644 --- a/methods/bzip2.cc +++ b/methods/bzip2.cc @@ -47,9 +47,9 @@ class Bzip2Method : public pkgAcqMethod bool Bzip2Method::Fetch(FetchItem *Itm) { URI Get = Itm->Uri; - string Path = Get.Host + Get.Path; // To account for relative paths + std::string Path = Get.Host + Get.Path; // To account for relative paths - string GzPathOption = "Dir::bin::"+string(Prog); + std::string GzPathOption = "Dir::bin::" + std::string(Prog); FetchResult Res; Res.Filename = Itm->DestFile; @@ -78,7 +78,7 @@ bool Bzip2Method::Fetch(FetchItem *Itm) SetCloseExec(STDOUT_FILENO,false); const char *Args[3]; - string Tmp = _config->Find(GzPathOption,Prog); + std::string Tmp = _config->Find(GzPathOption,Prog); Args[0] = Tmp.c_str(); Args[1] = "-d"; Args[2] = 0; diff --git a/methods/connect.cc b/methods/connect.cc index 16fb6e793..ba2264faa 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -35,13 +35,13 @@ #include /*}}}*/ -static string LastHost; +static std::string LastHost; static int LastPort = 0; static struct addrinfo *LastHostAddr = 0; static struct addrinfo *LastUsed = 0; // Set of IP/hostnames that we timed out before or couldn't resolve -static std::set bad_addr; +static std::set bad_addr; // RotateDNS - Select a new server from a DNS rotation /*{{{*/ // --------------------------------------------------------------------- @@ -58,7 +58,7 @@ void RotateDNS() // DoConnect - Attempt a connect operation /*{{{*/ // --------------------------------------------------------------------- /* This helper function attempts a connection to a single address. */ -static bool DoConnect(struct addrinfo *Addr,string Host, +static bool DoConnect(struct addrinfo *Addr,std::string Host, unsigned long TimeOut,int &Fd,pkgAcqMethod *Owner) { // Show a status indicator @@ -73,7 +73,7 @@ static bool DoConnect(struct addrinfo *Addr,string Host, Owner->Status(_("Connecting to %s (%s)"),Host.c_str(),Name); // if that addr did timeout before, we do not try it again - if(bad_addr.find(string(Name)) != bad_addr.end()) + if(bad_addr.find(std::string(Name)) != bad_addr.end()) return false; /* If this is an IP rotation store the IP we are using.. If something goes @@ -100,7 +100,7 @@ static bool DoConnect(struct addrinfo *Addr,string Host, /* This implements a timeout for connect by opening the connection nonblocking */ if (WaitFd(Fd,true,TimeOut) == false) { - bad_addr.insert(bad_addr.begin(), string(Name)); + bad_addr.insert(bad_addr.begin(), std::string(Name)); Owner->SetFailReason("Timeout"); return _error->Error(_("Could not connect to %s:%s (%s), " "connection timed out"),Host.c_str(),Service,Name); @@ -119,7 +119,7 @@ static bool DoConnect(struct addrinfo *Addr,string Host, Owner->SetFailReason("ConnectionRefused"); else if (errno == ETIMEDOUT) Owner->SetFailReason("ConnectionTimedOut"); - bad_addr.insert(bad_addr.begin(), string(Name)); + bad_addr.insert(bad_addr.begin(), std::string(Name)); return _error->Errno("connect",_("Could not connect to %s:%s (%s)."),Host.c_str(), Service,Name); } @@ -130,7 +130,7 @@ static bool DoConnect(struct addrinfo *Addr,string Host, // Connect - Connect to a server /*{{{*/ // --------------------------------------------------------------------- /* Performs a connection to the server */ -bool Connect(string Host,int Port,const char *Service,int DefPort,int &Fd, +bool Connect(std::string Host,int Port,const char *Service,int DefPort,int &Fd, unsigned long TimeOut,pkgAcqMethod *Owner) { if (_error->PendingError() == true) diff --git a/methods/connect.h b/methods/connect.h index 6f208e31d..0afa00919 100644 --- a/methods/connect.h +++ b/methods/connect.h @@ -13,7 +13,7 @@ #include #include -bool Connect(string To,int Port,const char *Service,int DefPort, +bool Connect(std::string To,int Port,const char *Service,int DefPort, int &Fd,unsigned long TimeOut,pkgAcqMethod *Owner); void RotateDNS(); diff --git a/methods/copy.cc b/methods/copy.cc index 94467e054..fe2918469 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -37,7 +37,7 @@ class CopyMethod : public pkgAcqMethod bool CopyMethod::Fetch(FetchItem *Itm) { URI Get = Itm->Uri; - string File = Get.Path; + std::string File = Get.Path; // Stat the file and send a start message struct stat Buf; diff --git a/methods/file.cc b/methods/file.cc index 9fc4cd76c..d58652e6e 100644 --- a/methods/file.cc +++ b/methods/file.cc @@ -40,7 +40,7 @@ class FileMethod : public pkgAcqMethod bool FileMethod::Fetch(FetchItem *Itm) { URI Get = Itm->Uri; - string File = Get.Path; + std::string File = Get.Path; FetchResult Res; if (Get.Host.empty() == false) return _error->Error(_("Invalid URI, local URIS must not start with //")); @@ -58,10 +58,10 @@ bool FileMethod::Fetch(FetchItem *Itm) } // See if we can compute a file without a .gz exentsion - string::size_type Pos = File.rfind(".gz"); + std::string::size_type Pos = File.rfind(".gz"); if (Pos + 3 == File.length()) { - File = string(File,0,Pos); + File = std::string(File,0,Pos); if (stat(File.c_str(),&Buf) == 0) { FetchResult AltRes; diff --git a/methods/ftp.h b/methods/ftp.h index b4913ca57..7088e0954 100644 --- a/methods/ftp.h +++ b/methods/ftp.h @@ -33,7 +33,7 @@ class FTPConn socklen_t ServerAddrLen; // Private helper functions - bool ReadLine(string &Text); + bool ReadLine(std::string &Text); bool Login(); bool CreateDataFd(); bool Finalize(); @@ -43,8 +43,8 @@ class FTPConn bool Comp(URI Other) {return Other.Host == ServerName.Host && Other.Port == ServerName.Port && Other.User == ServerName.User && Other.Password == ServerName.Password; }; // Raw connection IO - bool ReadResp(unsigned int &Ret,string &Text); - bool WriteMsg(unsigned int &Ret,string &Text,const char *Fmt,...); + bool ReadResp(unsigned int &Ret,std::string &Text); + bool WriteMsg(unsigned int &Ret,std::string &Text,const char *Fmt,...); // Connection control bool Open(pkgAcqMethod *Owner); @@ -65,11 +65,11 @@ class FTPConn class FtpMethod : public pkgAcqMethod { virtual bool Fetch(FetchItem *Itm); - virtual bool Configuration(string Message); + virtual bool Configuration(std::string Message); FTPConn *Server; - static string FailFile; + static std::string FailFile; static int FailFd; static time_t FailTime; static void SigTerm(int); diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 251bcbc90..67cbd36a2 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -17,6 +17,9 @@ #include +using std::string; +using std::vector; + #define GNUPGPREFIX "[GNUPG:]" #define GNUPGBADSIG "[GNUPG:] BADSIG" #define GNUPGNOPUBKEY "[GNUPG:] NO_PUBKEY" diff --git a/methods/gzip.cc b/methods/gzip.cc index f4bb052e2..a51497948 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -41,7 +41,7 @@ class GzipMethod : public pkgAcqMethod bool GzipMethod::Fetch(FetchItem *Itm) { URI Get = Itm->Uri; - string Path = Get.Host + Get.Path; // To account for relative paths + std::string Path = Get.Host + Get.Path; // To account for relative paths FetchResult Res; Res.Filename = Itm->DestFile; diff --git a/methods/http.h b/methods/http.h index c47d7184a..08823d1b1 100644 --- a/methods/http.h +++ b/methods/http.h @@ -26,7 +26,7 @@ class CircleBuf unsigned long long Size; unsigned long long InP; unsigned long long OutP; - string OutQueue; + std::string OutQueue; unsigned long long StrPos; unsigned long long MaxGet; struct timeval Start; @@ -60,11 +60,11 @@ class CircleBuf // Read data in bool Read(int Fd); - bool Read(string Data); + bool Read(std::string Data); // Write data out bool Write(int Fd); - bool WriteTillEl(string &Data,bool Single = false); + bool WriteTillEl(std::string &Data,bool Single = false); // Control the write limit void Limit(long long Max) {if (Max == -1) MaxGet = 0-1; else MaxGet = OutP + Max;} @@ -99,7 +99,7 @@ struct ServerState enum {Chunked,Stream,Closes} Encoding; enum {Header, Data} State; bool Persistent; - string Location; + std::string Location; // This is a Persistent attribute of the server itself. bool Pipeline; @@ -112,7 +112,7 @@ struct ServerState int ServerFd; URI ServerName; - bool HeaderLine(string Line); + bool HeaderLine(std::string Line); bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;}; void Reset() {Major = 0; Minor = 0; Result = 0; Size = 0; StartPos = 0; Encoding = Closes; time(&Date); ServerFd = -1; @@ -167,10 +167,10 @@ class HttpMethod : public pkgAcqMethod /** \brief Try to AutoDetect the proxy */ bool AutoDetectProxy(); - virtual bool Configuration(string Message); + virtual bool Configuration(std::string Message); // In the event of a fatal signal this file will be closed and timestamped. - static string FailFile; + static std::string FailFile; static int FailFd; static time_t FailTime; static void SigTerm(int); @@ -178,8 +178,8 @@ class HttpMethod : public pkgAcqMethod protected: virtual bool Fetch(FetchItem *); - string NextURI; - string AutoDetectProxyCmd; + std::string NextURI; + std::string AutoDetectProxyCmd; public: friend struct ServerState; diff --git a/methods/rred.cc b/methods/rred.cc index bc941ed04..2a05acce1 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -472,7 +472,7 @@ bool RredMethod::Fetch(FetchItem *Itm) /*{{{*/ { Debug = _config->FindB("Debug::pkgAcquire::RRed", false); URI Get = Itm->Uri; - string Path = Get.Host + Get.Path; // To account for relative paths + std::string Path = Get.Host + Get.Path; // To account for relative paths FetchResult Res; Res.Filename = Itm->DestFile; @@ -525,7 +525,7 @@ bool RredMethod::Fetch(FetchItem *Itm) /*{{{*/ and use the access time from the "old" file */ struct stat BufBase, BufPatch; if (stat(Path.c_str(),&BufBase) != 0 || - stat(string(Path+".ed").c_str(),&BufPatch) != 0) + stat(std::string(Path+".ed").c_str(),&BufPatch) != 0) return _error->Errno("stat",_("Failed to stat")); struct utimbuf TimeBuf; diff --git a/methods/rsh.cc b/methods/rsh.cc index c95a4d3eb..add128c49 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -32,7 +32,7 @@ const char *Prog; unsigned long TimeOut = 120; Configuration::Item const *RshOptions = 0; time_t RSHMethod::FailTime = 0; -string RSHMethod::FailFile; +std::string RSHMethod::FailFile; int RSHMethod::FailFd = -1; // RSHConn::RSHConn - Constructor /*{{{*/ @@ -85,7 +85,7 @@ bool RSHConn::Open() // RSHConn::Connect - Fire up rsh and connect /*{{{*/ // --------------------------------------------------------------------- /* */ -bool RSHConn::Connect(string Host, string User) +bool RSHConn::Connect(std::string Host, std::string User) { // Create the pipes int Pipes[4] = {-1,-1,-1,-1}; @@ -154,7 +154,7 @@ bool RSHConn::Connect(string Host, string User) // RSHConn::ReadLine - Very simple buffered read with timeout /*{{{*/ // --------------------------------------------------------------------- /* */ -bool RSHConn::ReadLine(string &Text) +bool RSHConn::ReadLine(std::string &Text) { if (Process == -1 || ReadFd == -1) return false; @@ -174,7 +174,7 @@ bool RSHConn::ReadLine(string &Text) continue; I++; - Text = string(Buffer,I); + Text = std::string(Buffer,I); memmove(Buffer,Buffer+I,Len - I); Len -= I; return true; @@ -205,7 +205,7 @@ bool RSHConn::ReadLine(string &Text) // --------------------------------------------------------------------- /* The remote sync flag appends a || echo which will insert blank line once the command completes. */ -bool RSHConn::WriteMsg(string &Text,bool Sync,const char *Fmt,...) +bool RSHConn::WriteMsg(std::string &Text,bool Sync,const char *Fmt,...) { va_list args; va_start(args,Fmt); @@ -254,7 +254,7 @@ bool RSHConn::WriteMsg(string &Text,bool Sync,const char *Fmt,...) bool RSHConn::Size(const char *Path,unsigned long long &Size) { // Query the size - string Msg; + std::string Msg; Size = 0; if (WriteMsg(Msg,true,"find %s -follow -printf '%%s\\n'",Path) == false) @@ -276,7 +276,7 @@ bool RSHConn::ModTime(const char *Path, time_t &Time) { Time = time(&Time); // Query the mod time - string Msg; + std::string Msg; if (WriteMsg(Msg,true,"TZ=UTC find %s -follow -printf '%%TY%%Tm%%Td%%TH%%TM%%TS\\n'",Path) == false) return false; @@ -309,7 +309,7 @@ bool RSHConn::Get(const char *Path,FileFd &To,unsigned long long Resume, } // FIXME: Detect file-not openable type errors. - string Jnk; + std::string Jnk; if (WriteMsg(Jnk,false,"dd if=%s bs=2048 skip=%u", Path, Resume / 2048) == false) return false; @@ -366,7 +366,7 @@ RSHMethod::RSHMethod() : pkgAcqMethod("1.0",SendConfig) /*}}}*/ // RSHMethod::Configuration - Handle a configuration message /*{{{*/ // --------------------------------------------------------------------- -bool RSHMethod::Configuration(string Message) +bool RSHMethod::Configuration(std::string Message) { char ProgStr[100]; diff --git a/methods/rsh.h b/methods/rsh.h index c81396b5f..7bebe29a0 100644 --- a/methods/rsh.h +++ b/methods/rsh.h @@ -25,15 +25,15 @@ class RSHConn URI ServerName; // Private helper functions - bool ReadLine(string &Text); + bool ReadLine(std::string &Text); public: pid_t Process; // Raw connection IO - bool WriteMsg(string &Text,bool Sync,const char *Fmt,...); - bool Connect(string Host, string User); + bool WriteMsg(std::string &Text,bool Sync,const char *Fmt,...); + bool Connect(std::string Host, std::string User); bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;}; // Connection control @@ -53,11 +53,11 @@ class RSHConn class RSHMethod : public pkgAcqMethod { virtual bool Fetch(FetchItem *Itm); - virtual bool Configuration(string Message); + virtual bool Configuration(std::string Message); RSHConn *Server; - static string FailFile; + static std::string FailFile; static int FailFd; static time_t FailTime; static void SigTerm(int); -- cgit v1.2.3 From 472ff00ef2e48383805d281c6364ec27839e3f4d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 19 Sep 2011 19:14:19 +0200 Subject: use forward declaration in headers if possible instead of includes --- methods/bzip2.cc | 1 + methods/cdrom.cc | 1 + methods/connect.cc | 2 ++ methods/connect.h | 3 ++- methods/copy.cc | 1 + methods/file.cc | 1 + methods/ftp.cc | 1 + methods/ftp.h | 4 ++++ methods/gpgv.cc | 1 + methods/http.cc | 6 ++++++ methods/http.h | 7 +++++-- methods/https.cc | 1 + methods/https.h | 3 ++- methods/mirror.cc | 3 ++- methods/mirror.h | 25 +++++++++++++------------ methods/rred.cc | 1 + methods/rsh.cc | 3 +++ methods/rsh.h | 8 +++++--- 18 files changed, 52 insertions(+), 20 deletions(-) (limited to 'methods') diff --git a/methods/bzip2.cc b/methods/bzip2.cc index ad5db6cfb..8e7e46557 100644 --- a/methods/bzip2.cc +++ b/methods/bzip2.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include #include diff --git a/methods/cdrom.cc b/methods/cdrom.cc index bc115d259..e7114b168 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/methods/connect.cc b/methods/connect.cc index ba2264faa..9a092a43c 100644 --- a/methods/connect.cc +++ b/methods/connect.cc @@ -15,6 +15,8 @@ #include #include +#include +#include #include #include diff --git a/methods/connect.h b/methods/connect.h index 0afa00919..bbe1bb35d 100644 --- a/methods/connect.h +++ b/methods/connect.h @@ -11,7 +11,8 @@ #define CONNECT_H #include -#include + +class pkgAcqMethod; bool Connect(std::string To,int Port,const char *Service,int DefPort, int &Fd,unsigned long TimeOut,pkgAcqMethod *Owner); diff --git a/methods/copy.cc b/methods/copy.cc index fe2918469..f8d58e479 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/methods/file.cc b/methods/file.cc index d58652e6e..5025c996d 100644 --- a/methods/file.cc +++ b/methods/file.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/methods/ftp.cc b/methods/ftp.cc index 861647aea..2ca0ac6f7 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/methods/ftp.h b/methods/ftp.h index 7088e0954..2634f0732 100644 --- a/methods/ftp.h +++ b/methods/ftp.h @@ -10,6 +10,10 @@ #ifndef APT_FTP_H #define APT_FTP_H +#include + +#include + class FTPConn { char Buffer[1024*10]; diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 67cbd36a2..2b2aba017 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/methods/http.cc b/methods/http.cc index b60cfeb9e..0d81c73ed 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -288,6 +289,11 @@ void CircleBuf::Stats() clog << "Got " << InP << " in " << Diff << " at " << InP/Diff << endl;*/ } /*}}}*/ +CircleBuf::~CircleBuf() +{ + delete [] Buf; + delete Hash; +} // ServerState::ServerState - Constructor /*{{{*/ // --------------------------------------------------------------------- diff --git a/methods/http.h b/methods/http.h index 08823d1b1..c73d4df5c 100644 --- a/methods/http.h +++ b/methods/http.h @@ -13,12 +13,15 @@ #define MAXLEN 360 -#include +#include + +#include using std::cout; using std::endl; class HttpMethod; +class Hashes; class CircleBuf { @@ -80,7 +83,7 @@ class CircleBuf void Stats(); CircleBuf(unsigned long long Size); - ~CircleBuf() {delete [] Buf; delete Hash;}; + ~CircleBuf(); }; struct ServerState diff --git a/methods/https.cc b/methods/https.cc index 06a0e285a..e70206dfb 100644 --- a/methods/https.cc +++ b/methods/https.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/methods/https.h b/methods/https.h index 3f0c416b6..b7adeb880 100644 --- a/methods/https.h +++ b/methods/https.h @@ -20,7 +20,7 @@ using std::cout; using std::endl; class HttpsMethod; - +class FileFd; class HttpsMethod : public pkgAcqMethod { @@ -45,6 +45,7 @@ class HttpsMethod : public pkgAcqMethod }; }; +#include URI Proxy; #endif diff --git a/methods/mirror.cc b/methods/mirror.cc index 61a7f12fd..3d5983efa 100644 --- a/methods/mirror.cc +++ b/methods/mirror.cc @@ -18,7 +18,8 @@ #include #include #include - +#include +#include #include #include diff --git a/methods/mirror.h b/methods/mirror.h index 97d18144a..81e531e21 100644 --- a/methods/mirror.h +++ b/methods/mirror.h @@ -11,8 +11,9 @@ #ifndef APT_MIRROR_H #define APT_MIRROR_H - #include +#include +#include using std::cout; using std::cerr; @@ -24,29 +25,29 @@ class MirrorMethod : public HttpMethod { FetchResult Res; // we simply transform between BaseUri and Mirror - string BaseUri; // the original mirror://... url - string Mirror; // the selected mirror uri (http://...) - vector AllMirrors; // all available mirrors - string MirrorFile; // the file that contains the list of mirrors + std::string BaseUri; // the original mirror://... url + std::string Mirror; // the selected mirror uri (http://...) + std::vector AllMirrors; // all available mirrors + std::string MirrorFile; // the file that contains the list of mirrors bool DownloadedMirrorFile; // already downloaded this session - string Dist; // the target distrubtion (e.g. sid, oneiric) + std::string Dist; // the target distrubtion (e.g. sid, oneiric) bool Debug; protected: - bool DownloadMirrorFile(string uri); - bool RandomizeMirrorFile(string file); - string GetMirrorFileName(string uri); + bool DownloadMirrorFile(std::string uri); + bool RandomizeMirrorFile(std::string file); + std::string GetMirrorFileName(std::string uri); bool InitMirrors(); bool TryNextMirror(); void CurrentQueueUriToMirror(); - bool Clean(string dir); + bool Clean(std::string dir); // we need to overwrite those to transform the url back - virtual void Fail(string Why, bool Transient = false); + virtual void Fail(std::string Why, bool Transient = false); virtual void URIStart(FetchResult &Res); virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0); - virtual bool Configuration(string Message); + virtual bool Configuration(std::string Message); public: MirrorMethod(); diff --git a/methods/rred.cc b/methods/rred.cc index 2a05acce1..ef00fcaa3 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/methods/rsh.cc b/methods/rsh.cc index add128c49..da9777fc4 100644 --- a/methods/rsh.cc +++ b/methods/rsh.cc @@ -14,6 +14,9 @@ #include #include +#include +#include +#include #include #include diff --git a/methods/rsh.h b/methods/rsh.h index 7bebe29a0..d7efa3f06 100644 --- a/methods/rsh.h +++ b/methods/rsh.h @@ -12,9 +12,9 @@ #include #include -#include -#include -#include + +class Hashes; +class FileFd; class RSHConn { @@ -50,6 +50,8 @@ class RSHConn ~RSHConn(); }; +#include + class RSHMethod : public pkgAcqMethod { virtual bool Fetch(FetchItem *Itm); -- cgit v1.2.3