<commit_before>//
//  ex8_13.cpp
//  Exercise 8.13
//
//  Created by pezy on 11/29/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Rewrite the phone number program from this section to read from
//          a named file rather than from cin.
//  @See    ex8_11.cpp

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>

using std::vector; using std::string; using std::cin; using std::istringstream;
using std::ostringstream; using std::ifstream; using std::cerr; using std::cout; using std::endl;

struct PersonInfo {
    string name;
    vector<string> phones;
};

bool valid(const string& str)
{
    return isnumber(str[0]);
}

string format(const string& str)
{
    return str.substr(0,3) + "-" + str.substr(3,3) + "-" + str.substr(6);
}

int main()
{
    ifstream ifs("../data/phonenumbers.txt");
    if (!ifs)
    {
        cerr << "no phone numbers?" << endl;
        return -1;
    }

    string line, word;
    vector<PersonInfo> people;
    istringstream record;
    while (getline(ifs, line))
    {
        PersonInfo info;
        record.clear();
        record.str(line);
        record >> info.name;
        while (record >> word)
            info.phones.push_back(word);
        people.push_back(info);
    }

    for (const auto &entry : people)
    {
        ostringstream formatted, badNums;
        for (const auto &nums : entry.phones)
            if (!valid(nums)) badNums << " " << nums;
            else formatted << " " << format(nums);
        if (badNums.str().empty())
            cout << entry.name << " " << formatted.str() << endl;
        else
            cerr << "input error: " << entry.name
                 << " invalid number(s) " << badNums.str() << endl;
    }

    return 0;
}
<commit_msg>improved portability. check issue #115 for detail. 	modified:   ex8_13.cpp<commit_after>//
//  ex8_13.cpp
//  Exercise 8.13
//
//  Created by pezy on 11/29/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Rewrite the phone number program from this section to read from
//          a named file rather than from cin.
//  @See    ex8_11.cpp

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>

using std::vector; using std::string; using std::cin; using std::istringstream;
using std::ostringstream; using std::ifstream; using std::cerr; using std::cout; using std::endl;
using std::isdigit;

struct PersonInfo {
    string name;
    vector<string> phones;
};

bool valid(const string& str)
{
    return isdigit(str[0]);
}

string format(const string& str)
{
    return str.substr(0,3) + "-" + str.substr(3,3) + "-" + str.substr(6);
}

