<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "Exceptions.hh"
#include "TypeImpl.hh"

namespace orc {

  Type::~Type() {
    // PASS
  }

  TypeImpl::TypeImpl(TypeKind _kind) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = 0;
    scale = 0;
    subtypeCount = 0;
  }

  TypeImpl::TypeImpl(TypeKind _kind, unsigned int _maxLength) {
    columnId = 0;
    kind = _kind;
    maxLength = _maxLength;
    precision = 0;
    scale = 0;
    subtypeCount = 0;
  }

  TypeImpl::TypeImpl(TypeKind _kind, unsigned int _precision,
                     unsigned int _scale) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = _precision;
    scale = _scale;
    subtypeCount = 0;
  }

  TypeImpl::TypeImpl(TypeKind _kind,
                     const std::vector<Type*>& types,
                     const std::vector<std::string>& _fieldNames) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = 0;
    scale = 0;
    subtypeCount = static_cast<unsigned int>(types.size());
    subTypes.assign(types.begin(), types.end());
    fieldNames.assign(_fieldNames.begin(), _fieldNames.end());
  }

  TypeImpl::TypeImpl(TypeKind _kind, const std::vector<Type*>& types) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = 0;
    scale = 0;
    subtypeCount = static_cast<unsigned int>(types.size());
    subTypes.assign(types.begin(), types.end());
  }

  int TypeImpl::assignIds(int root) {
    columnId = root;
    int current = root + 1;
    for(unsigned int i=0; i < subtypeCount; ++i) {
      current = subTypes[i]->assignIds(current);
    }
    return current;
  }

  TypeImpl::~TypeImpl() {
    for (std::vector<Type*>::iterator it = subTypes.begin();
        it != subTypes.end(); it++) {
      delete (*it) ;
    }
  }

  int TypeImpl::getColumnId() const {
    return columnId;
  }

  TypeKind TypeImpl::getKind() const {
    return kind;
  }

  unsigned int TypeImpl::getSubtypeCount() const {
    return subtypeCount;
  }

  const Type& TypeImpl::getSubtype(unsigned int i) const {
    return *(subTypes[i]);
  }

  const std::string& TypeImpl::getFieldName(unsigned int i) const {
    return fieldNames[i];
  }

  unsigned int TypeImpl::getMaximumLength() const {
    return maxLength;
  }

  unsigned int TypeImpl::getPrecision() const {
    return precision;
  }

  unsigned int TypeImpl::getScale() const {
    return scale;
  }

  std::unique_ptr<Type> createPrimitiveType(TypeKind kind) {
    return std::unique_ptr<Type>(new TypeImpl(kind));
  }

  std::unique_ptr<Type> createCharType(TypeKind kind,
                                       unsigned int maxLength) {
    return std::unique_ptr<Type>(new TypeImpl(kind, maxLength));
  }

  std::unique_ptr<Type> createDecimalType(unsigned int precision,
                                          unsigned int scale) {
    return std::unique_ptr<Type>(new TypeImpl(DECIMAL, precision, scale));
  }

  std::unique_ptr<Type>
      createStructType(std::vector<Type*> types,
                       std::vector<std::string> fieldNames) {
    std::vector<Type*> typeVector(types.begin(), types.end());
    std::vector<std::string> fieldVector(fieldNames.begin(), fieldNames.end());

    return std::unique_ptr<Type>(new TypeImpl(STRUCT, typeVector,
                                              fieldVector));
  }

#if __cplusplus >= 201103L
  std::unique_ptr<Type> createStructType(
      std::initializer_list<std::unique_ptr<Type> > types,
      std::initializer_list<std::string> fieldNames) {
    std::vector<Type*> typeVector(types.size());
    std::vector<std::string> fieldVector(types.size());
    auto currentType = types.begin();
    auto endType = types.end();
    size_t current = 0;
    while (currentType != endType) {
      typeVector[current++] =
          const_cast<std::unique_ptr<Type>*>(currentType)->release();
      ++currentType;
    }
    fieldVector.insert(fieldVector.end(), fieldNames.begin(),
        fieldNames.end());
    return std::unique_ptr<Type>(new TypeImpl(STRUCT, typeVector,
        fieldVector));
  }
#endif // __cplusplus

  std::unique_ptr<Type> createListType(std::unique_ptr<Type> elements) {
    std::vector<Type*> subtypes(1);
    subtypes[0] = elements.release();
    return std::unique_ptr<Type>(new TypeImpl(LIST, subtypes));
  }

  std::unique_ptr<Type> createMapType(std::unique_ptr<Type> key,
                                      std::unique_ptr<Type> value) {
    std::vector<Type*> subtypes(2);
    subtypes[0] = key.release();
    subtypes[1] = value.release();
    return std::unique_ptr<Type>(new TypeImpl(MAP, subtypes));
  }

  std::unique_ptr<Type>
      createUnionType(std::vector<Type*> types) {
    std::vector<Type*> typeVector(types.begin(), types.end());
    return std::unique_ptr<Type>(new TypeImpl(UNION, typeVector));
  }

  std::unique_ptr<Type> convertType(const proto::Type& type,
                                    const proto::Footer& footer) {
    switch (static_cast<int>(type.kind())) {

    case proto::Type_Kind_BOOLEAN:
    case proto::Type_Kind_BYTE:
    case proto::Type_Kind_SHORT:
    case proto::Type_Kind_INT:
    case proto::Type_Kind_LONG:
    case proto::Type_Kind_FLOAT:
    case proto::Type_Kind_DOUBLE:
    case proto::Type_Kind_STRING:
    case proto::Type_Kind_BINARY:
    case proto::Type_Kind_TIMESTAMP:
    case proto::Type_Kind_DATE:
      return std::unique_ptr<Type>
        (new TypeImpl(static_cast<TypeKind>(type.kind())));

    case proto::Type_Kind_CHAR:
    case proto::Type_Kind_VARCHAR:
      return std::unique_ptr<Type>
        (new TypeImpl(static_cast<TypeKind>(type.kind()),
                      type.maximumlength()));

    case proto::Type_Kind_DECIMAL:
      return std::unique_ptr<Type>
        (new TypeImpl(DECIMAL, type.precision(), type.scale()));

    case proto::Type_Kind_LIST:
    case proto::Type_Kind_MAP:
    case proto::Type_Kind_UNION: {
      unsigned long size = static_cast<unsigned long>(type.subtypes_size());
      std::vector<Type*> typeList(size);
      for(int i=0; i < type.subtypes_size(); ++i) {
        typeList[static_cast<unsigned int>(i)] =
          convertType(footer.types(static_cast<int>(type.subtypes(i))),
                      footer).release();
      }
      return std::unique_ptr<Type>
        (new TypeImpl(static_cast<TypeKind>(type.kind()), typeList));
    }

    case proto::Type_Kind_STRUCT: {
      unsigned long size = static_cast<unsigned long>(type.subtypes_size());
      std::vector<Type*> typeList(size);
      std::vector<std::string> fieldList(size);
      for(int i=0; i < type.subtypes_size(); ++i) {
        typeList[static_cast<unsigned int>(i)] =
          convertType(footer.types(static_cast<int>(type.subtypes(i))),
                      footer).release();
        fieldList[static_cast<unsigned int>(i)] = type.fieldnames(i);
      }
      return std::unique_ptr<Type>
        (new TypeImpl(STRUCT, typeList, fieldList));
    }
    default:
      throw NotImplementedYet("Unknown type kind");
    }
  }

  std::string kind2String(TypeKind t) {
      std::string name ;
      switch(static_cast<int>(t)) {
        case BOOLEAN: { name = "BOOLEAN"; break; }
        case BYTE: { name = "BYTE"; break; }
        case SHORT: { name = "SHORT"; break; }
        case INT: { name = "INT"; break; }
        case LONG: { name = "LONG"; break; }
        case FLOAT: { name = "FLOAT"; break; }
        case DOUBLE: { name = "DOUBLE"; break; }
        case STRING: { name = "STRING"; break; }
        case BINARY: { name = "BINARY"; break; }
        case TIMESTAMP: { name = "TIMESTAMP"; break; }
        case LIST: { name = "LIST"; break; }
        case MAP: { name = "MAP"; break; }
        case STRUCT: { name = "STRUCT"; break; }
        case UNION: { name = "UNION"; break; }
        case DECIMAL: { name = "DECIMAL"; break; }
        case DATE: { name = "DATE"; break; }
        case VARCHAR: { name = "VARCHAR"; break; }
        case CHAR: { name = "CHAR"; break; }
        default: { name = "UNKNOWN"; break; }
      }
      return name ;
    }

}
<commit_msg>Changed how we print data type names.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "Exceptions.hh"
#include "TypeImpl.hh"

namespace orc {

  Type::~Type() {
    // PASS
  }

  TypeImpl::TypeImpl(TypeKind _kind) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = 0;
    scale = 0;
    subtypeCount = 0;
  }

  TypeImpl::TypeImpl(TypeKind _kind, unsigned int _maxLength) {
    columnId = 0;
    kind = _kind;
    maxLength = _maxLength;
    precision = 0;
    scale = 0;
    subtypeCount = 0;
  }

  TypeImpl::TypeImpl(TypeKind _kind, unsigned int _precision,
                     unsigned int _scale) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = _precision;
    scale = _scale;
    subtypeCount = 0;
  }

  TypeImpl::TypeImpl(TypeKind _kind,
                     const std::vector<Type*>& types,
                     const std::vector<std::string>& _fieldNames) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = 0;
    scale = 0;
    subtypeCount = static_cast<unsigned int>(types.size());
    subTypes.assign(types.begin(), types.end());
    fieldNames.assign(_fieldNames.begin(), _fieldNames.end());
  }

  TypeImpl::TypeImpl(TypeKind _kind, const std::vector<Type*>& types) {
    columnId = 0;
    kind = _kind;
    maxLength = 0;
    precision = 0;
    scale = 0;
    subtypeCount = static_cast<unsigned int>(types.size());
    subTypes.assign(types.begin(), types.end());
  }

  int TypeImpl::assignIds(int root) {
    columnId = root;
    int current = root + 1;
    for(unsigned int i=0; i < subtypeCount; ++i) {
      current = subTypes[i]->assignIds(current);
    }
    return current;
  }

  TypeImpl::~TypeImpl() {
    for (std::vector<Type*>::iterator it = subTypes.begin();
        it != subTypes.end(); it++) {
      delete (*it) ;
    }
  }

  int TypeImpl::getColumnId() const {
    return columnId;
  }

  TypeKind TypeImpl::getKind() const {
    return kind;
  }

  unsigned int TypeImpl::getSubtypeCount() const {
    return subtypeCount;
  }

  const Type& TypeImpl::getSubtype(unsigned int i) const {
    return *(subTypes[i]);
  }

  const std::string& TypeImpl::getFieldName(unsigned int i) const {
    return fieldNames[i];
  }

  unsigned int TypeImpl::getMaximumLength() const {
    return maxLength;
  }

  unsigned int TypeImpl::getPrecision() const {
    return precision;
  }

  unsigned int TypeImpl::getScale() const {
    return scale;
  }

  std::unique_ptr<Type> createPrimitiveType(TypeKind kind) {
    return std::unique_ptr<Type>(new TypeImpl(kind));
  }

  std::unique_ptr<Type> createCharType(TypeKind kind,
                                       unsigned int maxLength) {
    return std::unique_ptr<Type>(new TypeImpl(kind, maxLength));
  }

  std::unique_ptr<Type> createDecimalType(unsigned int precision,
                                          unsigned int scale) {
    return std::unique_ptr<Type>(new TypeImpl(DECIMAL, precision, scale));
  }

  std::unique_ptr<Type>
      createStructType(std::vector<Type*> types,
                       std::vector<std::string> fieldNames) {
    std::vector<Type*> typeVector(types.begin(), types.end());
    std::vector<std::string> fieldVector(fieldNames.begin(), fieldNames.end());

    return std::unique_ptr<Type>(new TypeImpl(STRUCT, typeVector,
                                              fieldVector));
  }

