mirror of https://github.com/lukechilds/komodo.git
Wladimir J. van der Laan
14 years ago
31 changed files with 14691 additions and 127 deletions
@ -0,0 +1,526 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#ifndef BITCOIN_DB_H |
|||
#define BITCOIN_DB_H |
|||
|
|||
#include "key.h" |
|||
|
|||
#include <map> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#include <db_cxx.h> |
|||
|
|||
class CTransaction; |
|||
class CTxIndex; |
|||
class CDiskBlockIndex; |
|||
class CDiskTxPos; |
|||
class COutPoint; |
|||
class CUser; |
|||
class CReview; |
|||
class CAddress; |
|||
class CWalletTx; |
|||
class CAccount; |
|||
class CAccountingEntry; |
|||
class CBlockLocator; |
|||
|
|||
extern std::map<std::string, std::string> mapAddressBook; |
|||
extern CCriticalSection cs_mapAddressBook; |
|||
extern std::vector<unsigned char> vchDefaultKey; |
|||
extern bool fClient; |
|||
extern int nBestHeight; |
|||
|
|||
|
|||
extern unsigned int nWalletDBUpdated; |
|||
extern DbEnv dbenv; |
|||
|
|||
|
|||
extern void DBFlush(bool fShutdown); |
|||
extern std::vector<unsigned char> GetKeyFromKeyPool(); |
|||
extern int64 GetOldestKeyPoolTime(); |
|||
|
|||
|
|||
|
|||
|
|||
class CDB |
|||
{ |
|||
protected: |
|||
Db* pdb; |
|||
std::string strFile; |
|||
std::vector<DbTxn*> vTxn; |
|||
bool fReadOnly; |
|||
|
|||
explicit CDB(const char* pszFile, const char* pszMode="r+"); |
|||
~CDB() { Close(); } |
|||
public: |
|||
void Close(); |
|||
private: |
|||
CDB(const CDB&); |
|||
void operator=(const CDB&); |
|||
|
|||
protected: |
|||
template<typename K, typename T> |
|||
bool Read(const K& key, T& value) |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
|
|||
// Key
|
|||
CDataStream ssKey(SER_DISK); |
|||
ssKey.reserve(1000); |
|||
ssKey << key; |
|||
Dbt datKey(&ssKey[0], ssKey.size()); |
|||
|
|||
// Read
|
|||
Dbt datValue; |
|||
datValue.set_flags(DB_DBT_MALLOC); |
|||
int ret = pdb->get(GetTxn(), &datKey, &datValue, 0); |
|||
memset(datKey.get_data(), 0, datKey.get_size()); |
|||
if (datValue.get_data() == NULL) |
|||
return false; |
|||
|
|||
// Unserialize value
|
|||
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK); |
|||
ssValue >> value; |
|||
|
|||
// Clear and free memory
|
|||
memset(datValue.get_data(), 0, datValue.get_size()); |
|||
free(datValue.get_data()); |
|||
return (ret == 0); |
|||
} |
|||
|
|||
template<typename K, typename T> |
|||
bool Write(const K& key, const T& value, bool fOverwrite=true) |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
if (fReadOnly) |
|||
assert(("Write called on database in read-only mode", false)); |
|||
|
|||
// Key
|
|||
CDataStream ssKey(SER_DISK); |
|||
ssKey.reserve(1000); |
|||
ssKey << key; |
|||
Dbt datKey(&ssKey[0], ssKey.size()); |
|||
|
|||
// Value
|
|||
CDataStream ssValue(SER_DISK); |
|||
ssValue.reserve(10000); |
|||
ssValue << value; |
|||
Dbt datValue(&ssValue[0], ssValue.size()); |
|||
|
|||
// Write
|
|||
int ret = pdb->put(GetTxn(), &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE)); |
|||
|
|||
// Clear memory in case it was a private key
|
|||
memset(datKey.get_data(), 0, datKey.get_size()); |
|||
memset(datValue.get_data(), 0, datValue.get_size()); |
|||
return (ret == 0); |
|||
} |
|||
|
|||
template<typename K> |
|||
bool Erase(const K& key) |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
if (fReadOnly) |
|||
assert(("Erase called on database in read-only mode", false)); |
|||
|
|||
// Key
|
|||
CDataStream ssKey(SER_DISK); |
|||
ssKey.reserve(1000); |
|||
ssKey << key; |
|||
Dbt datKey(&ssKey[0], ssKey.size()); |
|||
|
|||
// Erase
|
|||
int ret = pdb->del(GetTxn(), &datKey, 0); |
|||
|
|||
// Clear memory
|
|||
memset(datKey.get_data(), 0, datKey.get_size()); |
|||
return (ret == 0 || ret == DB_NOTFOUND); |
|||
} |
|||
|
|||
template<typename K> |
|||
bool Exists(const K& key) |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
|
|||
// Key
|
|||
CDataStream ssKey(SER_DISK); |
|||
ssKey.reserve(1000); |
|||
ssKey << key; |
|||
Dbt datKey(&ssKey[0], ssKey.size()); |
|||
|
|||
// Exists
|
|||
int ret = pdb->exists(GetTxn(), &datKey, 0); |
|||
|
|||
// Clear memory
|
|||
memset(datKey.get_data(), 0, datKey.get_size()); |
|||
return (ret == 0); |
|||
} |
|||
|
|||
Dbc* GetCursor() |
|||
{ |
|||
if (!pdb) |
|||
return NULL; |
|||
Dbc* pcursor = NULL; |
|||
int ret = pdb->cursor(NULL, &pcursor, 0); |
|||
if (ret != 0) |
|||
return NULL; |
|||
return pcursor; |
|||
} |
|||
|
|||
int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT) |
|||
{ |
|||
// Read at cursor
|
|||
Dbt datKey; |
|||
if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) |
|||
{ |
|||
datKey.set_data(&ssKey[0]); |
|||
datKey.set_size(ssKey.size()); |
|||
} |
|||
Dbt datValue; |
|||
if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) |
|||
{ |
|||
datValue.set_data(&ssValue[0]); |
|||
datValue.set_size(ssValue.size()); |
|||
} |
|||
datKey.set_flags(DB_DBT_MALLOC); |
|||
datValue.set_flags(DB_DBT_MALLOC); |
|||
int ret = pcursor->get(&datKey, &datValue, fFlags); |
|||
if (ret != 0) |
|||
return ret; |
|||
else if (datKey.get_data() == NULL || datValue.get_data() == NULL) |
|||
return 99999; |
|||
|
|||
// Convert to streams
|
|||
ssKey.SetType(SER_DISK); |
|||
ssKey.clear(); |
|||
ssKey.write((char*)datKey.get_data(), datKey.get_size()); |
|||
ssValue.SetType(SER_DISK); |
|||
ssValue.clear(); |
|||
ssValue.write((char*)datValue.get_data(), datValue.get_size()); |
|||
|
|||
// Clear and free memory
|
|||
memset(datKey.get_data(), 0, datKey.get_size()); |
|||
memset(datValue.get_data(), 0, datValue.get_size()); |
|||
free(datKey.get_data()); |
|||
free(datValue.get_data()); |
|||
return 0; |
|||
} |
|||
|
|||
DbTxn* GetTxn() |
|||
{ |
|||
if (!vTxn.empty()) |
|||
return vTxn.back(); |
|||
else |
|||
return NULL; |
|||
} |
|||
|
|||
public: |
|||
bool TxnBegin() |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
DbTxn* ptxn = NULL; |
|||
int ret = dbenv.txn_begin(GetTxn(), &ptxn, DB_TXN_NOSYNC); |
|||
if (!ptxn || ret != 0) |
|||
return false; |
|||
vTxn.push_back(ptxn); |
|||
return true; |
|||
} |
|||
|
|||
bool TxnCommit() |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
if (vTxn.empty()) |
|||
return false; |
|||
int ret = vTxn.back()->commit(0); |
|||
vTxn.pop_back(); |
|||
return (ret == 0); |
|||
} |
|||
|
|||
bool TxnAbort() |
|||
{ |
|||
if (!pdb) |
|||
return false; |
|||
if (vTxn.empty()) |
|||
return false; |
|||
int ret = vTxn.back()->abort(); |
|||
vTxn.pop_back(); |
|||
return (ret == 0); |
|||
} |
|||
|
|||
bool ReadVersion(int& nVersion) |
|||
{ |
|||
nVersion = 0; |
|||
return Read(std::string("version"), nVersion); |
|||
} |
|||
|
|||
bool WriteVersion(int nVersion) |
|||
{ |
|||
return Write(std::string("version"), nVersion); |
|||
} |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
class CTxDB : public CDB |
|||
{ |
|||
public: |
|||
CTxDB(const char* pszMode="r+") : CDB("blkindex.dat", pszMode) { } |
|||
private: |
|||
CTxDB(const CTxDB&); |
|||
void operator=(const CTxDB&); |
|||
public: |
|||
bool ReadTxIndex(uint256 hash, CTxIndex& txindex); |
|||
bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex); |
|||
bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight); |
|||
bool EraseTxIndex(const CTransaction& tx); |
|||
bool ContainsTx(uint256 hash); |
|||
bool ReadOwnerTxes(uint160 hash160, int nHeight, std::vector<CTransaction>& vtx); |
|||
bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex); |
|||
bool ReadDiskTx(uint256 hash, CTransaction& tx); |
|||
bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex); |
|||
bool ReadDiskTx(COutPoint outpoint, CTransaction& tx); |
|||
bool WriteBlockIndex(const CDiskBlockIndex& blockindex); |
|||
bool EraseBlockIndex(uint256 hash); |
|||
bool ReadHashBestChain(uint256& hashBestChain); |
|||
bool WriteHashBestChain(uint256 hashBestChain); |
|||
bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); |
|||
bool WriteBestInvalidWork(CBigNum bnBestInvalidWork); |
|||
bool LoadBlockIndex(); |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
class CAddrDB : public CDB |
|||
{ |
|||
public: |
|||
CAddrDB(const char* pszMode="r+") : CDB("addr.dat", pszMode) { } |
|||
private: |
|||
CAddrDB(const CAddrDB&); |
|||
void operator=(const CAddrDB&); |
|||
public: |
|||
bool WriteAddress(const CAddress& addr); |
|||
bool EraseAddress(const CAddress& addr); |
|||
bool LoadAddresses(); |
|||
}; |
|||
|
|||
bool LoadAddresses(); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
class CKeyPool |
|||
{ |
|||
public: |
|||
int64 nTime; |
|||
std::vector<unsigned char> vchPubKey; |
|||
|
|||
CKeyPool() |
|||
{ |
|||
nTime = GetTime(); |
|||
} |
|||
|
|||
CKeyPool(const std::vector<unsigned char>& vchPubKeyIn) |
|||
{ |
|||
nTime = GetTime(); |
|||
vchPubKey = vchPubKeyIn; |
|||
} |
|||
|
|||
IMPLEMENT_SERIALIZE |
|||
( |
|||
if (!(nType & SER_GETHASH)) |
|||
READWRITE(nVersion); |
|||
READWRITE(nTime); |
|||
READWRITE(vchPubKey); |
|||
) |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
class CWalletDB : public CDB |
|||
{ |
|||
public: |
|||
CWalletDB(const char* pszMode="r+") : CDB("wallet.dat", pszMode) |
|||
{ |
|||
} |
|||
private: |
|||
CWalletDB(const CWalletDB&); |
|||
void operator=(const CWalletDB&); |
|||
public: |
|||
bool ReadName(const std::string& strAddress, std::string& strName) |
|||
{ |
|||
strName = ""; |
|||
return Read(std::make_pair(std::string("name"), strAddress), strName); |
|||
} |
|||
|
|||
bool WriteName(const std::string& strAddress, const std::string& strName) |
|||
{ |
|||
CRITICAL_BLOCK(cs_mapAddressBook) |
|||
mapAddressBook[strAddress] = strName; |
|||
nWalletDBUpdated++; |
|||
return Write(std::make_pair(std::string("name"), strAddress), strName); |
|||
} |
|||
|
|||
bool EraseName(const std::string& strAddress) |
|||
{ |
|||
// This should only be used for sending addresses, never for receiving addresses,
|
|||
// receiving addresses must always have an address book entry if they're not change return.
|
|||
CRITICAL_BLOCK(cs_mapAddressBook) |
|||
mapAddressBook.erase(strAddress); |
|||
nWalletDBUpdated++; |
|||
return Erase(std::make_pair(std::string("name"), strAddress)); |
|||
} |
|||
|
|||
bool ReadTx(uint256 hash, CWalletTx& wtx) |
|||
{ |
|||
return Read(std::make_pair(std::string("tx"), hash), wtx); |
|||
} |
|||
|
|||
bool WriteTx(uint256 hash, const CWalletTx& wtx) |
|||
{ |
|||
nWalletDBUpdated++; |
|||
return Write(std::make_pair(std::string("tx"), hash), wtx); |
|||
} |
|||
|
|||
bool EraseTx(uint256 hash) |
|||
{ |
|||
nWalletDBUpdated++; |
|||
return Erase(std::make_pair(std::string("tx"), hash)); |
|||
} |
|||
|
|||
bool ReadKey(const std::vector<unsigned char>& vchPubKey, CPrivKey& vchPrivKey) |
|||
{ |
|||
vchPrivKey.clear(); |
|||
return Read(std::make_pair(std::string("key"), vchPubKey), vchPrivKey); |
|||
} |
|||
|
|||
bool WriteKey(const std::vector<unsigned char>& vchPubKey, const CPrivKey& vchPrivKey) |
|||
{ |
|||
nWalletDBUpdated++; |
|||
return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false); |
|||
} |
|||
|
|||
bool WriteBestBlock(const CBlockLocator& locator) |
|||
{ |
|||
nWalletDBUpdated++; |
|||
return Write(std::string("bestblock"), locator); |
|||
} |
|||
|
|||
bool ReadBestBlock(CBlockLocator& locator) |
|||
{ |
|||
return Read(std::string("bestblock"), locator); |
|||
} |
|||
|
|||
bool ReadDefaultKey(std::vector<unsigned char>& vchPubKey) |
|||
{ |
|||
vchPubKey.clear(); |
|||
return Read(std::string("defaultkey"), vchPubKey); |
|||
} |
|||
|
|||
bool WriteDefaultKey(const std::vector<unsigned char>& vchPubKey) |
|||
{ |
|||
vchDefaultKey = vchPubKey; |
|||
nWalletDBUpdated++; |
|||
return Write(std::string("defaultkey"), vchPubKey); |
|||
} |
|||
|
|||
template<typename T> |
|||
bool ReadSetting(const std::string& strKey, T& value) |
|||
{ |
|||
return Read(std::make_pair(std::string("setting"), strKey), value); |
|||
} |
|||
|
|||
template<typename T> |
|||
bool WriteSetting(const std::string& strKey, const T& value) |
|||
{ |
|||
nWalletDBUpdated++; |
|||
return Write(std::make_pair(std::string("setting"), strKey), value); |
|||
} |
|||
|
|||
bool ReadAccount(const std::string& strAccount, CAccount& account); |
|||
bool WriteAccount(const std::string& strAccount, const CAccount& account); |
|||
bool WriteAccountingEntry(const CAccountingEntry& acentry); |
|||
int64 GetAccountCreditDebit(const std::string& strAccount); |
|||
void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries); |
|||
|
|||
bool LoadWallet(); |
|||
protected: |
|||
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool); |
|||
void KeepKey(int64 nIndex); |
|||
static void ReturnKey(int64 nIndex); |
|||
friend class CReserveKey; |
|||
friend std::vector<unsigned char> GetKeyFromKeyPool(); |
|||
friend int64 GetOldestKeyPoolTime(); |
|||
}; |
|||
|
|||
bool LoadWallet(bool& fFirstRunRet); |
|||
void BackupWallet(const std::string& strDest); |
|||
|
|||
inline bool SetAddressBookName(const std::string& strAddress, const std::string& strName) |
|||
{ |
|||
return CWalletDB().WriteName(strAddress, strName); |
|||
} |
|||
|
|||
class CReserveKey |
|||
{ |
|||
protected: |
|||
int64 nIndex; |
|||
std::vector<unsigned char> vchPubKey; |
|||
public: |
|||
CReserveKey() |
|||
{ |
|||
nIndex = -1; |
|||
} |
|||
|
|||
~CReserveKey() |
|||
{ |
|||
if (!fShutdown) |
|||
ReturnKey(); |
|||
} |
|||
|
|||
std::vector<unsigned char> GetReservedKey() |
|||
{ |
|||
if (nIndex == -1) |
|||
{ |
|||
CKeyPool keypool; |
|||
CWalletDB().ReserveKeyFromKeyPool(nIndex, keypool); |
|||
vchPubKey = keypool.vchPubKey; |
|||
} |
|||
assert(!vchPubKey.empty()); |
|||
return vchPubKey; |
|||
} |
|||
|
|||
void KeepKey() |
|||
{ |
|||
if (nIndex != -1) |
|||
CWalletDB().KeepKey(nIndex); |
|||
nIndex = -1; |
|||
vchPubKey.clear(); |
|||
} |
|||
|
|||
void ReturnKey() |
|||
{ |
|||
if (nIndex != -1) |
|||
CWalletDB::ReturnKey(nIndex); |
|||
nIndex = -1; |
|||
vchPubKey.clear(); |
|||
} |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,147 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#ifdef _MSC_VER |
|||
#pragma warning(disable:4786) |
|||
#pragma warning(disable:4804) |
|||
#pragma warning(disable:4805) |
|||
#pragma warning(disable:4717) |
|||
#endif |
|||
#ifdef _WIN32_WINNT |
|||
#undef _WIN32_WINNT |
|||
#endif |
|||
#define _WIN32_WINNT 0x0500 |
|||
#ifdef _WIN32_IE |
|||
#undef _WIN32_IE |
|||
#endif |
|||
#define _WIN32_IE 0x0400 |
|||
#define WIN32_LEAN_AND_MEAN 1 |
|||
#define __STDC_LIMIT_MACROS // to enable UINT64_MAX from stdint.h
|
|||
#if (defined(__unix__) || defined(unix)) && !defined(USG) |
|||
#include <sys/param.h> // to get BSD define |
|||
#endif |
|||
#ifdef __WXMAC_OSX__ |
|||
#ifndef BSD |
|||
#define BSD 1 |
|||
#endif |
|||
#endif |
|||
#ifdef GUI |
|||
#include <wx/wx.h> |
|||
#include <wx/stdpaths.h> |
|||
#include <wx/snglinst.h> |
|||
#include <wx/utils.h> |
|||
#include <wx/clipbrd.h> |
|||
#include <wx/taskbar.h> |
|||
#endif |
|||
#include <openssl/buffer.h> |
|||
#include <openssl/ecdsa.h> |
|||
#include <openssl/evp.h> |
|||
#include <openssl/rand.h> |
|||
#include <openssl/sha.h> |
|||
#include <openssl/ripemd.h> |
|||
#include <db_cxx.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <time.h> |
|||
#include <math.h> |
|||
#include <limits.h> |
|||
#include <float.h> |
|||
#include <assert.h> |
|||
#include <memory> |
|||
#include <iostream> |
|||
#include <sstream> |
|||
#include <string> |
|||
#include <vector> |
|||
#include <list> |
|||
#include <deque> |
|||
#include <map> |
|||
#include <set> |
|||
#include <algorithm> |
|||
#include <numeric> |
|||
#include <boost/foreach.hpp> |
|||
#include <boost/lexical_cast.hpp> |
|||
#include <boost/tuple/tuple.hpp> |
|||
#include <boost/tuple/tuple_comparison.hpp> |
|||
#include <boost/tuple/tuple_io.hpp> |
|||
#include <boost/array.hpp> |
|||
#include <boost/bind.hpp> |
|||
#include <boost/function.hpp> |
|||
#include <boost/filesystem.hpp> |
|||
#include <boost/filesystem/fstream.hpp> |
|||
#include <boost/algorithm/string.hpp> |
|||
#include <boost/thread.hpp> |
|||
#include <boost/interprocess/sync/file_lock.hpp> |
|||
#include <boost/interprocess/sync/interprocess_mutex.hpp> |
|||
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> |
|||
#include <boost/date_time/gregorian/gregorian_types.hpp> |
|||
#include <boost/date_time/posix_time/posix_time_types.hpp> |
|||
#include <boost/config.hpp> |
|||
#include <boost/program_options/detail/config_file.hpp> |
|||
#include <boost/program_options/parsers.hpp> |
|||
|
|||
#ifdef __WXMSW__ |
|||
#include <windows.h> |
|||
#include <winsock2.h> |
|||
#include <mswsock.h> |
|||
#include <shlobj.h> |
|||
#include <shlwapi.h> |
|||
#include <io.h> |
|||
#include <process.h> |
|||
#include <malloc.h> |
|||
#else |
|||
#include <sys/time.h> |
|||
#include <sys/resource.h> |
|||
#include <sys/socket.h> |
|||
#include <sys/stat.h> |
|||
#include <arpa/inet.h> |
|||
#include <netdb.h> |
|||
#include <unistd.h> |
|||
#include <errno.h> |
|||
#include <net/if.h> |
|||
#include <ifaddrs.h> |
|||
#include <fcntl.h> |
|||
#include <signal.h> |
|||
#endif |
|||
#ifdef BSD |
|||
#include <netinet/in.h> |
|||
#endif |
|||
|
|||
|
|||
#pragma hdrstop |
|||
|
|||
#include "strlcpy.h" |
|||
#include "serialize.h" |
|||
#include "uint256.h" |
|||
#include "util.h" |
|||
#include "key.h" |
|||
#include "bignum.h" |
|||
#include "base58.h" |
|||
#include "script.h" |
|||
#include "db.h" |
|||
#include "net.h" |
|||
#include "irc.h" |
|||
#include "main.h" |
|||
#include "rpc.h" |
|||
#ifdef GUI |
|||
#include "uibase.h" |
|||
#include "ui.h" |
|||
#else |
|||
#include "noui.h" |
|||
#endif |
|||
#include "init.h" |
|||
|
|||
#ifdef GUI |
|||
#include "xpm/addressbook16.xpm" |
|||
#include "xpm/addressbook20.xpm" |
|||
#include "xpm/bitcoin16.xpm" |
|||
#include "xpm/bitcoin20.xpm" |
|||
#include "xpm/bitcoin32.xpm" |
|||
#include "xpm/bitcoin48.xpm" |
|||
#include "xpm/bitcoin80.xpm" |
|||
#include "xpm/check.xpm" |
|||
#include "xpm/send16.xpm" |
|||
#include "xpm/send16noshadow.xpm" |
|||
#include "xpm/send20.xpm" |
|||
#include "xpm/about.xpm" |
|||
#endif |
@ -0,0 +1,11 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#ifndef BITCOIN_INIT_H |
|||
#define BITCOIN_INIT_H |
|||
|
|||
void Shutdown(void* parg); |
|||
bool AppInit(int argc, char* argv[]); |
|||
bool AppInit2(int argc, char* argv[]); |
|||
|
|||
#endif |
@ -0,0 +1,13 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#ifndef BITCOIN_IRC_H |
|||
#define BITCOIN_IRC_H |
|||
|
|||
bool RecvLine(SOCKET hSocket, std::string& strLine); |
|||
void ThreadIRCSeed(void* parg); |
|||
|
|||
extern int nGotIRCAddresses; |
|||
extern bool fGotExternalIP; |
|||
|
|||
#endif |
@ -0,0 +1,67 @@ |
|||
// Copyright (c) 2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#ifndef BITCOIN_NOUI_H |
|||
#define BITCOIN_NOUI_H |
|||
|
|||
#include <string> |
|||
|
|||
typedef void wxWindow; |
|||
#define wxYES 0x00000002 |
|||
#define wxOK 0x00000004 |
|||
#define wxNO 0x00000008 |
|||
#define wxYES_NO (wxYES|wxNO) |
|||
#define wxCANCEL 0x00000010 |
|||
#define wxAPPLY 0x00000020 |
|||
#define wxCLOSE 0x00000040 |
|||
#define wxOK_DEFAULT 0x00000000 |
|||
#define wxYES_DEFAULT 0x00000000 |
|||
#define wxNO_DEFAULT 0x00000080 |
|||
#define wxCANCEL_DEFAULT 0x80000000 |
|||
#define wxICON_EXCLAMATION 0x00000100 |
|||
#define wxICON_HAND 0x00000200 |
|||
#define wxICON_WARNING wxICON_EXCLAMATION |
|||
#define wxICON_ERROR wxICON_HAND |
|||
#define wxICON_QUESTION 0x00000400 |
|||
#define wxICON_INFORMATION 0x00000800 |
|||
#define wxICON_STOP wxICON_HAND |
|||
#define wxICON_ASTERISK wxICON_INFORMATION |
|||
#define wxICON_MASK (0x00000100|0x00000200|0x00000400|0x00000800) |
|||
#define wxFORWARD 0x00001000 |
|||
#define wxBACKWARD 0x00002000 |
|||
#define wxRESET 0x00004000 |
|||
#define wxHELP 0x00008000 |
|||
#define wxMORE 0x00010000 |
|||
#define wxSETUP 0x00020000 |
|||
|
|||
inline int MyMessageBox(const std::string& message, const std::string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1) |
|||
{ |
|||
printf("%s: %s\n", caption.c_str(), message.c_str()); |
|||
fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); |
|||
return 4; |
|||
} |
|||
#define wxMessageBox MyMessageBox |
|||
|
|||
inline int ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1) |
|||
{ |
|||
return MyMessageBox(message, caption, style, parent, x, y); |
|||
} |
|||
|
|||
inline bool ThreadSafeAskFee(int64 nFeeRequired, const std::string& strCaption, wxWindow* parent) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
inline void CalledSetStatusBar(const std::string& strText, int nField) |
|||
{ |
|||
} |
|||
|
|||
inline void UIThreadCall(boost::function0<void> fn) |
|||
{ |
|||
} |
|||
|
|||
inline void MainFrameRepaint() |
|||
{ |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,6 @@ |
|||
// Copyright (c) 2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
void ThreadRPCServer(void* parg); |
|||
int CommandLineRPC(int argc, char *argv[]); |
@ -0,0 +1,718 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#ifndef H_BITCOIN_SCRIPT |
|||
#define H_BITCOIN_SCRIPT |
|||
|
|||
#include "base58.h" |
|||
|
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
class CTransaction; |
|||
|
|||
enum |
|||
{ |
|||
SIGHASH_ALL = 1, |
|||
SIGHASH_NONE = 2, |
|||
SIGHASH_SINGLE = 3, |
|||
SIGHASH_ANYONECANPAY = 0x80, |
|||
}; |
|||
|
|||
|
|||
|
|||
enum opcodetype |
|||
{ |
|||
// push value
|
|||
OP_0=0, |
|||
OP_FALSE=OP_0, |
|||
OP_PUSHDATA1=76, |
|||
OP_PUSHDATA2, |
|||
OP_PUSHDATA4, |
|||
OP_1NEGATE, |
|||
OP_RESERVED, |
|||
OP_1, |
|||
OP_TRUE=OP_1, |
|||
OP_2, |
|||
OP_3, |
|||
OP_4, |
|||
OP_5, |
|||
OP_6, |
|||
OP_7, |
|||
OP_8, |
|||
OP_9, |
|||
OP_10, |
|||
OP_11, |
|||
OP_12, |
|||
OP_13, |
|||
OP_14, |
|||
OP_15, |
|||
OP_16, |
|||
|
|||
// control
|
|||
OP_NOP, |
|||
OP_VER, |
|||
OP_IF, |
|||
OP_NOTIF, |
|||
OP_VERIF, |
|||
OP_VERNOTIF, |
|||
OP_ELSE, |
|||
OP_ENDIF, |
|||
OP_VERIFY, |
|||
OP_RETURN, |
|||
|
|||
// stack ops
|
|||
OP_TOALTSTACK, |
|||
OP_FROMALTSTACK, |
|||
OP_2DROP, |
|||
OP_2DUP, |
|||
OP_3DUP, |
|||
OP_2OVER, |
|||
OP_2ROT, |
|||
OP_2SWAP, |
|||
OP_IFDUP, |
|||
OP_DEPTH, |
|||
OP_DROP, |
|||
OP_DUP, |
|||
OP_NIP, |
|||
OP_OVER, |
|||
OP_PICK, |
|||
OP_ROLL, |
|||
OP_ROT, |
|||
OP_SWAP, |
|||
OP_TUCK, |
|||
|
|||
// splice ops
|
|||
OP_CAT, |
|||
OP_SUBSTR, |
|||
OP_LEFT, |
|||
OP_RIGHT, |
|||
OP_SIZE, |
|||
|
|||
// bit logic
|
|||
OP_INVERT, |
|||
OP_AND, |
|||
OP_OR, |
|||
OP_XOR, |
|||
OP_EQUAL, |
|||
OP_EQUALVERIFY, |
|||
OP_RESERVED1, |
|||
OP_RESERVED2, |
|||
|
|||
// numeric
|
|||
OP_1ADD, |
|||
OP_1SUB, |
|||
OP_2MUL, |
|||
OP_2DIV, |
|||
OP_NEGATE, |
|||
OP_ABS, |
|||
OP_NOT, |
|||
OP_0NOTEQUAL, |
|||
|
|||
OP_ADD, |
|||
OP_SUB, |
|||
OP_MUL, |
|||
OP_DIV, |
|||
OP_MOD, |
|||
OP_LSHIFT, |
|||
OP_RSHIFT, |
|||
|
|||
OP_BOOLAND, |
|||
OP_BOOLOR, |
|||
OP_NUMEQUAL, |
|||
OP_NUMEQUALVERIFY, |
|||
OP_NUMNOTEQUAL, |
|||
OP_LESSTHAN, |
|||
OP_GREATERTHAN, |
|||
OP_LESSTHANOREQUAL, |
|||
OP_GREATERTHANOREQUAL, |
|||
OP_MIN, |
|||
OP_MAX, |
|||
|
|||
OP_WITHIN, |
|||
|
|||
// crypto
|
|||
OP_RIPEMD160, |
|||
OP_SHA1, |
|||
OP_SHA256, |
|||
OP_HASH160, |
|||
OP_HASH256, |
|||
OP_CODESEPARATOR, |
|||
OP_CHECKSIG, |
|||
OP_CHECKSIGVERIFY, |
|||
OP_CHECKMULTISIG, |
|||
OP_CHECKMULTISIGVERIFY, |
|||
|
|||
// expansion
|
|||
OP_NOP1, |
|||
OP_NOP2, |
|||
OP_NOP3, |
|||
OP_NOP4, |
|||
OP_NOP5, |
|||
OP_NOP6, |
|||
OP_NOP7, |
|||
OP_NOP8, |
|||
OP_NOP9, |
|||
OP_NOP10, |
|||
|
|||
|
|||
|
|||
// template matching params
|
|||
OP_PUBKEYHASH = 0xfd, |
|||
OP_PUBKEY = 0xfe, |
|||
|
|||
OP_INVALIDOPCODE = 0xff, |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
inline const char* GetOpName(opcodetype opcode) |
|||
{ |
|||
switch (opcode) |
|||
{ |
|||
// push value
|
|||
case OP_0 : return "0"; |
|||
case OP_PUSHDATA1 : return "OP_PUSHDATA1"; |
|||
case OP_PUSHDATA2 : return "OP_PUSHDATA2"; |
|||
case OP_PUSHDATA4 : return "OP_PUSHDATA4"; |
|||
case OP_1NEGATE : return "-1"; |
|||
case OP_RESERVED : return "OP_RESERVED"; |
|||
case OP_1 : return "1"; |
|||
case OP_2 : return "2"; |
|||
case OP_3 : return "3"; |
|||
case OP_4 : return "4"; |
|||
case OP_5 : return "5"; |
|||
case OP_6 : return "6"; |
|||
case OP_7 : return "7"; |
|||
case OP_8 : return "8"; |
|||
case OP_9 : return "9"; |
|||
case OP_10 : return "10"; |
|||
case OP_11 : return "11"; |
|||
case OP_12 : return "12"; |
|||
case OP_13 : return "13"; |
|||
case OP_14 : return "14"; |
|||
case OP_15 : return "15"; |
|||
case OP_16 : return "16"; |
|||
|
|||
// control
|
|||
case OP_NOP : return "OP_NOP"; |
|||
case OP_VER : return "OP_VER"; |
|||
case OP_IF : return "OP_IF"; |
|||
case OP_NOTIF : return "OP_NOTIF"; |
|||
case OP_VERIF : return "OP_VERIF"; |
|||
case OP_VERNOTIF : return "OP_VERNOTIF"; |
|||
case OP_ELSE : return "OP_ELSE"; |
|||
case OP_ENDIF : return "OP_ENDIF"; |
|||
case OP_VERIFY : return "OP_VERIFY"; |
|||
case OP_RETURN : return "OP_RETURN"; |
|||
|
|||
// stack ops
|
|||
case OP_TOALTSTACK : return "OP_TOALTSTACK"; |
|||
case OP_FROMALTSTACK : return "OP_FROMALTSTACK"; |
|||
case OP_2DROP : return "OP_2DROP"; |
|||
case OP_2DUP : return "OP_2DUP"; |
|||
case OP_3DUP : return "OP_3DUP"; |
|||
case OP_2OVER : return "OP_2OVER"; |
|||
case OP_2ROT : return "OP_2ROT"; |
|||
case OP_2SWAP : return "OP_2SWAP"; |
|||
case OP_IFDUP : return "OP_IFDUP"; |
|||
case OP_DEPTH : return "OP_DEPTH"; |
|||
case OP_DROP : return "OP_DROP"; |
|||
case OP_DUP : return "OP_DUP"; |
|||
case OP_NIP : return "OP_NIP"; |
|||
case OP_OVER : return "OP_OVER"; |
|||
case OP_PICK : return "OP_PICK"; |
|||
case OP_ROLL : return "OP_ROLL"; |
|||
case OP_ROT : return "OP_ROT"; |
|||
case OP_SWAP : return "OP_SWAP"; |
|||
case OP_TUCK : return "OP_TUCK"; |
|||
|
|||
// splice ops
|
|||
case OP_CAT : return "OP_CAT"; |
|||
case OP_SUBSTR : return "OP_SUBSTR"; |
|||
case OP_LEFT : return "OP_LEFT"; |
|||
case OP_RIGHT : return "OP_RIGHT"; |
|||
case OP_SIZE : return "OP_SIZE"; |
|||
|
|||
// bit logic
|
|||
case OP_INVERT : return "OP_INVERT"; |
|||
case OP_AND : return "OP_AND"; |
|||
case OP_OR : return "OP_OR"; |
|||
case OP_XOR : return "OP_XOR"; |
|||
case OP_EQUAL : return "OP_EQUAL"; |
|||
case OP_EQUALVERIFY : return "OP_EQUALVERIFY"; |
|||
case OP_RESERVED1 : return "OP_RESERVED1"; |
|||
case OP_RESERVED2 : return "OP_RESERVED2"; |
|||
|
|||
// numeric
|
|||
case OP_1ADD : return "OP_1ADD"; |
|||
case OP_1SUB : return "OP_1SUB"; |
|||
case OP_2MUL : return "OP_2MUL"; |
|||
case OP_2DIV : return "OP_2DIV"; |
|||
case OP_NEGATE : return "OP_NEGATE"; |
|||
case OP_ABS : return "OP_ABS"; |
|||
case OP_NOT : return "OP_NOT"; |
|||
case OP_0NOTEQUAL : return "OP_0NOTEQUAL"; |
|||
case OP_ADD : return "OP_ADD"; |
|||
case OP_SUB : return "OP_SUB"; |
|||
case OP_MUL : return "OP_MUL"; |
|||
case OP_DIV : return "OP_DIV"; |
|||
case OP_MOD : return "OP_MOD"; |
|||
case OP_LSHIFT : return "OP_LSHIFT"; |
|||
case OP_RSHIFT : return "OP_RSHIFT"; |
|||
case OP_BOOLAND : return "OP_BOOLAND"; |
|||
case OP_BOOLOR : return "OP_BOOLOR"; |
|||
case OP_NUMEQUAL : return "OP_NUMEQUAL"; |
|||
case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY"; |
|||
case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL"; |
|||
case OP_LESSTHAN : return "OP_LESSTHAN"; |
|||
case OP_GREATERTHAN : return "OP_GREATERTHAN"; |
|||
case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL"; |
|||
case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL"; |
|||
case OP_MIN : return "OP_MIN"; |
|||
case OP_MAX : return "OP_MAX"; |
|||
case OP_WITHIN : return "OP_WITHIN"; |
|||
|
|||
// crypto
|
|||
case OP_RIPEMD160 : return "OP_RIPEMD160"; |
|||
case OP_SHA1 : return "OP_SHA1"; |
|||
case OP_SHA256 : return "OP_SHA256"; |
|||
case OP_HASH160 : return "OP_HASH160"; |
|||
case OP_HASH256 : return "OP_HASH256"; |
|||
case OP_CODESEPARATOR : return "OP_CODESEPARATOR"; |
|||
case OP_CHECKSIG : return "OP_CHECKSIG"; |
|||
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY"; |
|||
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG"; |
|||
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY"; |
|||
|
|||
// expanson
|
|||
case OP_NOP1 : return "OP_NOP1"; |
|||
case OP_NOP2 : return "OP_NOP2"; |
|||
case OP_NOP3 : return "OP_NOP3"; |
|||
case OP_NOP4 : return "OP_NOP4"; |
|||
case OP_NOP5 : return "OP_NOP5"; |
|||
case OP_NOP6 : return "OP_NOP6"; |
|||
case OP_NOP7 : return "OP_NOP7"; |
|||
case OP_NOP8 : return "OP_NOP8"; |
|||
case OP_NOP9 : return "OP_NOP9"; |
|||
case OP_NOP10 : return "OP_NOP10"; |
|||
|
|||
|
|||
|
|||
// template matching params
|
|||
case OP_PUBKEYHASH : return "OP_PUBKEYHASH"; |
|||
case OP_PUBKEY : return "OP_PUBKEY"; |
|||
|
|||
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; |
|||
default: |
|||
return "OP_UNKNOWN"; |
|||
} |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
inline std::string ValueString(const std::vector<unsigned char>& vch) |
|||
{ |
|||
if (vch.size() <= 4) |
|||
return strprintf("%d", CBigNum(vch).getint()); |
|||
else |
|||
return HexStr(vch); |
|||
} |
|||
|
|||
inline std::string StackString(const std::vector<std::vector<unsigned char> >& vStack) |
|||
{ |
|||
std::string str; |
|||
BOOST_FOREACH(const std::vector<unsigned char>& vch, vStack) |
|||
{ |
|||
if (!str.empty()) |
|||
str += " "; |
|||
str += ValueString(vch); |
|||
} |
|||
return str; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
class CScript : public std::vector<unsigned char> |
|||
{ |
|||
protected: |
|||
CScript& push_int64(int64 n) |
|||
{ |
|||
if (n == -1 || (n >= 1 && n <= 16)) |
|||
{ |
|||
push_back(n + (OP_1 - 1)); |
|||
} |
|||
else |
|||
{ |
|||
CBigNum bn(n); |
|||
*this << bn.getvch(); |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
CScript& push_uint64(uint64 n) |
|||
{ |
|||
if (n >= 1 && n <= 16) |
|||
{ |
|||
push_back(n + (OP_1 - 1)); |
|||
} |
|||
else |
|||
{ |
|||
CBigNum bn(n); |
|||
*this << bn.getvch(); |
|||
} |
|||
return *this; |
|||
} |
|||
|
|||
public: |
|||
CScript() { } |
|||
CScript(const CScript& b) : std::vector<unsigned char>(b.begin(), b.end()) { } |
|||
CScript(const_iterator pbegin, const_iterator pend) : std::vector<unsigned char>(pbegin, pend) { } |
|||
#ifndef _MSC_VER |
|||
CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector<unsigned char>(pbegin, pend) { } |
|||
#endif |
|||
|
|||
CScript& operator+=(const CScript& b) |
|||
{ |
|||
insert(end(), b.begin(), b.end()); |
|||
return *this; |
|||
} |
|||
|
|||
friend CScript operator+(const CScript& a, const CScript& b) |
|||
{ |
|||
CScript ret = a; |
|||
ret += b; |
|||
return ret; |
|||
} |
|||
|
|||
|
|||
explicit CScript(char b) { operator<<(b); } |
|||
explicit CScript(short b) { operator<<(b); } |
|||
explicit CScript(int b) { operator<<(b); } |
|||
explicit CScript(long b) { operator<<(b); } |
|||
explicit CScript(int64 b) { operator<<(b); } |
|||
explicit CScript(unsigned char b) { operator<<(b); } |
|||
explicit CScript(unsigned int b) { operator<<(b); } |
|||
explicit CScript(unsigned short b) { operator<<(b); } |
|||
explicit CScript(unsigned long b) { operator<<(b); } |
|||
explicit CScript(uint64 b) { operator<<(b); } |
|||
|
|||
explicit CScript(opcodetype b) { operator<<(b); } |
|||
explicit CScript(const uint256& b) { operator<<(b); } |
|||
explicit CScript(const CBigNum& b) { operator<<(b); } |
|||
explicit CScript(const std::vector<unsigned char>& b) { operator<<(b); } |
|||
|
|||
|
|||
CScript& operator<<(char b) { return push_int64(b); } |
|||
CScript& operator<<(short b) { return push_int64(b); } |
|||
CScript& operator<<(int b) { return push_int64(b); } |
|||
CScript& operator<<(long b) { return push_int64(b); } |
|||
CScript& operator<<(int64 b) { return push_int64(b); } |
|||
CScript& operator<<(unsigned char b) { return push_uint64(b); } |
|||
CScript& operator<<(unsigned int b) { return push_uint64(b); } |
|||
CScript& operator<<(unsigned short b) { return push_uint64(b); } |
|||
CScript& operator<<(unsigned long b) { return push_uint64(b); } |
|||
CScript& operator<<(uint64 b) { return push_uint64(b); } |
|||
|
|||
CScript& operator<<(opcodetype opcode) |
|||
{ |
|||
if (opcode < 0 || opcode > 0xff) |
|||
throw std::runtime_error("CScript::operator<<() : invalid opcode"); |
|||
insert(end(), (unsigned char)opcode); |
|||
return *this; |
|||
} |
|||
|
|||
CScript& operator<<(const uint160& b) |
|||
{ |
|||
insert(end(), sizeof(b)); |
|||
insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); |
|||
return *this; |
|||
} |
|||
|
|||
CScript& operator<<(const uint256& b) |
|||
{ |
|||
insert(end(), sizeof(b)); |
|||
insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b)); |
|||
return *this; |
|||
} |
|||
|
|||
CScript& operator<<(const CBigNum& b) |
|||
{ |
|||
*this << b.getvch(); |
|||
return *this; |
|||
} |
|||
|
|||
CScript& operator<<(const std::vector<unsigned char>& b) |
|||
{ |
|||
if (b.size() < OP_PUSHDATA1) |
|||
{ |
|||
insert(end(), (unsigned char)b.size()); |
|||
} |
|||
else if (b.size() <= 0xff) |
|||
{ |
|||
insert(end(), OP_PUSHDATA1); |
|||
insert(end(), (unsigned char)b.size()); |
|||
} |
|||
else if (b.size() <= 0xffff) |
|||
{ |
|||
insert(end(), OP_PUSHDATA2); |
|||
unsigned short nSize = b.size(); |
|||
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); |
|||
} |
|||
else |
|||
{ |
|||
insert(end(), OP_PUSHDATA4); |
|||
unsigned int nSize = b.size(); |
|||
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize)); |
|||
} |
|||
insert(end(), b.begin(), b.end()); |
|||
return *this; |
|||
} |
|||
|
|||
CScript& operator<<(const CScript& b) |
|||
{ |
|||
// I'm not sure if this should push the script or concatenate scripts.
|
|||
// If there's ever a use for pushing a script onto a script, delete this member fn
|
|||
assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false)); |
|||
return *this; |
|||
} |
|||
|
|||
|
|||
bool GetOp(iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) |
|||
{ |
|||
// Wrapper so it can be called with either iterator or const_iterator
|
|||
const_iterator pc2 = pc; |
|||
bool fRet = GetOp2(pc2, opcodeRet, &vchRet); |
|||
pc = begin() + (pc2 - begin()); |
|||
return fRet; |
|||
} |
|||
|
|||
bool GetOp(iterator& pc, opcodetype& opcodeRet) |
|||
{ |
|||
const_iterator pc2 = pc; |
|||
bool fRet = GetOp2(pc2, opcodeRet, NULL); |
|||
pc = begin() + (pc2 - begin()); |
|||
return fRet; |
|||
} |
|||
|
|||
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>& vchRet) const |
|||
{ |
|||
return GetOp2(pc, opcodeRet, &vchRet); |
|||
} |
|||
|
|||
bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const |
|||
{ |
|||
return GetOp2(pc, opcodeRet, NULL); |
|||
} |
|||
|
|||
bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet) const |
|||
{ |
|||
opcodeRet = OP_INVALIDOPCODE; |
|||
if (pvchRet) |
|||
pvchRet->clear(); |
|||
if (pc >= end()) |
|||
return false; |
|||
|
|||
// Read instruction
|
|||
if (end() - pc < 1) |
|||
return false; |
|||
unsigned int opcode = *pc++; |
|||
|
|||
// Immediate operand
|
|||
if (opcode <= OP_PUSHDATA4) |
|||
{ |
|||
unsigned int nSize; |
|||
if (opcode < OP_PUSHDATA1) |
|||
{ |
|||
nSize = opcode; |
|||
} |
|||
else if (opcode == OP_PUSHDATA1) |
|||
{ |
|||
if (end() - pc < 1) |
|||
return false; |
|||
nSize = *pc++; |
|||
} |
|||
else if (opcode == OP_PUSHDATA2) |
|||
{ |
|||
if (end() - pc < 2) |
|||
return false; |
|||
nSize = 0; |
|||
memcpy(&nSize, &pc[0], 2); |
|||
pc += 2; |
|||
} |
|||
else if (opcode == OP_PUSHDATA4) |
|||
{ |
|||
if (end() - pc < 4) |
|||
return false; |
|||
memcpy(&nSize, &pc[0], 4); |
|||
pc += 4; |
|||
} |
|||
if (end() - pc < nSize) |
|||
return false; |
|||
if (pvchRet) |
|||
pvchRet->assign(pc, pc + nSize); |
|||
pc += nSize; |
|||
} |
|||
|
|||
opcodeRet = (opcodetype)opcode; |
|||
return true; |
|||
} |
|||
|
|||
|
|||
void FindAndDelete(const CScript& b) |
|||
{ |
|||
if (b.empty()) |
|||
return; |
|||
iterator pc = begin(); |
|||
opcodetype opcode; |
|||
do |
|||
{ |
|||
while (end() - pc >= b.size() && memcmp(&pc[0], &b[0], b.size()) == 0) |
|||
erase(pc, pc + b.size()); |
|||
} |
|||
while (GetOp(pc, opcode)); |
|||
} |
|||
|
|||
|
|||
int GetSigOpCount() const |
|||
{ |
|||
int n = 0; |
|||
const_iterator pc = begin(); |
|||
while (pc < end()) |
|||
{ |
|||
opcodetype opcode; |
|||
if (!GetOp(pc, opcode)) |
|||
break; |
|||
if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY) |
|||
n++; |
|||
else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY) |
|||
n += 20; |
|||
} |
|||
return n; |
|||
} |
|||
|
|||
|
|||
bool IsPushOnly() const |
|||
{ |
|||
if (size() > 200) |
|||
return false; |
|||
const_iterator pc = begin(); |
|||
while (pc < end()) |
|||
{ |
|||
opcodetype opcode; |
|||
if (!GetOp(pc, opcode)) |
|||
return false; |
|||
if (opcode > OP_16) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
|
|||
uint160 GetBitcoinAddressHash160() const |
|||
{ |
|||
opcodetype opcode; |
|||
std::vector<unsigned char> vch; |
|||
CScript::const_iterator pc = begin(); |
|||
if (!GetOp(pc, opcode, vch) || opcode != OP_DUP) return 0; |
|||
if (!GetOp(pc, opcode, vch) || opcode != OP_HASH160) return 0; |
|||
if (!GetOp(pc, opcode, vch) || vch.size() != sizeof(uint160)) return 0; |
|||
uint160 hash160 = uint160(vch); |
|||
if (!GetOp(pc, opcode, vch) || opcode != OP_EQUALVERIFY) return 0; |
|||
if (!GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG) return 0; |
|||
if (pc != end()) return 0; |
|||
return hash160; |
|||
} |
|||
|
|||
std::string GetBitcoinAddress() const |
|||
{ |
|||
uint160 hash160 = GetBitcoinAddressHash160(); |
|||
if (hash160 == 0) |
|||
return ""; |
|||
return Hash160ToAddress(hash160); |
|||
} |
|||
|
|||
void SetBitcoinAddress(const uint160& hash160) |
|||
{ |
|||
this->clear(); |
|||
*this << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; |
|||
} |
|||
|
|||
void SetBitcoinAddress(const std::vector<unsigned char>& vchPubKey) |
|||
{ |
|||
SetBitcoinAddress(Hash160(vchPubKey)); |
|||
} |
|||
|
|||
bool SetBitcoinAddress(const std::string& strAddress) |
|||
{ |
|||
this->clear(); |
|||
uint160 hash160; |
|||
if (!AddressToHash160(strAddress, hash160)) |
|||
return false; |
|||
SetBitcoinAddress(hash160); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
void PrintHex() const |
|||
{ |
|||
printf("CScript(%s)\n", HexStr(begin(), end(), true).c_str()); |
|||
} |
|||
|
|||
std::string ToString() const |
|||
{ |
|||
std::string str; |
|||
opcodetype opcode; |
|||
std::vector<unsigned char> vch; |
|||
const_iterator pc = begin(); |
|||
while (pc < end()) |
|||
{ |
|||
if (!str.empty()) |
|||
str += " "; |
|||
if (!GetOp(pc, opcode, vch)) |
|||
{ |
|||
str += "[error]"; |
|||
return str; |
|||
} |
|||
if (0 <= opcode && opcode <= OP_PUSHDATA4) |
|||
str += ValueString(vch); |
|||
else |
|||
str += GetOpName(opcode); |
|||
} |
|||
return str; |
|||
} |
|||
|
|||
void print() const |
|||
{ |
|||
printf("%s\n", ToString().c_str()); |
|||
} |
|||
}; |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); |
|||
bool IsStandard(const CScript& scriptPubKey); |
|||
bool IsMine(const CScript& scriptPubKey); |
|||
bool ExtractPubKey(const CScript& scriptPubKey, bool fMineOnly, std::vector<unsigned char>& vchPubKeyRet); |
|||
bool ExtractHash160(const CScript& scriptPubKey, uint160& hash160Ret); |
|||
bool SignSignature(const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL, CScript scriptPrereq=CScript()); |
|||
bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType=0); |
|||
|
|||
#endif |
File diff suppressed because it is too large
@ -0,0 +1,522 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
#include "headers.h" |
|||
|
|||
using namespace std; |
|||
using namespace boost; |
|||
|
|||
//////////////////////////////////////////////////////////////////////////////
|
|||
//
|
|||
// Shutdown
|
|||
//
|
|||
|
|||
void ExitTimeout(void* parg) |
|||
{ |
|||
#ifdef __WXMSW__ |
|||
Sleep(5000); |
|||
ExitProcess(0); |
|||
#endif |
|||
} |
|||
|
|||
void Shutdown(void* parg) |
|||
{ |
|||
static CCriticalSection cs_Shutdown; |
|||
static bool fTaken; |
|||
bool fFirstThread; |
|||
CRITICAL_BLOCK(cs_Shutdown) |
|||
{ |
|||
fFirstThread = !fTaken; |
|||
fTaken = true; |
|||
} |
|||
static bool fExit; |
|||
if (fFirstThread) |
|||
{ |
|||
fShutdown = true; |
|||
nTransactionsUpdated++; |
|||
DBFlush(false); |
|||
StopNode(); |
|||
DBFlush(true); |
|||
boost::filesystem::remove(GetPidFile()); |
|||
CreateThread(ExitTimeout, NULL); |
|||
Sleep(50); |
|||
printf("Bitcoin exiting\n\n"); |
|||
fExit = true; |
|||
exit(0); |
|||
} |
|||
else |
|||
{ |
|||
while (!fExit) |
|||
Sleep(500); |
|||
Sleep(100); |
|||
ExitThread(0); |
|||
} |
|||
} |
|||
|
|||
void HandleSIGTERM(int) |
|||
{ |
|||
fRequestShutdown = true; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
//////////////////////////////////////////////////////////////////////////////
|
|||
//
|
|||
// Start
|
|||
//
|
|||
#if 0 |
|||
#ifndef GUI |
|||
int main(int argc, char* argv[]) |
|||
{ |
|||
bool fRet = false; |
|||
fRet = AppInit(argc, argv); |
|||
|
|||
if (fRet && fDaemon) |
|||
return 0; |
|||
|
|||
return 1; |
|||
} |
|||
#endif |
|||
#endif |
|||
|
|||
bool AppInit(int argc, char* argv[]) |
|||
{ |
|||
bool fRet = false; |
|||
try |
|||
{ |
|||
fRet = AppInit2(argc, argv); |
|||
} |
|||
catch (std::exception& e) { |
|||
PrintException(&e, "AppInit()"); |
|||
} catch (...) { |
|||
PrintException(NULL, "AppInit()"); |
|||
} |
|||
if (!fRet) |
|||
Shutdown(NULL); |
|||
return fRet; |
|||
} |
|||
|
|||
bool AppInit2(int argc, char* argv[]) |
|||
{ |
|||
#ifdef _MSC_VER |
|||
// Turn off microsoft heap dump noise
|
|||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); |
|||
_CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); |
|||
#endif |
|||
#if _MSC_VER >= 1400 |
|||
// Disable confusing "helpful" text message on abort, ctrl-c
|
|||
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); |
|||
#endif |
|||
#ifndef __WXMSW__ |
|||
umask(077); |
|||
#endif |
|||
#ifndef __WXMSW__ |
|||
// Clean shutdown on SIGTERM
|
|||
struct sigaction sa; |
|||
sa.sa_handler = HandleSIGTERM; |
|||
sigemptyset(&sa.sa_mask); |
|||
sa.sa_flags = 0; |
|||
sigaction(SIGTERM, &sa, NULL); |
|||
sigaction(SIGINT, &sa, NULL); |
|||
sigaction(SIGHUP, &sa, NULL); |
|||
#endif |
|||
|
|||
//
|
|||
// Parameters
|
|||
//
|
|||
ParseParameters(argc, argv); |
|||
|
|||
if (mapArgs.count("-datadir")) |
|||
{ |
|||
filesystem::path pathDataDir = filesystem::system_complete(mapArgs["-datadir"]); |
|||
strlcpy(pszSetDataDir, pathDataDir.string().c_str(), sizeof(pszSetDataDir)); |
|||
} |
|||
|
|||
ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
|
|||
|
|||
if (mapArgs.count("-?") || mapArgs.count("--help")) |
|||
{ |
|||
string beta = VERSION_IS_BETA ? _(" beta") : ""; |
|||
string strUsage = string() + |
|||
_("Bitcoin version") + " " + FormatFullVersion() + "\n\n" + |
|||
_("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" + |
|||
" bitcoin [options] \t " + "\n" + |
|||
" bitcoin [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") + |
|||
" bitcoin [options] help \t\t " + _("List commands\n") + |
|||
" bitcoin [options] help <command> \t\t " + _("Get help for a command\n") + |
|||
_("Options:\n") + |
|||
" -conf=<file> \t\t " + _("Specify configuration file (default: bitcoin.conf)\n") + |
|||
" -pid=<file> \t\t " + _("Specify pid file (default: bitcoind.pid)\n") + |
|||
" -gen \t\t " + _("Generate coins\n") + |
|||
" -gen=0 \t\t " + _("Don't generate coins\n") + |
|||
" -min \t\t " + _("Start minimized\n") + |
|||
" -datadir=<dir> \t\t " + _("Specify data directory\n") + |
|||
" -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") + |
|||
" -dns \t " + _("Allow DNS lookups for addnode and connect\n") + |
|||
" -addnode=<ip> \t " + _("Add a node to connect to\n") + |
|||
" -connect=<ip> \t\t " + _("Connect only to the specified node\n") + |
|||
" -nolisten \t " + _("Don't accept connections from outside\n") + |
|||
#ifdef USE_UPNP |
|||
#if USE_UPNP |
|||
" -noupnp \t " + _("Don't attempt to use UPnP to map the listening port\n") + |
|||
#else |
|||
" -upnp \t " + _("Attempt to use UPnP to map the listening port\n") + |
|||
#endif |
|||
#endif |
|||
" -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send\n") + |
|||
#ifdef GUI |
|||
" -server \t\t " + _("Accept command line and JSON-RPC commands\n") + |
|||
#endif |
|||
#ifndef __WXMSW__ |
|||
" -daemon \t\t " + _("Run in the background as a daemon and accept commands\n") + |
|||
#endif |
|||
" -testnet \t\t " + _("Use the test network\n") + |
|||
" -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") + |
|||
" -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") + |
|||
" -rpcport=<port> \t\t " + _("Listen for JSON-RPC connections on <port> (default: 8332)\n") + |
|||
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address\n") + |
|||
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)\n") + |
|||
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)\n") + |
|||
" -rescan \t " + _("Rescan the block chain for missing wallet transactions\n"); |
|||
|
|||
#ifdef USE_SSL |
|||
strUsage += string() + |
|||
_("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)\n") + |
|||
" -rpcssl \t " + _("Use OpenSSL (https) for JSON-RPC connections\n") + |
|||
" -rpcsslcertificatechainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)\n") + |
|||
" -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)\n") + |
|||
" -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n"); |
|||
#endif |
|||
|
|||
strUsage += string() + |
|||
" -? \t\t " + _("This help message\n"); |
|||
|
|||
#if defined(__WXMSW__) && defined(GUI) |
|||
// Tabs make the columns line up in the message box
|
|||
wxMessageBox(strUsage, "Bitcoin", wxOK); |
|||
#else |
|||
// Remove tabs
|
|||
strUsage.erase(std::remove(strUsage.begin(), strUsage.end(), '\t'), strUsage.end()); |
|||
fprintf(stderr, "%s", strUsage.c_str()); |
|||
#endif |
|||
return false; |
|||
} |
|||
|
|||
fDebug = GetBoolArg("-debug"); |
|||
fAllowDNS = GetBoolArg("-dns"); |
|||
|
|||
#ifndef __WXMSW__ |
|||
fDaemon = GetBoolArg("-daemon"); |
|||
#else |
|||
fDaemon = false; |
|||
#endif |
|||
|
|||
if (fDaemon) |
|||
fServer = true; |
|||
else |
|||
fServer = GetBoolArg("-server"); |
|||
|
|||
/* force fServer when running without GUI */ |
|||
#ifndef GUI |
|||
fServer = true; |
|||
#endif |
|||
|
|||
fPrintToConsole = GetBoolArg("-printtoconsole"); |
|||
fPrintToDebugger = GetBoolArg("-printtodebugger"); |
|||
|
|||
fTestNet = GetBoolArg("-testnet"); |
|||
fNoListen = GetBoolArg("-nolisten"); |
|||
fLogTimestamps = GetBoolArg("-logtimestamps"); |
|||
|
|||
for (int i = 1; i < argc; i++) |
|||
if (!IsSwitchChar(argv[i][0])) |
|||
fCommandLine = true; |
|||
|
|||
if (fCommandLine) |
|||
{ |
|||
int ret = CommandLineRPC(argc, argv); |
|||
exit(ret); |
|||
} |
|||
|
|||
#ifndef __WXMSW__ |
|||
if (fDaemon) |
|||
{ |
|||
// Daemonize
|
|||
pid_t pid = fork(); |
|||
if (pid < 0) |
|||
{ |
|||
fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); |
|||
return false; |
|||
} |
|||
if (pid > 0) |
|||
{ |
|||
CreatePidFile(GetPidFile(), pid); |
|||
return true; |
|||
} |
|||
|
|||
pid_t sid = setsid(); |
|||
if (sid < 0) |
|||
fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); |
|||
} |
|||
#endif |
|||
|
|||
if (!fDebug && !pszSetDataDir[0]) |
|||
ShrinkDebugFile(); |
|||
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); |
|||
printf("Bitcoin version %s\n", FormatFullVersion().c_str()); |
|||
#ifdef GUI |
|||
printf("OS version %s\n", ((string)wxGetOsDescription()).c_str()); |
|||
printf("System default language is %d %s\n", g_locale.GetSystemLanguage(), ((string)g_locale.GetSysName()).c_str()); |
|||
printf("Language file %s (%s)\n", (string("locale/") + (string)g_locale.GetCanonicalName() + "/LC_MESSAGES/bitcoin.mo").c_str(), ((string)g_locale.GetLocale()).c_str()); |
|||
#endif |
|||
printf("Default data directory %s\n", GetDefaultDataDir().c_str()); |
|||
|
|||
if (GetBoolArg("-loadblockindextest")) |
|||
{ |
|||
CTxDB txdb("r"); |
|||
txdb.LoadBlockIndex(); |
|||
PrintBlockTree(); |
|||
return false; |
|||
} |
|||
|
|||
//
|
|||
// Limit to single instance per user
|
|||
// Required to protect the database files if we're going to keep deleting log.*
|
|||
//
|
|||
#if defined(__WXMSW__) && defined(GUI) |
|||
// wxSingleInstanceChecker doesn't work on Linux
|
|||
wxString strMutexName = wxString("bitcoin_running.") + getenv("HOMEPATH"); |
|||
for (int i = 0; i < strMutexName.size(); i++) |
|||
if (!isalnum(strMutexName[i])) |
|||
strMutexName[i] = '.'; |
|||
wxSingleInstanceChecker* psingleinstancechecker = new wxSingleInstanceChecker(strMutexName); |
|||
if (psingleinstancechecker->IsAnotherRunning()) |
|||
{ |
|||
printf("Existing instance found\n"); |
|||
unsigned int nStart = GetTime(); |
|||
loop |
|||
{ |
|||
// Show the previous instance and exit
|
|||
HWND hwndPrev = FindWindowA("wxWindowClassNR", "Bitcoin"); |
|||
if (hwndPrev) |
|||
{ |
|||
if (IsIconic(hwndPrev)) |
|||
ShowWindow(hwndPrev, SW_RESTORE); |
|||
SetForegroundWindow(hwndPrev); |
|||
return false; |
|||
} |
|||
|
|||
if (GetTime() > nStart + 60) |
|||
return false; |
|||
|
|||
// Resume this instance if the other exits
|
|||
delete psingleinstancechecker; |
|||
Sleep(1000); |
|||
psingleinstancechecker = new wxSingleInstanceChecker(strMutexName); |
|||
if (!psingleinstancechecker->IsAnotherRunning()) |
|||
break; |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
// Make sure only a single bitcoin process is using the data directory.
|
|||
string strLockFile = GetDataDir() + "/.lock"; |
|||
FILE* file = fopen(strLockFile.c_str(), "a"); // empty lock file; created if it doesn't exist.
|
|||
if (file) fclose(file); |
|||
static boost::interprocess::file_lock lock(strLockFile.c_str()); |
|||
if (!lock.try_lock()) |
|||
{ |
|||
wxMessageBox(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().c_str()), "Bitcoin"); |
|||
return false; |
|||
} |
|||
|
|||
// Bind to the port early so we can tell if another instance is already running.
|
|||
string strErrors; |
|||
if (!fNoListen) |
|||
{ |
|||
if (!BindListenPort(strErrors)) |
|||
{ |
|||
wxMessageBox(strErrors, "Bitcoin"); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
//
|
|||
// Load data files
|
|||
//
|
|||
if (fDaemon) |
|||
fprintf(stdout, "bitcoin server starting\n"); |
|||
strErrors = ""; |
|||
int64 nStart; |
|||
|
|||
printf("Loading addresses...\n"); |
|||
nStart = GetTimeMillis(); |
|||
if (!LoadAddresses()) |
|||
strErrors += _("Error loading addr.dat \n"); |
|||
printf(" addresses %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
|||
|
|||
printf("Loading block index...\n"); |
|||
nStart = GetTimeMillis(); |
|||
if (!LoadBlockIndex()) |
|||
strErrors += _("Error loading blkindex.dat \n"); |
|||
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
|||
|
|||
printf("Loading wallet...\n"); |
|||
nStart = GetTimeMillis(); |
|||
bool fFirstRun; |
|||
if (!LoadWallet(fFirstRun)) |
|||
strErrors += _("Error loading wallet.dat \n"); |
|||
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
|||
|
|||
CBlockIndex *pindexRescan = pindexBest; |
|||
if (GetBoolArg("-rescan")) |
|||
pindexRescan = pindexGenesisBlock; |
|||
else |
|||
{ |
|||
CWalletDB walletdb; |
|||
CBlockLocator locator; |
|||
if (walletdb.ReadBestBlock(locator)) |
|||
pindexRescan = locator.GetBlockIndex(); |
|||
} |
|||
if (pindexBest != pindexRescan) |
|||
{ |
|||
printf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); |
|||
nStart = GetTimeMillis(); |
|||
ScanForWalletTransactions(pindexRescan); |
|||
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); |
|||
} |
|||
|
|||
printf("Done loading\n"); |
|||
|
|||
//// debug print
|
|||
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); |
|||
printf("nBestHeight = %d\n", nBestHeight); |
|||
printf("mapKeys.size() = %d\n", mapKeys.size()); |
|||
printf("mapPubKeys.size() = %d\n", mapPubKeys.size()); |
|||
printf("mapWallet.size() = %d\n", mapWallet.size()); |
|||
printf("mapAddressBook.size() = %d\n", mapAddressBook.size()); |
|||
|
|||
if (!strErrors.empty()) |
|||
{ |
|||
wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR); |
|||
return false; |
|||
} |
|||
|
|||
// Add wallet transactions that aren't already in a block to mapTransactions
|
|||
ReacceptWalletTransactions(); |
|||
|
|||
//
|
|||
// Parameters
|
|||
//
|
|||
if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) |
|||
{ |
|||
PrintBlockTree(); |
|||
return false; |
|||
} |
|||
|
|||
if (mapArgs.count("-printblock")) |
|||
{ |
|||
string strMatch = mapArgs["-printblock"]; |
|||
int nFound = 0; |
|||
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) |
|||
{ |
|||
uint256 hash = (*mi).first; |
|||
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) |
|||
{ |
|||
CBlockIndex* pindex = (*mi).second; |
|||
CBlock block; |
|||
block.ReadFromDisk(pindex); |
|||
block.BuildMerkleTree(); |
|||
block.print(); |
|||
printf("\n"); |
|||
nFound++; |
|||
} |
|||
} |
|||
if (nFound == 0) |
|||
printf("No blocks matching %s were found\n", strMatch.c_str()); |
|||
return false; |
|||
} |
|||
|
|||
fGenerateBitcoins = GetBoolArg("-gen"); |
|||
|
|||
if (mapArgs.count("-proxy")) |
|||
{ |
|||
fUseProxy = true; |
|||
addrProxy = CAddress(mapArgs["-proxy"]); |
|||
if (!addrProxy.IsValid()) |
|||
{ |
|||
wxMessageBox(_("Invalid -proxy address"), "Bitcoin"); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (mapArgs.count("-addnode")) |
|||
{ |
|||
BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"]) |
|||
{ |
|||
CAddress addr(strAddr, fAllowDNS); |
|||
addr.nTime = 0; // so it won't relay unless successfully connected
|
|||
if (addr.IsValid()) |
|||
AddAddress(addr); |
|||
} |
|||
} |
|||
|
|||
if (mapArgs.count("-dnsseed")) |
|||
DNSAddressSeed(); |
|||
|
|||
if (mapArgs.count("-paytxfee")) |
|||
{ |
|||
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) |
|||
{ |
|||
wxMessageBox(_("Invalid amount for -paytxfee=<amount>"), "Bitcoin"); |
|||
return false; |
|||
} |
|||
if (nTransactionFee > 0.25 * COIN) |
|||
wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION); |
|||
} |
|||
|
|||
if (fHaveUPnP) |
|||
{ |
|||
#if USE_UPNP |
|||
if (GetBoolArg("-noupnp")) |
|||
fUseUPnP = false; |
|||
#else |
|||
if (GetBoolArg("-upnp")) |
|||
fUseUPnP = true; |
|||
#endif |
|||
} |
|||
|
|||
//
|
|||
// Create the main window and start the node
|
|||
//
|
|||
#ifdef GUI |
|||
if (!fDaemon) |
|||
CreateMainWindow(); |
|||
#endif |
|||
|
|||
if (!CheckDiskSpace()) |
|||
return false; |
|||
|
|||
RandAddSeedPerfmon(); |
|||
|
|||
if (!CreateThread(StartNode, NULL)) |
|||
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin"); |
|||
|
|||
if (fServer) |
|||
CreateThread(ThreadRPCServer, NULL); |
|||
|
|||
#if defined(__WXMSW__) && defined(GUI) |
|||
if (fFirstRun) |
|||
SetStartOnSystemStartup(true); |
|||
#endif |
|||
|
|||
#ifndef GUI |
|||
while (1) |
|||
Sleep(5000); |
|||
#endif |
|||
|
|||
return true; |
|||
} |
@ -0,0 +1,438 @@ |
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
|||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
|||
|
|||
#include "headers.h" |
|||
|
|||
using namespace std; |
|||
using namespace boost; |
|||
|
|||
int nGotIRCAddresses = 0; |
|||
bool fGotExternalIP = false; |
|||
|
|||
void ThreadIRCSeed2(void* parg); |
|||
|
|||
|
|||
|
|||
|
|||
#pragma pack(push, 1) |
|||
struct ircaddr |
|||
{ |
|||
int ip; |
|||
short port; |
|||
}; |
|||
#pragma pack(pop) |
|||
|
|||
string EncodeAddress(const CAddress& addr) |
|||
{ |
|||
struct ircaddr tmp; |
|||
tmp.ip = addr.ip; |
|||
tmp.port = addr.port; |
|||
|
|||
vector<unsigned char> vch(UBEGIN(tmp), UEND(tmp)); |
|||
return string("u") + EncodeBase58Check(vch); |
|||
} |
|||
|
|||
bool DecodeAddress(string str, CAddress& addr) |
|||
{ |
|||
vector<unsigned char> vch; |
|||
if (!DecodeBase58Check(str.substr(1), vch)) |
|||
return false; |
|||
|
|||
struct ircaddr tmp; |
|||
if (vch.size() != sizeof(tmp)) |
|||
return false; |
|||
memcpy(&tmp, &vch[0], sizeof(tmp)); |
|||
|
|||
addr = CAddress(tmp.ip, ntohs(tmp.port), NODE_NETWORK); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
static bool Send(SOCKET hSocket, const char* pszSend) |
|||
{ |
|||
if (strstr(pszSend, "PONG") != pszSend) |
|||
printf("IRC SENDING: %s\n", pszSend); |
|||
const char* psz = pszSend; |
|||
const char* pszEnd = psz + strlen(psz); |
|||
while (psz < pszEnd) |
|||
{ |
|||
int ret = send(hSocket, psz, pszEnd - psz, MSG_NOSIGNAL); |
|||
if (ret < 0) |
|||
return false; |
|||
psz += ret; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool RecvLine(SOCKET hSocket, string& strLine) |
|||
{ |
|||
strLine = ""; |
|||
loop |
|||
{ |
|||
char c; |
|||
int nBytes = recv(hSocket, &c, 1, 0); |
|||
if (nBytes > 0) |
|||
{ |
|||
if (c == '\n') |
|||
continue; |
|||
if (c == '\r') |
|||
return true; |
|||
strLine += c; |
|||
if (strLine.size() >= 9000) |
|||
return true; |
|||
} |
|||
else if (nBytes <= 0) |
|||
{ |
|||
if (fShutdown) |
|||
return false; |
|||
if (nBytes < 0) |
|||
{ |
|||
int nErr = WSAGetLastError(); |
|||
if (nErr == WSAEMSGSIZE) |
|||
continue; |
|||
if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS) |
|||
{ |
|||
Sleep(10); |
|||
continue; |
|||
} |
|||
} |
|||
if (!strLine.empty()) |
|||
return true; |
|||
if (nBytes == 0) |
|||
{ |
|||
// socket closed
|
|||
printf("IRC socket closed\n"); |
|||
return false; |
|||
} |
|||
else |
|||
{ |
|||
// socket error
|
|||
int nErr = WSAGetLastError(); |
|||
printf("IRC recv failed: %d\n", nErr); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool RecvLineIRC(SOCKET hSocket, string& strLine) |
|||
{ |
|||
loop |
|||
{ |
|||
bool fRet = RecvLine(hSocket, strLine); |
|||
if (fRet) |
|||
{ |
|||
if (fShutdown) |
|||
return false; |
|||
vector<string> vWords; |
|||
ParseString(strLine, ' ', vWords); |
|||
if (vWords.size() >= 1 && vWords[0] == "PING") |
|||
{ |
|||
strLine[1] = 'O'; |
|||
strLine += '\r'; |
|||
Send(hSocket, strLine.c_str()); |
|||
continue; |
|||
} |
|||
} |
|||
return fRet; |
|||
} |
|||
} |
|||
|
|||
int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const char* psz3=NULL, const char* psz4=NULL) |
|||
{ |
|||
loop |
|||
{ |
|||
string strLine; |
|||
strLine.reserve(10000); |
|||
if (!RecvLineIRC(hSocket, strLine)) |
|||
return 0; |
|||
printf("IRC %s\n", strLine.c_str()); |
|||
if (psz1 && strLine.find(psz1) != -1) |
|||
return 1; |
|||
if (psz2 && strLine.find(psz2) != -1) |
|||
return 2; |
|||
if (psz3 && strLine.find(psz3) != -1) |
|||
return 3; |
|||
if (psz4 && strLine.find(psz4) != -1) |
|||
return 4; |
|||
} |
|||
} |
|||
|
|||
bool Wait(int nSeconds) |
|||
{ |
|||
if (fShutdown) |
|||
return false; |
|||
printf("IRC waiting %d seconds to reconnect\n", nSeconds); |
|||
for (int i = 0; i < nSeconds; i++) |
|||
{ |
|||
if (fShutdown) |
|||
return false; |
|||
Sleep(1000); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool RecvCodeLine(SOCKET hSocket, const char* psz1, string& strRet) |
|||
{ |
|||
strRet.clear(); |
|||
loop |
|||
{ |
|||
string strLine; |
|||
if (!RecvLineIRC(hSocket, strLine)) |
|||
return false; |
|||
|
|||
vector<string> vWords; |
|||
ParseString(strLine, ' ', vWords); |
|||
if (vWords.size() < 2) |
|||
continue; |
|||
|
|||
if (vWords[1] == psz1) |
|||
{ |
|||
printf("IRC %s\n", strLine.c_str()); |
|||
strRet = strLine; |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool GetIPFromIRC(SOCKET hSocket, string strMyName, unsigned int& ipRet) |
|||
{ |
|||
Send(hSocket, strprintf("USERHOST %s\r", strMyName.c_str()).c_str()); |
|||
|
|||
string strLine; |
|||
if (!RecvCodeLine(hSocket, "302", strLine)) |
|||
return false; |
|||
|
|||
vector<string> vWords; |
|||
ParseString(strLine, ' ', vWords); |
|||
if (vWords.size() < 4) |
|||
return false; |
|||
|
|||
string str = vWords[3]; |
|||
if (str.rfind("@") == string::npos) |
|||
return false; |
|||
string strHost = str.substr(str.rfind("@")+1); |
|||
|
|||
// Hybrid IRC used by lfnet always returns IP when you userhost yourself,
|
|||
// but in case another IRC is ever used this should work.
|
|||
printf("GetIPFromIRC() got userhost %s\n", strHost.c_str()); |
|||
if (fUseProxy) |
|||
return false; |
|||
CAddress addr(strHost, 0, true); |
|||
if (!addr.IsValid()) |
|||
return false; |
|||
ipRet = addr.ip; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
|
|||
void ThreadIRCSeed(void* parg) |
|||
{ |
|||
IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg)); |
|||
try |
|||
{ |
|||
ThreadIRCSeed2(parg); |
|||
} |
|||
catch (std::exception& e) { |
|||
PrintExceptionContinue(&e, "ThreadIRCSeed()"); |
|||
} catch (...) { |
|||
PrintExceptionContinue(NULL, "ThreadIRCSeed()"); |
|||
} |
|||
printf("ThreadIRCSeed exiting\n"); |
|||
} |
|||
|
|||
void ThreadIRCSeed2(void* parg) |
|||
{ |
|||
/* Dont advertise on IRC if we don't allow incoming connections */ |
|||
if (mapArgs.count("-connect") || fNoListen) |
|||
return; |
|||
|
|||
if (GetBoolArg("-noirc")) |
|||
return; |
|||
printf("ThreadIRCSeed started\n"); |
|||
int nErrorWait = 10; |
|||
int nRetryWait = 10; |
|||
bool fNameInUse = false; |
|||
bool fTOR = (fUseProxy && addrProxy.port == htons(9050)); |
|||
|
|||
while (!fShutdown) |
|||
{ |
|||
//CAddress addrConnect("216.155.130.130:6667"); // chat.freenode.net
|
|||
CAddress addrConnect("92.243.23.21:6667"); // irc.lfnet.org
|
|||
if (!fTOR) |
|||
{ |
|||
//struct hostent* phostent = gethostbyname("chat.freenode.net");
|
|||
CAddress addrIRC("irc.lfnet.org:6667", 0, true); |
|||
if (addrIRC.IsValid()) |
|||
addrConnect = addrIRC; |
|||
} |
|||
|
|||
SOCKET hSocket; |
|||
if (!ConnectSocket(addrConnect, hSocket)) |
|||
{ |
|||
printf("IRC connect failed\n"); |
|||
nErrorWait = nErrorWait * 11 / 10; |
|||
if (Wait(nErrorWait += 60)) |
|||
continue; |
|||
else |
|||
return; |
|||
} |
|||
|
|||
if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname")) |
|||
{ |
|||
closesocket(hSocket); |
|||
hSocket = INVALID_SOCKET; |
|||
nErrorWait = nErrorWait * 11 / 10; |
|||
if (Wait(nErrorWait += 60)) |
|||
continue; |
|||
else |
|||
return; |
|||
} |
|||
|
|||
string strMyName; |
|||
if (addrLocalHost.IsRoutable() && !fUseProxy && !fNameInUse) |
|||
strMyName = EncodeAddress(addrLocalHost); |
|||
else |
|||
strMyName = strprintf("x%u", GetRand(1000000000)); |
|||
|
|||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); |
|||
Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str()); |
|||
|
|||
int nRet = RecvUntil(hSocket, " 004 ", " 433 "); |
|||
if (nRet != 1) |
|||
{ |
|||
closesocket(hSocket); |
|||
hSocket = INVALID_SOCKET; |
|||
if (nRet == 2) |
|||
{ |
|||
printf("IRC name already in use\n"); |
|||
fNameInUse = true; |
|||
Wait(10); |
|||
continue; |
|||
} |
|||
nErrorWait = nErrorWait * 11 / 10; |
|||
if (Wait(nErrorWait += 60)) |
|||
continue; |
|||
else |
|||
return; |
|||
} |
|||
Sleep(500); |
|||
|
|||
// Get our external IP from the IRC server and re-nick before joining the channel
|
|||
CAddress addrFromIRC; |
|||
if (GetIPFromIRC(hSocket, strMyName, addrFromIRC.ip)) |
|||
{ |
|||
printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToStringIP().c_str()); |
|||
if (!fUseProxy && addrFromIRC.IsRoutable()) |
|||
{ |
|||
// IRC lets you to re-nick
|
|||
fGotExternalIP = true; |
|||
addrLocalHost.ip = addrFromIRC.ip; |
|||
strMyName = EncodeAddress(addrLocalHost); |
|||
Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); |
|||
} |
|||
} |
|||
|
|||
Send(hSocket, fTestNet ? "JOIN #bitcoinTEST\r" : "JOIN #bitcoin\r"); |
|||
Send(hSocket, fTestNet ? "WHO #bitcoinTEST\r" : "WHO #bitcoin\r"); |
|||
|
|||
int64 nStart = GetTime(); |
|||
string strLine; |
|||
strLine.reserve(10000); |
|||
while (!fShutdown && RecvLineIRC(hSocket, strLine)) |
|||
{ |
|||
if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':') |
|||
continue; |
|||
|
|||
vector<string> vWords; |
|||
ParseString(strLine, ' ', vWords); |
|||
if (vWords.size() < 2) |
|||
continue; |
|||
|
|||
char pszName[10000]; |
|||
pszName[0] = '\0'; |
|||
|
|||
if (vWords[1] == "352" && vWords.size() >= 8) |
|||
{ |
|||
// index 7 is limited to 16 characters
|
|||
// could get full length name at index 10, but would be different from join messages
|
|||
strlcpy(pszName, vWords[7].c_str(), sizeof(pszName)); |
|||
printf("IRC got who\n"); |
|||
} |
|||
|
|||
if (vWords[1] == "JOIN" && vWords[0].size() > 1) |
|||
{ |
|||
// :username!username@50000007.F000000B.90000002.IP JOIN :#channelname
|
|||
strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName)); |
|||
if (strchr(pszName, '!')) |
|||
*strchr(pszName, '!') = '\0'; |
|||
printf("IRC got join\n"); |
|||
} |
|||
|
|||
if (pszName[0] == 'u') |
|||
{ |
|||
CAddress addr; |
|||
if (DecodeAddress(pszName, addr)) |
|||
{ |
|||
addr.nTime = GetAdjustedTime(); |
|||
if (AddAddress(addr, 51 * 60)) |
|||
printf("IRC got new address: %s\n", addr.ToString().c_str()); |
|||
nGotIRCAddresses++; |
|||
} |
|||
else |
|||
{ |
|||
printf("IRC decode failed\n"); |
|||
} |
|||
} |
|||
} |
|||
closesocket(hSocket); |
|||
hSocket = INVALID_SOCKET; |
|||
|
|||
// IRC usually blocks TOR, so only try once
|
|||
if (fTOR) |
|||
return; |
|||
|
|||
if (GetTime() - nStart > 20 * 60) |
|||
{ |
|||
nErrorWait /= 3; |
|||
nRetryWait /= 3; |
|||
} |
|||
|
|||
nRetryWait = nRetryWait * 11 / 10; |
|||
if (!Wait(nRetryWait += 60)) |
|||
return; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
#ifdef TEST |
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
WSADATA wsadata; |
|||
if (WSAStartup(MAKEWORD(2,2), &wsadata) != NO_ERROR) |
|||
{ |
|||
printf("Error at WSAStartup()\n"); |
|||
return false; |
|||
} |
|||
|
|||
ThreadIRCSeed(NULL); |
|||
|
|||
WSACleanup(); |
|||
return 0; |
|||
} |
|||
#endif |
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,18 @@ |
|||
#ifndef JSON_SPIRIT |
|||
#define JSON_SPIRIT |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include "json_spirit_value.h" |
|||
#include "json_spirit_reader.h" |
|||
#include "json_spirit_writer.h" |
|||
#include "json_spirit_utils.h" |
|||
|
|||
#endif |
@ -0,0 +1,54 @@ |
|||
#ifndef JSON_SPIRIT_ERROR_POSITION |
|||
#define JSON_SPIRIT_ERROR_POSITION |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include <string> |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
// An Error_position exception is thrown by the "read_or_throw" functions below on finding an error.
|
|||
// Note the "read_or_throw" functions are around 3 times slower than the standard functions "read"
|
|||
// functions that return a bool.
|
|||
//
|
|||
struct Error_position |
|||
{ |
|||
Error_position(); |
|||
Error_position( unsigned int line, unsigned int column, const std::string& reason ); |
|||
bool operator==( const Error_position& lhs ) const; |
|||
unsigned int line_; |
|||
unsigned int column_; |
|||
std::string reason_; |
|||
}; |
|||
|
|||
inline Error_position::Error_position() |
|||
: line_( 0 ) |
|||
, column_( 0 ) |
|||
{ |
|||
} |
|||
|
|||
inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason ) |
|||
: line_( line ) |
|||
, column_( column ) |
|||
, reason_( reason ) |
|||
{ |
|||
} |
|||
|
|||
inline bool Error_position::operator==( const Error_position& lhs ) const |
|||
{ |
|||
if( this == &lhs ) return true; |
|||
|
|||
return ( reason_ == lhs.reason_ ) && |
|||
( line_ == lhs.line_ ) && |
|||
( column_ == lhs.column_ ); |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,62 @@ |
|||
#ifndef JSON_SPIRIT_READER |
|||
#define JSON_SPIRIT_READER |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include "json_spirit_value.h" |
|||
#include "json_spirit_error_position.h" |
|||
#include <iostream> |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
// functions to reads a JSON values
|
|||
|
|||
bool read( const std::string& s, Value& value ); |
|||
bool read( std::istream& is, Value& value ); |
|||
bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); |
|||
|
|||
void read_or_throw( const std::string& s, Value& value ); |
|||
void read_or_throw( std::istream& is, Value& value ); |
|||
void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
bool read( const std::wstring& s, wValue& value ); |
|||
bool read( std::wistream& is, wValue& value ); |
|||
bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); |
|||
|
|||
void read_or_throw( const std::wstring& s, wValue& value ); |
|||
void read_or_throw( std::wistream& is, wValue& value ); |
|||
void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); |
|||
|
|||
#endif |
|||
|
|||
bool read( const std::string& s, mValue& value ); |
|||
bool read( std::istream& is, mValue& value ); |
|||
bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); |
|||
|
|||
void read_or_throw( const std::string& s, mValue& value ); |
|||
void read_or_throw( std::istream& is, mValue& value ); |
|||
void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
bool read( const std::wstring& s, wmValue& value ); |
|||
bool read( std::wistream& is, wmValue& value ); |
|||
bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); |
|||
|
|||
void read_or_throw( const std::wstring& s, wmValue& value ); |
|||
void read_or_throw( std::wistream& is, wmValue& value ); |
|||
void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); |
|||
|
|||
#endif |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,612 @@ |
|||
#ifndef JSON_SPIRIT_READER_TEMPLATE |
|||
#define JSON_SPIRIT_READER_TEMPLATE |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#include "json_spirit_value.h" |
|||
#include "json_spirit_error_position.h" |
|||
|
|||
//#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread
|
|||
|
|||
#include <boost/bind.hpp> |
|||
#include <boost/function.hpp> |
|||
#include <boost/version.hpp> |
|||
|
|||
#if BOOST_VERSION >= 103800 |
|||
#include <boost/spirit/include/classic_core.hpp> |
|||
#include <boost/spirit/include/classic_confix.hpp> |
|||
#include <boost/spirit/include/classic_escape_char.hpp> |
|||
#include <boost/spirit/include/classic_multi_pass.hpp> |
|||
#include <boost/spirit/include/classic_position_iterator.hpp> |
|||
#define spirit_namespace boost::spirit::classic |
|||
#else |
|||
#include <boost/spirit/core.hpp> |
|||
#include <boost/spirit/utility/confix.hpp> |
|||
#include <boost/spirit/utility/escape_char.hpp> |
|||
#include <boost/spirit/iterator/multi_pass.hpp> |
|||
#include <boost/spirit/iterator/position_iterator.hpp> |
|||
#define spirit_namespace boost::spirit |
|||
#endif |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >(); |
|||
const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >(); |
|||
|
|||
template< class Iter_type > |
|||
bool is_eq( Iter_type first, Iter_type last, const char* c_str ) |
|||
{ |
|||
for( Iter_type i = first; i != last; ++i, ++c_str ) |
|||
{ |
|||
if( *c_str == 0 ) return false; |
|||
|
|||
if( *i != *c_str ) return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
template< class Char_type > |
|||
Char_type hex_to_num( const Char_type c ) |
|||
{ |
|||
if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0'; |
|||
if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10; |
|||
if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10; |
|||
return 0; |
|||
} |
|||
|
|||
template< class Char_type, class Iter_type > |
|||
Char_type hex_str_to_char( Iter_type& begin ) |
|||
{ |
|||
const Char_type c1( *( ++begin ) ); |
|||
const Char_type c2( *( ++begin ) ); |
|||
|
|||
return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 ); |
|||
} |
|||
|
|||
template< class Char_type, class Iter_type > |
|||
Char_type unicode_str_to_char( Iter_type& begin ) |
|||
{ |
|||
const Char_type c1( *( ++begin ) ); |
|||
const Char_type c2( *( ++begin ) ); |
|||
const Char_type c3( *( ++begin ) ); |
|||
const Char_type c4( *( ++begin ) ); |
|||
|
|||
return ( hex_to_num( c1 ) << 12 ) + |
|||
( hex_to_num( c2 ) << 8 ) + |
|||
( hex_to_num( c3 ) << 4 ) + |
|||
hex_to_num( c4 ); |
|||
} |
|||
|
|||
template< class String_type > |
|||
void append_esc_char_and_incr_iter( String_type& s, |
|||
typename String_type::const_iterator& begin, |
|||
typename String_type::const_iterator end ) |
|||
{ |
|||
typedef typename String_type::value_type Char_type; |
|||
|
|||
const Char_type c2( *begin ); |
|||
|
|||
switch( c2 ) |
|||
{ |
|||
case 't': s += '\t'; break; |
|||
case 'b': s += '\b'; break; |
|||
case 'f': s += '\f'; break; |
|||
case 'n': s += '\n'; break; |
|||
case 'r': s += '\r'; break; |
|||
case '\\': s += '\\'; break; |
|||
case '/': s += '/'; break; |
|||
case '"': s += '"'; break; |
|||
case 'x': |
|||
{ |
|||
if( end - begin >= 3 ) // expecting "xHH..."
|
|||
{ |
|||
s += hex_str_to_char< Char_type >( begin ); |
|||
} |
|||
break; |
|||
} |
|||
case 'u': |
|||
{ |
|||
if( end - begin >= 5 ) // expecting "uHHHH..."
|
|||
{ |
|||
s += unicode_str_to_char< Char_type >( begin ); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
template< class String_type > |
|||
String_type substitute_esc_chars( typename String_type::const_iterator begin, |
|||
typename String_type::const_iterator end ) |
|||
{ |
|||
typedef typename String_type::const_iterator Iter_type; |
|||
|
|||
if( end - begin < 2 ) return String_type( begin, end ); |
|||
|
|||
String_type result; |
|||
|
|||
result.reserve( end - begin ); |
|||
|
|||
const Iter_type end_minus_1( end - 1 ); |
|||
|
|||
Iter_type substr_start = begin; |
|||
Iter_type i = begin; |
|||
|
|||
for( ; i < end_minus_1; ++i ) |
|||
{ |
|||
if( *i == '\\' ) |
|||
{ |
|||
result.append( substr_start, i ); |
|||
|
|||
++i; // skip the '\'
|
|||
|
|||
append_esc_char_and_incr_iter( result, i, end ); |
|||
|
|||
substr_start = i + 1; |
|||
} |
|||
} |
|||
|
|||
result.append( substr_start, end ); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template< class String_type > |
|||
String_type get_str_( typename String_type::const_iterator begin, |
|||
typename String_type::const_iterator end ) |
|||
{ |
|||
assert( end - begin >= 2 ); |
|||
|
|||
typedef typename String_type::const_iterator Iter_type; |
|||
|
|||
Iter_type str_without_quotes( ++begin ); |
|||
Iter_type end_without_quotes( --end ); |
|||
|
|||
return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes ); |
|||
} |
|||
|
|||
inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end ) |
|||
{ |
|||
return get_str_< std::string >( begin, end ); |
|||
} |
|||
|
|||
inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end ) |
|||
{ |
|||
return get_str_< std::wstring >( begin, end ); |
|||
} |
|||
|
|||
template< class String_type, class Iter_type > |
|||
String_type get_str( Iter_type begin, Iter_type end ) |
|||
{ |
|||
const String_type tmp( begin, end ); // convert multipass iterators to string iterators
|
|||
|
|||
return get_str( tmp.begin(), tmp.end() ); |
|||
} |
|||
|
|||
// this class's methods get called by the spirit parse resulting
|
|||
// in the creation of a JSON object or array
|
|||
//
|
|||
// NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator
|
|||
//
|
|||
template< class Value_type, class Iter_type > |
|||
class Semantic_actions |
|||
{ |
|||
public: |
|||
|
|||
typedef typename Value_type::Config_type Config_type; |
|||
typedef typename Config_type::String_type String_type; |
|||
typedef typename Config_type::Object_type Object_type; |
|||
typedef typename Config_type::Array_type Array_type; |
|||
typedef typename String_type::value_type Char_type; |
|||
|
|||
Semantic_actions( Value_type& value ) |
|||
: value_( value ) |
|||
, current_p_( 0 ) |
|||
{ |
|||
} |
|||
|
|||
void begin_obj( Char_type c ) |
|||
{ |
|||
assert( c == '{' ); |
|||
|
|||
begin_compound< Object_type >(); |
|||
} |
|||
|
|||
void end_obj( Char_type c ) |
|||
{ |
|||
assert( c == '}' ); |
|||
|
|||
end_compound(); |
|||
} |
|||
|
|||
void begin_array( Char_type c ) |
|||
{ |
|||
assert( c == '[' ); |
|||
|
|||
begin_compound< Array_type >(); |
|||
} |
|||
|
|||
void end_array( Char_type c ) |
|||
{ |
|||
assert( c == ']' ); |
|||
|
|||
end_compound(); |
|||
} |
|||
|
|||
void new_name( Iter_type begin, Iter_type end ) |
|||
{ |
|||
assert( current_p_->type() == obj_type ); |
|||
|
|||
name_ = get_str< String_type >( begin, end ); |
|||
} |
|||
|
|||
void new_str( Iter_type begin, Iter_type end ) |
|||
{ |
|||
add_to_current( get_str< String_type >( begin, end ) ); |
|||
} |
|||
|
|||
void new_true( Iter_type begin, Iter_type end ) |
|||
{ |
|||
assert( is_eq( begin, end, "true" ) ); |
|||
|
|||
add_to_current( true ); |
|||
} |
|||
|
|||
void new_false( Iter_type begin, Iter_type end ) |
|||
{ |
|||
assert( is_eq( begin, end, "false" ) ); |
|||
|
|||
add_to_current( false ); |
|||
} |
|||
|
|||
void new_null( Iter_type begin, Iter_type end ) |
|||
{ |
|||
assert( is_eq( begin, end, "null" ) ); |
|||
|
|||
add_to_current( Value_type() ); |
|||
} |
|||
|
|||
void new_int( boost::int64_t i ) |
|||
{ |
|||
add_to_current( i ); |
|||
} |
|||
|
|||
void new_uint64( boost::uint64_t ui ) |
|||
{ |
|||
add_to_current( ui ); |
|||
} |
|||
|
|||
void new_real( double d ) |
|||
{ |
|||
add_to_current( d ); |
|||
} |
|||
|
|||
private: |
|||
|
|||
Semantic_actions& operator=( const Semantic_actions& ); |
|||
// to prevent "assignment operator could not be generated" warning
|
|||
|
|||
Value_type* add_first( const Value_type& value ) |
|||
{ |
|||
assert( current_p_ == 0 ); |
|||
|
|||
value_ = value; |
|||
current_p_ = &value_; |
|||
return current_p_; |
|||
} |
|||
|
|||
template< class Array_or_obj > |
|||
void begin_compound() |
|||
{ |
|||
if( current_p_ == 0 ) |
|||
{ |
|||
add_first( Array_or_obj() ); |
|||
} |
|||
else |
|||
{ |
|||
stack_.push_back( current_p_ ); |
|||
|
|||
Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place
|
|||
|
|||
current_p_ = add_to_current( new_array_or_obj ); |
|||
} |
|||
} |
|||
|
|||
void end_compound() |
|||
{ |
|||
if( current_p_ != &value_ ) |
|||
{ |
|||
current_p_ = stack_.back(); |
|||
|
|||
stack_.pop_back(); |
|||
} |
|||
} |
|||
|
|||
Value_type* add_to_current( const Value_type& value ) |
|||
{ |
|||
if( current_p_ == 0 ) |
|||
{ |
|||
return add_first( value ); |
|||
} |
|||
else if( current_p_->type() == array_type ) |
|||
{ |
|||
current_p_->get_array().push_back( value ); |
|||
|
|||
return ¤t_p_->get_array().back(); |
|||
} |
|||
|
|||
assert( current_p_->type() == obj_type ); |
|||
|
|||
return &Config_type::add( current_p_->get_obj(), name_, value ); |
|||
} |
|||
|
|||
Value_type& value_; // this is the object or array that is being created
|
|||
Value_type* current_p_; // the child object or array that is currently being constructed
|
|||
|
|||
std::vector< Value_type* > stack_; // previous child objects and arrays
|
|||
|
|||
String_type name_; // of current name/value pair
|
|||
}; |
|||
|
|||
template< typename Iter_type > |
|||
void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason ) |
|||
{ |
|||
throw Error_position( i.get_position().line, i.get_position().column, reason ); |
|||
} |
|||
|
|||
template< typename Iter_type > |
|||
void throw_error( Iter_type i, const std::string& reason ) |
|||
{ |
|||
throw reason; |
|||
} |
|||
|
|||
// the spirit grammer
|
|||
//
|
|||
template< class Value_type, class Iter_type > |
|||
class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > > |
|||
{ |
|||
public: |
|||
|
|||
typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t; |
|||
|
|||
Json_grammer( Semantic_actions_t& semantic_actions ) |
|||
: actions_( semantic_actions ) |
|||
{ |
|||
} |
|||
|
|||
static void throw_not_value( Iter_type begin, Iter_type end ) |
|||
{ |
|||
throw_error( begin, "not a value" ); |
|||
} |
|||
|
|||
static void throw_not_array( Iter_type begin, Iter_type end ) |
|||
{ |
|||
throw_error( begin, "not an array" ); |
|||
} |
|||
|
|||
static void throw_not_object( Iter_type begin, Iter_type end ) |
|||
{ |
|||
throw_error( begin, "not an object" ); |
|||
} |
|||
|
|||
static void throw_not_pair( Iter_type begin, Iter_type end ) |
|||
{ |
|||
throw_error( begin, "not a pair" ); |
|||
} |
|||
|
|||
static void throw_not_colon( Iter_type begin, Iter_type end ) |
|||
{ |
|||
throw_error( begin, "no colon in pair" ); |
|||
} |
|||
|
|||
static void throw_not_string( Iter_type begin, Iter_type end ) |
|||
{ |
|||
throw_error( begin, "not a string" ); |
|||
} |
|||
|
|||
template< typename ScannerT > |
|||
class definition |
|||
{ |
|||
public: |
|||
|
|||
definition( const Json_grammer& self ) |
|||
{ |
|||
using namespace spirit_namespace; |
|||
|
|||
typedef typename Value_type::String_type::value_type Char_type; |
|||
|
|||
// first we convert the semantic action class methods to functors with the
|
|||
// parameter signature expected by spirit
|
|||
|
|||
typedef boost::function< void( Char_type ) > Char_action; |
|||
typedef boost::function< void( Iter_type, Iter_type ) > Str_action; |
|||
typedef boost::function< void( double ) > Real_action; |
|||
typedef boost::function< void( boost::int64_t ) > Int_action; |
|||
typedef boost::function< void( boost::uint64_t ) > Uint64_action; |
|||
|
|||
Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); |
|||
Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); |
|||
Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) ); |
|||
Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) ); |
|||
Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) ); |
|||
Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) ); |
|||
Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) ); |
|||
Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) ); |
|||
Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) ); |
|||
Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) ); |
|||
Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) ); |
|||
Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) ); |
|||
|
|||
// actual grammer
|
|||
|
|||
json_ |
|||
= value_ | eps_p[ &throw_not_value ] |
|||
; |
|||
|
|||
value_ |
|||
= string_[ new_str ] |
|||
| number_ |
|||
| object_ |
|||
| array_ |
|||
| str_p( "true" ) [ new_true ] |
|||
| str_p( "false" )[ new_false ] |
|||
| str_p( "null" ) [ new_null ] |
|||
; |
|||
|
|||
object_ |
|||
= ch_p('{')[ begin_obj ] |
|||
>> !members_ |
|||
>> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] ) |
|||
; |
|||
|
|||
members_ |
|||
= pair_ >> *( ',' >> pair_ ) |
|||
; |
|||
|
|||
pair_ |
|||
= string_[ new_name ] |
|||
>> ( ':' | eps_p[ &throw_not_colon ] ) |
|||
>> ( value_ | eps_p[ &throw_not_value ] ) |
|||
; |
|||
|
|||
array_ |
|||
= ch_p('[')[ begin_array ] |
|||
>> !elements_ |
|||
>> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] ) |
|||
; |
|||
|
|||
elements_ |
|||
= value_ >> *( ',' >> value_ ) |
|||
; |
|||
|
|||
string_ |
|||
= lexeme_d // this causes white space inside a string to be retained
|
|||
[ |
|||
confix_p |
|||
( |
|||
'"', |
|||
*lex_escape_ch_p, |
|||
'"' |
|||
) |
|||
] |
|||
; |
|||
|
|||
number_ |
|||
= strict_real_p[ new_real ] |
|||
| int64_p [ new_int ] |
|||
| uint64_p [ new_uint64 ] |
|||
; |
|||
} |
|||
|
|||
spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_; |
|||
|
|||
const spirit_namespace::rule< ScannerT >& start() const { return json_; } |
|||
}; |
|||
|
|||
private: |
|||
|
|||
Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning
|
|||
|
|||
Semantic_actions_t& actions_; |
|||
}; |
|||
|
|||
template< class Iter_type, class Value_type > |
|||
Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) |
|||
{ |
|||
Semantic_actions< Value_type, Iter_type > semantic_actions( value ); |
|||
|
|||
const spirit_namespace::parse_info< Iter_type > info = |
|||
spirit_namespace::parse( begin, end, |
|||
Json_grammer< Value_type, Iter_type >( semantic_actions ), |
|||
spirit_namespace::space_p ); |
|||
|
|||
if( !info.hit ) |
|||
{ |
|||
assert( false ); // in theory exception should already have been thrown
|
|||
throw_error( info.stop, "error" ); |
|||
} |
|||
|
|||
return info.stop; |
|||
} |
|||
|
|||
template< class Iter_type, class Value_type > |
|||
void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) |
|||
{ |
|||
typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t; |
|||
|
|||
const Posn_iter_t posn_begin( begin, end ); |
|||
const Posn_iter_t posn_end( end, end ); |
|||
|
|||
read_range_or_throw( posn_begin, posn_end, value ); |
|||
} |
|||
|
|||
template< class Iter_type, class Value_type > |
|||
bool read_range( Iter_type& begin, Iter_type end, Value_type& value ) |
|||
{ |
|||
try |
|||
{ |
|||
begin = read_range_or_throw( begin, end, value ); |
|||
|
|||
return true; |
|||
} |
|||
catch( ... ) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
template< class String_type, class Value_type > |
|||
void read_string_or_throw( const String_type& s, Value_type& value ) |
|||
{ |
|||
add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value ); |
|||
} |
|||
|
|||
template< class String_type, class Value_type > |
|||
bool read_string( const String_type& s, Value_type& value ) |
|||
{ |
|||
typename String_type::const_iterator begin = s.begin(); |
|||
|
|||
return read_range( begin, s.end(), value ); |
|||
} |
|||
|
|||
template< class Istream_type > |
|||
struct Multi_pass_iters |
|||
{ |
|||
typedef typename Istream_type::char_type Char_type; |
|||
typedef std::istream_iterator< Char_type, Char_type > istream_iter; |
|||
typedef spirit_namespace::multi_pass< istream_iter > Mp_iter; |
|||
|
|||
Multi_pass_iters( Istream_type& is ) |
|||
{ |
|||
is.unsetf( std::ios::skipws ); |
|||
|
|||
begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) ); |
|||
end_ = spirit_namespace::make_multi_pass( istream_iter() ); |
|||
} |
|||
|
|||
Mp_iter begin_; |
|||
Mp_iter end_; |
|||
}; |
|||
|
|||
template< class Istream_type, class Value_type > |
|||
bool read_stream( Istream_type& is, Value_type& value ) |
|||
{ |
|||
Multi_pass_iters< Istream_type > mp_iters( is ); |
|||
|
|||
return read_range( mp_iters.begin_, mp_iters.end_, value ); |
|||
} |
|||
|
|||
template< class Istream_type, class Value_type > |
|||
void read_stream_or_throw( Istream_type& is, Value_type& value ) |
|||
{ |
|||
const Multi_pass_iters< Istream_type > mp_iters( is ); |
|||
|
|||
add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value ); |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,70 @@ |
|||
#ifndef JSON_SPIRIT_READ_STREAM |
|||
#define JSON_SPIRIT_READ_STREAM |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include "json_spirit_reader_template.h" |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
// these classes allows you to read multiple top level contiguous values from a stream,
|
|||
// the normal stream read functions have a bug that prevent multiple top level values
|
|||
// from being read unless they are separated by spaces
|
|||
|
|||
template< class Istream_type, class Value_type > |
|||
class Stream_reader |
|||
{ |
|||
public: |
|||
|
|||
Stream_reader( Istream_type& is ) |
|||
: iters_( is ) |
|||
{ |
|||
} |
|||
|
|||
bool read_next( Value_type& value ) |
|||
{ |
|||
return read_range( iters_.begin_, iters_.end_, value ); |
|||
} |
|||
|
|||
private: |
|||
|
|||
typedef Multi_pass_iters< Istream_type > Mp_iters; |
|||
|
|||
Mp_iters iters_; |
|||
}; |
|||
|
|||
template< class Istream_type, class Value_type > |
|||
class Stream_reader_thrower |
|||
{ |
|||
public: |
|||
|
|||
Stream_reader_thrower( Istream_type& is ) |
|||
: iters_( is ) |
|||
, posn_begin_( iters_.begin_, iters_.end_ ) |
|||
, posn_end_( iters_.end_, iters_.end_ ) |
|||
{ |
|||
} |
|||
|
|||
void read_next( Value_type& value ) |
|||
{ |
|||
posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value ); |
|||
} |
|||
|
|||
private: |
|||
|
|||
typedef Multi_pass_iters< Istream_type > Mp_iters; |
|||
typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t; |
|||
|
|||
Mp_iters iters_; |
|||
Posn_iter_t posn_begin_, posn_end_; |
|||
}; |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,61 @@ |
|||
#ifndef JSON_SPIRIT_UTILS |
|||
#define JSON_SPIRIT_UTILS |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include "json_spirit_value.h" |
|||
#include <map> |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
template< class Obj_t, class Map_t > |
|||
void obj_to_map( const Obj_t& obj, Map_t& mp_obj ) |
|||
{ |
|||
mp_obj.clear(); |
|||
|
|||
for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i ) |
|||
{ |
|||
mp_obj[ i->name_ ] = i->value_; |
|||
} |
|||
} |
|||
|
|||
template< class Obj_t, class Map_t > |
|||
void map_to_obj( const Map_t& mp_obj, Obj_t& obj ) |
|||
{ |
|||
obj.clear(); |
|||
|
|||
for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i ) |
|||
{ |
|||
obj.push_back( typename Obj_t::value_type( i->first, i->second ) ); |
|||
} |
|||
} |
|||
|
|||
typedef std::map< std::string, Value > Mapped_obj; |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
typedef std::map< std::wstring, wValue > wMapped_obj; |
|||
#endif |
|||
|
|||
template< class Object_type, class String_type > |
|||
const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name ) |
|||
{ |
|||
for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i ) |
|||
{ |
|||
if( i->name_ == name ) |
|||
{ |
|||
return i->value_; |
|||
} |
|||
} |
|||
|
|||
return Object_type::value_type::Value_type::null; |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,534 @@ |
|||
#ifndef JSON_SPIRIT_VALUE |
|||
#define JSON_SPIRIT_VALUE |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include <vector> |
|||
#include <map> |
|||
#include <string> |
|||
#include <cassert> |
|||
#include <sstream> |
|||
#include <stdexcept> |
|||
#include <boost/config.hpp> |
|||
#include <boost/cstdint.hpp> |
|||
#include <boost/shared_ptr.hpp> |
|||
#include <boost/variant.hpp> |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type }; |
|||
static const char* Value_type_name[]={"obj", "array", "str", "bool", "int", "real", "null"}; |
|||
|
|||
template< class Config > // Config determines whether the value uses std::string or std::wstring and
|
|||
// whether JSON Objects are represented as vectors or maps
|
|||
class Value_impl |
|||
{ |
|||
public: |
|||
|
|||
typedef Config Config_type; |
|||
typedef typename Config::String_type String_type; |
|||
typedef typename Config::Object_type Object; |
|||
typedef typename Config::Array_type Array; |
|||
typedef typename String_type::const_pointer Const_str_ptr; // eg const char*
|
|||
|
|||
Value_impl(); // creates null value
|
|||
Value_impl( Const_str_ptr value ); |
|||
Value_impl( const String_type& value ); |
|||
Value_impl( const Object& value ); |
|||
Value_impl( const Array& value ); |
|||
Value_impl( bool value ); |
|||
Value_impl( int value ); |
|||
Value_impl( boost::int64_t value ); |
|||
Value_impl( boost::uint64_t value ); |
|||
Value_impl( double value ); |
|||
|
|||
Value_impl( const Value_impl& other ); |
|||
|
|||
bool operator==( const Value_impl& lhs ) const; |
|||
|
|||
Value_impl& operator=( const Value_impl& lhs ); |
|||
|
|||
Value_type type() const; |
|||
|
|||
bool is_uint64() const; |
|||
bool is_null() const; |
|||
|
|||
const String_type& get_str() const; |
|||
const Object& get_obj() const; |
|||
const Array& get_array() const; |
|||
bool get_bool() const; |
|||
int get_int() const; |
|||
boost::int64_t get_int64() const; |
|||
boost::uint64_t get_uint64() const; |
|||
double get_real() const; |
|||
|
|||
Object& get_obj(); |
|||
Array& get_array(); |
|||
|
|||
template< typename T > T get_value() const; // example usage: int i = value.get_value< int >();
|
|||
// or double d = value.get_value< double >();
|
|||
|
|||
static const Value_impl null; |
|||
|
|||
private: |
|||
|
|||
void check_type( const Value_type vtype ) const; |
|||
|
|||
typedef boost::variant< String_type, |
|||
boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, |
|||
bool, boost::int64_t, double > Variant; |
|||
|
|||
Value_type type_; |
|||
Variant v_; |
|||
bool is_uint64_; |
|||
}; |
|||
|
|||
// vector objects
|
|||
|
|||
template< class Config > |
|||
struct Pair_impl |
|||
{ |
|||
typedef typename Config::String_type String_type; |
|||
typedef typename Config::Value_type Value_type; |
|||
|
|||
Pair_impl( const String_type& name, const Value_type& value ); |
|||
|
|||
bool operator==( const Pair_impl& lhs ) const; |
|||
|
|||
String_type name_; |
|||
Value_type value_; |
|||
}; |
|||
|
|||
template< class String > |
|||
struct Config_vector |
|||
{ |
|||
typedef String String_type; |
|||
typedef Value_impl< Config_vector > Value_type; |
|||
typedef Pair_impl < Config_vector > Pair_type; |
|||
typedef std::vector< Value_type > Array_type; |
|||
typedef std::vector< Pair_type > Object_type; |
|||
|
|||
static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) |
|||
{ |
|||
obj.push_back( Pair_type( name , value ) ); |
|||
|
|||
return obj.back().value_; |
|||
} |
|||
|
|||
static String_type get_name( const Pair_type& pair ) |
|||
{ |
|||
return pair.name_; |
|||
} |
|||
|
|||
static Value_type get_value( const Pair_type& pair ) |
|||
{ |
|||
return pair.value_; |
|||
} |
|||
}; |
|||
|
|||
// typedefs for ASCII
|
|||
|
|||
typedef Config_vector< std::string > Config; |
|||
|
|||
typedef Config::Value_type Value; |
|||
typedef Config::Pair_type Pair; |
|||
typedef Config::Object_type Object; |
|||
typedef Config::Array_type Array; |
|||
|
|||
// typedefs for Unicode
|
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
typedef Config_vector< std::wstring > wConfig; |
|||
|
|||
typedef wConfig::Value_type wValue; |
|||
typedef wConfig::Pair_type wPair; |
|||
typedef wConfig::Object_type wObject; |
|||
typedef wConfig::Array_type wArray; |
|||
#endif |
|||
|
|||
// map objects
|
|||
|
|||
template< class String > |
|||
struct Config_map |
|||
{ |
|||
typedef String String_type; |
|||
typedef Value_impl< Config_map > Value_type; |
|||
typedef std::vector< Value_type > Array_type; |
|||
typedef std::map< String_type, Value_type > Object_type; |
|||
typedef typename Object_type::value_type Pair_type; |
|||
|
|||
static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value ) |
|||
{ |
|||
return obj[ name ] = value; |
|||
} |
|||
|
|||
static String_type get_name( const Pair_type& pair ) |
|||
{ |
|||
return pair.first; |
|||
} |
|||
|
|||
static Value_type get_value( const Pair_type& pair ) |
|||
{ |
|||
return pair.second; |
|||
} |
|||
}; |
|||
|
|||
// typedefs for ASCII
|
|||
|
|||
typedef Config_map< std::string > mConfig; |
|||
|
|||
typedef mConfig::Value_type mValue; |
|||
typedef mConfig::Object_type mObject; |
|||
typedef mConfig::Array_type mArray; |
|||
|
|||
// typedefs for Unicode
|
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
typedef Config_map< std::wstring > wmConfig; |
|||
|
|||
typedef wmConfig::Value_type wmValue; |
|||
typedef wmConfig::Object_type wmObject; |
|||
typedef wmConfig::Array_type wmArray; |
|||
|
|||
#endif |
|||
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////
|
|||
//
|
|||
// implementation
|
|||
|
|||
template< class Config > |
|||
const Value_impl< Config > Value_impl< Config >::null; |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl() |
|||
: type_( null_type ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( const Const_str_ptr value ) |
|||
: type_( str_type ) |
|||
, v_( String_type( value ) ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( const String_type& value ) |
|||
: type_( str_type ) |
|||
, v_( value ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( const Object& value ) |
|||
: type_( obj_type ) |
|||
, v_( value ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( const Array& value ) |
|||
: type_( array_type ) |
|||
, v_( value ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( bool value ) |
|||
: type_( bool_type ) |
|||
, v_( value ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( int value ) |
|||
: type_( int_type ) |
|||
, v_( static_cast< boost::int64_t >( value ) ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( boost::int64_t value ) |
|||
: type_( int_type ) |
|||
, v_( value ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( boost::uint64_t value ) |
|||
: type_( int_type ) |
|||
, v_( static_cast< boost::int64_t >( value ) ) |
|||
, is_uint64_( true ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( double value ) |
|||
: type_( real_type ) |
|||
, v_( value ) |
|||
, is_uint64_( false ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >::Value_impl( const Value_impl< Config >& other ) |
|||
: type_( other.type() ) |
|||
, v_( other.v_ ) |
|||
, is_uint64_( other.is_uint64_ ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs ) |
|||
{ |
|||
Value_impl tmp( lhs ); |
|||
|
|||
std::swap( type_, tmp.type_ ); |
|||
std::swap( v_, tmp.v_ ); |
|||
std::swap( is_uint64_, tmp.is_uint64_ ); |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
template< class Config > |
|||
bool Value_impl< Config >::operator==( const Value_impl& lhs ) const |
|||
{ |
|||
if( this == &lhs ) return true; |
|||
|
|||
if( type() != lhs.type() ) return false; |
|||
|
|||
return v_ == lhs.v_; |
|||
} |
|||
|
|||
template< class Config > |
|||
Value_type Value_impl< Config >::type() const |
|||
{ |
|||
return type_; |
|||
} |
|||
|
|||
template< class Config > |
|||
bool Value_impl< Config >::is_uint64() const |
|||
{ |
|||
return is_uint64_; |
|||
} |
|||
|
|||
template< class Config > |
|||
bool Value_impl< Config >::is_null() const |
|||
{ |
|||
return type() == null_type; |
|||
} |
|||
|
|||
template< class Config > |
|||
void Value_impl< Config >::check_type( const Value_type vtype ) const |
|||
{ |
|||
if( type() != vtype ) |
|||
{ |
|||
std::ostringstream os; |
|||
|
|||
///// Bitcoin: Tell the types by name instead of by number
|
|||
os << "value is type " << Value_type_name[type()] << ", expected " << Value_type_name[vtype]; |
|||
|
|||
throw std::runtime_error( os.str() ); |
|||
} |
|||
} |
|||
|
|||
template< class Config > |
|||
const typename Config::String_type& Value_impl< Config >::get_str() const |
|||
{ |
|||
check_type( str_type ); |
|||
|
|||
return *boost::get< String_type >( &v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const |
|||
{ |
|||
check_type( obj_type ); |
|||
|
|||
return *boost::get< Object >( &v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const |
|||
{ |
|||
check_type( array_type ); |
|||
|
|||
return *boost::get< Array >( &v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
bool Value_impl< Config >::get_bool() const |
|||
{ |
|||
check_type( bool_type ); |
|||
|
|||
return boost::get< bool >( v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
int Value_impl< Config >::get_int() const |
|||
{ |
|||
check_type( int_type ); |
|||
|
|||
return static_cast< int >( get_int64() ); |
|||
} |
|||
|
|||
template< class Config > |
|||
boost::int64_t Value_impl< Config >::get_int64() const |
|||
{ |
|||
check_type( int_type ); |
|||
|
|||
return boost::get< boost::int64_t >( v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
boost::uint64_t Value_impl< Config >::get_uint64() const |
|||
{ |
|||
check_type( int_type ); |
|||
|
|||
return static_cast< boost::uint64_t >( get_int64() ); |
|||
} |
|||
|
|||
template< class Config > |
|||
double Value_impl< Config >::get_real() const |
|||
{ |
|||
if( type() == int_type ) |
|||
{ |
|||
return is_uint64() ? static_cast< double >( get_uint64() ) |
|||
: static_cast< double >( get_int64() ); |
|||
} |
|||
|
|||
check_type( real_type ); |
|||
|
|||
return boost::get< double >( v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() |
|||
{ |
|||
check_type( obj_type ); |
|||
|
|||
return *boost::get< Object >( &v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
typename Value_impl< Config >::Array& Value_impl< Config >::get_array() |
|||
{ |
|||
check_type( array_type ); |
|||
|
|||
return *boost::get< Array >( &v_ ); |
|||
} |
|||
|
|||
template< class Config > |
|||
Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value ) |
|||
: name_( name ) |
|||
, value_( value ) |
|||
{ |
|||
} |
|||
|
|||
template< class Config > |
|||
bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const |
|||
{ |
|||
if( this == &lhs ) return true; |
|||
|
|||
return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ ); |
|||
} |
|||
|
|||
// converts a C string, ie. 8 bit char array, to a string object
|
|||
//
|
|||
template < class String_type > |
|||
String_type to_str( const char* c_str ) |
|||
{ |
|||
String_type result; |
|||
|
|||
for( const char* p = c_str; *p != 0; ++p ) |
|||
{ |
|||
result += *p; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
//
|
|||
|
|||
namespace internal_ |
|||
{ |
|||
template< typename T > |
|||
struct Type_to_type |
|||
{ |
|||
}; |
|||
|
|||
template< class Value > |
|||
int get_value( const Value& value, Type_to_type< int > ) |
|||
{ |
|||
return value.get_int(); |
|||
} |
|||
|
|||
template< class Value > |
|||
boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > ) |
|||
{ |
|||
return value.get_int64(); |
|||
} |
|||
|
|||
template< class Value > |
|||
boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > ) |
|||
{ |
|||
return value.get_uint64(); |
|||
} |
|||
|
|||
template< class Value > |
|||
double get_value( const Value& value, Type_to_type< double > ) |
|||
{ |
|||
return value.get_real(); |
|||
} |
|||
|
|||
template< class Value > |
|||
typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > ) |
|||
{ |
|||
return value.get_str(); |
|||
} |
|||
|
|||
template< class Value > |
|||
typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > ) |
|||
{ |
|||
return value.get_array(); |
|||
} |
|||
|
|||
template< class Value > |
|||
typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > ) |
|||
{ |
|||
return value.get_obj(); |
|||
} |
|||
|
|||
template< class Value > |
|||
bool get_value( const Value& value, Type_to_type< bool > ) |
|||
{ |
|||
return value.get_bool(); |
|||
} |
|||
} |
|||
|
|||
template< class Config > |
|||
template< typename T > |
|||
T Value_impl< Config >::get_value() const |
|||
{ |
|||
return internal_::get_value( *this, internal_::Type_to_type< T >() ); |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,50 @@ |
|||
#ifndef JSON_SPIRIT_WRITER |
|||
#define JSON_SPIRIT_WRITER |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|||
# pragma once |
|||
#endif |
|||
|
|||
#include "json_spirit_value.h" |
|||
#include <iostream> |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
// functions to convert JSON Values to text,
|
|||
// the "formatted" versions add whitespace to format the output nicely
|
|||
|
|||
void write ( const Value& value, std::ostream& os ); |
|||
void write_formatted( const Value& value, std::ostream& os ); |
|||
std::string write ( const Value& value ); |
|||
std::string write_formatted( const Value& value ); |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
void write ( const wValue& value, std::wostream& os ); |
|||
void write_formatted( const wValue& value, std::wostream& os ); |
|||
std::wstring write ( const wValue& value ); |
|||
std::wstring write_formatted( const wValue& value ); |
|||
|
|||
#endif |
|||
|
|||
void write ( const mValue& value, std::ostream& os ); |
|||
void write_formatted( const mValue& value, std::ostream& os ); |
|||
std::string write ( const mValue& value ); |
|||
std::string write_formatted( const mValue& value ); |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
void write ( const wmValue& value, std::wostream& os ); |
|||
void write_formatted( const wmValue& value, std::wostream& os ); |
|||
std::wstring write ( const wmValue& value ); |
|||
std::wstring write_formatted( const wmValue& value ); |
|||
|
|||
#endif |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,248 @@ |
|||
#ifndef JSON_SPIRIT_WRITER_TEMPLATE |
|||
#define JSON_SPIRIT_WRITER_TEMPLATE |
|||
|
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#include "json_spirit_value.h" |
|||
|
|||
#include <cassert> |
|||
#include <sstream> |
|||
#include <iomanip> |
|||
|
|||
namespace json_spirit |
|||
{ |
|||
inline char to_hex_char( unsigned int c ) |
|||
{ |
|||
assert( c <= 0xF ); |
|||
|
|||
const char ch = static_cast< char >( c ); |
|||
|
|||
if( ch < 10 ) return '0' + ch; |
|||
|
|||
return 'A' - 10 + ch; |
|||
} |
|||
|
|||
template< class String_type > |
|||
String_type non_printable_to_string( unsigned int c ) |
|||
{ |
|||
typedef typename String_type::value_type Char_type; |
|||
|
|||
String_type result( 6, '\\' ); |
|||
|
|||
result[1] = 'u'; |
|||
|
|||
result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4; |
|||
result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4; |
|||
result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4; |
|||
result[ 2 ] = to_hex_char( c & 0x000F ); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template< typename Char_type, class String_type > |
|||
bool add_esc_char( Char_type c, String_type& s ) |
|||
{ |
|||
switch( c ) |
|||
{ |
|||
case '"': s += to_str< String_type >( "\\\"" ); return true; |
|||
case '\\': s += to_str< String_type >( "\\\\" ); return true; |
|||
case '\b': s += to_str< String_type >( "\\b" ); return true; |
|||
case '\f': s += to_str< String_type >( "\\f" ); return true; |
|||
case '\n': s += to_str< String_type >( "\\n" ); return true; |
|||
case '\r': s += to_str< String_type >( "\\r" ); return true; |
|||
case '\t': s += to_str< String_type >( "\\t" ); return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template< class String_type > |
|||
String_type add_esc_chars( const String_type& s ) |
|||
{ |
|||
typedef typename String_type::const_iterator Iter_type; |
|||
typedef typename String_type::value_type Char_type; |
|||
|
|||
String_type result; |
|||
|
|||
const Iter_type end( s.end() ); |
|||
|
|||
for( Iter_type i = s.begin(); i != end; ++i ) |
|||
{ |
|||
const Char_type c( *i ); |
|||
|
|||
if( add_esc_char( c, result ) ) continue; |
|||
|
|||
const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c ); |
|||
|
|||
if( iswprint( unsigned_c ) ) |
|||
{ |
|||
result += c; |
|||
} |
|||
else |
|||
{ |
|||
result += non_printable_to_string< String_type >( unsigned_c ); |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
// this class generates the JSON text,
|
|||
// it keeps track of the indentation level etc.
|
|||
//
|
|||
template< class Value_type, class Ostream_type > |
|||
class Generator |
|||
{ |
|||
typedef typename Value_type::Config_type Config_type; |
|||
typedef typename Config_type::String_type String_type; |
|||
typedef typename Config_type::Object_type Object_type; |
|||
typedef typename Config_type::Array_type Array_type; |
|||
typedef typename String_type::value_type Char_type; |
|||
typedef typename Object_type::value_type Obj_member_type; |
|||
|
|||
public: |
|||
|
|||
Generator( const Value_type& value, Ostream_type& os, bool pretty ) |
|||
: os_( os ) |
|||
, indentation_level_( 0 ) |
|||
, pretty_( pretty ) |
|||
{ |
|||
output( value ); |
|||
} |
|||
|
|||
private: |
|||
|
|||
void output( const Value_type& value ) |
|||
{ |
|||
switch( value.type() ) |
|||
{ |
|||
case obj_type: output( value.get_obj() ); break; |
|||
case array_type: output( value.get_array() ); break; |
|||
case str_type: output( value.get_str() ); break; |
|||
case bool_type: output( value.get_bool() ); break; |
|||
case int_type: output_int( value ); break; |
|||
|
|||
/// Bitcoin: Added std::fixed and changed precision from 16 to 8
|
|||
case real_type: os_ << std::showpoint << std::fixed << std::setprecision(8) |
|||
<< value.get_real(); break; |
|||
|
|||
case null_type: os_ << "null"; break; |
|||
default: assert( false ); |
|||
} |
|||
} |
|||
|
|||
void output( const Object_type& obj ) |
|||
{ |
|||
output_array_or_obj( obj, '{', '}' ); |
|||
} |
|||
|
|||
void output( const Array_type& arr ) |
|||
{ |
|||
output_array_or_obj( arr, '[', ']' ); |
|||
} |
|||
|
|||
void output( const Obj_member_type& member ) |
|||
{ |
|||
output( Config_type::get_name( member ) ); space(); |
|||
os_ << ':'; space(); |
|||
output( Config_type::get_value( member ) ); |
|||
} |
|||
|
|||
void output_int( const Value_type& value ) |
|||
{ |
|||
if( value.is_uint64() ) |
|||
{ |
|||
os_ << value.get_uint64(); |
|||
} |
|||
else |
|||
{ |
|||
os_ << value.get_int64(); |
|||
} |
|||
} |
|||
|
|||
void output( const String_type& s ) |
|||
{ |
|||
os_ << '"' << add_esc_chars( s ) << '"'; |
|||
} |
|||
|
|||
void output( bool b ) |
|||
{ |
|||
os_ << to_str< String_type >( b ? "true" : "false" ); |
|||
} |
|||
|
|||
template< class T > |
|||
void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char ) |
|||
{ |
|||
os_ << start_char; new_line(); |
|||
|
|||
++indentation_level_; |
|||
|
|||
for( typename T::const_iterator i = t.begin(); i != t.end(); ++i ) |
|||
{ |
|||
indent(); output( *i ); |
|||
|
|||
typename T::const_iterator next = i; |
|||
|
|||
if( ++next != t.end()) |
|||
{ |
|||
os_ << ','; |
|||
} |
|||
|
|||
new_line(); |
|||
} |
|||
|
|||
--indentation_level_; |
|||
|
|||
indent(); os_ << end_char; |
|||
} |
|||
|
|||
void indent() |
|||
{ |
|||
if( !pretty_ ) return; |
|||
|
|||
for( int i = 0; i < indentation_level_; ++i ) |
|||
{ |
|||
os_ << " "; |
|||
} |
|||
} |
|||
|
|||
void space() |
|||
{ |
|||
if( pretty_ ) os_ << ' '; |
|||
} |
|||
|
|||
void new_line() |
|||
{ |
|||
if( pretty_ ) os_ << '\n'; |
|||
} |
|||
|
|||
Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
|
|||
|
|||
Ostream_type& os_; |
|||
int indentation_level_; |
|||
bool pretty_; |
|||
}; |
|||
|
|||
template< class Value_type, class Ostream_type > |
|||
void write_stream( const Value_type& value, Ostream_type& os, bool pretty ) |
|||
{ |
|||
Generator< Value_type, Ostream_type >( value, os, pretty ); |
|||
} |
|||
|
|||
template< class Value_type > |
|||
typename Value_type::String_type write_string( const Value_type& value, bool pretty ) |
|||
{ |
|||
typedef typename Value_type::String_type::value_type Char_type; |
|||
|
|||
std::basic_ostringstream< Char_type > os; |
|||
|
|||
write_stream( value, os, pretty ); |
|||
|
|||
return os.str(); |
|||
} |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,137 @@ |
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#include "json/json_spirit_reader.h" |
|||
#include "json/json_spirit_reader_template.h" |
|||
|
|||
using namespace json_spirit; |
|||
|
|||
bool json_spirit::read( const std::string& s, Value& value ) |
|||
{ |
|||
return read_string( s, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( const std::string& s, Value& value ) |
|||
{ |
|||
read_string_or_throw( s, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::istream& is, Value& value ) |
|||
{ |
|||
return read_stream( is, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::istream& is, Value& value ) |
|||
{ |
|||
read_stream_or_throw( is, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) |
|||
{ |
|||
return read_range( begin, end, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ) |
|||
{ |
|||
begin = read_range_or_throw( begin, end, value ); |
|||
} |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
bool json_spirit::read( const std::wstring& s, wValue& value ) |
|||
{ |
|||
return read_string( s, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( const std::wstring& s, wValue& value ) |
|||
{ |
|||
read_string_or_throw( s, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::wistream& is, wValue& value ) |
|||
{ |
|||
return read_stream( is, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::wistream& is, wValue& value ) |
|||
{ |
|||
read_stream_or_throw( is, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) |
|||
{ |
|||
return read_range( begin, end, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ) |
|||
{ |
|||
begin = read_range_or_throw( begin, end, value ); |
|||
} |
|||
|
|||
#endif |
|||
|
|||
bool json_spirit::read( const std::string& s, mValue& value ) |
|||
{ |
|||
return read_string( s, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( const std::string& s, mValue& value ) |
|||
{ |
|||
read_string_or_throw( s, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::istream& is, mValue& value ) |
|||
{ |
|||
return read_stream( is, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::istream& is, mValue& value ) |
|||
{ |
|||
read_stream_or_throw( is, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) |
|||
{ |
|||
return read_range( begin, end, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ) |
|||
{ |
|||
begin = read_range_or_throw( begin, end, value ); |
|||
} |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
bool json_spirit::read( const std::wstring& s, wmValue& value ) |
|||
{ |
|||
return read_string( s, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( const std::wstring& s, wmValue& value ) |
|||
{ |
|||
read_string_or_throw( s, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::wistream& is, wmValue& value ) |
|||
{ |
|||
return read_stream( is, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::wistream& is, wmValue& value ) |
|||
{ |
|||
read_stream_or_throw( is, value ); |
|||
} |
|||
|
|||
bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) |
|||
{ |
|||
return read_range( begin, end, value ); |
|||
} |
|||
|
|||
void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ) |
|||
{ |
|||
begin = read_range_or_throw( begin, end, value ); |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,8 @@ |
|||
/* Copyright (c) 2007 John W Wilkinson
|
|||
|
|||
This source code can be used for any purpose as long as |
|||
this comment is retained. */ |
|||
|
|||
// json spirit version 2.00
|
|||
|
|||
#include "json/json_spirit_value.h" |
@ -0,0 +1,95 @@ |
|||
// Copyright John W. Wilkinson 2007 - 2009.
|
|||
// Distributed under the MIT License, see accompanying file LICENSE.txt
|
|||
|
|||
// json spirit version 4.03
|
|||
|
|||
#include "json/json_spirit_writer.h" |
|||
#include "json/json_spirit_writer_template.h" |
|||
|
|||
void json_spirit::write( const Value& value, std::ostream& os ) |
|||
{ |
|||
write_stream( value, os, false ); |
|||
} |
|||
|
|||
void json_spirit::write_formatted( const Value& value, std::ostream& os ) |
|||
{ |
|||
write_stream( value, os, true ); |
|||
} |
|||
|
|||
std::string json_spirit::write( const Value& value ) |
|||
{ |
|||
return write_string( value, false ); |
|||
} |
|||
|
|||
std::string json_spirit::write_formatted( const Value& value ) |
|||
{ |
|||
return write_string( value, true ); |
|||
} |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
void json_spirit::write( const wValue& value, std::wostream& os ) |
|||
{ |
|||
write_stream( value, os, false ); |
|||
} |
|||
|
|||
void json_spirit::write_formatted( const wValue& value, std::wostream& os ) |
|||
{ |
|||
write_stream( value, os, true ); |
|||
} |
|||
|
|||
std::wstring json_spirit::write( const wValue& value ) |
|||
{ |
|||
return write_string( value, false ); |
|||
} |
|||
|
|||
std::wstring json_spirit::write_formatted( const wValue& value ) |
|||
{ |
|||
return write_string( value, true ); |
|||
} |
|||
|
|||
#endif |
|||
|
|||
void json_spirit::write( const mValue& value, std::ostream& os ) |
|||
{ |
|||
write_stream( value, os, false ); |
|||
} |
|||
|
|||
void json_spirit::write_formatted( const mValue& value, std::ostream& os ) |
|||
{ |
|||
write_stream( value, os, true ); |
|||
} |
|||
|
|||
std::string json_spirit::write( const mValue& value ) |
|||
{ |
|||
return write_string( value, false ); |
|||
} |
|||
|
|||
std::string json_spirit::write_formatted( const mValue& value ) |
|||
{ |
|||
return write_string( value, true ); |
|||
} |
|||
|
|||
#ifndef BOOST_NO_STD_WSTRING |
|||
|
|||
void json_spirit::write( const wmValue& value, std::wostream& os ) |
|||
{ |
|||
write_stream( value, os, false ); |
|||
} |
|||
|
|||
void json_spirit::write_formatted( const wmValue& value, std::wostream& os ) |
|||
{ |
|||
write_stream( value, os, true ); |
|||
} |
|||
|
|||
std::wstring json_spirit::write( const wmValue& value ) |
|||
{ |
|||
return write_string( value, false ); |
|||
} |
|||
|
|||
std::wstring json_spirit::write_formatted( const wmValue& value ) |
|||
{ |
|||
return write_string( value, true ); |
|||
} |
|||
|
|||
#endif |
Loading…
Reference in new issue