int main()
{
    ifstream ifs("../data/phonenumbers.txt");
    if (!ifs)
    {
        cerr << "no phone numbers?" << endl;
        return -1;
    }

    string line, word;
    vector<PersonInfo> people;
    istringstream record;
    while (getline(ifs, line))
    {
        PersonInfo info;
        record.clear();
        record.str(line);
        record >> info.name;
        while (record >> word)
            info.phones.push_back(word);
        people.push_back(info);
    }

    for (const auto &entry : people)
    {
        ostringstream formatted, badNums;
        for (const auto &nums : entry.phones)
            if (!valid(nums)) badNums << " " << nums;
            else formatted << " " << format(nums);
        if (badNums.str().empty())
            cout << entry.name << " " << formatted.str() << endl;
        else
            cerr << "input error: " << entry.name
                 << " invalid number(s) " << badNums.str() << endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>//
//  ex9_44.cpp
//  Exercise 9.44
//
//  Created by pezy on 12/4/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Rewrite the previous function using an index and replace.
//  @See    9.43

#include <iostream>
#include <string>

using std::cout; using std::endl; using std::string;

void func(string &s, const string &oldVal, const string &newVal)
{
    for (string::size_type i=0; i!=s.size(); ++i)
        if (s.substr(i, oldVal.size()) == oldVal)
            s.replace(i, oldVal.size(), newVal);
}

int main()
{
    string str{"To drive straight thru is a foolish, tho courageous act."};
    func(str, "tho", "though");
    func(str, "thru", "through");
    cout << str << endl;

    return 0;
}
<commit_msg>fixed the same bug as ex9_43 in ex9_44<commit_after>//
//  ex9_44.cpp
//  Exercise 9.44
//
//  Created by XDXX on 4/17/15.
//  Copyright (c) 2015 XDXX. All rights reserved.
//
//  @Brief  Rewrite the previous function using an index and replace.
//  @See    9.43

#include <iostream>
#include <string>

using std::cout; using std::endl; using std::string;

void func(string &s, string const& oldVal, string const& newVal)
{
	for (size_t pos = 0; pos <= s.size() - oldVal.size();) {
		if (s[pos] == oldVal[0] && s.substr(pos, oldVal.size()) == oldVal) {
			s.replace(pos, oldVal.size(), newVal);
			pos += newVal.size();
		}
		else
			++pos;
	}
}

int main()
{
	string str{"To drive straight thru is a foolish, tho courageous act."};
   	func(str, "tho", "though");
  	func(str, "thru", "through");
	cout << str << endl;
	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <time.h>
#include "SerialPort.h"

using namespace std;

SerialPort::SerialPort()
	:
	portName(""),
	baudrate(9600),
	parity(ParityNone),
	stopbits(StopBitOne),
	databits(8),
	flowCtrl(FlowCtrlNone),
	hRs232c(INVALID_HANDLE_VALUE)
{
}
SerialPort::~SerialPort()
{
}
bool SerialPort::Open(int timeout/* = 0*/)
{
    memset(SndBuf,0,sizeof(SndBuf));
    memset(RcvBuf,0,sizeof(RcvBuf));

	string filename = string("\\\\.\\").append(portName);

    // COM|[g̃I[v
    hRs232c = CreateFile(
        filename.c_str(),
		GENERIC_READ|GENERIC_WRITE,0,NULL,
        OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL
#ifdef OVERLAPPED_IO
		|FILE_FLAG_OVERLAPPED
#endif
		,NULL);
    if ( hRs232c == INVALID_HANDLE_VALUE ) {
#ifdef _DEBUG
        cerr << "RS232C CreateFile Error" << endl;
#endif
        return false;
    }

    // COM|[g̃ZbgAbv
    if (SetupComm(hRs232c,sizeof(RcvBuf),sizeof(SndBuf)) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C SetupComm Error" << endl;
#endif
        return false;
    }

    // COM|[g̐ݒ擾
    DCB dcb;
    memset(&dcb, NULL, sizeof(DCB));
    dcb.DCBlength = sizeof(DCB);
    GetCommState(hRs232c, &dcb );

    // COM|[g̐ݒύX
    dcb.BaudRate = baudrate;
    dcb.fParity  = (parity == ParityNone) ? FALSE : TRUE;
    dcb.Parity   = (int)parity;
    dcb.StopBits = (int)stopbits;
    dcb.ByteSize = databits;

	// Flow control
	switch (this->flowCtrl) {
		break;
	case FlowCtrlXonXoff:
		dcb.fInX = TRUE;
		dcb.fOutX = TRUE;
		dcb.XonChar = 0x11;
		dcb.XoffChar = 0x13;
		dcb.XonLim = 0;
		dcb.XoffLim = 0;
		break;
	case FlowCtrlHardware:
		dcb.fOutxCtsFlow = TRUE;
		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
		dcb.XonLim = 0;
		dcb.XoffLim = 0;
		break;
	case FlowCtrlNone:
	default:
		break;
	}

    if (SetCommState(hRs232c,&dcb) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C SetCommState Error" << endl;
#endif
        return false;
    }
	COMMTIMEOUTS tmo;
	tmo.ReadTotalTimeoutConstant = timeout;
	tmo.ReadTotalTimeoutMultiplier = 0;
	tmo.WriteTotalTimeoutConstant = timeout;
	tmo.WriteTotalTimeoutMultiplier = 0;
	if(SetCommTimeouts(hRs232c, &tmo) == FALSE) {
#ifdef _DEBUG
        cerr << "RS232C SetCommTimeouts Error" << endl;
#endif
		return false;
	}

#ifdef OVERLAPPED_IO
    // COM|[g̎MCxg쐬
    memset(&ovRead,0,sizeof(ovRead));
    ovRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (ovRead.hEvent == NULL){
#ifdef _DEBUG
        cerr << "RS232C CreateEvent Error" << endl;
#endif
        return 0;
    }
    // COM|[g̎MCxg}XN
    if (SetCommMask(hRs232c, EV_RXCHAR) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C SetCommMask Error" << endl;
#endif
        return 0;
    }
#endif
	return true;
}
void SerialPort::Close()
{
#ifdef OVERLAPPED_IO
    // OM|[g̎MCxgN[Y
    CloseHandle(ovRead.hEvent);
#endif

    // COM|[g̃N[Y
    CloseHandle(hRs232c);
	hRs232c = INVALID_HANDLE_VALUE;
}
int SerialPort::Write(const void* buf, int offset, int count)
{
	const unsigned char* sendbuf = (const unsigned char*)buf;
    DWORD dwSize = 0;
	OVERLAPPED* pOverlapped = 0;

#ifdef OVERLAPPED_IO
    OVERLAPPED ovWrite;
    memset(&ovWrite,0,sizeof(ovWrite));
	pOverlapped = &ovWrite;
#endif

    if (WriteFile(hRs232c, &sendbuf[offset], count, &dwSize, pOverlapped) == FALSE) {
#ifdef _DEBUG
        cerr << "RS232C WriteFile Error" << endl;
#endif
        return 0;
    }
	return (int)dwSize;
}
int SerialPort::Read(void* buf, int offset, int count)
{
	unsigned char* recvbuf = (unsigned char*)buf;
	DWORD dwSize = 0;
	OVERLAPPED* pOverlapped = 0;

#ifdef OVERLAPPED_IO
	pOverlapped = &ovRead;

    // COM|[g̎M҂
    DWORD dwEvtMask = 0;
    DWORD dwTransfer = 0;
	clock_t wait_start = clock();
    if (WaitCommEvent(hRs232c, &dwEvtMask, pOverlapped) == FALSE){
        if (GetLastError() == ERROR_IO_PENDING) {
            GetOverlappedResult(hRs232c, pOverlapped, &dwTransfer, TRUE);
        }else{
#ifdef _DEBUG
        cerr << "RS232C WaitCommEvent Error" << endl;
#endif
            return 0;
        }
    }
    // COM|[g̎MCxg`FbN
    if ((dwEvtMask & EV_RXCHAR) != EV_RXCHAR){
		return 0;
	}
    // COM|[g̎Mf[^`FbN
    COMSTAT comst;
    DWORD dwErr;
    ClearCommError(hRs232c, &dwErr, &comst);
	if(comst.cbInQue < count) {
		return 0;
	}
#endif
	// Check available byte count
	DWORD dwError = 0UL;
	COMSTAT comstat;
	ClearCommError(hRs232c, &dwError, &comstat);
	DWORD dwCount = comstat.cbInQue;
	if (dwCount < count) {
		return 0;
	}
    // COM|[gf[^M
    if(ReadFile(hRs232c, &recvbuf[offset], count, &dwSize, pOverlapped) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C ReadFile Error" << endl;
#endif
        return -1;
    }
	if(count != 0 && dwSize == 0) {
		return -1;
	}
	return (int)dwSize;
}
<commit_msg>Suppress warning<commit_after>#include <iostream>
#include <time.h>
#include "SerialPort.h"

using namespace std;

SerialPort::SerialPort()
	:
	portName(""),
	baudrate(9600),
	parity(ParityNone),
	stopbits(StopBitOne),
	databits(8),
	flowCtrl(FlowCtrlNone),
	hRs232c(INVALID_HANDLE_VALUE)
{
}
SerialPort::~SerialPort()
{
}
bool SerialPort::Open(int timeout/* = 0*/)
{
    memset(SndBuf,0,sizeof(SndBuf));
    memset(RcvBuf,0,sizeof(RcvBuf));

	string filename = string("\\\\.\\").append(portName);

    // COM|[g̃I[v
    hRs232c = CreateFile(
        filename.c_str(),
		GENERIC_READ|GENERIC_WRITE,0,NULL,
        OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL
#ifdef OVERLAPPED_IO
		|FILE_FLAG_OVERLAPPED
#endif
		,NULL);
    if ( hRs232c == INVALID_HANDLE_VALUE ) {
#ifdef _DEBUG
        cerr << "RS232C CreateFile Error" << endl;
#endif
        return false;
    }

    // COM|[g̃ZbgAbv
    if (SetupComm(hRs232c,sizeof(RcvBuf),sizeof(SndBuf)) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C SetupComm Error" << endl;
#endif
        return false;
    }

    // COM|[g̐ݒ擾
    DCB dcb;
    memset(&dcb, NULL, sizeof(DCB));
    dcb.DCBlength = sizeof(DCB);
    GetCommState(hRs232c, &dcb );

    // COM|[g̐ݒύX
    dcb.BaudRate = baudrate;
    dcb.fParity  = (parity == ParityNone) ? FALSE : TRUE;
    dcb.Parity   = (int)parity;
    dcb.StopBits = (int)stopbits;
    dcb.ByteSize = databits;

	// Flow control
	switch (this->flowCtrl) {
		break;
	case FlowCtrlXonXoff:
		dcb.fInX = TRUE;
		dcb.fOutX = TRUE;
		dcb.XonChar = 0x11;
		dcb.XoffChar = 0x13;
		dcb.XonLim = 0;
		dcb.XoffLim = 0;
		break;
	case FlowCtrlHardware:
		dcb.fOutxCtsFlow = TRUE;
		dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
		dcb.XonLim = 0;
		dcb.XoffLim = 0;
		break;
	case FlowCtrlNone:
	default:
		break;
	}

    if (SetCommState(hRs232c,&dcb) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C SetCommState Error" << endl;
#endif
        return false;
    }
	COMMTIMEOUTS tmo;
	tmo.ReadTotalTimeoutConstant = timeout;
	tmo.ReadTotalTimeoutMultiplier = 0;
	tmo.WriteTotalTimeoutConstant = timeout;
	tmo.WriteTotalTimeoutMultiplier = 0;
	if(SetCommTimeouts(hRs232c, &tmo) == FALSE) {
#ifdef _DEBUG
        cerr << "RS232C SetCommTimeouts Error" << endl;
#endif
		return false;
	}

#ifdef OVERLAPPED_IO
    // COM|[g̎MCxg쐬
    memset(&ovRead,0,sizeof(ovRead));
    ovRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (ovRead.hEvent == NULL){
#ifdef _DEBUG
        cerr << "RS232C CreateEvent Error" << endl;
#endif
        return 0;
    }
    // COM|[g̎MCxg}XN
    if (SetCommMask(hRs232c, EV_RXCHAR) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C SetCommMask Error" << endl;
#endif
        return 0;
    }
#endif
	return true;
}
void SerialPort::Close()
{
#ifdef OVERLAPPED_IO
    // OM|[g̎MCxgN[Y
    CloseHandle(ovRead.hEvent);
#endif

    // COM|[g̃N[Y
    CloseHandle(hRs232c);
	hRs232c = INVALID_HANDLE_VALUE;
}
int SerialPort::Write(const void* buf, int offset, int count)
{
	const unsigned char* sendbuf = (const unsigned char*)buf;
    DWORD dwSize = 0;
	OVERLAPPED* pOverlapped = 0;

#ifdef OVERLAPPED_IO
    OVERLAPPED ovWrite;
    memset(&ovWrite,0,sizeof(ovWrite));
	pOverlapped = &ovWrite;
#endif

    if (WriteFile(hRs232c, &sendbuf[offset], count, &dwSize, pOverlapped) == FALSE) {
#ifdef _DEBUG
        cerr << "RS232C WriteFile Error" << endl;
#endif
        return 0;
    }
	return (int)dwSize;
}
int SerialPort::Read(void* buf, int offset, int count)
{
	unsigned char* recvbuf = (unsigned char*)buf;
	DWORD dwSize = 0;
	OVERLAPPED* pOverlapped = 0;

#ifdef OVERLAPPED_IO
	pOverlapped = &ovRead;

    // COM|[g̎M҂
    DWORD dwEvtMask = 0;
    DWORD dwTransfer = 0;
	clock_t wait_start = clock();
    if (WaitCommEvent(hRs232c, &dwEvtMask, pOverlapped) == FALSE){
        if (GetLastError() == ERROR_IO_PENDING) {
            GetOverlappedResult(hRs232c, pOverlapped, &dwTransfer, TRUE);
        }else{
#ifdef _DEBUG
        cerr << "RS232C WaitCommEvent Error" << endl;
#endif
            return 0;
        }
    }
    // COM|[g̎MCxg`FbN
    if ((dwEvtMask & EV_RXCHAR) != EV_RXCHAR){
		return 0;
	}
    // COM|[g̎Mf[^`FbN
    COMSTAT comst;
    DWORD dwErr;
    ClearCommError(hRs232c, &dwErr, &comst);
	if(comst.cbInQue < count) {
		return 0;
	}
#endif
	// Check available byte count
	DWORD dwError = 0UL;
	COMSTAT comstat;
	ClearCommError(hRs232c, &dwError, &comstat);
	DWORD dwCount = comstat.cbInQue;
	if (dwCount < (DWORD)count) {
		return 0;
	}
    // COM|[gf[^M
    if(ReadFile(hRs232c, &recvbuf[offset], count, &dwSize, pOverlapped) == FALSE){
#ifdef _DEBUG
        cerr << "RS232C ReadFile Error" << endl;
#endif
        return -1;
    }
	if(count != 0 && dwSize == 0) {
		return -1;
	}
	return (int)dwSize;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010-2014 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "netenum.h"
# include  "compiler.h"
# include  <cassert>

using namespace std;

netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag,
		     bool integer_flag, long msb, long lsb, size_t name_count)
: base_type_(btype), signed_flag_(signed_flag), integer_flag_(integer_flag),
  msb_(msb), lsb_(lsb), names_(name_count), bits_(name_count)
{
}

netenum_t::~netenum_t()
{
}

bool netenum_t::get_signed() const
{
      return signed_flag_;
}

bool netenum_t::get_isint() const
{
      return integer_flag_;
}

/*
 * Enumerations are by definition always packed.
 */
bool netenum_t::packed() const
{
      return true;
}

long netenum_t::packed_width() const
{
      if (msb_ >= lsb_)
	    return msb_ - lsb_ + 1;
      else
	    return lsb_ - msb_ + 1;
}

vector<netrange_t> netenum_t::slice_dimensions() const
{
      vector<netrange_t> tmp (1);
      tmp[0] = netrange_t(msb_, lsb_);
      return tmp;
}

bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val)
{
      std::pair<std::map<perm_string,verinum>::iterator, bool> res;

      assert((msb_-lsb_+1) > 0);
      assert(val.has_len() && val.len() == (unsigned)(msb_-lsb_+1));

	// Insert a map of the name to the value. This also gets a
	// flag that returns true if the  name is unique, or false
	// otherwise.
      res = names_map_.insert( make_pair(name,val) );

      assert(name_idx < names_.size() && names_[name_idx] == 0);
      names_[name_idx] = name;

      return res.second;
}

void netenum_t::insert_name_close(void)
{
      for (size_t idx = 0 ; idx < names_.size() ; idx += 1) {
	    netenum_t::iterator cur = names_map_.find(names_[idx]);

	    vector<char>str (cur->second.len() + 1);
	    for (unsigned bit = 0 ; bit < cur->second.len() ; bit += 1) {
		  switch (cur->second.get(bit)) {
		      case verinum::V0:
			str[bit] = '0';
			break;
		      case verinum::V1:
			str[bit] = '1';
			break;
		      case verinum::Vx:
			str[bit] = 'x';
			break;
		      case verinum::Vz:
			str[bit] = 'z';
			break;
		  }
	    }
	    bits_[idx] = bits_strings.make(&str[0]);
      }
}

netenum_t::iterator netenum_t::find_name(perm_string name) const
{
      return names_map_.find(name);
}

/*
 * Check to see if the given value is already in the enumeration mapping.
 */
perm_string netenum_t::find_value(const verinum&val) const
{
      perm_string res;
      for(netenum_t::iterator cur = names_map_.begin();
          cur != names_map_.end(); ++ cur) {
	    if (cur->second == val) {
		  res = cur->first;
		  break;
	    }
      }
      return res;
}

netenum_t::iterator netenum_t::end_name() const
{
      return names_map_.end();
}

netenum_t::iterator netenum_t::first_name() const
{
      return names_map_.find(names_.front());
}

netenum_t::iterator netenum_t::last_name() const
{
      return names_map_.find(names_.back());
}

perm_string netenum_t::name_at(size_t idx) const
{
      assert(idx < names_.size());
      return names_[idx];
}

perm_string netenum_t::bits_at(size_t idx) const
{
      return bits_[idx];
}
<commit_msg>Don't crash if there are problems elaborating an enumeration.<commit_after>/*
 * Copyright (c) 2010-2014 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

# include  "netenum.h"
# include  "compiler.h"
# include  <cassert>

using namespace std;

netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag,
		     bool integer_flag, long msb, long lsb, size_t name_count)
: base_type_(btype), signed_flag_(signed_flag), integer_flag_(integer_flag),
  msb_(msb), lsb_(lsb), names_(name_count), bits_(name_count)
{
}

netenum_t::~netenum_t()
{
}

bool netenum_t::get_signed() const
{
      return signed_flag_;
}

bool netenum_t::get_isint() const
{
      return integer_flag_;
}

/*
 * Enumerations are by definition always packed.
 */
bool netenum_t::packed() const
{
      return true;
}

long netenum_t::packed_width() const
{
      if (msb_ >= lsb_)
	    return msb_ - lsb_ + 1;
      else
	    return lsb_ - msb_ + 1;
}

vector<netrange_t> netenum_t::slice_dimensions() const
{
      vector<netrange_t> tmp (1);
      tmp[0] = netrange_t(msb_, lsb_);
      return tmp;
}

bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val)
{
      std::pair<std::map<perm_string,verinum>::iterator, bool> res;

      assert((msb_-lsb_+1) > 0);
      assert(val.has_len() && val.len() == (unsigned)(msb_-lsb_+1));

	// Insert a map of the name to the value. This also gets a
	// flag that returns true if the  name is unique, or false
	// otherwise.
      res = names_map_.insert( make_pair(name,val) );

      assert(name_idx < names_.size() && names_[name_idx] == 0);
      names_[name_idx] = name;

      return res.second;
}