#if __cplusplus >= 201103L
  std::unique_ptr<Type> createStructType(
      std::initializer_list<std::unique_ptr<Type> > types,
      std::initializer_list<std::string> fieldNames) {
    std::vector<Type*> typeVector(types.size());
    std::vector<std::string> fieldVector(types.size());
    auto currentType = types.begin();
    auto endType = types.end();
    size_t current = 0;
    while (currentType != endType) {
      typeVector[current++] =
          const_cast<std::unique_ptr<Type>*>(currentType)->release();
      ++currentType;
    }
    fieldVector.insert(fieldVector.end(), fieldNames.begin(),
        fieldNames.end());
    return std::unique_ptr<Type>(new TypeImpl(STRUCT, typeVector,
        fieldVector));
  }
#endif // __cplusplus

  std::unique_ptr<Type> createListType(std::unique_ptr<Type> elements) {
    std::vector<Type*> subtypes(1);
    subtypes[0] = elements.release();
    return std::unique_ptr<Type>(new TypeImpl(LIST, subtypes));
  }

  std::unique_ptr<Type> createMapType(std::unique_ptr<Type> key,
                                      std::unique_ptr<Type> value) {
    std::vector<Type*> subtypes(2);
    subtypes[0] = key.release();
    subtypes[1] = value.release();
    return std::unique_ptr<Type>(new TypeImpl(MAP, subtypes));
  }

  std::unique_ptr<Type>
      createUnionType(std::vector<Type*> types) {
    std::vector<Type*> typeVector(types.begin(), types.end());
    return std::unique_ptr<Type>(new TypeImpl(UNION, typeVector));
  }

  std::unique_ptr<Type> convertType(const proto::Type& type,
                                    const proto::Footer& footer) {
    switch (static_cast<int>(type.kind())) {

    case proto::Type_Kind_BOOLEAN:
    case proto::Type_Kind_BYTE:
    case proto::Type_Kind_SHORT:
    case proto::Type_Kind_INT:
    case proto::Type_Kind_LONG:
    case proto::Type_Kind_FLOAT:
    case proto::Type_Kind_DOUBLE:
    case proto::Type_Kind_STRING:
    case proto::Type_Kind_BINARY:
    case proto::Type_Kind_TIMESTAMP:
    case proto::Type_Kind_DATE:
      return std::unique_ptr<Type>
        (new TypeImpl(static_cast<TypeKind>(type.kind())));

    case proto::Type_Kind_CHAR:
    case proto::Type_Kind_VARCHAR:
      return std::unique_ptr<Type>
        (new TypeImpl(static_cast<TypeKind>(type.kind()),
                      type.maximumlength()));

    case proto::Type_Kind_DECIMAL:
      return std::unique_ptr<Type>
        (new TypeImpl(DECIMAL, type.precision(), type.scale()));

    case proto::Type_Kind_LIST:
    case proto::Type_Kind_MAP:
    case proto::Type_Kind_UNION: {
      unsigned long size = static_cast<unsigned long>(type.subtypes_size());
      std::vector<Type*> typeList(size);
      for(int i=0; i < type.subtypes_size(); ++i) {
        typeList[static_cast<unsigned int>(i)] =
          convertType(footer.types(static_cast<int>(type.subtypes(i))),
                      footer).release();
      }
      return std::unique_ptr<Type>
        (new TypeImpl(static_cast<TypeKind>(type.kind()), typeList));
    }

    case proto::Type_Kind_STRUCT: {
      unsigned long size = static_cast<unsigned long>(type.subtypes_size());
      std::vector<Type*> typeList(size);
      std::vector<std::string> fieldList(size);
      for(int i=0; i < type.subtypes_size(); ++i) {
        typeList[static_cast<unsigned int>(i)] =
          convertType(footer.types(static_cast<int>(type.subtypes(i))),
                      footer).release();
        fieldList[static_cast<unsigned int>(i)] = type.fieldnames(i);
      }
      return std::unique_ptr<Type>
        (new TypeImpl(STRUCT, typeList, fieldList));
    }
    default:
      throw NotImplementedYet("Unknown type kind");
    }
  }

  std::string kind2String(TypeKind t) {
      std::string name ;
      switch(static_cast<int>(t)) {
        case BOOLEAN: { name = "BOOLEAN"; break; }
        case BYTE: { name = "TINYINT"; break; }
        case SHORT: { name = "SMALLINT"; break; }
        case INT: { name = "INT"; break; }
        case LONG: { name = "BIGINT"; break; }
        case FLOAT: { name = "FLOAT"; break; }
        case DOUBLE: { name = "DOUBLE"; break; }
        case STRING: { name = "STRING"; break; }
        case BINARY: { name = "BINARY"; break; }
        case TIMESTAMP: { name = "TIMESTAMP"; break; }
        case LIST: { name = "LIST"; break; }
        case MAP: { name = "MAP"; break; }
        case STRUCT: { name = "STRUCT"; break; }
        case UNION: { name = "UNION"; break; }
        case DECIMAL: { name = "DECIMAL"; break; }
        case DATE: { name = "DATE"; break; }
        case VARCHAR: { name = "VARCHAR"; break; }
        case CHAR: { name = "CHAR"; break; }
        default: { name = "UNKNOWN"; break; }
      }
      return name ;
    }

}
<|endoftext|>


<commit_before>// Utf8_16.cxx
// Copyright (C) 2002 Scott Kirkwood
//
// Permission to use, copy, modify, distribute and sell this code
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies or
// any derived copies.  Scott Kirkwood makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////

#include "Utf8_16.h"

#include <stdio.h>

const Utf8_16::utf8 Utf8_16::k_Boms[][3] = {
	{0x00, 0x00, 0x00},  // Unknown
	{0xFE, 0xFF, 0x00},  // Big endian
	{0xFF, 0xFE, 0x00},  // Little endian
	{0xEF, 0xBB, 0xBF}, // UTF8
};

// ==================================================================

Utf8_16_Read::Utf8_16_Read() {
	m_eEncoding = eUnknown;
	m_nBufSize = 0;
	m_pNewBuf = NULL;
	m_bFirstRead = true;
}

Utf8_16_Read::~Utf8_16_Read() {
	if ((m_eEncoding != eUnknown) && (m_eEncoding != eUtf8)) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
	}
}

size_t Utf8_16_Read::convert(char* buf, size_t len) {
	m_pBuf = reinterpret_cast<ubyte*>(buf);
	m_nLen = len;

	int nSkip = 0;
	if (m_bFirstRead) {
		nSkip = determineEncoding();
		m_bFirstRead = false;
	}

	if (m_eEncoding == eUnknown) {
		// Do nothing, pass through
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf;
		return len;
	}

	if (m_eEncoding == eUtf8) {
		// Pass through after BOM
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf + nSkip;
		return len - nSkip;
	}

	// Else...
	size_t newSize = len + len / 2 + 1;
	if (m_nBufSize != newSize) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
		m_pNewBuf = new ubyte[newSize];
		m_nBufSize = newSize;
	}

	ubyte* pCur = m_pNewBuf;

	m_Iter16.set(m_pBuf + nSkip, len - nSkip, m_eEncoding);

	for (; m_Iter16; ++m_Iter16) {
		*pCur++ = m_Iter16.get();
	}

	// Return number of bytes writen out
	return pCur - m_pNewBuf;
}

int Utf8_16_Read::determineEncoding() {
	m_eEncoding = eUnknown;

	int nRet = 0;

	if (m_nLen > 1) {
		if (m_pBuf[0] == k_Boms[eUtf16BigEndian][0] && m_pBuf[1] == k_Boms[eUtf16BigEndian][1]) {
			m_eEncoding = eUtf16BigEndian;
			nRet = 2;
		} else if (m_pBuf[0] == k_Boms[eUtf16LittleEndian][0] && m_pBuf[1] == k_Boms[eUtf16LittleEndian][1]) {
			m_eEncoding = eUtf16LittleEndian;
			nRet = 2;
		} else if (m_nLen > 2 && m_pBuf[0] == k_Boms[eUtf8][0] && m_pBuf[1] == k_Boms[eUtf8][1] && m_pBuf[2] == k_Boms[eUtf8][2]) {
			m_eEncoding = eUtf8;
			nRet = 3;
		}
	}

	return nRet;
}

// ==================================================================

Utf8_16_Write::Utf8_16_Write() {
	m_eEncoding = eUnknown;
	m_pFile = NULL;
	m_pBuf = NULL;
	m_bFirstWrite = true;
	m_nBufSize = 0;
}

Utf8_16_Write::~Utf8_16_Write() {
	if (m_pFile) {
		fclose();
	}
}

FILE * Utf8_16_Write::fopen(const char *_name, const char *_type) {
	m_pFile = ::fopen(_name, _type);

	m_bFirstWrite = true;

	return m_pFile;
}

size_t Utf8_16_Write::fwrite(const void* p, size_t _size) {
	if (!m_pFile) {
		return 0; // fail
	}

	if (m_eEncoding == eUnknown) {
		// Normal write
		return ::fwrite(p, _size, 1, m_pFile);
	}

	if (m_eEncoding == eUtf8) {
		if (m_bFirstWrite)
			::fwrite(k_Boms[m_eEncoding], 3, 1, m_pFile);
		m_bFirstWrite = false;
		return ::fwrite(p, _size, 1, m_pFile);
	}

	if (_size > m_nBufSize) {
		m_nBufSize = _size;
		delete [] m_pBuf;
		m_pBuf = NULL;
		m_pBuf = new utf16[_size + 1];
	}

	if (m_bFirstWrite) {
		if (m_eEncoding == eUtf16BigEndian || m_eEncoding == eUtf16LittleEndian) {
			// Write the BOM
			::fwrite(k_Boms[m_eEncoding], 2, 1, m_pFile);
		}

		m_bFirstWrite = false;
	}

	Utf8_Iter iter8;
	iter8.set(static_cast<const ubyte*>(p), _size, m_eEncoding);

	utf16* pCur = m_pBuf;

	for (; iter8; ++iter8) {
		if (iter8.canGet()) {
			*pCur++ = iter8.get();
		}
	}

	size_t ret = ::fwrite(m_pBuf, (const char*)pCur - (const char*)m_pBuf, 1, m_pFile);

	return ret;
}

void Utf8_16_Write::fclose() {
	delete [] m_pBuf;
	m_pBuf = NULL;

	::fclose(m_pFile);
	m_pFile = NULL;
}

void Utf8_16_Write::setEncoding(Utf8_16::encodingType eType) {
	m_eEncoding = eType;
}

//=================================================================
Utf8_Iter::Utf8_Iter() {
	reset();
}