void netenum_t::insert_name_close(void)
{
      for (size_t idx = 0 ; idx < names_.size() ; idx += 1) {
	      // If we failed to elaborate the name then skip this step.
	    if (names_[idx].nil()) continue;

	    netenum_t::iterator cur = names_map_.find(names_[idx]);

	    vector<char>str (cur->second.len() + 1);
	    for (unsigned bit = 0 ; bit < cur->second.len() ; bit += 1) {
		  switch (cur->second.get(bit)) {
		      case verinum::V0:
			str[bit] = '0';
			break;
		      case verinum::V1:
			str[bit] = '1';
			break;
		      case verinum::Vx:
			str[bit] = 'x';
			break;
		      case verinum::Vz:
			str[bit] = 'z';
			break;
		  }
	    }
	    bits_[idx] = bits_strings.make(&str[0]);
      }
}

netenum_t::iterator netenum_t::find_name(perm_string name) const
{
      return names_map_.find(name);
}

/*
 * Check to see if the given value is already in the enumeration mapping.
 */
perm_string netenum_t::find_value(const verinum&val) const
{
      perm_string res;
      for(netenum_t::iterator cur = names_map_.begin();
          cur != names_map_.end(); ++ cur) {
	    if (cur->second == val) {
		  res = cur->first;
		  break;
	    }
      }
      return res;
}

netenum_t::iterator netenum_t::end_name() const
{
      return names_map_.end();
}

netenum_t::iterator netenum_t::first_name() const
{
      return names_map_.find(names_.front());
}

netenum_t::iterator netenum_t::last_name() const
{
      return names_map_.find(names_.back());
}

perm_string netenum_t::name_at(size_t idx) const
{
      assert(idx < names_.size());
      return names_[idx];
}

perm_string netenum_t::bits_at(size_t idx) const
{
      return bits_[idx];
}
<|endoftext|>


<commit_before>#include "CgStr.hpp"
#include "HighlightedFile.hpp"
#include "MultiTuProcessor.hpp"
#include "annotate.hpp"
#include "cgWrappers.hpp"
#include "config.hpp"
#include "xref.hpp"

#include <climits>
#include <cstring>
#include <iostream>
#include <string>

using namespace synth;

namespace {

struct FileState {
    HighlightedFile& hlFile;
    std::size_t hlFileIdx;
    MultiTuProcessor& multiTuProcessor;
};

} // anonymous namespace

static bool isTypeKind(CXCursorKind k)
{
    SYNTH_DISCLANGWARN_BEGIN("-Wswitch-enum")
    switch (k) {
        case CXCursor_ClassDecl:
        case CXCursor_ClassTemplate:
        case CXCursor_ClassTemplatePartialSpecialization:
        case CXCursor_StructDecl:
        case CXCursor_UnionDecl:
        case CXCursor_EnumDecl:
        case CXCursor_TypedefDecl:
        case CXCursor_ObjCInterfaceDecl:
        case CXCursor_ObjCCategoryDecl:
        case CXCursor_ObjCProtocolDecl:
        case CXCursor_ObjCImplementationDecl:
        case CXCursor_TemplateTypeParameter:
        case CXCursor_TemplateTemplateParameter:
        case CXCursor_TypeAliasDecl:
        case CXCursor_TypeAliasTemplateDecl:
        case CXCursor_TypeRef:
        case CXCursor_ObjCSuperClassRef:
        case CXCursor_ObjCProtocolRef:
        case CXCursor_ObjCClassRef:
        case CXCursor_CXXBaseSpecifier:
            return true;

        default:
            return false;
    }
    SYNTH_DISCLANGWARN_END
}

static TokenAttributes getVarTokenAttributes(CXCursor cur)
{
    if (clang_getCursorLinkage(cur) == CXLinkage_NoLinkage)
        return TokenAttributes::varLocal;
    if (clang_getCXXAccessSpecifier(cur) == CX_CXXInvalidAccessSpecifier)
        return TokenAttributes::varGlobal;
    if (clang_Cursor_getStorageClass(cur) == CX_SC_Static)
        return TokenAttributes::varStaticMember;
    return TokenAttributes::varNonstaticMember;
}

static TokenAttributes getIntCssClasses(CXToken tok, CXTranslationUnit tu)
{
    std::string sp = CgStr(clang_getTokenSpelling(tu, tok)).gets();
    if (!sp.empty()) {
        if (sp.size() >= 2 && sp[0] == '0') {
            if (sp[1] == 'x' || sp[1] == 'X')
                return TokenAttributes::litNumIntHex;
            if (sp[1] == 'b' || sp[1] == 'B')
                return TokenAttributes::litNumIntBin;
            return TokenAttributes::litNumIntOct;
        }
        char suffix = sp[sp.size() - 1];
        if (suffix == 'l' || suffix == 'L')
            return TokenAttributes::litNumIntDecLong;
    }
    return TokenAttributes::litNum;
}

static bool startsWith(std::string const& s, std::string const& p) {
    return s.compare(0, p.size(), p) == 0;
}

static bool isBuiltinTypeKw(std::string const& t) {
    return startsWith(t, "unsigned ")
        || t == "unsigned"
        || startsWith(t, "signed ")
        || t == "signed"
        || startsWith(t, "short ")
        || t == "short"
        || startsWith(t, "long ")
        || t == "long"
        || t == "int"
        || t == "float"
        || t == "double"
        || t == "bool"
        || t == "char"
        || t == "char16_t"
        || t == "char32_t"
        || t == "wchar_t";
}

static TokenAttributes getTokenAttributes(
    CXToken tok, CXCursor cur, CXTranslationUnit tu)
{
    CXCursorKind k = clang_getCursorKind(cur);
    CXTokenKind tk = clang_getTokenKind(tok);
    if (clang_isPreprocessing(k)) {
        if (k == CXCursor_InclusionDirective
            && (tk == CXToken_Literal || tk == CXToken_Identifier)
        ) {
            CgStr spelling = clang_getTokenSpelling(tu, tok);
            if (!std::strcmp(spelling.gets(), "include"))
                return TokenAttributes::preIncludeFile;
        }
        return TokenAttributes::pre;
    }

    switch (tk) {
        case CXToken_Punctuation:
            if (k == CXCursor_BinaryOperator || k == CXCursor_UnaryOperator)
                return TokenAttributes::op;
            return TokenAttributes::punct;

        case CXToken_Comment:
            return TokenAttributes::cmmt;

        case CXToken_Literal:
            SYNTH_DISCLANGWARN_BEGIN("-Wswitch-enum")
            switch (k) {
                case CXCursor_ObjCStringLiteral:
                case CXCursor_StringLiteral:
                    return TokenAttributes::litStr;
                case CXCursor_CharacterLiteral:
                    return TokenAttributes::litChr;
                case CXCursor_FloatingLiteral:
                    return TokenAttributes::litNumFlt;
                case CXCursor_IntegerLiteral:
                    return getIntCssClasses(tok, tu);
                case CXCursor_ImaginaryLiteral:
                    return TokenAttributes::litNum;
                default:
                    return TokenAttributes::lit;
            }
            SYNTH_DISCLANGWARN_END

        case CXToken_Keyword: {
            if (k == CXCursor_BinaryOperator || k == CXCursor_UnaryOperator)
                return TokenAttributes::opWord;
            if (k == CXCursor_CXXNullPtrLiteralExpr
                || k == CXCursor_CXXBoolLiteralExpr
                || k == CXCursor_ObjCBoolLiteralExpr
            ) {
                return TokenAttributes::litKw;
            }
            std::string sp = CgStr(clang_getTokenSpelling(tu, tok)).gets();
            if (k == CXCursor_TypeRef || isBuiltinTypeKw(sp))
                return TokenAttributes::tyBuiltin;
            if (clang_isDeclaration(k))
                return TokenAttributes::kwDecl;
            return TokenAttributes::kw;
        }

        case CXToken_Identifier:
            if (isTypeKind(k))
                return TokenAttributes::ty;
            SYNTH_DISCLANGWARN_BEGIN("-Wswitch-enum")
            switch (k) {
                case CXCursor_MemberRef:
                case CXCursor_DeclRefExpr:
                case CXCursor_MemberRefExpr:
                case CXCursor_UsingDeclaration:
                case CXCursor_TemplateRef: {
                    CXCursor refd = clang_getCursorReferenced(cur);
                    return getTokenAttributes(tok, refd, tu);
                }

                case CXCursor_ObjCPropertyDecl:
                    return TokenAttributes::varNonstaticMember; // Sorta right.

                case CXCursor_ObjCIvarDecl:
                case CXCursor_FieldDecl:
                    return TokenAttributes::varNonstaticMember; // TODO

                case CXCursor_EnumConstantDecl:
                case CXCursor_NonTypeTemplateParameter:
                    return TokenAttributes::constant;

                case CXCursor_FunctionDecl:
                case CXCursor_ObjCInstanceMethodDecl:
                case CXCursor_ObjCClassMethodDecl:
                case CXCursor_CXXMethod:
                case CXCursor_FunctionTemplate:
                case CXCursor_Constructor:
                case CXCursor_Destructor:
                case CXCursor_ConversionFunction:
                case CXCursor_OverloadedDeclRef:
                    return TokenAttributes::func;

                case CXCursor_VarDecl:
                    return getVarTokenAttributes(cur);
                case CXCursor_ParmDecl:
                    return TokenAttributes::varLocal;

                case CXCursor_Namespace:
                case CXCursor_NamespaceAlias:
                case CXCursor_UsingDirective:
                case CXCursor_NamespaceRef:
                    return TokenAttributes::namesp;

                case CXCursor_LabelStmt:
                    return TokenAttributes::lbl;

                default:
                    if (clang_isAttribute(k))
                        return TokenAttributes::attr;
                    return TokenAttributes::none;
            }
            SYNTH_DISCLANGWARN_END
            assert("unreachable" && false);
    }
}