void Utf8_Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eState = eStart;
	m_nCur = 0;
	m_eEncoding = eUnknown;
}

void Utf8_Iter::set
	(const ubyte* pBuf, size_t nLen, encodingType eEncoding) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + nLen;
	m_eEncoding = eEncoding;
	operator++();
	// Note: m_eState, m_nCur not reset
}
// Go to the next byte.
void Utf8_Iter::operator++() {
	switch (m_eState) {
	case eStart:
		if ((0xE0 & *m_pRead) == 0xE0) {
			m_nCur = static_cast<utf16>((~0xE0 & *m_pRead) << 12);
			m_eState = e3Bytes_Byte2;
		} else if ((0xC0 & *m_pRead) == 0xC0) {
			m_nCur = static_cast<utf16>((~0xC0 & *m_pRead) << 6);
			m_eState = e2Bytes_Byte2;
		} else {
			m_nCur = *m_pRead;
			toStart();
		}
		break;
	case e2Bytes_Byte2:
		m_nCur |= static_cast<utf8>(0x3F & *m_pRead);
		toStart();
		break;
	case e3Bytes_Byte2:
		m_nCur |= static_cast<utf8>((0x3F & *m_pRead) << 6);
		m_eState = e3Bytes_Byte3;
		break;
	case e3Bytes_Byte3:
		m_nCur |= static_cast<utf8>(0x3F & *m_pRead);
		toStart();
		break;
	}
	++m_pRead;
}

void Utf8_Iter::toStart() {
	m_eState = eStart;
	if (m_eEncoding == eUtf16BigEndian) {
		swap();
	}
}

void Utf8_Iter::swap() {
	utf8* p = reinterpret_cast<utf8*>(&m_nCur);
	utf8 swapbyte = *p;
	*p = *(p + 1);
	*(p + 1) = swapbyte;
}

//==================================================
Utf16_Iter::Utf16_Iter() {
	reset();
}

void Utf16_Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eState = eStart;
	m_nCur = 0;
	m_nCur16 = 0;
	m_eEncoding = eUnknown;
}

void Utf16_Iter::set
	(const ubyte* pBuf, size_t nLen, encodingType eEncoding) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + nLen;
	m_eEncoding = eEncoding;
	operator++();
	// Note: m_eState, m_nCur, m_nCur16 not reinitalized.
}

// Goes to the next byte.
// Not the next symbol which you might expect.
// This way we can continue from a partial buffer that doesn't align
void Utf16_Iter::operator++() {
	switch (m_eState) {
	case eStart:
		if (m_eEncoding == eUtf16LittleEndian) {
			m_nCur16 = *m_pRead++;
			m_nCur16 |= static_cast<utf16>(*m_pRead << 8);
		} else {
			m_nCur16 = static_cast<utf16>(*m_pRead++ << 8);
			m_nCur16 |= *m_pRead;
		}
		++m_pRead;

		if (m_nCur16 < 0x80) {
			m_nCur = static_cast<ubyte>(m_nCur16 & 0xFF);
			m_eState = eStart;
		} else if (m_nCur16 < 0x800) {
			m_nCur = static_cast<ubyte>(0xC0 | m_nCur16 >> 6);
			m_eState = e2Bytes2;
		} else {
			m_nCur = static_cast<ubyte>(0xE0 | m_nCur16 >> 12);
			m_eState = e3Bytes2;
		}
		break;
	case e2Bytes2:
		m_nCur = static_cast<ubyte>(0x80 | m_nCur16 & 0x3F);
		m_eState = eStart;
		break;
	case e3Bytes2:
		m_nCur = static_cast<ubyte>(0x80 | ((m_nCur16 >> 6) & 0x3F));
		m_eState = e3Bytes3;
		break;
	case e3Bytes3:
		m_nCur = static_cast<ubyte>(0x80 | m_nCur16 & 0x3F);
		m_eState = eStart;
		break;
	}
}
<commit_msg>Bug fixed in saving to UCS2BE.<commit_after>// Utf8_16.cxx
// Copyright (C) 2002 Scott Kirkwood
//
// Permission to use, copy, modify, distribute and sell this code
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies or
// any derived copies.  Scott Kirkwood makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////

#include "Utf8_16.h"

#include <stdio.h>

const Utf8_16::utf8 Utf8_16::k_Boms[][3] = {
	{0x00, 0x00, 0x00},  // Unknown
	{0xFE, 0xFF, 0x00},  // Big endian
	{0xFF, 0xFE, 0x00},  // Little endian
	{0xEF, 0xBB, 0xBF}, // UTF8
};

// ==================================================================

Utf8_16_Read::Utf8_16_Read() {
	m_eEncoding = eUnknown;
	m_nBufSize = 0;
	m_pNewBuf = NULL;
	m_bFirstRead = true;
}

Utf8_16_Read::~Utf8_16_Read() {
	if ((m_eEncoding != eUnknown) && (m_eEncoding != eUtf8)) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
	}
}

size_t Utf8_16_Read::convert(char* buf, size_t len) {
	m_pBuf = reinterpret_cast<ubyte*>(buf);
	m_nLen = len;

	int nSkip = 0;
	if (m_bFirstRead) {
		nSkip = determineEncoding();
		m_bFirstRead = false;
	}

	if (m_eEncoding == eUnknown) {
		// Do nothing, pass through
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf;
		return len;
	}

	if (m_eEncoding == eUtf8) {
		// Pass through after BOM
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf + nSkip;
		return len - nSkip;
	}

	// Else...
	size_t newSize = len + len / 2 + 1;
	if (m_nBufSize != newSize) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
		m_pNewBuf = new ubyte[newSize];
		m_nBufSize = newSize;
	}

	ubyte* pCur = m_pNewBuf;

	m_Iter16.set(m_pBuf + nSkip, len - nSkip, m_eEncoding);

	for (; m_Iter16; ++m_Iter16) {
		*pCur++ = m_Iter16.get();
	}

	// Return number of bytes writen out
	return pCur - m_pNewBuf;
}

int Utf8_16_Read::determineEncoding() {
	m_eEncoding = eUnknown;

	int nRet = 0;

	if (m_nLen > 1) {
		if (m_pBuf[0] == k_Boms[eUtf16BigEndian][0] && m_pBuf[1] == k_Boms[eUtf16BigEndian][1]) {
			m_eEncoding = eUtf16BigEndian;
			nRet = 2;
		} else if (m_pBuf[0] == k_Boms[eUtf16LittleEndian][0] && m_pBuf[1] == k_Boms[eUtf16LittleEndian][1]) {
			m_eEncoding = eUtf16LittleEndian;
			nRet = 2;
		} else if (m_nLen > 2 && m_pBuf[0] == k_Boms[eUtf8][0] && m_pBuf[1] == k_Boms[eUtf8][1] && m_pBuf[2] == k_Boms[eUtf8][2]) {
			m_eEncoding = eUtf8;
			nRet = 3;
		}
	}

	return nRet;
}

// ==================================================================

Utf8_16_Write::Utf8_16_Write() {
	m_eEncoding = eUnknown;
	m_pFile = NULL;
	m_pBuf = NULL;
	m_bFirstWrite = true;
	m_nBufSize = 0;
}

Utf8_16_Write::~Utf8_16_Write() {
	if (m_pFile) {
		fclose();
	}
}

FILE * Utf8_16_Write::fopen(const char *_name, const char *_type) {
	m_pFile = ::fopen(_name, _type);

	m_bFirstWrite = true;

	return m_pFile;
}

size_t Utf8_16_Write::fwrite(const void* p, size_t _size) {
	if (!m_pFile) {
		return 0; // fail
	}

	if (m_eEncoding == eUnknown) {
		// Normal write
		return ::fwrite(p, _size, 1, m_pFile);
	}

	if (m_eEncoding == eUtf8) {
		if (m_bFirstWrite)
			::fwrite(k_Boms[m_eEncoding], 3, 1, m_pFile);
		m_bFirstWrite = false;
		return ::fwrite(p, _size, 1, m_pFile);
	}

	if (_size > m_nBufSize) {
		m_nBufSize = _size;
		delete [] m_pBuf;
		m_pBuf = NULL;
		m_pBuf = new utf16[_size + 1];
	}

	if (m_bFirstWrite) {
		if (m_eEncoding == eUtf16BigEndian || m_eEncoding == eUtf16LittleEndian) {
			// Write the BOM
			::fwrite(k_Boms[m_eEncoding], 2, 1, m_pFile);
		}

		m_bFirstWrite = false;
	}

	Utf8_Iter iter8;
	iter8.set(static_cast<const ubyte*>(p), _size, m_eEncoding);

	utf16* pCur = m_pBuf;

	for (; iter8; ++iter8) {
		if (iter8.canGet()) {
			*pCur++ = iter8.get();
		}
	}

	size_t ret = ::fwrite(m_pBuf, (const char*)pCur - (const char*)m_pBuf, 1, m_pFile);

	return ret;
}

void Utf8_16_Write::fclose() {
	delete [] m_pBuf;
	m_pBuf = NULL;

	::fclose(m_pFile);
	m_pFile = NULL;
}

void Utf8_16_Write::setEncoding(Utf8_16::encodingType eType) {
	m_eEncoding = eType;
}

//=================================================================
Utf8_Iter::Utf8_Iter() {
	reset();
}

void Utf8_Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eState = eStart;
	m_nCur = 0;
	m_eEncoding = eUnknown;
}

void Utf8_Iter::set
	(const ubyte* pBuf, size_t nLen, encodingType eEncoding) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + nLen;
	m_eEncoding = eEncoding;
	operator++();
	// Note: m_eState, m_nCur not reset
}
// Go to the next byte.
void Utf8_Iter::operator++() {
	switch (m_eState) {
	case eStart:
		if ((0xE0 & *m_pRead) == 0xE0) {
			m_nCur = static_cast<utf16>((~0xE0 & *m_pRead) << 12);
			m_eState = e3Bytes_Byte2;
		} else if ((0xC0 & *m_pRead) == 0xC0) {
			m_nCur = static_cast<utf16>((~0xC0 & *m_pRead) << 6);
			m_eState = e2Bytes_Byte2;
		} else {
			m_nCur = *m_pRead;
			toStart();
		}
		break;
	case e2Bytes_Byte2:
		m_nCur |= static_cast<utf8>(0x3F & *m_pRead);
		toStart();
		break;
	case e3Bytes_Byte2:
		m_nCur |= static_cast<utf16>((0x3F & *m_pRead) << 6);
		m_eState = e3Bytes_Byte3;
		break;
	case e3Bytes_Byte3:
		m_nCur |= static_cast<utf8>(0x3F & *m_pRead);
		toStart();
		break;
	}
	++m_pRead;
}

void Utf8_Iter::toStart() {
	m_eState = eStart;
	if (m_eEncoding == eUtf16BigEndian) {
		swap();
	}
}

void Utf8_Iter::swap() {
	utf8* p = reinterpret_cast<utf8*>(&m_nCur);
	utf8 swapbyte = *p;
	*p = *(p + 1);
	*(p + 1) = swapbyte;
}

//==================================================
Utf16_Iter::Utf16_Iter() {
	reset();
}

void Utf16_Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eState = eStart;
	m_nCur = 0;
	m_nCur16 = 0;
	m_eEncoding = eUnknown;
}