static void processToken(FileState& state, CXToken tok, CXCursor cur)
{
    auto& markups = state.hlFile.markups;
    markups.emplace_back();
    Markup& m = markups.back();
    CXTranslationUnit tu = clang_Cursor_getTranslationUnit(cur);
    CXSourceRange rng = clang_getTokenExtent(tu, tok);
    //std::cout << rng << ": " << CgStr(clang_getTokenSpelling(tu, tok)).gets() << '\n';
    unsigned lineno;
    clang_getFileLocation(
        clang_getRangeStart(rng), nullptr, &lineno, nullptr, &m.begin_offset);
    clang_getFileLocation(
        clang_getRangeEnd(rng), nullptr, nullptr, nullptr, &m.end_offset);
    if (m.begin_offset == m.end_offset) {
        markups.pop_back();
        return;
    }

    m.refdFilename = nullptr;
    m.attrs = getTokenAttributes(tok, cur, tu);

    CXTokenKind tk = clang_getTokenKind(tok);
    if (tk == CXToken_Comment || tk == CXToken_Literal)
        return;

    if (!clang_equalLocations(
            clang_getRangeStart(rng), clang_getCursorLocation(cur))
    ) {
        return;
    }

    CXCursorKind k = clang_getCursorKind(cur);
    if (k == CXCursor_InclusionDirective) {
        Markup incLnk = {};
        CXSourceRange incrng = clang_getCursorExtent(cur);
        clang_getFileLocation(
            clang_getRangeStart(incrng),
            nullptr,
            nullptr,
            nullptr,
            &incLnk.begin_offset);
        clang_getFileLocation(
            clang_getRangeEnd(incrng),
            nullptr,
            nullptr,
            nullptr,
            &incLnk.end_offset);
        if (linkInclude(incLnk, cur, state.multiTuProcessor))
            state.hlFile.markups.push_back(std::move(incLnk));
        return;
    }

    if (clang_isDeclaration(k))
        m.attrs |= TokenAttributes::flagDecl;

    // std::cout << CgStr(clang_getTokenSpelling(tu, tok)).gets()
    //     << " " << CgStr(clang_getCursorKindSpelling(k)).gets() << '\n';

    // clang_isReference() sometimes reports false negatives, e.g. for
    // overloaded operators, so check manually.
    CXCursor referenced = clang_getCursorReferenced(cur);
    bool isref = !clang_Cursor_isNull(referenced)
        && !clang_equalCursors(cur, referenced);
    if (isref)
        linkCursorIfIncludedDst(m, referenced, lineno, state.multiTuProcessor);

    CXCursor defcur = clang_getCursorDefinition(cur);
    if (clang_equalCursors(defcur, cur)) { // This is a definition:
        m.attrs |= TokenAttributes::flagDef;
        CgStr usr(clang_getCursorUSR(cur));
        if (!usr.empty()) {
            SymbolDeclaration decl {
                usr.get(),
                state.hlFile.originalPath,
                lineno
            };
            state.multiTuProcessor.registerDef(std::move(decl));
        }
    } else if (!isref) {
        if (clang_Cursor_isNull(defcur)) {
            CgStr usr(clang_getCursorUSR(cur));
            if (!usr.empty()) {
                state.multiTuProcessor.registerMissingDefLink(
                    state.hlFileIdx,
                    state.hlFile.markups.size() - 1,
                    usr.get());
            }
        } else {
            linkCursorIfIncludedDst(m, defcur, lineno, state.multiTuProcessor);
        }
    }
}

namespace {

struct IncVisitorData {
    MultiTuProcessor& multiTuProcessor;
    CXTranslationUnit tu;
};

} // anonymous namespace

static void processFile(
    CXFile file, CXSourceLocation*, unsigned, CXClientData ud)
{
    auto& cdata = *static_cast<IncVisitorData*>(ud);
    CXTranslationUnit tu = cdata.tu;
    MultiTuProcessor& multiTuProcessor = cdata.multiTuProcessor;

    CXSourceLocation beg = clang_getLocationForOffset(tu, file, 0);
    CXSourceLocation end = clang_getLocation(tu, file, UINT_MAX, UINT_MAX);

    auto output = multiTuProcessor.prepareToProcess(file);
    if (!output.first)
        return;

    CXToken* tokens;
    unsigned numTokens;
    clang_tokenize(tu, clang_getRange(beg, end), &tokens, &numTokens);
    CgTokensCleanup tokCleanup(tokens, numTokens, tu);

    if (numTokens > 0) {
        FileState state {*output.first, output.second, multiTuProcessor};
        std::vector<CXCursor> tokCurs(numTokens);
        clang_annotateTokens(tu, tokens, numTokens, tokCurs.data());
        for (unsigned i = 0; i < numTokens - 1; ++i) {
            CXCursor cur = tokCurs[i];
            CXSourceLocation tokLoc = clang_getTokenLocation(tu, tokens[i]);
            if (!clang_equalLocations(clang_getCursorLocation(cur), tokLoc)) {
                CXCursor c2 = clang_getCursor(tu, tokLoc);
                if (clang_equalLocations(clang_getCursorLocation(c2), tokLoc))
                    cur = c2;
            }
            processToken(state, tokens[i], cur);
        }
    }
    std::cout << "Processed " << numTokens << " tokens in "
              << *output.first->originalPath << '\n';
}

int synth::processTu(
    CXIndex cidx,
    MultiTuProcessor& state,
    char const* const* args,
    int nargs)
{
    CXTranslationUnit tu = nullptr;
    CXErrorCode err = clang_parseTranslationUnit2FullArgv(
        cidx,
        /*source_filename:*/ nullptr, // Included in commandline.
        args,
        nargs,
        /*unsaved_files:*/ nullptr,
        /*num_unsaved_files:*/ 0,
        CXTranslationUnit_DetailedPreprocessingRecord,
        &tu);
    CgTuHandle htu(tu);
    if (err != CXError_Success) {
        std::cerr << "Failed parsing translation unit (code "
                  << static_cast<int>(err)
                  << ")\n";
        std::cerr << "  args:";
        for (int i = 0; i < nargs; ++i)
            std::cerr << ' ' << args[i];
        std::cerr << '\n';
        return err + 10;
    }

    IncVisitorData ud {state, tu};
    clang_getInclusions(tu, &processFile, &ud);
    return EXIT_SUCCESS;
}
<commit_msg>Fix highlighting of #include filenames.<commit_after>#include "CgStr.hpp"
#include "HighlightedFile.hpp"
#include "MultiTuProcessor.hpp"
#include "annotate.hpp"
#include "cgWrappers.hpp"
#include "config.hpp"
#include "xref.hpp"

#include <climits>
#include <cstring>
#include <iostream>
#include <string>

using namespace synth;

namespace {

struct FileState {
    HighlightedFile& hlFile;
    std::size_t hlFileIdx;
    MultiTuProcessor& multiTuProcessor;
};

} // anonymous namespace

static bool isTypeKind(CXCursorKind k)
{
    SYNTH_DISCLANGWARN_BEGIN("-Wswitch-enum")
    switch (k) {
        case CXCursor_ClassDecl:
        case CXCursor_ClassTemplate:
        case CXCursor_ClassTemplatePartialSpecialization:
        case CXCursor_StructDecl:
        case CXCursor_UnionDecl:
        case CXCursor_EnumDecl:
        case CXCursor_TypedefDecl:
        case CXCursor_ObjCInterfaceDecl:
        case CXCursor_ObjCCategoryDecl:
        case CXCursor_ObjCProtocolDecl:
        case CXCursor_ObjCImplementationDecl:
        case CXCursor_TemplateTypeParameter:
        case CXCursor_TemplateTemplateParameter:
        case CXCursor_TypeAliasDecl:
        case CXCursor_TypeAliasTemplateDecl:
        case CXCursor_TypeRef:
        case CXCursor_ObjCSuperClassRef:
        case CXCursor_ObjCProtocolRef:
        case CXCursor_ObjCClassRef:
        case CXCursor_CXXBaseSpecifier:
            return true;

        default:
            return false;
    }
    SYNTH_DISCLANGWARN_END
}

static TokenAttributes getVarTokenAttributes(CXCursor cur)
{
    if (clang_getCursorLinkage(cur) == CXLinkage_NoLinkage)
        return TokenAttributes::varLocal;
    if (clang_getCXXAccessSpecifier(cur) == CX_CXXInvalidAccessSpecifier)
        return TokenAttributes::varGlobal;
    if (clang_Cursor_getStorageClass(cur) == CX_SC_Static)
        return TokenAttributes::varStaticMember;
    return TokenAttributes::varNonstaticMember;
}

static TokenAttributes getIntCssClasses(CXToken tok, CXTranslationUnit tu)
{
    std::string sp = CgStr(clang_getTokenSpelling(tu, tok)).gets();
    if (!sp.empty()) {
        if (sp.size() >= 2 && sp[0] == '0') {
            if (sp[1] == 'x' || sp[1] == 'X')
                return TokenAttributes::litNumIntHex;
            if (sp[1] == 'b' || sp[1] == 'B')
                return TokenAttributes::litNumIntBin;
            return TokenAttributes::litNumIntOct;
        }
        char suffix = sp[sp.size() - 1];
        if (suffix == 'l' || suffix == 'L')
            return TokenAttributes::litNumIntDecLong;
    }
    return TokenAttributes::litNum;
}

static bool startsWith(std::string const& s, std::string const& p) {
    return s.compare(0, p.size(), p) == 0;
}

static bool isBuiltinTypeKw(std::string const& t) {
    return startsWith(t, "unsigned ")
        || t == "unsigned"
        || startsWith(t, "signed ")
        || t == "signed"
        || startsWith(t, "short ")
        || t == "short"
        || startsWith(t, "long ")
        || t == "long"
        || t == "int"
        || t == "float"
        || t == "double"
        || t == "bool"
        || t == "char"
        || t == "char16_t"
        || t == "char32_t"
        || t == "wchar_t";
}