void Utf16_Iter::set
	(const ubyte* pBuf, size_t nLen, encodingType eEncoding) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + nLen;
	m_eEncoding = eEncoding;
	operator++();
	// Note: m_eState, m_nCur, m_nCur16 not reinitalized.
}

// Goes to the next byte.
// Not the next symbol which you might expect.
// This way we can continue from a partial buffer that doesn't align
void Utf16_Iter::operator++() {
	switch (m_eState) {
	case eStart:
		if (m_eEncoding == eUtf16LittleEndian) {
			m_nCur16 = *m_pRead++;
			m_nCur16 |= static_cast<utf16>(*m_pRead << 8);
		} else {
			m_nCur16 = static_cast<utf16>(*m_pRead++ << 8);
			m_nCur16 |= *m_pRead;
		}
		++m_pRead;

		if (m_nCur16 < 0x80) {
			m_nCur = static_cast<ubyte>(m_nCur16 & 0xFF);
			m_eState = eStart;
		} else if (m_nCur16 < 0x800) {
			m_nCur = static_cast<ubyte>(0xC0 | m_nCur16 >> 6);
			m_eState = e2Bytes2;
		} else {
			m_nCur = static_cast<ubyte>(0xE0 | m_nCur16 >> 12);
			m_eState = e3Bytes2;
		}
		break;
	case e2Bytes2:
		m_nCur = static_cast<ubyte>(0x80 | m_nCur16 & 0x3F);
		m_eState = eStart;
		break;
	case e3Bytes2:
		m_nCur = static_cast<ubyte>(0x80 | ((m_nCur16 >> 6) & 0x3F));
		m_eState = e3Bytes3;
		break;
	case e3Bytes3:
		m_nCur = static_cast<ubyte>(0x80 | m_nCur16 & 0x3F);
		m_eState = eStart;
		break;
	}
}
<|endoftext|>


<commit_before>#include "cfb.h"

SymAlg::Ptr use_sym_alg(const uint8_t sym_alg, const std::string & key){
    SymAlg::Ptr alg;
    switch(sym_alg){
        case 1:
            alg = std::make_shared<IDEA>(key);
            break;
        case 2:
            alg = std::make_shared<TDES>(key.substr(0, 8), TDES_mode1, key.substr(8, 8), TDES_mode2, key.substr(16, 8), TDES_mode3);
            break;
        case 3:
            alg = std::make_shared<CAST128>(key);
            break;
        case 4:
            alg = std::make_shared<Blowfish>(key);
            break;
        case 7: case 8: case 9:
            alg = std::make_shared<AES>(key);
            break;
        case 10:
            alg = std::make_shared<Twofish>(key);
            break;
        case 11: case 12: case 13:
            alg = std::make_shared<Camellia>(key);
            break;
        default:
            throw std::runtime_error("Error: Unknown Symmetric Key Algorithm value.");
            break;
    }
    return alg;
}

std::string OpenPGP_CFB_encrypt(SymAlg::Ptr & crypt, const uint8_t packet, const std::string & data, std::string prefix){
    const unsigned int BS = crypt -> blocksize() >> 3;

    if (prefix.size() > BS){
        prefix = prefix.substr(0, BS);
    }

    // 1
    std::string FR(BS, 0);
    // 2
    std::string FRE = crypt -> encrypt(FR);
    // 3
    FRE = xor_strings(FRE, prefix);
    std::string C = FRE;
    // 4
    FR = C;
    // 5
    FRE = crypt -> encrypt(FR);
    // 6
    C += xor_strings(FRE.substr(0, 2), prefix.substr(BS - 2, 2));
    // 7
    if (packet == 9){ // resynchronization
        FR = C.substr(2, BS);
        // 8
        FRE = crypt -> encrypt(FR);
        // 9
        C += xor_strings(FRE, data.substr(0, BS));
        unsigned int x = BS;
        while ((x - BS) < data.size()){
            // 10
            FR = C.substr(x + 2, BS);
            // 11
            FRE = crypt -> encrypt(FR);
            // 12
            C += xor_strings(FRE, data.substr(x, BS));
            x += BS;
        }
    }
    else{ // no resynchronization
        // 8
        FRE = crypt -> encrypt(FR);
        // 9
        C += xor_strings(FRE.substr(2, BS - 2), data.substr(0, BS));
        C = C.substr(0, BS << 1);
        unsigned int x = BS;
        while ((x - BS) < data.size()){
            // 10
            FR = C.substr(x, BS);
            // 11
            FRE = crypt -> encrypt(FR);
            // 12
            C += xor_strings(FRE, data.substr(x - 2, BS));
            x += BS;
        }
    }
    return C;
}

std::string OpenPGP_CFB_decrypt(SymAlg::Ptr & crypt, const uint8_t packet, const std::string & data){
    const unsigned int BS = crypt -> blocksize() >> 3;

    // 1
    std::string FR(BS, 0);
    // 2
    std::string FRE = crypt -> encrypt(FR);
    // 4
    FR = data.substr(0, BS);
    // 3
    std::string prefix = xor_strings(FRE, FR);
    // 5
    FRE = crypt -> encrypt(FR); // encryption of ciphertext
    std::string check = xor_strings(FRE.substr(0, 2), data.substr(BS, 2));
    // 6
    if (prefix.substr(BS - 2, 2) != check){
        throw std::runtime_error("Error: Bad OpenPGP_CFB check value.");
    }
    std::string P = "";
    unsigned int x = (packet == 9)?2:0; // 7
    while ((x + BS) < data.size()){
        std::string substr = data.substr(x, BS);
        P += xor_strings(FRE, substr);
        FRE = crypt -> encrypt(substr);
        x += BS;
    }
    P += xor_strings(FRE, data.substr(x, BS));
    return prefix + prefix.substr(BS - 2, 2) + P.substr(BS + 2, P.size() - BS - 2);
}

std::string use_OpenPGP_CFB_encrypt(const uint8_t sym_alg, const uint8_t packet, const std::string & data, const std::string & key, const std::string & prefix){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = OpenPGP_CFB_encrypt(alg, packet, data, prefix);
    return out;
}

std::string use_OpenPGP_CFB_decrypt(const uint8_t sym_alg, const uint8_t packet, const std::string & data, const std::string & key){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = OpenPGP_CFB_decrypt(alg, packet, data);
    return out;
}

std::string normal_CFB_encrypt(SymAlg::Ptr & crypt, std::string & data, std::string & IV){
    std::string out = "";
    const unsigned int BS = crypt -> blocksize() >> 3;
    unsigned int x = 0;
    while (out.size() < data.size()){
        IV = xor_strings(crypt -> encrypt(IV), data.substr(x, BS));
        out += IV;
        x += BS;
    }
    return out;
}

std::string normal_CFB_decrypt(SymAlg::Ptr & crypt, std::string & data, std::string & IV){
    std::string out = "";
    const unsigned int BS = crypt -> blocksize() >> 3;
    unsigned int x = 0;
    while (x < data.size()){
        out += xor_strings(crypt -> encrypt(IV), data.substr(x, BS));
        IV = data.substr(x, BS);
        x += BS;
    }
    return out;
}

std::string use_normal_CFB_encrypt(const uint8_t sym_alg, std::string data, std::string key, std::string IV){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = normal_CFB_encrypt(alg, data, IV);
    return out;
}

std::string use_normal_CFB_decrypt(const uint8_t sym_alg, std::string data, std::string key, std::string IV){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = normal_CFB_decrypt(alg, data, IV);
    return out;
}
<commit_msg>encrypt bug doesnt exist?<commit_after>#include "cfb.h"

SymAlg::Ptr use_sym_alg(const uint8_t sym_alg, const std::string & key){
    SymAlg::Ptr alg;
    switch(sym_alg){
        case 1:
            alg = std::make_shared<IDEA>(key);
            break;
        case 2:
            alg = std::make_shared<TDES>(key.substr(0, 8), TDES_mode1, key.substr(8, 8), TDES_mode2, key.substr(16, 8), TDES_mode3);
            break;
        case 3:
            alg = std::make_shared<CAST128>(key);
            break;
        case 4:
            alg = std::make_shared<Blowfish>(key);
            break;
        case 7: case 8: case 9:
            alg = std::make_shared<AES>(key);
            break;
        case 10:
            alg = std::make_shared<Twofish>(key);
            break;
        case 11: case 12: case 13:
            alg = std::make_shared<Camellia>(key);
            break;
        default:
            throw std::runtime_error("Error: Unknown Symmetric Key Algorithm value.");
            break;
    }
    return alg;
}

std::string OpenPGP_CFB_encrypt(SymAlg::Ptr & crypt, const uint8_t packet, const std::string & data, std::string prefix){
    const unsigned int BS = crypt -> blocksize() >> 3;

	if (prefix.size() < BS){
		throw std::runtime_error("Error: Given prefix too short.");
	}
	else if (prefix.size() > BS){
        prefix = prefix.substr(0, BS);	// reduce prefix
    }

	/*
	13.9. OpenPGP CFB Mode

		OpenPGP does symmetric encryption using a variant of Cipher Feedback
		mode (CFB mode). This section describes the procedure it uses in
		detail. This mode is what is used for Symmetrically Encrypted Data
		Packets; the mechanism used for encrypting secret-key material is
		similar, and is described in the sections above.
		In the description below, the value BS is the block size in octets of
		the cipher. Most ciphers have a block size of 8 octets. The AES and
		Twofish have a block size of 16 octets. Also note that the
		description below assumes that the IV and CFB arrays start with an
		index of 1 (unlike the C language, which assumes arrays start with a
		zero index).
		OpenPGP CFB mode uses an initialization vector (IV) of all zeros, and
		prefixes the plaintext with BS+2 octets of random data, such that
		octets BS+1 and BS+2 match octets BS-1 and BS. It does a CFB
		resynchronization after encrypting those BS+2 octets.
		Thus, for an algorithm that has a block size of 8 octets (64 bits),
		the IV is 10 octets long and ocets 7 and 8 of the IV are the same as
		octets 9 and 10. For an algorithm with a block size of 16 octets
		(128 bits), the IV is 18 octets long, and octets 17 and 18 replicate
		octets 15 and 16. Those extra two octets are an easy check for a
		correct key.

	Step by step, here is the procedure:
	*/

    // 1. The feedback register (FR) is set to the IV, which is all zeros.
    std::string FR(BS, 0);

    // 2. FR is encrypted to produce FRE (FR Encrypted). This is the encryption of an all-zero value.
    std::string FRE = crypt -> encrypt(FR);

    // 3. FRE is xored with the first BS octets of random data prefixed to the plaintext to produce C[1] through C[BS], the first BS octets of ciphertext.
    FRE = xor_strings(FRE, prefix);
    std::string C = FRE;

    // 4. FR is loaded with C[1] through C[BS].
    FR = C;

    // 5. FR is encrypted to produce FRE, the encryption of the first BS octets of ciphertext.
    FRE = crypt -> encrypt(FR);

    // 6. The left two octets of FRE get xored with the next two octets of data that were prefixed to the plaintext. This produces C[BS+1] and C[BS+2], the next two octets of ciphertext.
    C += xor_strings(FRE.substr(0, 2), prefix.substr(BS - 2, 2));

	if (packet == 9){ // resynchronization
		// 7. (The resynchronization step) FR is loaded with C[3] through C[BS+2].
        FR = C.substr(2, BS);

		// 8. FR is encrypted to produce FRE.
        FRE = crypt -> encrypt(FR);

		// 9. FRE is xored with the first BS octets of the given plaintext, now that we have finished encrypting the BS+2 octets of prefixed data. This produces C[BS+3] through C[BS+(BS+2)], the next BS octets of ciphertext.
        C += xor_strings(FRE, data.substr(0, BS));

        unsigned int x = BS;
        while (x < data.size()){
            // 10. FR is loaded with C[BS+3] to C[BS + (BS+2)] (which is C11-C18 for an 8-octet block).
            FR = C.substr(x + 2, BS);

			// 11. FR is encrypted to produce FRE.
            FRE = crypt -> encrypt(FR);

			// 12. FRE is xored with the next BS octets of plaintext, to produce the next BS octets of ciphertext. These are loaded into FR, and the process is repeated until the plaintext is used up.
            C += xor_strings(FRE, data.substr(x, BS));

            x += BS;
        }
    }
    else{ // no resynchronization
		/*
		5.13. Sym. Encrypted Integrity Protected Data Packet (Tag 18)

			Unlike the Symmetrically Encrypted Data Packet, no
			special CFB resynchronization is done after encrypting this prefix
			data.
		*/

        // 8
        // FRE = crypt -> encrypt(FR); // not needed

        // 9
        C += xor_strings(FRE.substr(2, BS - 2), data.substr(0, BS));
        C = C.substr(0, BS << 1);

        unsigned int x = BS;
        while (x < data.size()){
            // 10
            FR = C.substr(x, BS);

            // 11
            FRE = crypt -> encrypt(FR);

            // 12
            C += xor_strings(FRE, data.substr(x - 2, BS));

            x += BS;
        }
    }
    return C;
}

std::string OpenPGP_CFB_decrypt(SymAlg::Ptr & crypt, const uint8_t packet, const std::string & data){
    const unsigned int BS = crypt -> blocksize() >> 3;

    // 1
    std::string FR(BS, 0);
    // 2
    std::string FRE = crypt -> encrypt(FR);
    // 4
    FR = data.substr(0, BS);
    // 3
    std::string prefix = xor_strings(FRE, FR);
    // 5
    FRE = crypt -> encrypt(FR); // encryption of ciphertext
    std::string check = xor_strings(FRE.substr(0, 2), data.substr(BS, 2));
    // 6
    if (prefix.substr(BS - 2, 2) != check){
        throw std::runtime_error("Error: Bad OpenPGP_CFB check value.");
    }
    std::string P = "";
    unsigned int x = (packet == 9)?2:0; // 7
    while ((x + BS) < data.size()){
        std::string substr = data.substr(x, BS);
        P += xor_strings(FRE, substr);
        FRE = crypt -> encrypt(substr);
        x += BS;
    }
    P += xor_strings(FRE, data.substr(x, BS));
    return prefix + prefix.substr(BS - 2, 2) + P.substr(BS + 2, P.size() - BS - 2);
}

std::string use_OpenPGP_CFB_encrypt(const uint8_t sym_alg, const uint8_t packet, const std::string & data, const std::string & key, const std::string & prefix){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = OpenPGP_CFB_encrypt(alg, packet, data, prefix);
    return out;
}

std::string use_OpenPGP_CFB_decrypt(const uint8_t sym_alg, const uint8_t packet, const std::string & data, const std::string & key){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = OpenPGP_CFB_decrypt(alg, packet, data);
    return out;
}

std::string normal_CFB_encrypt(SymAlg::Ptr & crypt, std::string & data, std::string & IV){
    std::string out = "";
    const unsigned int BS = crypt -> blocksize() >> 3;
    unsigned int x = 0;
    while (out.size() < data.size()){
        IV = xor_strings(crypt -> encrypt(IV), data.substr(x, BS));
        out += IV;
        x += BS;
    }
    return out;
}

std::string normal_CFB_decrypt(SymAlg::Ptr & crypt, std::string & data, std::string & IV){
    std::string out = "";
    const unsigned int BS = crypt -> blocksize() >> 3;
    unsigned int x = 0;
    while (x < data.size()){
        out += xor_strings(crypt -> encrypt(IV), data.substr(x, BS));
        IV = data.substr(x, BS);
        x += BS;
    }
    return out;
}

std::string use_normal_CFB_encrypt(const uint8_t sym_alg, std::string data, std::string key, std::string IV){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = normal_CFB_encrypt(alg, data, IV);
    return out;
}

std::string use_normal_CFB_decrypt(const uint8_t sym_alg, std::string data, std::string key, std::string IV){
    if (!sym_alg){
        return data;
    }
    SymAlg::Ptr alg = use_sym_alg(sym_alg, key);
    std::string out = normal_CFB_decrypt(alg, data, IV);
    return out;
}
<|endoftext|>


<commit_before>#include "applyGettersSetters.h"
#include "expr.h"
#include "stmt.h"
#include "stringutil.h"
#include "symtab.h"

void ApplyGettersSetters::postProcessExpr(Expr* expr) {
  if (!applyGettersSetters) {
    return;
  }
  FnSymbol* fn = NULL;
  if (expr->parentStmt) {
    fn = expr->parentStmt->parentFunction();
  }
  if (fn && (fn->_setter || fn->_getter || fn->isConstructor)) {
    return;
  }
  if (dynamic_cast<VarInitExpr*>(expr->parentExpr)) {
    return;
  }
  if (MemberAccess* memberAccess = dynamic_cast<MemberAccess*>(expr)) {
    if (dynamic_cast<ParenOpExpr*>(memberAccess->parentExpr)) {
      return;
    }
    AList<Expr>* arguments = new AList<Expr>();
    arguments->insertAtTail(new Variable(Symboltable::lookupInternal("_methodToken")));
    arguments->insertAtTail(memberAccess->base->copy());
    Expr* replacement =
      new ParenOpExpr(
        new Variable(
          new UnresolvedSymbol(memberAccess->member->name)),
        arguments);
    expr->replace(replacement);
  }
  if (ParenOpExpr* parenOpExpr = dynamic_cast<ParenOpExpr*>(expr)) {
    if (MemberAccess* memberAccess = dynamic_cast<MemberAccess*>(parenOpExpr->baseExpr)) {
      AList<Expr>* arguments = parenOpExpr->argList->copy();
      arguments->insertAtHead(memberAccess->base->copy());
      arguments->insertAtHead(new Variable(Symboltable::lookupInternal("_methodToken")));
      Expr* replacement =
        new ParenOpExpr(
          new Variable(
            new UnresolvedSymbol(memberAccess->member->name)),
          arguments);
      expr->replace(replacement);
    }
  }
}
<commit_msg>Fixed a small bug with --apply-getters-setters in which arguments to a ParenOpExpr were not handled.<commit_after>#include "applyGettersSetters.h"
#include "expr.h"
#include "stmt.h"
#include "stringutil.h"
#include "symtab.h"