static TokenAttributes getTokenAttributes(
    CXToken tok, CXCursor cur, CXTranslationUnit tu)
{
    CXCursorKind k = clang_getCursorKind(cur);
    CXTokenKind tk = clang_getTokenKind(tok);
    if (clang_isPreprocessing(k)) {
        if (k == CXCursor_InclusionDirective) {
            CgStr spelling = clang_getTokenSpelling(tu, tok);
            if (std::strcmp(spelling.gets(), "include") != 0
                    && std::strcmp(spelling.gets(), "#") != 0
            ) {
                return TokenAttributes::preIncludeFile;
            }
        }
        return TokenAttributes::pre;
    }

    switch (tk) {
        case CXToken_Punctuation:
            if (k == CXCursor_BinaryOperator || k == CXCursor_UnaryOperator)
                return TokenAttributes::op;
            return TokenAttributes::punct;

        case CXToken_Comment:
            return TokenAttributes::cmmt;

        case CXToken_Literal:
            SYNTH_DISCLANGWARN_BEGIN("-Wswitch-enum")
            switch (k) {
                case CXCursor_ObjCStringLiteral:
                case CXCursor_StringLiteral:
                    return TokenAttributes::litStr;
                case CXCursor_CharacterLiteral:
                    return TokenAttributes::litChr;
                case CXCursor_FloatingLiteral:
                    return TokenAttributes::litNumFlt;
                case CXCursor_IntegerLiteral:
                    return getIntCssClasses(tok, tu);
                case CXCursor_ImaginaryLiteral:
                    return TokenAttributes::litNum;
                default:
                    return TokenAttributes::lit;
            }
            SYNTH_DISCLANGWARN_END

        case CXToken_Keyword: {
            if (k == CXCursor_BinaryOperator || k == CXCursor_UnaryOperator)
                return TokenAttributes::opWord;
            if (k == CXCursor_CXXNullPtrLiteralExpr
                || k == CXCursor_CXXBoolLiteralExpr
                || k == CXCursor_ObjCBoolLiteralExpr
            ) {
                return TokenAttributes::litKw;
            }
            std::string sp = CgStr(clang_getTokenSpelling(tu, tok)).gets();
            if (k == CXCursor_TypeRef || isBuiltinTypeKw(sp))
                return TokenAttributes::tyBuiltin;
            if (clang_isDeclaration(k))
                return TokenAttributes::kwDecl;
            return TokenAttributes::kw;
        }

        case CXToken_Identifier:
            if (isTypeKind(k))
                return TokenAttributes::ty;
            SYNTH_DISCLANGWARN_BEGIN("-Wswitch-enum")
            switch (k) {
                case CXCursor_MemberRef:
                case CXCursor_DeclRefExpr:
                case CXCursor_MemberRefExpr:
                case CXCursor_UsingDeclaration:
                case CXCursor_TemplateRef: {
                    CXCursor refd = clang_getCursorReferenced(cur);
                    return getTokenAttributes(tok, refd, tu);
                }

                case CXCursor_ObjCPropertyDecl:
                    return TokenAttributes::varNonstaticMember; // Sorta right.

                case CXCursor_ObjCIvarDecl:
                case CXCursor_FieldDecl:
                    return TokenAttributes::varNonstaticMember; // TODO

                case CXCursor_EnumConstantDecl:
                case CXCursor_NonTypeTemplateParameter:
                    return TokenAttributes::constant;

                case CXCursor_FunctionDecl:
                case CXCursor_ObjCInstanceMethodDecl:
                case CXCursor_ObjCClassMethodDecl:
                case CXCursor_CXXMethod:
                case CXCursor_FunctionTemplate:
                case CXCursor_Constructor:
                case CXCursor_Destructor:
                case CXCursor_ConversionFunction:
                case CXCursor_OverloadedDeclRef:
                    return TokenAttributes::func;

                case CXCursor_VarDecl:
                    return getVarTokenAttributes(cur);
                case CXCursor_ParmDecl:
                    return TokenAttributes::varLocal;

                case CXCursor_Namespace:
                case CXCursor_NamespaceAlias:
                case CXCursor_UsingDirective:
                case CXCursor_NamespaceRef:
                    return TokenAttributes::namesp;

                case CXCursor_LabelStmt:
                    return TokenAttributes::lbl;

                default:
                    if (clang_isAttribute(k))
                        return TokenAttributes::attr;
                    return TokenAttributes::none;
            }
            SYNTH_DISCLANGWARN_END
            assert("unreachable" && false);
    }
}

static void processToken(FileState& state, CXToken tok, CXCursor cur)
{
    auto& markups = state.hlFile.markups;
    markups.emplace_back();
    Markup& m = markups.back();
    CXTranslationUnit tu = clang_Cursor_getTranslationUnit(cur);
    CXSourceRange rng = clang_getTokenExtent(tu, tok);
    //std::cout << rng << ": " << CgStr(clang_getTokenSpelling(tu, tok)).gets() << '\n';
    unsigned lineno;
    clang_getFileLocation(
        clang_getRangeStart(rng), nullptr, &lineno, nullptr, &m.begin_offset);
    clang_getFileLocation(
        clang_getRangeEnd(rng), nullptr, nullptr, nullptr, &m.end_offset);
    if (m.begin_offset == m.end_offset) {
        markups.pop_back();
        return;
    }

    m.refdFilename = nullptr;
    m.attrs = getTokenAttributes(tok, cur, tu);

    CXTokenKind tk = clang_getTokenKind(tok);
    if (tk == CXToken_Comment || tk == CXToken_Literal)
        return;

    if (!clang_equalLocations(
            clang_getRangeStart(rng), clang_getCursorLocation(cur))
    ) {
        return;
    }

    CXCursorKind k = clang_getCursorKind(cur);
    if (k == CXCursor_InclusionDirective) {
        Markup incLnk = {};
        CXSourceRange incrng = clang_getCursorExtent(cur);
        clang_getFileLocation(
            clang_getRangeStart(incrng),
            nullptr,
            nullptr,
            nullptr,
            &incLnk.begin_offset);
        clang_getFileLocation(
            clang_getRangeEnd(incrng),
            nullptr,
            nullptr,
            nullptr,
            &incLnk.end_offset);
        if (linkInclude(incLnk, cur, state.multiTuProcessor))
            state.hlFile.markups.push_back(std::move(incLnk));
        return;
    }

    if (clang_isDeclaration(k))
        m.attrs |= TokenAttributes::flagDecl;

    // std::cout << CgStr(clang_getTokenSpelling(tu, tok)).gets()
    //     << " " << CgStr(clang_getCursorKindSpelling(k)).gets() << '\n';

    // clang_isReference() sometimes reports false negatives, e.g. for
    // overloaded operators, so check manually.
    CXCursor referenced = clang_getCursorReferenced(cur);
    bool isref = !clang_Cursor_isNull(referenced)
        && !clang_equalCursors(cur, referenced);
    if (isref)
        linkCursorIfIncludedDst(m, referenced, lineno, state.multiTuProcessor);

    CXCursor defcur = clang_getCursorDefinition(cur);
    if (clang_equalCursors(defcur, cur)) { // This is a definition:
        m.attrs |= TokenAttributes::flagDef;
        CgStr usr(clang_getCursorUSR(cur));
        if (!usr.empty()) {
            SymbolDeclaration decl {
                usr.get(),
                state.hlFile.originalPath,
                lineno
            };
            state.multiTuProcessor.registerDef(std::move(decl));
        }
    } else if (!isref) {
        if (clang_Cursor_isNull(defcur)) {
            CgStr usr(clang_getCursorUSR(cur));
            if (!usr.empty()) {
                state.multiTuProcessor.registerMissingDefLink(
                    state.hlFileIdx,
                    state.hlFile.markups.size() - 1,
                    usr.get());
            }
        } else {
            linkCursorIfIncludedDst(m, defcur, lineno, state.multiTuProcessor);
        }
    }
}

namespace {

struct IncVisitorData {
    MultiTuProcessor& multiTuProcessor;
    CXTranslationUnit tu;
};

} // anonymous namespace

static void processFile(
    CXFile file, CXSourceLocation*, unsigned, CXClientData ud)
{
    auto& cdata = *static_cast<IncVisitorData*>(ud);
    CXTranslationUnit tu = cdata.tu;
    MultiTuProcessor& multiTuProcessor = cdata.multiTuProcessor;

    CXSourceLocation beg = clang_getLocationForOffset(tu, file, 0);
    CXSourceLocation end = clang_getLocation(tu, file, UINT_MAX, UINT_MAX);

    auto output = multiTuProcessor.prepareToProcess(file);
    if (!output.first)
        return;

    CXToken* tokens;
    unsigned numTokens;
    clang_tokenize(tu, clang_getRange(beg, end), &tokens, &numTokens);
    CgTokensCleanup tokCleanup(tokens, numTokens, tu);

    if (numTokens > 0) {
        FileState state {*output.first, output.second, multiTuProcessor};
        std::vector<CXCursor> tokCurs(numTokens);
        clang_annotateTokens(tu, tokens, numTokens, tokCurs.data());
        for (unsigned i = 0; i < numTokens - 1; ++i) {
            CXCursor cur = tokCurs[i];
            CXSourceLocation tokLoc = clang_getTokenLocation(tu, tokens[i]);
            if (!clang_equalLocations(clang_getCursorLocation(cur), tokLoc)) {
                CXCursor c2 = clang_getCursor(tu, tokLoc);
                if (clang_equalLocations(clang_getCursorLocation(c2), tokLoc))
                    cur = c2;
            }
            processToken(state, tokens[i], cur);
        }
    }
    std::cout << "Processed " << numTokens << " tokens in "
              << *output.first->originalPath << '\n';
}

int synth::processTu(
    CXIndex cidx,
    MultiTuProcessor& state,
    char const* const* args,
    int nargs)
{
    CXTranslationUnit tu = nullptr;
    CXErrorCode err = clang_parseTranslationUnit2FullArgv(
        cidx,
        /*source_filename:*/ nullptr, // Included in commandline.
        args,
        nargs,
        /*unsaved_files:*/ nullptr,
        /*num_unsaved_files:*/ 0,
        CXTranslationUnit_DetailedPreprocessingRecord,
        &tu);
    CgTuHandle htu(tu);
    if (err != CXError_Success) {
        std::cerr << "Failed parsing translation unit (code "
                  << static_cast<int>(err)
                  << ")\n";
        std::cerr << "  args:";
        for (int i = 0; i < nargs; ++i)
            std::cerr << ' ' << args[i];
        std::cerr << '\n';
        return err + 10;
    }

    IncVisitorData ud {state, tu};
    clang_getInclusions(tu, &processFile, &ud);
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "stdafx.h"

#include <zorba/item.h>
#include <zorba/zorba_string.h>
#include <zorba/zorba_exception.h>
#include <zorba/diagnostic_handler.h>

#include "diagnostics/xquery_diagnostics.h"
#include "util/mem_sizeof.h"
#include "zorbautils/lock.h"

#include "system/globalenv.h"

#include "api/zorbaimpl.h"
#include "api/serialization/serializer.h"
#include "api/item_iter_store.h"
#include "api/item_iter_singleton.h"
#include "api/unmarshaller.h"

#include "store/api/item.h"
#include "store/api/item_factory.h"
#include "store/api/store.h"
#include "store/api/iterator.h"
#include "store/api/collection.h"

#include "zorbatypes/float.h"
#include "zorbatypes/integer.h"
#include "zorbatypes/numconversions.h"

namespace zorba {

#define ITEM_TRY try {

#define ITEM_CATCH \
  } catch (ZorbaException const & /* e */) { \
    throw; \
  } catch (std::exception const &e) { \
    throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR, ERROR_PARAMS(e.what())); \
  } catch (...) { \
    throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR); \
  }

Item::Item(const store::Item* other)
  :
  m_item(const_cast<store::Item*>(other))
{
  if (!isNull())
  {
    m_item->addReference();
  }
}

Item::Item()
  :
  m_item(NULL)
{
}

Item::Item(const Item& other)
  :
  m_item(other.m_item)
{
  if (!isNull())
  {
    m_item->addReference();
  }
}

Item::~Item()
{
  close();
}

size_t
Item::mem_size() const
{
  return ztd::mem_sizeof( m_item );
}

void
Item::close()
{
  if (!isNull())
  {
    m_item->removeReference();
    m_item = NULL;
  }
}

const Item& Item::operator =(const Item& rhs)
{
  if (m_item != rhs.m_item)
  {
    close();
    m_item = rhs.m_item;
    if (!isNull())
    {
      m_item->addReference();
    }
  }
  return *this;
}

const Item& Item::operator =(const store::Item* rhs)
{
  if (m_item != rhs)
  {
    close();
    m_item = const_cast<store::Item*>(rhs);
    if (!isNull())
    {
      m_item->addReference();
    }
  }
  return *this;
}

bool
Item::isNode() const
{
  ITEM_TRY
    return m_item->isNode();
  ITEM_CATCH
  return false;
}

bool
Item::isAtomic() const
{
  ITEM_TRY
    return m_item->isAtomic();
  ITEM_CATCH
  return false;
}

bool
Item::isNull() const
{
  ITEM_TRY
    return m_item == NULL;
  ITEM_CATCH
  return false;
}

store::SchemaTypeCode
Item::getTypeCode() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getTypeCode();

  ITEM_CATCH
    return store::XS_ANY_ATOMIC;
}

Item Item::getType() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return &*m_item->getType();

  ITEM_CATCH
  return Item();
}

bool
Item::isJSONItem() const
{
  ITEM_TRY
    return m_item->isObject() || m_item->isArray();
  ITEM_CATCH
  return false;
}

Iterator_t Item::getAtomizationValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    store::Item_t typedVal;
    store::Iterator_t typedIter;

    m_item->getTypedValue(typedVal, typedIter);

    if (typedIter == NULL)
    {
      return new API_SingletonIterator(typedVal, NULL);
    }
    else
    {
      return new StoreIteratorImpl(typedIter, NULL);
    }

  ITEM_CATCH
  return NULL;
}

String Item::getStringValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getStringValue().str();

  ITEM_CATCH
  return String((const char*)0);
}

int32_t Item::getIntValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getIntValue();

  ITEM_CATCH
  return 0;
}

uint32_t Item::getUnsignedIntValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getUnsignedIntValue();

  ITEM_CATCH
  return 0;
}

xs_long Item::getLongValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getLongValue();

  ITEM_CATCH
  return 0;

}

double Item::getDoubleValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getDoubleValue().getNumber();

  ITEM_CATCH
  return 0;
}

Item Item::getEBV() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    bool value = m_item->getEBV();

    store::Item_t result;
    GENV_ITEMFACTORY->createBoolean(result, value);

    return result.getp();

  ITEM_CATCH
  return Item();
}

/** QName Item */
String Item::getPrefix() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getPrefix().str();

  ITEM_CATCH
  return "";
}

String Item::getLocalName() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getLocalName().str();

  ITEM_CATCH
  return "";
}

String Item::getNamespace() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getNamespace().str();

  ITEM_CATCH
  return "";
}

/** Numeric Items */

bool Item::isNaN() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isNaN();

  ITEM_CATCH
  return false;
}

// @return true, if containing numbers represents -INF or +INF
bool Item::isPosOrNegInf() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isPosOrNegInf();

  ITEM_CATCH
  return false;
}

/** Boolean Items */
bool
Item::getBooleanValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getBooleanValue();

  ITEM_CATCH
  return false;
}

/** Node Items */
Iterator_t
Item::getChildren() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    // TODO, we should have an error handler here
    return new StoreIteratorImpl(m_item->getChildren(), 0);

  ITEM_CATCH
  return NULL;
}

Iterator_t
Item::getAttributes() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    // TODO, we should have an error handler here
    return new StoreIteratorImpl(m_item->getAttributes(), 0);

  ITEM_CATCH
  return NULL;
}

void
Item::getNamespaceBindings(NsBindings& aBindings,
                           store::StoreConsts::NsScoping aNsScoping) const
{
  ITEM_TRY
      SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

      store::NsBindings lStoreBindings;
      m_item->getNamespaceBindings(lStoreBindings, aNsScoping);
      aBindings.reserve(aBindings.size() + lStoreBindings.size());

      store::NsBindings::iterator ite = lStoreBindings.begin();
      store::NsBindings::iterator end = lStoreBindings.end();
      for (; ite != end; ++ite) {
        zstring& prefix = ite->first;
        zstring& nsuri = ite->second;
        aBindings.push_back(
            std::pair<String, String>(
              Unmarshaller::newString(prefix),
              Unmarshaller::newString(nsuri))
          );
      }

  ITEM_CATCH
}

Item
Item::getParent() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)
    return &*m_item->getParent();
  ITEM_CATCH
  return Item();
}

bool
Item::getNodeName(Item& aNodeName) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    store::Item* lNodeName = m_item->getNodeName();

    aNodeName = lNodeName;
    return true;

  ITEM_CATCH
  return false;
}

int
Item::getNodeKind() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getNodeKind();
  ITEM_CATCH
  return -1;
}

store::StoreConsts::JSONItemKind
Item::getJSONItemKind() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getJSONItemKind();
  ITEM_CATCH
  return store::StoreConsts::jsonItem;
}

uint64_t
Item::getArraySize() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return to_xs_long(m_item->getArraySize());
  ITEM_CATCH
  return 0;
}

Item
Item::getArrayValue(uint32_t aIndex) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)
    xs_integer lIndex(aIndex);
    return &*m_item->getArrayValue(lIndex);
  ITEM_CATCH
  return Item();
}

Iterator_t
Item::getObjectKeys() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return new StoreIteratorImpl(m_item->getObjectKeys(), nullptr);

  ITEM_CATCH
  return NULL;
}

Item
Item::getObjectValue(String const &aName) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)
    zstring& lName = Unmarshaller::getInternalString(aName);

    store::Item_t lStringItem;
    GENV_ITEMFACTORY->createString(lStringItem, lName);

    return m_item->getObjectValue(lStringItem).getp();

  ITEM_CATCH
  return Item();
}

bool
Item::isStreamable() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isStreamable();
  ITEM_CATCH
  return false;
}

bool
Item::isSeekable() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isSeekable();
  ITEM_CATCH
  return false;
}

std::istream&
Item::getStream()
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getStream();
  ITEM_CATCH
  // TODO: throw exception
}

bool
Item::isEncoded() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isEncoded();
  ITEM_CATCH
  // TODO: throw exception
}

const char*
Item::getBase64BinaryValue(size_t& s) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getBase64BinaryValue(s);
  ITEM_CATCH
  // TODO: throw exception
}

Item
Item::getCollectionName() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    if (!m_item->isNode()) {
      return 0;
    }
    const store::Collection* lColl = m_item->getCollection();
    if (lColl) {
      return lColl->getName();
    } else {
      return 0;
    }
  ITEM_CATCH
  return 0;
}

const char*
Item::getHexBinaryValue(size_t& s) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getHexBinaryValue(s);
  ITEM_CATCH
  // TODO: throw exception
}

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<commit_msg>Fixed getObjectValue().<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "stdafx.h"

#include <zorba/item.h>
#include <zorba/zorba_string.h>
#include <zorba/zorba_exception.h>
#include <zorba/diagnostic_handler.h>

#include "diagnostics/xquery_diagnostics.h"
#include "util/mem_sizeof.h"
#include "zorbautils/lock.h"

#include "system/globalenv.h"

#include "api/zorbaimpl.h"
#include "api/serialization/serializer.h"
#include "api/item_iter_store.h"
#include "api/item_iter_singleton.h"
#include "api/unmarshaller.h"

#include "store/api/item.h"
#include "store/api/item_factory.h"
#include "store/api/store.h"
#include "store/api/iterator.h"
#include "store/api/collection.h"

#include "zorbatypes/float.h"
#include "zorbatypes/integer.h"
#include "zorbatypes/numconversions.h"

namespace zorba {

#define ITEM_TRY try {

#define ITEM_CATCH \
  } catch (ZorbaException const & /* e */) { \
    throw; \
  } catch (std::exception const &e) { \
    throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR, ERROR_PARAMS(e.what())); \
  } catch (...) { \
    throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR); \
  }

Item::Item(const store::Item* other)
  :
  m_item(const_cast<store::Item*>(other))
{
  if (!isNull())
  {
    m_item->addReference();
  }
}

Item::Item()
  :
  m_item(NULL)
{
}

Item::Item(const Item& other)
  :
  m_item(other.m_item)
{
  if (!isNull())
  {
    m_item->addReference();
  }
}

Item::~Item()
{
  close();
}

size_t
Item::mem_size() const
{
  return ztd::mem_sizeof( m_item );
}

void
Item::close()
{
  if (!isNull())
  {
    m_item->removeReference();
    m_item = NULL;
  }
}

const Item& Item::operator =(const Item& rhs)
{
  if (m_item != rhs.m_item)
  {
    close();
    m_item = rhs.m_item;
    if (!isNull())
    {
      m_item->addReference();
    }
  }
  return *this;
}

const Item& Item::operator =(const store::Item* rhs)
{
  if (m_item != rhs)
  {
    close();
    m_item = const_cast<store::Item*>(rhs);
    if (!isNull())
    {
      m_item->addReference();
    }
  }
  return *this;
}

bool
Item::isNode() const
{
  ITEM_TRY
    return m_item->isNode();
  ITEM_CATCH
  return false;
}

bool
Item::isAtomic() const
{
  ITEM_TRY
    return m_item->isAtomic();
  ITEM_CATCH
  return false;
}

bool
Item::isNull() const
{
  ITEM_TRY
    return m_item == NULL;
  ITEM_CATCH
  return false;
}

store::SchemaTypeCode
Item::getTypeCode() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getTypeCode();

  ITEM_CATCH
    return store::XS_ANY_ATOMIC;
}

Item Item::getType() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return &*m_item->getType();

  ITEM_CATCH
  return Item();
}

bool
Item::isJSONItem() const
{
  ITEM_TRY
    return m_item->isObject() || m_item->isArray();
  ITEM_CATCH
  return false;
}