void ApplyGettersSetters::postProcessExpr(Expr* expr) {
  if (!applyGettersSetters) {
    return;
  }
  FnSymbol* fn = NULL;
  if (expr->parentStmt) {
    fn = expr->parentStmt->parentFunction();
  }
  if (fn && (fn->_setter || fn->_getter || fn->isConstructor)) {
    return;
  }
  if (dynamic_cast<VarInitExpr*>(expr->parentExpr)) {
    return;
  }
  if (MemberAccess* memberAccess = dynamic_cast<MemberAccess*>(expr)) {
    if (ParenOpExpr* parenOpExpr = dynamic_cast<ParenOpExpr*>(memberAccess->parentExpr)) {
      if (parenOpExpr->baseExpr == memberAccess) {
        return;
      }
    }
    AList<Expr>* arguments = new AList<Expr>();
    arguments->insertAtTail(new Variable(Symboltable::lookupInternal("_methodToken")));
    arguments->insertAtTail(memberAccess->base->copy());
    Expr* replacement =
      new ParenOpExpr(
        new Variable(
          new UnresolvedSymbol(memberAccess->member->name)),
        arguments);
    expr->replace(replacement);
  }
  if (ParenOpExpr* parenOpExpr = dynamic_cast<ParenOpExpr*>(expr)) {
    if (MemberAccess* memberAccess = dynamic_cast<MemberAccess*>(parenOpExpr->baseExpr)) {
      AList<Expr>* arguments = parenOpExpr->argList->copy();
      arguments->insertAtHead(memberAccess->base->copy());
      arguments->insertAtHead(new Variable(Symboltable::lookupInternal("_methodToken")));
      Expr* replacement =
        new ParenOpExpr(
          new Variable(
            new UnresolvedSymbol(memberAccess->member->name)),
          arguments);
      expr->replace(replacement);
    }
  }
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2015 Wojciech Migda
 * All rights reserved
 * Distributed under the terms of the GNU LGPL v3
 *******************************************************************************
 *
 * Filename: array2d.hpp
 *
 * Description:
 *      Let's try to have a numpy-like environment
 *
 * Authors:
 *          Wojciech Migda (wm)
 *
 *******************************************************************************
 * History:
 * --------
 * Date         Who  Ticket     Description
 * ----------   ---  ---------  ------------------------------------------------
 * 2015-01-30   wm              Initial version
 *
 ******************************************************************************/

#ifndef ARRAY2D_HPP_
#define ARRAY2D_HPP_

#include "num.hpp"
#include <cstdlib>
#include <utility>
#include <valarray>
#include <map>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <string>
#include <sstream>
#include <type_traits>
#include <unordered_set>

namespace num
{

typedef std::pair<size_type, size_type> shape_type;

template<typename _Type>
class array2d
{
public:
    enum class Axis
    {
        Row,
        Column
    };

    typedef _Type value_type;
    typedef std::size_t size_type;
    typedef std::pair<size_type, size_type> shape_type;
    typedef std::valarray<value_type> varray_type;

    array2d(shape_type shape, value_type initializer);

    shape_type shape(void) const;

    std::slice row(size_type n) const;
    std::slice column(size_type n) const;
    std::slice stripe(size_type n, enum Axis axis) const;

    std::gslice columns(size_type p, size_type q) const;

    std::valarray<value_type> operator[](std::slice slicearr) const;
    std::slice_array<value_type> operator[](std::slice slicearr);
    std::valarray<value_type> operator[](const std::gslice & gslicearr) const;
    std::gslice_array<value_type> operator[](const std::gslice & gslicearr);

private:
    shape_type m_shape;
    varray_type m_varray;
};

template<typename _Type>
inline
array2d<_Type>::array2d(shape_type shape, array2d<_Type>::value_type initializer)
:
    m_shape(shape),
    m_varray(initializer, shape.first * shape.second)
{

}

template<typename _Type>
inline
shape_type
array2d<_Type>::shape(void) const
{
    return m_shape;
}

template<typename _Type>
inline
std::slice
array2d<_Type>::row(size_type n) const
{
    return std::slice(n * m_shape.second, m_shape.second, 1);
}

template<typename _Type>
inline
std::slice
array2d<_Type>::column(size_type n) const
{
    return std::slice(n, m_shape.first, m_shape.second);
}

template<typename _Type>
inline
std::gslice
array2d<_Type>::columns(size_type p, size_type q) const
{
    return std::gslice(p, {m_shape.first, q - p + 1}, {m_shape.second, 1});
}

template<typename _Type>
inline
std::slice
array2d<_Type>::stripe(size_type n, enum Axis axis) const
{
    return axis == Axis::Row ? row(n) : column(n);
}

template<typename _Type>
inline
std::valarray<_Type>
array2d<_Type>::operator[](std::slice slicearr) const
{
    return m_varray[slicearr];
}

template<typename _Type>
inline
std::slice_array<_Type>
array2d<_Type>::operator[](std::slice slicearr)
{
    return m_varray[slicearr];
}

template<typename _Type>
inline
std::valarray<_Type>
array2d<_Type>::operator[](const std::gslice & gslicearr) const
{
    return m_varray[gslicearr];
}

template<typename _Type>
inline
std::gslice_array<_Type>
array2d<_Type>::operator[](const std::gslice & gslicearr)
{
    return m_varray[gslicearr];
}

template<typename _Type>
inline
array2d<_Type>
zeros(shape_type shape)
{
    return array2d<_Type>(shape, 0.0);
}

template<typename _Type>
inline
array2d<_Type>
ones(shape_type shape)
{
    return array2d<_Type>(shape, 1.0);
}

template<typename _Type = double>
struct loadtxtCfg
{
    typedef std::map<size_type, _Type(*)(const char *)> converters_type;

    loadtxtCfg()
    :
        m_comments{'#'},
        m_delimiter{' '},
        m_converters{},
        m_skip_header{0},
        m_skip_footer{0},
        m_use_cols{}
    {}

    loadtxtCfg & comments(char _comments)
    {
        m_comments = _comments;
        return *this;
    }

    char delimiter(void) const
    {
        return m_delimiter;
    }

    loadtxtCfg & delimiter(char _delimiter)
    {
        m_delimiter = _delimiter;
        return *this;
    }

    const converters_type & converters(void) const
    {
        return m_converters;
    }

    loadtxtCfg & converters(converters_type && _converters)
    {
        m_converters = std::move(_converters);
        return *this;
    }

    size_type skip_header(void) const
    {
        return m_skip_header;
    }

    loadtxtCfg & skip_header(size_type _skip_header)
    {
        m_skip_header = _skip_header;
        return *this;
    }

    size_type skip_footer(void) const
    {
        return m_skip_footer;
    }

    loadtxtCfg & skip_footer(size_type _skip_footer)
    {
        m_skip_footer = _skip_footer;
        return *this;
    }

    loadtxtCfg & use_cols(std::unordered_set<size_type> && _use_cols)
    {
        m_use_cols = std::move(_use_cols);
        return *this;
    }

    char m_comments;
    char m_delimiter;
    converters_type m_converters;
    size_type m_skip_header;
    size_type m_skip_footer;
    std::unordered_set<size_type> m_use_cols;
};

template<typename _Type>
array2d<_Type>
loadtxt(
    std::vector<std::string> && txt,
    loadtxtCfg<_Type> && cfg
)
{
    typedef _Type value_type;
    const bool skip_empty = false;

    auto count_delimiters = [&skip_empty](std::string where, char delim) -> size_type
    {
        auto predicate = [&delim](char _this, char _that)
        {
            return _this == _that && _this == delim;
        };
        if (skip_empty)
        {
            std::unique(where.begin(), where.end(), predicate);
        }

        return std::count(where.cbegin(), where.cend(), delim);
    };

    assert(txt.size() >= (cfg.skip_header() + cfg.skip_footer()));
    const size_type NROWS = txt.size() - cfg.skip_header() - cfg.skip_footer();
    if (NROWS == 0)
    {
        return zeros<value_type>(shape_type(0, 0));
    }

    // TODO use_ncols
    const size_type NCOLS = 1 + count_delimiters(txt.front(), cfg.delimiter());

    array2d<_Type> result = zeros<value_type>(shape_type(NROWS, NCOLS));

    for (size_type ridx{0}; ridx < NROWS; ++ridx)
    {
        std::valarray<value_type> row(NROWS);
        std::stringstream ss(txt[ridx + cfg.skip_header()]);
        std::string item;

        for (size_type cidx{0}; cidx < NCOLS && std::getline(ss, item, cfg.delimiter()); ++cidx) // TODO
        {
            if (cfg.converters().find(cidx) != cfg.converters().cend())
            {
                row[cidx] = cfg.converters().at(cidx)(item.c_str());
            }
            else if (std::is_convertible<value_type, long double>::value)
            {
                row[cidx] = std::strtold(item.c_str(), nullptr);
            }
            else if (std::is_convertible<value_type, long long>::value)
            {
                row[cidx] = std::atoll(item.c_str());
            }
            else
            {
                std::stringstream item_ss(item);
                item_ss >> row[cidx];
            }
        }

        result[result.row(ridx)] = row;
    }

    return result;
}

} // namespace num

namespace std
{

std::ostream & operator<<(std::ostream & os, const num::shape_type & shape)
{
    os << '(' << shape.first << ',' << shape.second << ')';
    return os;
}

} // namespace std

#endif /* ARRAY2D_HPP_ */
<commit_msg>negative indices for columns() for indexing relative to the last column<commit_after>/*******************************************************************************
 * Copyright (c) 2015 Wojciech Migda
 * All rights reserved
 * Distributed under the terms of the GNU LGPL v3
 *******************************************************************************
 *
 * Filename: array2d.hpp
 *
 * Description:
 *      Let's try to have a numpy-like environment
 *
 * Authors:
 *          Wojciech Migda (wm)
 *
 *******************************************************************************
 * History:
 * --------
 * Date         Who  Ticket     Description
 * ----------   ---  ---------  ------------------------------------------------
 * 2015-01-30   wm              Initial version
 *
 ******************************************************************************/

#ifndef ARRAY2D_HPP_
#define ARRAY2D_HPP_

#include "num.hpp"
#include <cstdlib>
#include <utility>
#include <valarray>
#include <map>
#include <algorithm>
#include <iostream>
#include <cassert>
#include <string>
#include <sstream>
#include <type_traits>
#include <unordered_set>

namespace num
{

typedef std::pair<size_type, size_type> shape_type;

template<typename _Type>
class array2d
{
public:
    enum class Axis
    {
        Row,
        Column
    };

    typedef _Type value_type;
    typedef std::size_t size_type;
    typedef std::pair<size_type, size_type> shape_type;
    typedef std::valarray<value_type> varray_type;

    array2d(shape_type shape, value_type initializer);

    shape_type shape(void) const;

    std::slice row(size_type n) const;
    std::slice column(size_type n) const;
    std::slice stripe(size_type n, enum Axis axis) const;

    std::gslice columns(int p, int q) const;

    std::valarray<value_type> operator[](std::slice slicearr) const;
    std::slice_array<value_type> operator[](std::slice slicearr);
    std::valarray<value_type> operator[](const std::gslice & gslicearr) const;
    std::gslice_array<value_type> operator[](const std::gslice & gslicearr);

private:
    shape_type m_shape;
    varray_type m_varray;
};

template<typename _Type>
inline
array2d<_Type>::array2d(shape_type shape, array2d<_Type>::value_type initializer)
:
    m_shape(shape),
    m_varray(initializer, shape.first * shape.second)
{

}

template<typename _Type>
inline
shape_type
array2d<_Type>::shape(void) const
{
    return m_shape;
}

template<typename _Type>
inline
std::slice
array2d<_Type>::row(size_type n) const
{
    return std::slice(n * m_shape.second, m_shape.second, 1);
}

template<typename _Type>
inline
std::slice
array2d<_Type>::column(size_type n) const
{
    return std::slice(n, m_shape.first, m_shape.second);
}

template<typename _Type>
inline
std::gslice
array2d<_Type>::columns(int p, int q) const
{
    if (p < 0)
    {
        assert(-p < m_shape.second);
        p = m_shape.second + p;
    }
    if (q < 0)
    {
        assert(-q < m_shape.second);
        q = m_shape.second + q;
    }

    return std::gslice(
        p,
        {m_shape.first, {q - p + 1u}},
        {m_shape.second, 1u}
    );
}

template<typename _Type>
inline
std::slice
array2d<_Type>::stripe(size_type n, enum Axis axis) const
{
    return axis == Axis::Row ? row(n) : column(n);
}

template<typename _Type>
inline
std::valarray<_Type>
array2d<_Type>::operator[](std::slice slicearr) const
{
    return m_varray[slicearr];
}

template<typename _Type>
inline
std::slice_array<_Type>
array2d<_Type>::operator[](std::slice slicearr)
{
    return m_varray[slicearr];
}

template<typename _Type>
inline
std::valarray<_Type>
array2d<_Type>::operator[](const std::gslice & gslicearr) const
{
    return m_varray[gslicearr];
}

template<typename _Type>
inline
std::gslice_array<_Type>
array2d<_Type>::operator[](const std::gslice & gslicearr)
{
    return m_varray[gslicearr];
}

template<typename _Type>
inline
array2d<_Type>
zeros(shape_type shape)
{
    return array2d<_Type>(shape, 0.0);
}

template<typename _Type>
inline
array2d<_Type>
ones(shape_type shape)
{
    return array2d<_Type>(shape, 1.0);
}

template<typename _Type = double>
struct loadtxtCfg
{
    typedef std::map<size_type, _Type(*)(const char *)> converters_type;

    loadtxtCfg()
    :
        m_comments{'#'},
        m_delimiter{' '},
        m_converters{},
        m_skip_header{0},
        m_skip_footer{0},
        m_use_cols{}
    {}

    loadtxtCfg & comments(char _comments)
    {
        m_comments = _comments;
        return *this;
    }

    char delimiter(void) const
    {
        return m_delimiter;
    }

    loadtxtCfg & delimiter(char _delimiter)
    {
        m_delimiter = _delimiter;
        return *this;
    }

    const converters_type & converters(void) const
    {
        return m_converters;
    }

    loadtxtCfg & converters(converters_type && _converters)
    {
        m_converters = std::move(_converters);
        return *this;
    }

    size_type skip_header(void) const
    {
        return m_skip_header;
    }

    loadtxtCfg & skip_header(size_type _skip_header)
    {
        m_skip_header = _skip_header;
        return *this;
    }

    size_type skip_footer(void) const
    {
        return m_skip_footer;
    }

    loadtxtCfg & skip_footer(size_type _skip_footer)
    {
        m_skip_footer = _skip_footer;
        return *this;
    }

    loadtxtCfg & use_cols(std::unordered_set<size_type> && _use_cols)
    {
        m_use_cols = std::move(_use_cols);
        return *this;
    }

    char m_comments;
    char m_delimiter;
    converters_type m_converters;
    size_type m_skip_header;
    size_type m_skip_footer;
    std::unordered_set<size_type> m_use_cols;
};

template<typename _Type>
array2d<_Type>
loadtxt(
    std::vector<std::string> && txt,
    loadtxtCfg<_Type> && cfg
)
{
    typedef _Type value_type;
    const bool skip_empty = false;

    auto count_delimiters = [&skip_empty](std::string where, char delim) -> size_type
    {
        auto predicate = [&delim](char _this, char _that)
        {
            return _this == _that && _this == delim;
        };
        if (skip_empty)
        {
            std::unique(where.begin(), where.end(), predicate);
        }

        return std::count(where.cbegin(), where.cend(), delim);
    };

    assert(txt.size() >= (cfg.skip_header() + cfg.skip_footer()));
    const size_type NROWS = txt.size() - cfg.skip_header() - cfg.skip_footer();
    if (NROWS == 0)
    {
        return zeros<value_type>(shape_type(0, 0));
    }

    // TODO use_ncols
    const size_type NCOLS = 1 + count_delimiters(txt.front(), cfg.delimiter());

    array2d<_Type> result = zeros<value_type>(shape_type(NROWS, NCOLS));

    for (size_type ridx{0}; ridx < NROWS; ++ridx)
    {
        std::valarray<value_type> row(NROWS);
        std::stringstream ss(txt[ridx + cfg.skip_header()]);
        std::string item;

        for (size_type cidx{0}; cidx < NCOLS && std::getline(ss, item, cfg.delimiter()); ++cidx) // TODO
        {
            if (cfg.converters().find(cidx) != cfg.converters().cend())
            {
                row[cidx] = cfg.converters().at(cidx)(item.c_str());
            }
            else if (std::is_convertible<value_type, long double>::value)
            {
                row[cidx] = std::strtold(item.c_str(), nullptr);
            }
            else if (std::is_convertible<value_type, long long>::value)
            {
                row[cidx] = std::atoll(item.c_str());
            }
            else
            {
                std::stringstream item_ss(item);
                item_ss >> row[cidx];
            }
        }

        result[result.row(ridx)] = row;
    }

    return result;
}

} // namespace num

namespace std
{

std::ostream & operator<<(std::ostream & os, const num::shape_type & shape)
{
    os << '(' << shape.first << ',' << shape.second << ')';
    return os;
}

} // namespace std

#endif /* ARRAY2D_HPP_ */
<|endoftext|>


<commit_before>
#ifndef __ADDRESSING_HPP__
#define __ADDRESSING_HPP__

/// Global Addresses for SoftXMT
///
///
///
///
/// We support two types of global addresses:
/// -# 2D addresses
/// -# Linear addresses
///
/// 2D addresses are node, address on node
///
/// linear addresses are block cyclic

#include "SoftXMT.hpp"

typedef int Pool;

/// assumes user data will have the top 16 bits all 0.

static const int block_size = sizeof(int64_t) * 8;

static const int tag_bits = 1;
static const int pointer_bits = 48;
static const int node_bits = 64 - pointer_bits - tag_bits;
static const int pool_bits = 64 - pointer_bits - tag_bits;

static const int tag_shift_val = 64 - tag_bits;
static const int pointer_shift_val = 64 - pointer_bits;
static const int node_shift_val = pointer_bits;
static const int pool_shift_val = pointer_bits;

static const intptr_t tag_mask = (1L << tag_shift_val);
static const intptr_t node_mask = (1L << node_bits) - 1;
static const intptr_t pool_mask = (1L << pool_bits) - 1;
static const intptr_t pointer_mask = (1L << pointer_bits) - 1;

template< typename T >
class GlobalAddress {
private:
  intptr_t storage_;
  //DISALLOW_COPY_AND_ASSIGN( GlobalAddress );
  template< typename U > friend std::ostream& operator<<( std::ostream& o, const GlobalAddress< U >& ga );
  //friend template< typename U > GlobalAddress< U > operator+( const GlobalAddress< U >& t, ptrdiff_t i );
  template< typename U > friend ptrdiff_t operator-( const GlobalAddress< U >& t, const GlobalAddress< U >& u );

  std::ostream& dump( std::ostream& o ) const {
    if( is_2D() ) {
      return o << "<GA 2D " << (void*)storage_
               << ": node " << node()
               << " pointer " << static_cast<void *>( pointer() )
               << ">";
    } else {
        return o << "<GA Linear " << (void*)storage_
                 << ": pool " << pool()
                 << " node " << node()
                 << " pointer " << static_cast<void *>( pointer()  )
                 << ">";
    }
  }

  // GlobalAddress( T * p, Node n = SoftXMT_mynode() )
  //   : storage_( ( 1L << tag_shift_val ) |
  //               ( ( n & node_mask) << node_shift_val ) |
  //               ( reinterpret_cast<intptr_t>( p ) ) )
  // {
  //   assert( SoftXMT_mynode() <= node_mask );
  //   assert( reinterpret_cast<intptr_t>( p ) >> node_shift_val == 0 );
  // }

public:

  GlobalAddress( ) : storage_( 0 ) { }

  /// construct a 2D global address
  static GlobalAddress TwoDimensional( T * t, Node n = SoftXMT_mynode() )
  {
    GlobalAddress g;
    g.storage_ = ( ( 1L << tag_shift_val ) |
                   ( ( n & node_mask) << node_shift_val ) |
                   ( reinterpret_cast<intptr_t>( t ) ) );
    assert( SoftXMT_mynode() <= node_mask );
    assert( reinterpret_cast<intptr_t>( t ) >> node_shift_val == 0 );
    return g;
  }

  /// construct a linear global address
  static GlobalAddress Linear( T * t, Pool p = 0 )
  {
    GlobalAddress g;
    g.storage_ = ( ( 0L << tag_shift_val ) |
                   //( ( n & node_mask) << node_shift_val ) |
                   ( reinterpret_cast<intptr_t>( t ) ) );
    assert( reinterpret_cast<intptr_t>( t ) >> node_shift_val == 0 );
    return g;
  }

  /// construct a global address from raw bits
  static GlobalAddress Raw( intptr_t t )
  {
    GlobalAddress g;
    g.storage_ = t;
    return g;
  }

  inline intptr_t raw_bits() const {
    return storage_;
  }

  inline Node node() const {
    if( is_2D() ) {
      return (storage_ >> node_shift_val) & node_mask;
    } else {
      intptr_t offset = storage_ % block_size;
      intptr_t node = (storage_ / block_size) % SoftXMT_nodes();
      intptr_t node_block = (storage_ / block_size) / SoftXMT_nodes();
      return node;
    }
  }

  inline Pool pool() const {
    return (storage_ >> pool_shift_val) & pool_mask;
  }

  inline T * pointer() const {
    if( is_2D() ) {
      intptr_t signextended = (storage_ << pointer_shift_val) >> pointer_shift_val;
      return reinterpret_cast< T * >( signextended );
    } else {
      intptr_t offset = storage_ % block_size;
      intptr_t block = (storage_ / block_size);
      intptr_t node = (storage_ / block_size) % SoftXMT_nodes();
      intptr_t node_block = (storage_ / block_size) / SoftXMT_nodes();
      return reinterpret_cast< T * >( node_block * block_size + offset );
    }
  }

  inline GlobalAddress< T > block_min() const {
    if( is_2D() ) {
      //intptr_t signextended = (storage_ << pointer_shift_val) >> pointer_shift_val;
      //GlobalAddress< U > u = GlobalAddress< U >::Raw( storage_ );
      return GlobalAddress< T >::TwoDimensional( (T*) 0, node() );
    } else {
      intptr_t first_byte = storage_;
      intptr_t first_byte_offset = first_byte % block_size;
      intptr_t node = (first_byte / block_size) %   SoftXMT_nodes();
      intptr_t node_block = (first_byte / block_size) / SoftXMT_nodes();
      return GlobalAddress< T >::Raw( this->raw_bits() - first_byte_offset );
    }
  }

  inline GlobalAddress< T > block_max() const {
    if( is_2D() ) {
      intptr_t signextended = (storage_ << pointer_shift_val) >> pointer_shift_val;
      //return reinterpret_cast< T * >( -1 );
      return GlobalAddress< T >::TwoDimensional( (T*) 1, node() );
    } else {
      intptr_t first_byte = storage_;
      intptr_t first_byte_offset = first_byte % block_size;
      intptr_t last_byte = first_byte + sizeof(T) - 1;
      intptr_t last_byte_offset = last_byte % block_size;
      intptr_t node = (last_byte / block_size) % SoftXMT_nodes();
      intptr_t node_block = (last_byte / block_size) / SoftXMT_nodes();
      return GlobalAddress< T >::Raw( this->raw_bits() + sizeof(T) + block_size - (last_byte_offset + 1) );
    }
  }

  inline bool is_2D() const {
    return storage_ & tag_mask;
  }

  inline bool is_linear() const {
    return !( storage_ & tag_mask );
  }

  // inline size_t block_size() const {
  //   return block_size_;
  // }

  inline GlobalAddress< T >& operator++() {
    storage_ += sizeof(T);
    return *this;
  }

  //inline GlobalAddress< T > operator++(int i) { return storage_ ++ i; }

  inline GlobalAddress< T >& operator--() {
    storage_ -= sizeof(T);
    return *this;
  }

  //inline GlobalAddress< T > operator--(int i) { return storage_ ++ i; }

  inline GlobalAddress< T >& operator+=(ptrdiff_t i) {
    storage_ += i * sizeof(T);
    return *this;
  }

  inline GlobalAddress< T >& operator-=(ptrdiff_t i) {
    storage_ -= i * sizeof(T);
    return *this;
  }

  bool equals( const GlobalAddress< T >& t ) const {
    return raw_bits() == t.raw_bits();
  }

  bool operator==( const GlobalAddress< T >& t ) const {
    return raw_bits() == t.raw_bits();
  }

  template< typename U >
  bool operator==( const GlobalAddress< U >& u ) const {
    return raw_bits() == u.raw_bits();
  }

  //T& operator[]( ptrdiff_t index ) { return

  template< typename U >
  operator GlobalAddress< U >( ) {
    GlobalAddress< U > u = GlobalAddress< U >::Raw( storage_ );
    return u;
  }

  template< typename U >
  operator U * ( ) {
    U * u = reinterpret_cast< U * >( storage_ );
    return u;
  }

};

template< typename T >
GlobalAddress< T > operator+( const GlobalAddress< T >& t, ptrdiff_t i ) {
  GlobalAddress< T > tt(t);
  return tt += i;
}

// template< typename T >
// GlobalAddress< T >&& operator+( GlobalAddress< T >&& t, ptrdiff_t i ) {
//   return t += i;
// }

template< typename T >
GlobalAddress< T > operator-( const GlobalAddress< T >& t, ptrdiff_t i ) {
  GlobalAddress< T > tt(t);
  return tt -= i;
}

// template< typename T >
// GlobalAddress< T >&& operator-( const GlobalAddress< T >&& t, ptrdiff_t i ) {
//   return t -= i;
// }

template< typename T >
ptrdiff_t operator-( const GlobalAddress< T >& t, const GlobalAddress< T >& u ) {
  if( t.is_2D() ) {
    return t.pointer() - u.pointer();
  } else {
    return (t.raw_bits() - u.raw_bits()) / sizeof(T);
  }
}

template< typename T >
GlobalAddress< T > localToGlobal( T * t ) {
  return GlobalAddress< T >::TwoDimensional( t, SoftXMT_mynode() );
}

template< typename T >
GlobalAddress< T > make_global( T * t, Node n = SoftXMT_mynode() ) {
  return GlobalAddress< T >::TwoDimensional( t, n );
}

/// takes a local pointer to a block-cyclic distributed chuck of
/// memory allocated at the same base address on all nodes, and makes
/// a linear global pointer pointing to that byte.
template< typename T >
GlobalAddress< T > make_linear( T * t ) {
  intptr_t tt = reinterpret_cast< intptr_t >( t );

  intptr_t offset = tt % block_size;
  intptr_t block = tt / block_size;
  // intptr_t node_from_address = block % SoftXMT_nodes();
  // CHECK_EQ( node_from_address, 0 ) << "Node from address should be zero. (Check alignment?)";
  intptr_t ga = ( block * SoftXMT_nodes() + SoftXMT_mynode() ) * block_size + offset;

  T * ttt = reinterpret_cast< T * >( ga );
  GlobalAddress< T > tttt = GlobalAddress< T >::Linear( ttt, 0 );

  CHECK_EQ( tttt.node(), SoftXMT_mynode() ) << "converted linear address node doesn't match";
  CHECK_EQ( tttt.pointer(), t ) << "converted linear address local pointer doesn't match";

  return tttt;
}

template< typename T >
std::ostream& operator<<( std::ostream& o, const GlobalAddress< T >& ga ) {
  return ga.dump( o );
}

//template< typename T >
#endif
<commit_msg>Update Linear address constructor so it behaves like 2D one, taking a raw local address.<commit_after>
#ifndef __ADDRESSING_HPP__
#define __ADDRESSING_HPP__

/// Global Addresses for SoftXMT
///
///
///
///
/// We support two types of global addresses:
/// -# 2D addresses
/// -# Linear addresses
///
/// 2D addresses are node, address on node
///
/// linear addresses are block cyclic

#include "SoftXMT.hpp"

typedef int Pool;

/// assumes user data will have the top 16 bits all 0.

static const int block_size = sizeof(int64_t) * 8;

static const int tag_bits = 1;
static const int pointer_bits = 48;
static const int node_bits = 64 - pointer_bits - tag_bits;
static const int pool_bits = 64 - pointer_bits - tag_bits;

static const int tag_shift_val = 64 - tag_bits;
static const int pointer_shift_val = 64 - pointer_bits;
static const int node_shift_val = pointer_bits;
static const int pool_shift_val = pointer_bits;

static const intptr_t tag_mask = (1L << tag_shift_val);
static const intptr_t node_mask = (1L << node_bits) - 1;
static const intptr_t pool_mask = (1L << pool_bits) - 1;
static const intptr_t pointer_mask = (1L << pointer_bits) - 1;

template< typename T >
class GlobalAddress {
private:
  intptr_t storage_;
  //DISALLOW_COPY_AND_ASSIGN( GlobalAddress );
  template< typename U > friend std::ostream& operator<<( std::ostream& o, const GlobalAddress< U >& ga );
  //friend template< typename U > GlobalAddress< U > operator+( const GlobalAddress< U >& t, ptrdiff_t i );
  template< typename U > friend ptrdiff_t operator-( const GlobalAddress< U >& t, const GlobalAddress< U >& u );

  std::ostream& dump( std::ostream& o ) const {
    if( is_2D() ) {
      return o << "<GA 2D " << (void*)storage_
               << ": node " << node()
               << " pointer " << static_cast<void *>( pointer() )
               << ">";
    } else {
        return o << "<GA Linear " << (void*)storage_
                 << ": pool " << pool()
                 << " node " << node()
                 << " pointer " << static_cast<void *>( pointer()  )
                 << ">";
    }
  }

  // GlobalAddress( T * p, Node n = SoftXMT_mynode() )
  //   : storage_( ( 1L << tag_shift_val ) |
  //               ( ( n & node_mask) << node_shift_val ) |
  //               ( reinterpret_cast<intptr_t>( p ) ) )
  // {
  //   assert( SoftXMT_mynode() <= node_mask );
  //   assert( reinterpret_cast<intptr_t>( p ) >> node_shift_val == 0 );
  // }

public:

  GlobalAddress( ) : storage_( 0 ) { }

  /// construct a 2D global address
  static GlobalAddress TwoDimensional( T * t, Node n = SoftXMT_mynode() )
  {
    GlobalAddress g;
    g.storage_ = ( ( 1L << tag_shift_val ) |
                   ( ( n & node_mask) << node_shift_val ) |
                   ( reinterpret_cast<intptr_t>( t ) ) );
    assert( SoftXMT_mynode() <= node_mask );
    assert( reinterpret_cast<intptr_t>( t ) >> node_shift_val == 0 );
    return g;
  }

  /// construct a linear global address
  static GlobalAddress Linear( T * t, Pool p = 0 )
  {
    intptr_t tt = reinterpret_cast< intptr_t >( t );

    intptr_t offset = tt % block_size;
    intptr_t block = tt / block_size;
    // intptr_t node_from_address = block % SoftXMT_nodes();
    // CHECK_EQ( node_from_address, 0 ) << "Node from address should be zero. (Check alignment?)";
    intptr_t ga = ( block * SoftXMT_nodes() + SoftXMT_mynode() ) * block_size + offset;

    T * ttt = reinterpret_cast< T * >( ga );

    GlobalAddress g;
    g.storage_ = ( ( 0L << tag_shift_val ) |
                   //( ( n & node_mask) << node_shift_val ) |
                   ( reinterpret_cast<intptr_t>( ttt ) ) );

    CHECK_EQ( g.node(), SoftXMT_mynode() ) << "converted linear address node doesn't match";
    CHECK_EQ( g.pointer(), t ) << "converted linear address local pointer doesn't match";

    return g;
  }

  /// construct a global address from raw bits
  static GlobalAddress Raw( intptr_t t )
  {
    GlobalAddress g;
    g.storage_ = t;
    return g;
  }

  inline intptr_t raw_bits() const {
    return storage_;
  }

  inline Node node() const {
    if( is_2D() ) {
      return (storage_ >> node_shift_val) & node_mask;
    } else {
      intptr_t offset = storage_ % block_size;
      intptr_t node = (storage_ / block_size) % SoftXMT_nodes();
      intptr_t node_block = (storage_ / block_size) / SoftXMT_nodes();
      return node;
    }
  }

  inline Pool pool() const {
    return (storage_ >> pool_shift_val) & pool_mask;
  }

  inline T * pointer() const {
    if( is_2D() ) {
      intptr_t signextended = (storage_ << pointer_shift_val) >> pointer_shift_val;
      return reinterpret_cast< T * >( signextended );
    } else {
      intptr_t offset = storage_ % block_size;
      intptr_t block = (storage_ / block_size);
      intptr_t node = (storage_ / block_size) % SoftXMT_nodes();
      intptr_t node_block = (storage_ / block_size) / SoftXMT_nodes();
      return reinterpret_cast< T * >( node_block * block_size + offset );
    }
  }

  inline GlobalAddress< T > block_min() const {
    if( is_2D() ) {
      //intptr_t signextended = (storage_ << pointer_shift_val) >> pointer_shift_val;
      //GlobalAddress< U > u = GlobalAddress< U >::Raw( storage_ );
      return GlobalAddress< T >::TwoDimensional( (T*) 0, node() );
    } else {
      intptr_t first_byte = storage_;
      intptr_t first_byte_offset = first_byte % block_size;
      intptr_t node = (first_byte / block_size) %   SoftXMT_nodes();
      intptr_t node_block = (first_byte / block_size) / SoftXMT_nodes();
      return GlobalAddress< T >::Raw( this->raw_bits() - first_byte_offset );
    }
  }

  inline GlobalAddress< T > block_max() const {
    if( is_2D() ) {
      intptr_t signextended = (storage_ << pointer_shift_val) >> pointer_shift_val;
      //return reinterpret_cast< T * >( -1 );
      return GlobalAddress< T >::TwoDimensional( (T*) 1, node() );
    } else {
      intptr_t first_byte = storage_;
      intptr_t first_byte_offset = first_byte % block_size;
      intptr_t last_byte = first_byte + sizeof(T) - 1;
      intptr_t last_byte_offset = last_byte % block_size;
      intptr_t node = (last_byte / block_size) % SoftXMT_nodes();
      intptr_t node_block = (last_byte / block_size) / SoftXMT_nodes();
      return GlobalAddress< T >::Raw( this->raw_bits() + sizeof(T) + block_size - (last_byte_offset + 1) );
    }
  }

  inline bool is_2D() const {
    return storage_ & tag_mask;
  }

  inline bool is_linear() const {
    return !( storage_ & tag_mask );
  }

  // inline size_t block_size() const {
  //   return block_size_;
  // }

  inline GlobalAddress< T >& operator++() {
    storage_ += sizeof(T);
    return *this;
  }

  //inline GlobalAddress< T > operator++(int i) { return storage_ ++ i; }

  inline GlobalAddress< T >& operator--() {
    storage_ -= sizeof(T);
    return *this;
  }

  //inline GlobalAddress< T > operator--(int i) { return storage_ ++ i; }

  inline GlobalAddress< T >& operator+=(ptrdiff_t i) {
    storage_ += i * sizeof(T);
    return *this;
  }

  inline GlobalAddress< T >& operator-=(ptrdiff_t i) {
    storage_ -= i * sizeof(T);
    return *this;
  }

  bool equals( const GlobalAddress< T >& t ) const {
    return raw_bits() == t.raw_bits();
  }

  bool operator==( const GlobalAddress< T >& t ) const {
    return raw_bits() == t.raw_bits();
  }

  template< typename U >
  bool operator==( const GlobalAddress< U >& u ) const {
    return raw_bits() == u.raw_bits();
  }

  //T& operator[]( ptrdiff_t index ) { return

  template< typename U >
  operator GlobalAddress< U >( ) {
    GlobalAddress< U > u = GlobalAddress< U >::Raw( storage_ );
    return u;
  }

  template< typename U >
  operator U * ( ) {
    U * u = reinterpret_cast< U * >( storage_ );
    return u;
  }

};

template< typename T >
GlobalAddress< T > operator+( const GlobalAddress< T >& t, ptrdiff_t i ) {
  GlobalAddress< T > tt(t);
  return tt += i;
}

// template< typename T >
// GlobalAddress< T >&& operator+( GlobalAddress< T >&& t, ptrdiff_t i ) {
//   return t += i;
// }

template< typename T >
GlobalAddress< T > operator-( const GlobalAddress< T >& t, ptrdiff_t i ) {
  GlobalAddress< T > tt(t);
  return tt -= i;
}

// template< typename T >
// GlobalAddress< T >&& operator-( const GlobalAddress< T >&& t, ptrdiff_t i ) {
//   return t -= i;
// }

template< typename T >
ptrdiff_t operator-( const GlobalAddress< T >& t, const GlobalAddress< T >& u ) {
  if( t.is_2D() ) {
    return t.pointer() - u.pointer();
  } else {
    return (t.raw_bits() - u.raw_bits()) / sizeof(T);
  }
}

template< typename T >
GlobalAddress< T > localToGlobal( T * t ) {
  return GlobalAddress< T >::TwoDimensional( t, SoftXMT_mynode() );
}

template< typename T >
GlobalAddress< T > make_global( T * t, Node n = SoftXMT_mynode() ) {
  return GlobalAddress< T >::TwoDimensional( t, n );
}

/// takes a local pointer to a block-cyclic distributed chuck of
/// memory allocated at the same base address on all nodes, and makes
/// a linear global pointer pointing to that byte.
template< typename T >
GlobalAddress< T > make_linear( T * t ) {
  return GlobalAddress< T >::Linear( t );
}

template< typename T >
std::ostream& operator<<( std::ostream& o, const GlobalAddress< T >& ga ) {
  return ga.dump( o );
}

//template< typename T >
#endif
<|endoftext|>