Iterator_t Item::getAtomizationValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    store::Item_t typedVal;
    store::Iterator_t typedIter;

    m_item->getTypedValue(typedVal, typedIter);

    if (typedIter == NULL)
    {
      return new API_SingletonIterator(typedVal, NULL);
    }
    else
    {
      return new StoreIteratorImpl(typedIter, NULL);
    }

  ITEM_CATCH
  return NULL;
}

String Item::getStringValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getStringValue().str();

  ITEM_CATCH
  return String((const char*)0);
}

int32_t Item::getIntValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getIntValue();

  ITEM_CATCH
  return 0;
}

uint32_t Item::getUnsignedIntValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getUnsignedIntValue();

  ITEM_CATCH
  return 0;
}

xs_long Item::getLongValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getLongValue();

  ITEM_CATCH
  return 0;

}

double Item::getDoubleValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getDoubleValue().getNumber();

  ITEM_CATCH
  return 0;
}

Item Item::getEBV() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    bool value = m_item->getEBV();

    store::Item_t result;
    GENV_ITEMFACTORY->createBoolean(result, value);

    return result.getp();

  ITEM_CATCH
  return Item();
}

/** QName Item */
String Item::getPrefix() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getPrefix().str();

  ITEM_CATCH
  return "";
}

String Item::getLocalName() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getLocalName().str();

  ITEM_CATCH
  return "";
}

String Item::getNamespace() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getNamespace().str();

  ITEM_CATCH
  return "";
}

/** Numeric Items */

bool Item::isNaN() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isNaN();

  ITEM_CATCH
  return false;
}

// @return true, if containing numbers represents -INF or +INF
bool Item::isPosOrNegInf() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isPosOrNegInf();

  ITEM_CATCH
  return false;
}

/** Boolean Items */
bool
Item::getBooleanValue() const
{
  ITEM_TRY

    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getBooleanValue();

  ITEM_CATCH
  return false;
}

/** Node Items */
Iterator_t
Item::getChildren() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    // TODO, we should have an error handler here
    return new StoreIteratorImpl(m_item->getChildren(), 0);

  ITEM_CATCH
  return NULL;
}

Iterator_t
Item::getAttributes() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    // TODO, we should have an error handler here
    return new StoreIteratorImpl(m_item->getAttributes(), 0);

  ITEM_CATCH
  return NULL;
}

void
Item::getNamespaceBindings(NsBindings& aBindings,
                           store::StoreConsts::NsScoping aNsScoping) const
{
  ITEM_TRY
      SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

      store::NsBindings lStoreBindings;
      m_item->getNamespaceBindings(lStoreBindings, aNsScoping);
      aBindings.reserve(aBindings.size() + lStoreBindings.size());

      store::NsBindings::iterator ite = lStoreBindings.begin();
      store::NsBindings::iterator end = lStoreBindings.end();
      for (; ite != end; ++ite) {
        zstring& prefix = ite->first;
        zstring& nsuri = ite->second;
        aBindings.push_back(
            std::pair<String, String>(
              Unmarshaller::newString(prefix),
              Unmarshaller::newString(nsuri))
          );
      }

  ITEM_CATCH
}

Item
Item::getParent() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)
    return &*m_item->getParent();
  ITEM_CATCH
  return Item();
}

bool
Item::getNodeName(Item& aNodeName) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    store::Item* lNodeName = m_item->getNodeName();

    aNodeName = lNodeName;
    return true;

  ITEM_CATCH
  return false;
}

int
Item::getNodeKind() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getNodeKind();
  ITEM_CATCH
  return -1;
}

store::StoreConsts::JSONItemKind
Item::getJSONItemKind() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getJSONItemKind();
  ITEM_CATCH
  return store::StoreConsts::jsonItem;
}

uint64_t
Item::getArraySize() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return to_xs_long(m_item->getArraySize());
  ITEM_CATCH
  return 0;
}

Item
Item::getArrayValue(uint32_t aIndex) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)
    xs_integer lIndex(aIndex);
    return &*m_item->getArrayValue(lIndex);
  ITEM_CATCH
  return Item();
}

Iterator_t
Item::getObjectKeys() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return new StoreIteratorImpl(m_item->getObjectKeys(), nullptr);

  ITEM_CATCH
  return NULL;
}

Item
Item::getObjectValue(String const &aName) const
{
  String lName( aName ); // copy needed because createString() is destructive
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)
    zstring& liName = Unmarshaller::getInternalString(lName);

    store::Item_t lStringItem;
    GENV_ITEMFACTORY->createString(lStringItem, liName);

    return m_item->getObjectValue(lStringItem).getp();

  ITEM_CATCH
  return Item();
}

bool
Item::isStreamable() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isStreamable();
  ITEM_CATCH
  return false;
}

bool
Item::isSeekable() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isSeekable();
  ITEM_CATCH
  return false;
}

std::istream&
Item::getStream()
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getStream();
  ITEM_CATCH
  // TODO: throw exception
}

bool
Item::isEncoded() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->isEncoded();
  ITEM_CATCH
  // TODO: throw exception
}

const char*
Item::getBase64BinaryValue(size_t& s) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getBase64BinaryValue(s);
  ITEM_CATCH
  // TODO: throw exception
}

Item
Item::getCollectionName() const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    if (!m_item->isNode()) {
      return 0;
    }
    const store::Collection* lColl = m_item->getCollection();
    if (lColl) {
      return lColl->getName();
    } else {
      return 0;
    }
  ITEM_CATCH
  return 0;
}

const char*
Item::getHexBinaryValue(size_t& s) const
{
  ITEM_TRY
    SYNC_CODE(AutoLock lock(GENV_STORE.getGlobalLock(), Lock::READ);)

    return m_item->getHexBinaryValue(s);
  ITEM_CATCH
  // TODO: throw exception
}

} // namespace zorba
/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before>/**************************************************************************
 * This file contains the Kvasir Register Abstraction DSL (Domain Specific Language)
 * which provide an extra layer between Hardware SFRs
 * (Special Function Registers) and code accessing them.
 * Copyright 2015 Odin Holmes
 * Aditional contribution from Stephan Bökelmann

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
****************************************************************************/
#pragma once
#include "Types.hpp"

namespace Kvasir{
namespace Register{
	constexpr unsigned maskFromRange(int high, int low){
		return (0xFFFFFFFFULL >> (31-(high-low)))<<low;
	}
	template<typename... Is>
	constexpr unsigned maskFromRange(int high, int low, Is...args){
		return maskFromRange(high,low) | maskFromRange(args...);
	}
	namespace Detail{
		using namespace MPL;

		constexpr int maskStartsAt(unsigned mask, int bitNum = 0) {
			return mask & 1 ? bitNum : maskStartsAt(mask >> 1, bitNum + 1);
		}

		constexpr bool onlyOneBitSet(unsigned i){
			return 	(i==(1u<<0)) ||
					(i==(1u<<1)) ||
					(i==(1u<<2)) ||
					(i==(1u<<3)) ||
					(i==(1u<<4)) ||
					(i==(1u<<5)) ||
					(i==(1u<<6)) ||
					(i==(1u<<7)) ||
					(i==(1u<<8)) ||
					(i==(1u<<9)) ||
					(i==(1u<<10)) ||
					(i==(1u<<11)) ||
					(i==(1u<<12)) ||
					(i==(1u<<13)) ||
					(i==(1u<<14)) ||
					(i==(1u<<15)) ||
					(i==(1u<<16)) ||
					(i==(1u<<17)) ||
					(i==(1u<<18)) ||
					(i==(1u<<19)) ||
					(i==(1u<<20)) ||
					(i==(1u<<21)) ||
					(i==(1u<<22)) ||
					(i==(1u<<23)) ||
					(i==(1u<<24)) ||
					(i==(1u<<25)) ||
					(i==(1u<<26)) ||
					(i==(1u<<27)) ||
					(i==(1u<<28)) ||
					(i==(1u<<29)) ||
					(i==(1u<<30)) ||
					(i==(1u<<31));
		}

		constexpr unsigned orAllOf(){
			return 0;
		}
		constexpr unsigned orAllOf(unsigned l){
			return l;
		}

		template<typename... Ts>
		constexpr unsigned orAllOf(unsigned l, unsigned r, Ts... args){
			return l | r | orAllOf(args...);
		}

		template<typename T>
		struct ValueToUnsigned;
		template<typename T, T I>
		struct ValueToUnsigned<MPL::Value<T,I>> : MPL::Unsigned<unsigned(I)>{};

		template<typename T>
		struct GetFieldType;
		template<typename TAddress, unsigned Mask, typename TAccess, typename TFieldType, typename TAction>
		struct GetFieldType<Action<FieldLocation<TAddress,Mask,TAccess,TFieldType>,TAction>> {
			using Type = TFieldType;
		};
		template<typename TAddress, unsigned Mask, typename TAccess, typename TFieldType>
		struct GetFieldType<FieldLocation<TAddress,Mask,TAccess,TFieldType>>{
			using Type = TFieldType;
		};
		template<typename T>
		using GetFieldTypeT = typename GetFieldType<T>::Type;

		template<typename T>
		struct IsWriteLiteral : std::false_type{};

		template<typename T>
		struct IsWriteRuntime : std::false_type{};

		template<typename T>
		struct IsFieldLocation : std::false_type{};
		template<typename TAddress, unsigned Mask, typename Access, typename TFieldType>
		struct IsFieldLocation<FieldLocation<TAddress, Mask, Access, TFieldType>> : std::true_type {};

		template<typename T>
		struct IsWritable : std::false_type{};
		template<typename TAddress, unsigned Mask, ReadActionType RAction, ModifiedWriteValueType WAction, typename TFieldType>
		struct IsWritable<FieldLocation<TAddress, Mask, Access<AccessType::readWrite, RAction, WAction>, TFieldType>> : std::true_type {};
		template<typename TAddress, unsigned Mask, ReadActionType RAction, ModifiedWriteValueType WAction, typename TFieldType>
		struct IsWritable<FieldLocation<TAddress, Mask, Access<AccessType::writeOnly, RAction, WAction>, TFieldType>> : std::true_type {};

		template<typename T>
		struct IsSetToClear : std::false_type{};
		template<typename TAddress, unsigned Mask, AccessType AT, ReadActionType RAction, typename TFieldType>
		struct IsSetToClear<FieldLocation<TAddress, Mask, Access<AT, RAction, ModifiedWriteValueType::oneToClear>, TFieldType>> : std::true_type {};

		template<typename T, typename U>
		struct WriteLocationAndCompileTimeValueTypeAreSame : std::false_type {};
		template<typename AT, unsigned M, typename A, typename FT, FT V>
		struct WriteLocationAndCompileTimeValueTypeAreSame<FieldLocation<AT, M, A, FT>,MPL::Value<FT,V>> : std::true_type{};

		//getters for specific parameters of an Action
		template<typename T>
		struct GetAddress;
		template<unsigned A, unsigned WIIZ, unsigned SOTC, typename TRegType, typename TMode>
		struct GetAddress<Address<A,WIIZ,SOTC,TRegType,TMode>> {
			static constexpr unsigned value = A;
			static unsigned read(){
				volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				return reg;
			}
			static void write(unsigned i){
				volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				reg = i;
			}
			using type = brigand::uint32_t<A>;
		};
		template<typename TAddress, unsigned Mask, typename TAccess, typename TFiledType>
		struct GetAddress<FieldLocation<TAddress,Mask,TAccess,TFiledType>> {
			static constexpr unsigned value = TAddress::value;
			static unsigned read(){
				volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				return reg;
			}
			static void write(unsigned i){
				volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				reg = i;
			}
			using type = brigand::uint32_t<TAddress::value>;
		};
		template<typename TReadLoc, typename TWriteLoc>
		struct GetAddress<FieldLocationPair<TReadLoc,TWriteLoc>> {
			static constexpr unsigned value = TReadLoc::value;
			static unsigned read(){
				volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				return reg;
			}
			static void write(unsigned i){
				volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				reg = i;
			}
			using type = brigand::uint32_t<value>;
		};
		template<typename TFieldLocation, typename TAction>
		struct GetAddress<Action<TFieldLocation,TAction>> : GetAddress<TFieldLocation> {};

		template<typename T>
		struct GetFieldLocation;
		template<typename TLocation, typename TAction>
		struct GetFieldLocation<Action<TLocation,TAction>>{
			using type = TLocation;
		};

		//predecate retuning result of left < right for RegisterOptions
		template<typename TLeft, typename TRight>
		struct RegisterActionLess;
		template<typename T1, typename U1, typename T2, typename U2>
		struct RegisterActionLess< Register::Action<T1,U1>, Register::Action<T2,U2> > : Bool<(GetAddress<T1>::value < GetAddress<T2>::value)>{};
		using RegisterActionLessP = Template<RegisterActionLess>;

		//predicate returns true if action is a read
		template<typename T>
		struct IsReadPred : std::false_type {};
		template<typename A>
		struct IsReadPred< Register::Action<A,ReadAction> > : std::true_type{};

		template<typename T>
		struct IsNotReadPred : std::integral_constant<bool,(!IsReadPred<T>::type::value)>{};

		template<typename T>
		struct GetMask;
		//from FieldLocations
		template<typename Address, unsigned Mask, typename TAccess, typename ResultType>
		struct GetMask<FieldLocation<Address,Mask,TAccess,ResultType>> : Value<unsigned,Mask>{};
		//from Action
		template<typename TFieldLocation, typename TAction>
		struct GetMask<Action<TFieldLocation,TAction>> : GetMask<TFieldLocation>{};

	}
}
}
<commit_msg>fixed reg type bug<commit_after>/**************************************************************************
 * This file contains the Kvasir Register Abstraction DSL (Domain Specific Language)
 * which provide an extra layer between Hardware SFRs
 * (Special Function Registers) and code accessing them.
 * Copyright 2015 Odin Holmes
 * Aditional contribution from Stephan Bökelmann

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
****************************************************************************/
#pragma once
#include "Types.hpp"

namespace Kvasir{
namespace Register{
	constexpr unsigned maskFromRange(int high, int low){
		return (0xFFFFFFFFULL >> (31-(high-low)))<<low;
	}
	template<typename... Is>
	constexpr unsigned maskFromRange(int high, int low, Is...args){
		return maskFromRange(high,low) | maskFromRange(args...);
	}
	namespace Detail{
		using namespace MPL;

		constexpr int maskStartsAt(unsigned mask, int bitNum = 0) {
			return mask & 1 ? bitNum : maskStartsAt(mask >> 1, bitNum + 1);
		}

		constexpr bool onlyOneBitSet(unsigned i){
			return 	(i==(1u<<0)) ||
					(i==(1u<<1)) ||
					(i==(1u<<2)) ||
					(i==(1u<<3)) ||
					(i==(1u<<4)) ||
					(i==(1u<<5)) ||
					(i==(1u<<6)) ||
					(i==(1u<<7)) ||
					(i==(1u<<8)) ||
					(i==(1u<<9)) ||
					(i==(1u<<10)) ||
					(i==(1u<<11)) ||
					(i==(1u<<12)) ||
					(i==(1u<<13)) ||
					(i==(1u<<14)) ||
					(i==(1u<<15)) ||
					(i==(1u<<16)) ||
					(i==(1u<<17)) ||
					(i==(1u<<18)) ||
					(i==(1u<<19)) ||
					(i==(1u<<20)) ||
					(i==(1u<<21)) ||
					(i==(1u<<22)) ||
					(i==(1u<<23)) ||
					(i==(1u<<24)) ||
					(i==(1u<<25)) ||
					(i==(1u<<26)) ||
					(i==(1u<<27)) ||
					(i==(1u<<28)) ||
					(i==(1u<<29)) ||
					(i==(1u<<30)) ||
					(i==(1u<<31));
		}

		constexpr unsigned orAllOf(){
			return 0;
		}
		constexpr unsigned orAllOf(unsigned l){
			return l;
		}

		template<typename... Ts>
		constexpr unsigned orAllOf(unsigned l, unsigned r, Ts... args){
			return l | r | orAllOf(args...);
		}

		template<typename T>
		struct ValueToUnsigned;
		template<typename T, T I>
		struct ValueToUnsigned<MPL::Value<T,I>> : MPL::Unsigned<unsigned(I)>{};

		template<typename T>
		struct GetFieldType;
		template<typename TAddress, unsigned Mask, typename TAccess, typename TFieldType, typename TAction>
		struct GetFieldType<Action<FieldLocation<TAddress,Mask,TAccess,TFieldType>,TAction>> {
			using Type = TFieldType;
		};
		template<typename TAddress, unsigned Mask, typename TAccess, typename TFieldType>
		struct GetFieldType<FieldLocation<TAddress,Mask,TAccess,TFieldType>>{
			using Type = TFieldType;
		};
		template<typename T>
		using GetFieldTypeT = typename GetFieldType<T>::Type;

		template<typename T>
		struct IsWriteLiteral : std::false_type{};

		template<typename T>
		struct IsWriteRuntime : std::false_type{};

		template<typename T>
		struct IsFieldLocation : std::false_type{};
		template<typename TAddress, unsigned Mask, typename Access, typename TFieldType>
		struct IsFieldLocation<FieldLocation<TAddress, Mask, Access, TFieldType>> : std::true_type {};

		template<typename T>
		struct IsWritable : std::false_type{};
		template<typename TAddress, unsigned Mask, ReadActionType RAction, ModifiedWriteValueType WAction, typename TFieldType>
		struct IsWritable<FieldLocation<TAddress, Mask, Access<AccessType::readWrite, RAction, WAction>, TFieldType>> : std::true_type {};
		template<typename TAddress, unsigned Mask, ReadActionType RAction, ModifiedWriteValueType WAction, typename TFieldType>
		struct IsWritable<FieldLocation<TAddress, Mask, Access<AccessType::writeOnly, RAction, WAction>, TFieldType>> : std::true_type {};

		template<typename T>
		struct IsSetToClear : std::false_type{};
		template<typename TAddress, unsigned Mask, AccessType AT, ReadActionType RAction, typename TFieldType>
		struct IsSetToClear<FieldLocation<TAddress, Mask, Access<AT, RAction, ModifiedWriteValueType::oneToClear>, TFieldType>> : std::true_type {};

		template<typename T, typename U>
		struct WriteLocationAndCompileTimeValueTypeAreSame : std::false_type {};
		template<typename AT, unsigned M, typename A, typename FT, FT V>
		struct WriteLocationAndCompileTimeValueTypeAreSame<FieldLocation<AT, M, A, FT>,MPL::Value<FT,V>> : std::true_type{};

		//getters for specific parameters of an Action
		template<typename T>
		struct GetAddress;
		template<unsigned A, unsigned WIIZ, unsigned SOTC, typename TRegType, typename TMode>
		struct GetAddress<Address<A,WIIZ,SOTC,TRegType,TMode>> {
			static constexpr unsigned value = A;
			static unsigned read(){
				volatile TRegType& reg = *reinterpret_cast<volatile TRegType*>(value);
				return reg;
			}
			static void write(unsigned i){
				volatile TRegType& reg = *reinterpret_cast<volatile TRegType*>(value);
				reg = i;
			}
			using type = brigand::uint32_t<A>;
		};
		template<typename TAddress, unsigned Mask, typename TAccess, typename TFiledType>
		struct GetAddress<FieldLocation<TAddress, Mask, TAccess, TFiledType>> : GetAddress<TAddress> {};
		//template<typename TReadLoc, typename TWriteLoc>
		//struct GetAddress<FieldLocationPair<TReadLoc,TWriteLoc>> {
			//static constexpr unsigned value = TReadLoc::value;
			//static unsigned read(){
				//volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				//return reg;
			//}
			//static void write(unsigned i){
				//volatile unsigned& reg = *reinterpret_cast<volatile unsigned*>(value);
				//reg = i;
			//}
			//using type = brigand::uint32_t<value>;
		//};
		template<typename TFieldLocation, typename TAction>
		struct GetAddress<Action<TFieldLocation,TAction>> : GetAddress<TFieldLocation> {};

		template<typename T>
		struct GetFieldLocation;
		template<typename TLocation, typename TAction>
		struct GetFieldLocation<Action<TLocation,TAction>>{
			using type = TLocation;
		};

		//predecate retuning result of left < right for RegisterOptions
		template<typename TLeft, typename TRight>
		struct RegisterActionLess;
		template<typename T1, typename U1, typename T2, typename U2>
		struct RegisterActionLess< Register::Action<T1,U1>, Register::Action<T2,U2> > : Bool<(GetAddress<T1>::value < GetAddress<T2>::value)>{};
		using RegisterActionLessP = Template<RegisterActionLess>;

		//predicate returns true if action is a read
		template<typename T>
		struct IsReadPred : std::false_type {};
		template<typename A>
		struct IsReadPred< Register::Action<A,ReadAction> > : std::true_type{};

		template<typename T>
		struct IsNotReadPred : std::integral_constant<bool,(!IsReadPred<T>::type::value)>{};

		template<typename T>
		struct GetMask;
		//from FieldLocations
		template<typename Address, unsigned Mask, typename TAccess, typename ResultType>
		struct GetMask<FieldLocation<Address,Mask,TAccess,ResultType>> : Value<unsigned,Mask>{};
		//from Action
		template<typename TFieldLocation, typename TAction>
		struct GetMask<Action<TFieldLocation,TAction>> : GetMask<TFieldLocation>{};

	}
}
}
<|endoftext|>